Mercurial > hg > xemacs-beta
annotate src/number-mp.c @ 5795:d2c0ff38ad5c
Report lstream errors when encoding/decoding.
See <CAHCOHQ=FAieD-2nP303fMvwkii8HK2z+X7gRZ2+4PH1CA5_-NA@mail.gmail.com> in
xemacs-patches.
author | Jerry James <james@xemacs.org> |
---|---|
date | Wed, 14 May 2014 14:16:24 -0600 |
parents | a2912073be85 |
children | 574f0cded429 |
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> | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
24 #include <stdlib.h> |
1983 | 25 #include "lisp.h" |
26 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
27 static MINT *bignum_bytesize, *bignum_one, *bignum_two; |
1983 | 28 MINT *bignum_zero, *intern_bignum; |
29 MINT *bignum_min_int, *bignum_max_int, *bignum_max_uint; | |
30 MINT *bignum_min_long, *bignum_max_long, *bignum_max_ulong; | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
31 MINT *bignum_min_llong, *bignum_max_llong, *bignum_max_ullong; |
1983 | 32 short div_rem; |
33 | |
34 char * | |
35 bignum_to_string (bignum b, int base) | |
36 { | |
37 REGISTER unsigned int i; | |
38 unsigned int bufsize = 128U, index = 0U; | |
39 int sign; | |
40 char *buffer = xnew_array (char, 128), *retval; | |
41 MINT *quo = MP_ITOM (0); | |
42 short rem; | |
43 | |
44 /* FIXME: signal something if base is < 2 or doesn't fit into a short. */ | |
45 | |
46 /* 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
|
47 sign = bignum_sign (b); |
1983 | 48 |
49 if (sign == 0) | |
50 { | |
51 XREALLOC_ARRAY (buffer, char, 2); | |
52 buffer[0] = '0'; | |
53 buffer[1] = '\0'; | |
54 return buffer; | |
55 } | |
56 /* Copy abs(b) into quo for destructive modification */ | |
57 else if (sign < 0) | |
58 MP_MSUB (bignum_zero, b, quo); | |
59 else | |
60 MP_MOVE (b, quo); | |
61 | |
62 /* Loop over the digits of b (in BASE) and place each one into buffer */ | |
63 for (i = 0U; MP_MCMP(quo, bignum_zero) > 0; i++) | |
64 { | |
65 MP_SDIV (quo, base, quo, &rem); | |
66 if (index == bufsize) | |
67 { | |
68 bufsize <<= 1; | |
69 XREALLOC_ARRAY (buffer, char, bufsize); | |
70 } | |
71 buffer[index++] = rem < 10 ? rem + '0' : rem - 10 + 'a'; | |
72 } | |
73 MP_MFREE (quo); | |
74 | |
75 /* Reverse the digits, maybe add a minus sign, and add a null terminator */ | |
76 bufsize = index + (sign < 0 ? 1 : 0) + 1; | |
77 retval = xnew_array (char, bufsize); | |
78 if (sign < 0) | |
79 { | |
80 retval[0] = '-'; | |
81 i = 1; | |
82 } | |
83 else | |
84 i = 0; | |
85 for (; i < bufsize - 1; i++) | |
86 retval[i] = buffer[--index]; | |
87 retval[bufsize - 1] = '\0'; | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4802
diff
changeset
|
88 xfree (buffer); |
1983 | 89 return retval; |
90 } | |
91 | |
92 #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
|
93 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
|
94 { \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
95 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
|
96 } \ |
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 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
|
99 \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
100 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
|
101 { \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
102 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
|
103 } \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
104 else \ |
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 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
|
107 } \ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
108 \ |
1983 | 109 for (i = 0U; i < sizeof(type); i++) \ |
110 { \ | |
111 MP_SDIV (quo, 256, quo, &rem); \ | |
112 retval |= ((accumtype) rem) << (8 * i); \ | |
113 } \ | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
114 bignum_fini (quo); \ |
1983 | 115 } while (0) |
116 | |
117 int | |
118 bignum_to_int (bignum b) | |
119 { | |
120 short rem, sign; | |
121 unsigned int retval = 0; | |
122 REGISTER unsigned int i; | |
123 MINT *quo; | |
124 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
125 sign = bignum_sign (b); |
1983 | 126 BIGNUM_TO_TYPE (int, unsigned int); |
127 return ((int) retval) * sign; | |
128 } | |
129 | |
130 unsigned int | |
131 bignum_to_uint (bignum b) | |
132 { | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
133 short rem, sign; |
1983 | 134 unsigned int retval = 0U; |
135 REGISTER unsigned int i; | |
136 MINT *quo; | |
137 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
138 sign = bignum_sign (b); |
1983 | 139 BIGNUM_TO_TYPE (unsigned int, unsigned int); |
140 return retval; | |
141 } | |
142 | |
143 long | |
144 bignum_to_long (bignum b) | |
145 { | |
146 short rem, sign; | |
147 unsigned long retval = 0L; | |
148 REGISTER unsigned int i; | |
149 MINT *quo; | |
150 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
151 sign = bignum_sign (b); |
1983 | 152 BIGNUM_TO_TYPE (long, unsigned long); |
153 return ((long) retval) * sign; | |
154 } | |
155 | |
156 unsigned long | |
157 bignum_to_ulong (bignum b) | |
158 { | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
159 short rem, sign; |
1983 | 160 unsigned long retval = 0UL; |
161 REGISTER unsigned int i; | |
162 MINT *quo; | |
163 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
164 sign = bignum_sign (b); |
1983 | 165 BIGNUM_TO_TYPE (unsigned long, unsigned long); |
166 return retval; | |
167 } | |
168 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
169 long long |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
170 bignum_to_llong (bignum b) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
171 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
172 short rem, sign; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
173 unsigned long long retval = 0LL; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
174 REGISTER unsigned int i; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
175 MINT *quo; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
176 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
177 sign = bignum_sign (b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
178 BIGNUM_TO_TYPE (long long, unsigned long long); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
179 return ((long long) retval) * sign; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
180 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
181 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
182 unsigned long long |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
183 bignum_to_ullong (bignum b) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
184 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
185 short rem, sign; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
186 unsigned long long retval = 0UL; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
187 REGISTER unsigned int i; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
188 MINT *quo; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
189 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
190 sign = bignum_sign (b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
191 BIGNUM_TO_TYPE (unsigned long long, unsigned long long); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
192 return retval; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
193 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
194 |
1983 | 195 double |
196 bignum_to_double (bignum b) | |
197 { | |
198 short rem, sign; | |
1990 | 199 double retval = 0.0, factor = 1.0; |
1983 | 200 REGISTER unsigned int i; |
201 MINT *quo; | |
202 | |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
203 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
|
204 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
|
205 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
|
206 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
207 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
|
208 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
209 else |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
210 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
211 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
|
212 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
213 |
1990 | 214 for (i = 0U; MP_MCMP (quo, bignum_zero) > 0; i++) |
1983 | 215 { |
216 MP_SDIV (quo, 256, quo, &rem); | |
1990 | 217 retval += rem * factor; |
218 factor *= 256.0; | |
1983 | 219 } |
220 MP_MFREE (quo); | |
221 return retval * sign; | |
222 } | |
223 | |
224 static short | |
225 char_to_number (char c) | |
226 { | |
227 if (c >= '0' && c <= '9') | |
228 return c - '0'; | |
229 if (c >= 'a' && c <= 'z') | |
230 return c - 'a' + 10; | |
231 if (c >= 'A' && c <= 'Z') | |
232 return c - 'A' + 10; | |
233 return -1; | |
234 } | |
235 | |
236 int | |
237 bignum_set_string (bignum b, const char *s, int base) | |
238 { | |
239 MINT *mbase; | |
240 short digit; | |
1993 | 241 int neg = 0; |
1983 | 242 |
243 if (base == 0) | |
244 { | |
245 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) | |
246 { | |
247 base = 16; | |
248 s += 2; | |
249 } | |
250 else if (*s == '0') | |
251 { | |
252 base = 8; | |
253 s++; | |
254 } | |
255 else | |
256 base = 10; | |
257 } | |
258 | |
259 /* FIXME: signal something if base is < 2 or doesn't fit into a short. */ | |
260 | |
1993 | 261 if (*s == '-') |
262 { | |
263 s++; | |
264 neg = 1; | |
265 } | |
266 | |
1983 | 267 mbase = MP_ITOM ((short) base); |
268 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
|
269 |
1983 | 270 for (digit = char_to_number (*s); digit >= 0 && digit < base; |
271 digit = char_to_number (*++s)) | |
272 { | |
273 MINT *temp; | |
274 | |
275 MP_MULT (b, mbase, b); | |
276 temp = MP_ITOM (digit); | |
277 MP_MADD (b, temp, b); | |
278 MP_MFREE (temp); | |
279 } | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
280 MP_MFREE (mbase); |
1983 | 281 |
1993 | 282 if (neg) |
283 MP_MSUB (bignum_zero, b, b); | |
284 | |
1983 | 285 return (digit >= 0) ? -1 : 0; |
286 } | |
287 | |
288 void | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
289 bignum_set_long (bignum b, long l) |
1983 | 290 { |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
291 char hex[SIZEOF_LONG * 2U + 2U]; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
292 MINT *temp; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
293 int neg = l < 0L; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
294 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
295 snprintf (hex, SIZEOF_LONG * 2U + 2U, "%lx", |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
296 neg ? (unsigned long) -l : (unsigned long) l); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
297 temp = MP_XTOM (hex); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
298 if (neg) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
299 MP_MSUB (bignum_zero, temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
300 else |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
301 MP_MOVE (temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
302 MP_MFREE (temp); |
1983 | 303 } |
304 | |
305 void | |
306 bignum_set_ulong (bignum b, unsigned long l) | |
307 { | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
308 char hex[SIZEOF_LONG * 2U + 2U]; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
309 MINT *temp; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
310 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
311 snprintf (hex, SIZEOF_LONG * 2U + 2U, "%lx", l); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
312 temp = MP_XTOM (hex); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
313 MP_MOVE (temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
314 MP_MFREE (temp); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
315 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
316 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
317 void |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
318 bignum_set_llong (bignum b, long long l) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
319 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
320 char hex[SIZEOF_LONG_LONG * 2U + 2U]; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
321 MINT *temp; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
322 int neg = l < 0LL; |
1983 | 323 |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
324 snprintf (hex, SIZEOF_LONG_LONG * 2U + 2U, "%llx", |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
325 neg ? (unsigned long long) -l : (unsigned long long) l); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
326 temp = MP_XTOM (hex); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
327 if (neg) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
328 MP_MSUB (bignum_zero, temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
329 else |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
330 MP_MOVE (temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
331 MP_MFREE (temp); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
332 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
333 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
334 void |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
335 bignum_set_ullong (bignum b, unsigned long long l) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
336 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
337 char hex[SIZEOF_LONG_LONG * 2U + 2U]; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
338 MINT *temp; |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
339 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
340 snprintf (hex, SIZEOF_LONG_LONG * 2U + 2U, "%llx", l); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
341 temp = MP_XTOM (hex); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
342 MP_MOVE (temp, b); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
343 MP_MFREE (temp); |
1983 | 344 } |
345 | |
346 void | |
347 bignum_set_double (bignum b, double d) | |
348 { | |
349 REGISTER unsigned int i; | |
350 int negative = (d < 0) ? 1 : 0; | |
351 MINT *multiplier = MP_ITOM (1); | |
352 | |
353 MP_MOVE (bignum_zero, b); | |
354 if (negative) | |
355 d = -d; | |
356 for (i = 0UL; d > 0.0; d /= 256, i++) | |
357 { | |
358 MINT *temp = MP_ITOM ((short) fmod (d, 256.0)); | |
359 MP_MULT (multiplier, temp, temp); | |
360 MP_MADD (b, temp, b); | |
361 MP_MULT (multiplier, bignum_bytesize, multiplier); | |
362 MP_MFREE (temp); | |
363 } | |
364 MP_MFREE (multiplier); | |
365 if (negative) | |
366 MP_MSUB (bignum_zero, b, b); | |
367 } | |
368 | |
369 /* Return nonzero if b1 is exactly divisible by b2 */ | |
370 int | |
371 bignum_divisible_p (bignum b1, bignum b2) | |
372 { | |
373 int retval; | |
374 MINT *rem = MP_ITOM (0); | |
375 MP_MDIV (b1, b2, intern_bignum, rem); | |
376 retval = (MP_MCMP (rem, bignum_zero) == 0); | |
377 MP_MFREE (rem); | |
378 return retval; | |
379 } | |
380 | |
381 void bignum_ceil (bignum quotient, bignum N, bignum D) | |
382 { | |
383 MP_MDIV (N, D, quotient, intern_bignum); | |
5646
7aa144d1404b
Remove a redundant double division, number-mp.c:bignum_ceil().
Aidan Kehoe <kehoea@parhasard.net>
parents:
5602
diff
changeset
|
384 |
5602
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
385 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
|
386 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
387 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
|
388 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
|
389 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
390 /* 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
|
391 positive infinity. */ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
392 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
|
393 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
394 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
|
395 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
396 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
|
397 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
398 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
399 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
|
400 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
401 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
|
402 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
403 } |
1983 | 404 } |
405 | |
406 void bignum_floor (bignum quotient, bignum N, bignum D) | |
407 { | |
408 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
|
409 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
410 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
|
411 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
412 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
|
413 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
|
414 |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
415 /* 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
|
416 infinity. */ |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
417 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
|
418 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
419 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
|
420 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
421 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
|
422 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
423 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
424 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
|
425 { |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
426 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
|
427 } |
c9e5612f5424
Support the MP library on recent FreeBSD, have it pass relevant tests.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5405
diff
changeset
|
428 } |
1983 | 429 } |
430 | |
431 /* RESULT = N to the POWth power */ | |
432 void | |
433 bignum_pow (bignum result, bignum n, unsigned long pow) | |
434 { | |
435 MP_MOVE (bignum_one, result); | |
436 for ( ; pow > 0UL; pow--) | |
437 MP_MULT (result, n, result); | |
438 } | |
439 | |
440 /* lcm(b1,b2) = b1 * b2 / gcd(b1, b2) */ | |
441 void | |
442 bignum_lcm (bignum result, bignum b1, bignum b2) | |
443 { | |
444 MP_MULT (b1, b2, result); | |
445 MP_GCD (b1, b2, intern_bignum); | |
446 MP_MDIV (result, intern_bignum, result, intern_bignum); | |
447 } | |
448 | |
449 /* FIXME: We can't handle negative args, so right now we just make them | |
450 positive before doing anything else. How should we really handle negative | |
451 args? */ | |
452 #define bignum_bit_op(result, b1, b2, op) \ | |
453 REGISTER unsigned int i; \ | |
454 MINT *multiplier = MP_ITOM (1), *n1 = MP_ITOM (0), *n2 = MP_ITOM (0); \ | |
455 \ | |
456 if (MP_MCMP (bignum_zero, b1) > 0) \ | |
457 MP_MSUB (bignum_zero, b1, n1); \ | |
458 else \ | |
459 MP_MOVE (b1, n1); \ | |
460 if (MP_MCMP (bignum_zero, b2) > 0) \ | |
461 MP_MSUB (bignum_zero, b2, n2); \ | |
462 else \ | |
463 MP_MOVE (b2, n2); \ | |
464 \ | |
465 MP_MOVE (bignum_zero, result); \ | |
466 \ | |
467 for (i = 0UL; MP_MCMP (bignum_zero, n1) < 0 && \ | |
468 MP_MCMP (bignum_zero, n2) < 0; i++) \ | |
469 { \ | |
470 short byte1, byte2; \ | |
471 MINT *temp; \ | |
472 \ | |
473 MP_SDIV (n1, 256, n1, &byte1); \ | |
474 MP_SDIV (n2, 256, n2, &byte2); \ | |
475 temp = MP_ITOM (byte1 op byte2); \ | |
476 MP_MULT (multiplier, temp, temp); \ | |
477 MP_MADD (result, temp, result); \ | |
478 MP_MULT (multiplier, bignum_bytesize, multiplier); \ | |
479 MP_MFREE (temp); \ | |
480 } \ | |
481 MP_MFREE (n2); \ | |
482 MP_MFREE (n1); \ | |
483 MP_MFREE (multiplier) | |
484 | |
485 void | |
486 bignum_and (bignum result, bignum b1, bignum b2) | |
487 { | |
488 bignum_bit_op (result, b1, b2, &); | |
489 } | |
490 | |
491 void | |
492 bignum_ior (bignum result, bignum b1, bignum b2) | |
493 { | |
494 bignum_bit_op (result, b1, b2, |); | |
495 } | |
496 | |
497 void | |
498 bignum_xor (bignum result, bignum b1, bignum b2) | |
499 { | |
500 bignum_bit_op (result, b1, b2, ^); | |
501 } | |
502 | |
503 /* NOT is not well-defined for bignums ... where do you stop flipping bits? | |
504 We just flip until we see the last one. This is probably a bad idea. */ | |
505 void | |
506 bignum_not (bignum result, bignum b) | |
507 { | |
508 REGISTER unsigned int i; | |
509 MINT *multiplier = MP_ITOM (1), *n = MP_ITOM (0); | |
510 | |
511 if (MP_MCMP (bignum_zero, b) > 0) | |
512 MP_MSUB (bignum_zero, b, n); | |
513 else | |
514 MP_MOVE (b, n); | |
515 | |
516 MP_MOVE (bignum_zero, result); | |
517 | |
518 for (i = 0UL; MP_MCMP (bignum_zero, n) < 0; i++) | |
519 { | |
520 short byte; | |
521 MINT *temp; | |
522 | |
523 MP_SDIV (n, 256, n, &byte); | |
524 temp = MP_ITOM (~byte); | |
525 MP_MULT (multiplier, temp, temp); | |
526 MP_MADD (result, temp, result); | |
527 MP_MULT (multiplier, bignum_bytesize, multiplier); | |
528 MP_MFREE (temp); | |
529 } | |
530 MP_MFREE (n); | |
531 MP_MFREE (multiplier); | |
532 } | |
533 | |
534 void | |
535 bignum_setbit (bignum b, unsigned long bit) | |
536 { | |
537 bignum_pow (intern_bignum, bignum_two, bit); | |
538 bignum_ior (b, b, intern_bignum); | |
539 } | |
540 | |
541 /* This is so evil, even I feel queasy. */ | |
542 void | |
543 bignum_clrbit (bignum b, unsigned long bit) | |
544 { | |
545 MINT *num = MP_ITOM (0); | |
546 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
547 /* See if the bit is set, and subtract it off if so */ |
1983 | 548 MP_MOVE (b, intern_bignum); |
549 bignum_pow (num, bignum_two, bit); | |
550 bignum_ior (intern_bignum, intern_bignum, num); | |
551 if (MP_MCMP (b, intern_bignum) == 0) | |
552 MP_MSUB (b, num, b); | |
553 MP_MFREE (num); | |
554 } | |
555 | |
556 int | |
557 bignum_testbit (bignum b, unsigned long bit) | |
558 { | |
559 bignum_pow (intern_bignum, bignum_two, bit); | |
560 bignum_and (intern_bignum, b, intern_bignum); | |
561 return MP_MCMP (intern_bignum, bignum_zero); | |
562 } | |
563 | |
564 void | |
565 bignum_lshift (bignum result, bignum b, unsigned long bits) | |
566 { | |
567 bignum_pow (intern_bignum, bignum_two, bits); | |
568 MP_MULT (b, intern_bignum, result); | |
569 } | |
570 | |
571 void | |
572 bignum_rshift (bignum result, bignum b, unsigned long bits) | |
573 { | |
574 bignum_pow (intern_bignum, bignum_two, bits); | |
575 MP_MDIV (b, intern_bignum, result, intern_bignum); | |
576 } | |
577 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
578 void |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
579 bignum_random (bignum result, bignum limit) |
1983 | 580 { |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
581 MINT *denominator = MP_ITOM (0), *divisor = MP_ITOM (0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
582 bignum_set_long (denominator, RAND_MAX); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
583 MP_MADD (denominator, bignum_one, denominator); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
584 MP_MADD (limit, bignum_one, divisor); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
585 MP_MDIV (denominator, divisor, denominator, intern_bignum); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
586 MP_MFREE (divisor); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
587 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
588 do |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
589 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
590 MINT *limitcmp = MP_ITOM (1); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
591 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
592 /* Accumulate at least as many random bits as in LIMIT */ |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
593 MP_MOVE (bignum_zero, result); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
594 do |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
595 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
596 bignum_lshift (limitcmp, limitcmp, FIXNUM_VALBITS); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
597 bignum_lshift (result, result, FIXNUM_VALBITS); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
598 bignum_set_long (intern_bignum, get_random ()); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
599 MP_MADD (intern_bignum, result, result); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
600 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
601 while (MP_MCMP (limitcmp, limit) <= 0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
602 MP_MDIV (result, denominator, result, intern_bignum); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
603 MP_MFREE (limitcmp); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
604 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
605 while (MP_MCMP (limit, result) <= 0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
606 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
607 MP_MFREE (denominator); |
1983 | 608 } |
609 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
610 #ifdef HAVE_MP_SET_MEMORY_FUNCTIONS |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
611 /* We need the next two functions due to the extra parameter. */ |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
612 static void * |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
613 mp_realloc (void *ptr, size_t UNUSED (old_size), size_t new_size) |
1983 | 614 { |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
615 return xrealloc (ptr, new_size); |
1983 | 616 } |
617 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
618 static void |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
619 mp_free (void *ptr, size_t UNUSED (size)) |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
620 { |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
621 xfree (ptr); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
622 } |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
623 #endif |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
624 |
1983 | 625 void |
5739
a2912073be85
Support bignums with MPIR. Add documentation on the bignum, ratio,
Jerry James <james@xemacs.org>
parents:
5736
diff
changeset
|
626 init_number_mp (void) |
1983 | 627 { |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
628 #ifdef HAVE_MP_SET_MEMORY_FUNCTIONS |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
629 mp_set_memory_functions ((void *(*) (size_t)) xmalloc, mp_realloc, mp_free); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
630 #endif |
1983 | 631 |
632 bignum_zero = MP_ITOM (0); | |
633 bignum_one = MP_ITOM (1); | |
634 bignum_two = MP_ITOM (2); | |
635 | |
636 /* intern_bignum holds throwaway values from macro expansions in | |
637 number-mp.h. Its value is immaterial. */ | |
638 intern_bignum = MP_ITOM (0); | |
639 | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
640 /* The multiplier used to shift a number left by one byte's worth of bits */ |
1983 | 641 bignum_bytesize = MP_ITOM (256); |
642 | |
643 /* The MP interface only supports turning short ints into MINTs, so we have | |
644 to set these the hard way. */ | |
645 | |
646 bignum_min_int = MP_ITOM (0); | |
647 bignum_set_long (bignum_min_int, INT_MIN); | |
648 | |
649 bignum_max_int = MP_ITOM (0); | |
650 bignum_set_long (bignum_max_int, INT_MAX); | |
651 | |
652 bignum_max_uint = MP_ITOM (0); | |
653 bignum_set_ulong (bignum_max_uint, UINT_MAX); | |
654 | |
655 bignum_min_long = MP_ITOM (0); | |
656 bignum_set_long (bignum_min_long, LONG_MIN); | |
657 | |
658 bignum_max_long = MP_ITOM (0); | |
659 bignum_set_long (bignum_max_long, LONG_MAX); | |
660 | |
661 bignum_max_ulong = MP_ITOM (0); | |
662 bignum_set_ulong (bignum_max_ulong, ULONG_MAX); | |
5736
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
663 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
664 bignum_min_llong = MP_ITOM (0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
665 bignum_set_llong (bignum_min_llong, LLONG_MIN); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
666 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
667 bignum_max_llong = MP_ITOM (0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
668 bignum_set_llong (bignum_max_llong, LLONG_MAX); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
669 |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
670 bignum_max_ullong = MP_ITOM (0); |
3192994c49ca
Convert C (un)signed long long values to bignums properly.
Jerry James <james@xemacs.org>
parents:
5646
diff
changeset
|
671 bignum_set_ullong (bignum_max_ullong, ULLONG_MAX); |
1983 | 672 } |