Commit | Line | Data |
---|---|---|
efd04ce3 KB |
1 | /* |
2 | * Copyright (c) 1982 Regents of the University of California | |
3 | */ | |
4 | #ifndef lint | |
5 | static 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 | ||
12 | Bignum Znumber; | |
13 | ||
14 | /* | |
15 | * Construct an integer. | |
16 | */ | |
17 | ||
18 | Bignum 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 | ||
130 | Bignum 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 | ||
151 | Ovf 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 | */ | |
172 | int isclear(dst) | |
173 | reg chptr dst; | |
174 | { | |
175 | return(!isunequal(dst, CH_FIELD(Znumber))); | |
176 | } | |
177 | ||
178 | int 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 | ||
191 | Ovf 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 | ||
202 | Ovf 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 | ||
248 | Ovf 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 | ||
258 | Ovf 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 | ||
279 | Ovf 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 | ||
289 | Ovf 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 | ||
300 | bignumprint(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 |