Mercurial > hg > xemacs-beta
annotate src/number-mp.c @ 5624:c39052c921b5
New "foreback" face property.
-------------------- ChangeLog entries follow: --------------------
lisp/ChangeLog addition:
2011-12-27 Didier Verna <didier@xemacs.org>
* cl-macs.el (face-foreback): New defsetf.
* faces.el (set-face-property): Document the foreback property.
* faces.el (face-foreback):
* faces.el (face-foreback-instance):
* faces.el (face-foreback-name):
* faces.el (set-face-foreback): New functions.
* faces.el (face-equal):
* faces.el (init-other-random-faces):
* cus-face.el (custom-face-attributes):
* x-faces.el (x-init-face-from-resources): Handle the foreback
property.
src/ChangeLog addition:
2011-12-27 Didier Verna <didier@xemacs.org>
* faces.h (struct Lisp_Face): New 'foreback slot.
* faces.h (struct face_cachel): New 'foreback and
'foreback_specified slots.
* faces.h (WINDOW_FACE_CACHEL_FOREBACK):
* faces.h (FACE_FOREBACK): New macros.
* faces.c: Declare Qforeback.
* lisp.h: Externalize it.
* faces.c (syms_of_faces): Define it.
* faces.c (vars_of_faces): Update built-in face specifiers.
* faces.c (complex_vars_of_faces): Update specifier fallbacks.
* faces.c (mark_face):
* faces.c (face_equal):
* faces.c (face_getprop):
* faces.c (face_putprop):
* faces.c (face_remprop):
* faces.c (face_plist):
* faces.c (reset_face):
* faces.c (update_face_inheritance_mapper):
* faces.c (Fmake_face):
* faces.c (mark_face_cachels):
* faces.c (update_face_cachel_data):
* faces.c (merge_face_cachel_data):
* faces.c (reset_face_cachel):
* faces.c (face_property_was_changed):
* faces.c (Fcopy_face):
* fontcolor.c (face_color_validate): Handle the foreback property.
* redisplay-msw.c (mswindows_output_blank):
* redisplay-msw.c (mswindows_output_string):
* redisplay-output.c (redisplay_clear_region):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay-xlike-inc.c (XLIKE_output_blank): Use the face's
foreback color instead of the foreground one for drawing a
background bitmap.
author | Didier Verna <didier@xemacs.org> |
---|---|
date | Tue, 27 Dec 2011 17:07:23 +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 } |