12#include "ruby/internal/config.h"
27#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_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"
46#include "ruby_assert.h"
57static const bool debug_integer_pack = (
58#ifdef DEBUG_INTEGER_PACK
65const char ruby_digitmap[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
67#ifndef SIZEOF_BDIGIT_DBL
68# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
69# define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
71# define SIZEOF_BDIGIT_DBL SIZEOF_LONG
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);
83#if SIZEOF_BDIGIT < SIZEOF_LONG
84STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
86STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
90# define HOST_BIGENDIAN_P 1
92# define HOST_BIGENDIAN_P 0
95#define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
96#define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
97#define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
98#define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
99#define POW2_P(x) (((x)&((x)-1))==0)
101#define BDIGITS(x) (BIGNUM_DIGITS(x))
102#define BITSPERDIG (SIZEOF_BDIGIT*CHAR_BIT)
103#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
104#define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
105#define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
106#define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
107#define BIGDN(x) RSHIFT((x),BITSPERDIG)
108#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
109#define BDIGMAX ((BDIGIT)(BIGRAD-1))
110#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
112#if SIZEOF_BDIGIT == 2
113# define swap_bdigit(x) swap16(x)
114#elif SIZEOF_BDIGIT == 4
115# define swap_bdigit(x) swap32(x)
116#elif SIZEOF_BDIGIT == 8
117# define swap_bdigit(x) swap64(x)
120#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
121 (BDIGITS(x)[0] == 0 && \
122 (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
123#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
124 BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
125 (size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
126 rb_absint_size(x, NULL))
128#define BIGDIVREM_EXTRA_WORDS 1
129#define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT)
130#define BARY_ARGS(ary) ary, numberof(ary)
132#define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
133#define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
134#define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
135#define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
136#define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
138#define BIGNUM_SET_NEGATIVE_SIGN(b) BIGNUM_SET_SIGN(b, 0)
139#define BIGNUM_SET_POSITIVE_SIGN(b) BIGNUM_SET_SIGN(b, 1)
141#define bignew(len,sign) bignew_1(rb_cInteger,(len),(sign))
143#define BDIGITS_ZERO(ptr, n) do { \
144 BDIGIT *bdigitz_zero_ptr = (ptr); \
145 size_t bdigitz_zero_n = (n); \
146 while (bdigitz_zero_n) { \
147 *bdigitz_zero_ptr++ = 0; \
152#define BARY_TRUNC(ds, n) do { \
153 while (0 < (n) && (ds)[(n)-1] == 0) \
157#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
158#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
160#define GMP_MUL_DIGITS 20
161#define KARATSUBA_MUL_DIGITS 70
162#define TOOM3_MUL_DIGITS 150
164#define GMP_DIV_DIGITS 20
165#define GMP_BIG2STR_DIGITS 20
166#define GMP_STR2BIG_DIGITS 20
168# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
170# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
173typedef 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);
175static mulfunc_t bary_mul_toom3_start;
176static mulfunc_t bary_mul_karatsuba_start;
177static BDIGIT bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y);
183static inline VALUE power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret);
185#if SIZEOF_BDIGIT <= SIZEOF_INT
186static int nlz(BDIGIT x) {
return nlz_int((
unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGIT) * CHAR_BIT; }
187#elif SIZEOF_BDIGIT <= SIZEOF_LONG
188static int nlz(BDIGIT x) {
return nlz_long((
unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
189#elif SIZEOF_BDIGIT <= SIZEOF_LONG_LONG
190static int nlz(BDIGIT x) {
return nlz_long_long((
unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
191#elif SIZEOF_BDIGIT <= SIZEOF_INT128_T
192static int nlz(BDIGIT x) {
return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGIT) * CHAR_BIT; }
195#define U16(a) ((uint16_t)(a))
196#define U32(a) ((uint32_t)(a))
198#define U64(a,b) (((uint64_t)(a) << 32) | (b))
201#define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
248#if SIZEOF_BDIGIT_DBL == 2
249static const int maxpow16_exp[35] = {
250 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
251 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
253static const uint16_t maxpow16_num[35] = {
254 U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
255 U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
256 U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
257 U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
258 U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
259 U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
260 U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
261 U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
262 U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
264#elif SIZEOF_BDIGIT_DBL == 4
265static const int maxpow32_exp[35] = {
266 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
267 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
269static const uint32_t maxpow32_num[35] = {
270 U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
271 U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
272 U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
273 U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
274 U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
275 U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
276 U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
277 U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
278 U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
280#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
281static const int maxpow64_exp[35] = {
282 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
283 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
286static const uint64_t maxpow64_num[35] = {
287 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
288 U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
289 U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
290 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
291 U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
292 U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
293 U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
294 U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
295 U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
296 U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
297 U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
298 U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
299 U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
300 U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
301 U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
302 U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
303 U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
304 U64(0x41c21cb8,0xe1000000),
306#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
307static const int maxpow128_exp[35] = {
308 127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
309 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
312static const uint128_t maxpow128_num[35] = {
313 U128(0x80000000,0x00000000,0x00000000,0x00000000),
314 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
315 U128(0x40000000,0x00000000,0x00000000,0x00000000),
316 U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
317 U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
318 U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
319 U128(0x40000000,0x00000000,0x00000000,0x00000000),
320 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
321 U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
322 U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
323 U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
324 U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
325 U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
326 U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
327 U128(0x10000000,0x00000000,0x00000000,0x00000000),
328 U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
329 U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
330 U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
331 U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
332 U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
333 U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
334 U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
335 U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
336 U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
337 U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
338 U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
339 U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
340 U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
341 U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
342 U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
343 U128(0x20000000,0x00000000,0x00000000,0x00000000),
344 U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
345 U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
346 U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
347 U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
352maxpow_in_bdigit_dbl(
int base,
int *exp_ret)
360#if SIZEOF_BDIGIT_DBL == 2
361 maxpow = maxpow16_num[base-2];
362 exponent = maxpow16_exp[base-2];
363#elif SIZEOF_BDIGIT_DBL == 4
364 maxpow = maxpow32_num[base-2];
365 exponent = maxpow32_exp[base-2];
366#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
367 maxpow = maxpow64_num[base-2];
368 exponent = maxpow64_exp[base-2];
369#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
370 maxpow = maxpow128_num[base-2];
371 exponent = maxpow128_exp[base-2];
375 while (maxpow <= BDIGIT_DBL_MAX / base) {
386static inline BDIGIT_DBL
387bary2bdigitdbl(
const BDIGIT *ds,
size_t n)
392 return ds[0] | BIGUP(ds[1]);
399bdigitdbl2bary(BDIGIT *ds,
size_t n, BDIGIT_DBL num)
404 ds[1] = (BDIGIT)BIGDN(num);
408bary_cmp(
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
419 for (i = 0; i < xn; i++)
420 if (xds[xn - i - 1] != yds[yn - i - 1])
424 return xds[xn - i - 1] < yds[yn - i - 1] ? -1 : 1;
428bary_small_lshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift)
434 for (i=0; i<n; i++) {
435 num = num | (BDIGIT_DBL)*xds++ << shift;
443bary_small_rshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift, BDIGIT higher_bdigit)
450 num = BIGUP(higher_bdigit);
451 for (i = 0; i < n; i++) {
452 BDIGIT x = xds[n - i - 1];
453 num = (num | x) >> shift;
454 zds[n - i - 1] = BIGLO(num);
460bary_zero_p(
const BDIGIT *xds,
size_t xn)
465 if (xds[--xn])
return 0;
471bary_neg(BDIGIT *ds,
size_t n)
474 for (i = 0; i < n; i++)
475 ds[n - i - 1] = BIGLO(~ds[n - i - 1]);
479bary_2comp(BDIGIT *ds,
size_t n)
482 for (i = 0; i < n; i++) {
490 ds[i] = BIGLO(~ds[i] + 1);
493 ds[i] = BIGLO(~ds[i]);
499bary_swap(BDIGIT *ds,
size_t num_bdigits)
502 BDIGIT *p2 = ds + num_bdigits - 1;
503 for (; p1 < p2; p1++, p2--) {
510#define INTEGER_PACK_WORDORDER_MASK \
511 (INTEGER_PACK_MSWORD_FIRST | \
512 INTEGER_PACK_LSWORD_FIRST)
513#define INTEGER_PACK_BYTEORDER_MASK \
514 (INTEGER_PACK_MSBYTE_FIRST | \
515 INTEGER_PACK_LSBYTE_FIRST | \
516 INTEGER_PACK_NATIVE_BYTE_ORDER)
519validate_integer_pack_format(
size_t numwords,
size_t wordsize,
size_t nails,
int flags,
int supported_flags)
521 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
522 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
524 if (flags & ~supported_flags) {
525 rb_raise(rb_eArgError,
"unsupported flags specified");
527 if (wordorder_bits == 0) {
529 rb_raise(rb_eArgError,
"word order not specified");
533 rb_raise(rb_eArgError,
"unexpected word order");
534 if (byteorder_bits == 0) {
535 rb_raise(rb_eArgError,
"byte order not specified");
540 rb_raise(rb_eArgError,
"unexpected byte order");
542 rb_raise(rb_eArgError,
"invalid wordsize: %"PRI_SIZE_PREFIX
"u", wordsize);
543 if (SSIZE_MAX < wordsize)
544 rb_raise(rb_eArgError,
"too big wordsize: %"PRI_SIZE_PREFIX
"u", wordsize);
545 if (wordsize <= nails / CHAR_BIT)
546 rb_raise(rb_eArgError,
"too big nails: %"PRI_SIZE_PREFIX
"u", nails);
547 if (SIZE_MAX / wordsize < numwords)
548 rb_raise(rb_eArgError,
"too big numwords * wordsize: %"PRI_SIZE_PREFIX
"u * %"PRI_SIZE_PREFIX
"u", numwords, wordsize);
552integer_pack_loop_setup(
553 size_t numwords,
size_t wordsize,
size_t nails,
int flags,
554 size_t *word_num_fullbytes_ret,
555 int *word_num_partialbits_ret,
556 size_t *word_start_ret,
557 ssize_t *word_step_ret,
558 size_t *word_last_ret,
559 size_t *byte_start_ret,
562 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
563 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
564 size_t word_num_fullbytes;
565 int word_num_partialbits;
572 word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
573 if (word_num_partialbits == CHAR_BIT)
574 word_num_partialbits = 0;
575 word_num_fullbytes = wordsize - (nails / CHAR_BIT);
576 if (word_num_partialbits != 0) {
577 word_num_fullbytes--;
581 word_start = wordsize*(numwords-1);
582 word_step = -(ssize_t)wordsize;
587 word_step = wordsize;
588 word_last = wordsize*(numwords-1);
592#ifdef WORDS_BIGENDIAN
599 byte_start = wordsize-1;
607 *word_num_partialbits_ret = word_num_partialbits;
608 *word_num_fullbytes_ret = word_num_fullbytes;
609 *word_start_ret = word_start;
610 *word_step_ret = word_step;
611 *word_last_ret = word_last;
612 *byte_start_ret = byte_start;
613 *byte_step_ret = byte_step;
617integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
619 if (*dpp < *dep && BITSPERDIG <= (
int)
sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
620 *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
621 *numbits_in_dd_p += BITSPERDIG;
623 else if (*dpp == *dep) {
625 *numbits_in_dd_p = (int)
sizeof(*ddp) * CHAR_BIT;
629static inline BDIGIT_DBL
630integer_pack_take_lowbits(
int n, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
633 ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
635 *numbits_in_dd_p -= n;
639#if !defined(WORDS_BIGENDIAN)
641bytes_2comp(
unsigned char *buf,
size_t len)
644 for (i = 0; i <
len; i++) {
645 signed char c = buf[i];
647 unsigned int e = d & 0xFF;
650 for (i = 0; i <
len; i++) {
660bary_pack(
int sign, BDIGIT *ds,
size_t num_bdigits,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
663 unsigned char *buf, *bufend;
666 de = ds + num_bdigits;
668 validate_integer_pack_format(numwords, wordsize, nails, flags,
677 while (dp < de && de[-1] == 0)
685 MEMZERO(words,
unsigned char, numwords * wordsize);
688 if (nails == 0 && numwords == 1) {
689 int need_swap = wordsize != 1 &&
695 *((
unsigned char *)words) = (
unsigned char)(d = dp[0]);
696 return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
698#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
699 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
700 uint16_t u = (uint16_t)(d = dp[0]);
701 if (need_swap) u = swap16(u);
702 *((uint16_t *)words) = u;
703 return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
706#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
707 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
708 uint32_t u = (uint32_t)(d = dp[0]);
709 if (need_swap) u = swap32(u);
710 *((uint32_t *)words) = u;
711 return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
714#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
715 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
716 uint64_t u = (uint64_t)(d = dp[0]);
717 if (need_swap) u = swap64(u);
718 *((uint64_t *)words) = u;
719 return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
726 *((
unsigned char *)words) = (
unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
727 return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
729#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
730 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
731 uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
732 if (need_swap) u = swap16(u);
733 *((uint16_t *)words) = u;
734 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
735 (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
738#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
739 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
740 uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
741 if (need_swap) u = swap32(u);
742 *((uint32_t *)words) = u;
743 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
744 (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
747#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
748 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
749 uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
750 if (need_swap) u = swap64(u);
751 *((uint64_t *)words) = u;
752 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
753 (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
758#if !defined(WORDS_BIGENDIAN)
759 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
762 size_t src_size = (de - dp) * SIZEOF_BDIGIT;
763 size_t dst_size = numwords * wordsize;
765 while (0 < src_size && ((
unsigned char *)ds)[src_size-1] == 0)
767 if (src_size <= dst_size) {
768 MEMCPY(words, dp,
char, src_size);
769 MEMZERO((
char*)words + src_size,
char, dst_size - src_size);
772 MEMCPY(words, dp,
char, dst_size);
776 int zero_p = bytes_2comp(words, dst_size);
777 if (zero_p && overflow) {
778 unsigned char *p = (
unsigned char *)dp;
779 if (dst_size == src_size-1 &&
790 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
791 wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words %
RUBY_ALIGNOF(BDIGIT) == 0) {
792 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
793 size_t src_num_bdigits = de - dp;
794 size_t dst_num_bdigits = numwords * bdigits_per_word;
799 if (src_num_bdigits <= dst_num_bdigits) {
800 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
801 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
804 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
808 int zero_p = bary_2comp(words, dst_num_bdigits);
809 if (zero_p && overflow &&
810 dst_num_bdigits == src_num_bdigits-1 &&
811 dp[dst_num_bdigits] == 1)
814 if (msbytefirst_p != HOST_BIGENDIAN_P) {
816 for (i = 0; i < dst_num_bdigits; i++) {
817 BDIGIT d = ((BDIGIT*)words)[i];
818 ((BDIGIT*)words)[i] = swap_bdigit(d);
821 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
824 for (i = 0; i < numwords; i++) {
825 bary_swap(p, bdigits_per_word);
826 p += bdigits_per_word;
830 bary_swap(words, dst_num_bdigits);
839 bufend = buf + numwords * wordsize;
846 if (de - dp == 1 && dp[0] == 1)
853 memset(buf,
'\0', bufend - buf);
855 else if (dp < de && buf < bufend) {
856 int word_num_partialbits;
857 size_t word_num_fullbytes;
863 size_t word_start, word_last;
864 unsigned char *wordp, *last_wordp;
868 integer_pack_loop_setup(numwords, wordsize, nails, flags,
869 &word_num_fullbytes, &word_num_partialbits,
870 &word_start, &word_step, &word_last, &byte_start, &byte_step);
872 wordp = buf + word_start;
873 last_wordp = buf + word_last;
879 integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
880#define TAKE_LOWBITS(n) \
881 integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
884 size_t index_in_word = 0;
885 unsigned char *bytep = wordp + byte_start;
886 while (index_in_word < word_num_fullbytes) {
888 *bytep = TAKE_LOWBITS(CHAR_BIT);
892 if (word_num_partialbits) {
894 *bytep = TAKE_LOWBITS(word_num_partialbits);
898 while (index_in_word < wordsize) {
904 if (wordp == last_wordp)
911 if (dp != de || 1 < dd) {
922 while (dp < de && *dp == 0)
934 int word_num_partialbits;
935 size_t word_num_fullbytes;
941 size_t word_start, word_last;
942 unsigned char *wordp, *last_wordp;
944 unsigned int partialbits_mask;
947 integer_pack_loop_setup(numwords, wordsize, nails, flags,
948 &word_num_fullbytes, &word_num_partialbits,
949 &word_start, &word_step, &word_last, &byte_start, &byte_step);
951 partialbits_mask = (1 << word_num_partialbits) - 1;
954 wordp = buf + word_start;
955 last_wordp = buf + word_last;
959 size_t index_in_word = 0;
960 unsigned char *bytep = wordp + byte_start;
961 while (index_in_word < word_num_fullbytes) {
962 carry += (
unsigned char)~*bytep;
963 *bytep = (
unsigned char)carry;
968 if (word_num_partialbits) {
969 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
970 *bytep = carry & partialbits_mask;
971 carry >>= word_num_partialbits;
976 if (wordp == last_wordp)
989integer_unpack_num_bdigits_small(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
992 size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
993 size_t num_bdigits = roomof(num_bits, BITSPERDIG);
994 *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
999integer_unpack_num_bdigits_generic(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1006 size_t num_bytes1 = wordsize * numwords;
1009 size_t q1 = numwords / CHAR_BIT;
1010 size_t r1 = numwords % CHAR_BIT;
1013 size_t num_bytes2 = num_bytes1 - nails * q1;
1016 size_t q2 = nails / CHAR_BIT;
1017 size_t r2 = nails % CHAR_BIT;
1020 size_t num_bytes3 = num_bytes2 - q2 * r1;
1023 size_t q3 = num_bytes3 / BITSPERDIG;
1024 size_t r3 = num_bytes3 % BITSPERDIG;
1027 size_t num_digits1 = CHAR_BIT * q3;
1040 if (CHAR_BIT * r3 >= r1 * r2) {
1041 size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
1042 size_t q4 = tmp1 / BITSPERDIG;
1043 int r4 = (int)(tmp1 % BITSPERDIG);
1044 size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
1049 size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
1050 size_t q4 = tmp1 / BITSPERDIG;
1051 int r4 = (int)(tmp1 % BITSPERDIG);
1052 size_t num_digits2 = num_digits1 - q4;
1059integer_unpack_num_bdigits(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1063 if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
1064 num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
1065 if (debug_integer_pack) {
1067 size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
1074 num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
1080integer_unpack_push_bits(
int data,
int numbits, BDIGIT_DBL *ddp,
int *numbits_in_dd_p, BDIGIT **dpp)
1082 (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
1083 *numbits_in_dd_p += numbits;
1084 while (BITSPERDIG <= *numbits_in_dd_p) {
1085 *(*dpp)++ = BIGLO(*ddp);
1087 *numbits_in_dd_p -= BITSPERDIG;
1092integer_unpack_single_bdigit(BDIGIT u,
size_t size,
int flags, BDIGIT *dp)
1097 ((size == SIZEOF_BDIGIT && u == 0) ? -2 : -1) :
1098 ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
1100 u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
1110#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
1111#define reinterpret_cast(type, value) (type) \
1112 __builtin_assume_aligned((value), sizeof(*(type)NULL));
1114#define reinterpret_cast(type, value) (type)value
1118bary_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)
1121 const unsigned char *buf = words;
1126 de = dp + num_bdigits;
1129 if (nails == 0 && numwords == 1) {
1130 int need_swap = wordsize != 1 &&
1133 if (wordsize == 1) {
1134 return integer_unpack_single_bdigit(*(uint8_t *)buf,
sizeof(uint8_t), flags, dp);
1136#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
1137 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
1138 uint16_t u = *reinterpret_cast(
const uint16_t *, buf);
1139 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
1142#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
1143 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
1144 uint32_t u = *reinterpret_cast(
const uint32_t *, buf);
1145 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
1148#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
1149 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
1150 uint64_t u = *reinterpret_cast(
const uint64_t *, buf);
1151 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
1154#undef reinterpret_cast
1156#if !defined(WORDS_BIGENDIAN)
1157 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1160 size_t src_size = numwords * wordsize;
1161 size_t dst_size = num_bdigits * SIZEOF_BDIGIT;
1162 MEMCPY(dp, words,
char, src_size);
1166 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1167 zero_p = bary_2comp(dp, num_bdigits);
1168 sign = zero_p ? -2 : -1;
1170 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
1171 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1172 bary_2comp(dp, num_bdigits);
1176 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1181 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1187 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1188 wordsize % SIZEOF_BDIGIT == 0) {
1189 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
1193 MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
1194 if (mswordfirst_p) {
1195 bary_swap(dp, num_bdigits);
1197 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
1200 for (i = 0; i < numwords; i++) {
1201 bary_swap(p, bdigits_per_word);
1202 p += bdigits_per_word;
1205 if (msbytefirst_p != HOST_BIGENDIAN_P) {
1207 for (p = dp; p < de; p++) {
1209 *p = swap_bdigit(d);
1214 int zero_p = bary_2comp(dp, num_bdigits);
1215 sign = zero_p ? -2 : -1;
1217 else if (BDIGIT_MSB(de[-1])) {
1218 bary_2comp(dp, num_bdigits);
1232 if (num_bdigits != 0) {
1233 int word_num_partialbits;
1234 size_t word_num_fullbytes;
1240 size_t word_start, word_last;
1241 const unsigned char *wordp, *last_wordp;
1245 integer_pack_loop_setup(numwords, wordsize, nails, flags,
1246 &word_num_fullbytes, &word_num_partialbits,
1247 &word_start, &word_step, &word_last, &byte_start, &byte_step);
1249 wordp = buf + word_start;
1250 last_wordp = buf + word_last;
1255#define PUSH_BITS(data, numbits) \
1256 integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
1259 size_t index_in_word = 0;
1260 const unsigned char *bytep = wordp + byte_start;
1261 while (index_in_word < word_num_fullbytes) {
1262 PUSH_BITS(*bytep, CHAR_BIT);
1266 if (word_num_partialbits) {
1267 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
1272 if (wordp == last_wordp)
1291 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
1292 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
1301 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
1304 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
1310 if (sign == -1 && num_bdigits != 0) {
1311 bary_2comp(bdigits, num_bdigits);
1319bary_unpack(BDIGIT *bdigits,
size_t num_bdigits,
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
1321 size_t num_bdigits0;
1325 validate_integer_pack_format(numwords, wordsize, nails, flags,
1336 num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
1340 sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
1342 if (num_bdigits0 < num_bdigits) {
1343 BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
1345 bdigits[num_bdigits0] = 1;
1351bary_subb(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int borrow)
1353 BDIGIT_DBL_SIGNED num;
1360 sn = xn < yn ? xn : yn;
1362 num = borrow ? -1 : 0;
1363 for (i = 0; i < sn; i++) {
1364 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
1365 zds[i] = BIGLO(num);
1369 for (; i < xn; i++) {
1370 if (num == 0)
goto num_is_zero;
1372 zds[i] = BIGLO(num);
1377 for (; i < yn; i++) {
1379 zds[i] = BIGLO(num);
1383 if (num == 0)
goto num_is_zero;
1384 for (; i < zn; i++) {
1390 if (xds == zds && xn == zn)
1392 for (; i < xn; i++) {
1395 for (; i < zn; i++) {
1402bary_sub(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1404 return bary_subb(zds, zn, xds, xn, yds, yn, 0);
1408bary_sub_one(BDIGIT *zds,
size_t zn)
1410 return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
1414bary_addc(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int carry)
1424 tds = xds; xds = yds; yds = tds;
1425 i = xn; xn = yn; yn = i;
1428 num = carry ? 1 : 0;
1429 for (i = 0; i < xn; i++) {
1430 num += (BDIGIT_DBL)xds[i] + yds[i];
1431 zds[i] = BIGLO(num);
1434 for (; i < yn; i++) {
1435 if (num == 0)
goto num_is_zero;
1437 zds[i] = BIGLO(num);
1440 for (; i < zn; i++) {
1441 if (num == 0)
goto num_is_zero;
1442 zds[i] = BIGLO(num);
1448 if (yds == zds && yn == zn)
1450 for (; i < yn; i++) {
1453 for (; i < zn; i++) {
1460bary_add(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1462 return bary_addc(zds, zn, xds, xn, yds, yn, 0);
1466bary_add_one(BDIGIT *ds,
size_t n)
1469 for (i = 0; i < n; i++) {
1470 BDIGIT_DBL n = ds[i];
1480bary_mul_single(BDIGIT *zds,
size_t zn, BDIGIT x, BDIGIT y)
1486 n = (BDIGIT_DBL)x * y;
1487 bdigitdbl2bary(zds, 2, n);
1488 BDIGITS_ZERO(zds + 2, zn - 2);
1492bary_muladd_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1504 for (j = 0; j < yn; j++) {
1505 BDIGIT_DBL ee = n + dd * yds[j];
1516 for (; j < zn; j++) {
1526static BDIGIT_DBL_SIGNED
1527bigdivrem_mulsub(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1531 BDIGIT_DBL_SIGNED num;
1540 BDIGIT_DBL_SIGNED ee;
1541 t2 += (BDIGIT_DBL)yds[i] * x;
1542 ee = num - BIGLO(t2);
1543 num = (BDIGIT_DBL_SIGNED)zds[i] + ee;
1544 if (ee) zds[i] = BIGLO(num);
1548 num -= (BDIGIT_DBL_SIGNED)t2;
1549 num += (BDIGIT_DBL_SIGNED)zds[yn];
1554bary_mulsub_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1556 BDIGIT_DBL_SIGNED num;
1560 num = bigdivrem_mulsub(zds, zn, x, yds, yn);
1561 zds[yn] = BIGLO(num);
1568bary_mul_normal(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1574 BDIGITS_ZERO(zds, zn);
1575 for (i = 0; i < xn; i++) {
1576 bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
1583 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1584 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1585 bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
1596bary_sq_fast(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn)
1605 BDIGITS_ZERO(zds, zn);
1610 for (i = 0; i < xn-1; i++) {
1611 v = (BDIGIT_DBL)xds[i];
1614 c = (BDIGIT_DBL)zds[i + i] + v * v;
1615 zds[i + i] = BIGLO(c);
1620 for (j = i + 1; j < xn; j++) {
1621 w = (BDIGIT_DBL)xds[j];
1622 c += (BDIGIT_DBL)zds[i + j] + vl * w;
1623 zds[i + j] = BIGLO(c);
1629 c += (BDIGIT_DBL)zds[i + xn];
1630 zds[i + xn] = BIGLO(c);
1633 zds[i + xn + 1] += (BDIGIT)c;
1638 v = (BDIGIT_DBL)xds[i];
1641 c = (BDIGIT_DBL)zds[i + i] + v * v;
1642 zds[i + i] = BIGLO(c);
1645 zds[i + xn] += BIGLO(c);
1650rb_big_sq_fast(
VALUE x)
1652 size_t xn = BIGNUM_LEN(x), zn = 2 * xn;
1653 VALUE z = bignew(zn, 1);
1654 bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
1660max_size(
size_t a,
size_t b)
1662 return (a > b ? a : b);
1667bary_mul_balance_with_mulfunc(BDIGIT *
const zds,
const size_t zn,
1668 const BDIGIT *
const xds,
const size_t xn,
1669 const BDIGIT *
const yds,
const size_t yn,
1670 BDIGIT *wds,
size_t wn, mulfunc_t *
const mulfunc)
1677 RUBY_ASSERT(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
1679 BDIGITS_ZERO(zds, xn);
1688 const size_t r = yn % xn;
1689 if (2*xn + yn + max_size(xn-r, r) > zn) {
1697 const size_t r = (xn > (yn - n) ? (yn - n) : xn);
1698 const size_t tn = (xn + r);
1699 if (2 * (xn + r) <= zn - n) {
1700 BDIGIT *
const tds = zds + n + xn + r;
1701 mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
1702 BDIGITS_ZERO(zds + n + xn, r);
1703 bary_add(zds + n, tn,
1708 BDIGIT *
const tds = zds + n;
1715 rb_bug(
"wds is not enough: %" PRIdSIZE
" for %" PRIdSIZE, wn, xn);
1718 MEMCPY(wds, zds + n, BDIGIT, xn);
1719 mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
1720 bary_add(zds + n, tn,
1726 BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
1735 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1736 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1737 bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
1745bary_mul_karatsuba(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1750 int sub_p, borrow, carry1, carry2, carry3;
1756 const BDIGIT *xds0, *xds1, *yds0, *yds1;
1757 BDIGIT *zds0, *zds1, *zds2, *zds3;
1763 sq = xds == yds && xn == yn;
1813 if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
1814 bary_2comp(zds0, n);
1822 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
1825 if (bary_sub(wds, n, yds, n, yds+n, n)) {
1832 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
1839 borrow = !bary_2comp(zds1, 2*n);
1843 MEMCPY(wds, zds1, BDIGIT, n);
1847 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
1851 carry1 = bary_add(wds, n, wds, n, zds0, n);
1852 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
1856 carry2 = bary_add(zds1, n, zds1, n, wds, n);
1860 MEMCPY(wds, zds2, BDIGIT, n);
1864 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
1868 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
1872 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
1876 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
1881 bary_add_one(zds2, zn-2*n);
1883 if (carry1 + carry3 - borrow < 0)
1884 bary_sub_one(zds3, zn-3*n);
1885 else if (carry1 + carry3 - borrow > 0) {
1886 BDIGIT c = carry1 + carry3 - borrow;
1887 bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
1902 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1903 bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
1906 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1916 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1917 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1918 if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
1919 rb_raise(rb_eArgError,
"unexpected bignum length for karatsuba");
1920 bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
1927bary_mul_toom3(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1934 size_t x0n;
const BDIGIT *x0ds;
1935 size_t x1n;
const BDIGIT *x1ds;
1936 size_t x2n;
const BDIGIT *x2ds;
1937 size_t y0n;
const BDIGIT *y0ds;
1938 size_t y1n;
const BDIGIT *y1ds;
1939 size_t y2n;
const BDIGIT *y2ds;
1941 size_t u1n; BDIGIT *u1ds;
int u1p;
1942 size_t u2n; BDIGIT *u2ds;
int u2p;
1943 size_t u3n; BDIGIT *u3ds;
int u3p;
1945 size_t v1n; BDIGIT *v1ds;
int v1p;
1946 size_t v2n; BDIGIT *v2ds;
int v2p;
1947 size_t v3n; BDIGIT *v3ds;
int v3p;
1949 size_t t0n; BDIGIT *t0ds;
int t0p;
1950 size_t t1n; BDIGIT *t1ds;
int t1p;
1951 size_t t2n; BDIGIT *t2ds;
int t2p;
1952 size_t t3n; BDIGIT *t3ds;
int t3p;
1953 size_t t4n; BDIGIT *t4ds;
int t4p;
1955 size_t z0n; BDIGIT *z0ds;
1956 size_t z1n; BDIGIT *z1ds;
int z1p;
1957 size_t z2n; BDIGIT *z2ds;
int z2p;
1958 size_t z3n; BDIGIT *z3ds;
int z3p;
1959 size_t z4n; BDIGIT *z4ds;
1961 size_t zzn; BDIGIT *zzds;
1963 int sq = xds == yds && xn == yn;
1981 wnc += (t1n = 2*n+2);
1982 wnc += (t2n = 2*n+2);
1983 wnc += (t3n = 2*n+2);
1986 wnc += (z1n = 2*n+1);
1987 wnc += (z2n = 2*n+1);
1988 wnc += (z3n = 2*n+1);
1995 u1ds = wds; wds += u1n;
1996 u2ds = wds; wds += u2n;
1997 u3ds = wds; wds += u3n;
1999 v1ds = wds; wds += v1n;
2000 v2ds = wds; wds += v2n;
2001 v3ds = wds; wds += v3n;
2003 t0ds = wds; wds += t0n;
2004 t1ds = wds; wds += t1n;
2005 t2ds = wds; wds += t2n;
2006 t3ds = wds; wds += t3n;
2007 t4ds = wds; wds += t4n;
2009 z1ds = wds; wds += z1n;
2010 z2ds = wds; wds += z2n;
2011 z3ds = wds; wds += z3n;
2077 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
2081 if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
2082 bary_2comp(u2ds, u2n);
2090 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
2095 bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
2097 else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
2098 bary_2comp(u3ds, u3n);
2101 bary_small_lshift(u3ds, u3ds, u3n, 1);
2103 bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
2105 else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
2106 bary_2comp(u3ds, u3n);
2111 v1n = u1n; v1ds = u1ds; v1p = u1p;
2112 v2n = u2n; v2ds = u2ds; v2p = u2p;
2113 v3n = u3n; v3ds = u3ds; v3p = u3p;
2117 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
2122 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
2123 bary_2comp(v2ds, v2n);
2128 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
2133 bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
2135 else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
2136 bary_2comp(v3ds, v3n);
2139 bary_small_lshift(v3ds, v3ds, v3n, 1);
2141 bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
2143 else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
2144 bary_2comp(v3ds, v3n);
2150 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
2154 bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
2160 bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
2166 bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
2172 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
2180 z0n = t0n; z0ds = t0ds;
2183 z4n = t4n; z4ds = t4ds;
2188 if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
2189 bary_2comp(z3ds, z3n);
2195 bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
2197 bigdivrem_single(z3ds, z3ds, z3n, 3);
2202 if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
2203 bary_2comp(z1ds, z1n);
2209 bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
2211 bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
2216 if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
2217 bary_2comp(z2ds, z2n);
2223 bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
2229 if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
2230 bary_2comp(z3ds, z3n);
2236 bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
2238 bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
2240 bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
2243 if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
2244 bary_2comp(z3ds, z3n);
2251 bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
2254 if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
2255 bary_2comp(z2ds, z2n);
2261 if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
2262 bary_2comp(z2ds, z2n);
2267 bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
2272 if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
2273 bary_2comp(z1ds, z1n);
2278 bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
2285 MEMCPY(zzds, z0ds, BDIGIT, z0n);
2286 BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
2287 MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
2288 BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
2290 bary_add(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2292 bary_sub(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2294 bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2296 bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2298 bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2300 bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2302 BARY_TRUNC(zzds, zzn);
2303 MEMCPY(zds, zzds, BDIGIT, zzn);
2304 BDIGITS_ZERO(zds + zzn, zn - zzn);
2313 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2314 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2315 if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
2316 rb_raise(rb_eArgError,
"unexpected bignum length for toom3");
2317 bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
2325bdigits_to_mpz(mpz_t mp,
const BDIGIT *digits,
size_t len)
2327 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2328 mpz_import(mp,
len, -1,
sizeof(BDIGIT), 0, nails, digits);
2332bdigits_from_mpz(mpz_t mp, BDIGIT *digits,
size_t *
len)
2334 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2335 mpz_export(digits,
len, -1,
sizeof(BDIGIT), 0, nails, mp);
2339bary_mul_gmp(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2349 bdigits_to_mpz(x, xds, xn);
2350 if (xds == yds && xn == yn) {
2354 bdigits_to_mpz(y, yds, yn);
2357 bdigits_from_mpz(z, zds, &count);
2358 BDIGITS_ZERO(zds+count, zn-count);
2367 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2368 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2369 bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
2377bary_short_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2381 if (xn == 1 && yn == 1) {
2382 bary_mul_single(zds, zn, xds[0], yds[0]);
2385 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2392bary_sparse_p(
const BDIGIT *ds,
size_t n)
2396 if ( ds[2 * n / 5]) c++;
2397 if (c <= 1 && ds[ n / 2]) c++;
2398 if (c <= 1 && ds[3 * n / 5]) c++;
2400 return (c <= 1) ? 1 : 0;
2404bary_mul_precheck(BDIGIT **zdsp,
size_t *znp,
const BDIGIT **xdsp,
size_t *xnp,
const BDIGIT **ydsp,
size_t *ynp)
2408 BDIGIT *zds = *zdsp;
2410 const BDIGIT *xds = *xdsp;
2412 const BDIGIT *yds = *ydsp;
2420 if (xds[xn-1] == 0) {
2436 if (yds[yn-1] == 0) {
2452 BDIGITS_ZERO(zds, nlsz);
2461 tds = xds; xds = yds; yds = tds;
2462 tn = xn; xn = yn; yn = tn;
2468 BDIGITS_ZERO(zds, zn);
2473 MEMCPY(zds, yds, BDIGIT, yn);
2474 BDIGITS_ZERO(zds+yn, zn-yn);
2477 if (POW2_P(xds[0])) {
2478 zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
2479 BDIGITS_ZERO(zds+yn+1, zn-yn-1);
2482 if (yn == 1 && yds[0] == 1) {
2484 BDIGITS_ZERO(zds+1, zn-1);
2487 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2502bary_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)
2505 if (xn < KARATSUBA_MUL_DIGITS) {
2510 if (bary_sparse_p(xds, xn))
goto normal;
2511 if (bary_sparse_p(yds, yn)) {
2512 bary_short_mul(zds, zn, yds, yn, xds, xn);
2517 if (!KARATSUBA_BALANCED(xn, yn)) {
2518 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
2523 bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
2527 if (xds == yds && xn == yn) {
2528 bary_sq_fast(zds, zn, xds, xn);
2531 bary_short_mul(zds, zn, xds, xn, yds, yn);
2536bary_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 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2541 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2545bary_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 if (xn < TOOM3_MUL_DIGITS) {
2548 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2552 if (!TOOM3_BALANCED(xn, yn)) {
2553 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
2557 bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
2561bary_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 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2566 bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2570bary_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2573 if (xn < NAIVE_MUL_DIGITS) {
2574 if (xds == yds && xn == yn)
2575 bary_sq_fast(zds, zn, xds, xn);
2577 bary_short_mul(zds, zn, xds, xn, yds, yn);
2582 if (yn < NAIVE_MUL_DIGITS) {
2583 bary_short_mul(zds, zn, yds, yn, xds, xn);
2589 bary_mul_gmp(zds, zn, xds, xn, yds, yn);
2591 bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
2598 volatile VALUE stop;
2602bigdivrem1(
void *ptr)
2605 size_t yn = bds->yn;
2606 size_t zn = bds->zn;
2607 BDIGIT *yds = bds->yds, *zds = bds->zds;
2608 BDIGIT_DBL_SIGNED num;
2616 if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
2617 else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
2619 num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
2624 num = bary_add(zds+zn-(yn+1), yn,
2638rb_big_stop(
void *ptr)
2645bigdivrem_single1(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
2652 bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
2658 t2 = x_higher_bdigit;
2659 for (i = 0; i < xn; i++) {
2660 t2 = BIGUP(t2) + xds[xn - i - 1];
2661 qds[xn - i - 1] = (BDIGIT)(t2 / y);
2669bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y)
2671 return bigdivrem_single1(qds, xds, xn, 0, y);
2675bigdivrem_restoring(BDIGIT *zds,
size_t zn, BDIGIT *yds,
size_t yn)
2684 for (ynzero = 0; !yds[ynzero]; ynzero++);
2686 if (ynzero+1 == yn) {
2688 r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
2693 bds.yn = yn - ynzero;
2694 bds.zds = zds + ynzero;
2695 bds.yds = yds + ynzero;
2697 bds.zn = zn - ynzero;
2698 if (bds.zn > 10000 || bds.yn > 10000) {
2703 if (bds.stop ==
Qtrue) {
2714bary_divmod_normal(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2721 RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2725 zn = xn + BIGDIVREM_EXTRA_WORDS;
2727 shift = nlz(yds[yn-1]);
2730 int alloc_z = !qds || qn < zn;
2731 if (alloc_y && alloc_z) {
2732 yyds =
ALLOCV_N(BDIGIT, tmpyz, yn+zn);
2736 yyds = alloc_y ?
ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
2737 zds = alloc_z ?
ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
2739 zds[xn] = bary_small_lshift(zds, xds, xn, shift);
2740 bary_small_lshift(yyds, yds, yn, shift);
2743 if (qds && zn <= qn)
2747 MEMCPY(zds, xds, BDIGIT, xn);
2751 yyds = (BDIGIT *)yds;
2754 bigdivrem_restoring(zds, zn, yyds, yn);
2758 bary_small_rshift(rds, zds, yn, shift, 0);
2760 MEMCPY(rds, zds, BDIGIT, yn);
2761 BDIGITS_ZERO(rds+yn, rn-yn);
2766 MEMMOVE(qds, zds+yn, BDIGIT, j);
2767 BDIGITS_ZERO(qds+j, qn-j);
2777 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2778 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2781 BARY_TRUNC(yds, yn);
2784 BARY_TRUNC(xds, xn);
2786 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2789 qn = xn + BIGDIVREM_EXTRA_WORDS;
2790 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2794 r = bignew(rn, BIGNUM_SIGN(x));
2797 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2810bary_divmod_gmp(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2815 RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2822 if (qds) mpz_init(q);
2823 if (rds) mpz_init(r);
2825 bdigits_to_mpz(x, xds, xn);
2826 bdigits_to_mpz(y, yds, yn);
2829 mpz_fdiv_q(q, x, y);
2832 mpz_fdiv_r(r, x, y);
2835 mpz_fdiv_qr(q, r, x, y);
2842 bdigits_from_mpz(q, qds, &count);
2843 BDIGITS_ZERO(qds+count, qn-count);
2848 bdigits_from_mpz(r, rds, &count);
2849 BDIGITS_ZERO(rds+count, rn-count);
2857 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2858 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2861 BARY_TRUNC(yds, yn);
2864 BARY_TRUNC(xds, xn);
2866 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2870 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2874 r = bignew(rn, BIGNUM_SIGN(x));
2877 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2890bary_divmod_branch(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2893 if (GMP_DIV_DIGITS < xn) {
2894 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2898 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2902bary_divmod(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2907 BARY_TRUNC(yds, yn);
2911 BARY_TRUNC(xds, xn);
2913 BDIGITS_ZERO(qds, qn);
2914 BDIGITS_ZERO(rds, rn);
2918 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
2919 MEMCPY(rds, xds, BDIGIT, xn);
2920 BDIGITS_ZERO(rds+xn, rn-xn);
2921 BDIGITS_ZERO(qds, qn);
2924 MEMCPY(qds, xds, BDIGIT, xn);
2925 BDIGITS_ZERO(qds+xn, qn-xn);
2926 rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
2927 BDIGITS_ZERO(rds+1, rn-1);
2929 else if (xn == 2 && yn == 2) {
2930 BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
2931 BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
2932 BDIGIT_DBL q = x / y;
2933 BDIGIT_DBL r = x % y;
2935 qds[1] = BIGLO(BIGDN(q));
2936 BDIGITS_ZERO(qds+2, qn-2);
2938 rds[1] = BIGLO(BIGDN(r));
2939 BDIGITS_ZERO(rds+2, rn-2);
2942 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
2949 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2962 rb_cmperr_reason(a, b,
"comparator returned nil");
2966 if (l > 0)
return 1;
2967 if (l < 0)
return -1;
2970 if (RB_BIGNUM_TYPE_P(val)) {
2971 if (BIGZEROP(val))
return 0;
2972 if (BIGNUM_SIGN(val))
return 1;
2980#define BIGNUM_SET_LEN(b,l) \
2981 (BIGNUM_EMBED_P(b) ? \
2982 (void)(RBASIC(b)->flags = \
2983 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2984 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2985 (void)(RBIGNUM(b)->as.heap.len = (l)))
2988big_embed_capa(
VALUE big)
2990 size_t size = rb_gc_obj_slot_size(big) - offsetof(
struct RBignum, as.ary);
2992 size_t capa = size /
sizeof(BDIGIT);
2998big_embed_size(
size_t capa)
3000 size_t size = offsetof(
struct RBignum, as.ary) + (
sizeof(BDIGIT) *
capa);
3001 if (size <
sizeof(
struct RBignum)) {
3002 size =
sizeof(
struct RBignum);
3008big_embeddable_p(
size_t capa)
3010 if (
capa > BIGNUM_EMBED_LEN_MAX) {
3013 return rb_gc_size_allocatable_p(big_embed_size(
capa));
3017rb_big_realloc(
VALUE big,
size_t len)
3020 size_t embed_capa = big_embed_capa(big);
3022 if (BIGNUM_EMBED_P(big)) {
3023 if (embed_capa <
len) {
3025 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, embed_capa);
3026 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
3027 RBIGNUM(big)->as.heap.digits = ds;
3032 if (
len <= embed_capa) {
3033 ds = RBIGNUM(big)->as.heap.digits;
3034 size_t old_len = RBIGNUM(big)->as.heap.len;
3036 BIGNUM_SET_LEN(big,
len);
3037 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)RBIGNUM(big)->as.ary, embed_capa *
sizeof(BDIGIT));
3039 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT,
len);
3040 SIZED_FREE_N(ds, old_len);
3044 if (BIGNUM_LEN(big) == 0) {
3045 RBIGNUM(big)->as.heap.digits =
ALLOC_N(BDIGIT,
len);
3047 else if (BIGNUM_LEN(big) !=
len) {
3048 SIZED_REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT,
len, BIGNUM_LEN(big));
3057 rb_big_realloc(big,
len);
3058 BIGNUM_SET_LEN(big,
len);
3062bignew_1(
VALUE klass,
size_t len,
int sign)
3066 if (big_embeddable_p(
len)) {
3067 size_t size = big_embed_size(
len);
3069 NEWOBJ_OF(big,
struct RBignum, klass,
3073 BIGNUM_SET_SIGN(bigv, sign);
3074 BIGNUM_SET_LEN(bigv,
len);
3075 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)big->as.ary,
len *
sizeof(BDIGIT));
3078 NEWOBJ_OF(big,
struct RBignum, klass,
3081 BIGNUM_SET_SIGN(bigv, sign);
3083 big->as.heap.len =
len;
3090rb_big_new(
size_t len,
int sign)
3092 VALUE obj = bignew(
len, sign != 0);
3093 memset(BIGNUM_DIGITS(obj), 0,
len *
sizeof(BDIGIT));
3100 size_t len = BIGNUM_LEN(x);
3103 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT,
len);
3108big_extend_carry(
VALUE x)
3110 rb_big_resize(x, BIGNUM_LEN(x)+1);
3111 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3118 long i = BIGNUM_LEN(x);
3119 BDIGIT *ds = BDIGITS(x);
3121 if (bary_2comp(ds, i)) {
3122 big_extend_carry(x);
3133abs2twocomp(
VALUE *xp,
long *n_ret)
3136 long n = BIGNUM_LEN(x);
3137 BDIGIT *ds = BDIGITS(x);
3142 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3144 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3145 bary_2comp(BDIGITS(z), n);
3154twocomp2abs_bang(
VALUE x,
int hibits)
3156 BIGNUM_SET_SIGN(x, !hibits);
3165 size_t len = BIGNUM_LEN(x);
3166 BDIGIT *ds = BDIGITS(x);
3168 if (
len == 0)
return x;
3169 while (--
len && !ds[
len]);
3170 if (BIGNUM_LEN(x) >
len+1) {
3171 rb_big_resize(x,
len+1);
3179 size_t n = BIGNUM_LEN(x);
3180 BDIGIT *ds = BDIGITS(x);
3181#if SIZEOF_BDIGIT < SIZEOF_LONG
3189 if (n == 0)
return INT2FIX(0);
3191#if SIZEOF_BDIGIT < SIZEOF_LONG
3192 if (
sizeof(
long)/SIZEOF_BDIGIT < n)
3198 u = (
unsigned long)(BIGUP(u) + ds[i]);
3208 if (BIGNUM_POSITIVE_P(x)) {
3216 rb_big_resize(x, n);
3223 if (RB_BIGNUM_TYPE_P(x)) {
3236rb_uint2big(uintptr_t n)
3240 BDIGIT *digits = BDIGITS(big);
3242#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3246 digits[i] = BIGLO(n);
3252 while (--i && !digits[i]) ;
3253 BIGNUM_SET_LEN(big, i+1);
3258rb_int2big(intptr_t n)
3265 u = 1 + (
VALUE)(-(n + 1));
3271 big = rb_uint2big(u);
3273 BIGNUM_SET_NEGATIVE_SIGN(big);
3279rb_uint2inum(uintptr_t n)
3282 return rb_uint2big(n);
3286rb_int2inum(intptr_t n)
3289 return rb_int2big(n);
3293rb_big_pack(
VALUE val,
unsigned long *buf,
long num_longs)
3295 rb_integer_pack(val, buf, num_longs,
sizeof(
long), 0,
3301rb_big_unpack(
unsigned long *buf,
long num_longs)
3303 return rb_integer_unpack(buf, num_longs,
sizeof(
long), 0,
3325rb_absint_size(
VALUE val,
int *nlz_bits_ret)
3329 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3331 int num_leading_zeros;
3340#if SIZEOF_BDIGIT >= SIZEOF_LONG
3345 for (i = 0; i < numberof(fixbuf); i++) {
3346 fixbuf[i] = BIGLO(v);
3352 de = fixbuf + numberof(fixbuf);
3356 de = dp + BIGNUM_LEN(val);
3358 while (dp < de && de[-1] == 0)
3365 num_leading_zeros = nlz(de[-1]);
3367 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3368 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3372absint_numwords_small(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3374 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3375 size_t div = val_numbits / word_numbits;
3376 size_t mod = val_numbits % word_numbits;
3379 numwords = mod == 0 ? div : div + 1;
3380 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3381 *nlz_bits_ret = nlz_bits;
3386absint_numwords_generic(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3388 static const BDIGIT char_bit[1] = { CHAR_BIT };
3389 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(numbytes))];
3390 BDIGIT val_numbits_bary[bdigit_roomof(
sizeof(numbytes) + 1)];
3391 BDIGIT nlz_bits_in_msbyte_bary[1];
3392 BDIGIT word_numbits_bary[bdigit_roomof(
sizeof(word_numbits))];
3393 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3394 BDIGIT mod_bary[numberof(word_numbits_bary)];
3395 BDIGIT one[1] = { 1 };
3401 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3410 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
3412 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3413 if (nlz_bits_in_msbyte)
3414 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3415 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1,
sizeof(word_numbits), 0,
3417 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3418 if (BARY_ZERO_P(mod_bary)) {
3422 BARY_ADD(div_bary, div_bary, one);
3423 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1,
sizeof(mod), 0,
3425 nlz_bits = word_numbits - mod;
3427 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1,
sizeof(numwords), 0,
3431#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3436 *nlz_bits_ret = nlz_bits;
3460rb_absint_numwords(
VALUE val,
size_t word_numbits,
size_t *nlz_bits_ret)
3463 int nlz_bits_in_msbyte;
3465 size_t nlz_bits = 0;
3467 if (word_numbits == 0)
3470 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3472 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3473 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3474 if (debug_integer_pack) {
3475 size_t numwords0, nlz_bits0;
3476 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3483 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3485 if (numwords == (
size_t)-1)
3489 *nlz_bits_ret = nlz_bits;
3527 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3537#if SIZEOF_BDIGIT >= SIZEOF_LONG
3542 for (i = 0; i < numberof(fixbuf); i++) {
3543 fixbuf[i] = BIGLO(v);
3549 de = fixbuf + numberof(fixbuf);
3553 de = dp + BIGNUM_LEN(val);
3555 while (dp < de && de[-1] == 0)
3557 while (dp < de && dp[0] == 0)
3624rb_integer_pack(
VALUE val,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3629 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3642#if SIZEOF_BDIGIT >= SIZEOF_LONG
3647 for (i = 0; i < numberof(fixbuf); i++) {
3648 fixbuf[i] = BIGLO(v);
3654 num_bdigits = numberof(fixbuf);
3657 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3659 num_bdigits = BIGNUM_LEN(val);
3662 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3710rb_integer_unpack(
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3717 BDIGIT fixbuf[2] = { 0, 0 };
3719 validate_integer_pack_format(numwords, wordsize, nails, flags,
3730 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3732 if (LONG_MAX-1 < num_bdigits)
3733 rb_raise(rb_eArgError,
"too big to unpack as an integer");
3739 val = bignew((
long)num_bdigits, 0);
3742 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3746 big_extend_carry(val);
3748 else if (num_bdigits == numberof(fixbuf)) {
3749 val = bignew((
long)num_bdigits+1, 0);
3750 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3751 BDIGITS(val)[num_bdigits++] = 1;
3754 ds[num_bdigits++] = 1;
3759 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3764 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3766 return LONG2FIX((
long)-(BDIGIT_DBL_SIGNED)u);
3767 val = bignew((
long)num_bdigits, 0 <= sign);
3768 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3772 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3774 BIGNUM_SET_SIGN(val, 0 <= sign);
3777 return bigtrunc(val);
3778 return bignorm(val);
3781#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3783NORETURN(
static inline void invalid_radix(
int base));
3784NORETURN(
static inline void invalid_integer(
VALUE s));
3787valid_radix_p(
int base)
3789 return (1 < base && base <= 36);
3793invalid_radix(
int base)
3795 rb_raise(rb_eArgError,
"invalid radix %d", base);
3799invalid_integer(
VALUE s)
3801 rb_raise(rb_eArgError,
"invalid value for Integer(): %+"PRIsVALUE, s);
3805str2big_scan_digits(
const char *s,
const char *str,
int base,
int badcheck,
size_t *num_digits_p, ssize_t *len_p)
3808 size_t num_digits = 0;
3809 const char *digits_start = str;
3810 const char *digits_end = str;
3811 ssize_t
len = *len_p;
3821 if (badcheck && *str ==
'_')
return FALSE;
3823 while ((c = *str++) != 0) {
3826 if (badcheck)
return FALSE;
3829 nondigit = (char) c;
3831 else if ((c = conv_digit(c)) < 0 || c >= base) {
3839 if (
len > 0 && !--
len)
break;
3841 if (badcheck && nondigit)
return FALSE;
3842 if (badcheck &&
len) {
3844 while (*str &&
ISSPACE(*str)) {
3846 if (
len > 0 && !--
len)
break;
3852 *num_digits_p = num_digits;
3853 *len_p = digits_end - digits_start;
3860 const char *digits_start,
3861 const char *digits_end,
3874 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3875 z = bignew(num_bdigits, sign);
3879 for (p = digits_end; digits_start < p; p--) {
3880 if ((c = conv_digit(p[-1])) < 0)
3882 dd |= (BDIGIT_DBL)c << numbits;
3883 numbits += bits_per_digit;
3884 if (BITSPERDIG <= numbits) {
3887 numbits -= BITSPERDIG;
3893 RUBY_ASSERT((
size_t)(dp - BDIGITS(z)) == num_bdigits);
3901 const char *digits_start,
3902 const char *digits_end,
3915 z = bignew(num_bdigits, sign);
3917 BDIGITS_ZERO(zds, num_bdigits);
3919 for (p = digits_start; p < digits_end; p++) {
3920 if ((c = conv_digit(*p)) < 0)
3926 num += (BDIGIT_DBL)zds[i]*base;
3927 zds[i++] = BIGLO(num);
3945 const char *digits_start,
3946 const char *digits_end,
3949 int digits_per_bdigits_dbl,
3955 BDIGIT *uds, *vds, *tds;
3957 BDIGIT_DBL current_base;
3959 int power_level = 0;
3966 uds =
ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3967 vds = uds + num_bdigits;
3969 powerv = power_cache_get_power(base, power_level, NULL);
3974 m = digits_per_bdigits_dbl;
3975 if (num_digits < (
size_t)m)
3976 m = (int)num_digits;
3977 for (p = digits_end; digits_start < p; p--) {
3978 if ((c = conv_digit(p[-1])) < 0)
3980 dd = dd + c * current_base;
3981 current_base *= base;
3985 uds[i++] = BIGLO(dd);
3986 uds[i++] = (BDIGIT)BIGDN(dd);
3988 m = digits_per_bdigits_dbl;
3989 if (num_digits < (
size_t)m)
3990 m = (
int)num_digits;
3995 for (unit = 2; unit < num_bdigits; unit *= 2) {
3996 for (i = 0; i < num_bdigits; i += unit*2) {
3997 if (2*unit <= num_bdigits - i) {
3998 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
3999 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
4001 else if (unit <= num_bdigits - i) {
4002 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
4003 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
4006 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
4010 powerv = power_cache_get_power(base, power_level, NULL);
4015 BARY_TRUNC(uds, num_bdigits);
4016 z = bignew(num_bdigits, sign);
4017 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
4029 const char *digits_start,
4030 const char *digits_end,
4043 buf =
ALLOCV_N(
char, tmps, num_digits+1);
4045 for (q = digits_start; q < digits_end; q++) {
4046 if (conv_digit(*q) < 0)
4053 mpz_set_str(mz, buf, base);
4055 z = bignew(zn, sign);
4057 bdigits_from_mpz(mz, BDIGITS(z), &count);
4058 BDIGITS_ZERO(zds+count, zn-count);
4068static VALUE rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base);
4087rb_cstr_to_inum(
const char *str,
int base,
int badcheck)
4090 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4116rb_int_parse_cstr(
const char *str, ssize_t
len,
char **endp,
size_t *ndigits,
4117 int base,
int flags)
4119 const char *
const s = str;
4127 const char *digits_start, *digits_end;
4128 size_t num_digits = 0;
4130 const ssize_t len0 =
len;
4131 const int badcheck = !endp;
4134 if (len > 0 && len <= (n)) goto bad; \
4138#define ASSERT_LEN() do {\
4139 RUBY_ASSERT(len != 0); \
4140 if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
4146 if (
len && (flags & RB_INT_PARSE_SIGN)) {
4149 if (str[0] ==
'+') {
4152 else if (str[0] ==
'-') {
4159 if (str[0] ==
'0' &&
len > 1) {
4181 else if (base < -1) {
4188 else if (
len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4191 else if (base == 2) {
4192 if (str[0] ==
'0' && (str[1] ==
'b'||str[1] ==
'B')) {
4196 else if (base == 8) {
4197 if (str[0] ==
'0' && (str[1] ==
'o'||str[1] ==
'O')) {
4201 else if (base == 10) {
4202 if (str[0] ==
'0' && (str[1] ==
'd'||str[1] ==
'D')) {
4206 else if (base == 16) {
4207 if (str[0] ==
'0' && (str[1] ==
'x'||str[1] ==
'X')) {
4211 if (!valid_radix_p(base)) {
4212 invalid_radix(base);
4215 num_digits = str - s;
4216 if (*str ==
'0' &&
len != 1) {
4218 const char *end =
len < 0 ? NULL : str +
len;
4220 while ((c = *++str) ==
'0' ||
4221 ((flags & RB_INT_PARSE_UNDERSCORE) && c ==
'_')) {
4230 if (str == end)
break;
4233 if (end)
len = end - str;
4237 if (c < 0 || c >= base) {
4238 if (!badcheck && num_digits) z =
INT2FIX(0);
4242 if (ndigits) *ndigits = num_digits;
4243 val = ruby_scan_digits(str,
len, base, &num_digits, &ov);
4245 const char *end = &str[num_digits];
4246 if (num_digits > 0 && *end ==
'_' && (flags & RB_INT_PARSE_UNDERSCORE))
4248 if (endp) *endp = (
char *)end;
4249 if (ndigits) *ndigits += num_digits;
4251 if (num_digits == 0)
return Qnil;
4252 while (
len < 0 ? *end : end < str +
len) {
4261 long result = -(long)val;
4266 VALUE big = rb_uint2big(val);
4267 BIGNUM_SET_SIGN(big, sign);
4268 return bignorm(big);
4274 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4276 if (endp) *endp = (
char *)(str +
len);
4277 if (ndigits) *ndigits += num_digits;
4278 digits_end = digits_start +
len;
4281 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4282 bit_length(base-1));
4285 int digits_per_bdigits_dbl;
4286 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4287 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4290 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4291 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4296 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4297 z = str2big_normal(sign, digits_start, digits_end,
4301 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4302 num_bdigits, digits_per_bdigits_dbl, base);
4309 if (endp) *endp = (
char *)str;
4310 if (ndigits) *ndigits = num_digits;
4315rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base)
4317 return rb_int_parse_cstr(str,
len, endp, NULL, base,
4318 RB_INT_PARSE_DEFAULT);
4322rb_str_convert_to_inum(
VALUE str,
int base,
int badcheck,
int raise_exception)
4332 ret = rb_cstr_parse_inum(s,
len, (badcheck ? NULL : &end), base);
4335 if (!raise_exception)
return Qnil;
4336 invalid_integer(str);
4344rb_str_to_inum(
VALUE str,
int base,
int badcheck)
4346 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4350rb_str2big_poweroftwo(
VALUE arg,
int base,
int badcheck)
4353 const char *s, *str;
4354 const char *digits_start, *digits_end;
4359 if (!valid_radix_p(base) || !POW2_P(base)) {
4360 invalid_radix(base);
4365 len = RSTRING_LEN(arg);
4373 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4374 invalid_integer(arg);
4375 digits_end = digits_start +
len;
4377 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4378 bit_length(base-1));
4386rb_str2big_normal(
VALUE arg,
int base,
int badcheck)
4389 const char *s, *str;
4390 const char *digits_start, *digits_end;
4395 int digits_per_bdigits_dbl;
4398 if (!valid_radix_p(base)) {
4399 invalid_radix(base);
4404 len = RSTRING_LEN(arg);
4405 if (
len > 0 && *str ==
'-') {
4412 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4413 invalid_integer(arg);
4414 digits_end = digits_start +
len;
4416 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4417 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4419 z = str2big_normal(positive_p, digits_start, digits_end,
4428rb_str2big_karatsuba(
VALUE arg,
int base,
int badcheck)
4431 const char *s, *str;
4432 const char *digits_start, *digits_end;
4437 int digits_per_bdigits_dbl;
4440 if (!valid_radix_p(base)) {
4441 invalid_radix(base);
4446 len = RSTRING_LEN(arg);
4447 if (
len > 0 && *str ==
'-') {
4454 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4455 invalid_integer(arg);
4456 digits_end = digits_start +
len;
4458 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4459 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4461 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4462 num_bdigits, digits_per_bdigits_dbl, base);
4471rb_str2big_gmp(
VALUE arg,
int base,
int badcheck)
4474 const char *s, *str;
4475 const char *digits_start, *digits_end;
4480 int digits_per_bdigits_dbl;
4483 if (!valid_radix_p(base)) {
4484 invalid_radix(base);
4489 len = RSTRING_LEN(arg);
4490 if (
len > 0 && *str ==
'-') {
4497 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4498 invalid_integer(arg);
4499 digits_end = digits_start +
len;
4501 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4502 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4504 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4518 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4519 BDIGIT *digits = BDIGITS(big);
4521#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4524 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4525 digits[i] = BIGLO(n);
4530 i = bdigit_roomof(SIZEOF_LONG_LONG);
4531 while (i-- && !digits[i]) ;
4532 BIGNUM_SET_LEN(big, i+1);
4550 big = rb_ull2big(u);
4552 BIGNUM_SET_NEGATIVE_SIGN(big);
4561 return rb_ull2big(n);
4568 return rb_ll2big(n);
4575rb_uint128t2big(uint128_t n)
4578 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4579 BDIGIT *digits = BDIGITS(big);
4581 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4582 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4585 i = bdigit_roomof(SIZEOF_INT128_T);
4586 while (i-- && !digits[i]) ;
4587 BIGNUM_SET_LEN(big, i+1);
4592rb_int128t2big(int128_t n)
4599 u = 1 + (uint128_t)(-(n + 1));
4605 big = rb_uint128t2big(u);
4607 BIGNUM_SET_NEGATIVE_SIGN(big);
4614rb_cstr2inum(
const char *str,
int base)
4616 return rb_cstr_to_inum(str, base, base==0);
4622 return rb_str_to_inum(str, base, base==0);
4626big_shift3(
VALUE x,
int lshift_p,
size_t shift_numdigits,
int shift_numbits)
4635 if (LONG_MAX < shift_numdigits) {
4639 s1 = shift_numdigits;
4641 if ((
size_t)s1 != shift_numdigits)
goto too_big;
4643 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1)
goto too_big;
4644 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4646 BDIGITS_ZERO(zds, s1);
4648 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4653 if (LONG_MAX < shift_numdigits || (
size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4654 if (BIGNUM_POSITIVE_P(x) ||
4655 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4660 s1 = shift_numdigits;
4662 hibitsx = abs2twocomp(&x, &xn);
4670 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4671 twocomp2abs_bang(z, hibitsx != 0);
4682 size_t shift_numdigits;
4690 sign = rb_integer_pack(y, lens, numberof(lens),
sizeof(
size_t), 0,
4693 lshift_p = !lshift_p;
4697 if (1 < sign || CHAR_BIT <= lens[1])
4701 if (1 < sign || CHAR_BIT <= lens[1])
4704 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4705 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4706 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4707 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4711big_lshift(
VALUE x,
unsigned long shift)
4713 long s1 = shift/BITSPERDIG;
4714 int s2 = (int)(shift%BITSPERDIG);
4715 return big_shift3(x, 1, s1, s2);
4719big_rshift(
VALUE x,
unsigned long shift)
4721 long s1 = shift/BITSPERDIG;
4722 int s2 = (int)(shift%BITSPERDIG);
4723 return big_shift3(x, 0, s1, s2);
4726#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4728static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4729static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4732power_cache_init(
void)
4737power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret)
4753 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4754 rb_bug(
"too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4756 VALUE power = base36_power_cache[base - 2][power_level];
4759 if (power_level == 0) {
4761 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4762 power = bignew(2, 1);
4763 bdigitdbl2bary(BDIGITS(power), 2, dd);
4764 numdigits = numdigits0;
4767 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4771 base36_power_cache[base - 2][power_level] = power;
4772 base36_numdigits_cache[base - 2][power_level] = numdigits;
4773 rb_vm_register_global_object(power);
4776 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4784 int hbase2_numdigits;
4792 if (LONG_MAX-1 <
len)
4793 rb_raise(rb_eArgError,
"too big number");
4795 b2s->ptr = RSTRING_PTR(b2s->result);
4801big2str_2bdigits(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t taillen)
4805 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4806 int beginning = !b2s->ptr;
4810 num = bary2bdigitdbl(xds, xn);
4818 BDIGIT_DBL idx = num % b2s->base;
4820 p[--j] = ruby_digitmap[idx];
4822 len =
sizeof(buf) - j;
4823 big2str_alloc(b2s,
len + taillen);
4828 j = b2s->hbase2_numdigits;
4830 BDIGIT_DBL idx = num % b2s->base;
4832 p[--j] = ruby_digitmap[idx];
4834 len = b2s->hbase2_numdigits;
4840big2str_karatsuba(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t wn,
4841 int power_level,
size_t taillen)
4844 size_t half_numdigits, lower_numdigits;
4845 int lower_power_level;
4870 if (xn == 0 || bary_zero_p(xds, xn)) {
4873 power_cache_get_power(b2s->base, power_level, &
len);
4874 memset(b2s->ptr,
'0',
len);
4880 if (power_level == 0) {
4881 big2str_2bdigits(b2s, xds, xn, taillen);
4885 lower_power_level = power_level-1;
4886 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4890 half_numdigits = lower_numdigits;
4892 while (0 < lower_power_level &&
4894 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4895 lower_power_level--;
4896 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4901 if (lower_power_level == 0 &&
4903 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4905 len = half_numdigits * 2 - lower_numdigits;
4906 memset(b2s->ptr,
'0',
len);
4909 big2str_2bdigits(b2s, xds, xn, taillen);
4917 if (lower_power_level != power_level-1 && b2s->ptr) {
4918 len = (half_numdigits - lower_numdigits) * 2;
4919 memset(b2s->ptr,
'0',
len);
4923 shift = nlz(bds[bn-1]);
4925 qn = xn + BIGDIVREM_EXTRA_WORDS;
4930 tds = (BDIGIT *)bds;
4938 bary_small_lshift(tds, bds, bn, shift);
4939 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4942 bigdivrem_restoring(xds, qn, tds, bn);
4951 bary_small_rshift(rds, rds, rn, shift, 0);
4954 BARY_TRUNC(qds, qn);
4956 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4957 BARY_TRUNC(rds, rn);
4958 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4963big2str_base_poweroftwo(
VALUE x,
int base)
4965 int word_numbits = ffs(base) - 1;
4969 numwords = rb_absint_numwords(x, word_numbits, NULL);
4970 if (BIGNUM_NEGATIVE_P(x)) {
4971 if (LONG_MAX-1 < numwords)
4972 rb_raise(rb_eArgError,
"too big number");
4974 ptr = RSTRING_PTR(result);
4975 *ptr++ = BIGNUM_POSITIVE_P(x) ?
'+' :
'-';
4978 if (LONG_MAX < numwords)
4979 rb_raise(rb_eArgError,
"too big number");
4981 ptr = RSTRING_PTR(result);
4983 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4985 while (0 < numwords) {
4986 *ptr = ruby_digitmap[*(
unsigned char *)ptr];
4994rb_big2str_poweroftwo(
VALUE x,
int base)
4996 return big2str_base_poweroftwo(x, base);
5000big2str_generic(
VALUE x,
int base)
5010 BARY_TRUNC(xds, xn);
5016 if (!valid_radix_p(base))
5017 invalid_radix(base);
5019 if (xn >= LONG_MAX/BITSPERDIG) {
5020 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5024 power = power_cache_get_power(base, power_level, NULL);
5025 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
5026 (
size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
5028 power = power_cache_get_power(base, power_level, NULL);
5030 RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
5032 if ((
size_t)BIGNUM_LEN(power) <= xn) {
5046 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5047 b2s_data.base = base;
5048 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5050 b2s_data.result =
Qnil;
5051 b2s_data.ptr = NULL;
5053 if (power_level == 0) {
5054 big2str_2bdigits(&b2s_data, xds, xn, 0);
5060 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5061 wds =
ALLOCV_N(BDIGIT, tmpw, xn + wn);
5062 MEMCPY(wds, xds, BDIGIT, xn);
5063 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5069 *b2s_data.ptr =
'\0';
5070 rb_str_resize(b2s_data.result, (
long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5073 return b2s_data.result;
5077rb_big2str_generic(
VALUE x,
int base)
5079 return big2str_generic(x, base);
5084big2str_gmp(
VALUE x,
int base)
5089 BDIGIT *xds = BDIGITS(x);
5090 size_t xn = BIGNUM_LEN(x);
5093 bdigits_to_mpz(mx, xds, xn);
5095 size = mpz_sizeinbase(mx, base);
5097 if (BIGNUM_NEGATIVE_P(x)) {
5104 mpz_get_str(RSTRING_PTR(str), base, mx);
5107 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] ==
'\0') {
5116rb_big2str_gmp(
VALUE x,
int base)
5118 return big2str_gmp(x, base);
5123rb_big2str1(
VALUE x,
int base)
5135 BARY_TRUNC(xds, xn);
5141 if (!valid_radix_p(base))
5142 invalid_radix(base);
5144 if (xn >= LONG_MAX/BITSPERDIG) {
5145 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5150 return big2str_base_poweroftwo(x, base);
5154 if (GMP_BIG2STR_DIGITS < xn) {
5155 return big2str_gmp(x, base);
5159 return big2str_generic(x, base);
5165 return rb_big2str1(x, base);
5171#if SIZEOF_LONG > SIZEOF_BDIGIT
5174 size_t len = BIGNUM_LEN(x);
5180 if (BIGSIZE(x) >
sizeof(
long)) {
5184#if SIZEOF_LONG <= SIZEOF_BDIGIT
5185 num = (
unsigned long)ds[0];
5188 for (i = 0; i <
len; i++) {
5190 num += (
unsigned long)ds[
len - i - 1];
5199 unsigned long num = big2ulong(x,
"unsigned long");
5201 if (BIGNUM_POSITIVE_P(x)) {
5205 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5206 return -(long)(num-1)-1;
5208 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long");
5214 unsigned long num = big2ulong(x,
"long");
5216 if (BIGNUM_POSITIVE_P(x)) {
5217 if (num <= LONG_MAX)
5221 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5222 return -(long)(num-1)-1;
5224 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long'");
5232#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5235 size_t len = BIGNUM_LEN(x);
5237 BDIGIT *ds = BDIGITS(x);
5241 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5243#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5247 for (i = 0; i <
len; i++) {
5249 num += ds[
len - i - 1];
5258 unsigned LONG_LONG num = big2ull(x,
"unsigned long long");
5260 if (BIGNUM_POSITIVE_P(x)) {
5264 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5267 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long long");
5273 unsigned LONG_LONG num = big2ull(x,
"long long");
5275 if (BIGNUM_POSITIVE_P(x)) {
5276 if (num <= LLONG_MAX)
5280 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5283 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long long'");
5295 double u = (d < 0)?-d:d;
5305 u /= (double)(BIGRAD);
5308 z = bignew(i, d>=0);
5309 digits = BDIGITS(z);
5323 return bignorm(dbl2big(d));
5330 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5331 BDIGIT *ds = BDIGITS(x), dl;
5334 bits = i * BITSPERDIG - nlz(ds[i-1]);
5335 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5339 if (bits > DBL_MANT_DIG+1)
5340 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5344 d = ds[i] + BIGRAD*d;
5347 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5348 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5356 BDIGIT mask = BDIGMAX;
5368 if (lo > INT_MAX / BITSPERDIG)
5370 else if (lo < INT_MIN / BITSPERDIG)
5373 d = ldexp(d, (
int)(lo * BITSPERDIG));
5377 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5384 double d = big2dbl(x);
5406 if (yd > 0.0)
return INT2FIX(-1);
5411#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5438 rel = rb_big_cmp(x, y);
5439 if (yf == 0.0 || rel !=
INT2FIX(0))
5446#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG
5447COMPILER_WARNING_PUSH
5448#if __has_warning("-Wimplicit-int-float-conversion")
5449COMPILER_WARNING_IGNORED(-Wimplicit-
int-
float-conversion)
5451static const double LONG_MAX_as_double = LONG_MAX;
5467#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5469 return RBOOL(xd == yd);
5472 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5476 return RBOOL(xn == yn);
5480 return rb_big_eq(x, y);
5493 if (sx < sy)
return INT2FIX(-1);
5497 else if (RB_BIGNUM_TYPE_P(y)) {
5498 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5499 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5500 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5504 return rb_integer_float_cmp(x, y);
5509 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5526 rel = rb_big_cmp(x, y);
5529 rel = rb_integer_float_cmp(x, y);
5534 case big_op_gt:
id =
'>';
break;
5535 case big_op_ge:
id = idGE;
break;
5536 case big_op_lt:
id =
'<';
break;
5537 case big_op_le:
id = idLE;
break;
5546 case big_op_gt:
return RBOOL(n > 0);
5547 case big_op_ge:
return RBOOL(n >= 0);
5548 case big_op_lt:
return RBOOL(n < 0);
5549 case big_op_le:
return RBOOL(n <= 0);
5557 return big_op(x, y, big_op_gt);
5563 return big_op(x, y, big_op_ge);
5569 return big_op(x, y, big_op_lt);
5575 return big_op(x, y, big_op_le);
5593 return RBOOL(bignorm(x) == y);
5595 else if (RB_BIGNUM_TYPE_P(y)) {
5598 return rb_integer_float_eq(x, y);
5603 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5604 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5605 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5611 if (!RB_BIGNUM_TYPE_P(y))
return Qfalse;
5612 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5613 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5614 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5618rb_big_uminus(
VALUE x)
5620 VALUE z = rb_big_clone(x);
5630 VALUE z = rb_big_clone(x);
5631 BDIGIT *ds = BDIGITS(z);
5632 long n = BIGNUM_LEN(z);
5636 if (BIGNUM_POSITIVE_P(z)) {
5637 if (bary_add_one(ds, n)) {
5638 big_extend_carry(z);
5640 BIGNUM_SET_NEGATIVE_SIGN(z);
5644 if (bary_add_one(ds, n))
5647 BIGNUM_SET_POSITIVE_SIGN(z);
5657 BDIGIT *xds, *yds, *zds;
5662 zn = xn < yn ? yn : xn;
5670 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5671 bary_2comp(zds, zn);
5672 BIGNUM_SET_NEGATIVE_SIGN(z);
5681bigsub_int(
VALUE x,
long y0)
5686 BDIGIT_DBL_SIGNED num;
5697#if SIZEOF_BDIGIT < SIZEOF_LONG
5698 if (zn < bdigit_roomof(SIZEOF_LONG))
5699 zn = bdigit_roomof(SIZEOF_LONG);
5701 z = bignew(zn, BIGNUM_SIGN(x));
5704#if SIZEOF_BDIGIT >= SIZEOF_LONG
5706 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5707 if (xn == 1 && num < 0) {
5709 zds[0] = (BDIGIT)-num;
5713 zds[0] = BIGLO(num);
5721 for (i=0; i < xn; i++) {
5722 if (y == 0)
goto y_is_zero_x;
5723 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5724 zds[i] = BIGLO(num);
5728 for (; i < zn; i++) {
5729 if (y == 0)
goto y_is_zero_z;
5731 zds[i] = BIGLO(num);
5738 for (; i < xn; i++) {
5740 if (num == 0)
goto num_is_zero_x;
5742 zds[i] = BIGLO(num);
5745#if SIZEOF_BDIGIT < SIZEOF_LONG
5746 for (; i < zn; i++) {
5748 if (num == 0)
goto num_is_zero_z;
5749 zds[i] = BIGLO(num);
5755 for (; i < xn; i++) {
5759#if SIZEOF_BDIGIT < SIZEOF_LONG
5760 for (; i < zn; i++) {
5778bigadd_int(
VALUE x,
long y)
5793#if SIZEOF_BDIGIT < SIZEOF_LONG
5794 if (zn < bdigit_roomof(SIZEOF_LONG))
5795 zn = bdigit_roomof(SIZEOF_LONG);
5799 z = bignew(zn, BIGNUM_SIGN(x));
5802#if SIZEOF_BDIGIT >= SIZEOF_LONG
5803 num = (BDIGIT_DBL)xds[0] + y;
5804 zds[0] = BIGLO(num);
5812 for (i=0; i < xn; i++) {
5813 if (y == 0)
goto y_is_zero_x;
5814 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5815 zds[i] = BIGLO(num);
5819 for (; i < zn; i++) {
5820 if (y == 0)
goto y_is_zero_z;
5822 zds[i] = BIGLO(num);
5830 for (;i < xn; i++) {
5832 if (num == 0)
goto num_is_zero_x;
5833 num += (BDIGIT_DBL)xds[i];
5834 zds[i] = BIGLO(num);
5837 for (; i < zn; i++) {
5839 if (num == 0)
goto num_is_zero_z;
5840 zds[i] = BIGLO(num);
5845 for (;i < xn; i++) {
5849 for (; i < zn; i++) {
5866 sign = (sign == BIGNUM_SIGN(y));
5867 if (BIGNUM_SIGN(x) != sign) {
5868 if (sign)
return bigsub(y, x);
5869 return bigsub(x, y);
5872 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5873 len = BIGNUM_LEN(x) + 1;
5876 len = BIGNUM_LEN(y) + 1;
5878 z = bignew(
len, sign);
5880 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5881 BDIGITS(x), BIGNUM_LEN(x),
5882 BDIGITS(y), BIGNUM_LEN(y));
5894 if ((n > 0) != BIGNUM_SIGN(x)) {
5898 return bigsub_int(x, n);
5903 return bigadd_int(x, n);
5905 else if (RB_BIGNUM_TYPE_P(y)) {
5906 return bignorm(bigadd(x, y, 1));
5923 if ((n > 0) != BIGNUM_SIGN(x)) {
5927 return bigadd_int(x, n);
5932 return bigsub_int(x, n);
5934 else if (RB_BIGNUM_TYPE_P(y)) {
5935 return bignorm(bigadd(x, y, 0));
5953 if (MUL_OVERFLOW_LONG_P(2, xn))
5954 rb_raise(rb_eArgError,
"square overflow");
5962 if (xn < NAIVE_MUL_DIGITS)
5963 bary_sq_fast(zds, zn, xds, xn);
5965 bary_mul(zds, zn, xds, xn, xds, xn);
5976 BDIGIT *xds, *yds, *zds;
5983 if (ADD_OVERFLOW_LONG_P(xn, yn))
5984 rb_raise(rb_eArgError,
"multiplication overflow");
5987 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5993 bary_mul(zds, zn, xds, xn, yds, yn);
6006 else if (RB_BIGNUM_TYPE_P(y)) {
6015 return bignorm(bigmul0(x, y));
6021 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
6023 BDIGIT *xds, *yds, *zds;
6031 BARY_TRUNC(yds, yn);
6036 BARY_TRUNC(xds, xn);
6038 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
6039 if (divp) *divp = rb_int2big(0);
6040 if (modp) *modp = x;
6045 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6047 dd = bigdivrem_single(zds, xds, xn, dd);
6049 *modp = rb_uint2big((uintptr_t)dd);
6050 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6052 if (divp) *divp = z;
6055 if (xn == 2 && yn == 2) {
6056 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6057 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6058 BDIGIT_DBL q0 = x0 / y0;
6059 BDIGIT_DBL r0 = x0 % y0;
6061 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6064 zds[1] = BIGLO(BIGDN(q0));
6068 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6071 zds[1] = BIGLO(BIGDN(r0));
6078 qn = xn + BIGDIVREM_EXTRA_WORDS;
6079 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6089 r = bignew(rn, BIGNUM_SIGN(x));
6097 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6116 bigdivrem(x, y, divp, &mod);
6117 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6118 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6119 if (modp) *modp = bigadd(mod, y, 1);
6135 else if (RB_BIGNUM_TYPE_P(y)) {
6139 double dx = rb_big2dbl(x);
6140 return rb_flo_div_flo(
DBL2NUM(dx), y);
6146 v = rb_big_divide(x, y,
'/');
6153 bigdivmod(x, y, &z, 0);
6161 return rb_big_divide(x, y,
'/');
6167 return rb_big_divide(x, y, idDiv);
6178 else if (!RB_BIGNUM_TYPE_P(y)) {
6181 bigdivmod(x, y, 0, &z);
6194 else if (!RB_BIGNUM_TYPE_P(y)) {
6197 bigdivrem(x, y, 0, &z);
6210 else if (!RB_BIGNUM_TYPE_P(y)) {
6213 bigdivmod(x, y, &div, &mod);
6219big_shift(
VALUE x,
long n)
6222 return big_lshift(x, 1+(
unsigned long)(-(n+1)));
6224 return big_rshift(x, (
unsigned long)n);
6228enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6238 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6239 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6240 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6241 else if (ex > 0) ex = 0;
6242 if (ex) x = big_shift(x, ex);
6244 bigdivrem(x, y, &z, 0);
6246#if SIZEOF_LONG > SIZEOF_INT
6249 if (l > INT_MAX)
return HUGE_VAL;
6250 if (l < INT_MIN)
return 0.0;
6253 return ldexp(big2dbl(z), (
int)l);
6262 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6263 ey -= DBL_BIGDIG * BITSPERDIG;
6264 if (ey) y = big_shift(y, ey);
6265 return big_fdiv(x, y, ey);
6272 y = dbl2big(ldexp(frexp(
RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6273 return big_fdiv(x, y, i - DBL_MANT_DIG);
6286 return big_fdiv_int(x, rb_int2big(
FIX2LONG(y)));
6288 else if (RB_BIGNUM_TYPE_P(y)) {
6289 return big_fdiv_int(x, y);
6296 return big_fdiv_float(x, y);
6308 return DBL2NUM(rb_big_fdiv_double(x, y));
6319 if (y ==
INT2FIX(1))
return x;
6322 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6323 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6326 else if (RB_BIGNUM_TYPE_P(y)) {
6330 rb_raise(rb_eArgError,
"exponent is too large");
6345 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6346#if SIZEOF_SIZE_T == 4
6347 const size_t BIGLEN_LIMIT = 1ULL << 31;
6349 const size_t BIGLEN_LIMIT = 1ULL << 34;
6352 if (xbits == (
size_t)-1 ||
6353 (xbits > BIGLEN_LIMIT) ||
6354 MUL_OVERFLOW_LONG_P(yy, xbits) ||
6355 (xbits * yy > BIGLEN_LIMIT)) {
6356 rb_raise(rb_eArgError,
"exponent is too large");
6359 for (mask =
FIXNUM_MAX + 1; mask; mask >>= 1) {
6360 if (z) z = bigsq(z);
6362 z = z ? bigtrunc(bigmul0(z, x)) : x;
6372 return DBL2NUM(pow(rb_big2dbl(x), d));
6376bigand_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6384 if (y == 0)
return INT2FIX(0);
6386 hibitsy = 0 <= y ? 0 : BDIGMAX;
6388#if SIZEOF_BDIGIT >= SIZEOF_LONG
6396#if SIZEOF_BDIGIT < SIZEOF_LONG
6397 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6398 zn = bdigit_roomof(SIZEOF_LONG);
6404#if SIZEOF_BDIGIT >= SIZEOF_LONG
6406 zds[0] = xds[0] & BIGLO(y);
6408 for (i=0; i < xn; i++) {
6409 if (y == 0 || y == -1)
break;
6410 zds[i] = xds[i] & BIGLO(y);
6413 for (; i < zn; i++) {
6414 if (y == 0 || y == -1)
break;
6415 zds[i] = hibitsx & BIGLO(y);
6419 for (;i < xn; i++) {
6420 zds[i] = xds[i] & hibitsy;
6422 for (;i < zn; i++) {
6423 zds[i] = hibitsx & hibitsy;
6425 twocomp2abs_bang(z, hibitsx && hibitsy);
6434 BDIGIT *ds1, *ds2, *zds;
6435 long i, xn, yn, n1, n2;
6436 BDIGIT hibitsx, hibitsy;
6437 BDIGIT hibits1, hibits2;
6446 hibitsx = abs2twocomp(&x, &xn);
6448 return bigand_int(x, xn, hibitsx,
FIX2LONG(y));
6450 hibitsy = abs2twocomp(&y, &yn);
6452 tmpv = x; x = y; y = tmpv;
6453 tmpn = xn; xn = yn; yn = tmpn;
6454 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6469 for (i=0; i<n1; i++) {
6470 zds[i] = ds1[i] & ds2[i];
6473 zds[i] = hibits1 & ds2[i];
6475 twocomp2abs_bang(z, hibits1 && hibits2);
6482bigor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6490 if (y == -1)
return INT2FIX(-1);
6492 hibitsy = 0 <= y ? 0 : BDIGMAX;
6496#if SIZEOF_BDIGIT < SIZEOF_LONG
6497 if (zn < bdigit_roomof(SIZEOF_LONG))
6498 zn = bdigit_roomof(SIZEOF_LONG);
6503#if SIZEOF_BDIGIT >= SIZEOF_LONG
6505 zds[0] = xds[0] | BIGLO(y);
6507 goto y_is_fixed_point;
6510 for (i=0; i < xn; i++) {
6511 if (y == 0 || y == -1)
goto y_is_fixed_point;
6512 zds[i] = xds[i] | BIGLO(y);
6517 for (; i < zn; i++) {
6518 if (y == 0 || y == -1)
goto y_is_fixed_point;
6528 for (; i < xn; i++) {
6533 for (; i < zn; i++) {
6539 for (; i < zn; i++) {
6544 twocomp2abs_bang(z, hibitsx || hibitsy);
6553 BDIGIT *ds1, *ds2, *zds;
6554 long i, xn, yn, n1, n2;
6555 BDIGIT hibitsx, hibitsy;
6556 BDIGIT hibits1, hibits2;
6565 hibitsx = abs2twocomp(&x, &xn);
6567 return bigor_int(x, xn, hibitsx,
FIX2LONG(y));
6569 hibitsy = abs2twocomp(&y, &yn);
6571 tmpv = x; x = y; y = tmpv;
6572 tmpn = xn; xn = yn; yn = tmpn;
6573 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6588 for (i=0; i<n1; i++) {
6589 zds[i] = ds1[i] | ds2[i];
6592 zds[i] = hibits1 | ds2[i];
6594 twocomp2abs_bang(z, hibits1 || hibits2);
6601bigxor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6609 hibitsy = 0 <= y ? 0 : BDIGMAX;
6612#if SIZEOF_BDIGIT < SIZEOF_LONG
6613 if (zn < bdigit_roomof(SIZEOF_LONG))
6614 zn = bdigit_roomof(SIZEOF_LONG);
6619#if SIZEOF_BDIGIT >= SIZEOF_LONG
6621 zds[0] = xds[0] ^ BIGLO(y);
6623 for (i = 0; i < xn; i++) {
6624 zds[i] = xds[i] ^ BIGLO(y);
6627 for (; i < zn; i++) {
6628 zds[i] = hibitsx ^ BIGLO(y);
6632 for (; i < xn; i++) {
6633 zds[i] = xds[i] ^ hibitsy;
6635 for (; i < zn; i++) {
6636 zds[i] = hibitsx ^ hibitsy;
6638 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6647 BDIGIT *ds1, *ds2, *zds;
6648 long i, xn, yn, n1, n2;
6649 BDIGIT hibitsx, hibitsy;
6650 BDIGIT hibits1, hibits2;
6659 hibitsx = abs2twocomp(&x, &xn);
6661 return bigxor_int(x, xn, hibitsx,
FIX2LONG(y));
6663 hibitsy = abs2twocomp(&y, &yn);
6665 tmpv = x; x = y; y = tmpv;
6666 tmpn = xn; xn = yn; yn = tmpn;
6667 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6679 for (i=0; i<n1; i++) {
6680 zds[i] = ds1[i] ^ ds2[i];
6683 zds[i] = hibitsx ^ ds2[i];
6685 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6695 size_t shift_numdigits;
6701 unsigned long shift;
6708 shift = 1+(
unsigned long)(-(l+1));
6710 shift_numbits = (int)(shift & (BITSPERDIG-1));
6711 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6712 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6714 else if (RB_BIGNUM_TYPE_P(y)) {
6715 return bignorm(big_shift2(x, 1, y));
6725 size_t shift_numdigits;
6731 unsigned long shift;
6738 shift = 1+(
unsigned long)(-(l+1));
6740 shift_numbits = (int)(shift & (BITSPERDIG-1));
6741 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6742 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6744 else if (RB_BIGNUM_TYPE_P(y)) {
6745 return bignorm(big_shift2(x, 0, y));
6760 if (RB_BIGNUM_TYPE_P(y)) {
6761 if (BIGNUM_NEGATIVE_P(y))
6764 if (BIGSIZE(y) >
sizeof(
size_t)) {
6767#if SIZEOF_SIZE_T <= SIZEOF_LONG
6768 shift = big2ulong(y,
"long");
6770 shift = big2ull(y,
"long long");
6778 s1 = shift/BITSPERDIG;
6779 s2 = shift%BITSPERDIG;
6780 bit = (BDIGIT)1 << s2;
6782 if (s1 >= BIGNUM_LEN(x))
6786 if (BIGNUM_POSITIVE_P(x))
6788 if (xds[s1] & (bit-1))
6790 for (i = 0; i < s1; i++)
6801 size_t copy_begin, xn, shift;
6802 ssize_t begin, length, end;
6803 bool negative_add_one;
6810 shift = begin < 0 ? -begin : 0;
6814 if (length < 0)
return rb_big_rshift(x, beg);
6815 if (length == 0 || end <= 0)
return INT2FIX(0);
6816 if (begin < 0) begin = 0;
6818 if ((
size_t)(end - 1) / BITSPERDIG >= xn) {
6820 end = xn * BITSPERDIG;
6823 if ((
size_t)begin / BITSPERDIG < xn) {
6825 size_t shift_bits, copy_end;
6826 copy_begin = begin / BITSPERDIG;
6827 shift_bits = begin % BITSPERDIG;
6828 copy_end = (end - 1) / BITSPERDIG + 1;
6829 v = bignew(copy_end - copy_begin, 1);
6831 MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
6832 negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
6834 if (shift_bits) v = rb_int_rshift(v,
SIZET2NUM(shift_bits));
6839 negative_add_one =
false;
6840 copy_begin = begin = end = 0;
6843 if (BIGNUM_NEGATIVE_P(x)) {
6844 size_t mask_size = length - shift;
6846 v = rb_int_xor(v, mask);
6847 for (
size_t i = 0; negative_add_one && i < copy_begin; i++) {
6848 if (xds[i]) negative_add_one =
false;
6850 if (negative_add_one) v = rb_int_plus(v,
INT2FIX(1));
6851 v = rb_int_and(v, mask);
6854 size_t mask_size = (size_t)end - begin;
6856 v = rb_int_and(v, mask);
6859 if (shift) v = rb_int_lshift(v,
SSIZET2NUM(shift));
6868 hash =
rb_memhash(BDIGITS(x),
sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6903 if (BIGNUM_NEGATIVE_P(x)) {
6904 x = rb_big_clone(x);
6905 BIGNUM_SET_POSITIVE_SIGN(x);
6913 return BIGNUM_SIGN(x);
6917rb_big_size(
VALUE big)
6919 return BIGSIZE(big);
6923rb_big_size_m(
VALUE big)
6929rb_big_bit_length(
VALUE big)
6934 static const BDIGIT char_bit[1] = { CHAR_BIT };
6935 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(
size_t))];
6937 BDIGIT result_bary[bdigit_roomof(
sizeof(
size_t)+1)];
6939 numbytes = rb_absint_size(big, &nlz_bits);
6944 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6945 if (nlz_bits != CHAR_BIT-1) {
6954 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6955 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6958 nlz_bary[0] = nlz_bits;
6960 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
6962 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6963 BARY_SUB(result_bary, result_bary, nlz_bary);
6965 return rb_integer_unpack(result_bary, numberof(result_bary),
sizeof(BDIGIT), 0,
6970rb_big_odd_p(
VALUE num)
6972 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6976rb_big_even_p(
VALUE num)
6978 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6984unsigned long rb_ulong_isqrt(
unsigned long);
6985#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6986BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6987# ifdef ULL_TO_DOUBLE
6988# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6991# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6993#ifndef BDIGIT_DBL_TO_DOUBLE
6994# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
6998rb_big_isqrt(
VALUE n)
7000 BDIGIT *nds = BDIGITS(n);
7001 size_t len = BIGNUM_LEN(n);
7004 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds,
len));
7005#if SIZEOF_BDIGIT > SIZEOF_LONG
7012 size_t shift =
FIX2LONG(rb_big_bit_length(n)) / 4;
7016 x = rb_int_plus(rb_int_lshift(x,
SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n,
SIZET2NUM(shift + 1)), x));
7017 VALUE xx = rb_int_mul(x, x);
7018 while (rb_int_gt(xx, n)) {
7019 xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x),
INT2FIX(1)));
7020 x = rb_int_minus(x,
INT2FIX(1));
7028bary_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)
7036 bdigits_to_mpz(x, xds, xn);
7037 bdigits_to_mpz(y, yds, yn);
7038 bdigits_to_mpz(m, mds, mn);
7039 mpz_powm(z, x, y, m);
7040 bdigits_from_mpz(z, zds, &count);
7041 BDIGITS_ZERO(zds+count, zn-count);
7054 size_t xn, yn, mn, zn;
7068 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7069 if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
7070 z = rb_big_minus(z, m);
7075 return rb_big_norm(z);
7081 if (
RTEST(rb_int_odd_p(y))) {
7082 tmp = rb_int_mul(tmp, x);
7083 tmp = rb_int_modulo(tmp, m);
7085 x = rb_int_mul(x, x);
7086 x = rb_int_modulo(x, m);
7088 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7090 tmp = rb_int_mul(tmp, x);
7091 tmp = rb_int_modulo(tmp, m);
7093 x = rb_int_mul(x, x);
7094 x = rb_int_modulo(x, m);
7097 if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
7098 tmp = rb_int_minus(tmp, m);
7109int_pow_tmp1(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7116 if (
RTEST(rb_int_odd_p(y))) {
7117 tmp = (tmp * xx) % mm;
7119 xx = (xx * xx) % mm;
7121 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7123 tmp = (tmp * xx) % mm;
7125 xx = (xx * xx) % mm;
7128 if (nega_flg && tmp) {
7135int_pow_tmp2(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7143# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7148# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7152 if (
RTEST(rb_int_odd_p(y))) {
7153 tmp2 = MUL_MODULO(tmp2, xx, m);
7155 xx = MUL_MODULO(xx, xx, m);
7157 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7159 tmp2 = MUL_MODULO(tmp2, xx, m);
7161 xx = MUL_MODULO(xx, xx, m);
7169 if (nega_flg && tmp) {
7187rb_int_powm(
int const argc,
VALUE *
const argv,
VALUE const num)
7192 return rb_int_pow(num, argv[0]);
7195 VALUE const a = num;
7196 VALUE const b = argv[0];
7200 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7202 if (rb_int_negative_p(b)) {
7203 rb_raise(
rb_eRangeError,
"Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7206 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless all arguments are integers");
7209 if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
7214 if (rb_int_negative_p(m)) {
7215 m = rb_int_uminus(m);
7220 long const half_val = (long)HALF_LONG_MSB;
7223 if (mm == 1)
return INT2FIX(0);
7224 if (mm <= half_val) {
7225 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7228 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7234 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7265 rb_define_const(
rb_cInteger,
"GMP_VERSION", rb_sprintf(
"GMP %s", gmp_version));
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_DEBUG
Define this macro when you want assertions.
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define NUM2SSIZET
Old name of RB_NUM2SSIZE.
#define ISSPACE
Old name of rb_isspace.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define NEGFIXABLE
Old name of RB_NEGFIXABLE.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define CLASS_OF
Old name of rb_class_of.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define NUM2DBL
Old name of rb_num2dbl.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define FIXNUM_MIN
Old name of RUBY_FIXNUM_MIN.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
#define POSFIXABLE
Old name of RB_POSFIXABLE.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
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.
VALUE rb_eFloatDomainError
FloatDomainError exception.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
VALUE rb_cInteger
Module class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
#define RGENGC_WB_PROTECTED_BIGNUM
This is a compile-time flag to enable/disable write barrier for struct RBignum.
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.
#define INTEGER_PACK_LSBYTE_FIRST
Stores/interprets the least significant byte in a word as the first byte in the word.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Means either INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST, depending on the host processor'...
#define INTEGER_PACK_FORCE_BIGNUM
Always generates a bignum object even if the integer can be representable using fixnum scheme (unpack...
#define INTEGER_PACK_BIG_ENDIAN
Big endian combination.
#define INTEGER_PACK_2COMP
Uses 2's complement representation.
#define INTEGER_PACK_NEGATIVE
Interprets the input as a signed negative number (unpack only).
#define INTEGER_PACK_MSWORD_FIRST
Stores/interprets the most significant word as the first word.
#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
Uses "generic" implementation (handy on test).
#define INTEGER_PACK_LSWORD_FIRST
Stores/interprets the least significant word as the first word.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_num_zerodiv(void)
Just always raises an exception.
VALUE rb_fix2str(VALUE val, int base)
Generates a place-value representation of the given Fixnum, with given radix.
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().
VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_cmp(), except for return values.
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
VALUE rb_rational_raw(VALUE num, VALUE den)
Identical to rb_rational_new(), except it skips argument validations.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
void rb_thread_check_ints(void)
Checks for interrupts.
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
#define RB_NOGVL_UBF_ASYNC_SAFE
Passing this flag to rb_nogvl() indicates that the passed UBF is async-signal-safe.
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...
#define RB_NOGVL_OFFLOAD_SAFE
Passing this flag to rb_nogvl() indicates that the passed function is safe to offload to a background...
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.
#define MEMCMP(p1, p2, type, n)
Handy macro to call memcmp.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define StringValue(v)
Ensures that the parameter object is a String.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#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.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
#define RBIMPL_WARNING_PUSH()
Pushes compiler warning state.
#define RBIMPL_WARNING_POP()
Pops compiler warning state.