Ruby 2.7.7p221 (2022-11-24 revision 168ec2b1e5ad0e4688e963d9de019557c78feed9)
bignum.c
Go to the documentation of this file.
1/**********************************************************************
2
3 bignum.c -
4
5 $Author$
6 created at: Fri Jun 10 00:48:55 JST 1994
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "internal.h"
13#include "ruby/thread.h"
14#include "ruby/util.h"
15#include "id.h"
16
17#ifdef HAVE_STRINGS_H
18#include <strings.h>
19#endif
20#include <math.h>
21#include <float.h>
22#include <ctype.h>
23#ifdef HAVE_IEEEFP_H
24#include <ieeefp.h>
25#endif
26#include "ruby_assert.h"
27
28#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
29#define USE_GMP
30#include <gmp.h>
31#endif
32
33#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
34
35#ifndef RUBY_INTEGER_UNIFICATION
37#endif
38const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
39
40#ifndef SIZEOF_BDIGIT_DBL
41# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
42# define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
43# else
44# define SIZEOF_BDIGIT_DBL SIZEOF_LONG
45# endif
46#endif
47
48STATIC_ASSERT(sizeof_bdigit_dbl, sizeof(BDIGIT_DBL) == SIZEOF_BDIGIT_DBL);
49STATIC_ASSERT(sizeof_bdigit_dbl_signed, sizeof(BDIGIT_DBL_SIGNED) == SIZEOF_BDIGIT_DBL);
50STATIC_ASSERT(sizeof_bdigit, SIZEOF_BDIGIT <= sizeof(BDIGIT));
51STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGIT*2 <= SIZEOF_BDIGIT_DBL);
52STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
53STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
54STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
56
57#if SIZEOF_BDIGIT < SIZEOF_LONG
58STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
59#else
60STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
61#endif
62
63#ifdef WORDS_BIGENDIAN
64# define HOST_BIGENDIAN_P 1
65#else
66# define HOST_BIGENDIAN_P 0
67#endif
68/* (!LSHIFTABLE(d, n) ? 0 : (n)) is same as n but suppress a warning, C4293, by Visual Studio. */
69#define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
70#define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
71#define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
72#define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
73#define POW2_P(x) (((x)&((x)-1))==0)
74
75#define BDIGITS(x) (BIGNUM_DIGITS(x))
76#define BITSPERDIG (SIZEOF_BDIGIT*CHAR_BIT)
77#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
78#define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
79#define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
80#define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
81#define BIGDN(x) RSHIFT((x),BITSPERDIG)
82#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
83#define BDIGMAX ((BDIGIT)(BIGRAD-1))
84#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
85
86#if SIZEOF_BDIGIT == 2
87# define swap_bdigit(x) swap16(x)
88#elif SIZEOF_BDIGIT == 4
89# define swap_bdigit(x) swap32(x)
90#elif SIZEOF_BDIGIT == 8
91# define swap_bdigit(x) swap64(x)
92#endif
93
94#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
95 (BDIGITS(x)[0] == 0 && \
96 (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
97#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
98 BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
99 (size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
100 rb_absint_size(x, NULL))
101
102#define BIGDIVREM_EXTRA_WORDS 1
103#define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT)
104#define BARY_ARGS(ary) ary, numberof(ary)
105
106#define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
107#define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
108#define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
109#define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
110#define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
111
112#define BIGNUM_SET_NEGATIVE_SIGN(b) BIGNUM_SET_SIGN(b, 0)
113#define BIGNUM_SET_POSITIVE_SIGN(b) BIGNUM_SET_SIGN(b, 1)
114
115#define bignew(len,sign) bignew_1(rb_cInteger,(len),(sign))
116
117#define BDIGITS_ZERO(ptr, n) do { \
118 BDIGIT *bdigitz_zero_ptr = (ptr); \
119 size_t bdigitz_zero_n = (n); \
120 while (bdigitz_zero_n) { \
121 *bdigitz_zero_ptr++ = 0; \
122 bdigitz_zero_n--; \
123 } \
124} while (0)
125
126#define BARY_TRUNC(ds, n) do { \
127 while (0 < (n) && (ds)[(n)-1] == 0) \
128 (n)--; \
129 } while (0)
130
131#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
132#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
133
134#define GMP_MUL_DIGITS 20
135#define KARATSUBA_MUL_DIGITS 70
136#define TOOM3_MUL_DIGITS 150
137
138#define GMP_DIV_DIGITS 20
139#define GMP_BIG2STR_DIGITS 20
140#define GMP_STR2BIG_DIGITS 20
141#ifdef USE_GMP
142# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
143#else
144# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
145#endif
146
147typedef void (mulfunc_t)(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn);
148
149static mulfunc_t bary_mul_toom3_start;
150static mulfunc_t bary_mul_karatsuba_start;
151static BDIGIT bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y);
152static void bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn);
153
154static VALUE bigmul0(VALUE x, VALUE y);
155static void bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn);
156static VALUE bignew_1(VALUE klass, size_t len, int sign);
157static inline VALUE bigtrunc(VALUE x);
158
159static VALUE bigsq(VALUE x);
160static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp);
161static inline VALUE power_cache_get_power(int base, int power_level, size_t *numdigits_ret);
162
163#if SIZEOF_BDIGIT <= SIZEOF_INT
164static int nlz(BDIGIT x) { return nlz_int((unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGIT) * CHAR_BIT; }
165#elif SIZEOF_BDIGIT <= SIZEOF_LONG
166static int nlz(BDIGIT x) { return nlz_long((unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
167#elif SIZEOF_BDIGIT <= SIZEOF_LONG_LONG
168static int nlz(BDIGIT x) { return nlz_long_long((unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
169#elif SIZEOF_BDIGIT <= SIZEOF_INT128_T
170static int nlz(BDIGIT x) { return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGIT) * CHAR_BIT; }
171#endif
172
173#define U16(a) ((uint16_t)(a))
174#define U32(a) ((uint32_t)(a))
175#ifdef HAVE_UINT64_T
176#define U64(a,b) (((uint64_t)(a) << 32) | (b))
177#endif
178#ifdef HAVE_UINT128_T
179#define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
180#endif
181
182/* The following script, maxpow.rb, generates the tables follows.
183
184def big(n, bits)
185 ns = []
186 ((bits+31)/32).times {
187 ns << sprintf("0x%08x", n & 0xffff_ffff)
188 n >>= 32
189 }
190 "U#{bits}(" + ns.reverse.join(",") + ")"
191end
192def values(ary, width, indent)
193 lines = [""]
194 ary.each {|e|
195 lines << "" if !ary.last.empty? && width < (lines.last + e + ", ").length
196 lines.last << e + ", "
197 }
198 lines.map {|line| " " * indent + line.chomp(" ") + "\n" }.join
199end
200[16,32,64,128].each {|bits|
201 max = 2**bits-1
202 exps = []
203 nums = []
204 2.upto(36) {|base|
205 exp = 0
206 n = 1
207 while n * base <= max
208 exp += 1
209 n *= base
210 end
211 exps << exp.to_s
212 nums << big(n, bits)
213 }
214 puts "#ifdef HAVE_UINT#{bits}_T"
215 puts "static const int maxpow#{bits}_exp[35] = {"
216 print values(exps, 70, 4)
217 puts "};"
218 puts "static const uint#{bits}_t maxpow#{bits}_num[35] = {"
219 print values(nums, 70, 4)
220 puts "};"
221 puts "#endif"
222}
223
224 */
225
226#if SIZEOF_BDIGIT_DBL == 2
227static const int maxpow16_exp[35] = {
228 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
229 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
230};
231static const uint16_t maxpow16_num[35] = {
232 U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
233 U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
234 U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
235 U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
236 U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
237 U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
238 U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
239 U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
240 U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
241};
242#elif SIZEOF_BDIGIT_DBL == 4
243static const int maxpow32_exp[35] = {
244 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
245 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
246};
247static const uint32_t maxpow32_num[35] = {
248 U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
249 U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
250 U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
251 U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
252 U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
253 U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
254 U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
255 U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
256 U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
257};
258#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
259static const int maxpow64_exp[35] = {
260 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
261 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
262 12,
263};
264static const uint64_t maxpow64_num[35] = {
265 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
266 U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
267 U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
268 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
269 U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
270 U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
271 U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
272 U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
273 U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
274 U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
275 U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
276 U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
277 U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
278 U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
279 U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
280 U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
281 U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
282 U64(0x41c21cb8,0xe1000000),
283};
284#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
285static const int maxpow128_exp[35] = {
286 127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
287 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
288 24,
289};
290static const uint128_t maxpow128_num[35] = {
291 U128(0x80000000,0x00000000,0x00000000,0x00000000),
292 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
293 U128(0x40000000,0x00000000,0x00000000,0x00000000),
294 U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
295 U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
296 U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
297 U128(0x40000000,0x00000000,0x00000000,0x00000000),
298 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
299 U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
300 U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
301 U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
302 U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
303 U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
304 U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
305 U128(0x10000000,0x00000000,0x00000000,0x00000000),
306 U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
307 U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
308 U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
309 U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
310 U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
311 U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
312 U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
313 U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
314 U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
315 U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
316 U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
317 U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
318 U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
319 U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
320 U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
321 U128(0x20000000,0x00000000,0x00000000,0x00000000),
322 U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
323 U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
324 U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
325 U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
326};
327#endif
328
329static BDIGIT_DBL
330maxpow_in_bdigit_dbl(int base, int *exp_ret)
331{
332 BDIGIT_DBL maxpow;
333 int exponent;
334
335 assert(2 <= base && base <= 36);
336
337 {
338#if SIZEOF_BDIGIT_DBL == 2
339 maxpow = maxpow16_num[base-2];
340 exponent = maxpow16_exp[base-2];
341#elif SIZEOF_BDIGIT_DBL == 4
342 maxpow = maxpow32_num[base-2];
343 exponent = maxpow32_exp[base-2];
344#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
345 maxpow = maxpow64_num[base-2];
346 exponent = maxpow64_exp[base-2];
347#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
348 maxpow = maxpow128_num[base-2];
349 exponent = maxpow128_exp[base-2];
350#else
351 maxpow = base;
352 exponent = 1;
353 while (maxpow <= BDIGIT_DBL_MAX / base) {
354 maxpow *= base;
355 exponent++;
356 }
357#endif
358 }
359
360 *exp_ret = exponent;
361 return maxpow;
362}
363
364static inline BDIGIT_DBL
365bary2bdigitdbl(const BDIGIT *ds, size_t n)
366{
367 assert(n <= 2);
368
369 if (n == 2)
370 return ds[0] | BIGUP(ds[1]);
371 if (n == 1)
372 return ds[0];
373 return 0;
374}
375
376static inline void
377bdigitdbl2bary(BDIGIT *ds, size_t n, BDIGIT_DBL num)
378{
379 assert(n == 2);
380
381 ds[0] = BIGLO(num);
382 ds[1] = (BDIGIT)BIGDN(num);
383}
384
385static int
386bary_cmp(const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
387{
388 size_t i;
389 BARY_TRUNC(xds, xn);
390 BARY_TRUNC(yds, yn);
391
392 if (xn < yn)
393 return -1;
394 if (xn > yn)
395 return 1;
396
397 for (i = 0; i < xn; i++)
398 if (xds[xn - i - 1] != yds[yn - i - 1])
399 break;
400 if (i == xn)
401 return 0;
402 return xds[xn - i - 1] < yds[yn - i - 1] ? -1 : 1;
403}
404
405static BDIGIT
406bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
407{
408 size_t i;
409 BDIGIT_DBL num = 0;
410 assert(0 <= shift && shift < BITSPERDIG);
411
412 for (i=0; i<n; i++) {
413 num = num | (BDIGIT_DBL)*xds++ << shift;
414 *zds++ = BIGLO(num);
415 num = BIGDN(num);
416 }
417 return BIGLO(num);
418}
419
420static void
421bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT higher_bdigit)
422{
423 size_t i;
424 BDIGIT_DBL num = 0;
425
426 assert(0 <= shift && shift < BITSPERDIG);
427
428 num = BIGUP(higher_bdigit);
429 for (i = 0; i < n; i++) {
430 BDIGIT x = xds[n - i - 1];
431 num = (num | x) >> shift;
432 zds[n - i - 1] = BIGLO(num);
433 num = BIGUP(x);
434 }
435}
436
437static int
438bary_zero_p(const BDIGIT *xds, size_t xn)
439{
440 if (xn == 0)
441 return 1;
442 do {
443 if (xds[--xn]) return 0;
444 } while (xn);
445 return 1;
446}
447
448static void
449bary_neg(BDIGIT *ds, size_t n)
450{
451 size_t i;
452 for (i = 0; i < n; i++)
453 ds[n - i - 1] = BIGLO(~ds[n - i - 1]);
454}
455
456static int
457bary_2comp(BDIGIT *ds, size_t n)
458{
459 size_t i;
460 i = 0;
461 for (i = 0; i < n; i++) {
462 if (ds[i] != 0) {
463 goto non_zero;
464 }
465 }
466 return 1;
467
468 non_zero:
469 ds[i] = BIGLO(~ds[i] + 1);
470 i++;
471 for (; i < n; i++) {
472 ds[i] = BIGLO(~ds[i]);
473 }
474 return 0;
475}
476
477static void
478bary_swap(BDIGIT *ds, size_t num_bdigits)
479{
480 BDIGIT *p1 = ds;
481 BDIGIT *p2 = ds + num_bdigits - 1;
482 for (; p1 < p2; p1++, p2--) {
483 BDIGIT tmp = *p1;
484 *p1 = *p2;
485 *p2 = tmp;
486 }
487}
488
489#define INTEGER_PACK_WORDORDER_MASK \
490 (INTEGER_PACK_MSWORD_FIRST | \
491 INTEGER_PACK_LSWORD_FIRST)
492#define INTEGER_PACK_BYTEORDER_MASK \
493 (INTEGER_PACK_MSBYTE_FIRST | \
494 INTEGER_PACK_LSBYTE_FIRST | \
495 INTEGER_PACK_NATIVE_BYTE_ORDER)
496
497static void
498validate_integer_pack_format(size_t numwords, size_t wordsize, size_t nails, int flags, int supported_flags)
499{
500 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
501 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
502
503 if (flags & ~supported_flags) {
504 rb_raise(rb_eArgError, "unsupported flags specified");
505 }
506 if (wordorder_bits == 0) {
507 if (1 < numwords)
508 rb_raise(rb_eArgError, "word order not specified");
509 }
510 else if (wordorder_bits != INTEGER_PACK_MSWORD_FIRST &&
511 wordorder_bits != INTEGER_PACK_LSWORD_FIRST)
512 rb_raise(rb_eArgError, "unexpected word order");
513 if (byteorder_bits == 0) {
514 rb_raise(rb_eArgError, "byte order not specified");
515 }
516 else if (byteorder_bits != INTEGER_PACK_MSBYTE_FIRST &&
517 byteorder_bits != INTEGER_PACK_LSBYTE_FIRST &&
518 byteorder_bits != INTEGER_PACK_NATIVE_BYTE_ORDER)
519 rb_raise(rb_eArgError, "unexpected byte order");
520 if (wordsize == 0)
521 rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
522 if (SSIZE_MAX < wordsize)
523 rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
524 if (wordsize <= nails / CHAR_BIT)
525 rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails);
526 if (SIZE_MAX / wordsize < numwords)
527 rb_raise(rb_eArgError, "too big numwords * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", numwords, wordsize);
528}
529
530static void
531integer_pack_loop_setup(
532 size_t numwords, size_t wordsize, size_t nails, int flags,
533 size_t *word_num_fullbytes_ret,
534 int *word_num_partialbits_ret,
535 size_t *word_start_ret,
536 ssize_t *word_step_ret,
537 size_t *word_last_ret,
538 size_t *byte_start_ret,
539 int *byte_step_ret)
540{
541 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
542 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
543 size_t word_num_fullbytes;
544 int word_num_partialbits;
545 size_t word_start;
546 ssize_t word_step;
547 size_t word_last;
548 size_t byte_start;
549 int byte_step;
550
551 word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
552 if (word_num_partialbits == CHAR_BIT)
553 word_num_partialbits = 0;
554 word_num_fullbytes = wordsize - (nails / CHAR_BIT);
555 if (word_num_partialbits != 0) {
556 word_num_fullbytes--;
557 }
558
559 if (wordorder_bits == INTEGER_PACK_MSWORD_FIRST) {
560 word_start = wordsize*(numwords-1);
561 word_step = -(ssize_t)wordsize;
562 word_last = 0;
563 }
564 else {
565 word_start = 0;
566 word_step = wordsize;
567 word_last = wordsize*(numwords-1);
568 }
569
570 if (byteorder_bits == INTEGER_PACK_NATIVE_BYTE_ORDER) {
571#ifdef WORDS_BIGENDIAN
572 byteorder_bits = INTEGER_PACK_MSBYTE_FIRST;
573#else
574 byteorder_bits = INTEGER_PACK_LSBYTE_FIRST;
575#endif
576 }
577 if (byteorder_bits == INTEGER_PACK_MSBYTE_FIRST) {
578 byte_start = wordsize-1;
579 byte_step = -1;
580 }
581 else {
582 byte_start = 0;
583 byte_step = 1;
584 }
585
586 *word_num_partialbits_ret = word_num_partialbits;
587 *word_num_fullbytes_ret = word_num_fullbytes;
588 *word_start_ret = word_start;
589 *word_step_ret = word_step;
590 *word_last_ret = word_last;
591 *byte_start_ret = byte_start;
592 *byte_step_ret = byte_step;
593}
594
595static inline void
596integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
597{
598 if (*dpp < *dep && BITSPERDIG <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
599 *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
600 *numbits_in_dd_p += BITSPERDIG;
601 }
602 else if (*dpp == *dep) {
603 /* higher bits are infinity zeros */
604 *numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT;
605 }
606}
607
608static inline BDIGIT_DBL
609integer_pack_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
610{
611 BDIGIT_DBL ret;
612 ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
613 *ddp >>= n;
614 *numbits_in_dd_p -= n;
615 return ret;
616}
617
618#if !defined(WORDS_BIGENDIAN)
619static int
620bytes_2comp(unsigned char *buf, size_t len)
621{
622 size_t i;
623 for (i = 0; i < len; i++) {
624 signed char c = buf[i];
625 signed int d = ~c;
626 unsigned int e = d & 0xFF;
627 buf[i] = e;
628 }
629 for (i = 0; i < len; i++) {
630 buf[i]++;
631 if (buf[i] != 0)
632 return 0;
633 }
634 return 1;
635}
636#endif
637
638static int
639bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
640{
641 BDIGIT *dp, *de;
642 unsigned char *buf, *bufend;
643
644 dp = ds;
645 de = ds + num_bdigits;
646
647 validate_integer_pack_format(numwords, wordsize, nails, flags,
655
656 while (dp < de && de[-1] == 0)
657 de--;
658 if (dp == de) {
659 sign = 0;
660 }
661
663 if (sign == 0) {
664 MEMZERO(words, unsigned char, numwords * wordsize);
665 return 0;
666 }
667 if (nails == 0 && numwords == 1) {
668 int need_swap = wordsize != 1 &&
671 if (0 < sign || !(flags & INTEGER_PACK_2COMP)) {
672 BDIGIT d;
673 if (wordsize == 1) {
674 *((unsigned char *)words) = (unsigned char)(d = dp[0]);
675 return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
676 }
677#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
678 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
679 uint16_t u = (uint16_t)(d = dp[0]);
680 if (need_swap) u = swap16(u);
681 *((uint16_t *)words) = u;
682 return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
683 }
684#endif
685#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
686 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
687 uint32_t u = (uint32_t)(d = dp[0]);
688 if (need_swap) u = swap32(u);
689 *((uint32_t *)words) = u;
690 return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
691 }
692#endif
693#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
694 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
695 uint64_t u = (uint64_t)(d = dp[0]);
696 if (need_swap) u = swap64(u);
697 *((uint64_t *)words) = u;
698 return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
699 }
700#endif
701 }
702 else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */
704 if (wordsize == 1) {
705 *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
706 return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
707 }
708#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
709 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
710 uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
711 if (need_swap) u = swap16(u);
712 *((uint16_t *)words) = u;
713 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
714 (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
715 }
716#endif
717#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
718 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
719 uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
720 if (need_swap) u = swap32(u);
721 *((uint32_t *)words) = u;
722 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
723 (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
724 }
725#endif
726#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
727 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
728 uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
729 if (need_swap) u = swap64(u);
730 *((uint64_t *)words) = u;
731 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
732 (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
733 }
734#endif
735 }
736 }
737#if !defined(WORDS_BIGENDIAN)
738 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
741 size_t src_size = (de - dp) * SIZEOF_BDIGIT;
742 size_t dst_size = numwords * wordsize;
743 int overflow = 0;
744 while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0)
745 src_size--;
746 if (src_size <= dst_size) {
747 MEMCPY(words, dp, char, src_size);
748 MEMZERO((char*)words + src_size, char, dst_size - src_size);
749 }
750 else {
751 MEMCPY(words, dp, char, dst_size);
752 overflow = 1;
753 }
754 if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
755 int zero_p = bytes_2comp(words, dst_size);
756 if (zero_p && overflow) {
757 unsigned char *p = (unsigned char *)dp;
758 if (dst_size == src_size-1 &&
759 p[dst_size] == 1) {
760 overflow = 0;
761 }
762 }
763 }
764 if (overflow)
765 sign *= 2;
766 return sign;
767 }
768#endif
769 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
770 wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words % RUBY_ALIGNOF(BDIGIT) == 0) {
771 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
772 size_t src_num_bdigits = de - dp;
773 size_t dst_num_bdigits = numwords * bdigits_per_word;
774 int overflow = 0;
775 int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
776 int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
777 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
778 if (src_num_bdigits <= dst_num_bdigits) {
779 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
780 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
781 }
782 else {
783 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
784 overflow = 1;
785 }
786 if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
787 int zero_p = bary_2comp(words, dst_num_bdigits);
788 if (zero_p && overflow &&
789 dst_num_bdigits == src_num_bdigits-1 &&
790 dp[dst_num_bdigits] == 1)
791 overflow = 0;
792 }
793 if (msbytefirst_p != HOST_BIGENDIAN_P) {
794 size_t i;
795 for (i = 0; i < dst_num_bdigits; i++) {
796 BDIGIT d = ((BDIGIT*)words)[i];
797 ((BDIGIT*)words)[i] = swap_bdigit(d);
798 }
799 }
800 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
801 size_t i;
802 BDIGIT *p = words;
803 for (i = 0; i < numwords; i++) {
804 bary_swap(p, bdigits_per_word);
805 p += bdigits_per_word;
806 }
807 }
808 if (mswordfirst_p) {
809 bary_swap(words, dst_num_bdigits);
810 }
811 if (overflow)
812 sign *= 2;
813 return sign;
814 }
815 }
816
817 buf = words;
818 bufend = buf + numwords * wordsize;
819
820 if (buf == bufend) {
821 /* overflow if non-zero*/
822 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
823 sign *= 2;
824 else {
825 if (de - dp == 1 && dp[0] == 1)
826 sign = -1; /* val == -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
827 else
828 sign = -2; /* val < -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
829 }
830 }
831 else if (dp == de) {
832 memset(buf, '\0', bufend - buf);
833 }
834 else if (dp < de && buf < bufend) {
835 int word_num_partialbits;
836 size_t word_num_fullbytes;
837
838 ssize_t word_step;
839 size_t byte_start;
840 int byte_step;
841
842 size_t word_start, word_last;
843 unsigned char *wordp, *last_wordp;
844 BDIGIT_DBL dd;
845 int numbits_in_dd;
846
847 integer_pack_loop_setup(numwords, wordsize, nails, flags,
848 &word_num_fullbytes, &word_num_partialbits,
849 &word_start, &word_step, &word_last, &byte_start, &byte_step);
850
851 wordp = buf + word_start;
852 last_wordp = buf + word_last;
853
854 dd = 0;
855 numbits_in_dd = 0;
856
857#define FILL_DD \
858 integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
859#define TAKE_LOWBITS(n) \
860 integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
861
862 while (1) {
863 size_t index_in_word = 0;
864 unsigned char *bytep = wordp + byte_start;
865 while (index_in_word < word_num_fullbytes) {
866 FILL_DD;
867 *bytep = TAKE_LOWBITS(CHAR_BIT);
868 bytep += byte_step;
869 index_in_word++;
870 }
871 if (word_num_partialbits) {
872 FILL_DD;
873 *bytep = TAKE_LOWBITS(word_num_partialbits);
874 bytep += byte_step;
875 index_in_word++;
876 }
877 while (index_in_word < wordsize) {
878 *bytep = 0;
879 bytep += byte_step;
880 index_in_word++;
881 }
882
883 if (wordp == last_wordp)
884 break;
885
886 wordp += word_step;
887 }
888 FILL_DD;
889 /* overflow tests */
890 if (dp != de || 1 < dd) {
891 /* 2**(numwords*(wordsize*CHAR_BIT-nails)+1) <= abs(val) */
892 sign *= 2;
893 }
894 else if (dd == 1) {
895 /* 2**(numwords*(wordsize*CHAR_BIT-nails)) <= abs(val) < 2**(numwords*(wordsize*CHAR_BIT-nails)+1) */
896 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
897 sign *= 2;
898 else { /* overflow_2comp && sign == -1 */
899 /* test lower bits are all zero. */
900 dp = ds;
901 while (dp < de && *dp == 0)
902 dp++;
903 if (de - dp == 1 && /* only one non-zero word. */
904 POW2_P(*dp)) /* *dp contains only one bit set. */
905 sign = -1; /* val == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
906 else
907 sign = -2; /* val < -2**(numwords*(wordsize*CHAR_BIT-nails)) */
908 }
909 }
910 }
911
912 if ((flags & INTEGER_PACK_2COMP) && (sign < 0 && numwords != 0)) {
913 int word_num_partialbits;
914 size_t word_num_fullbytes;
915
916 ssize_t word_step;
917 size_t byte_start;
918 int byte_step;
919
920 size_t word_start, word_last;
921 unsigned char *wordp, *last_wordp;
922
923 unsigned int partialbits_mask;
924 int carry;
925
926 integer_pack_loop_setup(numwords, wordsize, nails, flags,
927 &word_num_fullbytes, &word_num_partialbits,
928 &word_start, &word_step, &word_last, &byte_start, &byte_step);
929
930 partialbits_mask = (1 << word_num_partialbits) - 1;
931
932 buf = words;
933 wordp = buf + word_start;
934 last_wordp = buf + word_last;
935
936 carry = 1;
937 while (1) {
938 size_t index_in_word = 0;
939 unsigned char *bytep = wordp + byte_start;
940 while (index_in_word < word_num_fullbytes) {
941 carry += (unsigned char)~*bytep;
942 *bytep = (unsigned char)carry;
943 carry >>= CHAR_BIT;
944 bytep += byte_step;
945 index_in_word++;
946 }
947 if (word_num_partialbits) {
948 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
949 *bytep = carry & partialbits_mask;
950 carry >>= word_num_partialbits;
951 bytep += byte_step;
952 index_in_word++;
953 }
954
955 if (wordp == last_wordp)
956 break;
957
958 wordp += word_step;
959 }
960 }
961
962 return sign;
963#undef FILL_DD
964#undef TAKE_LOWBITS
965}
966
967static size_t
968integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
969{
970 /* nlp_bits stands for number of leading padding bits */
971 size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
972 size_t num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG;
973 *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
974 return num_bdigits;
975}
976
977static size_t
978integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
979{
980 /* BITSPERDIG = SIZEOF_BDIGIT * CHAR_BIT */
981 /* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
982 /* num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG */
983
984 /* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
985 size_t num_bytes1 = wordsize * numwords;
986
987 /* q1 * CHAR_BIT + r1 = numwords */
988 size_t q1 = numwords / CHAR_BIT;
989 size_t r1 = numwords % CHAR_BIT;
990
991 /* num_bits = CHAR_BIT * num_bytes1 - nails * (q1 * CHAR_BIT + r1) = CHAR_BIT * num_bytes2 - nails * r1 */
992 size_t num_bytes2 = num_bytes1 - nails * q1;
993
994 /* q2 * CHAR_BIT + r2 = nails */
995 size_t q2 = nails / CHAR_BIT;
996 size_t r2 = nails % CHAR_BIT;
997
998 /* num_bits = CHAR_BIT * num_bytes2 - (q2 * CHAR_BIT + r2) * r1 = CHAR_BIT * num_bytes3 - r1 * r2 */
999 size_t num_bytes3 = num_bytes2 - q2 * r1;
1000
1001 /* q3 * BITSPERDIG + r3 = num_bytes3 */
1002 size_t q3 = num_bytes3 / BITSPERDIG;
1003 size_t r3 = num_bytes3 % BITSPERDIG;
1004
1005 /* num_bits = CHAR_BIT * (q3 * BITSPERDIG + r3) - r1 * r2 = BITSPERDIG * num_digits1 + CHAR_BIT * r3 - r1 * r2 */
1006 size_t num_digits1 = CHAR_BIT * q3;
1007
1008 /*
1009 * if CHAR_BIT * r3 >= r1 * r2
1010 * CHAR_BIT * r3 - r1 * r2 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2))
1011 * q4 * BITSPERDIG + r4 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2)
1012 * num_bits = BITSPERDIG * num_digits1 + CHAR_BIT * BITSPERDIG - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
1013 * else
1014 * q4 * BITSPERDIG + r4 = -(CHAR_BIT * r3 - r1 * r2)
1015 * num_bits = BITSPERDIG * num_digits1 - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
1016 * end
1017 */
1018
1019 if (CHAR_BIT * r3 >= r1 * r2) {
1020 size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
1021 size_t q4 = tmp1 / BITSPERDIG;
1022 int r4 = (int)(tmp1 % BITSPERDIG);
1023 size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
1024 *nlp_bits_ret = r4;
1025 return num_digits2;
1026 }
1027 else {
1028 size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
1029 size_t q4 = tmp1 / BITSPERDIG;
1030 int r4 = (int)(tmp1 % BITSPERDIG);
1031 size_t num_digits2 = num_digits1 - q4;
1032 *nlp_bits_ret = r4;
1033 return num_digits2;
1034 }
1035}
1036
1037static size_t
1038integer_unpack_num_bdigits(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
1039{
1040 size_t num_bdigits;
1041
1042 if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
1043 num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
1044#ifdef DEBUG_INTEGER_PACK
1045 {
1046 int nlp_bits1;
1047 size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
1048 assert(num_bdigits == num_bdigits1);
1049 assert(*nlp_bits_ret == nlp_bits1);
1050 }
1051#endif
1052 }
1053 else {
1054 num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
1055 }
1056 return num_bdigits;
1057}
1058
1059static inline void
1060integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
1061{
1062 (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
1063 *numbits_in_dd_p += numbits;
1064 while (BITSPERDIG <= *numbits_in_dd_p) {
1065 *(*dpp)++ = BIGLO(*ddp);
1066 *ddp = BIGDN(*ddp);
1067 *numbits_in_dd_p -= BITSPERDIG;
1068 }
1069}
1070
1071static int
1072integer_unpack_single_bdigit(BDIGIT u, size_t size, int flags, BDIGIT *dp)
1073{
1074 int sign;
1075 if (flags & INTEGER_PACK_2COMP) {
1076 sign = (flags & INTEGER_PACK_NEGATIVE) ?
1077 ((size == SIZEOF_BDIGIT && u == 0) ? -2 : -1) :
1078 ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
1079 if (sign < 0) {
1080 u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
1081 u = BIGLO(1 + ~u);
1082 }
1083 }
1084 else
1085 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1086 *dp = u;
1087 return sign;
1088}
1089
1090#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
1091#define reinterpret_cast(type, value) (type) \
1092 __builtin_assume_aligned((value), sizeof(*(type)NULL));
1093#else
1094#define reinterpret_cast(type, value) (type)value
1095#endif
1096
1097static int
1098bary_unpack_internal(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags, int nlp_bits)
1099{
1100 int sign;
1101 const unsigned char *buf = words;
1102 BDIGIT *dp;
1103 BDIGIT *de;
1104
1105 dp = bdigits;
1106 de = dp + num_bdigits;
1107
1109 if (nails == 0 && numwords == 1) {
1110 int need_swap = wordsize != 1 &&
1113 if (wordsize == 1) {
1114 return integer_unpack_single_bdigit(*(uint8_t *)buf, sizeof(uint8_t), flags, dp);
1115 }
1116#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
1117 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
1118 uint16_t u = *reinterpret_cast(const uint16_t *, buf);
1119 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
1120 }
1121#endif
1122#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
1123 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
1124 uint32_t u = *reinterpret_cast(const uint32_t *, buf);
1125 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
1126 }
1127#endif
1128#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
1129 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
1130 uint64_t u = *reinterpret_cast(const uint64_t *, buf);
1131 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
1132 }
1133#endif
1134#undef reinterpret_cast
1135 }
1136#if !defined(WORDS_BIGENDIAN)
1137 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
1140 size_t src_size = numwords * wordsize;
1141 size_t dst_size = num_bdigits * SIZEOF_BDIGIT;
1142 MEMCPY(dp, words, char, src_size);
1143 if (flags & INTEGER_PACK_2COMP) {
1144 if (flags & INTEGER_PACK_NEGATIVE) {
1145 int zero_p;
1146 memset((char*)dp + src_size, 0xff, dst_size - src_size);
1147 zero_p = bary_2comp(dp, num_bdigits);
1148 sign = zero_p ? -2 : -1;
1149 }
1150 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
1151 memset((char*)dp + src_size, 0xff, dst_size - src_size);
1152 bary_2comp(dp, num_bdigits);
1153 sign = -1;
1154 }
1155 else {
1156 MEMZERO((char*)dp + src_size, char, dst_size - src_size);
1157 sign = 1;
1158 }
1159 }
1160 else {
1161 MEMZERO((char*)dp + src_size, char, dst_size - src_size);
1162 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1163 }
1164 return sign;
1165 }
1166#endif
1167 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
1168 wordsize % SIZEOF_BDIGIT == 0) {
1169 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
1170 int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
1171 int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
1172 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
1173 MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
1174 if (mswordfirst_p) {
1175 bary_swap(dp, num_bdigits);
1176 }
1177 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
1178 size_t i;
1179 BDIGIT *p = dp;
1180 for (i = 0; i < numwords; i++) {
1181 bary_swap(p, bdigits_per_word);
1182 p += bdigits_per_word;
1183 }
1184 }
1185 if (msbytefirst_p != HOST_BIGENDIAN_P) {
1186 BDIGIT *p;
1187 for (p = dp; p < de; p++) {
1188 BDIGIT d = *p;
1189 *p = swap_bdigit(d);
1190 }
1191 }
1192 if (flags & INTEGER_PACK_2COMP) {
1193 if (flags & INTEGER_PACK_NEGATIVE) {
1194 int zero_p = bary_2comp(dp, num_bdigits);
1195 sign = zero_p ? -2 : -1;
1196 }
1197 else if (BDIGIT_MSB(de[-1])) {
1198 bary_2comp(dp, num_bdigits);
1199 sign = -1;
1200 }
1201 else {
1202 sign = 1;
1203 }
1204 }
1205 else {
1206 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1207 }
1208 return sign;
1209 }
1210 }
1211
1212 if (num_bdigits != 0) {
1213 int word_num_partialbits;
1214 size_t word_num_fullbytes;
1215
1216 ssize_t word_step;
1217 size_t byte_start;
1218 int byte_step;
1219
1220 size_t word_start, word_last;
1221 const unsigned char *wordp, *last_wordp;
1222 BDIGIT_DBL dd;
1223 int numbits_in_dd;
1224
1225 integer_pack_loop_setup(numwords, wordsize, nails, flags,
1226 &word_num_fullbytes, &word_num_partialbits,
1227 &word_start, &word_step, &word_last, &byte_start, &byte_step);
1228
1229 wordp = buf + word_start;
1230 last_wordp = buf + word_last;
1231
1232 dd = 0;
1233 numbits_in_dd = 0;
1234
1235#define PUSH_BITS(data, numbits) \
1236 integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
1237
1238 while (1) {
1239 size_t index_in_word = 0;
1240 const unsigned char *bytep = wordp + byte_start;
1241 while (index_in_word < word_num_fullbytes) {
1242 PUSH_BITS(*bytep, CHAR_BIT);
1243 bytep += byte_step;
1244 index_in_word++;
1245 }
1246 if (word_num_partialbits) {
1247 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
1248 bytep += byte_step;
1249 index_in_word++;
1250 }
1251
1252 if (wordp == last_wordp)
1253 break;
1254
1255 wordp += word_step;
1256 }
1257 if (dd)
1258 *dp++ = (BDIGIT)dd;
1259 assert(dp <= de);
1260 while (dp < de)
1261 *dp++ = 0;
1262#undef PUSH_BITS
1263 }
1264
1265 if (!(flags & INTEGER_PACK_2COMP)) {
1266 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1267 }
1268 else {
1269 if (nlp_bits) {
1270 if ((flags & INTEGER_PACK_NEGATIVE) ||
1271 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
1272 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
1273 sign = -1;
1274 }
1275 else {
1276 sign = 1;
1277 }
1278 }
1279 else {
1280 if (flags & INTEGER_PACK_NEGATIVE) {
1281 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
1282 }
1283 else {
1284 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
1285 sign = -1;
1286 else
1287 sign = 1;
1288 }
1289 }
1290 if (sign == -1 && num_bdigits != 0) {
1291 bary_2comp(bdigits, num_bdigits);
1292 }
1293 }
1294
1295 return sign;
1296}
1297
1298static void
1299bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
1300{
1301 size_t num_bdigits0;
1302 int nlp_bits;
1303 int sign;
1304
1305 validate_integer_pack_format(numwords, wordsize, nails, flags,
1315
1316 num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
1317
1318 assert(num_bdigits0 <= num_bdigits);
1319
1320 sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
1321
1322 if (num_bdigits0 < num_bdigits) {
1323 BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
1324 if (sign == -2) {
1325 bdigits[num_bdigits0] = 1;
1326 }
1327 }
1328}
1329
1330static int
1331bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int borrow)
1332{
1334 size_t i;
1335 size_t sn;
1336
1337 assert(xn <= zn);
1338 assert(yn <= zn);
1339
1340 sn = xn < yn ? xn : yn;
1341
1342 num = borrow ? -1 : 0;
1343 for (i = 0; i < sn; i++) {
1344 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
1345 zds[i] = BIGLO(num);
1346 num = BIGDN(num);
1347 }
1348 if (yn <= xn) {
1349 for (; i < xn; i++) {
1350 if (num == 0) goto num_is_zero;
1351 num += xds[i];
1352 zds[i] = BIGLO(num);
1353 num = BIGDN(num);
1354 }
1355 }
1356 else {
1357 for (; i < yn; i++) {
1358 num -= yds[i];
1359 zds[i] = BIGLO(num);
1360 num = BIGDN(num);
1361 }
1362 }
1363 if (num == 0) goto num_is_zero;
1364 for (; i < zn; i++) {
1365 zds[i] = BDIGMAX;
1366 }
1367 return 1;
1368
1369 num_is_zero:
1370 if (xds == zds && xn == zn)
1371 return 0;
1372 for (; i < xn; i++) {
1373 zds[i] = xds[i];
1374 }
1375 for (; i < zn; i++) {
1376 zds[i] = 0;
1377 }
1378 return 0;
1379}
1380
1381static int
1382bary_sub(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1383{
1384 return bary_subb(zds, zn, xds, xn, yds, yn, 0);
1385}
1386
1387static int
1388bary_sub_one(BDIGIT *zds, size_t zn)
1389{
1390 return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
1391}
1392
1393static int
1394bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int carry)
1395{
1396 BDIGIT_DBL num;
1397 size_t i;
1398
1399 assert(xn <= zn);
1400 assert(yn <= zn);
1401
1402 if (xn > yn) {
1403 const BDIGIT *tds;
1404 tds = xds; xds = yds; yds = tds;
1405 i = xn; xn = yn; yn = i;
1406 }
1407
1408 num = carry ? 1 : 0;
1409 for (i = 0; i < xn; i++) {
1410 num += (BDIGIT_DBL)xds[i] + yds[i];
1411 zds[i] = BIGLO(num);
1412 num = BIGDN(num);
1413 }
1414 for (; i < yn; i++) {
1415 if (num == 0) goto num_is_zero;
1416 num += yds[i];
1417 zds[i] = BIGLO(num);
1418 num = BIGDN(num);
1419 }
1420 for (; i < zn; i++) {
1421 if (num == 0) goto num_is_zero;
1422 zds[i] = BIGLO(num);
1423 num = BIGDN(num);
1424 }
1425 return num != 0;
1426
1427 num_is_zero:
1428 if (yds == zds && yn == zn)
1429 return 0;
1430 for (; i < yn; i++) {
1431 zds[i] = yds[i];
1432 }
1433 for (; i < zn; i++) {
1434 zds[i] = 0;
1435 }
1436 return 0;
1437}
1438
1439static int
1440bary_add(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1441{
1442 return bary_addc(zds, zn, xds, xn, yds, yn, 0);
1443}
1444
1445static int
1446bary_add_one(BDIGIT *ds, size_t n)
1447{
1448 size_t i;
1449 for (i = 0; i < n; i++) {
1450 BDIGIT_DBL n = ds[i];
1451 n += 1;
1452 ds[i] = BIGLO(n);
1453 if (ds[i] != 0)
1454 return 0;
1455 }
1456 return 1;
1457}
1458
1459static void
1460bary_mul_single(BDIGIT *zds, size_t zn, BDIGIT x, BDIGIT y)
1461{
1462 BDIGIT_DBL n;
1463
1464 assert(2 <= zn);
1465
1466 n = (BDIGIT_DBL)x * y;
1467 bdigitdbl2bary(zds, 2, n);
1468 BDIGITS_ZERO(zds + 2, zn - 2);
1469}
1470
1471static int
1472bary_muladd_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1473{
1474 BDIGIT_DBL n;
1475 BDIGIT_DBL dd;
1476 size_t j;
1477
1478 assert(zn > yn);
1479
1480 if (x == 0)
1481 return 0;
1482 dd = x;
1483 n = 0;
1484 for (j = 0; j < yn; j++) {
1485 BDIGIT_DBL ee = n + dd * yds[j];
1486 if (ee) {
1487 n = zds[j] + ee;
1488 zds[j] = BIGLO(n);
1489 n = BIGDN(n);
1490 }
1491 else {
1492 n = 0;
1493 }
1494
1495 }
1496 for (; j < zn; j++) {
1497 if (n == 0)
1498 break;
1499 n += zds[j];
1500 zds[j] = BIGLO(n);
1501 n = BIGDN(n);
1502 }
1503 return n != 0;
1504}
1505
1506static BDIGIT_DBL_SIGNED
1507bigdivrem_mulsub(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1508{
1509 size_t i;
1510 BDIGIT_DBL t2;
1512
1513 assert(zn == yn + 1);
1514
1515 num = 0;
1516 t2 = 0;
1517 i = 0;
1518
1519 do {
1521 t2 += (BDIGIT_DBL)yds[i] * x;
1522 ee = num - BIGLO(t2);
1523 num = (BDIGIT_DBL_SIGNED)zds[i] + ee;
1524 if (ee) zds[i] = BIGLO(num);
1525 num = BIGDN(num);
1526 t2 = BIGDN(t2);
1527 } while (++i < yn);
1528 num -= (BDIGIT_DBL_SIGNED)t2;
1529 num += (BDIGIT_DBL_SIGNED)zds[yn]; /* borrow from high digit; don't update */
1530 return num;
1531}
1532
1533static int
1534bary_mulsub_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1535{
1537
1538 assert(zn == yn + 1);
1539
1540 num = bigdivrem_mulsub(zds, zn, x, yds, yn);
1541 zds[yn] = BIGLO(num);
1542 if (BIGDN(num))
1543 return 1;
1544 return 0;
1545}
1546
1547static void
1548bary_mul_normal(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1549{
1550 size_t i;
1551
1552 assert(xn + yn <= zn);
1553
1554 BDIGITS_ZERO(zds, zn);
1555 for (i = 0; i < xn; i++) {
1556 bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
1557 }
1558}
1559
1560VALUE
1562{
1563 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1564 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1565 bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
1566 RB_GC_GUARD(x);
1567 RB_GC_GUARD(y);
1568 return z;
1569}
1570
1571/* efficient squaring (2 times faster than normal multiplication)
1572 * ref: Handbook of Applied Cryptography, Algorithm 14.16
1573 * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
1574 */
1575static void
1576bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
1577{
1578 size_t i, j;
1579 BDIGIT_DBL c, v, w;
1580 BDIGIT vl;
1581 int vh;
1582
1583 assert(xn * 2 <= zn);
1584
1585 BDIGITS_ZERO(zds, zn);
1586
1587 if (xn == 0)
1588 return;
1589
1590 for (i = 0; i < xn-1; i++) {
1591 v = (BDIGIT_DBL)xds[i];
1592 if (!v)
1593 continue;
1594 c = (BDIGIT_DBL)zds[i + i] + v * v;
1595 zds[i + i] = BIGLO(c);
1596 c = BIGDN(c);
1597 v *= 2;
1598 vl = BIGLO(v);
1599 vh = (int)BIGDN(v);
1600 for (j = i + 1; j < xn; j++) {
1601 w = (BDIGIT_DBL)xds[j];
1602 c += (BDIGIT_DBL)zds[i + j] + vl * w;
1603 zds[i + j] = BIGLO(c);
1604 c = BIGDN(c);
1605 if (vh)
1606 c += w;
1607 }
1608 if (c) {
1609 c += (BDIGIT_DBL)zds[i + xn];
1610 zds[i + xn] = BIGLO(c);
1611 c = BIGDN(c);
1612 if (c)
1613 zds[i + xn + 1] += (BDIGIT)c;
1614 }
1615 }
1616
1617 /* i == xn-1 */
1618 v = (BDIGIT_DBL)xds[i];
1619 if (!v)
1620 return;
1621 c = (BDIGIT_DBL)zds[i + i] + v * v;
1622 zds[i + i] = BIGLO(c);
1623 c = BIGDN(c);
1624 if (c) {
1625 zds[i + xn] += BIGLO(c);
1626 }
1627}
1628
1629VALUE
1631{
1632 size_t xn = BIGNUM_LEN(x), zn = 2 * xn;
1633 VALUE z = bignew(zn, 1);
1634 bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
1635 RB_GC_GUARD(x);
1636 return z;
1637}
1638
1639/* balancing multiplication by slicing larger argument */
1640static void
1641bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn, mulfunc_t *mulfunc)
1642{
1643 VALUE work = 0;
1644 size_t yn0 = yn;
1645 size_t r, n;
1646
1647 assert(xn + yn <= zn);
1648 assert(xn <= yn);
1650
1651 BDIGITS_ZERO(zds, xn);
1652
1653 n = 0;
1654 while (yn > 0) {
1655 BDIGIT *tds;
1656 size_t tn;
1657 r = xn > yn ? yn : xn;
1658 tn = xn + r;
1659 if (2 * (xn + r) <= zn - n) {
1660 tds = zds + n + xn + r;
1661 mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
1662 BDIGITS_ZERO(zds + n + xn, r);
1663 bary_add(zds + n, tn,
1664 zds + n, tn,
1665 tds, tn);
1666 }
1667 else {
1668 if (wn < xn) {
1669 wn = xn;
1670 wds = ALLOCV_N(BDIGIT, work, wn);
1671 }
1672 tds = zds + n;
1673 MEMCPY(wds, zds + n, BDIGIT, xn);
1674 mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
1675 bary_add(zds + n, tn,
1676 zds + n, tn,
1677 wds, xn);
1678 }
1679 yn -= r;
1680 n += r;
1681 }
1682 BDIGITS_ZERO(zds+xn+yn0, zn - (xn+yn0));
1683
1684 if (work)
1685 ALLOCV_END(work);
1686}
1687
1688VALUE
1690{
1691 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1692 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1693 bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
1694 RB_GC_GUARD(x);
1695 RB_GC_GUARD(y);
1696 return z;
1697}
1698
1699/* multiplication by karatsuba method */
1700static void
1701bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
1702{
1703 VALUE work = 0;
1704
1705 size_t n;
1706 int sub_p, borrow, carry1, carry2, carry3;
1707
1708 int odd_y = 0;
1709 int odd_xy = 0;
1710 int sq;
1711
1712 const BDIGIT *xds0, *xds1, *yds0, *yds1;
1713 BDIGIT *zds0, *zds1, *zds2, *zds3;
1714
1715 assert(xn + yn <= zn);
1716 assert(xn <= yn);
1717 assert(yn < 2 * xn);
1718
1719 sq = xds == yds && xn == yn;
1720
1721 if (yn & 1) {
1722 odd_y = 1;
1723 yn--;
1724 if (yn < xn) {
1725 odd_xy = 1;
1726 xn--;
1727 }
1728 }
1729
1730 n = yn / 2;
1731
1732 assert(n < xn);
1733
1734 if (wn < n) {
1735 /* This function itself needs only n BDIGITs for work area.
1736 * However this function calls bary_mul_karatsuba and
1737 * bary_mul_balance recursively.
1738 * 2n BDIGITs are enough to avoid allocations in
1739 * the recursively called functions.
1740 */
1741 wn = 2*n;
1742 wds = ALLOCV_N(BDIGIT, work, wn);
1743 }
1744
1745 /* Karatsuba algorithm:
1746 *
1747 * x = x0 + r*x1
1748 * y = y0 + r*y1
1749 * z = x*y
1750 * = (x0 + r*x1) * (y0 + r*y1)
1751 * = x0*y0 + r*(x1*y0 + x0*y1) + r*r*x1*y1
1752 * = x0*y0 + r*(x0*y0 + x1*y1 - (x1-x0)*(y1-y0)) + r*r*x1*y1
1753 * = x0*y0 + r*(x0*y0 + x1*y1 - (x0-x1)*(y0-y1)) + r*r*x1*y1
1754 */
1755
1756 xds0 = xds;
1757 xds1 = xds + n;
1758 yds0 = yds;
1759 yds1 = yds + n;
1760 zds0 = zds;
1761 zds1 = zds + n;
1762 zds2 = zds + 2*n;
1763 zds3 = zds + 3*n;
1764
1765 sub_p = 1;
1766
1767 /* zds0:? zds1:? zds2:? zds3:? wds:? */
1768
1769 if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
1770 bary_2comp(zds0, n);
1771 sub_p = !sub_p;
1772 }
1773
1774 /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:? */
1775
1776 if (sq) {
1777 sub_p = 1;
1778 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
1779 }
1780 else {
1781 if (bary_sub(wds, n, yds, n, yds+n, n)) {
1782 bary_2comp(wds, n);
1783 sub_p = !sub_p;
1784 }
1785
1786 /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:|y1-y0| */
1787
1788 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
1789 }
1790
1791 /* zds0:|x1-x0| zds1,zds2:|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
1792
1793 borrow = 0;
1794 if (sub_p) {
1795 borrow = !bary_2comp(zds1, 2*n);
1796 }
1797 /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
1798
1799 MEMCPY(wds, zds1, BDIGIT, n);
1800
1801 /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
1802
1803 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
1804
1805 /* zds0,zds1:x0*y0 zds2:hi(-?|x1-x0|*|y1-y0|) zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
1806
1807 carry1 = bary_add(wds, n, wds, n, zds0, n);
1808 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
1809
1810 /* zds0,zds1:x0*y0 zds2:hi(x0*y0-?|x1-x0|*|y1-y0|) zds3:? wds:lo(x0*y0-?|x1-x0|*|y1-y0|) */
1811
1812 carry2 = bary_add(zds1, n, zds1, n, wds, n);
1813
1814 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2:hi(x0*y0-?|x1-x0|*|y1-y0|) zds3:? wds:lo(x0*y0-?|x1-x0|*|y1-y0|) */
1815
1816 MEMCPY(wds, zds2, BDIGIT, n);
1817
1818 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2:_ zds3:? wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1819
1820 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
1821
1822 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2,zds3:x1*y1 wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1823
1824 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
1825
1826 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1 wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1827
1828 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
1829
1830 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1+hi(x1*y1) wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1831
1832 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
1833
1834 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1+hi(x1*y1)+hi(x0*y0-?|x1-x0|*|y1-y0|) wds:_ */
1835
1836 if (carry2)
1837 bary_add_one(zds2, zn-2*n);
1838
1839 if (carry1 + carry3 - borrow < 0)
1840 bary_sub_one(zds3, zn-3*n);
1841 else if (carry1 + carry3 - borrow > 0) {
1842 BDIGIT c = carry1 + carry3 - borrow;
1843 bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
1844 }
1845
1846 /*
1847 if (SIZEOF_BDIGIT * zn <= 16) {
1848 uint128_t z, x, y;
1849 ssize_t i;
1850 for (x = 0, i = xn-1; 0 <= i; i--) { x <<= SIZEOF_BDIGIT*CHAR_BIT; x |= xds[i]; }
1851 for (y = 0, i = yn-1; 0 <= i; i--) { y <<= SIZEOF_BDIGIT*CHAR_BIT; y |= yds[i]; }
1852 for (z = 0, i = zn-1; 0 <= i; i--) { z <<= SIZEOF_BDIGIT*CHAR_BIT; z |= zds[i]; }
1853 assert(z == x * y);
1854 }
1855 */
1856
1857 if (odd_xy) {
1858 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1859 bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
1860 }
1861 else if (odd_y) {
1862 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1863 }
1864
1865 if (work)
1866 ALLOCV_END(work);
1867}
1868
1869VALUE
1871{
1872 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1873 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1874 if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
1875 rb_raise(rb_eArgError, "unexpected bignum length for karatsuba");
1876 bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
1877 RB_GC_GUARD(x);
1878 RB_GC_GUARD(y);
1879 return z;
1880}
1881
1882static void
1883bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
1884{
1885 size_t n;
1886 size_t wnc;
1887 VALUE work = 0;
1888
1889 /* "p" stands for "positive". Actually it means "non-negative", though. */
1890 size_t x0n; const BDIGIT *x0ds;
1891 size_t x1n; const BDIGIT *x1ds;
1892 size_t x2n; const BDIGIT *x2ds;
1893 size_t y0n; const BDIGIT *y0ds;
1894 size_t y1n; const BDIGIT *y1ds;
1895 size_t y2n; const BDIGIT *y2ds;
1896
1897 size_t u1n; BDIGIT *u1ds; int u1p;
1898 size_t u2n; BDIGIT *u2ds; int u2p;
1899 size_t u3n; BDIGIT *u3ds; int u3p;
1900
1901 size_t v1n; BDIGIT *v1ds; int v1p;
1902 size_t v2n; BDIGIT *v2ds; int v2p;
1903 size_t v3n; BDIGIT *v3ds; int v3p;
1904
1905 size_t t0n; BDIGIT *t0ds; int t0p;
1906 size_t t1n; BDIGIT *t1ds; int t1p;
1907 size_t t2n; BDIGIT *t2ds; int t2p;
1908 size_t t3n; BDIGIT *t3ds; int t3p;
1909 size_t t4n; BDIGIT *t4ds; int t4p;
1910
1911 size_t z0n; BDIGIT *z0ds;
1912 size_t z1n; BDIGIT *z1ds; int z1p;
1913 size_t z2n; BDIGIT *z2ds; int z2p;
1914 size_t z3n; BDIGIT *z3ds; int z3p;
1915 size_t z4n; BDIGIT *z4ds;
1916
1917 size_t zzn; BDIGIT *zzds;
1918
1919 int sq = xds == yds && xn == yn;
1920
1921 assert(xn <= yn); /* assume y >= x */
1922 assert(xn + yn <= zn);
1923
1924 n = (yn + 2) / 3;
1925 assert(2*n < xn);
1926
1927 wnc = 0;
1928
1929 wnc += (u1n = n+1); /* BITSPERDIG*n+2 bits */
1930 wnc += (u2n = n+1); /* BITSPERDIG*n+1 bits */
1931 wnc += (u3n = n+1); /* BITSPERDIG*n+3 bits */
1932 wnc += (v1n = n+1); /* BITSPERDIG*n+2 bits */
1933 wnc += (v2n = n+1); /* BITSPERDIG*n+1 bits */
1934 wnc += (v3n = n+1); /* BITSPERDIG*n+3 bits */
1935
1936 wnc += (t0n = 2*n); /* BITSPERDIG*2*n bits */
1937 wnc += (t1n = 2*n+2); /* BITSPERDIG*2*n+4 bits but bary_mul needs u1n+v1n */
1938 wnc += (t2n = 2*n+2); /* BITSPERDIG*2*n+2 bits but bary_mul needs u2n+v2n */
1939 wnc += (t3n = 2*n+2); /* BITSPERDIG*2*n+6 bits but bary_mul needs u3n+v3n */
1940 wnc += (t4n = 2*n); /* BITSPERDIG*2*n bits */
1941
1942 wnc += (z1n = 2*n+1); /* BITSPERDIG*2*n+5 bits */
1943 wnc += (z2n = 2*n+1); /* BITSPERDIG*2*n+6 bits */
1944 wnc += (z3n = 2*n+1); /* BITSPERDIG*2*n+8 bits */
1945
1946 if (wn < wnc) {
1947 wn = wnc * 3 / 2; /* Allocate working memory for whole recursion at once. */
1948 wds = ALLOCV_N(BDIGIT, work, wn);
1949 }
1950
1951 u1ds = wds; wds += u1n;
1952 u2ds = wds; wds += u2n;
1953 u3ds = wds; wds += u3n;
1954
1955 v1ds = wds; wds += v1n;
1956 v2ds = wds; wds += v2n;
1957 v3ds = wds; wds += v3n;
1958
1959 t0ds = wds; wds += t0n;
1960 t1ds = wds; wds += t1n;
1961 t2ds = wds; wds += t2n;
1962 t3ds = wds; wds += t3n;
1963 t4ds = wds; wds += t4n;
1964
1965 z1ds = wds; wds += z1n;
1966 z2ds = wds; wds += z2n;
1967 z3ds = wds; wds += z3n;
1968
1969 wn -= wnc;
1970
1971 zzds = u1ds;
1972 zzn = 6*n+1;
1973
1974 x0n = n;
1975 x1n = n;
1976 x2n = xn - 2*n;
1977 x0ds = xds;
1978 x1ds = xds + n;
1979 x2ds = xds + 2*n;
1980
1981 if (sq) {
1982 y0n = x0n;
1983 y1n = x1n;
1984 y2n = x2n;
1985 y0ds = x0ds;
1986 y1ds = x1ds;
1987 y2ds = x2ds;
1988 }
1989 else {
1990 y0n = n;
1991 y1n = n;
1992 y2n = yn - 2*n;
1993 y0ds = yds;
1994 y1ds = yds + n;
1995 y2ds = yds + 2*n;
1996 }
1997
1998 /*
1999 * ref. http://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
2000 *
2001 * x(b) = x0 * b^0 + x1 * b^1 + x2 * b^2
2002 * y(b) = y0 * b^0 + y1 * b^1 + y2 * b^2
2003 *
2004 * z(b) = x(b) * y(b)
2005 * z(b) = z0 * b^0 + z1 * b^1 + z2 * b^2 + z3 * b^3 + z4 * b^4
2006 * where:
2007 * z0 = x0 * y0
2008 * z1 = x0 * y1 + x1 * y0
2009 * z2 = x0 * y2 + x1 * y1 + x2 * y0
2010 * z3 = x1 * y2 + x2 * y1
2011 * z4 = x2 * y2
2012 *
2013 * Toom3 method (a.k.a. Toom-Cook method):
2014 * (Step1) calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4),
2015 * where:
2016 * b0 = 0, b1 = 1, b2 = -1, b3 = -2, b4 = inf,
2017 * z(0) = x(0) * y(0) = x0 * y0
2018 * z(1) = x(1) * y(1) = (x0 + x1 + x2) * (y0 + y1 + y2)
2019 * z(-1) = x(-1) * y(-1) = (x0 - x1 + x2) * (y0 - y1 + y2)
2020 * z(-2) = x(-2) * y(-2) = (x0 - 2 * (x1 - 2 * x2)) * (y0 - 2 * (y1 - 2 * y2))
2021 * z(inf) = x(inf) * y(inf) = x2 * y2
2022 *
2023 * (Step2) interpolating z0, z1, z2, z3 and z4.
2024 *
2025 * (Step3) Substituting base value into b of the polynomial z(b),
2026 */
2027
2028 /*
2029 * [Step1] calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4)
2030 */
2031
2032 /* u1 <- x0 + x2 */
2033 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
2034 u1p = 1;
2035
2036 /* x(-1) : u2 <- u1 - x1 = x0 - x1 + x2 */
2037 if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
2038 bary_2comp(u2ds, u2n);
2039 u2p = 0;
2040 }
2041 else {
2042 u2p = 1;
2043 }
2044
2045 /* x(1) : u1 <- u1 + x1 = x0 + x1 + x2 */
2046 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
2047
2048 /* x(-2) : u3 <- 2 * (u2 + x2) - x0 = x0 - 2 * (x1 - 2 * x2) */
2049 u3p = 1;
2050 if (u2p) {
2051 bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
2052 }
2053 else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
2054 bary_2comp(u3ds, u3n);
2055 u3p = 0;
2056 }
2057 bary_small_lshift(u3ds, u3ds, u3n, 1);
2058 if (!u3p) {
2059 bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
2060 }
2061 else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
2062 bary_2comp(u3ds, u3n);
2063 u3p = 0;
2064 }
2065
2066 if (sq) {
2067 v1n = u1n; v1ds = u1ds; v1p = u1p;
2068 v2n = u2n; v2ds = u2ds; v2p = u2p;
2069 v3n = u3n; v3ds = u3ds; v3p = u3p;
2070 }
2071 else {
2072 /* v1 <- y0 + y2 */
2073 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
2074 v1p = 1;
2075
2076 /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
2077 v2p = 1;
2078 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
2079 bary_2comp(v2ds, v2n);
2080 v2p = 0;
2081 }
2082
2083 /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
2084 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
2085
2086 /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
2087 v3p = 1;
2088 if (v2p) {
2089 bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
2090 }
2091 else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
2092 bary_2comp(v3ds, v3n);
2093 v3p = 0;
2094 }
2095 bary_small_lshift(v3ds, v3ds, v3n, 1);
2096 if (!v3p) {
2097 bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
2098 }
2099 else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
2100 bary_2comp(v3ds, v3n);
2101 v3p = 0;
2102 }
2103 }
2104
2105 /* z(0) : t0 <- x0 * y0 */
2106 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
2107 t0p = 1;
2108
2109 /* z(1) : t1 <- u1 * v1 */
2110 bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
2111 t1p = u1p == v1p;
2112 assert(t1ds[t1n-1] == 0);
2113 t1n--;
2114
2115 /* z(-1) : t2 <- u2 * v2 */
2116 bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
2117 t2p = u2p == v2p;
2118 assert(t2ds[t2n-1] == 0);
2119 t2n--;
2120
2121 /* z(-2) : t3 <- u3 * v3 */
2122 bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
2123 t3p = u3p == v3p;
2124 assert(t3ds[t3n-1] == 0);
2125 t3n--;
2126
2127 /* z(inf) : t4 <- x2 * y2 */
2128 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
2129 t4p = 1;
2130
2131 /*
2132 * [Step2] interpolating z0, z1, z2, z3 and z4.
2133 */
2134
2135 /* z0 <- z(0) == t0 */
2136 z0n = t0n; z0ds = t0ds;
2137
2138 /* z4 <- z(inf) == t4 */
2139 z4n = t4n; z4ds = t4ds;
2140
2141 /* z3 <- (z(-2) - z(1)) / 3 == (t3 - t1) / 3 */
2142 if (t3p == t1p) {
2143 z3p = t3p;
2144 if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
2145 bary_2comp(z3ds, z3n);
2146 z3p = !z3p;
2147 }
2148 }
2149 else {
2150 z3p = t3p;
2151 bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
2152 }
2153 bigdivrem_single(z3ds, z3ds, z3n, 3);
2154
2155 /* z1 <- (z(1) - z(-1)) / 2 == (t1 - t2) / 2 */
2156 if (t1p == t2p) {
2157 z1p = t1p;
2158 if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
2159 bary_2comp(z1ds, z1n);
2160 z1p = !z1p;
2161 }
2162 }
2163 else {
2164 z1p = t1p;
2165 bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
2166 }
2167 bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
2168
2169 /* z2 <- z(-1) - z(0) == t2 - t0 */
2170 if (t2p == t0p) {
2171 z2p = t2p;
2172 if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
2173 bary_2comp(z2ds, z2n);
2174 z2p = !z2p;
2175 }
2176 }
2177 else {
2178 z2p = t2p;
2179 bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
2180 }
2181
2182 /* z3 <- (z2 - z3) / 2 + 2 * z(inf) == (z2 - z3) / 2 + 2 * t4 */
2183 if (z2p == z3p) {
2184 z3p = z2p;
2185 if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
2186 bary_2comp(z3ds, z3n);
2187 z3p = !z3p;
2188 }
2189 }
2190 else {
2191 z3p = z2p;
2192 bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
2193 }
2194 bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
2195 if (z3p == t4p) {
2196 bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
2197 }
2198 else {
2199 if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
2200 bary_2comp(z3ds, z3n);
2201 z3p = !z3p;
2202 }
2203 }
2204
2205 /* z2 <- z2 + z1 - z(inf) == z2 + z1 - t4 */
2206 if (z2p == z1p) {
2207 bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
2208 }
2209 else {
2210 if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
2211 bary_2comp(z2ds, z2n);
2212 z2p = !z2p;
2213 }
2214 }
2215
2216 if (z2p == t4p) {
2217 if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
2218 bary_2comp(z2ds, z2n);
2219 z2p = !z2p;
2220 }
2221 }
2222 else {
2223 bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
2224 }
2225
2226 /* z1 <- z1 - z3 */
2227 if (z1p == z3p) {
2228 if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
2229 bary_2comp(z1ds, z1n);
2230 z1p = !z1p;
2231 }
2232 }
2233 else {
2234 bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
2235 }
2236
2237 /*
2238 * [Step3] Substituting base value into b of the polynomial z(b),
2239 */
2240
2241 MEMCPY(zzds, z0ds, BDIGIT, z0n);
2242 BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
2243 MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
2244 BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
2245 if (z1p)
2246 bary_add(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2247 else
2248 bary_sub(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2249 if (z2p)
2250 bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2251 else
2252 bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2253 if (z3p)
2254 bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2255 else
2256 bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2257
2258 BARY_TRUNC(zzds, zzn);
2259 MEMCPY(zds, zzds, BDIGIT, zzn);
2260 BDIGITS_ZERO(zds + zzn, zn - zzn);
2261
2262 if (work)
2263 ALLOCV_END(work);
2264}
2265
2266VALUE
2268{
2269 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2270 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2271 if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
2272 rb_raise(rb_eArgError, "unexpected bignum length for toom3");
2273 bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
2274 RB_GC_GUARD(x);
2275 RB_GC_GUARD(y);
2276 return z;
2277}
2278
2279#ifdef USE_GMP
2280static void
2281bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2282{
2283 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2284 mpz_t x, y, z;
2285 size_t count;
2286
2287 assert(xn + yn <= zn);
2288
2289 mpz_init(x);
2290 mpz_init(y);
2291 mpz_init(z);
2292 mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
2293 if (xds == yds && xn == yn) {
2294 mpz_mul(z, x, x);
2295 }
2296 else {
2297 mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
2298 mpz_mul(z, x, y);
2299 }
2300 mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z);
2301 BDIGITS_ZERO(zds+count, zn-count);
2302 mpz_clear(x);
2303 mpz_clear(y);
2304 mpz_clear(z);
2305}
2306
2307VALUE
2309{
2310 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2311 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2312 bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
2313 RB_GC_GUARD(x);
2314 RB_GC_GUARD(y);
2315 return z;
2316}
2317#endif
2318
2319static void
2320bary_short_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2321{
2322 assert(xn + yn <= zn);
2323
2324 if (xn == 1 && yn == 1) {
2325 bary_mul_single(zds, zn, xds[0], yds[0]);
2326 }
2327 else {
2328 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2330 }
2331}
2332
2333/* determine whether a bignum is sparse or not by random sampling */
2334static inline int
2335bary_sparse_p(const BDIGIT *ds, size_t n)
2336{
2337 long c = 0;
2338
2339 if ( ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
2340 if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
2341 if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
2342
2343 return (c <= 1) ? 1 : 0;
2344}
2345
2346static int
2347bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp, const BDIGIT **ydsp, size_t *ynp)
2348{
2349 size_t nlsz; /* number of least significant zero BDIGITs */
2350
2351 BDIGIT *zds = *zdsp;
2352 size_t zn = *znp;
2353 const BDIGIT *xds = *xdsp;
2354 size_t xn = *xnp;
2355 const BDIGIT *yds = *ydsp;
2356 size_t yn = *ynp;
2357
2358 assert(xn + yn <= zn);
2359
2360 nlsz = 0;
2361
2362 while (0 < xn) {
2363 if (xds[xn-1] == 0) {
2364 xn--;
2365 }
2366 else {
2367 do {
2368 if (xds[0] != 0)
2369 break;
2370 xds++;
2371 xn--;
2372 nlsz++;
2373 } while (0 < xn);
2374 break;
2375 }
2376 }
2377
2378 while (0 < yn) {
2379 if (yds[yn-1] == 0) {
2380 yn--;
2381 }
2382 else {
2383 do {
2384 if (yds[0] != 0)
2385 break;
2386 yds++;
2387 yn--;
2388 nlsz++;
2389 } while (0 < yn);
2390 break;
2391 }
2392 }
2393
2394 if (nlsz) {
2395 BDIGITS_ZERO(zds, nlsz);
2396 zds += nlsz;
2397 zn -= nlsz;
2398 }
2399
2400 /* make sure that y is longer than x */
2401 if (xn > yn) {
2402 const BDIGIT *tds;
2403 size_t tn;
2404 tds = xds; xds = yds; yds = tds;
2405 tn = xn; xn = yn; yn = tn;
2406 }
2407 assert(xn <= yn);
2408
2409 if (xn <= 1) {
2410 if (xn == 0) {
2411 BDIGITS_ZERO(zds, zn);
2412 return 1;
2413 }
2414
2415 if (xds[0] == 1) {
2416 MEMCPY(zds, yds, BDIGIT, yn);
2417 BDIGITS_ZERO(zds+yn, zn-yn);
2418 return 1;
2419 }
2420 if (POW2_P(xds[0])) {
2421 zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
2422 BDIGITS_ZERO(zds+yn+1, zn-yn-1);
2423 return 1;
2424 }
2425 if (yn == 1 && yds[0] == 1) {
2426 zds[0] = xds[0];
2427 BDIGITS_ZERO(zds+1, zn-1);
2428 return 1;
2429 }
2430 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2431 return 1;
2432 }
2433
2434 *zdsp = zds;
2435 *znp = zn;
2436 *xdsp = xds;
2437 *xnp = xn;
2438 *ydsp = yds;
2439 *ynp = yn;
2440
2441 return 0;
2442}
2443
2444static void
2445bary_mul_karatsuba_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
2446{
2447 /* normal multiplication when x is small */
2448 if (xn < KARATSUBA_MUL_DIGITS) {
2449 normal:
2450 if (xds == yds && xn == yn)
2451 bary_sq_fast(zds, zn, xds, xn);
2452 else
2453 bary_short_mul(zds, zn, xds, xn, yds, yn);
2454 return;
2455 }
2456
2457 /* normal multiplication when x or y is a sparse bignum */
2458 if (bary_sparse_p(xds, xn)) goto normal;
2459 if (bary_sparse_p(yds, yn)) {
2460 bary_short_mul(zds, zn, yds, yn, xds, xn);
2461 return;
2462 }
2463
2464 /* balance multiplication by slicing y when x is much smaller than y */
2465 if (!KARATSUBA_BALANCED(xn, yn)) {
2466 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
2467 return;
2468 }
2469
2470 /* multiplication by karatsuba method */
2471 bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
2472}
2473
2474static void
2475bary_mul_karatsuba_start(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
2476{
2477 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2478 return;
2479
2480 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2481}
2482
2483static void
2484bary_mul_toom3_branch(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
2485{
2486 if (xn < TOOM3_MUL_DIGITS) {
2487 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2488 return;
2489 }
2490
2491 if (!TOOM3_BALANCED(xn, yn)) {
2492 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
2493 return;
2494 }
2495
2496 bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
2497}
2498
2499static void
2500bary_mul_toom3_start(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
2501{
2502 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2503 return;
2504
2505 bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2506}
2507
2508static void
2509bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2510{
2511 if (xn <= yn) {
2512 if (xn < NAIVE_MUL_DIGITS) {
2513 if (xds == yds && xn == yn)
2514 bary_sq_fast(zds, zn, xds, xn);
2515 else
2516 bary_short_mul(zds, zn, xds, xn, yds, yn);
2517 return;
2518 }
2519 }
2520 else {
2521 if (yn < NAIVE_MUL_DIGITS) {
2522 bary_short_mul(zds, zn, yds, yn, xds, xn);
2523 return;
2524 }
2525 }
2526
2527#ifdef USE_GMP
2528 bary_mul_gmp(zds, zn, xds, xn, yds, yn);
2529#else
2530 bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
2531#endif
2532}
2533
2535 size_t yn, zn;
2537 volatile VALUE stop;
2538};
2539
2540static void *
2541bigdivrem1(void *ptr)
2542{
2543 struct big_div_struct *bds = (struct big_div_struct*)ptr;
2544 size_t yn = bds->yn;
2545 size_t zn = bds->zn;
2546 BDIGIT *yds = bds->yds, *zds = bds->zds;
2548 BDIGIT q;
2549
2550 do {
2551 if (bds->stop) {
2552 bds->zn = zn;
2553 return 0;
2554 }
2555 if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
2556 else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
2557 if (q) {
2558 num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
2559 q,
2560 yds, yn);
2561 while (num) { /* "add back" required */
2562 q--;
2563 num = bary_add(zds+zn-(yn+1), yn,
2564 zds+zn-(yn+1), yn,
2565 yds, yn);
2566 num--;
2567 }
2568 }
2569 zn--;
2570 zds[zn] = q;
2571 } while (zn > yn);
2572 return 0;
2573}
2574
2575/* async-signal-safe */
2576static void
2577rb_big_stop(void *ptr)
2578{
2579 struct big_div_struct *bds = ptr;
2580 bds->stop = Qtrue;
2581}
2582
2583static BDIGIT
2584bigdivrem_single1(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
2585{
2586 assert(0 < xn);
2587 assert(x_higher_bdigit < y);
2588 if (POW2_P(y)) {
2589 BDIGIT r;
2590 r = xds[0] & (y-1);
2591 bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
2592 return r;
2593 }
2594 else {
2595 size_t i;
2596 BDIGIT_DBL t2;
2597 t2 = x_higher_bdigit;
2598 for (i = 0; i < xn; i++) {
2599 t2 = BIGUP(t2) + xds[xn - i - 1];
2600 qds[xn - i - 1] = (BDIGIT)(t2 / y);
2601 t2 %= y;
2602 }
2603 return (BDIGIT)t2;
2604 }
2605}
2606
2607static BDIGIT
2608bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y)
2609{
2610 return bigdivrem_single1(qds, xds, xn, 0, y);
2611}
2612
2613static void
2614bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
2615{
2616 struct big_div_struct bds;
2617 size_t ynzero;
2618
2619 assert(yn < zn);
2620 assert(BDIGIT_MSB(yds[yn-1]));
2621 assert(zds[zn-1] < yds[yn-1]);
2622
2623 for (ynzero = 0; !yds[ynzero]; ynzero++);
2624
2625 if (ynzero+1 == yn) {
2626 BDIGIT r;
2627 r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
2628 zds[ynzero] = r;
2629 return;
2630 }
2631
2632 bds.yn = yn - ynzero;
2633 bds.zds = zds + ynzero;
2634 bds.yds = yds + ynzero;
2635 bds.stop = Qfalse;
2636 bds.zn = zn - ynzero;
2637 if (bds.zn > 10000 || bds.yn > 10000) {
2638 retry:
2639 bds.stop = Qfalse;
2640 rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE);
2641
2642 if (bds.stop == Qtrue) {
2643 /* execute trap handler, but exception was not raised. */
2644 goto retry;
2645 }
2646 }
2647 else {
2648 bigdivrem1(&bds);
2649 }
2650}
2651
2652static void
2653bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2654{
2655 int shift;
2656 BDIGIT *zds, *yyds;
2657 size_t zn;
2658 VALUE tmpyz = 0;
2659
2660 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2661 assert(qds ? (xn - yn + 1) <= qn : 1);
2662 assert(rds ? yn <= rn : 1);
2663
2665
2666 shift = nlz(yds[yn-1]);
2667 if (shift) {
2668 int alloc_y = !rds;
2669 int alloc_z = !qds || qn < zn;
2670 if (alloc_y && alloc_z) {
2671 yyds = ALLOCV_N(BDIGIT, tmpyz, yn+zn);
2672 zds = yyds + yn;
2673 }
2674 else {
2675 yyds = alloc_y ? ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
2676 zds = alloc_z ? ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
2677 }
2678 zds[xn] = bary_small_lshift(zds, xds, xn, shift);
2679 bary_small_lshift(yyds, yds, yn, shift);
2680 }
2681 else {
2682 if (qds && zn <= qn)
2683 zds = qds;
2684 else
2685 zds = ALLOCV_N(BDIGIT, tmpyz, zn);
2686 MEMCPY(zds, xds, BDIGIT, xn);
2687 zds[xn] = 0;
2688 /* bigdivrem_restoring will not modify y.
2689 * So use yds directly. */
2690 yyds = (BDIGIT *)yds;
2691 }
2692
2693 bigdivrem_restoring(zds, zn, yyds, yn);
2694
2695 if (rds) {
2696 if (shift)
2697 bary_small_rshift(rds, zds, yn, shift, 0);
2698 else
2699 MEMCPY(rds, zds, BDIGIT, yn);
2700 BDIGITS_ZERO(rds+yn, rn-yn);
2701 }
2702
2703 if (qds) {
2704 size_t j = zn - yn;
2705 MEMMOVE(qds, zds+yn, BDIGIT, j);
2706 BDIGITS_ZERO(qds+j, qn-j);
2707 }
2708
2709 if (tmpyz)
2710 ALLOCV_END(tmpyz);
2711}
2712
2713VALUE
2715{
2716 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2717 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2718 VALUE q, r;
2719
2720 BARY_TRUNC(yds, yn);
2721 if (yn == 0)
2723 BARY_TRUNC(xds, xn);
2724
2725 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2726 return rb_assoc_new(LONG2FIX(0), x);
2727
2728 qn = xn + BIGDIVREM_EXTRA_WORDS;
2729 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2730 qds = BDIGITS(q);
2731
2732 rn = yn;
2733 r = bignew(rn, BIGNUM_SIGN(x));
2734 rds = BDIGITS(r);
2735
2736 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2737
2738 bigtrunc(q);
2739 bigtrunc(r);
2740
2741 RB_GC_GUARD(x);
2742 RB_GC_GUARD(y);
2743
2744 return rb_assoc_new(q, r);
2745}
2746
2747#ifdef USE_GMP
2748static void
2749bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2750{
2751 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2752 mpz_t x, y, q, r;
2753 size_t count;
2754
2755 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2756 assert(qds ? (xn - yn + 1) <= qn : 1);
2757 assert(rds ? yn <= rn : 1);
2758 assert(qds || rds);
2759
2760 mpz_init(x);
2761 mpz_init(y);
2762 if (qds) mpz_init(q);
2763 if (rds) mpz_init(r);
2764
2765 mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
2766 mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
2767
2768 if (!rds) {
2769 mpz_fdiv_q(q, x, y);
2770 }
2771 else if (!qds) {
2772 mpz_fdiv_r(r, x, y);
2773 }
2774 else {
2775 mpz_fdiv_qr(q, r, x, y);
2776 }
2777
2778 mpz_clear(x);
2779 mpz_clear(y);
2780
2781 if (qds) {
2782 mpz_export(qds, &count, -1, sizeof(BDIGIT), 0, nails, q);
2783 BDIGITS_ZERO(qds+count, qn-count);
2784 mpz_clear(q);
2785 }
2786
2787 if (rds) {
2788 mpz_export(rds, &count, -1, sizeof(BDIGIT), 0, nails, r);
2789 BDIGITS_ZERO(rds+count, rn-count);
2790 mpz_clear(r);
2791 }
2792}
2793
2794VALUE
2796{
2797 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2798 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2799 VALUE q, r;
2800
2801 BARY_TRUNC(yds, yn);
2802 if (yn == 0)
2804 BARY_TRUNC(xds, xn);
2805
2806 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2807 return rb_assoc_new(LONG2FIX(0), x);
2808
2809 qn = xn - yn + 1;
2810 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2811 qds = BDIGITS(q);
2812
2813 rn = yn;
2814 r = bignew(rn, BIGNUM_SIGN(x));
2815 rds = BDIGITS(r);
2816
2817 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2818
2819 bigtrunc(q);
2820 bigtrunc(r);
2821
2822 RB_GC_GUARD(x);
2823 RB_GC_GUARD(y);
2824
2825 return rb_assoc_new(q, r);
2826}
2827#endif
2828
2829static void
2830bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2831{
2832#ifdef USE_GMP
2833 if (GMP_DIV_DIGITS < xn) {
2834 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2835 return;
2836 }
2837#endif
2838 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2839}
2840
2841static void
2842bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2843{
2844 assert(xn <= qn);
2845 assert(yn <= rn);
2846
2847 BARY_TRUNC(yds, yn);
2848 if (yn == 0)
2850
2851 BARY_TRUNC(xds, xn);
2852 if (xn == 0) {
2853 BDIGITS_ZERO(qds, qn);
2854 BDIGITS_ZERO(rds, rn);
2855 return;
2856 }
2857
2858 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
2859 MEMCPY(rds, xds, BDIGIT, xn);
2860 BDIGITS_ZERO(rds+xn, rn-xn);
2861 BDIGITS_ZERO(qds, qn);
2862 }
2863 else if (yn == 1) {
2864 MEMCPY(qds, xds, BDIGIT, xn);
2865 BDIGITS_ZERO(qds+xn, qn-xn);
2866 rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
2867 BDIGITS_ZERO(rds+1, rn-1);
2868 }
2869 else if (xn == 2 && yn == 2) {
2870 BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
2871 BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
2872 BDIGIT_DBL q = x / y;
2873 BDIGIT_DBL r = x % y;
2874 qds[0] = BIGLO(q);
2875 qds[1] = BIGLO(BIGDN(q));
2876 BDIGITS_ZERO(qds+2, qn-2);
2877 rds[0] = BIGLO(r);
2878 rds[1] = BIGLO(BIGDN(r));
2879 BDIGITS_ZERO(rds+2, rn-2);
2880 }
2881 else {
2882 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
2883 }
2884}
2885
2886
2887#define BIGNUM_DEBUG 0
2888#if BIGNUM_DEBUG
2889#define ON_DEBUG(x) do { x; } while (0)
2890static void
2891dump_bignum(VALUE x)
2892{
2893 long i;
2894 printf("%c0x0", BIGNUM_SIGN(x) ? '+' : '-');
2895 for (i = BIGNUM_LEN(x); i--; ) {
2896 printf("_%0*"PRIxBDIGIT, SIZEOF_BDIGIT*2, BDIGITS(x)[i]);
2897 }
2898 printf(", len=%"PRIuSIZE, BIGNUM_LEN(x));
2899 puts("");
2900}
2901
2902static VALUE
2903rb_big_dump(VALUE x)
2904{
2905 dump_bignum(x);
2906 return x;
2907}
2908#else
2909#define ON_DEBUG(x)
2910#endif
2911
2912static int
2913bigzero_p(VALUE x)
2914{
2915 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2916}
2917
2918int
2920{
2921 return BIGZEROP(x);
2922}
2923
2924int
2926{
2927 if (NIL_P(val)) {
2928 rb_cmperr(a, b);
2929 }
2930 if (FIXNUM_P(val)) {
2931 long l = FIX2LONG(val);
2932 if (l > 0) return 1;
2933 if (l < 0) return -1;
2934 return 0;
2935 }
2936 if (RB_BIGNUM_TYPE_P(val)) {
2937 if (BIGZEROP(val)) return 0;
2938 if (BIGNUM_SIGN(val)) return 1;
2939 return -1;
2940 }
2941 if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
2942 if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
2943 return 0;
2944}
2945
2946#define BIGNUM_SET_LEN(b,l) \
2947 ((RBASIC(b)->flags & BIGNUM_EMBED_FLAG) ? \
2948 (void)(RBASIC(b)->flags = \
2949 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2950 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2951 (void)(RBIGNUM(b)->as.heap.len = (l)))
2952
2953static void
2954rb_big_realloc(VALUE big, size_t len)
2955{
2956 BDIGIT *ds;
2957 if (RBASIC(big)->flags & BIGNUM_EMBED_FLAG) {
2958 if (BIGNUM_EMBED_LEN_MAX < len) {
2959 ds = ALLOC_N(BDIGIT, len);
2960 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
2961 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
2962 RBIGNUM(big)->as.heap.digits = ds;
2963 RBASIC(big)->flags &= ~BIGNUM_EMBED_FLAG;
2964 }
2965 }
2966 else {
2967 if (len <= BIGNUM_EMBED_LEN_MAX) {
2968 ds = RBIGNUM(big)->as.heap.digits;
2969 RBASIC(big)->flags |= BIGNUM_EMBED_FLAG;
2970 BIGNUM_SET_LEN(big, len);
2971 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
2972 if (ds) {
2973 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
2974 xfree(ds);
2975 }
2976 }
2977 else {
2978 if (BIGNUM_LEN(big) == 0) {
2979 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
2980 }
2981 else {
2982 REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
2983 }
2984 }
2985 }
2986}
2987
2988void
2990{
2991 rb_big_realloc(big, len);
2992 BIGNUM_SET_LEN(big, len);
2993}
2994
2995static VALUE
2996bignew_1(VALUE klass, size_t len, int sign)
2997{
2999 BIGNUM_SET_SIGN(big, sign);
3000 if (len <= BIGNUM_EMBED_LEN_MAX) {
3001 RBASIC(big)->flags |= BIGNUM_EMBED_FLAG;
3002 BIGNUM_SET_LEN(big, len);
3003 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
3004 }
3005 else {
3006 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
3007 RBIGNUM(big)->as.heap.len = len;
3008 }
3009 OBJ_FREEZE(big);
3010 return (VALUE)big;
3011}
3012
3013VALUE
3014rb_big_new(size_t len, int sign)
3015{
3016 return bignew(len, sign != 0);
3017}
3018
3019VALUE
3021{
3022 size_t len = BIGNUM_LEN(x);
3023 VALUE z = bignew_1(CLASS_OF(x), len, BIGNUM_SIGN(x));
3024
3025 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
3026 return z;
3027}
3028
3029static void
3030big_extend_carry(VALUE x)
3031{
3032 rb_big_resize(x, BIGNUM_LEN(x)+1);
3033 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3034}
3035
3036/* modify a bignum by 2's complement */
3037static void
3038get2comp(VALUE x)
3039{
3040 long i = BIGNUM_LEN(x);
3041 BDIGIT *ds = BDIGITS(x);
3042
3043 if (bary_2comp(ds, i)) {
3044 big_extend_carry(x);
3045 }
3046}
3047
3048void
3049rb_big_2comp(VALUE x) /* get 2's complement */
3050{
3051 get2comp(x);
3052}
3053
3054static BDIGIT
3055abs2twocomp(VALUE *xp, long *n_ret)
3056{
3057 VALUE x = *xp;
3058 long n = BIGNUM_LEN(x);
3059 BDIGIT *ds = BDIGITS(x);
3060 BDIGIT hibits = 0;
3061
3062 BARY_TRUNC(ds, n);
3063
3064 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3065 VALUE z = bignew_1(CLASS_OF(x), n, 0);
3066 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3067 bary_2comp(BDIGITS(z), n);
3068 hibits = BDIGMAX;
3069 *xp = z;
3070 }
3071 *n_ret = n;
3072 return hibits;
3073}
3074
3075static void
3076twocomp2abs_bang(VALUE x, int hibits)
3077{
3078 BIGNUM_SET_SIGN(x, !hibits);
3079 if (hibits) {
3080 get2comp(x);
3081 }
3082}
3083
3084static inline VALUE
3085bigtrunc(VALUE x)
3086{
3087 size_t len = BIGNUM_LEN(x);
3088 BDIGIT *ds = BDIGITS(x);
3089
3090 if (len == 0) return x;
3091 while (--len && !ds[len]);
3092 if (BIGNUM_LEN(x) > len+1) {
3093 rb_big_resize(x, len+1);
3094 }
3095 return x;
3096}
3097
3098static inline VALUE
3099bigfixize(VALUE x)
3100{
3101 size_t n = BIGNUM_LEN(x);
3102 BDIGIT *ds = BDIGITS(x);
3103#if SIZEOF_BDIGIT < SIZEOF_LONG
3104 unsigned long u;
3105#else
3106 BDIGIT u;
3107#endif
3108
3109 BARY_TRUNC(ds, n);
3110
3111 if (n == 0) return INT2FIX(0);
3112
3113#if SIZEOF_BDIGIT < SIZEOF_LONG
3114 if (sizeof(long)/SIZEOF_BDIGIT < n)
3115 goto return_big;
3116 else {
3117 int i = (int)n;
3118 u = 0;
3119 while (i--) {
3120 u = (unsigned long)(BIGUP(u) + ds[i]);
3121 }
3122 }
3123#else /* SIZEOF_BDIGIT >= SIZEOF_LONG */
3124 if (1 < n)
3125 goto return_big;
3126 else
3127 u = ds[0];
3128#endif
3129
3130 if (BIGNUM_POSITIVE_P(x)) {
3131 if (POSFIXABLE(u)) return LONG2FIX((long)u);
3132 }
3133 else {
3134 if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u);
3135 }
3136
3137 return_big:
3138 rb_big_resize(x, n);
3139 return x;
3140}
3141
3142static VALUE
3143bignorm(VALUE x)
3144{
3145 if (RB_BIGNUM_TYPE_P(x)) {
3146 x = bigfixize(x);
3147 }
3148 return x;
3149}
3150
3151VALUE
3153{
3154 return bignorm(x);
3155}
3156
3157VALUE
3159{
3160 long i;
3162 BDIGIT *digits = BDIGITS(big);
3163
3164#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3165 digits[0] = n;
3166#else
3167 for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
3168 digits[i] = BIGLO(n);
3169 n = BIGDN(n);
3170 }
3171#endif
3172
3174 while (--i && !digits[i]) ;
3175 BIGNUM_SET_LEN(big, i+1);
3176 return big;
3177}
3178
3179VALUE
3181{
3182 long neg = 0;
3183 VALUE u;
3184 VALUE big;
3185
3186 if (n < 0) {
3187 u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
3188 neg = 1;
3189 }
3190 else {
3191 u = n;
3192 }
3193 big = rb_uint2big(u);
3194 if (neg) {
3196 }
3197 return big;
3198}
3199
3200VALUE
3202{
3203 if (POSFIXABLE(n)) return LONG2FIX(n);
3204 return rb_uint2big(n);
3205}
3206
3207VALUE
3209{
3210 if (FIXABLE(n)) return LONG2FIX(n);
3211 return rb_int2big(n);
3212}
3213
3214void
3215rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
3216{
3217 rb_integer_pack(val, buf, num_longs, sizeof(long), 0,
3220}
3221
3222VALUE
3223rb_big_unpack(unsigned long *buf, long num_longs)
3224{
3225 return rb_integer_unpack(buf, num_longs, sizeof(long), 0,
3228}
3229
3230/*
3231 * Calculate the number of bytes to be required to represent
3232 * the absolute value of the integer given as _val_.
3233 *
3234 * [val] an integer.
3235 * [nlz_bits_ret] number of leading zero bits in the most significant byte is returned if not NULL.
3236 *
3237 * This function returns ((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)
3238 * where val_numbits is the number of bits of abs(val).
3239 * This function should not overflow.
3240 *
3241 * If nlz_bits_ret is not NULL,
3242 * (return_value * CHAR_BIT - val_numbits) is stored in *nlz_bits_ret.
3243 * In this case, 0 <= *nlz_bits_ret < CHAR_BIT.
3244 *
3245 */
3246size_t
3247rb_absint_size(VALUE val, int *nlz_bits_ret)
3248{
3249 BDIGIT *dp;
3250 BDIGIT *de;
3251 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3252
3253 int num_leading_zeros;
3254
3255 val = rb_to_int(val);
3256
3257 if (FIXNUM_P(val)) {
3258 long v = FIX2LONG(val);
3259 if (v < 0) {
3260 v = -v;
3261 }
3262#if SIZEOF_BDIGIT >= SIZEOF_LONG
3263 fixbuf[0] = v;
3264#else
3265 {
3266 int i;
3267 for (i = 0; i < numberof(fixbuf); i++) {
3268 fixbuf[i] = BIGLO(v);
3269 v = BIGDN(v);
3270 }
3271 }
3272#endif
3273 dp = fixbuf;
3274 de = fixbuf + numberof(fixbuf);
3275 }
3276 else {
3277 dp = BDIGITS(val);
3278 de = dp + BIGNUM_LEN(val);
3279 }
3280 while (dp < de && de[-1] == 0)
3281 de--;
3282 if (dp == de) {
3283 if (nlz_bits_ret)
3284 *nlz_bits_ret = 0;
3285 return 0;
3286 }
3287 num_leading_zeros = nlz(de[-1]);
3288 if (nlz_bits_ret)
3289 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3290 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3291}
3292
3293static size_t
3294absint_numwords_small(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3295{
3296 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3297 size_t div = val_numbits / word_numbits;
3298 size_t mod = val_numbits % word_numbits;
3299 size_t numwords;
3300 size_t nlz_bits;
3301 numwords = mod == 0 ? div : div + 1;
3302 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3303 *nlz_bits_ret = nlz_bits;
3304 return numwords;
3305}
3306
3307static size_t
3308absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3309{
3310 static const BDIGIT char_bit[1] = { CHAR_BIT };
3311 BDIGIT numbytes_bary[bdigit_roomof(sizeof(numbytes))];
3312 BDIGIT val_numbits_bary[bdigit_roomof(sizeof(numbytes) + 1)];
3313 BDIGIT nlz_bits_in_msbyte_bary[1];
3314 BDIGIT word_numbits_bary[bdigit_roomof(sizeof(word_numbits))];
3315 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3316 BDIGIT mod_bary[numberof(word_numbits_bary)];
3317 BDIGIT one[1] = { 1 };
3318 size_t nlz_bits;
3319 size_t mod;
3320 int sign;
3321 size_t numwords;
3322
3323 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3324
3325 /*
3326 * val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
3327 * div, mod = val_numbits.divmod(word_numbits)
3328 * numwords = mod == 0 ? div : div + 1
3329 * nlz_bits = mod == 0 ? 0 : word_numbits - mod
3330 */
3331
3332 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
3334 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3335 if (nlz_bits_in_msbyte)
3336 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3337 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1, sizeof(word_numbits), 0,
3339 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3340 if (BARY_ZERO_P(mod_bary)) {
3341 nlz_bits = 0;
3342 }
3343 else {
3344 BARY_ADD(div_bary, div_bary, one);
3345 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1, sizeof(mod), 0,
3347 nlz_bits = word_numbits - mod;
3348 }
3349 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1, sizeof(numwords), 0,
3351
3352 if (sign == 2) {
3353#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3354 *nlz_bits_ret = 0;
3355#endif
3356 return (size_t)-1;
3357 }
3358 *nlz_bits_ret = nlz_bits;
3359 return numwords;
3360}
3361
3362/*
3363 * Calculate the number of words to be required to represent
3364 * the absolute value of the integer given as _val_.
3365 *
3366 * [val] an integer.
3367 * [word_numbits] number of bits in a word.
3368 * [nlz_bits_ret] number of leading zero bits in the most significant word is returned if not NULL.
3369 *
3370 * This function returns ((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)
3371 * where val_numbits is the number of bits of abs(val).
3372 *
3373 * This function can overflow.
3374 * When overflow occur, (size_t)-1 is returned.
3375 *
3376 * If nlz_bits_ret is not NULL and overflow is not occur,
3377 * (return_value * word_numbits - val_numbits) is stored in *nlz_bits_ret.
3378 * In this case, 0 <= *nlz_bits_ret < word_numbits.
3379 *
3380 */
3381size_t
3382rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
3383{
3384 size_t numbytes;
3385 int nlz_bits_in_msbyte;
3386 size_t numwords;
3387 size_t nlz_bits;
3388
3389 if (word_numbits == 0)
3390 return (size_t)-1;
3391
3392 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3393
3394 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3395 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3396#ifdef DEBUG_INTEGER_PACK
3397 {
3398 size_t numwords0, nlz_bits0;
3399 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3400 assert(numwords0 == numwords);
3401 assert(nlz_bits0 == nlz_bits);
3402 }
3403#endif
3404 }
3405 else {
3406 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3407 }
3408 if (numwords == (size_t)-1)
3409 return numwords;
3410
3411 if (nlz_bits_ret)
3412 *nlz_bits_ret = nlz_bits;
3413
3414 return numwords;
3415}
3416
3417/* Test abs(val) consists only a bit or not.
3418 *
3419 * Returns 1 if abs(val) == 1 << n for some n >= 0.
3420 * Returns 0 otherwise.
3421 *
3422 * rb_absint_singlebit_p can be used to determine required buffer size
3423 * for rb_integer_pack used with INTEGER_PACK_2COMP (two's complement).
3424 *
3425 * Following example calculates number of bits required to
3426 * represent val in two's complement number, without sign bit.
3427 *
3428 * size_t size;
3429 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3430 * size = rb_absint_numwords(val, 1, NULL)
3431 * if (size == (size_t)-1) ...overflow...
3432 * if (neg && rb_absint_singlebit_p(val))
3433 * size--;
3434 *
3435 * Following example calculates number of bytes required to
3436 * represent val in two's complement number, with sign bit.
3437 *
3438 * size_t size;
3439 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3440 * int nlz_bits;
3441 * size = rb_absint_size(val, &nlz_bits);
3442 * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
3443 * size++;
3444 */
3445int
3447{
3448 BDIGIT *dp;
3449 BDIGIT *de;
3450 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3451 BDIGIT d;
3452
3453 val = rb_to_int(val);
3454
3455 if (FIXNUM_P(val)) {
3456 long v = FIX2LONG(val);
3457 if (v < 0) {
3458 v = -v;
3459 }
3460#if SIZEOF_BDIGIT >= SIZEOF_LONG
3461 fixbuf[0] = v;
3462#else
3463 {
3464 int i;
3465 for (i = 0; i < numberof(fixbuf); i++) {
3466 fixbuf[i] = BIGLO(v);
3467 v = BIGDN(v);
3468 }
3469 }
3470#endif
3471 dp = fixbuf;
3472 de = fixbuf + numberof(fixbuf);
3473 }
3474 else {
3475 dp = BDIGITS(val);
3476 de = dp + BIGNUM_LEN(val);
3477 }
3478 while (dp < de && de[-1] == 0)
3479 de--;
3480 while (dp < de && dp[0] == 0)
3481 dp++;
3482 if (dp == de) /* no bit set. */
3483 return 0;
3484 if (dp != de-1) /* two non-zero words. two bits set, at least. */
3485 return 0;
3486 d = *dp;
3487 return POW2_P(d);
3488}
3489
3490
3491/*
3492 * Export an integer into a buffer.
3493 *
3494 * This function fills the buffer specified by _words_ and _numwords_ as
3495 * val in the format specified by _wordsize_, _nails_ and _flags_.
3496 *
3497 * [val] Fixnum, Bignum or another integer like object which has to_int method.
3498 * [words] buffer to export abs(val).
3499 * [numwords] the size of given buffer as number of words.
3500 * [wordsize] the size of word as number of bytes.
3501 * [nails] number of padding bits in a word.
3502 * Most significant nails bits of each word are filled by zero.
3503 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3504 *
3505 * flags:
3506 * [INTEGER_PACK_MSWORD_FIRST] Store the most significant word as the first word.
3507 * [INTEGER_PACK_LSWORD_FIRST] Store the least significant word as the first word.
3508 * [INTEGER_PACK_MSBYTE_FIRST] Store the most significant byte in a word as the first byte in the word.
3509 * [INTEGER_PACK_LSBYTE_FIRST] Store the least significant byte in a word as the first byte in the word.
3510 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3511 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3512 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3513 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3514 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3515 *
3516 * This function fills the buffer specified by _words_
3517 * as abs(val) if INTEGER_PACK_2COMP is not specified in _flags_.
3518 * If INTEGER_PACK_2COMP is specified, 2's complement representation of val is
3519 * filled in the buffer.
3520 *
3521 * This function returns the signedness and overflow condition.
3522 * The overflow condition depends on INTEGER_PACK_2COMP.
3523 *
3524 * INTEGER_PACK_2COMP is not specified:
3525 * -2 : negative overflow. val <= -2**(numwords*(wordsize*CHAR_BIT-nails))
3526 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0
3527 * 0 : zero. val == 0
3528 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3529 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3530 *
3531 * INTEGER_PACK_2COMP is specified:
3532 * -2 : negative overflow. val < -2**(numwords*(wordsize*CHAR_BIT-nails))
3533 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0
3534 * 0 : zero. val == 0
3535 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3536 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3537 *
3538 * The value, -2**(numwords*(wordsize*CHAR_BIT-nails)), is representable
3539 * in 2's complement representation but not representable in absolute value.
3540 * So -1 is returned for the value if INTEGER_PACK_2COMP is specified
3541 * but returns -2 if INTEGER_PACK_2COMP is not specified.
3542 *
3543 * The least significant words are filled in the buffer when overflow occur.
3544 */
3545
3546int
3547rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3548{
3549 int sign;
3550 BDIGIT *ds;
3551 size_t num_bdigits;
3552 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3553
3554 RB_GC_GUARD(val) = rb_to_int(val);
3555
3556 if (FIXNUM_P(val)) {
3557 long v = FIX2LONG(val);
3558 if (v < 0) {
3559 sign = -1;
3560 v = -v;
3561 }
3562 else {
3563 sign = 1;
3564 }
3565#if SIZEOF_BDIGIT >= SIZEOF_LONG
3566 fixbuf[0] = v;
3567#else
3568 {
3569 int i;
3570 for (i = 0; i < numberof(fixbuf); i++) {
3571 fixbuf[i] = BIGLO(v);
3572 v = BIGDN(v);
3573 }
3574 }
3575#endif
3576 ds = fixbuf;
3577 num_bdigits = numberof(fixbuf);
3578 }
3579 else {
3580 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3581 ds = BDIGITS(val);
3582 num_bdigits = BIGNUM_LEN(val);
3583 }
3584
3585 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3586}
3587
3588/*
3589 * Import an integer into a buffer.
3590 *
3591 * [words] buffer to import.
3592 * [numwords] the size of given buffer as number of words.
3593 * [wordsize] the size of word as number of bytes.
3594 * [nails] number of padding bits in a word.
3595 * Most significant nails bits of each word are ignored.
3596 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3597 *
3598 * flags:
3599 * [INTEGER_PACK_MSWORD_FIRST] Interpret the first word as the most significant word.
3600 * [INTEGER_PACK_LSWORD_FIRST] Interpret the first word as the least significant word.
3601 * [INTEGER_PACK_MSBYTE_FIRST] Interpret the first byte in a word as the most significant byte in the word.
3602 * [INTEGER_PACK_LSBYTE_FIRST] Interpret the first byte in a word as the least significant byte in the word.
3603 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3604 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3605 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3606 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3607 * [INTEGER_PACK_FORCE_BIGNUM] the result will be a Bignum
3608 * even if it is representable as a Fixnum.
3609 * [INTEGER_PACK_NEGATIVE] Returns non-positive value.
3610 * (Returns non-negative value if not specified.)
3611 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3612 *
3613 * This function returns the imported integer as Fixnum or Bignum.
3614 *
3615 * The range of the result value depends on INTEGER_PACK_2COMP and INTEGER_PACK_NEGATIVE.
3616 *
3617 * INTEGER_PACK_2COMP is not set:
3618 * 0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails)) if !INTEGER_PACK_NEGATIVE
3619 * -2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0 if INTEGER_PACK_NEGATIVE
3620 *
3621 * INTEGER_PACK_2COMP is set:
3622 * -2**(numwords*(wordsize*CHAR_BIT-nails)-1) <= val <= 2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1 if !INTEGER_PACK_NEGATIVE
3623 * -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1 if INTEGER_PACK_NEGATIVE
3624 *
3625 * INTEGER_PACK_2COMP without INTEGER_PACK_NEGATIVE means sign extension.
3626 * INTEGER_PACK_2COMP with INTEGER_PACK_NEGATIVE mean assuming the higher bits are 1.
3627 *
3628 * Note that this function returns 0 when numwords is zero and
3629 * INTEGER_PACK_2COMP is set but INTEGER_PACK_NEGATIVE is not set.
3630 */
3631
3632VALUE
3633rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3634{
3635 VALUE val;
3636 size_t num_bdigits;
3637 int sign;
3638 int nlp_bits;
3639 BDIGIT *ds;
3640 BDIGIT fixbuf[2] = { 0, 0 };
3641
3642 validate_integer_pack_format(numwords, wordsize, nails, flags,
3652
3653 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3654
3655 if (LONG_MAX-1 < num_bdigits)
3656 rb_raise(rb_eArgError, "too big to unpack as an integer");
3657 if (num_bdigits <= numberof(fixbuf) && !(flags & INTEGER_PACK_FORCE_BIGNUM)) {
3658 val = Qfalse;
3659 ds = fixbuf;
3660 }
3661 else {
3662 val = bignew((long)num_bdigits, 0);
3663 ds = BDIGITS(val);
3664 }
3665 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3666
3667 if (sign == -2) {
3668 if (val) {
3669 big_extend_carry(val);
3670 }
3671 else if (num_bdigits == numberof(fixbuf)) {
3672 val = bignew((long)num_bdigits+1, 0);
3673 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3674 BDIGITS(val)[num_bdigits++] = 1;
3675 }
3676 else {
3677 ds[num_bdigits++] = 1;
3678 }
3679 }
3680
3681 if (!val) {
3682 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3683 if (u == 0)
3684 return LONG2FIX(0);
3685 if (0 < sign && POSFIXABLE(u))
3686 return LONG2FIX(u);
3687 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3689 return LONG2FIX(-(BDIGIT_DBL_SIGNED)u);
3690 val = bignew((long)num_bdigits, 0 <= sign);
3691 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3692 }
3693
3694 if ((flags & INTEGER_PACK_FORCE_BIGNUM) && sign != 0 &&
3695 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3696 sign = 0;
3697 BIGNUM_SET_SIGN(val, 0 <= sign);
3698
3699 if (flags & INTEGER_PACK_FORCE_BIGNUM)
3700 return bigtrunc(val);
3701 return bignorm(val);
3702}
3703
3704#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3705
3706NORETURN(static inline void invalid_radix(int base));
3707NORETURN(static inline void invalid_integer(VALUE s));
3708
3709static inline int
3710valid_radix_p(int base)
3711{
3712 return (1 < base && base <= 36);
3713}
3714
3715static inline void
3716invalid_radix(int base)
3717{
3718 rb_raise(rb_eArgError, "invalid radix %d", base);
3719}
3720
3721static inline void
3722invalid_integer(VALUE s)
3723{
3724 rb_raise(rb_eArgError, "invalid value for Integer(): %+"PRIsVALUE, s);
3725}
3726
3727static int
3728str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size_t *num_digits_p, ssize_t *len_p)
3729{
3730 char nondigit = 0;
3731 size_t num_digits = 0;
3732 const char *digits_start = str;
3733 const char *digits_end = str;
3734 ssize_t len = *len_p;
3735
3736 int c;
3737
3738 if (!len) {
3739 *num_digits_p = 0;
3740 *len_p = 0;
3741 return TRUE;
3742 }
3743
3744 if (badcheck && *str == '_') goto bad;
3745
3746 while ((c = *str++) != 0) {
3747 if (c == '_') {
3748 if (nondigit) {
3749 if (badcheck) goto bad;
3750 break;
3751 }
3752 nondigit = (char) c;
3753 }
3754 else if ((c = conv_digit(c)) < 0 || c >= base) {
3755 break;
3756 }
3757 else {
3758 nondigit = 0;
3759 num_digits++;
3760 digits_end = str;
3761 }
3762 if (len > 0 && !--len) break;
3763 }
3764 if (badcheck && nondigit) goto bad;
3765 if (badcheck && len) {
3766 str--;
3767 while (*str && ISSPACE(*str)) {
3768 str++;
3769 if (len > 0 && !--len) break;
3770 }
3771 if (len && *str) {
3772 bad:
3773 return FALSE;
3774 }
3775 }
3776 *num_digits_p = num_digits;
3777 *len_p = digits_end - digits_start;
3778 return TRUE;
3779}
3780
3781static VALUE
3782str2big_poweroftwo(
3783 int sign,
3784 const char *digits_start,
3785 const char *digits_end,
3786 size_t num_digits,
3787 int bits_per_digit)
3788{
3789 BDIGIT *dp;
3790 BDIGIT_DBL dd;
3791 int numbits;
3792
3793 size_t num_bdigits;
3794 const char *p;
3795 int c;
3796 VALUE z;
3797
3798 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3799 z = bignew(num_bdigits, sign);
3800 dp = BDIGITS(z);
3801 dd = 0;
3802 numbits = 0;
3803 for (p = digits_end; digits_start < p; p--) {
3804 if ((c = conv_digit(p[-1])) < 0)
3805 continue;
3806 dd |= (BDIGIT_DBL)c << numbits;
3807 numbits += bits_per_digit;
3808 if (BITSPERDIG <= numbits) {
3809 *dp++ = BIGLO(dd);
3810 dd = BIGDN(dd);
3811 numbits -= BITSPERDIG;
3812 }
3813 }
3814 if (numbits) {
3815 *dp++ = BIGLO(dd);
3816 }
3817 assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
3818
3819 return z;
3820}
3821
3822static VALUE
3823str2big_normal(
3824 int sign,
3825 const char *digits_start,
3826 const char *digits_end,
3827 size_t num_bdigits,
3828 int base)
3829{
3830 size_t blen = 1;
3831 BDIGIT *zds;
3832 BDIGIT_DBL num;
3833
3834 size_t i;
3835 const char *p;
3836 int c;
3837 VALUE z;
3838
3839 z = bignew(num_bdigits, sign);
3840 zds = BDIGITS(z);
3841 BDIGITS_ZERO(zds, num_bdigits);
3842
3843 for (p = digits_start; p < digits_end; p++) {
3844 if ((c = conv_digit(*p)) < 0)
3845 continue;
3846 num = c;
3847 i = 0;
3848 for (;;) {
3849 while (i<blen) {
3850 num += (BDIGIT_DBL)zds[i]*base;
3851 zds[i++] = BIGLO(num);
3852 num = BIGDN(num);
3853 }
3854 if (num) {
3855 blen++;
3856 continue;
3857 }
3858 break;
3859 }
3860 assert(blen <= num_bdigits);
3861 }
3862
3863 return z;
3864}
3865
3866static VALUE
3867str2big_karatsuba(
3868 int sign,
3869 const char *digits_start,
3870 const char *digits_end,
3871 size_t num_digits,
3872 size_t num_bdigits,
3873 int digits_per_bdigits_dbl,
3874 int base)
3875{
3876 VALUE powerv;
3877 size_t unit;
3878 VALUE tmpuv = 0;
3879 BDIGIT *uds, *vds, *tds;
3880 BDIGIT_DBL dd;
3881 BDIGIT_DBL current_base;
3882 int m;
3883 int power_level = 0;
3884
3885 size_t i;
3886 const char *p;
3887 int c;
3888 VALUE z;
3889
3890 uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3891 vds = uds + num_bdigits;
3892
3893 powerv = power_cache_get_power(base, power_level, NULL);
3894
3895 i = 0;
3896 dd = 0;
3897 current_base = 1;
3898 m = digits_per_bdigits_dbl;
3899 if (num_digits < (size_t)m)
3900 m = (int)num_digits;
3901 for (p = digits_end; digits_start < p; p--) {
3902 if ((c = conv_digit(p[-1])) < 0)
3903 continue;
3904 dd = dd + c * current_base;
3905 current_base *= base;
3906 num_digits--;
3907 m--;
3908 if (m == 0) {
3909 uds[i++] = BIGLO(dd);
3910 uds[i++] = (BDIGIT)BIGDN(dd);
3911 dd = 0;
3912 m = digits_per_bdigits_dbl;
3913 if (num_digits < (size_t)m)
3914 m = (int)num_digits;
3915 current_base = 1;
3916 }
3917 }
3918 assert(i == num_bdigits);
3919 for (unit = 2; unit < num_bdigits; unit *= 2) {
3920 for (i = 0; i < num_bdigits; i += unit*2) {
3921 if (2*unit <= num_bdigits - i) {
3922 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
3923 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
3924 }
3925 else if (unit <= num_bdigits - i) {
3926 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
3927 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
3928 }
3929 else {
3930 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
3931 }
3932 }
3933 power_level++;
3934 powerv = power_cache_get_power(base, power_level, NULL);
3935 tds = vds;
3936 vds = uds;
3937 uds = tds;
3938 }
3939 BARY_TRUNC(uds, num_bdigits);
3940 z = bignew(num_bdigits, sign);
3941 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
3942
3943 if (tmpuv)
3944 ALLOCV_END(tmpuv);
3945
3946 return z;
3947}
3948
3949#ifdef USE_GMP
3950static VALUE
3951str2big_gmp(
3952 int sign,
3953 const char *digits_start,
3954 const char *digits_end,
3955 size_t num_digits,
3956 size_t num_bdigits,
3957 int base)
3958{
3959 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
3960 char *buf, *p;
3961 const char *q;
3962 VALUE tmps;
3963 mpz_t mz;
3964 VALUE z;
3965 BDIGIT *zds;
3966 size_t zn, count;
3967
3968 buf = ALLOCV_N(char, tmps, num_digits+1);
3969 p = buf;
3970 for (q = digits_start; q < digits_end; q++) {
3971 if (conv_digit(*q) < 0)
3972 continue;
3973 *p++ = *q;
3974 }
3975 *p = '\0';
3976
3977 mpz_init(mz);
3978 mpz_set_str(mz, buf, base);
3979 zn = num_bdigits;
3980 z = bignew(zn, sign);
3981 zds = BDIGITS(z);
3982 mpz_export(BDIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
3984 mpz_clear(mz);
3985
3986 if (tmps)
3987 ALLOCV_END(tmps);
3988
3989 return z;
3990}
3991#endif
3992
3993static VALUE rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base);
3994
3995/*
3996 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
3997 *
3998 * str: pointer to the string to be parsed.
3999 * should be NUL-terminated.
4000 * base: base of conversion, must be 2..36, or -36..0.
4001 * if +base+ > 0, the conversion is done according to the +base+
4002 * and unmatched prefix is parsed as a part of the result if
4003 * present.
4004 * if +base+ <= 0, the conversion is done according to the
4005 * prefix if present, in base <code>-base</code> if +base+ < -1,
4006 * or in base 10.
4007 * badcheck: if non-zero, +ArgumentError+ is raised when +str+ is not
4008 * valid as an Integer. if zero, Fixnum 0 is returned in
4009 * that case.
4010 */
4011VALUE
4012rb_cstr_to_inum(const char *str, int base, int badcheck)
4013{
4014 char *end;
4015 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4016 if (NIL_P(ret)) {
4017 if (badcheck) rb_invalid_str(str, "Integer()");
4018 ret = INT2FIX(0);
4019 }
4020 return ret;
4021}
4022
4023/*
4024 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
4025 *
4026 * str: pointer to the string to be parsed.
4027 * should be NUL-terminated if +len+ is negative.
4028 * len: length of +str+ if >= 0. if +len+ is negative, +str+ should
4029 * be NUL-terminated.
4030 * endp: if non-NULL, the address after parsed part is stored. if
4031 * NULL, Qnil is returned when +str+ is not valid as an Integer.
4032 * ndigits: if non-NULL, the number of parsed digits is stored.
4033 * base: see +rb_cstr_to_inum+
4034 * flags: bitwise OR of below flags:
4035 * RB_INT_PARSE_SIGN: allow preceding spaces and +/- sign
4036 * RB_INT_PARSE_UNDERSCORE: allow an underscore between digits
4037 * RB_INT_PARSE_PREFIX: allow preceding prefix
4038 */
4039
4040VALUE
4041rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
4042 int base, int flags)
4043{
4044 const char *const s = str;
4045 char sign = 1;
4046 int c;
4047 VALUE z = Qnil;
4048
4049 unsigned long val;
4050 int ov;
4051
4052 const char *digits_start, *digits_end;
4053 size_t num_digits = 0;
4054 size_t num_bdigits;
4055 const ssize_t len0 = len;
4056 const int badcheck = !endp;
4057
4058#define ADV(n) do {\
4059 if (len > 0 && len <= (n)) goto bad; \
4060 str += (n); \
4061 len -= (n); \
4062 } while (0)
4063#define ASSERT_LEN() do {\
4064 assert(len != 0); \
4065 if (len0 >= 0) assert(s + len0 == str + len); \
4066 } while (0)
4067
4068 if (!str) {
4069 bad:
4070 if (endp) *endp = (char *)str;
4071 if (ndigits) *ndigits = num_digits;
4072 return z;
4073 }
4074 if (len && (flags & RB_INT_PARSE_SIGN)) {
4075 while (ISSPACE(*str)) ADV(1);
4076
4077 if (str[0] == '+') {
4078 ADV(1);
4079 }
4080 else if (str[0] == '-') {
4081 ADV(1);
4082 sign = 0;
4083 }
4084 ASSERT_LEN();
4085 }
4086 if (base <= 0) {
4087 if (str[0] == '0' && len > 1) {
4088 switch (str[1]) {
4089 case 'x': case 'X':
4090 base = 16;
4091 ADV(2);
4092 break;
4093 case 'b': case 'B':
4094 base = 2;
4095 ADV(2);
4096 break;
4097 case 'o': case 'O':
4098 base = 8;
4099 ADV(2);
4100 break;
4101 case 'd': case 'D':
4102 base = 10;
4103 ADV(2);
4104 break;
4105 default:
4106 base = 8;
4107 }
4108 }
4109 else if (base < -1) {
4110 base = -base;
4111 }
4112 else {
4113 base = 10;
4114 }
4115 }
4116 else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4117 /* no prefix */
4118 }
4119 else if (base == 2) {
4120 if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
4121 ADV(2);
4122 }
4123 }
4124 else if (base == 8) {
4125 if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
4126 ADV(2);
4127 }
4128 }
4129 else if (base == 10) {
4130 if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
4131 ADV(2);
4132 }
4133 }
4134 else if (base == 16) {
4135 if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
4136 ADV(2);
4137 }
4138 }
4139 if (!valid_radix_p(base)) {
4140 invalid_radix(base);
4141 }
4142 if (!len) goto bad;
4143 num_digits = str - s;
4144 if (*str == '0' && len != 1) { /* squeeze preceding 0s */
4145 int us = 0;
4146 const char *end = len < 0 ? NULL : str + len;
4147 ++num_digits;
4148 while ((c = *++str) == '0' ||
4149 ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
4150 if (c == '_') {
4151 if (++us >= 2)
4152 break;
4153 }
4154 else {
4155 ++num_digits;
4156 us = 0;
4157 }
4158 if (str == end) break;
4159 }
4160 if (!c || ISSPACE(c)) --str;
4161 if (end) len = end - str;
4162 ASSERT_LEN();
4163 }
4164 c = *str;
4165 c = conv_digit(c);
4166 if (c < 0 || c >= base) {
4167 if (!badcheck && num_digits) z = INT2FIX(0);
4168 goto bad;
4169 }
4170
4171 if (ndigits) *ndigits = num_digits;
4172 val = ruby_scan_digits(str, len, base, &num_digits, &ov);
4173 if (!ov) {
4174 const char *end = &str[num_digits];
4175 if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
4176 goto bigparse;
4177 if (endp) *endp = (char *)end;
4178 if (ndigits) *ndigits += num_digits;
4179 if (badcheck) {
4180 if (num_digits == 0) return Qnil; /* no number */
4181 while (len < 0 ? *end : end < str + len) {
4182 if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
4183 end++;
4184 }
4185 }
4186
4187 if (POSFIXABLE(val)) {
4188 if (sign) return LONG2FIX(val);
4189 else {
4190 long result = -(long)val;
4191 return LONG2FIX(result);
4192 }
4193 }
4194 else {
4195 VALUE big = rb_uint2big(val);
4196 BIGNUM_SET_SIGN(big, sign);
4197 return bignorm(big);
4198 }
4199 }
4200
4201 bigparse:
4202 digits_start = str;
4203 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4204 goto bad;
4205 if (endp) *endp = (char *)(str + len);
4206 if (ndigits) *ndigits += num_digits;
4207 digits_end = digits_start + len;
4208
4209 if (POW2_P(base)) {
4210 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4211 bit_length(base-1));
4212 }
4213 else {
4214 int digits_per_bdigits_dbl;
4215 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4216 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4217
4218#ifdef USE_GMP
4219 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4220 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4221 num_bdigits, base);
4222 }
4223 else
4224#endif
4225 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4226 z = str2big_normal(sign, digits_start, digits_end,
4227 num_bdigits, base);
4228 }
4229 else {
4230 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4231 num_bdigits, digits_per_bdigits_dbl, base);
4232 }
4233 }
4234
4235 return bignorm(z);
4236}
4237
4238static VALUE
4239rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
4240{
4241 return rb_int_parse_cstr(str, len, endp, NULL, base,
4243}
4244
4245VALUE
4246rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception)
4247{
4248 VALUE ret;
4249 const char *s;
4250 long len;
4251 char *end;
4252
4255 RSTRING_GETMEM(str, s, len);
4256 ret = rb_cstr_parse_inum(s, len, (badcheck ? NULL : &end), base);
4257 if (NIL_P(ret)) {
4258 if (badcheck) {
4259 if (!raise_exception) return Qnil;
4260 invalid_integer(str);
4261 }
4262 ret = INT2FIX(0);
4263 }
4264 return ret;
4265}
4266
4267VALUE
4268rb_str_to_inum(VALUE str, int base, int badcheck)
4269{
4270 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4271}
4272
4273VALUE
4274rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
4275{
4276 int positive_p = 1;
4277 const char *s, *str;
4278 const char *digits_start, *digits_end;
4279 size_t num_digits;
4280 ssize_t len;
4281 VALUE z;
4282
4283 if (!valid_radix_p(base) || !POW2_P(base)) {
4284 invalid_radix(base);
4285 }
4286
4288 s = str = StringValueCStr(arg);
4289 len = RSTRING_LEN(arg);
4290 if (*str == '-') {
4291 len--;
4292 str++;
4293 positive_p = 0;
4294 }
4295
4296 digits_start = str;
4297 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4298 invalid_integer(arg);
4299 digits_end = digits_start + len;
4300
4301 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4302 bit_length(base-1));
4303
4305
4306 return bignorm(z);
4307}
4308
4309VALUE
4310rb_str2big_normal(VALUE arg, int base, int badcheck)
4311{
4312 int positive_p = 1;
4313 const char *s, *str;
4314 const char *digits_start, *digits_end;
4315 size_t num_digits;
4316 ssize_t len;
4317 VALUE z;
4318
4319 int digits_per_bdigits_dbl;
4320 size_t num_bdigits;
4321
4322 if (!valid_radix_p(base)) {
4323 invalid_radix(base);
4324 }
4325
4327 s = str = StringValuePtr(arg);
4328 len = RSTRING_LEN(arg);
4329 if (len > 0 && *str == '-') {
4330 len--;
4331 str++;
4332 positive_p = 0;
4333 }
4334
4335 digits_start = str;
4336 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4337 invalid_integer(arg);
4338 digits_end = digits_start + len;
4339
4340 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4341 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4342
4343 z = str2big_normal(positive_p, digits_start, digits_end,
4344 num_bdigits, base);
4345
4347
4348 return bignorm(z);
4349}
4350
4351VALUE
4352rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
4353{
4354 int positive_p = 1;
4355 const char *s, *str;
4356 const char *digits_start, *digits_end;
4357 size_t num_digits;
4358 ssize_t len;
4359 VALUE z;
4360
4361 int digits_per_bdigits_dbl;
4362 size_t num_bdigits;
4363
4364 if (!valid_radix_p(base)) {
4365 invalid_radix(base);
4366 }
4367
4369 s = str = StringValuePtr(arg);
4370 len = RSTRING_LEN(arg);
4371 if (len > 0 && *str == '-') {
4372 len--;
4373 str++;
4374 positive_p = 0;
4375 }
4376
4377 digits_start = str;
4378 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4379 invalid_integer(arg);
4380 digits_end = digits_start + len;
4381
4382 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4383 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4384
4385 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4386 num_bdigits, digits_per_bdigits_dbl, base);
4387
4389
4390 return bignorm(z);
4391}
4392
4393#ifdef USE_GMP
4394VALUE
4395rb_str2big_gmp(VALUE arg, int base, int badcheck)
4396{
4397 int positive_p = 1;
4398 const char *s, *str;
4399 const char *digits_start, *digits_end;
4400 size_t num_digits;
4401 ssize_t len;
4402 VALUE z;
4403
4404 int digits_per_bdigits_dbl;
4405 size_t num_bdigits;
4406
4407 if (!valid_radix_p(base)) {
4408 invalid_radix(base);
4409 }
4410
4412 s = str = StringValuePtr(arg);
4413 len = RSTRING_LEN(arg);
4414 if (len > 0 && *str == '-') {
4415 len--;
4416 str++;
4417 positive_p = 0;
4418 }
4419
4420 digits_start = str;
4421 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4422 invalid_integer(arg);
4423 digits_end = digits_start + len;
4424
4425 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4426 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4427
4428 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4429
4431
4432 return bignorm(z);
4433}
4434#endif
4435
4436#if HAVE_LONG_LONG
4437
4438static VALUE
4439rb_ull2big(unsigned LONG_LONG n)
4440{
4441 long i;
4443 BDIGIT *digits = BDIGITS(big);
4444
4445#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4446 digits[0] = n;
4447#else
4448 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4449 digits[i] = BIGLO(n);
4450 n = BIGDN(n);
4451 }
4452#endif
4453
4455 while (i-- && !digits[i]) ;
4456 BIGNUM_SET_LEN(big, i+1);
4457 return big;
4458}
4459
4460static VALUE
4461rb_ll2big(LONG_LONG n)
4462{
4463 long neg = 0;
4464 unsigned LONG_LONG u;
4465 VALUE big;
4466
4467 if (n < 0) {
4468 u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
4469 neg = 1;
4470 }
4471 else {
4472 u = n;
4473 }
4474 big = rb_ull2big(u);
4475 if (neg) {
4477 }
4478 return big;
4479}
4480
4481VALUE
4482rb_ull2inum(unsigned LONG_LONG n)
4483{
4484 if (POSFIXABLE(n)) return LONG2FIX(n);
4485 return rb_ull2big(n);
4486}
4487
4488VALUE
4490{
4491 if (FIXABLE(n)) return LONG2FIX(n);
4492 return rb_ll2big(n);
4493}
4494
4495#endif /* HAVE_LONG_LONG */
4496
4497#ifdef HAVE_INT128_T
4498static VALUE
4499rb_uint128t2big(uint128_t n)
4500{
4501 long i;
4503 BDIGIT *digits = BDIGITS(big);
4504
4505 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4506 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4507 }
4508
4510 while (i-- && !digits[i]) ;
4511 BIGNUM_SET_LEN(big, i+1);
4512 return big;
4513}
4514
4517{
4518 int neg = 0;
4519 uint128_t u;
4520 VALUE big;
4521
4522 if (n < 0) {
4523 u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
4524 neg = 1;
4525 }
4526 else {
4527 u = n;
4528 }
4529 big = rb_uint128t2big(u);
4530 if (neg) {
4532 }
4533 return big;
4534}
4535#endif
4536
4537VALUE
4538rb_cstr2inum(const char *str, int base)
4539{
4540 return rb_cstr_to_inum(str, base, base==0);
4541}
4542
4543VALUE
4545{
4546 return rb_str_to_inum(str, base, base==0);
4547}
4548
4549static VALUE
4550big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
4551{
4552 BDIGIT *xds, *zds;
4553 long s1;
4554 int s2;
4555 VALUE z;
4556 long xn;
4557
4558 if (lshift_p) {
4559 if (LONG_MAX < shift_numdigits) {
4560 rb_raise(rb_eArgError, "too big number");
4561 }
4562 s1 = shift_numdigits;
4563 s2 = shift_numbits;
4564 xn = BIGNUM_LEN(x);
4565 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4566 zds = BDIGITS(z);
4567 BDIGITS_ZERO(zds, s1);
4568 xds = BDIGITS(x);
4569 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4570 }
4571 else {
4572 long zn;
4573 BDIGIT hibitsx;
4574 if (LONG_MAX < shift_numdigits || (size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4575 if (BIGNUM_POSITIVE_P(x) ||
4576 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4577 return INT2FIX(0);
4578 else
4579 return INT2FIX(-1);
4580 }
4581 s1 = shift_numdigits;
4582 s2 = shift_numbits;
4583 hibitsx = abs2twocomp(&x, &xn);
4584 xds = BDIGITS(x);
4585 if (xn <= s1) {
4586 return hibitsx ? INT2FIX(-1) : INT2FIX(0);
4587 }
4588 zn = xn - s1;
4589 z = bignew(zn, 0);
4590 zds = BDIGITS(z);
4591 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4592 twocomp2abs_bang(z, hibitsx != 0);
4593 }
4594 RB_GC_GUARD(x);
4595 return z;
4596}
4597
4598static VALUE
4599big_shift2(VALUE x, int lshift_p, VALUE y)
4600{
4601 int sign;
4602 size_t lens[2];
4603 size_t shift_numdigits;
4604 int shift_numbits;
4605
4608
4609 if (BIGZEROP(x))
4610 return INT2FIX(0);
4611 sign = rb_integer_pack(y, lens, numberof(lens), sizeof(size_t), 0,
4613 if (sign < 0) {
4614 lshift_p = !lshift_p;
4615 sign = -sign;
4616 }
4617 if (lshift_p) {
4618 if (1 < sign || CHAR_BIT <= lens[1])
4619 rb_raise(rb_eRangeError, "shift width too big");
4620 }
4621 else {
4622 if (1 < sign || CHAR_BIT <= lens[1])
4623 return BIGNUM_POSITIVE_P(x) ? INT2FIX(0) : INT2FIX(-1);
4624 }
4625 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4626 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4627 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4628 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4629}
4630
4631static VALUE
4632big_lshift(VALUE x, unsigned long shift)
4633{
4634 long s1 = shift/BITSPERDIG;
4635 int s2 = (int)(shift%BITSPERDIG);
4636 return big_shift3(x, 1, s1, s2);
4637}
4638
4639static VALUE
4640big_rshift(VALUE x, unsigned long shift)
4641{
4642 long s1 = shift/BITSPERDIG;
4643 int s2 = (int)(shift%BITSPERDIG);
4644 return big_shift3(x, 0, s1, s2);
4645}
4646
4647#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4648
4649static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4650static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4651
4652static void
4653power_cache_init(void)
4654{
4655 int i, j;
4656 for (i = 0; i < 35; ++i) {
4657 for (j = 0; j < MAX_BASE36_POWER_TABLE_ENTRIES; ++j) {
4658 base36_power_cache[i][j] = Qnil;
4659 }
4660 }
4661}
4662
4663static inline VALUE
4664power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
4665{
4666 /*
4667 * MAX_BASE36_POWER_TABLE_ENTRIES is big enough to that
4668 * base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1] fills whole memory.
4669 * So MAX_BASE36_POWER_TABLE_ENTRIES <= power_level is not possible to calculate.
4670 *
4671 * number-of-bytes =
4672 * log256(base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1]) =
4673 * log256(maxpow_in_bdigit_dbl(base)**(2**(MAX_BASE36_POWER_TABLE_ENTRIES-1))) =
4674 * log256(maxpow_in_bdigit_dbl(base)**(2**(SIZEOF_SIZE_T*CHAR_BIT))) =
4675 * (2**(SIZEOF_SIZE_T*CHAR_BIT))*log256(maxpow_in_bdigit_dbl(base)) =
4676 * (256**SIZEOF_SIZE_T)*log256(maxpow_in_bdigit_dbl(base)) >
4677 * (256**SIZEOF_SIZE_T)*(sizeof(BDIGIT_DBL)-1) >
4678 * 256**SIZEOF_SIZE_T
4679 */
4680 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4681 rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4682
4683 if (NIL_P(base36_power_cache[base - 2][power_level])) {
4684 VALUE power;
4685 size_t numdigits;
4686 if (power_level == 0) {
4687 int numdigits0;
4688 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4689 power = bignew(2, 1);
4690 bdigitdbl2bary(BDIGITS(power), 2, dd);
4691 numdigits = numdigits0;
4692 }
4693 else {
4694 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4695 numdigits *= 2;
4696 }
4697 rb_obj_hide(power);
4698 base36_power_cache[base - 2][power_level] = power;
4699 base36_numdigits_cache[base - 2][power_level] = numdigits;
4701 }
4702 if (numdigits_ret)
4703 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4704 return base36_power_cache[base - 2][power_level];
4705}
4706
4709 int base;
4713 char *ptr;
4714};
4715
4716static void
4717big2str_alloc(struct big2str_struct *b2s, size_t len)
4718{
4719 if (LONG_MAX-1 < len)
4720 rb_raise(rb_eArgError, "too big number");
4721 b2s->result = rb_usascii_str_new(0, (long)(len + 1)); /* plus one for sign */
4722 b2s->ptr = RSTRING_PTR(b2s->result);
4723 if (b2s->negative)
4724 *b2s->ptr++ = '-';
4725}
4726
4727static void
4728big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t taillen)
4729{
4730 size_t j;
4731 BDIGIT_DBL num;
4732 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4733 int beginning = !b2s->ptr;
4734 size_t len = 0;
4735
4736 assert(xn <= 2);
4737 num = bary2bdigitdbl(xds, xn);
4738
4739 if (beginning) {
4740 if (num == 0)
4741 return;
4742 p = buf;
4743 j = sizeof(buf);
4744 do {
4745 BDIGIT_DBL idx = num % b2s->base;
4746 num /= b2s->base;
4747 p[--j] = ruby_digitmap[idx];
4748 } while (num);
4749 len = sizeof(buf) - j;
4750 big2str_alloc(b2s, len + taillen);
4751 MEMCPY(b2s->ptr, buf + j, char, len);
4752 }
4753 else {
4754 p = b2s->ptr;
4755 j = b2s->hbase2_numdigits;
4756 do {
4757 BDIGIT_DBL idx = num % b2s->base;
4758 num /= b2s->base;
4759 p[--j] = ruby_digitmap[idx];
4760 } while (j);
4761 len = b2s->hbase2_numdigits;
4762 }
4763 b2s->ptr += len;
4764}
4765
4766static void
4767big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
4768 int power_level, size_t taillen)
4769{
4770 VALUE b;
4771 size_t half_numdigits, lower_numdigits;
4772 int lower_power_level;
4773 size_t bn;
4774 const BDIGIT *bds;
4775 size_t len;
4776
4777 /*
4778 * Precondition:
4779 * abs(x) < maxpow**(2**power_level)
4780 * where
4781 * maxpow = maxpow_in_bdigit_dbl(base, &numdigits)
4782 *
4783 * This function generates sequence of zeros, and then stringized abs(x) into b2s->ptr.
4784 *
4785 * b2s->ptr can be NULL.
4786 * It is allocated when the first character is generated via big2str_alloc.
4787 *
4788 * The prefix zeros should be generated if and only if b2s->ptr is not NULL.
4789 * When the zeros are generated, the zeros and abs(x) consists
4790 * numdigits*(2**power_level) characters at total.
4791 *
4792 * Note:
4793 * power_cache_get_power(base, power_level, &len) may not be cached yet. It should not be called.
4794 * power_cache_get_power(base, power_level-1, &len) should be cached already if 0 <= power_level-1.
4795 */
4796
4797 if (xn == 0 || bary_zero_p(xds, xn)) {
4798 if (b2s->ptr) {
4799 /* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
4800 power_cache_get_power(b2s->base, power_level, &len);
4801 memset(b2s->ptr, '0', len);
4802 b2s->ptr += len;
4803 }
4804 return;
4805 }
4806
4807 if (power_level == 0) {
4808 big2str_2bdigits(b2s, xds, xn, taillen);
4809 return;
4810 }
4811
4812 lower_power_level = power_level-1;
4813 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4814 bn = BIGNUM_LEN(b);
4815 bds = BDIGITS(b);
4816
4817 half_numdigits = lower_numdigits;
4818
4819 while (0 < lower_power_level &&
4820 (xn < bn ||
4821 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4822 lower_power_level--;
4823 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4824 bn = BIGNUM_LEN(b);
4825 bds = BDIGITS(b);
4826 }
4827
4828 if (lower_power_level == 0 &&
4829 (xn < bn ||
4830 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4831 if (b2s->ptr) {
4832 len = half_numdigits * 2 - lower_numdigits;
4833 memset(b2s->ptr, '0', len);
4834 b2s->ptr += len;
4835 }
4836 big2str_2bdigits(b2s, xds, xn, taillen);
4837 }
4838 else {
4839 BDIGIT *qds, *rds;
4840 size_t qn, rn;
4841 BDIGIT *tds;
4842 int shift;
4843
4844 if (lower_power_level != power_level-1 && b2s->ptr) {
4845 len = (half_numdigits - lower_numdigits) * 2;
4846 memset(b2s->ptr, '0', len);
4847 b2s->ptr += len;
4848 }
4849
4850 shift = nlz(bds[bn-1]);
4851
4852 qn = xn + BIGDIVREM_EXTRA_WORDS;
4853
4854 if (shift == 0) {
4855 /* bigdivrem_restoring will not modify y.
4856 * So use bds directly. */
4857 tds = (BDIGIT *)bds;
4858 xds[xn] = 0;
4859 }
4860 else {
4861 /* bigdivrem_restoring will modify y.
4862 * So use temporary buffer. */
4863 tds = xds + qn;
4864 assert(qn + bn <= xn + wn);
4865 bary_small_lshift(tds, bds, bn, shift);
4866 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4867 }
4868
4869 bigdivrem_restoring(xds, qn, tds, bn);
4870
4871 rds = xds;
4872 rn = bn;
4873
4874 qds = xds + bn;
4875 qn = qn - bn;
4876
4877 if (shift) {
4878 bary_small_rshift(rds, rds, rn, shift, 0);
4879 }
4880
4881 BARY_TRUNC(qds, qn);
4882 assert(qn <= bn);
4883 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4884 BARY_TRUNC(rds, rn);
4885 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4886 }
4887}
4888
4889static VALUE
4890big2str_base_poweroftwo(VALUE x, int base)
4891{
4892 int word_numbits = ffs(base) - 1;
4893 size_t numwords;
4894 VALUE result;
4895 char *ptr;
4896 numwords = rb_absint_numwords(x, word_numbits, NULL);
4897 if (BIGNUM_NEGATIVE_P(x)) {
4898 if (LONG_MAX-1 < numwords)
4899 rb_raise(rb_eArgError, "too big number");
4900 result = rb_usascii_str_new(0, 1+numwords);
4901 ptr = RSTRING_PTR(result);
4902 *ptr++ = BIGNUM_POSITIVE_P(x) ? '+' : '-';
4903 }
4904 else {
4905 if (LONG_MAX < numwords)
4906 rb_raise(rb_eArgError, "too big number");
4907 result = rb_usascii_str_new(0, numwords);
4908 ptr = RSTRING_PTR(result);
4909 }
4910 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4912 while (0 < numwords) {
4913 *ptr = ruby_digitmap[*(unsigned char *)ptr];
4914 ptr++;
4915 numwords--;
4916 }
4917 return result;
4918}
4919
4920VALUE
4922{
4923 return big2str_base_poweroftwo(x, base);
4924}
4925
4926static VALUE
4927big2str_generic(VALUE x, int base)
4928{
4929 BDIGIT *xds;
4930 size_t xn;
4931 struct big2str_struct b2s_data;
4932 int power_level;
4933 VALUE power;
4934
4935 xds = BDIGITS(x);
4936 xn = BIGNUM_LEN(x);
4937 BARY_TRUNC(xds, xn);
4938
4939 if (xn == 0) {
4940 return rb_usascii_str_new2("0");
4941 }
4942
4943 if (!valid_radix_p(base))
4944 invalid_radix(base);
4945
4946 if (xn >= LONG_MAX/BITSPERDIG) {
4947 rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
4948 }
4949
4950 power_level = 0;
4951 power = power_cache_get_power(base, power_level, NULL);
4952 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
4953 (size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
4954 power_level++;
4955 power = power_cache_get_power(base, power_level, NULL);
4956 }
4957 assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
4958
4959 if ((size_t)BIGNUM_LEN(power) <= xn) {
4960 /*
4961 * This increment guarantees x < power_cache_get_power(base, power_level)
4962 * without invoking it actually.
4963 * (power_cache_get_power(base, power_level) can be slow and not used
4964 * in big2str_karatsuba.)
4965 *
4966 * Although it is possible that x < power_cache_get_power(base, power_level-1),
4967 * it is no problem because big2str_karatsuba checks it and
4968 * doesn't affect the result when b2s_data.ptr is NULL.
4969 */
4970 power_level++;
4971 }
4972
4973 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
4974 b2s_data.base = base;
4975 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
4976
4977 b2s_data.result = Qnil;
4978 b2s_data.ptr = NULL;
4979
4980 if (power_level == 0) {
4981 big2str_2bdigits(&b2s_data, xds, xn, 0);
4982 }
4983 else {
4984 VALUE tmpw = 0;
4985 BDIGIT *wds;
4986 size_t wn;
4987 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
4988 wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
4989 MEMCPY(wds, xds, BDIGIT, xn);
4990 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
4991 if (tmpw)
4992 ALLOCV_END(tmpw);
4993 }
4994 RB_GC_GUARD(x);
4995
4996 *b2s_data.ptr = '\0';
4997 rb_str_resize(b2s_data.result, (long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
4998
4999 RB_GC_GUARD(x);
5000 return b2s_data.result;
5001}
5002
5003VALUE
5005{
5006 return big2str_generic(x, base);
5007}
5008
5009#ifdef USE_GMP
5010static VALUE
5011big2str_gmp(VALUE x, int base)
5012{
5013 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
5014 mpz_t mx;
5015 size_t size;
5016 VALUE str;
5017 BDIGIT *xds = BDIGITS(x);
5018 size_t xn = BIGNUM_LEN(x);
5019
5020 mpz_init(mx);
5021 mpz_import(mx, xn, -1, sizeof(BDIGIT), 0, nails, xds);
5022
5023 size = mpz_sizeinbase(mx, base);
5024
5025 if (BIGNUM_NEGATIVE_P(x)) {
5026 mpz_neg(mx, mx);
5027 str = rb_usascii_str_new(0, size+1);
5028 }
5029 else {
5031 }
5032 mpz_get_str(RSTRING_PTR(str), base, mx);
5033 mpz_clear(mx);
5034
5035 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\0') {
5037 }
5038
5039 RB_GC_GUARD(x);
5040 return str;
5041}
5042
5043VALUE
5045{
5046 return big2str_gmp(x, base);
5047}
5048#endif
5049
5050static VALUE
5051rb_big2str1(VALUE x, int base)
5052{
5053 BDIGIT *xds;
5054 size_t xn;
5055
5056 if (FIXNUM_P(x)) {
5057 return rb_fix2str(x, base);
5058 }
5059
5060 bigtrunc(x);
5061 xds = BDIGITS(x);
5062 xn = BIGNUM_LEN(x);
5063 BARY_TRUNC(xds, xn);
5064
5065 if (xn == 0) {
5066 return rb_usascii_str_new2("0");
5067 }
5068
5069 if (!valid_radix_p(base))
5070 invalid_radix(base);
5071
5072 if (xn >= LONG_MAX/BITSPERDIG) {
5073 rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
5074 }
5075
5076 if (POW2_P(base)) {
5077 /* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
5078 return big2str_base_poweroftwo(x, base);
5079 }
5080
5081#ifdef USE_GMP
5082 if (GMP_BIG2STR_DIGITS < xn) {
5083 return big2str_gmp(x, base);
5084 }
5085#endif
5086
5087 return big2str_generic(x, base);
5088}
5089
5090VALUE
5092{
5093 return rb_big2str1(x, base);
5094}
5095
5096static unsigned long
5097big2ulong(VALUE x, const char *type)
5098{
5099#if SIZEOF_LONG > SIZEOF_BDIGIT
5100 size_t i;
5101#endif
5102 size_t len = BIGNUM_LEN(x);
5103 unsigned long num;
5104 BDIGIT *ds;
5105
5106 if (len == 0)
5107 return 0;
5108 if (BIGSIZE(x) > sizeof(long)) {
5109 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
5110 }
5111 ds = BDIGITS(x);
5112#if SIZEOF_LONG <= SIZEOF_BDIGIT
5113 num = (unsigned long)ds[0];
5114#else
5115 num = 0;
5116 for (i = 0; i < len; i++) {
5117 num <<= BITSPERDIG;
5118 num += (unsigned long)ds[len - i - 1]; /* overflow is already checked */
5119 }
5120#endif
5121 return num;
5122}
5123
5124unsigned long
5126{
5127 unsigned long num = big2ulong(x, "unsigned long");
5128
5129 if (BIGNUM_POSITIVE_P(x)) {
5130 return num;
5131 }
5132 else {
5133 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5134 return -(long)(num-1)-1;
5135 }
5136 rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
5137}
5138
5139long
5141{
5142 unsigned long num = big2ulong(x, "long");
5143
5144 if (BIGNUM_POSITIVE_P(x)) {
5145 if (num <= LONG_MAX)
5146 return num;
5147 }
5148 else {
5149 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5150 return -(long)(num-1)-1;
5151 }
5152 rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
5153}
5154
5155#if HAVE_LONG_LONG
5156
5157static unsigned LONG_LONG
5158big2ull(VALUE x, const char *type)
5159{
5160#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5161 size_t i;
5162#endif
5163 size_t len = BIGNUM_LEN(x);
5164 unsigned LONG_LONG num;
5165 BDIGIT *ds = BDIGITS(x);
5166
5167 if (len == 0)
5168 return 0;
5169 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5170 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
5171#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5172 num = (unsigned LONG_LONG)ds[0];
5173#else
5174 num = 0;
5175 for (i = 0; i < len; i++) {
5176 num = BIGUP(num);
5177 num += ds[len - i - 1];
5178 }
5179#endif
5180 return num;
5181}
5182
5183unsigned LONG_LONG
5185{
5186 unsigned LONG_LONG num = big2ull(x, "unsigned long long");
5187
5188 if (BIGNUM_POSITIVE_P(x)) {
5189 return num;
5190 }
5191 else {
5192 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5193 return -(LONG_LONG)(num-1)-1;
5194 }
5195 rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
5196}
5197
5200{
5201 unsigned LONG_LONG num = big2ull(x, "long long");
5202
5203 if (BIGNUM_POSITIVE_P(x)) {
5204 if (num <= LLONG_MAX)
5205 return num;
5206 }
5207 else {
5208 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5209 return -(LONG_LONG)(num-1)-1;
5210 }
5211 rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
5212}
5213
5214#endif /* HAVE_LONG_LONG */
5215
5216static VALUE
5217dbl2big(double d)
5218{
5219 long i = 0;
5220 BDIGIT c;
5221 BDIGIT *digits;
5222 VALUE z;
5223 double u = (d < 0)?-d:d;
5224
5225 if (isinf(d)) {
5226 rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
5227 }
5228 if (isnan(d)) {
5230 }
5231
5232 while (1.0 <= u) {
5233 u /= (double)(BIGRAD);
5234 i++;
5235 }
5236 z = bignew(i, d>=0);
5237 digits = BDIGITS(z);
5238 while (i--) {
5239 u *= BIGRAD;
5240 c = (BDIGIT)u;
5241 u -= c;
5242 digits[i] = c;
5243 }
5244
5245 return z;
5246}
5247
5248VALUE
5249rb_dbl2big(double d)
5250{
5251 return bignorm(dbl2big(d));
5252}
5253
5254static double
5255big2dbl(VALUE x)
5256{
5257 double d = 0.0;
5258 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5259 BDIGIT *ds = BDIGITS(x), dl;
5260
5261 if (i) {
5262 bits = i * BITSPERDIG - nlz(ds[i-1]);
5263 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5264 d = HUGE_VAL;
5265 }
5266 else {
5267 if (bits > DBL_MANT_DIG+1)
5268 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5269 else
5270 bits = 0;
5271 while (--i > lo) {
5272 d = ds[i] + BIGRAD*d;
5273 }
5274 dl = ds[i];
5275 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5276 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5277 if (!carry) {
5278 while (i-- > 0) {
5279 carry = ds[i] != 0;
5280 if (carry) break;
5281 }
5282 }
5283 if (carry) {
5285 BDIGIT bit = 1;
5286 mask <<= bits;
5287 bit <<= bits;
5288 dl &= mask;
5289 dl += bit;
5290 dl = BIGLO(dl);
5291 if (!dl) d += 1;
5292 }
5293 }
5294 d = dl + BIGRAD*d;
5295 if (lo) {
5296 if (lo > INT_MAX / BITSPERDIG)
5297 d = HUGE_VAL;
5298 else if (lo < INT_MIN / BITSPERDIG)
5299 d = 0.0;
5300 else
5301 d = ldexp(d, (int)(lo * BITSPERDIG));
5302 }
5303 }
5304 }
5305 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5306 return d;
5307}
5308
5309double
5311{
5312 double d = big2dbl(x);
5313
5314 if (isinf(d)) {
5315 rb_warning("Bignum out of Float range");
5316 if (d < 0.0)
5317 d = -HUGE_VAL;
5318 else
5319 d = HUGE_VAL;
5320 }
5321 return d;
5322}
5323
5324VALUE
5326{
5327 double yd = RFLOAT_VALUE(y);
5328 double yi, yf;
5329 VALUE rel;
5330
5331 if (isnan(yd))
5332 return Qnil;
5333 if (isinf(yd)) {
5334 if (yd > 0.0) return INT2FIX(-1);
5335 else return INT2FIX(1);
5336 }
5337 yf = modf(yd, &yi);
5338 if (FIXNUM_P(x)) {
5339#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5340 double xd = (double)FIX2LONG(x);
5341 if (xd < yd)
5342 return INT2FIX(-1);
5343 if (xd > yd)
5344 return INT2FIX(1);
5345 return INT2FIX(0);
5346#else
5347 long xn, yn;
5348 if (yi < FIXNUM_MIN)
5349 return INT2FIX(1);
5350 if (FIXNUM_MAX+1 <= yi)
5351 return INT2FIX(-1);
5352 xn = FIX2LONG(x);
5353 yn = (long)yi;
5354 if (xn < yn)
5355 return INT2FIX(-1);
5356 if (xn > yn)
5357 return INT2FIX(1);
5358 if (yf < 0.0)
5359 return INT2FIX(1);
5360 if (0.0 < yf)
5361 return INT2FIX(-1);
5362 return INT2FIX(0);
5363#endif
5364 }
5365 y = rb_dbl2big(yi);
5366 rel = rb_big_cmp(x, y);
5367 if (yf == 0.0 || rel != INT2FIX(0))
5368 return rel;
5369 if (yf < 0.0)
5370 return INT2FIX(1);
5371 return INT2FIX(-1);
5372}
5373
5374#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5376#ifdef __has_warning
5377#if __has_warning("-Wimplicit-int-float-conversion")
5378COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
5379#endif
5380#endif
5381static const double LONG_MAX_as_double = LONG_MAX;
5383#endif
5384
5385VALUE
5387{
5388 double yd = RFLOAT_VALUE(y);
5389 double yi, yf;
5390
5391 if (isnan(yd) || isinf(yd))
5392 return Qfalse;
5393 yf = modf(yd, &yi);
5394 if (yf != 0)
5395 return Qfalse;
5396 if (FIXNUM_P(x)) {
5397#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5398 double xd = (double)FIX2LONG(x);
5399 if (xd != yd)
5400 return Qfalse;
5401 return Qtrue;
5402#else
5403 long xn, yn;
5404 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5405 return Qfalse;
5406 xn = FIX2LONG(x);
5407 yn = (long)yi;
5408 if (xn != yn)
5409 return Qfalse;
5410 return Qtrue;
5411#endif
5412 }
5413 y = rb_dbl2big(yi);
5414 return rb_big_eq(x, y);
5415}
5416
5417
5418VALUE
5420{
5421 if (FIXNUM_P(y)) {
5422 x = bigfixize(x);
5423 if (FIXNUM_P(x)) {
5424 /* SIGNED_VALUE and Fixnum have same sign-bits, same
5425 * order */
5426 SIGNED_VALUE sx = (SIGNED_VALUE)x, sy = (SIGNED_VALUE)y;
5427 if (sx < sy) return INT2FIX(-1);
5428 return INT2FIX(sx > sy);
5429 }
5430 }
5431 else if (RB_BIGNUM_TYPE_P(y)) {
5432 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5433 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5434 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5435 }
5436 }
5437 else if (RB_FLOAT_TYPE_P(y)) {
5438 return rb_integer_float_cmp(x, y);
5439 }
5440 else {
5441 return rb_num_coerce_cmp(x, y, idCmp);
5442 }
5443 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5444}
5445
5450 big_op_le
5452
5453static VALUE
5454big_op(VALUE x, VALUE y, enum big_op_t op)
5455{
5456 VALUE rel;
5457 int n;
5458
5459 if (RB_INTEGER_TYPE_P(y)) {
5460 rel = rb_big_cmp(x, y);
5461 }
5462 else if (RB_FLOAT_TYPE_P(y)) {
5463 rel = rb_integer_float_cmp(x, y);
5464 }
5465 else {
5466 ID id = 0;
5467 switch (op) {
5468 case big_op_gt: id = '>'; break;
5469 case big_op_ge: id = idGE; break;
5470 case big_op_lt: id = '<'; break;
5471 case big_op_le: id = idLE; break;
5472 }
5473 return rb_num_coerce_relop(x, y, id);
5474 }
5475
5476 if (NIL_P(rel)) return Qfalse;
5477 n = FIX2INT(rel);
5478
5479 switch (op) {
5480 case big_op_gt: return n > 0 ? Qtrue : Qfalse;
5481 case big_op_ge: return n >= 0 ? Qtrue : Qfalse;
5482 case big_op_lt: return n < 0 ? Qtrue : Qfalse;
5483 case big_op_le: return n <= 0 ? Qtrue : Qfalse;
5484 }
5485 return Qundef;
5486}
5487
5488VALUE
5490{
5491 return big_op(x, y, big_op_gt);
5492}
5493
5494VALUE
5496{
5497 return big_op(x, y, big_op_ge);
5498}
5499
5500VALUE
5502{
5503 return big_op(x, y, big_op_lt);
5504}
5505
5506VALUE
5508{
5509 return big_op(x, y, big_op_le);
5510}
5511
5512/*
5513 * call-seq:
5514 * big == obj -> true or false
5515 *
5516 * Returns <code>true</code> only if <i>obj</i> has the same value
5517 * as <i>big</i>. Contrast this with Integer#eql?, which requires
5518 * <i>obj</i> to be a Integer.
5519 *
5520 * 68719476736 == 68719476736.0 #=> true
5521 */
5522
5523VALUE
5525{
5526 if (FIXNUM_P(y)) {
5527 return bignorm(x) == y ? Qtrue : Qfalse;
5528 }
5529 else if (RB_BIGNUM_TYPE_P(y)) {
5530 }
5531 else if (RB_FLOAT_TYPE_P(y)) {
5532 return rb_integer_float_eq(x, y);
5533 }
5534 else {
5535 return rb_equal(y, x);
5536 }
5537 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5538 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5539 if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
5540 return Qtrue;
5541}
5542
5543VALUE
5545{
5546 if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
5547 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5548 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5549 if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) != 0) return Qfalse;
5550 return Qtrue;
5551}
5552
5553VALUE
5555{
5556 VALUE z = rb_big_clone(x);
5557
5558 BIGNUM_NEGATE(z);
5559
5560 return bignorm(z);
5561}
5562
5563VALUE
5565{
5566 VALUE z = rb_big_clone(x);
5567 BDIGIT *ds = BDIGITS(z);
5568 long n = BIGNUM_LEN(z);
5569
5570 if (!n) return INT2FIX(-1);
5571
5572 if (BIGNUM_POSITIVE_P(z)) {
5573 if (bary_add_one(ds, n)) {
5574 big_extend_carry(z);
5575 }
5577 }
5578 else {
5579 bary_neg(ds, n);
5580 if (bary_add_one(ds, n))
5581 return INT2FIX(-1);
5582 bary_neg(ds, n);
5584 }
5585
5586 return bignorm(z);
5587}
5588
5589static VALUE
5590bigsub(VALUE x, VALUE y)
5591{
5592 VALUE z;
5593 BDIGIT *xds, *yds, *zds;
5594 long xn, yn, zn;
5595
5596 xn = BIGNUM_LEN(x);
5597 yn = BIGNUM_LEN(y);
5598 zn = xn < yn ? yn : xn;
5599
5600 z = bignew(zn, 1);
5601
5602 xds = BDIGITS(x);
5603 yds = BDIGITS(y);
5604 zds = BDIGITS(z);
5605
5606 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5607 bary_2comp(zds, zn);
5609 }
5610
5611 return z;
5612}
5613
5614static VALUE bigadd_int(VALUE x, long y);
5615
5616static VALUE
5617bigsub_int(VALUE x, long y0)
5618{
5619 VALUE z;
5620 BDIGIT *xds, *zds;
5621 long xn, zn;
5623 long i, y;
5624
5625 y = y0;
5626 xds = BDIGITS(x);
5627 xn = BIGNUM_LEN(x);
5628
5629 if (xn == 0)
5630 return LONG2NUM(-y0);
5631
5632 zn = xn;
5633#if SIZEOF_BDIGIT < SIZEOF_LONG
5634 if (zn < bdigit_roomof(SIZEOF_LONG))
5636#endif
5637 z = bignew(zn, BIGNUM_SIGN(x));
5638 zds = BDIGITS(z);
5639
5640#if SIZEOF_BDIGIT >= SIZEOF_LONG
5641 assert(xn == zn);
5642 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5643 if (xn == 1 && num < 0) {
5644 BIGNUM_NEGATE(z);
5645 zds[0] = (BDIGIT)-num;
5646 RB_GC_GUARD(x);
5647 return bignorm(z);
5648 }
5649 zds[0] = BIGLO(num);
5650 num = BIGDN(num);
5651 i = 1;
5652 if (i < xn)
5653 goto y_is_zero_x;
5654 goto finish;
5655#else
5656 num = 0;
5657 for (i=0; i < xn; i++) {
5658 if (y == 0) goto y_is_zero_x;
5659 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5660 zds[i] = BIGLO(num);
5661 num = BIGDN(num);
5662 y = BIGDN(y);
5663 }
5664 for (; i < zn; i++) {
5665 if (y == 0) goto y_is_zero_z;
5666 num -= BIGLO(y);
5667 zds[i] = BIGLO(num);
5668 num = BIGDN(num);
5669 y = BIGDN(y);
5670 }
5671 goto finish;
5672#endif
5673
5674 for (; i < xn; i++) {
5675 y_is_zero_x:
5676 if (num == 0) goto num_is_zero_x;
5677 num += xds[i];
5678 zds[i] = BIGLO(num);
5679 num = BIGDN(num);
5680 }
5681#if SIZEOF_BDIGIT < SIZEOF_LONG
5682 for (; i < zn; i++) {
5683 y_is_zero_z:
5684 if (num == 0) goto num_is_zero_z;
5685 zds[i] = BIGLO(num);
5686 num = BIGDN(num);
5687 }
5688#endif
5689 goto finish;
5690
5691 for (; i < xn; i++) {
5692 num_is_zero_x:
5693 zds[i] = xds[i];
5694 }
5695#if SIZEOF_BDIGIT < SIZEOF_LONG
5696 for (; i < zn; i++) {
5697 num_is_zero_z:
5698 zds[i] = 0;
5699 }
5700#endif
5701 goto finish;
5702
5703 finish:
5704 assert(num == 0 || num == -1);
5705 if (num < 0) {
5706 get2comp(z);
5707 BIGNUM_NEGATE(z);
5708 }
5709 RB_GC_GUARD(x);
5710 return bignorm(z);
5711}
5712
5713static VALUE
5714bigadd_int(VALUE x, long y)
5715{
5716 VALUE z;
5717 BDIGIT *xds, *zds;
5718 long xn, zn;
5719 BDIGIT_DBL num;
5720 long i;
5721
5722 xds = BDIGITS(x);
5723 xn = BIGNUM_LEN(x);
5724
5725 if (xn == 0)
5726 return LONG2NUM(y);
5727
5728 zn = xn;
5729#if SIZEOF_BDIGIT < SIZEOF_LONG
5730 if (zn < bdigit_roomof(SIZEOF_LONG))
5732#endif
5733 zn++;
5734
5735 z = bignew(zn, BIGNUM_SIGN(x));
5736 zds = BDIGITS(z);
5737
5738#if SIZEOF_BDIGIT >= SIZEOF_LONG
5739 num = (BDIGIT_DBL)xds[0] + y;
5740 zds[0] = BIGLO(num);
5741 num = BIGDN(num);
5742 i = 1;
5743 if (i < xn)
5744 goto y_is_zero_x;
5745 goto y_is_zero_z;
5746#else
5747 num = 0;
5748 for (i=0; i < xn; i++) {
5749 if (y == 0) goto y_is_zero_x;
5750 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5751 zds[i] = BIGLO(num);
5752 num = BIGDN(num);
5753 y = BIGDN(y);
5754 }
5755 for (; i < zn; i++) {
5756 if (y == 0) goto y_is_zero_z;
5757 num += BIGLO(y);
5758 zds[i] = BIGLO(num);
5759 num = BIGDN(num);
5760 y = BIGDN(y);
5761 }
5762 goto finish;
5763
5764#endif
5765
5766 for (;i < xn; i++) {
5767 y_is_zero_x:
5768 if (num == 0) goto num_is_zero_x;
5769 num += (BDIGIT_DBL)xds[i];
5770 zds[i] = BIGLO(num);
5771 num = BIGDN(num);
5772 }
5773 for (; i < zn; i++) {
5774 y_is_zero_z:
5775 if (num == 0) goto num_is_zero_z;
5776 zds[i] = BIGLO(num);
5777 num = BIGDN(num);
5778 }
5779 goto finish;
5780
5781 for (;i < xn; i++) {
5782 num_is_zero_x:
5783 zds[i] = xds[i];
5784 }
5785 for (; i < zn; i++) {
5786 num_is_zero_z:
5787 zds[i] = 0;
5788 }
5789 goto finish;
5790
5791 finish:
5792 RB_GC_GUARD(x);
5793 return bignorm(z);
5794}
5795
5796static VALUE
5797bigadd(VALUE x, VALUE y, int sign)
5798{
5799 VALUE z;
5800 size_t len;
5801
5802 sign = (sign == BIGNUM_SIGN(y));
5803 if (BIGNUM_SIGN(x) != sign) {
5804 if (sign) return bigsub(y, x);
5805 return bigsub(x, y);
5806 }
5807
5808 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5809 len = BIGNUM_LEN(x) + 1;
5810 }
5811 else {
5812 len = BIGNUM_LEN(y) + 1;
5813 }
5814 z = bignew(len, sign);
5815
5816 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5817 BDIGITS(x), BIGNUM_LEN(x),
5818 BDIGITS(y), BIGNUM_LEN(y));
5819
5820 return z;
5821}
5822
5823VALUE
5825{
5826 long n;
5827
5828 if (FIXNUM_P(y)) {
5829 n = FIX2LONG(y);
5830 if ((n > 0) != BIGNUM_SIGN(x)) {
5831 if (n < 0) {
5832 n = -n;
5833 }
5834 return bigsub_int(x, n);
5835 }
5836 if (n < 0) {
5837 n = -n;
5838 }
5839 return bigadd_int(x, n);
5840 }
5841 else if (RB_BIGNUM_TYPE_P(y)) {
5842 return bignorm(bigadd(x, y, 1));
5843 }
5844 else if (RB_FLOAT_TYPE_P(y)) {
5845 return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
5846 }
5847 else {
5848 return rb_num_coerce_bin(x, y, '+');
5849 }
5850}
5851
5852VALUE
5854{
5855 long n;
5856
5857 if (FIXNUM_P(y)) {
5858 n = FIX2LONG(y);
5859 if ((n > 0) != BIGNUM_SIGN(x)) {
5860 if (n < 0) {
5861 n = -n;
5862 }
5863 return bigadd_int(x, n);
5864 }
5865 if (n < 0) {
5866 n = -n;
5867 }
5868 return bigsub_int(x, n);
5869 }
5870 else if (RB_BIGNUM_TYPE_P(y)) {
5871 return bignorm(bigadd(x, y, 0));
5872 }
5873 else if (RB_FLOAT_TYPE_P(y)) {
5874 return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
5875 }
5876 else {
5877 return rb_num_coerce_bin(x, y, '-');
5878 }
5879}
5880
5881static VALUE
5882bigsq(VALUE x)
5883{
5884 long xn, zn;
5885 VALUE z;
5886 BDIGIT *xds, *zds;
5887
5888 xn = BIGNUM_LEN(x);
5889 zn = 2 * xn;
5890
5891 z = bignew(zn, 1);
5892
5893 xds = BDIGITS(x);
5894 zds = BDIGITS(z);
5895
5896 if (xn < NAIVE_MUL_DIGITS)
5897 bary_sq_fast(zds, zn, xds, xn);
5898 else
5899 bary_mul(zds, zn, xds, xn, xds, xn);
5900
5901 RB_GC_GUARD(x);
5902 return z;
5903}
5904
5905static VALUE
5906bigmul0(VALUE x, VALUE y)
5907{
5908 long xn, yn, zn;
5909 VALUE z;
5910 BDIGIT *xds, *yds, *zds;
5911
5912 if (x == y)
5913 return bigsq(x);
5914
5915 xn = BIGNUM_LEN(x);
5916 yn = BIGNUM_LEN(y);
5917 zn = xn + yn;
5918
5919 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5920
5921 xds = BDIGITS(x);
5922 yds = BDIGITS(y);
5923 zds = BDIGITS(z);
5924
5925 bary_mul(zds, zn, xds, xn, yds, yn);
5926
5927 RB_GC_GUARD(x);
5928 RB_GC_GUARD(y);
5929 return z;
5930}
5931
5932VALUE
5934{
5935 if (FIXNUM_P(y)) {
5936 y = rb_int2big(FIX2LONG(y));
5937 }
5938 else if (RB_BIGNUM_TYPE_P(y)) {
5939 }
5940 else if (RB_FLOAT_TYPE_P(y)) {
5941 return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
5942 }
5943 else {
5944 return rb_num_coerce_bin(x, y, '*');
5945 }
5946
5947 return bignorm(bigmul0(x, y));
5948}
5949
5950static VALUE
5951bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
5952{
5953 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
5954 VALUE z;
5955 BDIGIT *xds, *yds, *zds;
5956 BDIGIT dd;
5957
5958 VALUE q = Qnil, r = Qnil;
5959 BDIGIT *qds, *rds;
5960 long qn, rn;
5961
5962 yds = BDIGITS(y);
5963 BARY_TRUNC(yds, yn);
5964 if (yn == 0)
5966
5967 xds = BDIGITS(x);
5968 BARY_TRUNC(xds, xn);
5969
5970 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
5971 if (divp) *divp = rb_int2big(0);
5972 if (modp) *modp = x;
5973 return Qnil;
5974 }
5975 if (yn == 1) {
5976 dd = yds[0];
5977 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5978 zds = BDIGITS(z);
5979 dd = bigdivrem_single(zds, xds, xn, dd);
5980 if (modp) {
5981 *modp = rb_uint2big((uintptr_t)dd);
5982 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
5983 }
5984 if (divp) *divp = z;
5985 return Qnil;
5986 }
5987 if (xn == 2 && yn == 2) {
5988 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
5989 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
5990 BDIGIT_DBL q0 = x0 / y0;
5991 BDIGIT_DBL r0 = x0 % y0;
5992 if (divp) {
5994 zds = BDIGITS(z);
5995 zds[0] = BIGLO(q0);
5996 zds[1] = BIGLO(BIGDN(q0));
5997 *divp = z;
5998 }
5999 if (modp) {
6000 z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6001 zds = BDIGITS(z);
6002 zds[0] = BIGLO(r0);
6003 zds[1] = BIGLO(BIGDN(r0));
6004 *modp = z;
6005 }
6006 return Qnil;
6007 }
6008
6009 if (divp) {
6010 qn = xn + BIGDIVREM_EXTRA_WORDS;
6011 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6012 qds = BDIGITS(q);
6013 }
6014 else {
6015 qn = 0;
6016 qds = NULL;
6017 }
6018
6019 if (modp) {
6020 rn = yn;
6021 r = bignew(rn, BIGNUM_SIGN(x));
6022 rds = BDIGITS(r);
6023 }
6024 else {
6025 rn = 0;
6026 rds = NULL;
6027 }
6028
6029 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6030
6031 if (divp) {
6032 bigtrunc(q);
6033 *divp = q;
6034 }
6035 if (modp) {
6036 bigtrunc(r);
6037 *modp = r;
6038 }
6039
6040 return Qnil;
6041}
6042
6043static void
6044bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
6045{
6046 VALUE mod;
6047
6048 bigdivrem(x, y, divp, &mod);
6049 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6050 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6051 if (modp) *modp = bigadd(mod, y, 1);
6052 }
6053 else if (modp) {
6054 *modp = mod;
6055 }
6056}
6057
6058
6059static VALUE
6060rb_big_divide(VALUE x, VALUE y, ID op)
6061{
6062 VALUE z;
6063
6064 if (FIXNUM_P(y)) {
6065 y = rb_int2big(FIX2LONG(y));
6066 }
6067 else if (RB_BIGNUM_TYPE_P(y)) {
6068 }
6069 else if (RB_FLOAT_TYPE_P(y)) {
6070 if (op == '/') {
6071 double dx = rb_big2dbl(x);
6072 return rb_flo_div_flo(DBL2NUM(dx), y);
6073 }
6074 else {
6075 VALUE v;
6076 double dy = RFLOAT_VALUE(y);
6077 if (dy == 0.0) rb_num_zerodiv();
6078 v = rb_big_divide(x, y, '/');
6079 return rb_dbl2big(RFLOAT_VALUE(v));
6080 }
6081 }
6082 else {
6083 return rb_num_coerce_bin(x, y, op);
6084 }
6085 bigdivmod(x, y, &z, 0);
6086
6087 return bignorm(z);
6088}
6089
6090VALUE
6092{
6093 return rb_big_divide(x, y, '/');
6094}
6095
6096VALUE
6098{
6099 return rb_big_divide(x, y, idDiv);
6100}
6101
6102VALUE
6104{
6105 VALUE z;
6106
6107 if (FIXNUM_P(y)) {
6108 y = rb_int2big(FIX2LONG(y));
6109 }
6110 else if (!RB_BIGNUM_TYPE_P(y)) {
6111 return rb_num_coerce_bin(x, y, '%');
6112 }
6113 bigdivmod(x, y, 0, &z);
6114
6115 return bignorm(z);
6116}
6117
6118VALUE
6120{
6121 VALUE z;
6122
6123 if (FIXNUM_P(y)) {
6124 y = rb_int2big(FIX2LONG(y));
6125 }
6126 else if (!RB_BIGNUM_TYPE_P(y)) {
6127 return rb_num_coerce_bin(x, y, rb_intern("remainder"));
6128 }
6129 bigdivrem(x, y, 0, &z);
6130
6131 return bignorm(z);
6132}
6133
6134VALUE
6136{
6137 VALUE div, mod;
6138
6139 if (FIXNUM_P(y)) {
6140 y = rb_int2big(FIX2LONG(y));
6141 }
6142 else if (!RB_BIGNUM_TYPE_P(y)) {
6143 return rb_num_coerce_bin(x, y, idDivmod);
6144 }
6145 bigdivmod(x, y, &div, &mod);
6146
6147 return rb_assoc_new(bignorm(div), bignorm(mod));
6148}
6149
6150static VALUE
6151big_shift(VALUE x, long n)
6152{
6153 if (n < 0)
6154 return big_lshift(x, 1+(unsigned long)(-(n+1)));
6155 else if (n > 0)
6156 return big_rshift(x, (unsigned long)n);
6157 return x;
6158}
6159
6161
6162static double
6163big_fdiv(VALUE x, VALUE y, long ey)
6164{
6165 VALUE z;
6166 long l, ex;
6167
6168 bigtrunc(x);
6169 l = BIGNUM_LEN(x);
6170 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6171 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6172 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6173 else if (ex > 0) ex = 0;
6174 if (ex) x = big_shift(x, ex);
6175
6176 bigdivrem(x, y, &z, 0);
6177 l = ex - ey;
6178#if SIZEOF_LONG > SIZEOF_INT
6179 {
6180 /* Visual C++ can't be here */
6181 if (l > INT_MAX) return HUGE_VAL;
6182 if (l < INT_MIN) return 0.0;
6183 }
6184#endif
6185 return ldexp(big2dbl(z), (int)l);
6186}
6187
6188static double
6189big_fdiv_int(VALUE x, VALUE y)
6190{
6191 long l, ey;
6192 bigtrunc(y);
6193 l = BIGNUM_LEN(y);
6194 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6195 ey -= DBL_BIGDIG * BITSPERDIG;
6196 if (ey) y = big_shift(y, ey);
6197 return big_fdiv(x, y, ey);
6198}
6199
6200static double
6201big_fdiv_float(VALUE x, VALUE y)
6202{
6203 int i;
6204 y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6205 return big_fdiv(x, y, i - DBL_MANT_DIG);
6206}
6207
6208double
6210{
6211 double dx, dy;
6212 VALUE v;
6213
6214 dx = big2dbl(x);
6215 if (FIXNUM_P(y)) {
6216 dy = (double)FIX2LONG(y);
6217 if (isinf(dx))
6218 return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
6219 }
6220 else if (RB_BIGNUM_TYPE_P(y)) {
6221 return big_fdiv_int(x, y);
6222 }
6223 else if (RB_FLOAT_TYPE_P(y)) {
6224 dy = RFLOAT_VALUE(y);
6225 if (isnan(dy))
6226 return dy;
6227 if (isinf(dx))
6228 return big_fdiv_float(x, y);
6229 }
6230 else {
6231 return NUM2DBL(rb_num_coerce_bin(x, y, idFdiv));
6232 }
6233 v = rb_flo_div_flo(DBL2NUM(dx), DBL2NUM(dy));
6234 return NUM2DBL(v);
6235}
6236
6237VALUE
6239{
6240 return DBL2NUM(rb_big_fdiv_double(x, y));
6241}
6242
6243VALUE
6245{
6246 double d;
6247 SIGNED_VALUE yy;
6248
6249 again:
6250 if (y == INT2FIX(0)) return INT2FIX(1);
6251 if (y == INT2FIX(1)) return x;
6252 if (RB_FLOAT_TYPE_P(y)) {
6253 d = RFLOAT_VALUE(y);
6254 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6255 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6256 }
6257 }
6258 else if (RB_BIGNUM_TYPE_P(y)) {
6259 y = bignorm(y);
6260 if (FIXNUM_P(y))
6261 goto again;
6262 rb_warn("in a**b, b may be too big");
6263 d = rb_big2dbl(y);
6264 }
6265 else if (FIXNUM_P(y)) {
6266 yy = FIX2LONG(y);
6267
6268 if (yy < 0) {
6269 x = rb_big_pow(x, INT2NUM(-yy));
6270 if (RB_INTEGER_TYPE_P(x))
6271 return rb_rational_raw(INT2FIX(1), x);
6272 else
6273 return DBL2NUM(1.0 / NUM2DBL(x));
6274 }
6275 else {
6276 VALUE z = 0;
6278 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6279 const size_t BIGLEN_LIMIT = 32*1024*1024;
6280
6281 if (xbits == (size_t)-1 ||
6282 (xbits > BIGLEN_LIMIT) ||
6283 (xbits * yy > BIGLEN_LIMIT)) {
6284 rb_warn("in a**b, b may be too big");
6285 d = (double)yy;
6286 }
6287 else {
6288 for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
6289 if (z) z = bigsq(z);
6290 if (yy & mask) {
6291 z = z ? bigtrunc(bigmul0(z, x)) : x;
6292 }
6293 }
6294 return bignorm(z);
6295 }
6296 }
6297 }
6298 else {
6299 return rb_num_coerce_bin(x, y, idPow);
6300 }
6301 return DBL2NUM(pow(rb_big2dbl(x), d));
6302}
6303
6304static VALUE
6305bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6306{
6307 VALUE z;
6308 BDIGIT *xds, *zds;
6309 long zn;
6310 long i;
6311 BDIGIT hibitsy;
6312
6313 if (y == 0) return INT2FIX(0);
6314 if (xn == 0) return hibitsx ? LONG2NUM(y) : 0;
6315 hibitsy = 0 <= y ? 0 : BDIGMAX;
6316 xds = BDIGITS(x);
6317#if SIZEOF_BDIGIT >= SIZEOF_LONG
6318 if (!hibitsy) {
6319 y &= xds[0];
6320 return LONG2NUM(y);
6321 }
6322#endif
6323
6324 zn = xn;
6325#if SIZEOF_BDIGIT < SIZEOF_LONG
6326 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6328#endif
6329
6330 z = bignew(zn, 0);
6331 zds = BDIGITS(z);
6332
6333#if SIZEOF_BDIGIT >= SIZEOF_LONG
6334 i = 1;
6335 zds[0] = xds[0] & BIGLO(y);
6336#else
6337 for (i=0; i < xn; i++) {
6338 if (y == 0 || y == -1) break;
6339 zds[i] = xds[i] & BIGLO(y);
6340 y = BIGDN(y);
6341 }
6342 for (; i < zn; i++) {
6343 if (y == 0 || y == -1) break;
6344 zds[i] = hibitsx & BIGLO(y);
6345 y = BIGDN(y);
6346 }
6347#endif
6348 for (;i < xn; i++) {
6349 zds[i] = xds[i] & hibitsy;
6350 }
6351 for (;i < zn; i++) {
6352 zds[i] = hibitsx & hibitsy;
6353 }
6354 twocomp2abs_bang(z, hibitsx && hibitsy);
6355 RB_GC_GUARD(x);
6356 return bignorm(z);
6357}
6358
6359VALUE
6361{
6362 VALUE z;
6363 BDIGIT *ds1, *ds2, *zds;
6364 long i, xn, yn, n1, n2;
6365 BDIGIT hibitsx, hibitsy;
6366 BDIGIT hibits1, hibits2;
6367 VALUE tmpv;
6368 BDIGIT tmph;
6369 long tmpn;
6370
6371 if (!RB_INTEGER_TYPE_P(y)) {
6372 return rb_num_coerce_bit(x, y, '&');
6373 }
6374
6375 hibitsx = abs2twocomp(&x, &xn);
6376 if (FIXNUM_P(y)) {
6377 return bigand_int(x, xn, hibitsx, FIX2LONG(y));
6378 }
6379 hibitsy = abs2twocomp(&y, &yn);
6380 if (xn > yn) {
6381 tmpv = x; x = y; y = tmpv;
6382 tmpn = xn; xn = yn; yn = tmpn;
6383 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6384 }
6385 n1 = xn;
6386 n2 = yn;
6387 ds1 = BDIGITS(x);
6388 ds2 = BDIGITS(y);
6389 hibits1 = hibitsx;
6390 hibits2 = hibitsy;
6391
6392 if (!hibits1)
6393 n2 = n1;
6394
6395 z = bignew(n2, 0);
6396 zds = BDIGITS(z);
6397
6398 for (i=0; i<n1; i++) {
6399 zds[i] = ds1[i] & ds2[i];
6400 }
6401 for (; i<n2; i++) {
6402 zds[i] = hibits1 & ds2[i];
6403 }
6404 twocomp2abs_bang(z, hibits1 && hibits2);
6405 RB_GC_GUARD(x);
6406 RB_GC_GUARD(y);
6407 return bignorm(z);
6408}
6409
6410static VALUE
6411bigor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6412{
6413 VALUE z;
6414 BDIGIT *xds, *zds;
6415 long zn;
6416 long i;
6417 BDIGIT hibitsy;
6418
6419 if (y == -1) return INT2FIX(-1);
6420 if (xn == 0) return hibitsx ? INT2FIX(-1) : LONG2FIX(y);
6421 hibitsy = 0 <= y ? 0 : BDIGMAX;
6422 xds = BDIGITS(x);
6423
6424 zn = BIGNUM_LEN(x);
6425#if SIZEOF_BDIGIT < SIZEOF_LONG
6426 if (zn < bdigit_roomof(SIZEOF_LONG))
6428#endif
6429 z = bignew(zn, 0);
6430 zds = BDIGITS(z);
6431
6432#if SIZEOF_BDIGIT >= SIZEOF_LONG
6433 i = 1;
6434 zds[0] = xds[0] | BIGLO(y);
6435 if (i < zn)
6436 goto y_is_fixed_point;
6437 goto finish;
6438#else
6439 for (i=0; i < xn; i++) {
6440 if (y == 0 || y == -1) goto y_is_fixed_point;
6441 zds[i] = xds[i] | BIGLO(y);
6442 y = BIGDN(y);
6443 }
6444 if (hibitsx)
6445 goto fill_hibits;
6446 for (; i < zn; i++) {
6447 if (y == 0 || y == -1) goto y_is_fixed_point;
6448 zds[i] = BIGLO(y);
6449 y = BIGDN(y);
6450 }
6451 goto finish;
6452#endif
6453
6454 y_is_fixed_point:
6455 if (hibitsy)
6456 goto fill_hibits;
6457 for (; i < xn; i++) {
6458 zds[i] = xds[i];
6459 }
6460 if (hibitsx)
6461 goto fill_hibits;
6462 for (; i < zn; i++) {
6463 zds[i] = 0;
6464 }
6465 goto finish;
6466
6467 fill_hibits:
6468 for (; i < zn; i++) {
6469 zds[i] = BDIGMAX;
6470 }
6471
6472 finish:
6473 twocomp2abs_bang(z, hibitsx || hibitsy);
6474 RB_GC_GUARD(x);
6475 return bignorm(z);
6476}
6477
6478VALUE
6480{
6481 VALUE z;
6482 BDIGIT *ds1, *ds2, *zds;
6483 long i, xn, yn, n1, n2;
6484 BDIGIT hibitsx, hibitsy;
6485 BDIGIT hibits1, hibits2;
6486 VALUE tmpv;
6487 BDIGIT tmph;
6488 long tmpn;
6489
6490 if (!RB_INTEGER_TYPE_P(y)) {
6491 return rb_num_coerce_bit(x, y, '|');
6492 }
6493
6494 hibitsx = abs2twocomp(&x, &xn);
6495 if (FIXNUM_P(y)) {
6496 return bigor_int(x, xn, hibitsx, FIX2LONG(y));
6497 }
6498 hibitsy = abs2twocomp(&y, &yn);
6499 if (xn > yn) {
6500 tmpv = x; x = y; y = tmpv;
6501 tmpn = xn; xn = yn; yn = tmpn;
6502 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6503 }
6504 n1 = xn;
6505 n2 = yn;
6506 ds1 = BDIGITS(x);
6507 ds2 = BDIGITS(y);
6508 hibits1 = hibitsx;
6509 hibits2 = hibitsy;
6510
6511 if (hibits1)
6512 n2 = n1;
6513
6514 z = bignew(n2, 0);
6515 zds = BDIGITS(z);
6516
6517 for (i=0; i<n1; i++) {
6518 zds[i] = ds1[i] | ds2[i];
6519 }
6520 for (; i<n2; i++) {
6521 zds[i] = hibits1 | ds2[i];
6522 }
6523 twocomp2abs_bang(z, hibits1 || hibits2);
6524 RB_GC_GUARD(x);
6525 RB_GC_GUARD(y);
6526 return bignorm(z);
6527}
6528
6529static VALUE
6530bigxor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6531{
6532 VALUE z;
6533 BDIGIT *xds, *zds;
6534 long zn;
6535 long i;
6536 BDIGIT hibitsy;
6537
6538 hibitsy = 0 <= y ? 0 : BDIGMAX;
6539 xds = BDIGITS(x);
6540 zn = BIGNUM_LEN(x);
6541#if SIZEOF_BDIGIT < SIZEOF_LONG
6542 if (zn < bdigit_roomof(SIZEOF_LONG))
6544#endif
6545 z = bignew(zn, 0);
6546 zds = BDIGITS(z);
6547
6548#if SIZEOF_BDIGIT >= SIZEOF_LONG
6549 i = 1;
6550 zds[0] = xds[0] ^ BIGLO(y);
6551#else
6552 for (i = 0; i < xn; i++) {
6553 zds[i] = xds[i] ^ BIGLO(y);
6554 y = BIGDN(y);
6555 }
6556 for (; i < zn; i++) {
6557 zds[i] = hibitsx ^ BIGLO(y);
6558 y = BIGDN(y);
6559 }
6560#endif
6561 for (; i < xn; i++) {
6562 zds[i] = xds[i] ^ hibitsy;
6563 }
6564 for (; i < zn; i++) {
6565 zds[i] = hibitsx ^ hibitsy;
6566 }
6567 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6568 RB_GC_GUARD(x);
6569 return bignorm(z);
6570}
6571
6572VALUE
6574{
6575 VALUE z;
6576 BDIGIT *ds1, *ds2, *zds;
6577 long i, xn, yn, n1, n2;
6578 BDIGIT hibitsx, hibitsy;
6579 BDIGIT hibits1, hibits2;
6580 VALUE tmpv;
6581 BDIGIT tmph;
6582 long tmpn;
6583
6584 if (!RB_INTEGER_TYPE_P(y)) {
6585 return rb_num_coerce_bit(x, y, '^');
6586 }
6587
6588 hibitsx = abs2twocomp(&x, &xn);
6589 if (FIXNUM_P(y)) {
6590 return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
6591 }
6592 hibitsy = abs2twocomp(&y, &yn);
6593 if (xn > yn) {
6594 tmpv = x; x = y; y = tmpv;
6595 tmpn = xn; xn = yn; yn = tmpn;
6596 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6597 }
6598 n1 = xn;
6599 n2 = yn;
6600 ds1 = BDIGITS(x);
6601 ds2 = BDIGITS(y);
6602 hibits1 = hibitsx;
6603 hibits2 = hibitsy;
6604
6605 z = bignew(n2, 0);
6606 zds = BDIGITS(z);
6607
6608 for (i=0; i<n1; i++) {
6609 zds[i] = ds1[i] ^ ds2[i];
6610 }
6611 for (; i<n2; i++) {
6612 zds[i] = hibitsx ^ ds2[i];
6613 }
6614 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6615 RB_GC_GUARD(x);
6616 RB_GC_GUARD(y);
6617 return bignorm(z);
6618}
6619
6620VALUE
6622{
6623 int lshift_p;
6624 size_t shift_numdigits;
6625 int shift_numbits;
6626
6627 for (;;) {
6628 if (FIXNUM_P(y)) {
6629 long l = FIX2LONG(y);
6630 unsigned long shift;
6631 if (0 <= l) {
6632 lshift_p = 1;
6633 shift = l;
6634 }
6635 else {
6636 lshift_p = 0;
6637 shift = 1+(unsigned long)(-(l+1));
6638 }
6639 shift_numbits = (int)(shift & (BITSPERDIG-1));
6640 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6641 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6642 }
6643 else if (RB_BIGNUM_TYPE_P(y)) {
6644 return bignorm(big_shift2(x, 1, y));
6645 }
6646 y = rb_to_int(y);
6647 }
6648}
6649
6650VALUE
6652{
6653 int lshift_p;
6654 size_t shift_numdigits;
6655 int shift_numbits;
6656
6657 for (;;) {
6658 if (FIXNUM_P(y)) {
6659 long l = FIX2LONG(y);
6660 unsigned long shift;
6661 if (0 <= l) {
6662 lshift_p = 0;
6663 shift = l;
6664 }
6665 else {
6666 lshift_p = 1;
6667 shift = 1+(unsigned long)(-(l+1));
6668 }
6669 shift_numbits = (int)(shift & (BITSPERDIG-1));
6670 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6671 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6672 }
6673 else if (RB_BIGNUM_TYPE_P(y)) {
6674 return bignorm(big_shift2(x, 0, y));
6675 }
6676 y = rb_to_int(y);
6677 }
6678}
6679
6680VALUE
6682{
6683 BDIGIT *xds;
6684 size_t shift;
6685 size_t i, s1, s2;
6686 long l;
6687 BDIGIT bit;
6688
6689 if (RB_BIGNUM_TYPE_P(y)) {
6690 if (BIGNUM_NEGATIVE_P(y))
6691 return INT2FIX(0);
6692 bigtrunc(y);
6693 if (BIGSIZE(y) > sizeof(size_t)) {
6694 out_of_range:
6695 return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
6696 }
6697#if SIZEOF_SIZE_T <= SIZEOF_LONG
6698 shift = big2ulong(y, "long");
6699#else
6700 shift = big2ull(y, "long long");
6701#endif
6702 }
6703 else {
6704 l = NUM2LONG(y);
6705 if (l < 0) return INT2FIX(0);
6706 shift = (size_t)l;
6707 }
6708 s1 = shift/BITSPERDIG;
6709 s2 = shift%BITSPERDIG;
6710 bit = (BDIGIT)1 << s2;
6711
6712 if (s1 >= BIGNUM_LEN(x)) goto out_of_range;
6713
6714 xds = BDIGITS(x);
6715 if (BIGNUM_POSITIVE_P(x))
6716 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6717 if (xds[s1] & (bit-1))
6718 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6719 for (i = 0; i < s1; i++)
6720 if (xds[i])
6721 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6722 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6723}
6724
6725VALUE
6727{
6728 st_index_t hash;
6729
6730 hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6731 return ST2FIX(hash);
6732}
6733
6734/*
6735 * call-seq:
6736 * big.coerce(numeric) -> array
6737 *
6738 * Returns an array with both a +numeric+ and a +big+ represented as Bignum
6739 * objects.
6740 *
6741 * This is achieved by converting +numeric+ to a Bignum.
6742 *
6743 * A TypeError is raised if the +numeric+ is not a Fixnum or Bignum type.
6744 *
6745 * (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
6746 */
6747
6748static VALUE
6749rb_int_coerce(VALUE x, VALUE y)
6750{
6751 if (RB_INTEGER_TYPE_P(y)) {
6752 return rb_assoc_new(y, x);
6753 }
6754 else {
6755 x = rb_Float(x);
6756 y = rb_Float(y);
6757 return rb_assoc_new(y, x);
6758 }
6759}
6760
6761VALUE
6763{
6764 if (BIGNUM_NEGATIVE_P(x)) {
6765 x = rb_big_clone(x);
6767 }
6768 return x;
6769}
6770
6771int
6773{
6774 return BIGNUM_SIGN(x);
6775}
6776
6777size_t
6779{
6780 return BIGSIZE(big);
6781}
6782
6783VALUE
6785{
6786 return SIZET2NUM(rb_big_size(big));
6787}
6788
6789VALUE
6791{
6792 int nlz_bits;
6793 size_t numbytes;
6794
6795 static const BDIGIT char_bit[1] = { CHAR_BIT };
6796 BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
6797 BDIGIT nlz_bary[1];
6798 BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
6799
6800 numbytes = rb_absint_size(big, &nlz_bits);
6801
6802 if (numbytes == 0)
6803 return LONG2FIX(0);
6804
6805 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6806 if (nlz_bits != CHAR_BIT-1) {
6807 nlz_bits++;
6808 }
6809 else {
6810 nlz_bits = 0;
6811 numbytes--;
6812 }
6813 }
6814
6815 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6816 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6817 }
6818
6819 nlz_bary[0] = nlz_bits;
6820
6821 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
6823 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6824 BARY_SUB(result_bary, result_bary, nlz_bary);
6825
6826 return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
6828}
6829
6830VALUE
6832{
6833 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6834 return Qtrue;
6835 }
6836 return Qfalse;
6837}
6838
6839VALUE
6841{
6842 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6843 return Qfalse;
6844 }
6845 return Qtrue;
6846}
6847
6848unsigned long rb_ulong_isqrt(unsigned long);
6849#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6851# ifdef ULL_TO_DOUBLE
6852# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6853# endif
6854#else
6855# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6856#endif
6857#ifndef BDIGIT_DBL_TO_DOUBLE
6858# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
6859#endif
6860
6861static BDIGIT *
6862estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
6863{
6864 enum {dbl_per_bdig = roomof(DBL_MANT_DIG,BITSPERDIG)};
6865 const int zbits = nlz(nds[len-1]);
6866 VALUE x = *xp = bignew_1(0, xn, 1); /* division may release the GVL */
6867 BDIGIT *xds = BDIGITS(x);
6868 BDIGIT_DBL d = bary2bdigitdbl(nds+len-dbl_per_bdig, dbl_per_bdig);
6869 BDIGIT lowbits = 1;
6870 int rshift = (int)((BITSPERDIG*2-zbits+(len&BITSPERDIG&1) - DBL_MANT_DIG + 1) & ~1);
6871 double f;
6872
6873 if (rshift > 0) {
6874 lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
6875 d >>= rshift;
6876 }
6877 else if (rshift < 0) {
6878 d <<= -rshift;
6879 d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
6880 }
6882 d = (BDIGIT_DBL)ceil(f);
6883 if (BDIGIT_DBL_TO_DOUBLE(d) == f) {
6884 if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
6885 ++d;
6886 }
6887 else {
6888 lowbits = 1;
6889 }
6890 rshift /= 2;
6891 rshift += (2-(len&1))*BITSPERDIG/2;
6892 if (rshift >= 0) {
6893 if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) {
6894 /* (d << rshift) does cause overflow.
6895 * example: Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)
6896 */
6897 d = ~(BDIGIT_DBL)0;
6898 }
6899 else {
6900 d <<= rshift;
6901 }
6902 }
6903 BDIGITS_ZERO(xds, xn-2);
6904 bdigitdbl2bary(&xds[xn-2], 2, d);
6905
6906 if (!lowbits) return NULL; /* special case, exact result */
6907 return xds;
6908}
6909
6910VALUE
6912{
6913 BDIGIT *nds = BDIGITS(n);
6914 size_t len = BIGNUM_LEN(n);
6915 size_t xn = (len+1) / 2;
6916 VALUE x;
6917 BDIGIT *xds;
6918
6919 if (len <= 2) {
6920 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
6921#if SIZEOF_BDIGIT > SIZEOF_LONG
6922 return ULL2NUM(sq);
6923#else
6924 return ULONG2NUM(sq);
6925#endif
6926 }
6927 else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) {
6928 size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
6929 VALUE t = bignew_1(0, tn, 1);
6930 BDIGIT *tds = BDIGITS(t);
6931 tn = BIGNUM_LEN(t);
6932
6933 /* t = n/x */
6934 while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
6935 bary_cmp(tds, tn, xds, xn) < 0) {
6936 int carry;
6937 BARY_TRUNC(tds, tn);
6938 /* x = (x+t)/2 */
6939 carry = bary_add(xds, xn, xds, xn, tds, tn);
6940 bary_small_rshift(xds, xds, xn, 1, carry);
6941 tn = BIGNUM_LEN(t);
6942 }
6943 rb_big_realloc(t, 0);
6945 }
6947 return x;
6948}
6949
6950#ifdef USE_GMP
6951static void
6952bary_powm_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, const BDIGIT *mds, size_t mn)
6953{
6954 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
6955 mpz_t z, x, y, m;
6956 size_t count;
6957 mpz_init(x);
6958 mpz_init(y);
6959 mpz_init(m);
6960 mpz_init(z);
6961 mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
6962 mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
6963 mpz_import(m, mn, -1, sizeof(BDIGIT), 0, nails, mds);
6964 mpz_powm(z, x, y, m);
6965 mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z);
6966 BDIGITS_ZERO(zds+count, zn-count);
6967 mpz_clear(x);
6968 mpz_clear(y);
6969 mpz_clear(m);
6970 mpz_clear(z);
6971}
6972#endif
6973
6974static VALUE
6975int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
6976{
6977#ifdef USE_GMP
6978 VALUE z;
6979 size_t xn, yn, mn, zn;
6980
6981 if (FIXNUM_P(x)) {
6982 x = rb_int2big(FIX2LONG(x));
6983 }
6984 if (FIXNUM_P(y)) {
6985 y = rb_int2big(FIX2LONG(y));
6986 }
6988 xn = BIGNUM_LEN(x);
6989 yn = BIGNUM_LEN(y);
6990 mn = BIGNUM_LEN(m);
6991 zn = mn;
6992 z = bignew(zn, 1);
6993 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
6994 if (nega_flg & BIGNUM_POSITIVE_P(z)) {
6995 z = rb_big_minus(z, m);
6996 }
6997 RB_GC_GUARD(x);
6998 RB_GC_GUARD(y);
6999 RB_GC_GUARD(m);
7000 return rb_big_norm(z);
7001#else
7002 VALUE tmp = LONG2FIX(1L);
7003 long yy;
7004
7005 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7006 if (RTEST(rb_int_odd_p(y))) {
7007 tmp = rb_int_mul(tmp, x);
7008 tmp = rb_int_modulo(tmp, m);
7009 }
7010 x = rb_int_mul(x, x);
7011 x = rb_int_modulo(x, m);
7012 }
7013 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7014 if (yy & 1L) {
7015 tmp = rb_int_mul(tmp, x);
7016 tmp = rb_int_modulo(tmp, m);
7017 }
7018 x = rb_int_mul(x, x);
7019 x = rb_int_modulo(x, m);
7020 }
7021
7022 if (nega_flg && rb_int_positive_p(tmp)) {
7023 tmp = rb_int_minus(tmp, m);
7024 }
7025 return tmp;
7026#endif
7027}
7028
7029/*
7030 * Integer#pow
7031 */
7032
7033static VALUE
7034int_pow_tmp1(VALUE x, VALUE y, long mm, int nega_flg)
7035{
7036 long xx = FIX2LONG(x);
7037 long tmp = 1L;
7038 long yy;
7039
7040 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7041 if (RTEST(rb_int_odd_p(y))) {
7042 tmp = (tmp * xx) % mm;
7043 }
7044 xx = (xx * xx) % mm;
7045 }
7046 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7047 if (yy & 1L) {
7048 tmp = (tmp * xx) % mm;
7049 }
7050 xx = (xx * xx) % mm;
7051 }
7052
7053 if (nega_flg && tmp) {
7054 tmp -= mm;
7055 }
7056 return LONG2FIX(tmp);
7057}
7058
7059static VALUE
7060int_pow_tmp2(VALUE x, VALUE y, long mm, int nega_flg)
7061{
7062 long tmp = 1L;
7063 long yy;
7064#ifdef DLONG
7065 const DLONG m = mm;
7066 long tmp2 = tmp;
7067 long xx = FIX2LONG(x);
7068# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7069#else
7070 const VALUE m = LONG2FIX(mm);
7071 VALUE tmp2 = LONG2FIX(tmp);
7072 VALUE xx = x;
7073# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7074#endif
7075
7076 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7077 if (RTEST(rb_int_odd_p(y))) {
7078 tmp2 = MUL_MODULO(tmp2, xx, m);
7079 }
7080 xx = MUL_MODULO(xx, xx, m);
7081 }
7082 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7083 if (yy & 1L) {
7084 tmp2 = MUL_MODULO(tmp2, xx, m);
7085 }
7086 xx = MUL_MODULO(xx, xx, m);
7087 }
7088
7089#ifdef DLONG
7090 tmp = tmp2;
7091#else
7092 tmp = FIX2LONG(tmp2);
7093#endif
7094 if (nega_flg && tmp) {
7095 tmp -= mm;
7096 }
7097 return LONG2FIX(tmp);
7098}
7099
7100/*
7101 * Document-method: Integer#pow
7102 * call-seq:
7103 * integer.pow(numeric) -> numeric
7104 * integer.pow(integer, integer) -> integer
7105 *
7106 * Returns (modular) exponentiation as:
7107 *
7108 * a.pow(b) #=> same as a**b
7109 * a.pow(b, m) #=> same as (a**b) % m, but avoids huge temporary values
7110 */
7111VALUE
7112rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
7113{
7114 rb_check_arity(argc, 1, 2);
7115
7116 if (argc == 1) {
7117 return rb_int_pow(num, argv[0]);
7118 }
7119 else {
7120 VALUE const a = num;
7121 VALUE const b = argv[0];
7122 VALUE m = argv[1];
7123 int nega_flg = 0;
7124 if ( ! RB_INTEGER_TYPE_P(b)) {
7125 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7126 }
7127 if (rb_int_negative_p(b)) {
7128 rb_raise(rb_eRangeError, "Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7129 }
7130 if (!RB_INTEGER_TYPE_P(m)) {
7131 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
7132 }
7133
7134 if (rb_int_negative_p(m)) {
7135 m = rb_int_uminus(m);
7136 nega_flg = 1;
7137 }
7138
7139 if (FIXNUM_P(m)) {
7140 long const half_val = (long)HALF_LONG_MSB;
7141 long const mm = FIX2LONG(m);
7142 if (!mm) rb_num_zerodiv();
7143 if (mm <= half_val) {
7144 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7145 }
7146 else {
7147 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7148 }
7149 }
7150 else {
7151 if (rb_bigzero_p(m)) rb_num_zerodiv();
7152 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7153 }
7154 }
7156}
7157
7158/*
7159 * Bignum objects hold integers outside the range of
7160 * Fixnum. Bignum objects are created
7161 * automatically when integer calculations would otherwise overflow a
7162 * Fixnum. When a calculation involving
7163 * Bignum objects returns a result that will fit in a
7164 * Fixnum, the result is automatically converted.
7165 *
7166 * For the purposes of the bitwise operations and <code>[]</code>, a
7167 * Bignum is treated as if it were an infinite-length
7168 * bitstring with 2's complement representation.
7169 *
7170 * While Fixnum values are immediate, Bignum
7171 * objects are not---assignment and parameter passing work with
7172 * references to objects, not the objects themselves.
7173 *
7174 */
7175
7176void
7178{
7179#ifndef RUBY_INTEGER_UNIFICATION
7181#endif
7182 /* An obsolete class, use Integer */
7185
7186 rb_define_method(rb_cInteger, "coerce", rb_int_coerce, 1);
7187
7188#ifdef USE_GMP
7189 /* The version of loaded GMP. */
7190 rb_define_const(rb_cInteger, "GMP_VERSION", rb_sprintf("GMP %s", gmp_version));
7191#endif
7192
7193 power_cache_init();
7194}
#define bad(x)
Definition: _sdbm.c:123
#define DBL_MANT_DIG
Definition: acosh.c:19
#define BDIGIT_DBL_MAX
Definition: bignum.c:84
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3547
#define RB_BIGNUM_TYPE_P(x)
Definition: bignum.c:33
VALUE rb_big_lshift(VALUE x, VALUE y)
Definition: bignum.c:6621
VALUE rb_big_even_p(VALUE num)
Definition: bignum.c:6840
#define TAKE_LOWBITS(n)
VALUE rb_big_and(VALUE x, VALUE y)
Definition: bignum.c:6360
VALUE rb_big_or(VALUE x, VALUE y)
Definition: bignum.c:6479
size_t rb_big_size(VALUE big)
Definition: bignum.c:6778
VALUE rb_big_minus(VALUE x, VALUE y)
Definition: bignum.c:5853
VALUE rb_big_modulo(VALUE x, VALUE y)
Definition: bignum.c:6103
#define U16(a)
Definition: bignum.c:173
int rb_cmpint(VALUE val, VALUE a, VALUE b)
Definition: bignum.c:2925
NORETURN(static inline void invalid_radix(int base))
VALUE rb_big_new(size_t len, int sign)
Definition: bignum.c:3014
#define reinterpret_cast(type, value)
Definition: bignum.c:1094
#define NAIVE_MUL_DIGITS
Definition: bignum.c:144
double rb_big_fdiv_double(VALUE x, VALUE y)
Definition: bignum.c:6209
VALUE rb_big_pow(VALUE x, VALUE y)
Definition: bignum.c:6244
VALUE rb_big2str_generic(VALUE x, int base)
Definition: bignum.c:5004
#define INTEGER_PACK_BYTEORDER_MASK
Definition: bignum.c:492
VALUE rb_int2big(intptr_t n)
Definition: bignum.c:3180
#define GMP_DIV_DIGITS
Definition: bignum.c:138
int rb_bigzero_p(VALUE x)
Definition: bignum.c:2919
VALUE rb_big_clone(VALUE x)
Definition: bignum.c:3020
#define BIGNUM_SET_POSITIVE_SIGN(b)
Definition: bignum.c:113
VALUE rb_big_mul_toom3(VALUE x, VALUE y)
Definition: bignum.c:2267
VALUE rb_big_comp(VALUE x)
Definition: bignum.c:5564
@ DBL_BIGDIG
Definition: bignum.c:6160
VALUE rb_uint2big(uintptr_t n)
Definition: bignum.c:3158
#define BIGSIZE(x)
Definition: bignum.c:97
#define BARY_TRUNC(ds, n)
Definition: bignum.c:126
VALUE rb_int2inum(intptr_t n)
Definition: bignum.c:3208
#define FILL_DD
VALUE rb_big_sq_fast(VALUE x)
Definition: bignum.c:1630
VALUE rb_big_plus(VALUE x, VALUE y)
Definition: bignum.c:5824
#define rb_bdigit_dbl_isqrt(x)
Definition: bignum.c:6855
VALUE rb_big2str_poweroftwo(VALUE x, int base)
Definition: bignum.c:4921
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4268
#define INTEGER_PACK_WORDORDER_MASK
Definition: bignum.c:489
#define POW2_P(x)
Definition: bignum.c:73
size_t rb_absint_size(VALUE val, int *nlz_bits_ret)
Definition: bignum.c:3247
size_t rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
Definition: bignum.c:3382
int rb_absint_singlebit_p(VALUE val)
Definition: bignum.c:3446
VALUE rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3633
#define KARATSUBA_MUL_DIGITS
Definition: bignum.c:135
unsigned long rb_big2ulong(VALUE x)
Definition: bignum.c:5125
#define U32(a)
Definition: bignum.c:174
VALUE rb_big_idiv(VALUE x, VALUE y)
Definition: bignum.c:6097
VALUE rb_big_gt(VALUE x, VALUE y)
Definition: bignum.c:5489
#define BIGDIVREM_EXTRA_WORDS
Definition: bignum.c:102
VALUE rb_big_ge(VALUE x, VALUE y)
Definition: bignum.c:5495
#define KARATSUBA_BALANCED(xn, yn)
Definition: bignum.c:131
VALUE rb_big2str(VALUE x, int base)
Definition: bignum.c:5091
VALUE rb_uint2inum(uintptr_t n)
Definition: bignum.c:3201
VALUE rb_big_aref(VALUE x, VALUE y)
Definition: bignum.c:6681
#define BIGLO(x)
Definition: bignum.c:82
#define GMP_BIG2STR_DIGITS
Definition: bignum.c:139
COMPILER_WARNING_POP VALUE rb_integer_float_eq(VALUE x, VALUE y)
Definition: bignum.c:5386
#define BDIGITS_ZERO(ptr, n)
Definition: bignum.c:117
#define BIGRAD
Definition: bignum.c:77
#define ADV(n)
void() mulfunc_t(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
Definition: bignum.c:147
VALUE rb_big_bit_length(VALUE big)
Definition: bignum.c:6790
#define BIGUP(x)
Definition: bignum.c:80
VALUE rb_big_cmp(VALUE x, VALUE y)
Definition: bignum.c:5419
VALUE rb_str2inum(VALUE str, int base)
Definition: bignum.c:4544
VALUE rb_dbl2big(double d)
Definition: bignum.c:5249
#define LSHIFTX(d, n)
Definition: bignum.c:70
VALUE rb_big_eq(VALUE x, VALUE y)
Definition: bignum.c:5524
VALUE rb_big_eql(VALUE x, VALUE y)
Definition: bignum.c:5544
VALUE rb_big_mul(VALUE x, VALUE y)
Definition: bignum.c:5933
VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
Definition: bignum.c:4352
VALUE rb_big_lt(VALUE x, VALUE y)
Definition: bignum.c:5501
#define HOST_BIGENDIAN_P
Definition: bignum.c:66
#define BIGNUM_SET_LEN(b, l)
Definition: bignum.c:2946
VALUE rb_big_remainder(VALUE x, VALUE y)
Definition: bignum.c:6119
VALUE rb_big_odd_p(VALUE num)
Definition: bignum.c:6831
#define MUL_MODULO(a, b, c)
VALUE rb_big_size_m(VALUE big)
Definition: bignum.c:6784
const char ruby_digitmap[]
Definition: bignum.c:38
VALUE rb_int_powm(int const argc, VALUE *const argv, VALUE const num)
Definition: bignum.c:7112
#define BARY_DIVMOD(q, r, x, y)
Definition: bignum.c:109
VALUE rb_str2big_normal(VALUE arg, int base, int badcheck)
Definition: bignum.c:4310
#define FILL_LOWBITS(d, numbits)
Definition: bignum.c:72
#define bignew(len, sign)
Definition: bignum.c:115
#define BDIGMAX
Definition: bignum.c:83
VALUE rb_big_mul_karatsuba(VALUE x, VALUE y)
Definition: bignum.c:1870
#define BITSPERDIG
Definition: bignum.c:76
VALUE rb_cstr2inum(const char *str, int base)
Definition: bignum.c:4538
VALUE rb_integer_float_cmp(VALUE x, VALUE y)
Definition: bignum.c:5325
#define BARY_ADD(z, x, y)
Definition: bignum.c:106
#define BIGDN(x)
Definition: bignum.c:81
VALUE rb_big_unpack(unsigned long *buf, long num_longs)
Definition: bignum.c:3223
#define MAX_BASE36_POWER_TABLE_ENTRIES
Definition: bignum.c:4647
#define BARY_SUB(z, x, y)
Definition: bignum.c:107
#define bdigit_roomof(n)
Definition: bignum.c:103
#define BIGNUM_SET_NEGATIVE_SIGN(b)
Definition: bignum.c:112
#define ASSERT_LEN()
VALUE rb_big_fdiv(VALUE x, VALUE y)
Definition: bignum.c:6238
#define TOOM3_MUL_DIGITS
Definition: bignum.c:136
VALUE rb_big_divmod(VALUE x, VALUE y)
Definition: bignum.c:6135
#define BARY_ZERO_P(x)
Definition: bignum.c:110
#define CLEAR_LOWBITS(d, numbits)
Definition: bignum.c:71
#define BDIGIT_DBL_TO_DOUBLE(n)
Definition: bignum.c:6858
VALUE rb_big_hash(VALUE x)
Definition: bignum.c:6726
VALUE rb_big_xor(VALUE x, VALUE y)
Definition: bignum.c:6573
#define BARY_ARGS(ary)
Definition: bignum.c:104
VALUE rb_big_divrem_normal(VALUE x, VALUE y)
Definition: bignum.c:2714
VALUE rb_big_div(VALUE x, VALUE y)
Definition: bignum.c:6091
STATIC_ASSERT(sizeof_bdigit_dbl, sizeof(BDIGIT_DBL)==SIZEOF_BDIGIT_DBL)
VALUE rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception)
Definition: bignum.c:4246
VALUE rb_big_norm(VALUE x)
Definition: bignum.c:3152
#define GMP_STR2BIG_DIGITS
Definition: bignum.c:140
#define TOOM3_BALANCED(xn, yn)
Definition: bignum.c:132
#define BIGZEROP(x)
Definition: bignum.c:94
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Definition: bignum.c:4012
VALUE rb_big_uminus(VALUE x)
Definition: bignum.c:5554
void rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
Definition: bignum.c:3215
VALUE rb_big_rshift(VALUE x, VALUE y)
Definition: bignum.c:6651
VALUE rb_big_isqrt(VALUE n)
Definition: bignum.c:6911
double rb_big2dbl(VALUE x)
Definition: bignum.c:5310
void rb_big_2comp(VALUE x)
Definition: bignum.c:3049
VALUE rb_big_mul_balance(VALUE x, VALUE y)
Definition: bignum.c:1689
VALUE rb_big_abs(VALUE x)
Definition: bignum.c:6762
#define SIZEOF_BDIGIT_DBL
Definition: bignum.c:42
long rb_big2long(VALUE x)
Definition: bignum.c:5140
#define BDIGIT_MSB(d)
Definition: bignum.c:79
#define BDIGITS(x)
Definition: bignum.c:75
void rb_big_resize(VALUE big, size_t len)
Definition: bignum.c:2989
#define PUSH_BITS(data, numbits)
VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags)
Definition: bignum.c:4041
void Init_Bignum(void)
Definition: bignum.c:7177
big_op_t
Definition: bignum.c:5446
@ big_op_ge
Definition: bignum.c:5448
@ big_op_gt
Definition: bignum.c:5447
@ big_op_lt
Definition: bignum.c:5449
@ big_op_le
Definition: bignum.c:5450
VALUE rb_big_mul_normal(VALUE x, VALUE y)
Definition: bignum.c:1561
unsigned long rb_ulong_isqrt(unsigned long)
int rb_big_sign(VALUE x)
Definition: bignum.c:6772
#define conv_digit(c)
Definition: bignum.c:3704
VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
Definition: bignum.c:4274
#define BARY_SHORT_MUL(z, x, y)
Definition: bignum.c:108
VALUE rb_big_le(VALUE x, VALUE y)
Definition: bignum.c:5507
void rb_cmperr(VALUE x, VALUE y)
Definition: compar.c:25
#define mod(x, y)
Definition: date_strftime.c:28
enum @73::@75::@76 mask
struct RIMemo * ptr
Definition: debug.c:65
int count
Definition: encoding.c:57
char str[HTML_ESCAPE_MAX_LEN+1]
Definition: escape.c:18
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_cInteger
Definition: ruby.h:2033
VALUE rb_eFloatDomainError
Definition: ruby.h:2077
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_bug(const char *fmt,...)
Definition: error.c:636
VALUE rb_eRangeError
Definition: error.c:928
VALUE rb_eTypeError
Definition: error.c:924
void rb_invalid_str(const char *str, const char *type)
Definition: error.c:1867
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_Float(VALUE)
Equivalent to Kernel#Float in Ruby.
Definition: object.c:3493
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
Definition: object.c:78
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE rb_to_int(VALUE)
Converts val into Integer.
Definition: object.c:3021
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition: cxxanyargs.hpp:39
void rb_num_zerodiv(void)
Definition: numeric.c:194
#define DBL_MAX_EXP
Definition: numeric.c:46
int rb_int_negative_p(VALUE num)
Definition: numeric.c:307
__uint32_t uint32_t
unsigned long rb_genrand_ulong_limited(unsigned long i)
Definition: random.c:811
#define MEMCPY(p1, p2, type, n)
#define RUBY_ALIGNOF
#define NULL
#define BDIGIT_DBL
#define NUM2DBL(x)
#define dp(v)
#define rb_cBignum
#define uint128_t
VALUE rb_str_resize(VALUE, long)
Definition: string.c:2709
void div_t div(int __numer, int __denom)
use StringValue() instead")))
#define RSTRING_LEN(str)
#define ULL2NUM(v)
#define NEWOBJ_OF(obj, type, klass, flags)
#define RTEST(v)
#define ALLOCV_END(v)
VALUE rb_ull2inum(unsigned long long)
#define COMPILER_WARNING_PUSH
#define RBASIC(obj)
void rb_must_asciicompat(VALUE)
Definition: string.c:2166
VALUE rb_ll2inum(long long)
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3891
#define INT_MIN
#define SIZEOF_LONG
#define swap16(x)
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
#define LLONG_MAX
#define PRIxBDIGIT
#define StringValuePtr(v)
__uint16_t uint16_t
__uint8_t uint8_t
#define PRIuSIZE
#define INTEGER_PACK_MSBYTE_FIRST
VALUE rb_big2str_gmp(VALUE x, int base)
#define xfree
#define INTEGER_PACK_LSBYTE_FIRST
#define bit_length(x)
#define SSIZE_MAX
#define LONG2FIX(i)
#define INTEGER_PACK_NATIVE_BYTE_ORDER
#define Qundef
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
Definition: numeric.c:446
#define CHAR_BIT
#define BIGNUM_EMBED_LEN_MAX
double yn(int, double)
double ceil(double)
#define SIZE_MAX
double frexp(double, int *)
#define RSTRING_PTR(str)
void rb_gc_register_mark_object(VALUE)
Definition: gc.c:7079
@ RB_INT_PARSE_UNDERSCORE
@ RB_INT_PARSE_DEFAULT
#define swap32(x)
#define T_BIGNUM
#define MEMCMP(p1, p2, type, n)
#define SIZEOF_INT
int int int printf(const char *__restrict__,...) __attribute__((__format__(__printf__
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1444
#define NIL_P(v)
__intptr_t intptr_t
VALUE rb_int_pow(VALUE x, VALUE y)
Definition: numeric.c:4111
#define numberof(array)
#define DBL2NUM(dbl)
void rb_deprecate_constant(VALUE mod, const char *name)
Definition: variable.c:2958
#define HALF_LONG_MSB
#define LONG_MAX
VALUE rb_fix2str(VALUE, int)
Definition: numeric.c:3513
#define REALLOC_N(var, type, n)
#define COMPILER_WARNING_POP
#define BIGNUM_SET_SIGN(b, sign)
const char size_t n
#define rb_usascii_str_new(str, len)
#define MEMZERO(p, type, n)
#define BDIGIT_DBL_SIGNED
VALUE rb_rational_raw(VALUE, VALUE)
Definition: rational.c:1951
void rb_str_set_len(VALUE, long)
Definition: string.c:2692
unsigned long VALUE
VALUE rb_int_uminus(VALUE num)
Definition: numeric.c:3484
#define BIGNUM_NEGATE(b)
#define swap64(x)
#define SIZEOF_BDIGIT
#define INTEGER_PACK_FORCE_BIGNUM
double modf(double, double *)
VALUE rb_big_mul_gmp(VALUE x, VALUE y)
unsigned long long rb_big2ull(VALUE)
#define PRI_SIZE_PREFIX
#define isinf(__x)
VALUE rb_flo_div_flo(VALUE x, VALUE y)
Definition: numeric.c:1110
uint32_t i
#define roomof(x, y)
double y0(double)
#define char
#define RB_FLOAT_TYPE_P(obj)
#define isnan(__x)
#define RSTRING_GETMEM(str, ptrvar, lenvar)
__inline__ const void *__restrict__ size_t len
__uint64_t uint64_t
#define INTEGER_PACK_BIG_ENDIAN
#define ALLOC_N(type, n)
#define BIGNUM_EMBED_LEN_MASK
#define OBJ_FREEZE(x)
#define INT2NUM(x)
#define LONG2NUM(x)
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2891
#define long
#define RB_GC_GUARD(v)
VALUE rb_dbl_complex_new_polar_pi(double abs, double ang)
Definition: complex.c:667
#define PRIsVALUE
#define SIZEOF_SIZE_T
void * memset(void *, int, size_t)
const char * s2
#define rb_funcall(recv, mid, argc,...)
#define FIX2INT(x)
int VALUE v
#define BIGNUM_LEN(b)
double pow(double, double)
int ffs(int) __attribute__((__const__))
Definition: ffs.c:6
VALUE rb_num_coerce_bit(VALUE, VALUE, ID)
Definition: numeric.c:4431
#define rb_usascii_str_new2
#define BIGNUM_EMBED_FLAG
void rb_thread_check_ints(void)
Definition: thread.c:1361
#define rb_intern(str)
#define INT_MAX
#define UNREACHABLE_RETURN(val)
int rb_int_positive_p(VALUE num)
Definition: numeric.c:301
#define INTEGER_PACK_2COMP
#define int128_t
#define ALLOCV_N(type, v, n)
#define FIXNUM_MIN
#define RBASIC_SET_CLASS_RAW(obj, cls)
#define RFLOAT_VALUE(v)
double ldexp(double, int)
#define TRUE
#define FALSE
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:453
unsigned int size
#define Qtrue
#define MEMMOVE(p1, p2, type, n)
long unsigned int size_t
#define BDIGIT
long long rb_big2ll(VALUE)
#define FIXNUM_MAX
#define INTEGER_PACK_NEGATIVE
#define POSFIXABLE(f)
#define NEGFIXABLE(f)
struct rb_call_cache buf
__uintptr_t uintptr_t
#define Qnil
#define Qfalse
#define SIGNED_VALUE
st_data_t st_index_t
VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck)
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3654
#define ULONG2NUM(x)
#define INTEGER_PACK_MSWORD_FIRST
#define FIXABLE(f)
#define BIGNUM_SIGN(b)
#define FL_WB_PROTECTED
#define INT2FIX(i)
VALUE rb_int_odd_p(VALUE num)
Definition: numeric.c:3227
VALUE rb_num_coerce_relop(VALUE, VALUE, ID)
Definition: numeric.c:461
void rb_gc_force_recycle(VALUE)
Definition: gc.c:7027
#define MJIT_FUNC_EXPORTED
#define BIGNUM_NEGATIVE_P(b)
const VALUE * argv
_ssize_t ssize_t
#define SIZEOF_LONG_LONG
double sqrt(double)
__inline__ int
#define FIXNUM_P(f)
#define CLASS_OF(v)
#define RB_INTEGER_TYPE_P(obj)
unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Definition: util.c:97
int puts(const char *)
#define DLONG
#define assert
#define rb_check_arity
#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
#define BIGNUM_EMBED_LEN_SHIFT
VALUE rb_int128t2big(__int128 n)
#define RGENGC_WB_PROTECTED_BIGNUM
VALUE rb_sprintf(const char *,...) __attribute__((format(printf
unsigned long ID
#define SIZEOF_INT128_T
const char *void rb_warning(const char *,...) __attribute__((format(printf
#define BIGNUM_POSITIVE_P(b)
#define VALGRIND_MAKE_MEM_UNDEFINED(p, n)
#define LONG_MIN
#define ISSPACE(c)
#define FIX2LONG(x)
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define COMPILER_WARNING_IGNORED(flag)
#define RBIGNUM(obj)
#define SIZEOF_VALUE
#define LLONG_MIN
#define HUGE_VAL
#define ST2FIX(h)
#define INTEGER_PACK_LSWORD_FIRST
#define SIZET2NUM(v)
VALUE rb_big_divrem_gmp(VALUE x, VALUE y)
#define LONG_LONG
#define RSHIFT(x, y)
#define StringValueCStr(v)
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3704
#define lo
Definition: siphash.c:21
#define uint64_t
Definition: siphash.h:15
#define f
#define r2
#define r1
#define r3
VALUE result
Definition: bignum.c:4712
int hbase2_numdigits
Definition: bignum.c:4711
BDIGIT_DBL hbase2
Definition: bignum.c:4710
char * ptr
Definition: bignum.c:4713
volatile VALUE stop
Definition: bignum.c:2537
BDIGIT * zds
Definition: bignum.c:2536
size_t yn
Definition: bignum.c:2535
BDIGIT * yds
Definition: bignum.c:2536
size_t zn
Definition: bignum.c:2535
#define RB_NOGVL_UBF_ASYNC_SAFE
Definition: thread.h:26
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Definition: thread.c:1451
#define neg(x)
Definition: time.c:141