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