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));
2967 rb_cmperr_reason(a, b,
"comparator returned nil");
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;
3039 size_t old_len = RBIGNUM(big)->as.heap.len;
3041 BIGNUM_SET_LEN(big,
len);
3042 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)RBIGNUM(big)->as.ary, embed_capa *
sizeof(BDIGIT));
3044 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT,
len);
3045 SIZED_FREE_N(ds, old_len);
3049 if (BIGNUM_LEN(big) == 0) {
3050 RBIGNUM(big)->as.heap.digits =
ALLOC_N(BDIGIT,
len);
3052 else if (BIGNUM_LEN(big) !=
len) {
3053 SIZED_REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT,
len, BIGNUM_LEN(big));
3062 rb_big_realloc(big,
len);
3063 BIGNUM_SET_LEN(big,
len);
3067bignew_1(
VALUE klass,
size_t len,
int sign)
3071 if (big_embeddable_p(
len)) {
3072 size_t size = big_embed_size(
len);
3074 NEWOBJ_OF(big,
struct RBignum, klass,
3078 BIGNUM_SET_SIGN(bigv, sign);
3079 BIGNUM_SET_LEN(bigv,
len);
3080 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)big->as.ary,
len *
sizeof(BDIGIT));
3083 NEWOBJ_OF(big,
struct RBignum, klass,
3086 BIGNUM_SET_SIGN(bigv, sign);
3088 big->as.heap.len =
len;
3095rb_big_new(
size_t len,
int sign)
3097 VALUE obj = bignew(
len, sign != 0);
3098 memset(BIGNUM_DIGITS(obj), 0,
len *
sizeof(BDIGIT));
3105 size_t len = BIGNUM_LEN(x);
3108 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT,
len);
3113big_extend_carry(
VALUE x)
3115 rb_big_resize(x, BIGNUM_LEN(x)+1);
3116 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3123 long i = BIGNUM_LEN(x);
3124 BDIGIT *ds = BDIGITS(x);
3126 if (bary_2comp(ds, i)) {
3127 big_extend_carry(x);
3138abs2twocomp(
VALUE *xp,
long *n_ret)
3141 long n = BIGNUM_LEN(x);
3142 BDIGIT *ds = BDIGITS(x);
3147 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3149 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3150 bary_2comp(BDIGITS(z), n);
3159twocomp2abs_bang(
VALUE x,
int hibits)
3161 BIGNUM_SET_SIGN(x, !hibits);
3170 size_t len = BIGNUM_LEN(x);
3171 BDIGIT *ds = BDIGITS(x);
3173 if (
len == 0)
return x;
3174 while (--
len && !ds[
len]);
3175 if (BIGNUM_LEN(x) >
len+1) {
3176 rb_big_resize(x,
len+1);
3184 size_t n = BIGNUM_LEN(x);
3185 BDIGIT *ds = BDIGITS(x);
3186#if SIZEOF_BDIGIT < SIZEOF_LONG
3194 if (n == 0)
return INT2FIX(0);
3196#if SIZEOF_BDIGIT < SIZEOF_LONG
3197 if (
sizeof(
long)/SIZEOF_BDIGIT < n)
3203 u = (
unsigned long)(BIGUP(u) + ds[i]);
3213 if (BIGNUM_POSITIVE_P(x)) {
3221 rb_big_resize(x, n);
3228 if (RB_BIGNUM_TYPE_P(x)) {
3241rb_uint2big(uintptr_t n)
3245 BDIGIT *digits = BDIGITS(big);
3247#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3251 digits[i] = BIGLO(n);
3257 while (--i && !digits[i]) ;
3258 BIGNUM_SET_LEN(big, i+1);
3263rb_int2big(intptr_t n)
3270 u = 1 + (
VALUE)(-(n + 1));
3276 big = rb_uint2big(u);
3278 BIGNUM_SET_NEGATIVE_SIGN(big);
3284rb_uint2inum(uintptr_t n)
3287 return rb_uint2big(n);
3291rb_int2inum(intptr_t n)
3294 return rb_int2big(n);
3298rb_big_pack(
VALUE val,
unsigned long *buf,
long num_longs)
3300 rb_integer_pack(val, buf, num_longs,
sizeof(
long), 0,
3306rb_big_unpack(
unsigned long *buf,
long num_longs)
3308 return rb_integer_unpack(buf, num_longs,
sizeof(
long), 0,
3330rb_absint_size(
VALUE val,
int *nlz_bits_ret)
3334 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3336 int num_leading_zeros;
3345#if SIZEOF_BDIGIT >= SIZEOF_LONG
3350 for (i = 0; i < numberof(fixbuf); i++) {
3351 fixbuf[i] = BIGLO(v);
3357 de = fixbuf + numberof(fixbuf);
3361 de = dp + BIGNUM_LEN(val);
3363 while (dp < de && de[-1] == 0)
3370 num_leading_zeros = nlz(de[-1]);
3372 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3373 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3377absint_numwords_small(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3379 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3380 size_t div = val_numbits / word_numbits;
3381 size_t mod = val_numbits % word_numbits;
3384 numwords = mod == 0 ? div : div + 1;
3385 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3386 *nlz_bits_ret = nlz_bits;
3391absint_numwords_generic(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3393 static const BDIGIT char_bit[1] = { CHAR_BIT };
3394 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(numbytes))];
3395 BDIGIT val_numbits_bary[bdigit_roomof(
sizeof(numbytes) + 1)];
3396 BDIGIT nlz_bits_in_msbyte_bary[1];
3397 BDIGIT word_numbits_bary[bdigit_roomof(
sizeof(word_numbits))];
3398 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3399 BDIGIT mod_bary[numberof(word_numbits_bary)];
3400 BDIGIT one[1] = { 1 };
3406 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3415 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
3417 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3418 if (nlz_bits_in_msbyte)
3419 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3420 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1,
sizeof(word_numbits), 0,
3422 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3423 if (BARY_ZERO_P(mod_bary)) {
3427 BARY_ADD(div_bary, div_bary, one);
3428 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1,
sizeof(mod), 0,
3430 nlz_bits = word_numbits - mod;
3432 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1,
sizeof(numwords), 0,
3436#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3441 *nlz_bits_ret = nlz_bits;
3465rb_absint_numwords(
VALUE val,
size_t word_numbits,
size_t *nlz_bits_ret)
3468 int nlz_bits_in_msbyte;
3470 size_t nlz_bits = 0;
3472 if (word_numbits == 0)
3475 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3477 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3478 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3479 if (debug_integer_pack) {
3480 size_t numwords0, nlz_bits0;
3481 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3488 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3490 if (numwords == (
size_t)-1)
3494 *nlz_bits_ret = nlz_bits;
3532 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3542#if SIZEOF_BDIGIT >= SIZEOF_LONG
3547 for (i = 0; i < numberof(fixbuf); i++) {
3548 fixbuf[i] = BIGLO(v);
3554 de = fixbuf + numberof(fixbuf);
3558 de = dp + BIGNUM_LEN(val);
3560 while (dp < de && de[-1] == 0)
3562 while (dp < de && dp[0] == 0)
3629rb_integer_pack(
VALUE val,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3634 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3647#if SIZEOF_BDIGIT >= SIZEOF_LONG
3652 for (i = 0; i < numberof(fixbuf); i++) {
3653 fixbuf[i] = BIGLO(v);
3659 num_bdigits = numberof(fixbuf);
3662 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3664 num_bdigits = BIGNUM_LEN(val);
3667 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3715rb_integer_unpack(
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3722 BDIGIT fixbuf[2] = { 0, 0 };
3724 validate_integer_pack_format(numwords, wordsize, nails, flags,
3735 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3737 if (LONG_MAX-1 < num_bdigits)
3738 rb_raise(rb_eArgError,
"too big to unpack as an integer");
3744 val = bignew((
long)num_bdigits, 0);
3747 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3751 big_extend_carry(val);
3753 else if (num_bdigits == numberof(fixbuf)) {
3754 val = bignew((
long)num_bdigits+1, 0);
3755 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3756 BDIGITS(val)[num_bdigits++] = 1;
3759 ds[num_bdigits++] = 1;
3764 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3769 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3771 return LONG2FIX((
long)-(BDIGIT_DBL_SIGNED)u);
3772 val = bignew((
long)num_bdigits, 0 <= sign);
3773 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3777 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3779 BIGNUM_SET_SIGN(val, 0 <= sign);
3782 return bigtrunc(val);
3783 return bignorm(val);
3786#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3788NORETURN(
static inline void invalid_radix(
int base));
3789NORETURN(
static inline void invalid_integer(
VALUE s));
3792valid_radix_p(
int base)
3794 return (1 < base && base <= 36);
3798invalid_radix(
int base)
3800 rb_raise(rb_eArgError,
"invalid radix %d", base);
3804invalid_integer(
VALUE s)
3806 rb_raise(rb_eArgError,
"invalid value for Integer(): %+"PRIsVALUE, s);
3810str2big_scan_digits(
const char *s,
const char *str,
int base,
int badcheck,
size_t *num_digits_p, ssize_t *len_p)
3813 size_t num_digits = 0;
3814 const char *digits_start = str;
3815 const char *digits_end = str;
3816 ssize_t
len = *len_p;
3826 if (badcheck && *str ==
'_')
return FALSE;
3828 while ((c = *str++) != 0) {
3831 if (badcheck)
return FALSE;
3834 nondigit = (char) c;
3836 else if ((c = conv_digit(c)) < 0 || c >= base) {
3844 if (
len > 0 && !--
len)
break;
3846 if (badcheck && nondigit)
return FALSE;
3847 if (badcheck &&
len) {
3849 while (*str &&
ISSPACE(*str)) {
3851 if (
len > 0 && !--
len)
break;
3857 *num_digits_p = num_digits;
3858 *len_p = digits_end - digits_start;
3865 const char *digits_start,
3866 const char *digits_end,
3879 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3880 z = bignew(num_bdigits, sign);
3884 for (p = digits_end; digits_start < p; p--) {
3885 if ((c = conv_digit(p[-1])) < 0)
3887 dd |= (BDIGIT_DBL)c << numbits;
3888 numbits += bits_per_digit;
3889 if (BITSPERDIG <= numbits) {
3892 numbits -= BITSPERDIG;
3898 RUBY_ASSERT((
size_t)(dp - BDIGITS(z)) == num_bdigits);
3906 const char *digits_start,
3907 const char *digits_end,
3920 z = bignew(num_bdigits, sign);
3922 BDIGITS_ZERO(zds, num_bdigits);
3924 for (p = digits_start; p < digits_end; p++) {
3925 if ((c = conv_digit(*p)) < 0)
3931 num += (BDIGIT_DBL)zds[i]*base;
3932 zds[i++] = BIGLO(num);
3950 const char *digits_start,
3951 const char *digits_end,
3954 int digits_per_bdigits_dbl,
3960 BDIGIT *uds, *vds, *tds;
3962 BDIGIT_DBL current_base;
3964 int power_level = 0;
3971 uds =
ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3972 vds = uds + num_bdigits;
3974 powerv = power_cache_get_power(base, power_level, NULL);
3979 m = digits_per_bdigits_dbl;
3980 if (num_digits < (
size_t)m)
3981 m = (int)num_digits;
3982 for (p = digits_end; digits_start < p; p--) {
3983 if ((c = conv_digit(p[-1])) < 0)
3985 dd = dd + c * current_base;
3986 current_base *= base;
3990 uds[i++] = BIGLO(dd);
3991 uds[i++] = (BDIGIT)BIGDN(dd);
3993 m = digits_per_bdigits_dbl;
3994 if (num_digits < (
size_t)m)
3995 m = (
int)num_digits;
4000 for (unit = 2; unit < num_bdigits; unit *= 2) {
4001 for (i = 0; i < num_bdigits; i += unit*2) {
4002 if (2*unit <= num_bdigits - i) {
4003 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
4004 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
4006 else if (unit <= num_bdigits - i) {
4007 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
4008 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
4011 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
4015 powerv = power_cache_get_power(base, power_level, NULL);
4020 BARY_TRUNC(uds, num_bdigits);
4021 z = bignew(num_bdigits, sign);
4022 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
4034 const char *digits_start,
4035 const char *digits_end,
4048 buf =
ALLOCV_N(
char, tmps, num_digits+1);
4050 for (q = digits_start; q < digits_end; q++) {
4051 if (conv_digit(*q) < 0)
4058 mpz_set_str(mz, buf, base);
4060 z = bignew(zn, sign);
4062 bdigits_from_mpz(mz, BDIGITS(z), &count);
4063 BDIGITS_ZERO(zds+count, zn-count);
4073static VALUE rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base);
4092rb_cstr_to_inum(
const char *str,
int base,
int badcheck)
4095 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4121rb_int_parse_cstr(
const char *str, ssize_t
len,
char **endp,
size_t *ndigits,
4122 int base,
int flags)
4124 const char *
const s = str;
4132 const char *digits_start, *digits_end;
4133 size_t num_digits = 0;
4135 const ssize_t len0 =
len;
4136 const int badcheck = !endp;
4139 if (len > 0 && len <= (n)) goto bad; \
4143#define ASSERT_LEN() do {\
4144 RUBY_ASSERT(len != 0); \
4145 if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
4151 if (
len && (flags & RB_INT_PARSE_SIGN)) {
4154 if (str[0] ==
'+') {
4157 else if (str[0] ==
'-') {
4164 if (str[0] ==
'0' &&
len > 1) {
4186 else if (base < -1) {
4193 else if (
len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4196 else if (base == 2) {
4197 if (str[0] ==
'0' && (str[1] ==
'b'||str[1] ==
'B')) {
4201 else if (base == 8) {
4202 if (str[0] ==
'0' && (str[1] ==
'o'||str[1] ==
'O')) {
4206 else if (base == 10) {
4207 if (str[0] ==
'0' && (str[1] ==
'd'||str[1] ==
'D')) {
4211 else if (base == 16) {
4212 if (str[0] ==
'0' && (str[1] ==
'x'||str[1] ==
'X')) {
4216 if (!valid_radix_p(base)) {
4217 invalid_radix(base);
4220 num_digits = str - s;
4221 if (*str ==
'0' &&
len != 1) {
4223 const char *end =
len < 0 ? NULL : str +
len;
4225 while ((c = *++str) ==
'0' ||
4226 ((flags & RB_INT_PARSE_UNDERSCORE) && c ==
'_')) {
4235 if (str == end)
break;
4238 if (end)
len = end - str;
4242 if (c < 0 || c >= base) {
4243 if (!badcheck && num_digits) z =
INT2FIX(0);
4247 if (ndigits) *ndigits = num_digits;
4248 val = ruby_scan_digits(str,
len, base, &num_digits, &ov);
4250 const char *end = &str[num_digits];
4251 if (num_digits > 0 && *end ==
'_' && (flags & RB_INT_PARSE_UNDERSCORE))
4253 if (endp) *endp = (
char *)end;
4254 if (ndigits) *ndigits += num_digits;
4256 if (num_digits == 0)
return Qnil;
4257 while (
len < 0 ? *end : end < str +
len) {
4266 long result = -(long)val;
4271 VALUE big = rb_uint2big(val);
4272 BIGNUM_SET_SIGN(big, sign);
4273 return bignorm(big);
4279 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4281 if (endp) *endp = (
char *)(str +
len);
4282 if (ndigits) *ndigits += num_digits;
4283 digits_end = digits_start +
len;
4286 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4287 bit_length(base-1));
4290 int digits_per_bdigits_dbl;
4291 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4292 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4295 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4296 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4301 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4302 z = str2big_normal(sign, digits_start, digits_end,
4306 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4307 num_bdigits, digits_per_bdigits_dbl, base);
4314 if (endp) *endp = (
char *)str;
4315 if (ndigits) *ndigits = num_digits;
4320rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base)
4322 return rb_int_parse_cstr(str,
len, endp, NULL, base,
4323 RB_INT_PARSE_DEFAULT);
4327rb_str_convert_to_inum(
VALUE str,
int base,
int badcheck,
int raise_exception)
4337 ret = rb_cstr_parse_inum(s,
len, (badcheck ? NULL : &end), base);
4340 if (!raise_exception)
return Qnil;
4341 invalid_integer(str);
4349rb_str_to_inum(
VALUE str,
int base,
int badcheck)
4351 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4355rb_str2big_poweroftwo(
VALUE arg,
int base,
int badcheck)
4358 const char *s, *str;
4359 const char *digits_start, *digits_end;
4364 if (!valid_radix_p(base) || !POW2_P(base)) {
4365 invalid_radix(base);
4370 len = RSTRING_LEN(arg);
4378 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4379 invalid_integer(arg);
4380 digits_end = digits_start +
len;
4382 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4383 bit_length(base-1));
4391rb_str2big_normal(
VALUE arg,
int base,
int badcheck)
4394 const char *s, *str;
4395 const char *digits_start, *digits_end;
4400 int digits_per_bdigits_dbl;
4403 if (!valid_radix_p(base)) {
4404 invalid_radix(base);
4409 len = RSTRING_LEN(arg);
4410 if (
len > 0 && *str ==
'-') {
4417 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4418 invalid_integer(arg);
4419 digits_end = digits_start +
len;
4421 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4422 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4424 z = str2big_normal(positive_p, digits_start, digits_end,
4433rb_str2big_karatsuba(
VALUE arg,
int base,
int badcheck)
4436 const char *s, *str;
4437 const char *digits_start, *digits_end;
4442 int digits_per_bdigits_dbl;
4445 if (!valid_radix_p(base)) {
4446 invalid_radix(base);
4451 len = RSTRING_LEN(arg);
4452 if (
len > 0 && *str ==
'-') {
4459 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4460 invalid_integer(arg);
4461 digits_end = digits_start +
len;
4463 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4464 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4466 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4467 num_bdigits, digits_per_bdigits_dbl, base);
4476rb_str2big_gmp(
VALUE arg,
int base,
int badcheck)
4479 const char *s, *str;
4480 const char *digits_start, *digits_end;
4485 int digits_per_bdigits_dbl;
4488 if (!valid_radix_p(base)) {
4489 invalid_radix(base);
4494 len = RSTRING_LEN(arg);
4495 if (
len > 0 && *str ==
'-') {
4502 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4503 invalid_integer(arg);
4504 digits_end = digits_start +
len;
4506 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4507 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4509 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4523 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4524 BDIGIT *digits = BDIGITS(big);
4526#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4529 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4530 digits[i] = BIGLO(n);
4535 i = bdigit_roomof(SIZEOF_LONG_LONG);
4536 while (i-- && !digits[i]) ;
4537 BIGNUM_SET_LEN(big, i+1);
4555 big = rb_ull2big(u);
4557 BIGNUM_SET_NEGATIVE_SIGN(big);
4566 return rb_ull2big(n);
4573 return rb_ll2big(n);
4580rb_uint128t2big(uint128_t n)
4583 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4584 BDIGIT *digits = BDIGITS(big);
4586 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4587 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4590 i = bdigit_roomof(SIZEOF_INT128_T);
4591 while (i-- && !digits[i]) ;
4592 BIGNUM_SET_LEN(big, i+1);
4597rb_int128t2big(int128_t n)
4604 u = 1 + (uint128_t)(-(n + 1));
4610 big = rb_uint128t2big(u);
4612 BIGNUM_SET_NEGATIVE_SIGN(big);
4619rb_cstr2inum(
const char *str,
int base)
4621 return rb_cstr_to_inum(str, base, base==0);
4627 return rb_str_to_inum(str, base, base==0);
4631big_shift3(
VALUE x,
int lshift_p,
size_t shift_numdigits,
int shift_numbits)
4640 if (LONG_MAX < shift_numdigits) {
4644 s1 = shift_numdigits;
4646 if ((
size_t)s1 != shift_numdigits)
goto too_big;
4648 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1)
goto too_big;
4649 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4651 BDIGITS_ZERO(zds, s1);
4653 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4658 if (LONG_MAX < shift_numdigits || (
size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4659 if (BIGNUM_POSITIVE_P(x) ||
4660 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4665 s1 = shift_numdigits;
4667 hibitsx = abs2twocomp(&x, &xn);
4675 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4676 twocomp2abs_bang(z, hibitsx != 0);
4687 size_t shift_numdigits;
4695 sign = rb_integer_pack(y, lens, numberof(lens),
sizeof(
size_t), 0,
4698 lshift_p = !lshift_p;
4702 if (1 < sign || CHAR_BIT <= lens[1])
4706 if (1 < sign || CHAR_BIT <= lens[1])
4709 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4710 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4711 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4712 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4716big_lshift(
VALUE x,
unsigned long shift)
4718 long s1 = shift/BITSPERDIG;
4719 int s2 = (int)(shift%BITSPERDIG);
4720 return big_shift3(x, 1, s1, s2);
4724big_rshift(
VALUE x,
unsigned long shift)
4726 long s1 = shift/BITSPERDIG;
4727 int s2 = (int)(shift%BITSPERDIG);
4728 return big_shift3(x, 0, s1, s2);
4731#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4733static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4734static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4737power_cache_init(
void)
4742power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret)
4758 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4759 rb_bug(
"too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4761 VALUE power = base36_power_cache[base - 2][power_level];
4764 if (power_level == 0) {
4766 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4767 power = bignew(2, 1);
4768 bdigitdbl2bary(BDIGITS(power), 2, dd);
4769 numdigits = numdigits0;
4772 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4776 base36_power_cache[base - 2][power_level] = power;
4777 base36_numdigits_cache[base - 2][power_level] = numdigits;
4778 rb_vm_register_global_object(power);
4781 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4789 int hbase2_numdigits;
4797 if (LONG_MAX-1 <
len)
4798 rb_raise(rb_eArgError,
"too big number");
4800 b2s->ptr = RSTRING_PTR(b2s->result);
4806big2str_2bdigits(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t taillen)
4810 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4811 int beginning = !b2s->ptr;
4815 num = bary2bdigitdbl(xds, xn);
4823 BDIGIT_DBL idx = num % b2s->base;
4825 p[--j] = ruby_digitmap[idx];
4827 len =
sizeof(buf) - j;
4828 big2str_alloc(b2s,
len + taillen);
4833 j = b2s->hbase2_numdigits;
4835 BDIGIT_DBL idx = num % b2s->base;
4837 p[--j] = ruby_digitmap[idx];
4839 len = b2s->hbase2_numdigits;
4845big2str_karatsuba(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t wn,
4846 int power_level,
size_t taillen)
4849 size_t half_numdigits, lower_numdigits;
4850 int lower_power_level;
4875 if (xn == 0 || bary_zero_p(xds, xn)) {
4878 power_cache_get_power(b2s->base, power_level, &
len);
4879 memset(b2s->ptr,
'0',
len);
4885 if (power_level == 0) {
4886 big2str_2bdigits(b2s, xds, xn, taillen);
4890 lower_power_level = power_level-1;
4891 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4895 half_numdigits = lower_numdigits;
4897 while (0 < lower_power_level &&
4899 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4900 lower_power_level--;
4901 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4906 if (lower_power_level == 0 &&
4908 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4910 len = half_numdigits * 2 - lower_numdigits;
4911 memset(b2s->ptr,
'0',
len);
4914 big2str_2bdigits(b2s, xds, xn, taillen);
4922 if (lower_power_level != power_level-1 && b2s->ptr) {
4923 len = (half_numdigits - lower_numdigits) * 2;
4924 memset(b2s->ptr,
'0',
len);
4928 shift = nlz(bds[bn-1]);
4930 qn = xn + BIGDIVREM_EXTRA_WORDS;
4935 tds = (BDIGIT *)bds;
4943 bary_small_lshift(tds, bds, bn, shift);
4944 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4947 bigdivrem_restoring(xds, qn, tds, bn);
4956 bary_small_rshift(rds, rds, rn, shift, 0);
4959 BARY_TRUNC(qds, qn);
4961 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4962 BARY_TRUNC(rds, rn);
4963 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4968big2str_base_poweroftwo(
VALUE x,
int base)
4970 int word_numbits = ffs(base) - 1;
4974 numwords = rb_absint_numwords(x, word_numbits, NULL);
4975 if (BIGNUM_NEGATIVE_P(x)) {
4976 if (LONG_MAX-1 < numwords)
4977 rb_raise(rb_eArgError,
"too big number");
4979 ptr = RSTRING_PTR(result);
4980 *ptr++ = BIGNUM_POSITIVE_P(x) ?
'+' :
'-';
4983 if (LONG_MAX < numwords)
4984 rb_raise(rb_eArgError,
"too big number");
4986 ptr = RSTRING_PTR(result);
4988 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4990 while (0 < numwords) {
4991 *ptr = ruby_digitmap[*(
unsigned char *)ptr];
4999rb_big2str_poweroftwo(
VALUE x,
int base)
5001 return big2str_base_poweroftwo(x, base);
5005big2str_generic(
VALUE x,
int base)
5015 BARY_TRUNC(xds, xn);
5021 if (!valid_radix_p(base))
5022 invalid_radix(base);
5024 if (xn >= LONG_MAX/BITSPERDIG) {
5025 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5029 power = power_cache_get_power(base, power_level, NULL);
5030 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
5031 (
size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
5033 power = power_cache_get_power(base, power_level, NULL);
5035 RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
5037 if ((
size_t)BIGNUM_LEN(power) <= xn) {
5051 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5052 b2s_data.base = base;
5053 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5055 b2s_data.result =
Qnil;
5056 b2s_data.ptr = NULL;
5058 if (power_level == 0) {
5059 big2str_2bdigits(&b2s_data, xds, xn, 0);
5065 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5066 wds =
ALLOCV_N(BDIGIT, tmpw, xn + wn);
5067 MEMCPY(wds, xds, BDIGIT, xn);
5068 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5074 *b2s_data.ptr =
'\0';
5075 rb_str_resize(b2s_data.result, (
long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5078 return b2s_data.result;
5082rb_big2str_generic(
VALUE x,
int base)
5084 return big2str_generic(x, base);
5089big2str_gmp(
VALUE x,
int base)
5094 BDIGIT *xds = BDIGITS(x);
5095 size_t xn = BIGNUM_LEN(x);
5098 bdigits_to_mpz(mx, xds, xn);
5100 size = mpz_sizeinbase(mx, base);
5102 if (BIGNUM_NEGATIVE_P(x)) {
5109 mpz_get_str(RSTRING_PTR(str), base, mx);
5112 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] ==
'\0') {
5121rb_big2str_gmp(
VALUE x,
int base)
5123 return big2str_gmp(x, base);
5128rb_big2str1(
VALUE x,
int base)
5140 BARY_TRUNC(xds, xn);
5146 if (!valid_radix_p(base))
5147 invalid_radix(base);
5149 if (xn >= LONG_MAX/BITSPERDIG) {
5150 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5155 return big2str_base_poweroftwo(x, base);
5159 if (GMP_BIG2STR_DIGITS < xn) {
5160 return big2str_gmp(x, base);
5164 return big2str_generic(x, base);
5170 return rb_big2str1(x, base);
5176#if SIZEOF_LONG > SIZEOF_BDIGIT
5179 size_t len = BIGNUM_LEN(x);
5185 if (BIGSIZE(x) >
sizeof(
long)) {
5189#if SIZEOF_LONG <= SIZEOF_BDIGIT
5190 num = (
unsigned long)ds[0];
5193 for (i = 0; i <
len; i++) {
5195 num += (
unsigned long)ds[
len - i - 1];
5204 unsigned long num = big2ulong(x,
"unsigned long");
5206 if (BIGNUM_POSITIVE_P(x)) {
5210 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5211 return -(long)(num-1)-1;
5213 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long");
5219 unsigned long num = big2ulong(x,
"long");
5221 if (BIGNUM_POSITIVE_P(x)) {
5222 if (num <= LONG_MAX)
5226 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5227 return -(long)(num-1)-1;
5229 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long'");
5237#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5240 size_t len = BIGNUM_LEN(x);
5242 BDIGIT *ds = BDIGITS(x);
5246 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5248#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5252 for (i = 0; i <
len; i++) {
5254 num += ds[
len - i - 1];
5263 unsigned LONG_LONG num = big2ull(x,
"unsigned long long");
5265 if (BIGNUM_POSITIVE_P(x)) {
5269 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5272 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long long");
5278 unsigned LONG_LONG num = big2ull(x,
"long long");
5280 if (BIGNUM_POSITIVE_P(x)) {
5281 if (num <= LLONG_MAX)
5285 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5288 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long long'");
5300 double u = (d < 0)?-d:d;
5310 u /= (double)(BIGRAD);
5313 z = bignew(i, d>=0);
5314 digits = BDIGITS(z);
5328 return bignorm(dbl2big(d));
5335 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5336 BDIGIT *ds = BDIGITS(x), dl;
5339 bits = i * BITSPERDIG - nlz(ds[i-1]);
5340 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5344 if (bits > DBL_MANT_DIG+1)
5345 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5349 d = ds[i] + BIGRAD*d;
5352 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5353 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5361 BDIGIT mask = BDIGMAX;
5373 if (lo > INT_MAX / BITSPERDIG)
5375 else if (lo < INT_MIN / BITSPERDIG)
5378 d = ldexp(d, (
int)(lo * BITSPERDIG));
5382 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5389 double d = big2dbl(x);
5411 if (yd > 0.0)
return INT2FIX(-1);
5416#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5443 rel = rb_big_cmp(x, y);
5444 if (yf == 0.0 || rel !=
INT2FIX(0))
5451#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG
5452COMPILER_WARNING_PUSH
5453#if __has_warning("-Wimplicit-int-float-conversion")
5454COMPILER_WARNING_IGNORED(-Wimplicit-
int-
float-conversion)
5456static const double LONG_MAX_as_double = LONG_MAX;
5472#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5474 return RBOOL(xd == yd);
5477 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5481 return RBOOL(xn == yn);
5485 return rb_big_eq(x, y);
5498 if (sx < sy)
return INT2FIX(-1);
5502 else if (RB_BIGNUM_TYPE_P(y)) {
5503 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5504 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5505 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5509 return rb_integer_float_cmp(x, y);
5514 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5531 rel = rb_big_cmp(x, y);
5534 rel = rb_integer_float_cmp(x, y);
5539 case big_op_gt:
id =
'>';
break;
5540 case big_op_ge:
id = idGE;
break;
5541 case big_op_lt:
id =
'<';
break;
5542 case big_op_le:
id = idLE;
break;
5551 case big_op_gt:
return RBOOL(n > 0);
5552 case big_op_ge:
return RBOOL(n >= 0);
5553 case big_op_lt:
return RBOOL(n < 0);
5554 case big_op_le:
return RBOOL(n <= 0);
5562 return big_op(x, y, big_op_gt);
5568 return big_op(x, y, big_op_ge);
5574 return big_op(x, y, big_op_lt);
5580 return big_op(x, y, big_op_le);
5598 return RBOOL(bignorm(x) == y);
5600 else if (RB_BIGNUM_TYPE_P(y)) {
5603 return rb_integer_float_eq(x, y);
5608 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5609 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5610 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5616 if (!RB_BIGNUM_TYPE_P(y))
return Qfalse;
5617 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5618 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5619 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5623rb_big_uminus(
VALUE x)
5625 VALUE z = rb_big_clone(x);
5635 VALUE z = rb_big_clone(x);
5636 BDIGIT *ds = BDIGITS(z);
5637 long n = BIGNUM_LEN(z);
5641 if (BIGNUM_POSITIVE_P(z)) {
5642 if (bary_add_one(ds, n)) {
5643 big_extend_carry(z);
5645 BIGNUM_SET_NEGATIVE_SIGN(z);
5649 if (bary_add_one(ds, n))
5652 BIGNUM_SET_POSITIVE_SIGN(z);
5662 BDIGIT *xds, *yds, *zds;
5667 zn = xn < yn ? yn : xn;
5675 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5676 bary_2comp(zds, zn);
5677 BIGNUM_SET_NEGATIVE_SIGN(z);
5686bigsub_int(
VALUE x,
long y0)
5691 BDIGIT_DBL_SIGNED num;
5702#if SIZEOF_BDIGIT < SIZEOF_LONG
5703 if (zn < bdigit_roomof(SIZEOF_LONG))
5704 zn = bdigit_roomof(SIZEOF_LONG);
5706 z = bignew(zn, BIGNUM_SIGN(x));
5709#if SIZEOF_BDIGIT >= SIZEOF_LONG
5711 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5712 if (xn == 1 && num < 0) {
5714 zds[0] = (BDIGIT)-num;
5718 zds[0] = BIGLO(num);
5726 for (i=0; i < xn; i++) {
5727 if (y == 0)
goto y_is_zero_x;
5728 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5729 zds[i] = BIGLO(num);
5733 for (; i < zn; i++) {
5734 if (y == 0)
goto y_is_zero_z;
5736 zds[i] = BIGLO(num);
5743 for (; i < xn; i++) {
5745 if (num == 0)
goto num_is_zero_x;
5747 zds[i] = BIGLO(num);
5750#if SIZEOF_BDIGIT < SIZEOF_LONG
5751 for (; i < zn; i++) {
5753 if (num == 0)
goto num_is_zero_z;
5754 zds[i] = BIGLO(num);
5760 for (; i < xn; i++) {
5764#if SIZEOF_BDIGIT < SIZEOF_LONG
5765 for (; i < zn; i++) {
5783bigadd_int(
VALUE x,
long y)
5798#if SIZEOF_BDIGIT < SIZEOF_LONG
5799 if (zn < bdigit_roomof(SIZEOF_LONG))
5800 zn = bdigit_roomof(SIZEOF_LONG);
5804 z = bignew(zn, BIGNUM_SIGN(x));
5807#if SIZEOF_BDIGIT >= SIZEOF_LONG
5808 num = (BDIGIT_DBL)xds[0] + y;
5809 zds[0] = BIGLO(num);
5817 for (i=0; i < xn; i++) {
5818 if (y == 0)
goto y_is_zero_x;
5819 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5820 zds[i] = BIGLO(num);
5824 for (; i < zn; i++) {
5825 if (y == 0)
goto y_is_zero_z;
5827 zds[i] = BIGLO(num);
5835 for (;i < xn; i++) {
5837 if (num == 0)
goto num_is_zero_x;
5838 num += (BDIGIT_DBL)xds[i];
5839 zds[i] = BIGLO(num);
5842 for (; i < zn; i++) {
5844 if (num == 0)
goto num_is_zero_z;
5845 zds[i] = BIGLO(num);
5850 for (;i < xn; i++) {
5854 for (; i < zn; i++) {
5871 sign = (sign == BIGNUM_SIGN(y));
5872 if (BIGNUM_SIGN(x) != sign) {
5873 if (sign)
return bigsub(y, x);
5874 return bigsub(x, y);
5877 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5878 len = BIGNUM_LEN(x) + 1;
5881 len = BIGNUM_LEN(y) + 1;
5883 z = bignew(
len, sign);
5885 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5886 BDIGITS(x), BIGNUM_LEN(x),
5887 BDIGITS(y), BIGNUM_LEN(y));
5899 if ((n > 0) != BIGNUM_SIGN(x)) {
5903 return bigsub_int(x, n);
5908 return bigadd_int(x, n);
5910 else if (RB_BIGNUM_TYPE_P(y)) {
5911 return bignorm(bigadd(x, y, 1));
5928 if ((n > 0) != BIGNUM_SIGN(x)) {
5932 return bigadd_int(x, n);
5937 return bigsub_int(x, n);
5939 else if (RB_BIGNUM_TYPE_P(y)) {
5940 return bignorm(bigadd(x, y, 0));
5958 if (MUL_OVERFLOW_LONG_P(2, xn))
5959 rb_raise(rb_eArgError,
"square overflow");
5967 if (xn < NAIVE_MUL_DIGITS)
5968 bary_sq_fast(zds, zn, xds, xn);
5970 bary_mul(zds, zn, xds, xn, xds, xn);
5981 BDIGIT *xds, *yds, *zds;
5988 if (ADD_OVERFLOW_LONG_P(xn, yn))
5989 rb_raise(rb_eArgError,
"multiplication overflow");
5992 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5998 bary_mul(zds, zn, xds, xn, yds, yn);
6011 else if (RB_BIGNUM_TYPE_P(y)) {
6020 return bignorm(bigmul0(x, y));
6026 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
6028 BDIGIT *xds, *yds, *zds;
6036 BARY_TRUNC(yds, yn);
6041 BARY_TRUNC(xds, xn);
6043 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
6044 if (divp) *divp = rb_int2big(0);
6045 if (modp) *modp = x;
6050 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6052 dd = bigdivrem_single(zds, xds, xn, dd);
6054 *modp = rb_uint2big((uintptr_t)dd);
6055 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6057 if (divp) *divp = z;
6060 if (xn == 2 && yn == 2) {
6061 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6062 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6063 BDIGIT_DBL q0 = x0 / y0;
6064 BDIGIT_DBL r0 = x0 % y0;
6066 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6069 zds[1] = BIGLO(BIGDN(q0));
6073 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6076 zds[1] = BIGLO(BIGDN(r0));
6083 qn = xn + BIGDIVREM_EXTRA_WORDS;
6084 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6094 r = bignew(rn, BIGNUM_SIGN(x));
6102 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6121 bigdivrem(x, y, divp, &mod);
6122 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6123 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6124 if (modp) *modp = bigadd(mod, y, 1);
6140 else if (RB_BIGNUM_TYPE_P(y)) {
6144 double dx = rb_big2dbl(x);
6145 return rb_flo_div_flo(
DBL2NUM(dx), y);
6151 v = rb_big_divide(x, y,
'/');
6158 bigdivmod(x, y, &z, 0);
6166 return rb_big_divide(x, y,
'/');
6172 return rb_big_divide(x, y, idDiv);
6183 else if (!RB_BIGNUM_TYPE_P(y)) {
6186 bigdivmod(x, y, 0, &z);
6199 else if (!RB_BIGNUM_TYPE_P(y)) {
6202 bigdivrem(x, y, 0, &z);
6215 else if (!RB_BIGNUM_TYPE_P(y)) {
6218 bigdivmod(x, y, &div, &mod);
6224big_shift(
VALUE x,
long n)
6227 return big_lshift(x, 1+(
unsigned long)(-(n+1)));
6229 return big_rshift(x, (
unsigned long)n);
6233enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6243 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6244 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6245 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6246 else if (ex > 0) ex = 0;
6247 if (ex) x = big_shift(x, ex);
6249 bigdivrem(x, y, &z, 0);
6251#if SIZEOF_LONG > SIZEOF_INT
6254 if (l > INT_MAX)
return HUGE_VAL;
6255 if (l < INT_MIN)
return 0.0;
6258 return ldexp(big2dbl(z), (
int)l);
6267 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6268 ey -= DBL_BIGDIG * BITSPERDIG;
6269 if (ey) y = big_shift(y, ey);
6270 return big_fdiv(x, y, ey);
6277 y = dbl2big(ldexp(frexp(
RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6278 return big_fdiv(x, y, i - DBL_MANT_DIG);
6291 return big_fdiv_int(x, rb_int2big(
FIX2LONG(y)));
6293 else if (RB_BIGNUM_TYPE_P(y)) {
6294 return big_fdiv_int(x, y);
6301 return big_fdiv_float(x, y);
6313 return DBL2NUM(rb_big_fdiv_double(x, y));
6324 if (y ==
INT2FIX(1))
return x;
6327 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6328 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6331 else if (RB_BIGNUM_TYPE_P(y)) {
6335 rb_raise(rb_eArgError,
"exponent is too large");
6350 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6351#if SIZEOF_SIZE_T == 4
6352 const size_t BIGLEN_LIMIT = 1ULL << 31;
6354 const size_t BIGLEN_LIMIT = 1ULL << 34;
6357 if (xbits == (
size_t)-1 ||
6358 (xbits > BIGLEN_LIMIT) ||
6359 MUL_OVERFLOW_LONG_P(yy, xbits) ||
6360 (xbits * yy > BIGLEN_LIMIT)) {
6361 rb_raise(rb_eArgError,
"exponent is too large");
6364 for (mask =
FIXNUM_MAX + 1; mask; mask >>= 1) {
6365 if (z) z = bigsq(z);
6367 z = z ? bigtrunc(bigmul0(z, x)) : x;
6377 return DBL2NUM(pow(rb_big2dbl(x), d));
6381bigand_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6389 if (y == 0)
return INT2FIX(0);
6391 hibitsy = 0 <= y ? 0 : BDIGMAX;
6393#if SIZEOF_BDIGIT >= SIZEOF_LONG
6401#if SIZEOF_BDIGIT < SIZEOF_LONG
6402 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6403 zn = bdigit_roomof(SIZEOF_LONG);
6409#if SIZEOF_BDIGIT >= SIZEOF_LONG
6411 zds[0] = xds[0] & BIGLO(y);
6413 for (i=0; i < xn; i++) {
6414 if (y == 0 || y == -1)
break;
6415 zds[i] = xds[i] & BIGLO(y);
6418 for (; i < zn; i++) {
6419 if (y == 0 || y == -1)
break;
6420 zds[i] = hibitsx & BIGLO(y);
6424 for (;i < xn; i++) {
6425 zds[i] = xds[i] & hibitsy;
6427 for (;i < zn; i++) {
6428 zds[i] = hibitsx & hibitsy;
6430 twocomp2abs_bang(z, hibitsx && hibitsy);
6439 BDIGIT *ds1, *ds2, *zds;
6440 long i, xn, yn, n1, n2;
6441 BDIGIT hibitsx, hibitsy;
6442 BDIGIT hibits1, hibits2;
6451 hibitsx = abs2twocomp(&x, &xn);
6453 return bigand_int(x, xn, hibitsx,
FIX2LONG(y));
6455 hibitsy = abs2twocomp(&y, &yn);
6457 tmpv = x; x = y; y = tmpv;
6458 tmpn = xn; xn = yn; yn = tmpn;
6459 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6474 for (i=0; i<n1; i++) {
6475 zds[i] = ds1[i] & ds2[i];
6478 zds[i] = hibits1 & ds2[i];
6480 twocomp2abs_bang(z, hibits1 && hibits2);
6487bigor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6495 if (y == -1)
return INT2FIX(-1);
6497 hibitsy = 0 <= y ? 0 : BDIGMAX;
6501#if SIZEOF_BDIGIT < SIZEOF_LONG
6502 if (zn < bdigit_roomof(SIZEOF_LONG))
6503 zn = bdigit_roomof(SIZEOF_LONG);
6508#if SIZEOF_BDIGIT >= SIZEOF_LONG
6510 zds[0] = xds[0] | BIGLO(y);
6512 goto y_is_fixed_point;
6515 for (i=0; i < xn; i++) {
6516 if (y == 0 || y == -1)
goto y_is_fixed_point;
6517 zds[i] = xds[i] | BIGLO(y);
6522 for (; i < zn; i++) {
6523 if (y == 0 || y == -1)
goto y_is_fixed_point;
6533 for (; i < xn; i++) {
6538 for (; i < zn; i++) {
6544 for (; i < zn; i++) {
6549 twocomp2abs_bang(z, hibitsx || hibitsy);
6558 BDIGIT *ds1, *ds2, *zds;
6559 long i, xn, yn, n1, n2;
6560 BDIGIT hibitsx, hibitsy;
6561 BDIGIT hibits1, hibits2;
6570 hibitsx = abs2twocomp(&x, &xn);
6572 return bigor_int(x, xn, hibitsx,
FIX2LONG(y));
6574 hibitsy = abs2twocomp(&y, &yn);
6576 tmpv = x; x = y; y = tmpv;
6577 tmpn = xn; xn = yn; yn = tmpn;
6578 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6593 for (i=0; i<n1; i++) {
6594 zds[i] = ds1[i] | ds2[i];
6597 zds[i] = hibits1 | ds2[i];
6599 twocomp2abs_bang(z, hibits1 || hibits2);
6606bigxor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6614 hibitsy = 0 <= y ? 0 : BDIGMAX;
6617#if SIZEOF_BDIGIT < SIZEOF_LONG
6618 if (zn < bdigit_roomof(SIZEOF_LONG))
6619 zn = bdigit_roomof(SIZEOF_LONG);
6624#if SIZEOF_BDIGIT >= SIZEOF_LONG
6626 zds[0] = xds[0] ^ BIGLO(y);
6628 for (i = 0; i < xn; i++) {
6629 zds[i] = xds[i] ^ BIGLO(y);
6632 for (; i < zn; i++) {
6633 zds[i] = hibitsx ^ BIGLO(y);
6637 for (; i < xn; i++) {
6638 zds[i] = xds[i] ^ hibitsy;
6640 for (; i < zn; i++) {
6641 zds[i] = hibitsx ^ hibitsy;
6643 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6652 BDIGIT *ds1, *ds2, *zds;
6653 long i, xn, yn, n1, n2;
6654 BDIGIT hibitsx, hibitsy;
6655 BDIGIT hibits1, hibits2;
6664 hibitsx = abs2twocomp(&x, &xn);
6666 return bigxor_int(x, xn, hibitsx,
FIX2LONG(y));
6668 hibitsy = abs2twocomp(&y, &yn);
6670 tmpv = x; x = y; y = tmpv;
6671 tmpn = xn; xn = yn; yn = tmpn;
6672 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6684 for (i=0; i<n1; i++) {
6685 zds[i] = ds1[i] ^ ds2[i];
6688 zds[i] = hibitsx ^ ds2[i];
6690 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6700 size_t shift_numdigits;
6706 unsigned long shift;
6713 shift = 1+(
unsigned long)(-(l+1));
6715 shift_numbits = (int)(shift & (BITSPERDIG-1));
6716 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6717 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6719 else if (RB_BIGNUM_TYPE_P(y)) {
6720 return bignorm(big_shift2(x, 1, y));
6730 size_t shift_numdigits;
6736 unsigned long shift;
6743 shift = 1+(
unsigned long)(-(l+1));
6745 shift_numbits = (int)(shift & (BITSPERDIG-1));
6746 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6747 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6749 else if (RB_BIGNUM_TYPE_P(y)) {
6750 return bignorm(big_shift2(x, 0, y));
6765 if (RB_BIGNUM_TYPE_P(y)) {
6766 if (BIGNUM_NEGATIVE_P(y))
6769 if (BIGSIZE(y) >
sizeof(
size_t)) {
6772#if SIZEOF_SIZE_T <= SIZEOF_LONG
6773 shift = big2ulong(y,
"long");
6775 shift = big2ull(y,
"long long");
6783 s1 = shift/BITSPERDIG;
6784 s2 = shift%BITSPERDIG;
6785 bit = (BDIGIT)1 << s2;
6787 if (s1 >= BIGNUM_LEN(x))
6791 if (BIGNUM_POSITIVE_P(x))
6793 if (xds[s1] & (bit-1))
6795 for (i = 0; i < s1; i++)
6806 size_t copy_begin, xn, shift;
6807 ssize_t begin, length, end;
6808 bool negative_add_one;
6815 shift = begin < 0 ? -begin : 0;
6819 if (length < 0)
return rb_big_rshift(x, beg);
6820 if (length == 0 || end <= 0)
return INT2FIX(0);
6821 if (begin < 0) begin = 0;
6823 if ((
size_t)(end - 1) / BITSPERDIG >= xn) {
6825 end = xn * BITSPERDIG;
6828 if ((
size_t)begin / BITSPERDIG < xn) {
6830 size_t shift_bits, copy_end;
6831 copy_begin = begin / BITSPERDIG;
6832 shift_bits = begin % BITSPERDIG;
6833 copy_end = (end - 1) / BITSPERDIG + 1;
6834 v = bignew(copy_end - copy_begin, 1);
6836 MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
6837 negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
6839 if (shift_bits) v = rb_int_rshift(v,
SIZET2NUM(shift_bits));
6844 negative_add_one =
false;
6845 copy_begin = begin = end = 0;
6848 if (BIGNUM_NEGATIVE_P(x)) {
6849 size_t mask_size = length - shift;
6851 v = rb_int_xor(v, mask);
6852 for (
size_t i = 0; negative_add_one && i < copy_begin; i++) {
6853 if (xds[i]) negative_add_one =
false;
6855 if (negative_add_one) v = rb_int_plus(v,
INT2FIX(1));
6856 v = rb_int_and(v, mask);
6859 size_t mask_size = (size_t)end - begin;
6861 v = rb_int_and(v, mask);
6864 if (shift) v = rb_int_lshift(v,
SSIZET2NUM(shift));
6873 hash =
rb_memhash(BDIGITS(x),
sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6908 if (BIGNUM_NEGATIVE_P(x)) {
6909 x = rb_big_clone(x);
6910 BIGNUM_SET_POSITIVE_SIGN(x);
6918 return BIGNUM_SIGN(x);
6922rb_big_size(
VALUE big)
6924 return BIGSIZE(big);
6928rb_big_size_m(
VALUE big)
6934rb_big_bit_length(
VALUE big)
6939 static const BDIGIT char_bit[1] = { CHAR_BIT };
6940 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(
size_t))];
6942 BDIGIT result_bary[bdigit_roomof(
sizeof(
size_t)+1)];
6944 numbytes = rb_absint_size(big, &nlz_bits);
6949 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6950 if (nlz_bits != CHAR_BIT-1) {
6959 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6960 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6963 nlz_bary[0] = nlz_bits;
6965 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
6967 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6968 BARY_SUB(result_bary, result_bary, nlz_bary);
6970 return rb_integer_unpack(result_bary, numberof(result_bary),
sizeof(BDIGIT), 0,
6975rb_big_odd_p(
VALUE num)
6977 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6981rb_big_even_p(
VALUE num)
6983 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6989unsigned long rb_ulong_isqrt(
unsigned long);
6990#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6991BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6992# ifdef ULL_TO_DOUBLE
6993# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6996# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6998#ifndef BDIGIT_DBL_TO_DOUBLE
6999# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
7003rb_big_isqrt(
VALUE n)
7005 BDIGIT *nds = BDIGITS(n);
7006 size_t len = BIGNUM_LEN(n);
7009 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds,
len));
7010#if SIZEOF_BDIGIT > SIZEOF_LONG
7017 size_t shift =
FIX2LONG(rb_big_bit_length(n)) / 4;
7021 x = rb_int_plus(rb_int_lshift(x,
SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n,
SIZET2NUM(shift + 1)), x));
7022 VALUE xx = rb_int_mul(x, x);
7023 while (rb_int_gt(xx, n)) {
7024 xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x),
INT2FIX(1)));
7025 x = rb_int_minus(x,
INT2FIX(1));
7033bary_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)
7041 bdigits_to_mpz(x, xds, xn);
7042 bdigits_to_mpz(y, yds, yn);
7043 bdigits_to_mpz(m, mds, mn);
7044 mpz_powm(z, x, y, m);
7045 bdigits_from_mpz(z, zds, &count);
7046 BDIGITS_ZERO(zds+count, zn-count);
7059 size_t xn, yn, mn, zn;
7073 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7074 if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
7075 z = rb_big_minus(z, m);
7080 return rb_big_norm(z);
7086 if (
RTEST(rb_int_odd_p(y))) {
7087 tmp = rb_int_mul(tmp, x);
7088 tmp = rb_int_modulo(tmp, m);
7090 x = rb_int_mul(x, x);
7091 x = rb_int_modulo(x, m);
7093 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7095 tmp = rb_int_mul(tmp, x);
7096 tmp = rb_int_modulo(tmp, m);
7098 x = rb_int_mul(x, x);
7099 x = rb_int_modulo(x, m);
7102 if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
7103 tmp = rb_int_minus(tmp, m);
7114int_pow_tmp1(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7121 if (
RTEST(rb_int_odd_p(y))) {
7122 tmp = (tmp * xx) % mm;
7124 xx = (xx * xx) % mm;
7126 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7128 tmp = (tmp * xx) % mm;
7130 xx = (xx * xx) % mm;
7133 if (nega_flg && tmp) {
7140int_pow_tmp2(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7148# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7153# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7157 if (
RTEST(rb_int_odd_p(y))) {
7158 tmp2 = MUL_MODULO(tmp2, xx, m);
7160 xx = MUL_MODULO(xx, xx, m);
7162 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7164 tmp2 = MUL_MODULO(tmp2, xx, m);
7166 xx = MUL_MODULO(xx, xx, m);
7174 if (nega_flg && tmp) {
7192rb_int_powm(
int const argc,
VALUE *
const argv,
VALUE const num)
7197 return rb_int_pow(num, argv[0]);
7200 VALUE const a = num;
7201 VALUE const b = argv[0];
7205 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7207 if (rb_int_negative_p(b)) {
7208 rb_raise(
rb_eRangeError,
"Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7211 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless all arguments are integers");
7214 if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
7219 if (rb_int_negative_p(m)) {
7220 m = rb_int_uminus(m);
7225 long const half_val = (long)HALF_LONG_MSB;
7228 if (mm == 1)
return INT2FIX(0);
7229 if (mm <= half_val) {
7230 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7233 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7239 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7270 rb_define_const(
rb_cInteger,
"GMP_VERSION", rb_sprintf(
"GMP %s", gmp_version));
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_DEBUG
Define this macro when you want assertions.
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define NUM2SSIZET
Old name of RB_NUM2SSIZE.
#define ISSPACE
Old name of rb_isspace.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define NEGFIXABLE
Old name of RB_NEGFIXABLE.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define CLASS_OF
Old name of rb_class_of.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define NUM2DBL
Old name of rb_num2dbl.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define FIXNUM_MIN
Old name of RUBY_FIXNUM_MIN.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
#define POSFIXABLE
Old name of RB_POSFIXABLE.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
void rb_invalid_str(const char *str, const char *type)
Honestly I don't understand the name, but it raises an instance of rb_eArgError.
VALUE rb_eFloatDomainError
FloatDomainError exception.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
VALUE rb_cInteger
Module class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
#define RGENGC_WB_PROTECTED_BIGNUM
This is a compile-time flag to enable/disable write barrier for struct RBignum.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
#define INTEGER_PACK_MSBYTE_FIRST
Stores/interprets the most significant byte in a word as the first byte in the word.
#define INTEGER_PACK_LSBYTE_FIRST
Stores/interprets the least significant byte in a word as the first byte in the word.
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Means either INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST, depending on the host processor'...
#define INTEGER_PACK_FORCE_BIGNUM
Always generates a bignum object even if the integer can be representable using fixnum scheme (unpack...
#define INTEGER_PACK_BIG_ENDIAN
Big endian combination.
#define INTEGER_PACK_2COMP
Uses 2's complement representation.
#define INTEGER_PACK_NEGATIVE
Interprets the input as a signed negative number (unpack only).
#define INTEGER_PACK_MSWORD_FIRST
Stores/interprets the most significant word as the first word.
#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
Uses "generic" implementation (handy on test).
#define INTEGER_PACK_LSWORD_FIRST
Stores/interprets the least significant word as the first word.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_num_zerodiv(void)
Just always raises an exception.
VALUE rb_fix2str(VALUE val, int base)
Generates a place-value representation of the given Fixnum, with given radix.
VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op)
This one is optimised for bitwise operations, but the API is identical to rb_num_coerce_bin().
VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_cmp(), except for return values.
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
VALUE rb_rational_raw(VALUE num, VALUE den)
Identical to rb_rational_new(), except it skips argument validations.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
void rb_thread_check_ints(void)
Checks for interrupts.
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
#define RB_NOGVL_UBF_ASYNC_SAFE
Passing this flag to rb_nogvl() indicates that the passed UBF is async-signal-safe.
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Identical to rb_thread_call_without_gvl(), except it additionally takes "flags" that change the behav...
#define RB_NOGVL_OFFLOAD_SAFE
Passing this flag to rb_nogvl() indicates that the passed function is safe to offload to a background...
VALUE rb_ull2inum(unsigned LONG_LONG num)
Converts a C's unsigned long long into an instance of rb_cInteger.
VALUE rb_ll2inum(LONG_LONG num)
Converts a C's long long into an instance of rb_cInteger.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define MEMCMP(p1, p2, type, n)
Handy macro to call memcmp.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define StringValue(v)
Ensures that the parameter object is a String.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RTEST
This is an old name of RB_TEST.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
#define RBIMPL_WARNING_PUSH()
Pushes compiler warning state.
#define RBIMPL_WARNING_POP()
Pops compiler warning state.