date and time created 90/03/23 09:45:20 by bostic
[unix-history] / usr / src / old / as.tahoe / bignum.c
CommitLineData
efd04ce3
KB
1/*
2 * Copyright (c) 1982 Regents of the University of California
3 */
4#ifndef lint
5static char sccsid[] = "@(#)bignum1.c 4.4 6/30/83";
6#endif not lint
7
8#include <errno.h>
9#include <stdio.h>
10#include "as.h"
11
12Bignum Znumber;
13
14/*
15 * Construct an integer.
16 */
17
18Bignum as_atoi(ccp, radix, ovfp)
19 reg char *ccp; /* character cp */
20 int radix;
21 Ovf *ovfp;
22{
23 reg chptr bcp;
24 chptr tcp;
25 reg int i;
26 int val;
27 Bignum n_n;
28 Bignum t_n;
29 int sign;
30 Ovf ovf;
31
32 ovf = 0;
33 sign = 0;
34 for (; *ccp; ccp++){
35 switch(*ccp){
36 case '0':
37 case '+': continue;
38 case '-': sign ^= 1;
39 continue;
40 }
41 break;
42 }
43
44 n_n = Znumber;
45 t_n = Znumber;
46 bcp = CH_FIELD(n_n); (void)numclear(bcp);
47 tcp = CH_FIELD(t_n); (void)numclear(tcp);
48 for (; *ccp; ccp++){
49 switch(*ccp){
50 case '8': case '9':
51 if (radix < 10)
52 goto done;
53 /*FALLTHROUGH*/
54 case '0': case '1': case '2': case '3': case '4':
55 case '5': case '6': case '7':
56 val = *ccp - '0';
57 break;
58 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
59 if (radix < 16)
60 goto done;
61 val = *ccp - 'A' + 10;
62 break;
63 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
64 if (radix < 16)
65 goto done;
66 val = *ccp - 'a' + 10;
67 break;
68 default:
69 goto done;
70 }
71 switch(radix){
72 case 8:
73 ovf |= numshift(3, bcp, bcp);
74 break;
75 case 16:
76 ovf |= numshift(4, bcp, bcp);
77 break;
78 case 10:
79 ovf |= numshift(1, tcp, bcp);
80 ovf |= numshift(3, bcp, bcp);
81 ovf |= numaddv(bcp, tcp, bcp);
82 break;
83 }
84 ovf |= numaddd(bcp, bcp, val);
85 }
86 done: ;
87 ovf |= posovf(bcp);
88 if (sign){
89 if (ovf & OVF_MAXINT) {
90 ovf &= ~(OVF_MAXINT | OVF_POSOVF);
91 } else {
92 ovf |= numnegate(bcp, bcp);
93 }
94 }
95 /*
96 * find the highest set unit of the number
97 */
98 val = sign ? -1 : 0;
99 for (i = 0; i < CH_N; i++){
100 if (bcp[i] == val)
101 break;
102 }
103 {
104 static u_char tagtab[4][8] = {
105 { TYPB,
106 TYPW,
107 TYPL, TYPL,
108 TYPQ, TYPQ, TYPQ, TYPQ },
109 { TYPW,
110 TYPL,
111 TYPQ, TYPQ },
112 { 0 },
113 { TYPL,
114 TYPQ }
115 };
116 /*
117 * i indexes to the null chunk; make it point to the
118 * last non null chunk
119 */
120 i -= 1;
121 if (i < 0)
122 i = 0;
123 n_n.num_tag = tagtab[HOC][i];
124 assert(n_n.num_tag != 0, " Botch width computation");
125 }
126 *ovfp = ovf;
127 return(n_n);
128}
129
130Bignum as_atof (numbuf, radix)
131 char *numbuf;
132{
133 double atof ();
134 Bignum number;
135
136 number = Znumber;
137 number.num_tag = radix;
138 switch (radix)
139 {
140 case TYPD:
141 number.num_num.numFd_float.Fd_value = atof (numbuf);
142 break;
143 case TYPF:
144 number.num_num.numFf_float.Ff_value = atof (numbuf);
145 break;
146 }
147
148 return (number);
149}
150
151Ovf posovf(src)
152 reg chptr src;
153{
154 reg int i;
155 Ovf overflow = 0;
156
157 if (src[HOC] & SIGNBIT)
158 overflow = OVF_POSOVF;
159 if (src[HOC] == SIGNBIT){
160 for (i = HOC - 1; i >= 0; --i){
161 if (src[i] != 0)
162 return(overflow);
163 }
164 overflow |= OVF_MAXINT;
165 }
166 return(overflow);
167}
168
169/*
170 * check if the number is clear
171 */
172int isclear(dst)
173 reg chptr dst;
174{
175 return(!isunequal(dst, CH_FIELD(Znumber)));
176}
177
178int isunequal(src1, src2)
179 reg chptr src1, src2;
180{
181 reg int i;
182
183 i = CH_N;
184 do{
185 if (*src1++ != *src2++)
186 return(i);
187 }while(--i);
188 return(0);
189}
190
191Ovf numclear(dst)
192 reg chptr dst;
193{
194 reg int i;
195 i = CH_N;
196 do{
197 *dst++ = 0;
198 }while(--i);
199 return(0);
200}
201
202Ovf numshift(n, dst, src)
203 int n;
204 reg chptr dst, src;
205{
206 reg int i;
207 reg u_int carryi, carryo;
208 reg u_int mask;
209 reg u_int value;
210
211 i = CH_N;
212 if (n == 0){
213 do{
214 *dst++ = *src++;
215 } while(--i);
216 return(0);
217 }
218
219 carryi = 0;
220 mask = ONES(n);
221
222 if (n > 0){
223 do{
224 value = *src++;
225 carryo = (value >> (CH_BITS - n)) & mask;
226 value <<= n;
227 value &= ~mask;
228 *dst++ = value | carryi;
229 carryi = carryo;
230 } while (--i);
231 return(carryi ? OVF_LSHIFT : 0);
232 } else {
233 n = -n;
234 src += CH_N;
235 dst += CH_N;
236 do{
237 value = *--src;
238 carryo = value & mask;
239 value >>= n;
240 value &= ONES(CH_BITS - n);
241 *--dst = value | carryi;
242 carryi = carryo << (CH_BITS - n);
243 } while (--i);
244 return(carryi ? OVF_LSHIFT : 0);
245 }
246}
247
248Ovf numaddd(dst, src1, val)
249 chptr dst, src1;
250 int val;
251{
252 static Bignum work;
253
254 work.num_uchar[3] = val;
255 return (numaddv(dst, src1, CH_FIELD(work)));
256}
257
258Ovf numaddv(dst, src1, src2)
259 reg chptr dst, src1, src2;
260{
261 reg int i;
262 reg int carry;
263 reg u_int A,B,value;
264
265 carry = 0;
266 i = CH_N;
267 do{
268 A = *src1++;
269 B = *src2++;
270 value = A + B + carry;
271 *dst++ = value;
272 carry = 0;
273 if (value < A || value < B)
274 carry = 1;
275 } while (--i);
276 return(carry ? OVF_ADDV : 0);
277}
278
279Ovf numnegate(dst, src)
280 chptr dst, src;
281{
282 Ovf ovf;
283
284 ovf = num1comp(dst, src) ;
285 ovf |= numaddd(dst, dst, 1);
286 return(ovf);
287}
288
289Ovf num1comp(dst, src)
290 reg chptr dst, src;
291{
292 reg int i;
293 i = CH_N;
294 do{
295 *dst++ = ~ *src++;
296 }while (--i);
297 return(0);
298}
299
300bignumprint(number)
301 Bignum number; /* number presented */
302{
303 switch (num_type)
304 {
305 case TYPQ:
306 printf ("val[msd] = 0x%x, val[lsd] = 0x%x.",
307 number.num_num.numIq_int.Iq_ulong[1],
308 number.num_num.numIq_int.Iq_ulong[0]);
309 break;
310 case TYPF:
311 printf ("value %20.17f",
312 number.num_num.numFf_float.Ff_value);
313 break;
314 case TYPD:
315 printf ("value %20.17f",
316 number.num_num.numFd_float.Fd_value);
317 break;
318 default:
319 break;
320 }
321}
322