Mercurial > hg > xemacs-beta
annotate src/number-mp.c @ 5636:07256dcc0c8b
Add missing foreback specifier values to the GUI Element face.
They were missing for an unexplicable reason in my initial patch, leading to
nil color instances in the whole hierarchy of widget faces.
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2012-01-03 Didier Verna <didier@xemacs.org>
* faces.c (complex_vars_of_faces): Add missing foreback specifier
values to the GUI Element face.
author | Didier Verna <didier@lrde.epita.fr> |
---|---|
date | Tue, 03 Jan 2012 11:25:06 +0100 |
parents | c9e5612f5424 |
children | 7aa144d1404b |
rev | line source |
---|---|
1983 | 1 /* Numeric types for XEmacs using the MP library. |
2 Copyright (C) 2004 Jerry James. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
6 XEmacs is free software: you can redistribute it and/or modify it |
1983 | 7 under the terms of the GNU General Public License as published by the |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
8 Free Software Foundation, either version 3 of the License, or (at your |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
9 option) any later version. |
1983 | 10 |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
17 along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
1983 | 18 |
19 /* Synched up with: Not in FSF. */ | |
20 | |
21 #include <config.h> | |
22 #include <limits.h> | |
23 #include <math.h> | |
24 #include "lisp.h" | |
25 | |
26 static MINT *bignum_bytesize, *bignum_long_sign_bit, *bignum_one, *bignum_two; | |
27 MINT *bignum_zero, *intern_bignum; | |
28 MINT *bignum_min_int, *bignum_max_int, *bignum_max_uint; | |
29 MINT *bignum_min_long, *bignum_max_long, *bignum_max_ulong; | |
30 short div_rem; | |
31 | |
32 char * | |
33 bignum_to_string (bignum b, int base) | |
34 { | |
35 REGISTER unsigned int i; | |
36 unsigned int bufsize = 128U, index = 0U; | |
37 int sign; | |
38 char *buffer = xnew_array (char, 128), *retval; | |
39 MINT *quo = MP_ITOM (0); | |
40 short rem; | |
41 | |
42 /* FIXME: signal something if base is < 2 or doesn't fit into a short. */ | |
43 | |
44 /* Save the sign for later */ | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
45 sign = bignum_sign (b); |
1983 | 46 |
47 if (sign == 0) | |
48 { | |
49 XREALLOC_ARRAY (buffer, char, 2); | |
50 buffer[0] = '0'; | |
51 buffer[1] = '\0'; | |
52 return buffer; | |
53 } | |
54 /* Copy abs(b) into quo for destructive modification */ | |
55 else if (sign < 0) | |
56 MP_MSUB (bignum_zero, b, quo); | |
57 else | |
58 MP_MOVE (b, quo); | |
59 | |
60 /* Loop over the digits of b (in BASE) and place each one into buffer */ | |
61 for (i = 0U; MP_MCMP(quo, bignum_zero) > 0; i++) | |
62 { | |
63 MP_SDIV (quo, base, quo, &rem); | |
64 if (index == bufsize) | |
65 { | |
66 bufsize <<= 1; | |
67 XREALLOC_ARRAY (buffer, char, bufsize); | |
68 } | |
69 buffer[index++] = rem < 10 ? rem + '0' : rem - 10 + 'a'; | |
70 } | |
71 MP_MFREE (quo); | |
72 | |
73 /* Reverse the digits, maybe add a minus sign, and add a null terminator */ | |
74 bufsize = index + (sign < 0 ? 1 : 0) + 1; | |
75 retval = xnew_array (char, bufsize); | |
76 if (sign < 0) | |
77 { | |
78 retval[0] = '-'; | |
79 i = 1; | |
80 } | |
81 else | |
82 i = 0; | |
83 for (; i < bufsize - 1; i++) | |
84 retval[i] = buffer[--index]; | |
85 retval[bufsize - 1] = '\0'; | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4802
diff
changeset
|
86 xfree (buffer); |
1983 | 87 return retval; |
88 } | |
89 | |
90 #define BIGNUM_TO_TYPE(type,accumtype) do { \ | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
91 if (0 == sign) \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
92 { \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
93 return (type)0; \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
94 } \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
95 \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
96 bignum_init (quo); \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
97 \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
98 if (sign < 0) \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
99 { \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
100 MP_MSUB (bignum_zero, b, quo); \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
101 } \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
102 else \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
103 { \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
104 MP_MOVE (b, quo); \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
105 } \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
106 \ |
1983 | 107 for (i = 0U; i < sizeof(type); i++) \ |
108 { \ | |
109 MP_SDIV (quo, 256, quo, &rem); \ | |
110 retval |= ((accumtype) rem) << (8 * i); \ | |
111 } \ | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
112 bignum_fini (quo); \ |
1983 | 113 } while (0) |
114 | |
115 int | |
116 bignum_to_int (bignum b) | |
117 { | |
118 short rem, sign; | |
119 unsigned int retval = 0; | |
120 REGISTER unsigned int i; | |
121 MINT *quo; | |
122 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
123 sign = bignum_sign (b); |
1983 | 124 BIGNUM_TO_TYPE (int, unsigned int); |
125 return ((int) retval) * sign; | |
126 } | |
127 | |
128 unsigned int | |
129 bignum_to_uint (bignum b) | |
130 { | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
131 short rem, sign; |
1983 | 132 unsigned int retval = 0U; |
133 REGISTER unsigned int i; | |
134 MINT *quo; | |
135 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
136 sign = bignum_sign (b); |
1983 | 137 BIGNUM_TO_TYPE (unsigned int, unsigned int); |
138 return retval; | |
139 } | |
140 | |
141 long | |
142 bignum_to_long (bignum b) | |
143 { | |
144 short rem, sign; | |
145 unsigned long retval = 0L; | |
146 REGISTER unsigned int i; | |
147 MINT *quo; | |
148 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
149 sign = bignum_sign (b); |
1983 | 150 BIGNUM_TO_TYPE (long, unsigned long); |
151 return ((long) retval) * sign; | |
152 } | |
153 | |
154 unsigned long | |
155 bignum_to_ulong (bignum b) | |
156 { | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
157 short rem, sign; |
1983 | 158 unsigned long retval = 0UL; |
159 REGISTER unsigned int i; | |
160 MINT *quo; | |
161 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
162 sign = bignum_sign (b); |
1983 | 163 BIGNUM_TO_TYPE (unsigned long, unsigned long); |
164 return retval; | |
165 } | |
166 | |
167 double | |
168 bignum_to_double (bignum b) | |
169 { | |
170 short rem, sign; | |
1990 | 171 double retval = 0.0, factor = 1.0; |
1983 | 172 REGISTER unsigned int i; |
173 MINT *quo; | |
174 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
175 sign = bignum_sign (b); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
176 bignum_init (quo); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
177 if (sign < 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
178 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
179 MP_MSUB (bignum_zero, b, quo); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
180 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
181 else |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
182 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
183 MP_MOVE (b, quo); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
184 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
185 |
1990 | 186 for (i = 0U; MP_MCMP (quo, bignum_zero) > 0; i++) |
1983 | 187 { |
188 MP_SDIV (quo, 256, quo, &rem); | |
1990 | 189 retval += rem * factor; |
190 factor *= 256.0; | |
1983 | 191 } |
192 MP_MFREE (quo); | |
193 return retval * sign; | |
194 } | |
195 | |
196 static short | |
197 char_to_number (char c) | |
198 { | |
199 if (c >= '0' && c <= '9') | |
200 return c - '0'; | |
201 if (c >= 'a' && c <= 'z') | |
202 return c - 'a' + 10; | |
203 if (c >= 'A' && c <= 'Z') | |
204 return c - 'A' + 10; | |
205 return -1; | |
206 } | |
207 | |
208 int | |
209 bignum_set_string (bignum b, const char *s, int base) | |
210 { | |
211 MINT *mbase; | |
212 short digit; | |
1993 | 213 int neg = 0; |
1983 | 214 |
215 if (base == 0) | |
216 { | |
217 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) | |
218 { | |
219 base = 16; | |
220 s += 2; | |
221 } | |
222 else if (*s == '0') | |
223 { | |
224 base = 8; | |
225 s++; | |
226 } | |
227 else | |
228 base = 10; | |
229 } | |
230 | |
231 /* FIXME: signal something if base is < 2 or doesn't fit into a short. */ | |
232 | |
1993 | 233 if (*s == '-') |
234 { | |
235 s++; | |
236 neg = 1; | |
237 } | |
238 | |
1983 | 239 mbase = MP_ITOM ((short) base); |
240 MP_MOVE (bignum_zero, b); | |
4802
2fc0e2f18322
Don't create any bignums before pdumping. Add bignum, ratio, and bigfloat
Jerry James <james@xemacs.org>
parents:
1993
diff
changeset
|
241 |
1983 | 242 for (digit = char_to_number (*s); digit >= 0 && digit < base; |
243 digit = char_to_number (*++s)) | |
244 { | |
245 MINT *temp; | |
246 | |
247 MP_MULT (b, mbase, b); | |
248 temp = MP_ITOM (digit); | |
249 MP_MADD (b, temp, b); | |
250 MP_MFREE (temp); | |
251 } | |
252 | |
1993 | 253 if (neg) |
254 MP_MSUB (bignum_zero, b, b); | |
255 | |
1983 | 256 return (digit >= 0) ? -1 : 0; |
257 } | |
258 | |
259 void | |
260 bignum_set_long (MINT *b, long l) | |
261 { | |
262 /* Negative l is hard, not least because -LONG_MIN == LONG_MIN. We pretend | |
263 that l is unsigned, then subtract off the amount equal to the sign bit. */ | |
264 bignum_set_ulong (b, (unsigned long) l); | |
265 if (l < 0L) | |
266 MP_MSUB (b, bignum_long_sign_bit, b); | |
267 } | |
268 | |
269 void | |
270 bignum_set_ulong (bignum b, unsigned long l) | |
271 { | |
272 REGISTER unsigned int i; | |
273 MINT *multiplier = MP_ITOM (1); | |
274 | |
275 MP_MOVE (bignum_zero, b); | |
276 for (i = 0UL; l > 0UL; l >>= 8, i++) | |
277 { | |
278 MINT *temp = MP_ITOM ((short) (l & 255)); | |
279 MP_MULT (multiplier, temp, temp); | |
280 MP_MADD (b, temp, b); | |
281 MP_MULT (multiplier, bignum_bytesize, multiplier); | |
282 MP_MFREE (temp); | |
283 } | |
284 MP_MFREE (multiplier); | |
285 } | |
286 | |
287 void | |
288 bignum_set_double (bignum b, double d) | |
289 { | |
290 REGISTER unsigned int i; | |
291 int negative = (d < 0) ? 1 : 0; | |
292 MINT *multiplier = MP_ITOM (1); | |
293 | |
294 MP_MOVE (bignum_zero, b); | |
295 if (negative) | |
296 d = -d; | |
297 for (i = 0UL; d > 0.0; d /= 256, i++) | |
298 { | |
299 MINT *temp = MP_ITOM ((short) fmod (d, 256.0)); | |
300 MP_MULT (multiplier, temp, temp); | |
301 MP_MADD (b, temp, b); | |
302 MP_MULT (multiplier, bignum_bytesize, multiplier); | |
303 MP_MFREE (temp); | |
304 } | |
305 MP_MFREE (multiplier); | |
306 if (negative) | |
307 MP_MSUB (bignum_zero, b, b); | |
308 } | |
309 | |
310 /* Return nonzero if b1 is exactly divisible by b2 */ | |
311 int | |
312 bignum_divisible_p (bignum b1, bignum b2) | |
313 { | |
314 int retval; | |
315 MINT *rem = MP_ITOM (0); | |
316 MP_MDIV (b1, b2, intern_bignum, rem); | |
317 retval = (MP_MCMP (rem, bignum_zero) == 0); | |
318 MP_MFREE (rem); | |
319 return retval; | |
320 } | |
321 | |
322 void bignum_ceil (bignum quotient, bignum N, bignum D) | |
323 { | |
324 MP_MDIV (N, D, quotient, intern_bignum); | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
325 MP_MDIV (N, D, quotient, intern_bignum); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
326 if (MP_MCMP (intern_bignum, bignum_zero) != 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
327 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
328 short signN = MP_MCMP (N, bignum_zero); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
329 short signD = MP_MCMP (D, bignum_zero); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
330 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
331 /* If the quotient is positive, add one, since we're rounding to |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
332 positive infinity. */ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
333 if (signD < 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
334 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
335 if (signN <= 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
336 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
337 MP_MADD (quotient, bignum_one, quotient); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
338 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
339 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
340 else if (signN >= 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
341 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
342 MP_MADD (quotient, bignum_one, quotient); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
343 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
344 } |
1983 | 345 } |
346 | |
347 void bignum_floor (bignum quotient, bignum N, bignum D) | |
348 { | |
349 MP_MDIV (N, D, quotient, intern_bignum); | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
350 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
351 if (MP_MCMP (intern_bignum, bignum_zero) != 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
352 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
353 short signN = MP_MCMP (N, bignum_zero); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
354 short signD = MP_MCMP (D, bignum_zero); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
355 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
356 /* If the quotient is negative, subtract one, we're rounding to minus |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
357 infinity. */ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
358 if (signD < 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
359 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
360 if (signN >= 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
361 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
362 MP_MSUB (quotient, bignum_one, quotient); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
363 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
364 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
365 else if (signN < 0) |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
366 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
367 MP_MSUB (quotient, bignum_one, quotient); |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
368 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
369 } |
1983 | 370 } |
371 | |
372 /* RESULT = N to the POWth power */ | |
373 void | |
374 bignum_pow (bignum result, bignum n, unsigned long pow) | |
375 { | |
376 MP_MOVE (bignum_one, result); | |
377 for ( ; pow > 0UL; pow--) | |
378 MP_MULT (result, n, result); | |
379 } | |
380 | |
381 /* lcm(b1,b2) = b1 * b2 / gcd(b1, b2) */ | |
382 void | |
383 bignum_lcm (bignum result, bignum b1, bignum b2) | |
384 { | |
385 MP_MULT (b1, b2, result); | |
386 MP_GCD (b1, b2, intern_bignum); | |
387 MP_MDIV (result, intern_bignum, result, intern_bignum); | |
388 } | |
389 | |
390 /* FIXME: We can't handle negative args, so right now we just make them | |
391 positive before doing anything else. How should we really handle negative | |
392 args? */ | |
393 #define bignum_bit_op(result, b1, b2, op) \ | |
394 REGISTER unsigned int i; \ | |
395 MINT *multiplier = MP_ITOM (1), *n1 = MP_ITOM (0), *n2 = MP_ITOM (0); \ | |
396 \ | |
397 if (MP_MCMP (bignum_zero, b1) > 0) \ | |
398 MP_MSUB (bignum_zero, b1, n1); \ | |
399 else \ | |
400 MP_MOVE (b1, n1); \ | |
401 if (MP_MCMP (bignum_zero, b2) > 0) \ | |
402 MP_MSUB (bignum_zero, b2, n2); \ | |
403 else \ | |
404 MP_MOVE (b2, n2); \ | |
405 \ | |
406 MP_MOVE (bignum_zero, result); \ | |
407 \ | |
408 for (i = 0UL; MP_MCMP (bignum_zero, n1) < 0 && \ | |
409 MP_MCMP (bignum_zero, n2) < 0; i++) \ | |
410 { \ | |
411 short byte1, byte2; \ | |
412 MINT *temp; \ | |
413 \ | |
414 MP_SDIV (n1, 256, n1, &byte1); \ | |
415 MP_SDIV (n2, 256, n2, &byte2); \ | |
416 temp = MP_ITOM (byte1 op byte2); \ | |
417 MP_MULT (multiplier, temp, temp); \ | |
418 MP_MADD (result, temp, result); \ | |
419 MP_MULT (multiplier, bignum_bytesize, multiplier); \ | |
420 MP_MFREE (temp); \ | |
421 } \ | |
422 MP_MFREE (n2); \ | |
423 MP_MFREE (n1); \ | |
424 MP_MFREE (multiplier) | |
425 | |
426 void | |
427 bignum_and (bignum result, bignum b1, bignum b2) | |
428 { | |
429 bignum_bit_op (result, b1, b2, &); | |
430 } | |
431 | |
432 void | |
433 bignum_ior (bignum result, bignum b1, bignum b2) | |
434 { | |
435 bignum_bit_op (result, b1, b2, |); | |
436 } | |
437 | |
438 void | |
439 bignum_xor (bignum result, bignum b1, bignum b2) | |
440 { | |
441 bignum_bit_op (result, b1, b2, ^); | |
442 } | |
443 | |
444 /* NOT is not well-defined for bignums ... where do you stop flipping bits? | |
445 We just flip until we see the last one. This is probably a bad idea. */ | |
446 void | |
447 bignum_not (bignum result, bignum b) | |
448 { | |
449 REGISTER unsigned int i; | |
450 MINT *multiplier = MP_ITOM (1), *n = MP_ITOM (0); | |
451 | |
452 if (MP_MCMP (bignum_zero, b) > 0) | |
453 MP_MSUB (bignum_zero, b, n); | |
454 else | |
455 MP_MOVE (b, n); | |
456 | |
457 MP_MOVE (bignum_zero, result); | |
458 | |
459 for (i = 0UL; MP_MCMP (bignum_zero, n) < 0; i++) | |
460 { | |
461 short byte; | |
462 MINT *temp; | |
463 | |
464 MP_SDIV (n, 256, n, &byte); | |
465 temp = MP_ITOM (~byte); | |
466 MP_MULT (multiplier, temp, temp); | |
467 MP_MADD (result, temp, result); | |
468 MP_MULT (multiplier, bignum_bytesize, multiplier); | |
469 MP_MFREE (temp); | |
470 } | |
471 MP_MFREE (n); | |
472 MP_MFREE (multiplier); | |
473 } | |
474 | |
475 void | |
476 bignum_setbit (bignum b, unsigned long bit) | |
477 { | |
478 bignum_pow (intern_bignum, bignum_two, bit); | |
479 bignum_ior (b, b, intern_bignum); | |
480 } | |
481 | |
482 /* This is so evil, even I feel queasy. */ | |
483 void | |
484 bignum_clrbit (bignum b, unsigned long bit) | |
485 { | |
486 MINT *num = MP_ITOM (0); | |
487 | |
488 /* See if the bit is already set, and subtract it off if not */ | |
489 MP_MOVE (b, intern_bignum); | |
490 bignum_pow (num, bignum_two, bit); | |
491 bignum_ior (intern_bignum, intern_bignum, num); | |
492 if (MP_MCMP (b, intern_bignum) == 0) | |
493 MP_MSUB (b, num, b); | |
494 MP_MFREE (num); | |
495 } | |
496 | |
497 int | |
498 bignum_testbit (bignum b, unsigned long bit) | |
499 { | |
500 bignum_pow (intern_bignum, bignum_two, bit); | |
501 bignum_and (intern_bignum, b, intern_bignum); | |
502 return MP_MCMP (intern_bignum, bignum_zero); | |
503 } | |
504 | |
505 void | |
506 bignum_lshift (bignum result, bignum b, unsigned long bits) | |
507 { | |
508 bignum_pow (intern_bignum, bignum_two, bits); | |
509 MP_MULT (b, intern_bignum, result); | |
510 } | |
511 | |
512 void | |
513 bignum_rshift (bignum result, bignum b, unsigned long bits) | |
514 { | |
515 bignum_pow (intern_bignum, bignum_two, bits); | |
516 MP_MDIV (b, intern_bignum, result, intern_bignum); | |
517 } | |
518 | |
519 void bignum_random_seed(unsigned long seed) | |
520 { | |
521 /* FIXME: Implement me */ | |
522 } | |
523 | |
524 void bignum_random(bignum result, bignum limit) | |
525 { | |
526 /* FIXME: Implement me */ | |
527 MP_MOVE (bignum_zero, result); | |
528 } | |
529 | |
530 void | |
531 init_number_mp () | |
532 { | |
533 REGISTER unsigned int i; | |
534 | |
535 bignum_zero = MP_ITOM (0); | |
536 bignum_one = MP_ITOM (1); | |
537 bignum_two = MP_ITOM (2); | |
538 | |
539 /* intern_bignum holds throwaway values from macro expansions in | |
540 number-mp.h. Its value is immaterial. */ | |
541 intern_bignum = MP_ITOM (0); | |
542 | |
543 /* bignum_bytesize holds the number of bits in a byte. */ | |
544 bignum_bytesize = MP_ITOM (256); | |
545 | |
546 /* bignum_long_sign_bit holds an adjustment for negative longs. */ | |
547 bignum_long_sign_bit = MP_ITOM (256); | |
548 for (i = 1UL; i < sizeof (long); i++) | |
549 MP_MULT (bignum_bytesize, bignum_long_sign_bit, bignum_long_sign_bit); | |
550 | |
551 /* The MP interface only supports turning short ints into MINTs, so we have | |
552 to set these the hard way. */ | |
553 | |
554 bignum_min_int = MP_ITOM (0); | |
555 bignum_set_long (bignum_min_int, INT_MIN); | |
556 | |
557 bignum_max_int = MP_ITOM (0); | |
558 bignum_set_long (bignum_max_int, INT_MAX); | |
559 | |
560 bignum_max_uint = MP_ITOM (0); | |
561 bignum_set_ulong (bignum_max_uint, UINT_MAX); | |
562 | |
563 bignum_min_long = MP_ITOM (0); | |
564 bignum_set_long (bignum_min_long, LONG_MIN); | |
565 | |
566 bignum_max_long = MP_ITOM (0); | |
567 bignum_set_long (bignum_max_long, LONG_MAX); | |
568 | |
569 bignum_max_ulong = MP_ITOM (0); | |
570 bignum_set_ulong (bignum_max_ulong, ULONG_MAX); | |
571 } |