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