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);
2948# define BIGNUM_DEBUG (0+RUBY_DEBUG)
2954 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2971 if (l > 0)
return 1;
2972 if (l < 0)
return -1;
2975 if (RB_BIGNUM_TYPE_P(val)) {
2976 if (BIGZEROP(val))
return 0;
2977 if (BIGNUM_SIGN(val))
return 1;
2985#define BIGNUM_SET_LEN(b,l) \
2986 (BIGNUM_EMBED_P(b) ? \
2987 (void)(RBASIC(b)->flags = \
2988 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2989 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2990 (void)(RBIGNUM(b)->as.heap.len = (l)))
2993big_embed_capa(
VALUE big)
2995 size_t size = rb_gc_obj_slot_size(big) - offsetof(
struct RBignum, as.ary);
2997 size_t capa = size /
sizeof(BDIGIT);
3003big_embed_size(
size_t capa)
3005 size_t size = offsetof(
struct RBignum, as.ary) + (
sizeof(BDIGIT) *
capa);
3006 if (size <
sizeof(
struct RBignum)) {
3007 size =
sizeof(
struct RBignum);
3013big_embeddable_p(
size_t capa)
3015 if (
capa > BIGNUM_EMBED_LEN_MAX) {
3018 return rb_gc_size_allocatable_p(big_embed_size(
capa));
3022rb_big_realloc(
VALUE big,
size_t len)
3025 size_t embed_capa = big_embed_capa(big);
3027 if (BIGNUM_EMBED_P(big)) {
3028 if (embed_capa <
len) {
3030 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, embed_capa);
3031 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
3032 RBIGNUM(big)->as.heap.digits = ds;
3037 if (
len <= embed_capa) {
3038 ds = RBIGNUM(big)->as.heap.digits;
3040 BIGNUM_SET_LEN(big,
len);
3041 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)RBIGNUM(big)->as.ary, embed_capa *
sizeof(BDIGIT));
3043 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT,
len);
3048 if (BIGNUM_LEN(big) == 0) {
3049 RBIGNUM(big)->as.heap.digits =
ALLOC_N(BDIGIT,
len);
3051 else if (BIGNUM_LEN(big) <
len) {
3061 rb_big_realloc(big,
len);
3062 BIGNUM_SET_LEN(big,
len);
3066bignew_1(
VALUE klass,
size_t len,
int sign)
3070 if (big_embeddable_p(
len)) {
3071 size_t size = big_embed_size(
len);
3073 NEWOBJ_OF(big,
struct RBignum, klass,
3077 BIGNUM_SET_SIGN(bigv, sign);
3078 BIGNUM_SET_LEN(bigv,
len);
3079 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)big->as.ary,
len *
sizeof(BDIGIT));
3082 NEWOBJ_OF(big,
struct RBignum, klass,
3085 BIGNUM_SET_SIGN(bigv, sign);
3087 big->as.heap.len =
len;
3094rb_big_new(
size_t len,
int sign)
3096 VALUE obj = bignew(
len, sign != 0);
3097 memset(BIGNUM_DIGITS(obj), 0,
len *
sizeof(BDIGIT));
3104 size_t len = BIGNUM_LEN(x);
3107 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT,
len);
3112big_extend_carry(
VALUE x)
3114 rb_big_resize(x, BIGNUM_LEN(x)+1);
3115 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3122 long i = BIGNUM_LEN(x);
3123 BDIGIT *ds = BDIGITS(x);
3125 if (bary_2comp(ds, i)) {
3126 big_extend_carry(x);
3137abs2twocomp(
VALUE *xp,
long *n_ret)
3140 long n = BIGNUM_LEN(x);
3141 BDIGIT *ds = BDIGITS(x);
3146 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3148 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3149 bary_2comp(BDIGITS(z), n);
3158twocomp2abs_bang(
VALUE x,
int hibits)
3160 BIGNUM_SET_SIGN(x, !hibits);
3169 size_t len = BIGNUM_LEN(x);
3170 BDIGIT *ds = BDIGITS(x);
3172 if (
len == 0)
return x;
3173 while (--
len && !ds[
len]);
3174 if (BIGNUM_LEN(x) >
len+1) {
3175 rb_big_resize(x,
len+1);
3183 size_t n = BIGNUM_LEN(x);
3184 BDIGIT *ds = BDIGITS(x);
3185#if SIZEOF_BDIGIT < SIZEOF_LONG
3193 if (n == 0)
return INT2FIX(0);
3195#if SIZEOF_BDIGIT < SIZEOF_LONG
3196 if (
sizeof(
long)/SIZEOF_BDIGIT < n)
3202 u = (
unsigned long)(BIGUP(u) + ds[i]);
3212 if (BIGNUM_POSITIVE_P(x)) {
3220 rb_big_resize(x, n);
3227 if (RB_BIGNUM_TYPE_P(x)) {
3240rb_uint2big(uintptr_t n)
3244 BDIGIT *digits = BDIGITS(big);
3246#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3250 digits[i] = BIGLO(n);
3256 while (--i && !digits[i]) ;
3257 BIGNUM_SET_LEN(big, i+1);
3262rb_int2big(intptr_t n)
3269 u = 1 + (
VALUE)(-(n + 1));
3275 big = rb_uint2big(u);
3277 BIGNUM_SET_NEGATIVE_SIGN(big);
3283rb_uint2inum(uintptr_t n)
3286 return rb_uint2big(n);
3290rb_int2inum(intptr_t n)
3293 return rb_int2big(n);
3297rb_big_pack(
VALUE val,
unsigned long *buf,
long num_longs)
3299 rb_integer_pack(val, buf, num_longs,
sizeof(
long), 0,
3305rb_big_unpack(
unsigned long *buf,
long num_longs)
3307 return rb_integer_unpack(buf, num_longs,
sizeof(
long), 0,
3329rb_absint_size(
VALUE val,
int *nlz_bits_ret)
3333 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3335 int num_leading_zeros;
3344#if SIZEOF_BDIGIT >= SIZEOF_LONG
3349 for (i = 0; i < numberof(fixbuf); i++) {
3350 fixbuf[i] = BIGLO(v);
3356 de = fixbuf + numberof(fixbuf);
3360 de = dp + BIGNUM_LEN(val);
3362 while (dp < de && de[-1] == 0)
3369 num_leading_zeros = nlz(de[-1]);
3371 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3372 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3376absint_numwords_small(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3378 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3379 size_t div = val_numbits / word_numbits;
3380 size_t mod = val_numbits % word_numbits;
3383 numwords = mod == 0 ? div : div + 1;
3384 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3385 *nlz_bits_ret = nlz_bits;
3390absint_numwords_generic(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3392 static const BDIGIT char_bit[1] = { CHAR_BIT };
3393 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(numbytes))];
3394 BDIGIT val_numbits_bary[bdigit_roomof(
sizeof(numbytes) + 1)];
3395 BDIGIT nlz_bits_in_msbyte_bary[1];
3396 BDIGIT word_numbits_bary[bdigit_roomof(
sizeof(word_numbits))];
3397 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3398 BDIGIT mod_bary[numberof(word_numbits_bary)];
3399 BDIGIT one[1] = { 1 };
3405 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3414 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
3416 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3417 if (nlz_bits_in_msbyte)
3418 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3419 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1,
sizeof(word_numbits), 0,
3421 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3422 if (BARY_ZERO_P(mod_bary)) {
3426 BARY_ADD(div_bary, div_bary, one);
3427 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1,
sizeof(mod), 0,
3429 nlz_bits = word_numbits - mod;
3431 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1,
sizeof(numwords), 0,
3435#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3440 *nlz_bits_ret = nlz_bits;
3464rb_absint_numwords(
VALUE val,
size_t word_numbits,
size_t *nlz_bits_ret)
3467 int nlz_bits_in_msbyte;
3469 size_t nlz_bits = 0;
3471 if (word_numbits == 0)
3474 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3476 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3477 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3478 if (debug_integer_pack) {
3479 size_t numwords0, nlz_bits0;
3480 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3487 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3489 if (numwords == (
size_t)-1)
3493 *nlz_bits_ret = nlz_bits;
3531 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3541#if SIZEOF_BDIGIT >= SIZEOF_LONG
3546 for (i = 0; i < numberof(fixbuf); i++) {
3547 fixbuf[i] = BIGLO(v);
3553 de = fixbuf + numberof(fixbuf);
3557 de = dp + BIGNUM_LEN(val);
3559 while (dp < de && de[-1] == 0)
3561 while (dp < de && dp[0] == 0)
3628rb_integer_pack(
VALUE val,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3633 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3646#if SIZEOF_BDIGIT >= SIZEOF_LONG
3651 for (i = 0; i < numberof(fixbuf); i++) {
3652 fixbuf[i] = BIGLO(v);
3658 num_bdigits = numberof(fixbuf);
3661 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3663 num_bdigits = BIGNUM_LEN(val);
3666 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3714rb_integer_unpack(
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3721 BDIGIT fixbuf[2] = { 0, 0 };
3723 validate_integer_pack_format(numwords, wordsize, nails, flags,
3734 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3736 if (LONG_MAX-1 < num_bdigits)
3737 rb_raise(rb_eArgError,
"too big to unpack as an integer");
3743 val = bignew((
long)num_bdigits, 0);
3746 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3750 big_extend_carry(val);
3752 else if (num_bdigits == numberof(fixbuf)) {
3753 val = bignew((
long)num_bdigits+1, 0);
3754 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3755 BDIGITS(val)[num_bdigits++] = 1;
3758 ds[num_bdigits++] = 1;
3763 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3768 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3770 return LONG2FIX((
long)-(BDIGIT_DBL_SIGNED)u);
3771 val = bignew((
long)num_bdigits, 0 <= sign);
3772 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3776 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3778 BIGNUM_SET_SIGN(val, 0 <= sign);
3781 return bigtrunc(val);
3782 return bignorm(val);
3785#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3787NORETURN(
static inline void invalid_radix(
int base));
3788NORETURN(
static inline void invalid_integer(
VALUE s));
3791valid_radix_p(
int base)
3793 return (1 < base && base <= 36);
3797invalid_radix(
int base)
3799 rb_raise(rb_eArgError,
"invalid radix %d", base);
3803invalid_integer(
VALUE s)
3805 rb_raise(rb_eArgError,
"invalid value for Integer(): %+"PRIsVALUE, s);
3809str2big_scan_digits(
const char *s,
const char *str,
int base,
int badcheck,
size_t *num_digits_p, ssize_t *len_p)
3812 size_t num_digits = 0;
3813 const char *digits_start = str;
3814 const char *digits_end = str;
3815 ssize_t
len = *len_p;
3825 if (badcheck && *str ==
'_')
return FALSE;
3827 while ((c = *str++) != 0) {
3830 if (badcheck)
return FALSE;
3833 nondigit = (char) c;
3835 else if ((c = conv_digit(c)) < 0 || c >= base) {
3843 if (
len > 0 && !--
len)
break;
3845 if (badcheck && nondigit)
return FALSE;
3846 if (badcheck &&
len) {
3848 while (*str &&
ISSPACE(*str)) {
3850 if (
len > 0 && !--
len)
break;
3856 *num_digits_p = num_digits;
3857 *len_p = digits_end - digits_start;
3864 const char *digits_start,
3865 const char *digits_end,
3878 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3879 z = bignew(num_bdigits, sign);
3883 for (p = digits_end; digits_start < p; p--) {
3884 if ((c = conv_digit(p[-1])) < 0)
3886 dd |= (BDIGIT_DBL)c << numbits;
3887 numbits += bits_per_digit;
3888 if (BITSPERDIG <= numbits) {
3891 numbits -= BITSPERDIG;
3897 RUBY_ASSERT((
size_t)(dp - BDIGITS(z)) == num_bdigits);
3905 const char *digits_start,
3906 const char *digits_end,
3919 z = bignew(num_bdigits, sign);
3921 BDIGITS_ZERO(zds, num_bdigits);
3923 for (p = digits_start; p < digits_end; p++) {
3924 if ((c = conv_digit(*p)) < 0)
3930 num += (BDIGIT_DBL)zds[i]*base;
3931 zds[i++] = BIGLO(num);
3949 const char *digits_start,
3950 const char *digits_end,
3953 int digits_per_bdigits_dbl,
3959 BDIGIT *uds, *vds, *tds;
3961 BDIGIT_DBL current_base;
3963 int power_level = 0;
3970 uds =
ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3971 vds = uds + num_bdigits;
3973 powerv = power_cache_get_power(base, power_level, NULL);
3978 m = digits_per_bdigits_dbl;
3979 if (num_digits < (
size_t)m)
3980 m = (int)num_digits;
3981 for (p = digits_end; digits_start < p; p--) {
3982 if ((c = conv_digit(p[-1])) < 0)
3984 dd = dd + c * current_base;
3985 current_base *= base;
3989 uds[i++] = BIGLO(dd);
3990 uds[i++] = (BDIGIT)BIGDN(dd);
3992 m = digits_per_bdigits_dbl;
3993 if (num_digits < (
size_t)m)
3994 m = (
int)num_digits;
3999 for (unit = 2; unit < num_bdigits; unit *= 2) {
4000 for (i = 0; i < num_bdigits; i += unit*2) {
4001 if (2*unit <= num_bdigits - i) {
4002 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
4003 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
4005 else if (unit <= num_bdigits - i) {
4006 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
4007 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
4010 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
4014 powerv = power_cache_get_power(base, power_level, NULL);
4019 BARY_TRUNC(uds, num_bdigits);
4020 z = bignew(num_bdigits, sign);
4021 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
4033 const char *digits_start,
4034 const char *digits_end,
4047 buf =
ALLOCV_N(
char, tmps, num_digits+1);
4049 for (q = digits_start; q < digits_end; q++) {
4050 if (conv_digit(*q) < 0)
4057 mpz_set_str(mz, buf, base);
4059 z = bignew(zn, sign);
4061 bdigits_from_mpz(mz, BDIGITS(z), &count);
4062 BDIGITS_ZERO(zds+count, zn-count);
4072static VALUE rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base);
4091rb_cstr_to_inum(
const char *str,
int base,
int badcheck)
4094 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4120rb_int_parse_cstr(
const char *str, ssize_t
len,
char **endp,
size_t *ndigits,
4121 int base,
int flags)
4123 const char *
const s = str;
4131 const char *digits_start, *digits_end;
4132 size_t num_digits = 0;
4134 const ssize_t len0 =
len;
4135 const int badcheck = !endp;
4138 if (len > 0 && len <= (n)) goto bad; \
4142#define ASSERT_LEN() do {\
4143 RUBY_ASSERT(len != 0); \
4144 if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
4150 if (
len && (flags & RB_INT_PARSE_SIGN)) {
4153 if (str[0] ==
'+') {
4156 else if (str[0] ==
'-') {
4163 if (str[0] ==
'0' &&
len > 1) {
4185 else if (base < -1) {
4192 else if (
len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4195 else if (base == 2) {
4196 if (str[0] ==
'0' && (str[1] ==
'b'||str[1] ==
'B')) {
4200 else if (base == 8) {
4201 if (str[0] ==
'0' && (str[1] ==
'o'||str[1] ==
'O')) {
4205 else if (base == 10) {
4206 if (str[0] ==
'0' && (str[1] ==
'd'||str[1] ==
'D')) {
4210 else if (base == 16) {
4211 if (str[0] ==
'0' && (str[1] ==
'x'||str[1] ==
'X')) {
4215 if (!valid_radix_p(base)) {
4216 invalid_radix(base);
4219 num_digits = str - s;
4220 if (*str ==
'0' &&
len != 1) {
4222 const char *end =
len < 0 ? NULL : str +
len;
4224 while ((c = *++str) ==
'0' ||
4225 ((flags & RB_INT_PARSE_UNDERSCORE) && c ==
'_')) {
4234 if (str == end)
break;
4237 if (end)
len = end - str;
4241 if (c < 0 || c >= base) {
4242 if (!badcheck && num_digits) z =
INT2FIX(0);
4246 if (ndigits) *ndigits = num_digits;
4247 val = ruby_scan_digits(str,
len, base, &num_digits, &ov);
4249 const char *end = &str[num_digits];
4250 if (num_digits > 0 && *end ==
'_' && (flags & RB_INT_PARSE_UNDERSCORE))
4252 if (endp) *endp = (
char *)end;
4253 if (ndigits) *ndigits += num_digits;
4255 if (num_digits == 0)
return Qnil;
4256 while (
len < 0 ? *end : end < str +
len) {
4265 long result = -(long)val;
4270 VALUE big = rb_uint2big(val);
4271 BIGNUM_SET_SIGN(big, sign);
4272 return bignorm(big);
4278 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4280 if (endp) *endp = (
char *)(str +
len);
4281 if (ndigits) *ndigits += num_digits;
4282 digits_end = digits_start +
len;
4285 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4286 bit_length(base-1));
4289 int digits_per_bdigits_dbl;
4290 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4291 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4294 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4295 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4300 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4301 z = str2big_normal(sign, digits_start, digits_end,
4305 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4306 num_bdigits, digits_per_bdigits_dbl, base);
4313 if (endp) *endp = (
char *)str;
4314 if (ndigits) *ndigits = num_digits;
4319rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base)
4321 return rb_int_parse_cstr(str,
len, endp, NULL, base,
4322 RB_INT_PARSE_DEFAULT);
4326rb_str_convert_to_inum(
VALUE str,
int base,
int badcheck,
int raise_exception)
4336 ret = rb_cstr_parse_inum(s,
len, (badcheck ? NULL : &end), base);
4339 if (!raise_exception)
return Qnil;
4340 invalid_integer(str);
4348rb_str_to_inum(
VALUE str,
int base,
int badcheck)
4350 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4354rb_str2big_poweroftwo(
VALUE arg,
int base,
int badcheck)
4357 const char *s, *str;
4358 const char *digits_start, *digits_end;
4363 if (!valid_radix_p(base) || !POW2_P(base)) {
4364 invalid_radix(base);
4369 len = RSTRING_LEN(arg);
4377 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4378 invalid_integer(arg);
4379 digits_end = digits_start +
len;
4381 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4382 bit_length(base-1));
4390rb_str2big_normal(
VALUE arg,
int base,
int badcheck)
4393 const char *s, *str;
4394 const char *digits_start, *digits_end;
4399 int digits_per_bdigits_dbl;
4402 if (!valid_radix_p(base)) {
4403 invalid_radix(base);
4408 len = RSTRING_LEN(arg);
4409 if (
len > 0 && *str ==
'-') {
4416 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4417 invalid_integer(arg);
4418 digits_end = digits_start +
len;
4420 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4421 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4423 z = str2big_normal(positive_p, digits_start, digits_end,
4432rb_str2big_karatsuba(
VALUE arg,
int base,
int badcheck)
4435 const char *s, *str;
4436 const char *digits_start, *digits_end;
4441 int digits_per_bdigits_dbl;
4444 if (!valid_radix_p(base)) {
4445 invalid_radix(base);
4450 len = RSTRING_LEN(arg);
4451 if (
len > 0 && *str ==
'-') {
4458 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4459 invalid_integer(arg);
4460 digits_end = digits_start +
len;
4462 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4463 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4465 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4466 num_bdigits, digits_per_bdigits_dbl, base);
4475rb_str2big_gmp(
VALUE arg,
int base,
int badcheck)
4478 const char *s, *str;
4479 const char *digits_start, *digits_end;
4484 int digits_per_bdigits_dbl;
4487 if (!valid_radix_p(base)) {
4488 invalid_radix(base);
4493 len = RSTRING_LEN(arg);
4494 if (
len > 0 && *str ==
'-') {
4501 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4502 invalid_integer(arg);
4503 digits_end = digits_start +
len;
4505 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4506 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4508 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4522 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4523 BDIGIT *digits = BDIGITS(big);
4525#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4528 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4529 digits[i] = BIGLO(n);
4534 i = bdigit_roomof(SIZEOF_LONG_LONG);
4535 while (i-- && !digits[i]) ;
4536 BIGNUM_SET_LEN(big, i+1);
4554 big = rb_ull2big(u);
4556 BIGNUM_SET_NEGATIVE_SIGN(big);
4565 return rb_ull2big(n);
4572 return rb_ll2big(n);
4579rb_uint128t2big(uint128_t n)
4582 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4583 BDIGIT *digits = BDIGITS(big);
4585 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4586 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4589 i = bdigit_roomof(SIZEOF_INT128_T);
4590 while (i-- && !digits[i]) ;
4591 BIGNUM_SET_LEN(big, i+1);
4596rb_int128t2big(int128_t n)
4603 u = 1 + (uint128_t)(-(n + 1));
4609 big = rb_uint128t2big(u);
4611 BIGNUM_SET_NEGATIVE_SIGN(big);
4618rb_cstr2inum(
const char *str,
int base)
4620 return rb_cstr_to_inum(str, base, base==0);
4626 return rb_str_to_inum(str, base, base==0);
4630big_shift3(
VALUE x,
int lshift_p,
size_t shift_numdigits,
int shift_numbits)
4639 if (LONG_MAX < shift_numdigits) {
4643 s1 = shift_numdigits;
4645 if ((
size_t)s1 != shift_numdigits)
goto too_big;
4647 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1)
goto too_big;
4648 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4650 BDIGITS_ZERO(zds, s1);
4652 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4657 if (LONG_MAX < shift_numdigits || (
size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4658 if (BIGNUM_POSITIVE_P(x) ||
4659 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4664 s1 = shift_numdigits;
4666 hibitsx = abs2twocomp(&x, &xn);
4674 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4675 twocomp2abs_bang(z, hibitsx != 0);
4686 size_t shift_numdigits;
4694 sign = rb_integer_pack(y, lens, numberof(lens),
sizeof(
size_t), 0,
4697 lshift_p = !lshift_p;
4701 if (1 < sign || CHAR_BIT <= lens[1])
4705 if (1 < sign || CHAR_BIT <= lens[1])
4708 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4709 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4710 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4711 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4715big_lshift(
VALUE x,
unsigned long shift)
4717 long s1 = shift/BITSPERDIG;
4718 int s2 = (int)(shift%BITSPERDIG);
4719 return big_shift3(x, 1, s1, s2);
4723big_rshift(
VALUE x,
unsigned long shift)
4725 long s1 = shift/BITSPERDIG;
4726 int s2 = (int)(shift%BITSPERDIG);
4727 return big_shift3(x, 0, s1, s2);
4730#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4732static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4733static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4736power_cache_init(
void)
4741power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret)
4757 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4758 rb_bug(
"too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4760 VALUE power = base36_power_cache[base - 2][power_level];
4763 if (power_level == 0) {
4765 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4766 power = bignew(2, 1);
4767 bdigitdbl2bary(BDIGITS(power), 2, dd);
4768 numdigits = numdigits0;
4771 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4775 base36_power_cache[base - 2][power_level] = power;
4776 base36_numdigits_cache[base - 2][power_level] = numdigits;
4777 rb_vm_register_global_object(power);
4780 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4788 int hbase2_numdigits;
4796 if (LONG_MAX-1 <
len)
4797 rb_raise(rb_eArgError,
"too big number");
4799 b2s->ptr = RSTRING_PTR(b2s->result);
4805big2str_2bdigits(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t taillen)
4809 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4810 int beginning = !b2s->ptr;
4814 num = bary2bdigitdbl(xds, xn);
4822 BDIGIT_DBL idx = num % b2s->base;
4824 p[--j] = ruby_digitmap[idx];
4826 len =
sizeof(buf) - j;
4827 big2str_alloc(b2s,
len + taillen);
4832 j = b2s->hbase2_numdigits;
4834 BDIGIT_DBL idx = num % b2s->base;
4836 p[--j] = ruby_digitmap[idx];
4838 len = b2s->hbase2_numdigits;
4844big2str_karatsuba(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t wn,
4845 int power_level,
size_t taillen)
4848 size_t half_numdigits, lower_numdigits;
4849 int lower_power_level;
4874 if (xn == 0 || bary_zero_p(xds, xn)) {
4877 power_cache_get_power(b2s->base, power_level, &
len);
4878 memset(b2s->ptr,
'0',
len);
4884 if (power_level == 0) {
4885 big2str_2bdigits(b2s, xds, xn, taillen);
4889 lower_power_level = power_level-1;
4890 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4894 half_numdigits = lower_numdigits;
4896 while (0 < lower_power_level &&
4898 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4899 lower_power_level--;
4900 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4905 if (lower_power_level == 0 &&
4907 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4909 len = half_numdigits * 2 - lower_numdigits;
4910 memset(b2s->ptr,
'0',
len);
4913 big2str_2bdigits(b2s, xds, xn, taillen);
4921 if (lower_power_level != power_level-1 && b2s->ptr) {
4922 len = (half_numdigits - lower_numdigits) * 2;
4923 memset(b2s->ptr,
'0',
len);
4927 shift = nlz(bds[bn-1]);
4929 qn = xn + BIGDIVREM_EXTRA_WORDS;
4934 tds = (BDIGIT *)bds;
4942 bary_small_lshift(tds, bds, bn, shift);
4943 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4946 bigdivrem_restoring(xds, qn, tds, bn);
4955 bary_small_rshift(rds, rds, rn, shift, 0);
4958 BARY_TRUNC(qds, qn);
4960 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4961 BARY_TRUNC(rds, rn);
4962 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4967big2str_base_poweroftwo(
VALUE x,
int base)
4969 int word_numbits = ffs(base) - 1;
4973 numwords = rb_absint_numwords(x, word_numbits, NULL);
4974 if (BIGNUM_NEGATIVE_P(x)) {
4975 if (LONG_MAX-1 < numwords)
4976 rb_raise(rb_eArgError,
"too big number");
4978 ptr = RSTRING_PTR(result);
4979 *ptr++ = BIGNUM_POSITIVE_P(x) ?
'+' :
'-';
4982 if (LONG_MAX < numwords)
4983 rb_raise(rb_eArgError,
"too big number");
4985 ptr = RSTRING_PTR(result);
4987 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4989 while (0 < numwords) {
4990 *ptr = ruby_digitmap[*(
unsigned char *)ptr];
4998rb_big2str_poweroftwo(
VALUE x,
int base)
5000 return big2str_base_poweroftwo(x, base);
5004big2str_generic(
VALUE x,
int base)
5014 BARY_TRUNC(xds, xn);
5020 if (!valid_radix_p(base))
5021 invalid_radix(base);
5023 if (xn >= LONG_MAX/BITSPERDIG) {
5024 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5028 power = power_cache_get_power(base, power_level, NULL);
5029 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
5030 (
size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
5032 power = power_cache_get_power(base, power_level, NULL);
5034 RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
5036 if ((
size_t)BIGNUM_LEN(power) <= xn) {
5050 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5051 b2s_data.base = base;
5052 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5054 b2s_data.result =
Qnil;
5055 b2s_data.ptr = NULL;
5057 if (power_level == 0) {
5058 big2str_2bdigits(&b2s_data, xds, xn, 0);
5064 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5065 wds =
ALLOCV_N(BDIGIT, tmpw, xn + wn);
5066 MEMCPY(wds, xds, BDIGIT, xn);
5067 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5073 *b2s_data.ptr =
'\0';
5074 rb_str_resize(b2s_data.result, (
long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5077 return b2s_data.result;
5081rb_big2str_generic(
VALUE x,
int base)
5083 return big2str_generic(x, base);
5088big2str_gmp(
VALUE x,
int base)
5093 BDIGIT *xds = BDIGITS(x);
5094 size_t xn = BIGNUM_LEN(x);
5097 bdigits_to_mpz(mx, xds, xn);
5099 size = mpz_sizeinbase(mx, base);
5101 if (BIGNUM_NEGATIVE_P(x)) {
5108 mpz_get_str(RSTRING_PTR(str), base, mx);
5111 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] ==
'\0') {
5120rb_big2str_gmp(
VALUE x,
int base)
5122 return big2str_gmp(x, base);
5127rb_big2str1(
VALUE x,
int base)
5139 BARY_TRUNC(xds, xn);
5145 if (!valid_radix_p(base))
5146 invalid_radix(base);
5148 if (xn >= LONG_MAX/BITSPERDIG) {
5149 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5154 return big2str_base_poweroftwo(x, base);
5158 if (GMP_BIG2STR_DIGITS < xn) {
5159 return big2str_gmp(x, base);
5163 return big2str_generic(x, base);
5169 return rb_big2str1(x, base);
5175#if SIZEOF_LONG > SIZEOF_BDIGIT
5178 size_t len = BIGNUM_LEN(x);
5184 if (BIGSIZE(x) >
sizeof(
long)) {
5188#if SIZEOF_LONG <= SIZEOF_BDIGIT
5189 num = (
unsigned long)ds[0];
5192 for (i = 0; i <
len; i++) {
5194 num += (
unsigned long)ds[
len - i - 1];
5203 unsigned long num = big2ulong(x,
"unsigned long");
5205 if (BIGNUM_POSITIVE_P(x)) {
5209 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5210 return -(long)(num-1)-1;
5212 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long");
5218 unsigned long num = big2ulong(x,
"long");
5220 if (BIGNUM_POSITIVE_P(x)) {
5221 if (num <= LONG_MAX)
5225 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5226 return -(long)(num-1)-1;
5228 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long'");
5236#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5239 size_t len = BIGNUM_LEN(x);
5241 BDIGIT *ds = BDIGITS(x);
5245 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5247#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5251 for (i = 0; i <
len; i++) {
5253 num += ds[
len - i - 1];
5262 unsigned LONG_LONG num = big2ull(x,
"unsigned long long");
5264 if (BIGNUM_POSITIVE_P(x)) {
5268 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5271 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long long");
5277 unsigned LONG_LONG num = big2ull(x,
"long long");
5279 if (BIGNUM_POSITIVE_P(x)) {
5280 if (num <= LLONG_MAX)
5284 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5287 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long long'");
5299 double u = (d < 0)?-d:d;
5309 u /= (double)(BIGRAD);
5312 z = bignew(i, d>=0);
5313 digits = BDIGITS(z);
5327 return bignorm(dbl2big(d));
5334 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5335 BDIGIT *ds = BDIGITS(x), dl;
5338 bits = i * BITSPERDIG - nlz(ds[i-1]);
5339 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5343 if (bits > DBL_MANT_DIG+1)
5344 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5348 d = ds[i] + BIGRAD*d;
5351 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5352 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5360 BDIGIT mask = BDIGMAX;
5372 if (lo > INT_MAX / BITSPERDIG)
5374 else if (lo < INT_MIN / BITSPERDIG)
5377 d = ldexp(d, (
int)(lo * BITSPERDIG));
5381 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5388 double d = big2dbl(x);
5410 if (yd > 0.0)
return INT2FIX(-1);
5415#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5442 rel = rb_big_cmp(x, y);
5443 if (yf == 0.0 || rel !=
INT2FIX(0))
5450#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG
5451COMPILER_WARNING_PUSH
5452#if __has_warning("-Wimplicit-int-float-conversion")
5453COMPILER_WARNING_IGNORED(-Wimplicit-
int-
float-conversion)
5455static const double LONG_MAX_as_double = LONG_MAX;
5471#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5473 return RBOOL(xd == yd);
5476 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5480 return RBOOL(xn == yn);
5484 return rb_big_eq(x, y);
5497 if (sx < sy)
return INT2FIX(-1);
5501 else if (RB_BIGNUM_TYPE_P(y)) {
5502 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5503 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5504 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5508 return rb_integer_float_cmp(x, y);
5513 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5530 rel = rb_big_cmp(x, y);
5533 rel = rb_integer_float_cmp(x, y);
5538 case big_op_gt:
id =
'>';
break;
5539 case big_op_ge:
id = idGE;
break;
5540 case big_op_lt:
id =
'<';
break;
5541 case big_op_le:
id = idLE;
break;
5550 case big_op_gt:
return RBOOL(n > 0);
5551 case big_op_ge:
return RBOOL(n >= 0);
5552 case big_op_lt:
return RBOOL(n < 0);
5553 case big_op_le:
return RBOOL(n <= 0);
5561 return big_op(x, y, big_op_gt);
5567 return big_op(x, y, big_op_ge);
5573 return big_op(x, y, big_op_lt);
5579 return big_op(x, y, big_op_le);
5597 return RBOOL(bignorm(x) == y);
5599 else if (RB_BIGNUM_TYPE_P(y)) {
5602 return rb_integer_float_eq(x, y);
5607 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5608 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5609 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5615 if (!RB_BIGNUM_TYPE_P(y))
return Qfalse;
5616 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5617 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5618 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5622rb_big_uminus(
VALUE x)
5624 VALUE z = rb_big_clone(x);
5634 VALUE z = rb_big_clone(x);
5635 BDIGIT *ds = BDIGITS(z);
5636 long n = BIGNUM_LEN(z);
5640 if (BIGNUM_POSITIVE_P(z)) {
5641 if (bary_add_one(ds, n)) {
5642 big_extend_carry(z);
5644 BIGNUM_SET_NEGATIVE_SIGN(z);
5648 if (bary_add_one(ds, n))
5651 BIGNUM_SET_POSITIVE_SIGN(z);
5661 BDIGIT *xds, *yds, *zds;
5666 zn = xn < yn ? yn : xn;
5674 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5675 bary_2comp(zds, zn);
5676 BIGNUM_SET_NEGATIVE_SIGN(z);
5685bigsub_int(
VALUE x,
long y0)
5690 BDIGIT_DBL_SIGNED num;
5701#if SIZEOF_BDIGIT < SIZEOF_LONG
5702 if (zn < bdigit_roomof(SIZEOF_LONG))
5703 zn = bdigit_roomof(SIZEOF_LONG);
5705 z = bignew(zn, BIGNUM_SIGN(x));
5708#if SIZEOF_BDIGIT >= SIZEOF_LONG
5710 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5711 if (xn == 1 && num < 0) {
5713 zds[0] = (BDIGIT)-num;
5717 zds[0] = BIGLO(num);
5725 for (i=0; i < xn; i++) {
5726 if (y == 0)
goto y_is_zero_x;
5727 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5728 zds[i] = BIGLO(num);
5732 for (; i < zn; i++) {
5733 if (y == 0)
goto y_is_zero_z;
5735 zds[i] = BIGLO(num);
5742 for (; i < xn; i++) {
5744 if (num == 0)
goto num_is_zero_x;
5746 zds[i] = BIGLO(num);
5749#if SIZEOF_BDIGIT < SIZEOF_LONG
5750 for (; i < zn; i++) {
5752 if (num == 0)
goto num_is_zero_z;
5753 zds[i] = BIGLO(num);
5759 for (; i < xn; i++) {
5763#if SIZEOF_BDIGIT < SIZEOF_LONG
5764 for (; i < zn; i++) {
5782bigadd_int(
VALUE x,
long y)
5797#if SIZEOF_BDIGIT < SIZEOF_LONG
5798 if (zn < bdigit_roomof(SIZEOF_LONG))
5799 zn = bdigit_roomof(SIZEOF_LONG);
5803 z = bignew(zn, BIGNUM_SIGN(x));
5806#if SIZEOF_BDIGIT >= SIZEOF_LONG
5807 num = (BDIGIT_DBL)xds[0] + y;
5808 zds[0] = BIGLO(num);
5816 for (i=0; i < xn; i++) {
5817 if (y == 0)
goto y_is_zero_x;
5818 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5819 zds[i] = BIGLO(num);
5823 for (; i < zn; i++) {
5824 if (y == 0)
goto y_is_zero_z;
5826 zds[i] = BIGLO(num);
5834 for (;i < xn; i++) {
5836 if (num == 0)
goto num_is_zero_x;
5837 num += (BDIGIT_DBL)xds[i];
5838 zds[i] = BIGLO(num);
5841 for (; i < zn; i++) {
5843 if (num == 0)
goto num_is_zero_z;
5844 zds[i] = BIGLO(num);
5849 for (;i < xn; i++) {
5853 for (; i < zn; i++) {
5870 sign = (sign == BIGNUM_SIGN(y));
5871 if (BIGNUM_SIGN(x) != sign) {
5872 if (sign)
return bigsub(y, x);
5873 return bigsub(x, y);
5876 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5877 len = BIGNUM_LEN(x) + 1;
5880 len = BIGNUM_LEN(y) + 1;
5882 z = bignew(
len, sign);
5884 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5885 BDIGITS(x), BIGNUM_LEN(x),
5886 BDIGITS(y), BIGNUM_LEN(y));
5898 if ((n > 0) != BIGNUM_SIGN(x)) {
5902 return bigsub_int(x, n);
5907 return bigadd_int(x, n);
5909 else if (RB_BIGNUM_TYPE_P(y)) {
5910 return bignorm(bigadd(x, y, 1));
5927 if ((n > 0) != BIGNUM_SIGN(x)) {
5931 return bigadd_int(x, n);
5936 return bigsub_int(x, n);
5938 else if (RB_BIGNUM_TYPE_P(y)) {
5939 return bignorm(bigadd(x, y, 0));
5957 if (MUL_OVERFLOW_LONG_P(2, xn))
5958 rb_raise(rb_eArgError,
"square overflow");
5966 if (xn < NAIVE_MUL_DIGITS)
5967 bary_sq_fast(zds, zn, xds, xn);
5969 bary_mul(zds, zn, xds, xn, xds, xn);
5980 BDIGIT *xds, *yds, *zds;
5987 if (ADD_OVERFLOW_LONG_P(xn, yn))
5988 rb_raise(rb_eArgError,
"multiplication overflow");
5991 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5997 bary_mul(zds, zn, xds, xn, yds, yn);
6010 else if (RB_BIGNUM_TYPE_P(y)) {
6019 return bignorm(bigmul0(x, y));
6025 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
6027 BDIGIT *xds, *yds, *zds;
6035 BARY_TRUNC(yds, yn);
6040 BARY_TRUNC(xds, xn);
6042 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
6043 if (divp) *divp = rb_int2big(0);
6044 if (modp) *modp = x;
6049 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6051 dd = bigdivrem_single(zds, xds, xn, dd);
6053 *modp = rb_uint2big((uintptr_t)dd);
6054 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6056 if (divp) *divp = z;
6059 if (xn == 2 && yn == 2) {
6060 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6061 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6062 BDIGIT_DBL q0 = x0 / y0;
6063 BDIGIT_DBL r0 = x0 % y0;
6065 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6068 zds[1] = BIGLO(BIGDN(q0));
6072 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6075 zds[1] = BIGLO(BIGDN(r0));
6082 qn = xn + BIGDIVREM_EXTRA_WORDS;
6083 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6093 r = bignew(rn, BIGNUM_SIGN(x));
6101 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6120 bigdivrem(x, y, divp, &mod);
6121 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6122 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6123 if (modp) *modp = bigadd(mod, y, 1);
6139 else if (RB_BIGNUM_TYPE_P(y)) {
6143 double dx = rb_big2dbl(x);
6144 return rb_flo_div_flo(
DBL2NUM(dx), y);
6150 v = rb_big_divide(x, y,
'/');
6157 bigdivmod(x, y, &z, 0);
6165 return rb_big_divide(x, y,
'/');
6171 return rb_big_divide(x, y, idDiv);
6182 else if (!RB_BIGNUM_TYPE_P(y)) {
6185 bigdivmod(x, y, 0, &z);
6198 else if (!RB_BIGNUM_TYPE_P(y)) {
6201 bigdivrem(x, y, 0, &z);
6214 else if (!RB_BIGNUM_TYPE_P(y)) {
6217 bigdivmod(x, y, &div, &mod);
6223big_shift(
VALUE x,
long n)
6226 return big_lshift(x, 1+(
unsigned long)(-(n+1)));
6228 return big_rshift(x, (
unsigned long)n);
6232enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6242 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6243 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6244 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6245 else if (ex > 0) ex = 0;
6246 if (ex) x = big_shift(x, ex);
6248 bigdivrem(x, y, &z, 0);
6250#if SIZEOF_LONG > SIZEOF_INT
6253 if (l > INT_MAX)
return HUGE_VAL;
6254 if (l < INT_MIN)
return 0.0;
6257 return ldexp(big2dbl(z), (
int)l);
6266 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6267 ey -= DBL_BIGDIG * BITSPERDIG;
6268 if (ey) y = big_shift(y, ey);
6269 return big_fdiv(x, y, ey);
6276 y = dbl2big(ldexp(frexp(
RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6277 return big_fdiv(x, y, i - DBL_MANT_DIG);
6290 return big_fdiv_int(x, rb_int2big(
FIX2LONG(y)));
6292 else if (RB_BIGNUM_TYPE_P(y)) {
6293 return big_fdiv_int(x, y);
6300 return big_fdiv_float(x, y);
6312 return DBL2NUM(rb_big_fdiv_double(x, y));
6323 if (y ==
INT2FIX(1))
return x;
6326 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6327 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6330 else if (RB_BIGNUM_TYPE_P(y)) {
6334 rb_raise(rb_eArgError,
"exponent is too large");
6349 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6350#if SIZEOF_SIZE_T == 4
6351 const size_t BIGLEN_LIMIT = 1ULL << 31;
6353 const size_t BIGLEN_LIMIT = 1ULL << 34;
6356 if (xbits == (
size_t)-1 ||
6357 (xbits > BIGLEN_LIMIT) ||
6358 MUL_OVERFLOW_LONG_P(yy, xbits) ||
6359 (xbits * yy > BIGLEN_LIMIT)) {
6360 rb_raise(rb_eArgError,
"exponent is too large");
6363 for (mask =
FIXNUM_MAX + 1; mask; mask >>= 1) {
6364 if (z) z = bigsq(z);
6366 z = z ? bigtrunc(bigmul0(z, x)) : x;
6376 return DBL2NUM(pow(rb_big2dbl(x), d));
6380bigand_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6388 if (y == 0)
return INT2FIX(0);
6390 hibitsy = 0 <= y ? 0 : BDIGMAX;
6392#if SIZEOF_BDIGIT >= SIZEOF_LONG
6400#if SIZEOF_BDIGIT < SIZEOF_LONG
6401 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6402 zn = bdigit_roomof(SIZEOF_LONG);
6408#if SIZEOF_BDIGIT >= SIZEOF_LONG
6410 zds[0] = xds[0] & BIGLO(y);
6412 for (i=0; i < xn; i++) {
6413 if (y == 0 || y == -1)
break;
6414 zds[i] = xds[i] & BIGLO(y);
6417 for (; i < zn; i++) {
6418 if (y == 0 || y == -1)
break;
6419 zds[i] = hibitsx & BIGLO(y);
6423 for (;i < xn; i++) {
6424 zds[i] = xds[i] & hibitsy;
6426 for (;i < zn; i++) {
6427 zds[i] = hibitsx & hibitsy;
6429 twocomp2abs_bang(z, hibitsx && hibitsy);
6438 BDIGIT *ds1, *ds2, *zds;
6439 long i, xn, yn, n1, n2;
6440 BDIGIT hibitsx, hibitsy;
6441 BDIGIT hibits1, hibits2;
6450 hibitsx = abs2twocomp(&x, &xn);
6452 return bigand_int(x, xn, hibitsx,
FIX2LONG(y));
6454 hibitsy = abs2twocomp(&y, &yn);
6456 tmpv = x; x = y; y = tmpv;
6457 tmpn = xn; xn = yn; yn = tmpn;
6458 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6473 for (i=0; i<n1; i++) {
6474 zds[i] = ds1[i] & ds2[i];
6477 zds[i] = hibits1 & ds2[i];
6479 twocomp2abs_bang(z, hibits1 && hibits2);
6486bigor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6494 if (y == -1)
return INT2FIX(-1);
6496 hibitsy = 0 <= y ? 0 : BDIGMAX;
6500#if SIZEOF_BDIGIT < SIZEOF_LONG
6501 if (zn < bdigit_roomof(SIZEOF_LONG))
6502 zn = bdigit_roomof(SIZEOF_LONG);
6507#if SIZEOF_BDIGIT >= SIZEOF_LONG
6509 zds[0] = xds[0] | BIGLO(y);
6511 goto y_is_fixed_point;
6514 for (i=0; i < xn; i++) {
6515 if (y == 0 || y == -1)
goto y_is_fixed_point;
6516 zds[i] = xds[i] | BIGLO(y);
6521 for (; i < zn; i++) {
6522 if (y == 0 || y == -1)
goto y_is_fixed_point;
6532 for (; i < xn; i++) {
6537 for (; i < zn; i++) {
6543 for (; i < zn; i++) {
6548 twocomp2abs_bang(z, hibitsx || hibitsy);
6557 BDIGIT *ds1, *ds2, *zds;
6558 long i, xn, yn, n1, n2;
6559 BDIGIT hibitsx, hibitsy;
6560 BDIGIT hibits1, hibits2;
6569 hibitsx = abs2twocomp(&x, &xn);
6571 return bigor_int(x, xn, hibitsx,
FIX2LONG(y));
6573 hibitsy = abs2twocomp(&y, &yn);
6575 tmpv = x; x = y; y = tmpv;
6576 tmpn = xn; xn = yn; yn = tmpn;
6577 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6592 for (i=0; i<n1; i++) {
6593 zds[i] = ds1[i] | ds2[i];
6596 zds[i] = hibits1 | ds2[i];
6598 twocomp2abs_bang(z, hibits1 || hibits2);
6605bigxor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6613 hibitsy = 0 <= y ? 0 : BDIGMAX;
6616#if SIZEOF_BDIGIT < SIZEOF_LONG
6617 if (zn < bdigit_roomof(SIZEOF_LONG))
6618 zn = bdigit_roomof(SIZEOF_LONG);
6623#if SIZEOF_BDIGIT >= SIZEOF_LONG
6625 zds[0] = xds[0] ^ BIGLO(y);
6627 for (i = 0; i < xn; i++) {
6628 zds[i] = xds[i] ^ BIGLO(y);
6631 for (; i < zn; i++) {
6632 zds[i] = hibitsx ^ BIGLO(y);
6636 for (; i < xn; i++) {
6637 zds[i] = xds[i] ^ hibitsy;
6639 for (; i < zn; i++) {
6640 zds[i] = hibitsx ^ hibitsy;
6642 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6651 BDIGIT *ds1, *ds2, *zds;
6652 long i, xn, yn, n1, n2;
6653 BDIGIT hibitsx, hibitsy;
6654 BDIGIT hibits1, hibits2;
6663 hibitsx = abs2twocomp(&x, &xn);
6665 return bigxor_int(x, xn, hibitsx,
FIX2LONG(y));
6667 hibitsy = abs2twocomp(&y, &yn);
6669 tmpv = x; x = y; y = tmpv;
6670 tmpn = xn; xn = yn; yn = tmpn;
6671 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6683 for (i=0; i<n1; i++) {
6684 zds[i] = ds1[i] ^ ds2[i];
6687 zds[i] = hibitsx ^ ds2[i];
6689 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6699 size_t shift_numdigits;
6705 unsigned long shift;
6712 shift = 1+(
unsigned long)(-(l+1));
6714 shift_numbits = (int)(shift & (BITSPERDIG-1));
6715 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6716 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6718 else if (RB_BIGNUM_TYPE_P(y)) {
6719 return bignorm(big_shift2(x, 1, y));
6729 size_t shift_numdigits;
6735 unsigned long shift;
6742 shift = 1+(
unsigned long)(-(l+1));
6744 shift_numbits = (int)(shift & (BITSPERDIG-1));
6745 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6746 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6748 else if (RB_BIGNUM_TYPE_P(y)) {
6749 return bignorm(big_shift2(x, 0, y));
6764 if (RB_BIGNUM_TYPE_P(y)) {
6765 if (BIGNUM_NEGATIVE_P(y))
6768 if (BIGSIZE(y) >
sizeof(
size_t)) {
6771#if SIZEOF_SIZE_T <= SIZEOF_LONG
6772 shift = big2ulong(y,
"long");
6774 shift = big2ull(y,
"long long");
6782 s1 = shift/BITSPERDIG;
6783 s2 = shift%BITSPERDIG;
6784 bit = (BDIGIT)1 << s2;
6786 if (s1 >= BIGNUM_LEN(x))
6790 if (BIGNUM_POSITIVE_P(x))
6792 if (xds[s1] & (bit-1))
6794 for (i = 0; i < s1; i++)
6805 size_t copy_begin, xn, shift;
6806 ssize_t begin, length, end;
6807 bool negative_add_one;
6814 shift = begin < 0 ? -begin : 0;
6818 if (length < 0)
return rb_big_rshift(x, beg);
6819 if (length == 0 || end <= 0)
return INT2FIX(0);
6820 if (begin < 0) begin = 0;
6822 if ((
size_t)(end - 1) / BITSPERDIG >= xn) {
6824 end = xn * BITSPERDIG;
6827 if ((
size_t)begin / BITSPERDIG < xn) {
6829 size_t shift_bits, copy_end;
6830 copy_begin = begin / BITSPERDIG;
6831 shift_bits = begin % BITSPERDIG;
6832 copy_end = (end - 1) / BITSPERDIG + 1;
6833 v = bignew(copy_end - copy_begin, 1);
6835 MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
6836 negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
6838 if (shift_bits) v = rb_int_rshift(v,
SIZET2NUM(shift_bits));
6843 negative_add_one =
false;
6844 copy_begin = begin = end = 0;
6847 if (BIGNUM_NEGATIVE_P(x)) {
6848 size_t mask_size = length - shift;
6850 v = rb_int_xor(v, mask);
6851 for (
size_t i = 0; negative_add_one && i < copy_begin; i++) {
6852 if (xds[i]) negative_add_one =
false;
6854 if (negative_add_one) v = rb_int_plus(v,
INT2FIX(1));
6855 v = rb_int_and(v, mask);
6858 size_t mask_size = (size_t)end - begin;
6860 v = rb_int_and(v, mask);
6863 if (shift) v = rb_int_lshift(v,
SSIZET2NUM(shift));
6872 hash =
rb_memhash(BDIGITS(x),
sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6907 if (BIGNUM_NEGATIVE_P(x)) {
6908 x = rb_big_clone(x);
6909 BIGNUM_SET_POSITIVE_SIGN(x);
6917 return BIGNUM_SIGN(x);
6921rb_big_size(
VALUE big)
6923 return BIGSIZE(big);
6927rb_big_size_m(
VALUE big)
6933rb_big_bit_length(
VALUE big)
6938 static const BDIGIT char_bit[1] = { CHAR_BIT };
6939 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(
size_t))];
6941 BDIGIT result_bary[bdigit_roomof(
sizeof(
size_t)+1)];
6943 numbytes = rb_absint_size(big, &nlz_bits);
6948 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6949 if (nlz_bits != CHAR_BIT-1) {
6958 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6959 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6962 nlz_bary[0] = nlz_bits;
6964 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
6966 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6967 BARY_SUB(result_bary, result_bary, nlz_bary);
6969 return rb_integer_unpack(result_bary, numberof(result_bary),
sizeof(BDIGIT), 0,
6974rb_big_odd_p(
VALUE num)
6976 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6980rb_big_even_p(
VALUE num)
6982 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6988unsigned long rb_ulong_isqrt(
unsigned long);
6989#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6990BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6991# ifdef ULL_TO_DOUBLE
6992# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6995# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6997#ifndef BDIGIT_DBL_TO_DOUBLE
6998# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
7002rb_big_isqrt(
VALUE n)
7004 BDIGIT *nds = BDIGITS(n);
7005 size_t len = BIGNUM_LEN(n);
7008 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds,
len));
7009#if SIZEOF_BDIGIT > SIZEOF_LONG
7016 size_t shift =
FIX2LONG(rb_big_bit_length(n)) / 4;
7020 x = rb_int_plus(rb_int_lshift(x,
SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n,
SIZET2NUM(shift + 1)), x));
7021 VALUE xx = rb_int_mul(x, x);
7022 while (rb_int_gt(xx, n)) {
7023 xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x),
INT2FIX(1)));
7024 x = rb_int_minus(x,
INT2FIX(1));
7032bary_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)
7040 bdigits_to_mpz(x, xds, xn);
7041 bdigits_to_mpz(y, yds, yn);
7042 bdigits_to_mpz(m, mds, mn);
7043 mpz_powm(z, x, y, m);
7044 bdigits_from_mpz(z, zds, &count);
7045 BDIGITS_ZERO(zds+count, zn-count);
7058 size_t xn, yn, mn, zn;
7072 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7073 if (nega_flg & BIGNUM_POSITIVE_P(z)) {
7074 z = rb_big_minus(z, m);
7079 return rb_big_norm(z);
7085 if (
RTEST(rb_int_odd_p(y))) {
7086 tmp = rb_int_mul(tmp, x);
7087 tmp = rb_int_modulo(tmp, m);
7089 x = rb_int_mul(x, x);
7090 x = rb_int_modulo(x, m);
7092 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7094 tmp = rb_int_mul(tmp, x);
7095 tmp = rb_int_modulo(tmp, m);
7097 x = rb_int_mul(x, x);
7098 x = rb_int_modulo(x, m);
7101 if (nega_flg && rb_int_positive_p(tmp)) {
7102 tmp = rb_int_minus(tmp, m);
7113int_pow_tmp1(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7120 if (
RTEST(rb_int_odd_p(y))) {
7121 tmp = (tmp * xx) % mm;
7123 xx = (xx * xx) % mm;
7125 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7127 tmp = (tmp * xx) % mm;
7129 xx = (xx * xx) % mm;
7132 if (nega_flg && tmp) {
7139int_pow_tmp2(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7147# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7152# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7156 if (
RTEST(rb_int_odd_p(y))) {
7157 tmp2 = MUL_MODULO(tmp2, xx, m);
7159 xx = MUL_MODULO(xx, xx, m);
7161 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7163 tmp2 = MUL_MODULO(tmp2, xx, m);
7165 xx = MUL_MODULO(xx, xx, m);
7173 if (nega_flg && tmp) {
7191rb_int_powm(
int const argc,
VALUE *
const argv,
VALUE const num)
7196 return rb_int_pow(num, argv[0]);
7199 VALUE const a = num;
7200 VALUE const b = argv[0];
7204 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7206 if (rb_int_negative_p(b)) {
7207 rb_raise(
rb_eRangeError,
"Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7210 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless all arguments are integers");
7213 if (rb_int_negative_p(m)) {
7214 m = rb_int_uminus(m);
7219 long const half_val = (long)HALF_LONG_MSB;
7222 if (mm == 1)
return INT2FIX(0);
7223 if (mm <= half_val) {
7224 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7227 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7233 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7264 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 REALLOC_N
Old name of RB_REALLOC_N.
#define NUM2SSIZET
Old name of RB_NUM2SSIZE.
#define ISSPACE
Old name of rb_isspace.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define xfree
Old name of ruby_xfree.
#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.