12#include "ruby/internal/config.h"
27#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
39#include "internal/bignum.h"
40#include "internal/complex.h"
41#include "internal/gc.h"
42#include "internal/numeric.h"
43#include "internal/object.h"
44#include "internal/sanitizers.h"
45#include "internal/variable.h"
46#include "internal/warnings.h"
49#include "ruby_assert.h"
51const char ruby_digitmap[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
53#ifndef SIZEOF_BDIGIT_DBL
54# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
55# define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
57# define SIZEOF_BDIGIT_DBL SIZEOF_LONG
61STATIC_ASSERT(sizeof_bdigit_dbl,
sizeof(BDIGIT_DBL) == SIZEOF_BDIGIT_DBL);
62STATIC_ASSERT(sizeof_bdigit_dbl_signed,
sizeof(BDIGIT_DBL_SIGNED) == SIZEOF_BDIGIT_DBL);
63STATIC_ASSERT(sizeof_bdigit, SIZEOF_BDIGIT <=
sizeof(BDIGIT));
64STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGIT*2 <= SIZEOF_BDIGIT_DBL);
65STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
66STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
67STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
68STATIC_ASSERT(rbignum_embed_len_max, BIGNUM_EMBED_LEN_MAX <= (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT));
70#if SIZEOF_BDIGIT < SIZEOF_LONG
71STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
73STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
77# define HOST_BIGENDIAN_P 1
79# define HOST_BIGENDIAN_P 0
82#define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
83#define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
84#define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
85#define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
86#define POW2_P(x) (((x)&((x)-1))==0)
88#define BDIGITS(x) (BIGNUM_DIGITS(x))
89#define BITSPERDIG (SIZEOF_BDIGIT*CHAR_BIT)
90#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
91#define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
92#define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
93#define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
94#define BIGDN(x) RSHIFT((x),BITSPERDIG)
95#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
96#define BDIGMAX ((BDIGIT)(BIGRAD-1))
97#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
100# define swap_bdigit(x) swap16(x)
101#elif SIZEOF_BDIGIT == 4
102# define swap_bdigit(x) swap32(x)
103#elif SIZEOF_BDIGIT == 8
104# define swap_bdigit(x) swap64(x)
107#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
108 (BDIGITS(x)[0] == 0 && \
109 (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
110#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
111 BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
112 (size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
113 rb_absint_size(x, NULL))
115#define BIGDIVREM_EXTRA_WORDS 1
116#define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT)
117#define BARY_ARGS(ary) ary, numberof(ary)
119#define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
120#define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
121#define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
122#define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
123#define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
125#define BIGNUM_SET_NEGATIVE_SIGN(b) BIGNUM_SET_SIGN(b, 0)
126#define BIGNUM_SET_POSITIVE_SIGN(b) BIGNUM_SET_SIGN(b, 1)
128#define bignew(len,sign) bignew_1(rb_cInteger,(len),(sign))
130#define BDIGITS_ZERO(ptr, n) do { \
131 BDIGIT *bdigitz_zero_ptr = (ptr); \
132 size_t bdigitz_zero_n = (n); \
133 while (bdigitz_zero_n) { \
134 *bdigitz_zero_ptr++ = 0; \
139#define BARY_TRUNC(ds, n) do { \
140 while (0 < (n) && (ds)[(n)-1] == 0) \
144#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
145#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
147#define GMP_MUL_DIGITS 20
148#define KARATSUBA_MUL_DIGITS 70
149#define TOOM3_MUL_DIGITS 150
151#define GMP_DIV_DIGITS 20
152#define GMP_BIG2STR_DIGITS 20
153#define GMP_STR2BIG_DIGITS 20
155# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
157# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
160typedef void (mulfunc_t)(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn);
162static mulfunc_t bary_mul_toom3_start;
163static mulfunc_t bary_mul_karatsuba_start;
164static BDIGIT bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y);
166static VALUE bignew_1(
VALUE klass,
size_t len,
int sign);
170static inline VALUE power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret);
172#if SIZEOF_BDIGIT <= SIZEOF_INT
173static int nlz(BDIGIT x) {
return nlz_int((
unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGIT) * CHAR_BIT; }
174#elif SIZEOF_BDIGIT <= SIZEOF_LONG
175static int nlz(BDIGIT x) {
return nlz_long((
unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
176#elif SIZEOF_BDIGIT <= SIZEOF_LONG_LONG
177static int nlz(BDIGIT x) {
return nlz_long_long((
unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
178#elif SIZEOF_BDIGIT <= SIZEOF_INT128_T
179static int nlz(BDIGIT x) {
return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGIT) * CHAR_BIT; }
182#define U16(a) ((uint16_t)(a))
183#define U32(a) ((uint32_t)(a))
185#define U64(a,b) (((uint64_t)(a) << 32) | (b))
188#define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
235#if SIZEOF_BDIGIT_DBL == 2
236static const int maxpow16_exp[35] = {
237 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
238 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
240static const uint16_t maxpow16_num[35] = {
241 U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
242 U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
243 U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
244 U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
245 U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
246 U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
247 U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
248 U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
249 U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
251#elif SIZEOF_BDIGIT_DBL == 4
252static const int maxpow32_exp[35] = {
253 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
254 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
256static const uint32_t maxpow32_num[35] = {
257 U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
258 U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
259 U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
260 U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
261 U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
262 U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
263 U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
264 U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
265 U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
267#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
268static const int maxpow64_exp[35] = {
269 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
270 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
273static const uint64_t maxpow64_num[35] = {
274 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
275 U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
276 U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
277 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
278 U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
279 U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
280 U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
281 U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
282 U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
283 U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
284 U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
285 U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
286 U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
287 U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
288 U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
289 U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
290 U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
291 U64(0x41c21cb8,0xe1000000),
293#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
294static const int maxpow128_exp[35] = {
295 127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
296 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
299static const uint128_t maxpow128_num[35] = {
300 U128(0x80000000,0x00000000,0x00000000,0x00000000),
301 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
302 U128(0x40000000,0x00000000,0x00000000,0x00000000),
303 U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
304 U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
305 U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
306 U128(0x40000000,0x00000000,0x00000000,0x00000000),
307 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
308 U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
309 U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
310 U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
311 U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
312 U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
313 U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
314 U128(0x10000000,0x00000000,0x00000000,0x00000000),
315 U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
316 U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
317 U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
318 U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
319 U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
320 U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
321 U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
322 U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
323 U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
324 U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
325 U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
326 U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
327 U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
328 U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
329 U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
330 U128(0x20000000,0x00000000,0x00000000,0x00000000),
331 U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
332 U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
333 U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
334 U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
339maxpow_in_bdigit_dbl(
int base,
int *exp_ret)
344 assert(2 <= base && base <= 36);
347#if SIZEOF_BDIGIT_DBL == 2
348 maxpow = maxpow16_num[base-2];
349 exponent = maxpow16_exp[base-2];
350#elif SIZEOF_BDIGIT_DBL == 4
351 maxpow = maxpow32_num[base-2];
352 exponent = maxpow32_exp[base-2];
353#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
354 maxpow = maxpow64_num[base-2];
355 exponent = maxpow64_exp[base-2];
356#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
357 maxpow = maxpow128_num[base-2];
358 exponent = maxpow128_exp[base-2];
362 while (maxpow <= BDIGIT_DBL_MAX / base) {
373static inline BDIGIT_DBL
374bary2bdigitdbl(
const BDIGIT *ds,
size_t n)
379 return ds[0] | BIGUP(ds[1]);
386bdigitdbl2bary(BDIGIT *ds,
size_t n, BDIGIT_DBL num)
391 ds[1] = (BDIGIT)BIGDN(num);
395bary_cmp(
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
406 for (i = 0; i < xn; i++)
407 if (xds[xn - i - 1] != yds[yn - i - 1])
411 return xds[xn - i - 1] < yds[yn - i - 1] ? -1 : 1;
415bary_small_lshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift)
419 assert(0 <= shift && shift < BITSPERDIG);
421 for (i=0; i<n; i++) {
422 num = num | (BDIGIT_DBL)*xds++ << shift;
430bary_small_rshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift, BDIGIT higher_bdigit)
435 assert(0 <= shift && shift < BITSPERDIG);
437 num = BIGUP(higher_bdigit);
438 for (i = 0; i < n; i++) {
439 BDIGIT x = xds[n - i - 1];
440 num = (num | x) >> shift;
441 zds[n - i - 1] = BIGLO(num);
447bary_zero_p(
const BDIGIT *xds,
size_t xn)
452 if (xds[--xn])
return 0;
458bary_neg(BDIGIT *ds,
size_t n)
461 for (i = 0; i < n; i++)
462 ds[n - i - 1] = BIGLO(~ds[n - i - 1]);
466bary_2comp(BDIGIT *ds,
size_t n)
469 for (i = 0; i < n; i++) {
477 ds[i] = BIGLO(~ds[i] + 1);
480 ds[i] = BIGLO(~ds[i]);
486bary_swap(BDIGIT *ds,
size_t num_bdigits)
489 BDIGIT *p2 = ds + num_bdigits - 1;
490 for (; p1 < p2; p1++, p2--) {
497#define INTEGER_PACK_WORDORDER_MASK \
498 (INTEGER_PACK_MSWORD_FIRST | \
499 INTEGER_PACK_LSWORD_FIRST)
500#define INTEGER_PACK_BYTEORDER_MASK \
501 (INTEGER_PACK_MSBYTE_FIRST | \
502 INTEGER_PACK_LSBYTE_FIRST | \
503 INTEGER_PACK_NATIVE_BYTE_ORDER)
506validate_integer_pack_format(
size_t numwords,
size_t wordsize,
size_t nails,
int flags,
int supported_flags)
508 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
509 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
511 if (flags & ~supported_flags) {
514 if (wordorder_bits == 0) {
521 if (byteorder_bits == 0) {
530 if (SSIZE_MAX < wordsize)
532 if (wordsize <= nails / CHAR_BIT)
534 if (SIZE_MAX / wordsize < numwords)
535 rb_raise(
rb_eArgError,
"too big numwords * wordsize: %"PRI_SIZE_PREFIX
"u * %"PRI_SIZE_PREFIX
"u", numwords, wordsize);
539integer_pack_loop_setup(
540 size_t numwords,
size_t wordsize,
size_t nails,
int flags,
541 size_t *word_num_fullbytes_ret,
542 int *word_num_partialbits_ret,
543 size_t *word_start_ret,
544 ssize_t *word_step_ret,
545 size_t *word_last_ret,
546 size_t *byte_start_ret,
549 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
550 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
551 size_t word_num_fullbytes;
552 int word_num_partialbits;
559 word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
560 if (word_num_partialbits == CHAR_BIT)
561 word_num_partialbits = 0;
562 word_num_fullbytes = wordsize - (nails / CHAR_BIT);
563 if (word_num_partialbits != 0) {
564 word_num_fullbytes--;
568 word_start = wordsize*(numwords-1);
569 word_step = -(ssize_t)wordsize;
574 word_step = wordsize;
575 word_last = wordsize*(numwords-1);
579#ifdef WORDS_BIGENDIAN
586 byte_start = wordsize-1;
594 *word_num_partialbits_ret = word_num_partialbits;
595 *word_num_fullbytes_ret = word_num_fullbytes;
596 *word_start_ret = word_start;
597 *word_step_ret = word_step;
598 *word_last_ret = word_last;
599 *byte_start_ret = byte_start;
600 *byte_step_ret = byte_step;
604integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
606 if (*dpp < *dep && BITSPERDIG <= (
int)
sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
607 *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
608 *numbits_in_dd_p += BITSPERDIG;
610 else if (*dpp == *dep) {
612 *numbits_in_dd_p = (int)
sizeof(*ddp) * CHAR_BIT;
616static inline BDIGIT_DBL
617integer_pack_take_lowbits(
int n, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
620 ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
622 *numbits_in_dd_p -= n;
626#if !defined(WORDS_BIGENDIAN)
628bytes_2comp(
unsigned char *buf,
size_t len)
631 for (i = 0; i < len; i++) {
632 signed char c = buf[i];
634 unsigned int e = d & 0xFF;
637 for (i = 0; i < len; i++) {
647bary_pack(
int sign, BDIGIT *ds,
size_t num_bdigits,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
650 unsigned char *buf, *bufend;
653 de = ds + num_bdigits;
655 validate_integer_pack_format(numwords, wordsize, nails, flags,
664 while (dp < de && de[-1] == 0)
672 MEMZERO(words,
unsigned char, numwords * wordsize);
675 if (nails == 0 && numwords == 1) {
676 int need_swap = wordsize != 1 &&
682 *((
unsigned char *)words) = (
unsigned char)(d = dp[0]);
683 return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
685#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
686 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
687 uint16_t u = (uint16_t)(d = dp[0]);
688 if (need_swap) u = swap16(u);
689 *((uint16_t *)words) = u;
690 return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
693#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
694 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
695 uint32_t u = (uint32_t)(d = dp[0]);
696 if (need_swap) u = swap32(u);
697 *((uint32_t *)words) = u;
698 return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
701#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
702 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
703 uint64_t u = (uint64_t)(d = dp[0]);
704 if (need_swap) u = swap64(u);
705 *((uint64_t *)words) = u;
706 return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
713 *((
unsigned char *)words) = (
unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
714 return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
716#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
717 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
718 uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
719 if (need_swap) u = swap16(u);
720 *((uint16_t *)words) = u;
721 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
722 (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
725#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
726 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
727 uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
728 if (need_swap) u = swap32(u);
729 *((uint32_t *)words) = u;
730 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
731 (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
734#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
735 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
736 uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
737 if (need_swap) u = swap64(u);
738 *((uint64_t *)words) = u;
739 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
740 (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
745#if !defined(WORDS_BIGENDIAN)
746 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
749 size_t src_size = (de - dp) * SIZEOF_BDIGIT;
750 size_t dst_size = numwords * wordsize;
752 while (0 < src_size && ((
unsigned char *)ds)[src_size-1] == 0)
754 if (src_size <= dst_size) {
755 MEMCPY(words, dp,
char, src_size);
756 MEMZERO((
char*)words + src_size,
char, dst_size - src_size);
759 MEMCPY(words, dp,
char, dst_size);
763 int zero_p = bytes_2comp(words, dst_size);
764 if (zero_p && overflow) {
765 unsigned char *p = (
unsigned char *)dp;
766 if (dst_size == src_size-1 &&
777 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
778 wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words %
RUBY_ALIGNOF(BDIGIT) == 0) {
779 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
780 size_t src_num_bdigits = de - dp;
781 size_t dst_num_bdigits = numwords * bdigits_per_word;
786 if (src_num_bdigits <= dst_num_bdigits) {
787 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
788 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
791 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
795 int zero_p = bary_2comp(words, dst_num_bdigits);
796 if (zero_p && overflow &&
797 dst_num_bdigits == src_num_bdigits-1 &&
798 dp[dst_num_bdigits] == 1)
801 if (msbytefirst_p != HOST_BIGENDIAN_P) {
803 for (i = 0; i < dst_num_bdigits; i++) {
804 BDIGIT d = ((BDIGIT*)words)[i];
805 ((BDIGIT*)words)[i] = swap_bdigit(d);
808 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
811 for (i = 0; i < numwords; i++) {
812 bary_swap(p, bdigits_per_word);
813 p += bdigits_per_word;
817 bary_swap(words, dst_num_bdigits);
826 bufend = buf + numwords * wordsize;
833 if (de - dp == 1 && dp[0] == 1)
840 memset(buf,
'\0', bufend - buf);
842 else if (dp < de && buf < bufend) {
843 int word_num_partialbits;
844 size_t word_num_fullbytes;
850 size_t word_start, word_last;
851 unsigned char *wordp, *last_wordp;
855 integer_pack_loop_setup(numwords, wordsize, nails, flags,
856 &word_num_fullbytes, &word_num_partialbits,
857 &word_start, &word_step, &word_last, &byte_start, &byte_step);
859 wordp = buf + word_start;
860 last_wordp = buf + word_last;
866 integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
867#define TAKE_LOWBITS(n) \
868 integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
871 size_t index_in_word = 0;
872 unsigned char *bytep = wordp + byte_start;
873 while (index_in_word < word_num_fullbytes) {
875 *bytep = TAKE_LOWBITS(CHAR_BIT);
879 if (word_num_partialbits) {
881 *bytep = TAKE_LOWBITS(word_num_partialbits);
885 while (index_in_word < wordsize) {
891 if (wordp == last_wordp)
898 if (dp != de || 1 < dd) {
909 while (dp < de && *dp == 0)
921 int word_num_partialbits;
922 size_t word_num_fullbytes;
928 size_t word_start, word_last;
929 unsigned char *wordp, *last_wordp;
931 unsigned int partialbits_mask;
934 integer_pack_loop_setup(numwords, wordsize, nails, flags,
935 &word_num_fullbytes, &word_num_partialbits,
936 &word_start, &word_step, &word_last, &byte_start, &byte_step);
938 partialbits_mask = (1 << word_num_partialbits) - 1;
941 wordp = buf + word_start;
942 last_wordp = buf + word_last;
946 size_t index_in_word = 0;
947 unsigned char *bytep = wordp + byte_start;
948 while (index_in_word < word_num_fullbytes) {
949 carry += (
unsigned char)~*bytep;
950 *bytep = (
unsigned char)carry;
955 if (word_num_partialbits) {
956 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
957 *bytep = carry & partialbits_mask;
958 carry >>= word_num_partialbits;
963 if (wordp == last_wordp)
976integer_unpack_num_bdigits_small(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
979 size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
980 size_t num_bdigits = roomof(num_bits, BITSPERDIG);
981 *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
986integer_unpack_num_bdigits_generic(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
993 size_t num_bytes1 = wordsize * numwords;
996 size_t q1 = numwords / CHAR_BIT;
997 size_t r1 = numwords % CHAR_BIT;
1000 size_t num_bytes2 = num_bytes1 - nails * q1;
1003 size_t q2 = nails / CHAR_BIT;
1004 size_t r2 = nails % CHAR_BIT;
1007 size_t num_bytes3 = num_bytes2 - q2 * r1;
1010 size_t q3 = num_bytes3 / BITSPERDIG;
1011 size_t r3 = num_bytes3 % BITSPERDIG;
1014 size_t num_digits1 = CHAR_BIT * q3;
1027 if (CHAR_BIT * r3 >= r1 * r2) {
1028 size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
1029 size_t q4 = tmp1 / BITSPERDIG;
1030 int r4 = (int)(tmp1 % BITSPERDIG);
1031 size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
1036 size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
1037 size_t q4 = tmp1 / BITSPERDIG;
1038 int r4 = (int)(tmp1 % BITSPERDIG);
1039 size_t num_digits2 = num_digits1 - q4;
1046integer_unpack_num_bdigits(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1050 if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
1051 num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
1052#ifdef DEBUG_INTEGER_PACK
1055 size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
1056 assert(num_bdigits == num_bdigits1);
1057 assert(*nlp_bits_ret == nlp_bits1);
1063 num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
1069integer_unpack_push_bits(
int data,
int numbits, BDIGIT_DBL *ddp,
int *numbits_in_dd_p, BDIGIT **dpp)
1071 (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
1072 *numbits_in_dd_p += numbits;
1073 while (BITSPERDIG <= *numbits_in_dd_p) {
1074 *(*dpp)++ = BIGLO(*ddp);
1076 *numbits_in_dd_p -= BITSPERDIG;
1081integer_unpack_single_bdigit(BDIGIT u,
size_t size,
int flags, BDIGIT *dp)
1086 ((size == SIZEOF_BDIGIT && u == 0) ? -2 : -1) :
1087 ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
1089 u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
1099#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
1100#define reinterpret_cast(type, value) (type) \
1101 __builtin_assume_aligned((value), sizeof(*(type)NULL));
1103#define reinterpret_cast(type, value) (type)value
1107bary_unpack_internal(BDIGIT *bdigits,
size_t num_bdigits,
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags,
int nlp_bits)
1110 const unsigned char *buf = words;
1115 de = dp + num_bdigits;
1118 if (nails == 0 && numwords == 1) {
1119 int need_swap = wordsize != 1 &&
1122 if (wordsize == 1) {
1123 return integer_unpack_single_bdigit(*(uint8_t *)buf,
sizeof(uint8_t), flags, dp);
1125#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
1126 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
1127 uint16_t u = *reinterpret_cast(
const uint16_t *, buf);
1128 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
1131#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
1132 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
1133 uint32_t u = *reinterpret_cast(
const uint32_t *, buf);
1134 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
1137#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
1138 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
1139 uint64_t u = *reinterpret_cast(
const uint64_t *, buf);
1140 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
1143#undef reinterpret_cast
1145#if !defined(WORDS_BIGENDIAN)
1146 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1149 size_t src_size = numwords * wordsize;
1150 size_t dst_size = num_bdigits * SIZEOF_BDIGIT;
1151 MEMCPY(dp, words,
char, src_size);
1155 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1156 zero_p = bary_2comp(dp, num_bdigits);
1157 sign = zero_p ? -2 : -1;
1159 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
1160 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1161 bary_2comp(dp, num_bdigits);
1165 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1170 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1176 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1177 wordsize % SIZEOF_BDIGIT == 0) {
1178 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
1182 MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
1183 if (mswordfirst_p) {
1184 bary_swap(dp, num_bdigits);
1186 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
1189 for (i = 0; i < numwords; i++) {
1190 bary_swap(p, bdigits_per_word);
1191 p += bdigits_per_word;
1194 if (msbytefirst_p != HOST_BIGENDIAN_P) {
1196 for (p = dp; p < de; p++) {
1198 *p = swap_bdigit(d);
1203 int zero_p = bary_2comp(dp, num_bdigits);
1204 sign = zero_p ? -2 : -1;
1206 else if (BDIGIT_MSB(de[-1])) {
1207 bary_2comp(dp, num_bdigits);
1221 if (num_bdigits != 0) {
1222 int word_num_partialbits;
1223 size_t word_num_fullbytes;
1229 size_t word_start, word_last;
1230 const unsigned char *wordp, *last_wordp;
1234 integer_pack_loop_setup(numwords, wordsize, nails, flags,
1235 &word_num_fullbytes, &word_num_partialbits,
1236 &word_start, &word_step, &word_last, &byte_start, &byte_step);
1238 wordp = buf + word_start;
1239 last_wordp = buf + word_last;
1244#define PUSH_BITS(data, numbits) \
1245 integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
1248 size_t index_in_word = 0;
1249 const unsigned char *bytep = wordp + byte_start;
1250 while (index_in_word < word_num_fullbytes) {
1251 PUSH_BITS(*bytep, CHAR_BIT);
1255 if (word_num_partialbits) {
1256 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
1261 if (wordp == last_wordp)
1280 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
1281 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
1290 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
1293 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
1299 if (sign == -1 && num_bdigits != 0) {
1300 bary_2comp(bdigits, num_bdigits);
1308bary_unpack(BDIGIT *bdigits,
size_t num_bdigits,
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
1310 size_t num_bdigits0;
1314 validate_integer_pack_format(numwords, wordsize, nails, flags,
1325 num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
1327 assert(num_bdigits0 <= num_bdigits);
1329 sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
1331 if (num_bdigits0 < num_bdigits) {
1332 BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
1334 bdigits[num_bdigits0] = 1;
1340bary_subb(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int borrow)
1342 BDIGIT_DBL_SIGNED num;
1349 sn = xn < yn ? xn : yn;
1351 num = borrow ? -1 : 0;
1352 for (i = 0; i < sn; i++) {
1353 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
1354 zds[i] = BIGLO(num);
1358 for (; i < xn; i++) {
1359 if (num == 0)
goto num_is_zero;
1361 zds[i] = BIGLO(num);
1366 for (; i < yn; i++) {
1368 zds[i] = BIGLO(num);
1372 if (num == 0)
goto num_is_zero;
1373 for (; i < zn; i++) {
1379 if (xds == zds && xn == zn)
1381 for (; i < xn; i++) {
1384 for (; i < zn; i++) {
1391bary_sub(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1393 return bary_subb(zds, zn, xds, xn, yds, yn, 0);
1397bary_sub_one(BDIGIT *zds,
size_t zn)
1399 return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
1403bary_addc(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int carry)
1413 tds = xds; xds = yds; yds = tds;
1414 i = xn; xn = yn; yn = i;
1417 num = carry ? 1 : 0;
1418 for (i = 0; i < xn; i++) {
1419 num += (BDIGIT_DBL)xds[i] + yds[i];
1420 zds[i] = BIGLO(num);
1423 for (; i < yn; i++) {
1424 if (num == 0)
goto num_is_zero;
1426 zds[i] = BIGLO(num);
1429 for (; i < zn; i++) {
1430 if (num == 0)
goto num_is_zero;
1431 zds[i] = BIGLO(num);
1437 if (yds == zds && yn == zn)
1439 for (; i < yn; i++) {
1442 for (; i < zn; i++) {
1449bary_add(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1451 return bary_addc(zds, zn, xds, xn, yds, yn, 0);
1455bary_add_one(BDIGIT *ds,
size_t n)
1458 for (i = 0; i < n; i++) {
1459 BDIGIT_DBL n = ds[i];
1469bary_mul_single(BDIGIT *zds,
size_t zn, BDIGIT x, BDIGIT y)
1475 n = (BDIGIT_DBL)x * y;
1476 bdigitdbl2bary(zds, 2, n);
1477 BDIGITS_ZERO(zds + 2, zn - 2);
1481bary_muladd_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1493 for (j = 0; j < yn; j++) {
1494 BDIGIT_DBL ee = n + dd * yds[j];
1505 for (; j < zn; j++) {
1515static BDIGIT_DBL_SIGNED
1516bigdivrem_mulsub(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1520 BDIGIT_DBL_SIGNED num;
1522 assert(zn == yn + 1);
1529 BDIGIT_DBL_SIGNED ee;
1530 t2 += (BDIGIT_DBL)yds[i] * x;
1531 ee = num - BIGLO(t2);
1532 num = (BDIGIT_DBL_SIGNED)zds[i] + ee;
1533 if (ee) zds[i] = BIGLO(num);
1537 num -= (BDIGIT_DBL_SIGNED)t2;
1538 num += (BDIGIT_DBL_SIGNED)zds[yn];
1543bary_mulsub_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1545 BDIGIT_DBL_SIGNED num;
1547 assert(zn == yn + 1);
1549 num = bigdivrem_mulsub(zds, zn, x, yds, yn);
1550 zds[yn] = BIGLO(num);
1557bary_mul_normal(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1561 assert(xn + yn <= zn);
1563 BDIGITS_ZERO(zds, zn);
1564 for (i = 0; i < xn; i++) {
1565 bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
1572 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1573 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1574 bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
1585bary_sq_fast(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn)
1592 assert(xn * 2 <= zn);
1594 BDIGITS_ZERO(zds, zn);
1599 for (i = 0; i < xn-1; i++) {
1600 v = (BDIGIT_DBL)xds[i];
1603 c = (BDIGIT_DBL)zds[i + i] + v * v;
1604 zds[i + i] = BIGLO(c);
1609 for (j = i + 1; j < xn; j++) {
1610 w = (BDIGIT_DBL)xds[j];
1611 c += (BDIGIT_DBL)zds[i + j] + vl * w;
1612 zds[i + j] = BIGLO(c);
1618 c += (BDIGIT_DBL)zds[i + xn];
1619 zds[i + xn] = BIGLO(c);
1622 zds[i + xn + 1] += (BDIGIT)c;
1627 v = (BDIGIT_DBL)xds[i];
1630 c = (BDIGIT_DBL)zds[i + i] + v * v;
1631 zds[i + i] = BIGLO(c);
1634 zds[i + xn] += BIGLO(c);
1639rb_big_sq_fast(
VALUE x)
1641 size_t xn = BIGNUM_LEN(x), zn = 2 * xn;
1642 VALUE z = bignew(zn, 1);
1643 bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
1649max_size(
size_t a,
size_t b)
1651 return (a > b ? a : b);
1656bary_mul_balance_with_mulfunc(BDIGIT *
const zds,
const size_t zn,
1657 const BDIGIT *
const xds,
const size_t xn,
1658 const BDIGIT *
const yds,
const size_t yn,
1659 BDIGIT *wds,
size_t wn, mulfunc_t *
const mulfunc)
1664 assert(xn + yn <= zn);
1666 assert(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
1668 BDIGITS_ZERO(zds, xn);
1677 const size_t r = yn % xn;
1678 if (2*xn + yn + max_size(xn-r, r) > zn) {
1686 const size_t r = (xn > (yn - n) ? (yn - n) : xn);
1687 const size_t tn = (xn + r);
1688 if (2 * (xn + r) <= zn - n) {
1689 BDIGIT *
const tds = zds + n + xn + r;
1690 mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
1691 BDIGITS_ZERO(zds + n + xn, r);
1692 bary_add(zds + n, tn,
1697 BDIGIT *
const tds = zds + n;
1704 rb_bug(
"wds is not enough: %" PRIdSIZE
" for %" PRIdSIZE, wn, xn);
1707 MEMCPY(wds, zds + n, BDIGIT, xn);
1708 mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
1709 bary_add(zds + n, tn,
1715 BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
1724 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1725 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1726 bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
1734bary_mul_karatsuba(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1739 int sub_p, borrow, carry1, carry2, carry3;
1745 const BDIGIT *xds0, *xds1, *yds0, *yds1;
1746 BDIGIT *zds0, *zds1, *zds2, *zds3;
1748 assert(xn + yn <= zn);
1750 assert(yn < 2 * xn);
1752 sq = xds == yds && xn == yn;
1802 if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
1803 bary_2comp(zds0, n);
1811 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
1814 if (bary_sub(wds, n, yds, n, yds+n, n)) {
1821 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
1828 borrow = !bary_2comp(zds1, 2*n);
1832 MEMCPY(wds, zds1, BDIGIT, n);
1836 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
1840 carry1 = bary_add(wds, n, wds, n, zds0, n);
1841 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
1845 carry2 = bary_add(zds1, n, zds1, n, wds, n);
1849 MEMCPY(wds, zds2, BDIGIT, n);
1853 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
1857 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
1861 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
1865 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
1870 bary_add_one(zds2, zn-2*n);
1872 if (carry1 + carry3 - borrow < 0)
1873 bary_sub_one(zds3, zn-3*n);
1874 else if (carry1 + carry3 - borrow > 0) {
1875 BDIGIT c = carry1 + carry3 - borrow;
1876 bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
1891 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1892 bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
1895 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1905 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1906 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1907 if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
1909 bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
1916bary_mul_toom3(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1923 size_t x0n;
const BDIGIT *x0ds;
1924 size_t x1n;
const BDIGIT *x1ds;
1925 size_t x2n;
const BDIGIT *x2ds;
1926 size_t y0n;
const BDIGIT *y0ds;
1927 size_t y1n;
const BDIGIT *y1ds;
1928 size_t y2n;
const BDIGIT *y2ds;
1930 size_t u1n; BDIGIT *u1ds;
int u1p;
1931 size_t u2n; BDIGIT *u2ds;
int u2p;
1932 size_t u3n; BDIGIT *u3ds;
int u3p;
1934 size_t v1n; BDIGIT *v1ds;
int v1p;
1935 size_t v2n; BDIGIT *v2ds;
int v2p;
1936 size_t v3n; BDIGIT *v3ds;
int v3p;
1938 size_t t0n; BDIGIT *t0ds;
int t0p;
1939 size_t t1n; BDIGIT *t1ds;
int t1p;
1940 size_t t2n; BDIGIT *t2ds;
int t2p;
1941 size_t t3n; BDIGIT *t3ds;
int t3p;
1942 size_t t4n; BDIGIT *t4ds;
int t4p;
1944 size_t z0n; BDIGIT *z0ds;
1945 size_t z1n; BDIGIT *z1ds;
int z1p;
1946 size_t z2n; BDIGIT *z2ds;
int z2p;
1947 size_t z3n; BDIGIT *z3ds;
int z3p;
1948 size_t z4n; BDIGIT *z4ds;
1950 size_t zzn; BDIGIT *zzds;
1952 int sq = xds == yds && xn == yn;
1955 assert(xn + yn <= zn);
1970 wnc += (t1n = 2*n+2);
1971 wnc += (t2n = 2*n+2);
1972 wnc += (t3n = 2*n+2);
1975 wnc += (z1n = 2*n+1);
1976 wnc += (z2n = 2*n+1);
1977 wnc += (z3n = 2*n+1);
1984 u1ds = wds; wds += u1n;
1985 u2ds = wds; wds += u2n;
1986 u3ds = wds; wds += u3n;
1988 v1ds = wds; wds += v1n;
1989 v2ds = wds; wds += v2n;
1990 v3ds = wds; wds += v3n;
1992 t0ds = wds; wds += t0n;
1993 t1ds = wds; wds += t1n;
1994 t2ds = wds; wds += t2n;
1995 t3ds = wds; wds += t3n;
1996 t4ds = wds; wds += t4n;
1998 z1ds = wds; wds += z1n;
1999 z2ds = wds; wds += z2n;
2000 z3ds = wds; wds += z3n;
2066 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
2070 if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
2071 bary_2comp(u2ds, u2n);
2079 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
2084 bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
2086 else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
2087 bary_2comp(u3ds, u3n);
2090 bary_small_lshift(u3ds, u3ds, u3n, 1);
2092 bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
2094 else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
2095 bary_2comp(u3ds, u3n);
2100 v1n = u1n; v1ds = u1ds; v1p = u1p;
2101 v2n = u2n; v2ds = u2ds; v2p = u2p;
2102 v3n = u3n; v3ds = u3ds; v3p = u3p;
2106 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
2111 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
2112 bary_2comp(v2ds, v2n);
2117 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
2122 bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
2124 else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
2125 bary_2comp(v3ds, v3n);
2128 bary_small_lshift(v3ds, v3ds, v3n, 1);
2130 bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
2132 else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
2133 bary_2comp(v3ds, v3n);
2139 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
2143 bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
2145 assert(t1ds[t1n-1] == 0);
2149 bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
2151 assert(t2ds[t2n-1] == 0);
2155 bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
2157 assert(t3ds[t3n-1] == 0);
2161 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
2169 z0n = t0n; z0ds = t0ds;
2172 z4n = t4n; z4ds = t4ds;
2177 if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
2178 bary_2comp(z3ds, z3n);
2184 bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
2186 bigdivrem_single(z3ds, z3ds, z3n, 3);
2191 if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
2192 bary_2comp(z1ds, z1n);
2198 bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
2200 bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
2205 if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
2206 bary_2comp(z2ds, z2n);
2212 bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
2218 if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
2219 bary_2comp(z3ds, z3n);
2225 bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
2227 bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
2229 bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
2232 if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
2233 bary_2comp(z3ds, z3n);
2240 bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
2243 if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
2244 bary_2comp(z2ds, z2n);
2250 if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
2251 bary_2comp(z2ds, z2n);
2256 bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
2261 if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
2262 bary_2comp(z1ds, z1n);
2267 bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
2274 MEMCPY(zzds, z0ds, BDIGIT, z0n);
2275 BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
2276 MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
2277 BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
2279 bary_add(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2281 bary_sub(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2283 bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2285 bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2287 bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2289 bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2291 BARY_TRUNC(zzds, zzn);
2292 MEMCPY(zds, zzds, BDIGIT, zzn);
2293 BDIGITS_ZERO(zds + zzn, zn - zzn);
2302 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2303 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2304 if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
2306 bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
2314bdigits_to_mpz(mpz_t mp,
const BDIGIT *digits,
size_t len)
2316 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2317 mpz_import(mp, len, -1,
sizeof(BDIGIT), 0, nails, digits);
2321bdigits_from_mpz(mpz_t mp, BDIGIT *digits,
size_t *len)
2323 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2324 mpz_export(digits, len, -1,
sizeof(BDIGIT), 0, nails, mp);
2328bary_mul_gmp(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2333 assert(xn + yn <= zn);
2338 bdigits_to_mpz(x, xds, xn);
2339 if (xds == yds && xn == yn) {
2343 bdigits_to_mpz(y, yds, yn);
2346 bdigits_from_mpz(z, zds, &count);
2347 BDIGITS_ZERO(zds+count, zn-count);
2356 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2357 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2358 bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
2366bary_short_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2368 assert(xn + yn <= zn);
2370 if (xn == 1 && yn == 1) {
2371 bary_mul_single(zds, zn, xds[0], yds[0]);
2374 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2381bary_sparse_p(
const BDIGIT *ds,
size_t n)
2385 if ( ds[2 * n / 5]) c++;
2386 if (c <= 1 && ds[ n / 2]) c++;
2387 if (c <= 1 && ds[3 * n / 5]) c++;
2389 return (c <= 1) ? 1 : 0;
2393bary_mul_precheck(BDIGIT **zdsp,
size_t *znp,
const BDIGIT **xdsp,
size_t *xnp,
const BDIGIT **ydsp,
size_t *ynp)
2397 BDIGIT *zds = *zdsp;
2399 const BDIGIT *xds = *xdsp;
2401 const BDIGIT *yds = *ydsp;
2404 assert(xn + yn <= zn);
2409 if (xds[xn-1] == 0) {
2425 if (yds[yn-1] == 0) {
2441 BDIGITS_ZERO(zds, nlsz);
2450 tds = xds; xds = yds; yds = tds;
2451 tn = xn; xn = yn; yn = tn;
2457 BDIGITS_ZERO(zds, zn);
2462 MEMCPY(zds, yds, BDIGIT, yn);
2463 BDIGITS_ZERO(zds+yn, zn-yn);
2466 if (POW2_P(xds[0])) {
2467 zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
2468 BDIGITS_ZERO(zds+yn+1, zn-yn-1);
2471 if (yn == 1 && yds[0] == 1) {
2473 BDIGITS_ZERO(zds+1, zn-1);
2476 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2491bary_mul_karatsuba_branch(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
2494 if (xn < KARATSUBA_MUL_DIGITS) {
2499 if (bary_sparse_p(xds, xn))
goto normal;
2500 if (bary_sparse_p(yds, yn)) {
2501 bary_short_mul(zds, zn, yds, yn, xds, xn);
2506 if (!KARATSUBA_BALANCED(xn, yn)) {
2507 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
2512 bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
2516 if (xds == yds && xn == yn) {
2517 bary_sq_fast(zds, zn, xds, xn);
2520 bary_short_mul(zds, zn, xds, xn, yds, yn);
2525bary_mul_karatsuba_start(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
2527 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2530 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2534bary_mul_toom3_branch(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
2536 if (xn < TOOM3_MUL_DIGITS) {
2537 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2541 if (!TOOM3_BALANCED(xn, yn)) {
2542 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
2546 bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
2550bary_mul_toom3_start(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
2552 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2555 bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2559bary_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2562 if (xn < NAIVE_MUL_DIGITS) {
2563 if (xds == yds && xn == yn)
2564 bary_sq_fast(zds, zn, xds, xn);
2566 bary_short_mul(zds, zn, xds, xn, yds, yn);
2571 if (yn < NAIVE_MUL_DIGITS) {
2572 bary_short_mul(zds, zn, yds, yn, xds, xn);
2578 bary_mul_gmp(zds, zn, xds, xn, yds, yn);
2580 bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
2587 volatile VALUE stop;
2591bigdivrem1(
void *ptr)
2594 size_t yn = bds->yn;
2595 size_t zn = bds->zn;
2596 BDIGIT *yds = bds->yds, *zds = bds->zds;
2597 BDIGIT_DBL_SIGNED num;
2605 if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
2606 else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
2608 num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
2613 num = bary_add(zds+zn-(yn+1), yn,
2627rb_big_stop(
void *ptr)
2634bigdivrem_single1(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
2637 assert(x_higher_bdigit < y);
2641 bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
2647 t2 = x_higher_bdigit;
2648 for (i = 0; i < xn; i++) {
2649 t2 = BIGUP(t2) + xds[xn - i - 1];
2650 qds[xn - i - 1] = (BDIGIT)(t2 / y);
2658bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y)
2660 return bigdivrem_single1(qds, xds, xn, 0, y);
2664bigdivrem_restoring(BDIGIT *zds,
size_t zn, BDIGIT *yds,
size_t yn)
2670 assert(BDIGIT_MSB(yds[yn-1]));
2671 assert(zds[zn-1] < yds[yn-1]);
2673 for (ynzero = 0; !yds[ynzero]; ynzero++);
2675 if (ynzero+1 == yn) {
2677 r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
2682 bds.yn = yn - ynzero;
2683 bds.zds = zds + ynzero;
2684 bds.yds = yds + ynzero;
2686 bds.zn = zn - ynzero;
2687 if (bds.zn > 10000 || bds.yn > 10000) {
2692 if (bds.stop ==
Qtrue) {
2703bary_divmod_normal(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2710 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2711 assert(qds ? (xn - yn + 1) <= qn : 1);
2712 assert(rds ? yn <= rn : 1);
2714 zn = xn + BIGDIVREM_EXTRA_WORDS;
2716 shift = nlz(yds[yn-1]);
2719 int alloc_z = !qds || qn < zn;
2720 if (alloc_y && alloc_z) {
2721 yyds =
ALLOCV_N(BDIGIT, tmpyz, yn+zn);
2725 yyds = alloc_y ?
ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
2726 zds = alloc_z ?
ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
2728 zds[xn] = bary_small_lshift(zds, xds, xn, shift);
2729 bary_small_lshift(yyds, yds, yn, shift);
2732 if (qds && zn <= qn)
2736 MEMCPY(zds, xds, BDIGIT, xn);
2740 yyds = (BDIGIT *)yds;
2743 bigdivrem_restoring(zds, zn, yyds, yn);
2747 bary_small_rshift(rds, zds, yn, shift, 0);
2749 MEMCPY(rds, zds, BDIGIT, yn);
2750 BDIGITS_ZERO(rds+yn, rn-yn);
2755 MEMMOVE(qds, zds+yn, BDIGIT, j);
2756 BDIGITS_ZERO(qds+j, qn-j);
2766 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2767 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2770 BARY_TRUNC(yds, yn);
2773 BARY_TRUNC(xds, xn);
2775 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2776 return rb_assoc_new(
LONG2FIX(0), x);
2778 qn = xn + BIGDIVREM_EXTRA_WORDS;
2779 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2783 r = bignew(rn, BIGNUM_SIGN(x));
2786 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2794 return rb_assoc_new(q, r);
2799bary_divmod_gmp(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2804 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2805 assert(qds ? (xn - yn + 1) <= qn : 1);
2806 assert(rds ? yn <= rn : 1);
2811 if (qds) mpz_init(q);
2812 if (rds) mpz_init(r);
2814 bdigits_to_mpz(x, xds, xn);
2815 bdigits_to_mpz(y, yds, yn);
2818 mpz_fdiv_q(q, x, y);
2821 mpz_fdiv_r(r, x, y);
2824 mpz_fdiv_qr(q, r, x, y);
2831 bdigits_from_mpz(q, qds, &count);
2832 BDIGITS_ZERO(qds+count, qn-count);
2837 bdigits_from_mpz(r, rds, &count);
2838 BDIGITS_ZERO(rds+count, rn-count);
2846 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2847 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2850 BARY_TRUNC(yds, yn);
2853 BARY_TRUNC(xds, xn);
2855 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2856 return rb_assoc_new(
LONG2FIX(0), x);
2859 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2863 r = bignew(rn, BIGNUM_SIGN(x));
2866 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2874 return rb_assoc_new(q, r);
2879bary_divmod_branch(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2882 if (GMP_DIV_DIGITS < xn) {
2883 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2887 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2891bary_divmod(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2896 BARY_TRUNC(yds, yn);
2900 BARY_TRUNC(xds, xn);
2902 BDIGITS_ZERO(qds, qn);
2903 BDIGITS_ZERO(rds, rn);
2907 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
2908 MEMCPY(rds, xds, BDIGIT, xn);
2909 BDIGITS_ZERO(rds+xn, rn-xn);
2910 BDIGITS_ZERO(qds, qn);
2913 MEMCPY(qds, xds, BDIGIT, xn);
2914 BDIGITS_ZERO(qds+xn, qn-xn);
2915 rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
2916 BDIGITS_ZERO(rds+1, rn-1);
2918 else if (xn == 2 && yn == 2) {
2919 BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
2920 BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
2921 BDIGIT_DBL q = x / y;
2922 BDIGIT_DBL r = x % y;
2924 qds[1] = BIGLO(BIGDN(q));
2925 BDIGITS_ZERO(qds+2, qn-2);
2927 rds[1] = BIGLO(BIGDN(r));
2928 BDIGITS_ZERO(rds+2, rn-2);
2931 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
2937# define BIGNUM_DEBUG (0+RUBY_DEBUG)
2943 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2960 if (l > 0)
return 1;
2961 if (l < 0)
return -1;
2964 if (RB_BIGNUM_TYPE_P(val)) {
2965 if (BIGZEROP(val))
return 0;
2966 if (BIGNUM_SIGN(val))
return 1;
2969 if (
RTEST(rb_funcall(val,
'>', 1,
INT2FIX(0))))
return 1;
2970 if (
RTEST(rb_funcall(val,
'<', 1,
INT2FIX(0))))
return -1;
2974#define BIGNUM_SET_LEN(b,l) \
2975 (BIGNUM_EMBED_P(b) ? \
2976 (void)(RBASIC(b)->flags = \
2977 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2978 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2979 (void)(RBIGNUM(b)->as.heap.len = (l)))
2982rb_big_realloc(
VALUE big,
size_t len)
2985 if (BIGNUM_EMBED_P(big)) {
2986 if (BIGNUM_EMBED_LEN_MAX < len) {
2988 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
2989 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
2990 RBIGNUM(big)->as.heap.digits = ds;
2995 if (len <= BIGNUM_EMBED_LEN_MAX) {
2996 ds = RBIGNUM(big)->as.heap.digits;
2998 BIGNUM_SET_LEN(big, len);
2999 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)RBIGNUM(big)->as.ary,
sizeof(RBIGNUM(big)->as.ary));
3001 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
3006 if (BIGNUM_LEN(big) == 0) {
3007 RBIGNUM(big)->as.heap.digits =
ALLOC_N(BDIGIT, len);
3010 REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
3019 rb_big_realloc(big, len);
3020 BIGNUM_SET_LEN(big, len);
3024bignew_1(
VALUE klass,
size_t len,
int sign)
3028 BIGNUM_SET_SIGN(bigv, sign);
3029 if (len <= BIGNUM_EMBED_LEN_MAX) {
3031 BIGNUM_SET_LEN(bigv, len);
3032 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)big->as.ary,
sizeof(big->as.ary));
3035 big->as.heap.digits =
ALLOC_N(BDIGIT, len);
3036 big->as.heap.len = len;
3043rb_big_new(
size_t len,
int sign)
3045 return bignew(len, sign != 0);
3051 size_t len = BIGNUM_LEN(x);
3054 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
3059big_extend_carry(
VALUE x)
3061 rb_big_resize(x, BIGNUM_LEN(x)+1);
3062 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3069 long i = BIGNUM_LEN(x);
3070 BDIGIT *ds = BDIGITS(x);
3072 if (bary_2comp(ds, i)) {
3073 big_extend_carry(x);
3084abs2twocomp(
VALUE *xp,
long *n_ret)
3087 long n = BIGNUM_LEN(x);
3088 BDIGIT *ds = BDIGITS(x);
3093 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3095 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3096 bary_2comp(BDIGITS(z), n);
3105twocomp2abs_bang(
VALUE x,
int hibits)
3107 BIGNUM_SET_SIGN(x, !hibits);
3116 size_t len = BIGNUM_LEN(x);
3117 BDIGIT *ds = BDIGITS(x);
3119 if (len == 0)
return x;
3120 while (--len && !ds[len]);
3121 if (BIGNUM_LEN(x) > len+1) {
3122 rb_big_resize(x, len+1);
3130 size_t n = BIGNUM_LEN(x);
3131 BDIGIT *ds = BDIGITS(x);
3132#if SIZEOF_BDIGIT < SIZEOF_LONG
3140 if (n == 0)
return INT2FIX(0);
3142#if SIZEOF_BDIGIT < SIZEOF_LONG
3143 if (
sizeof(
long)/SIZEOF_BDIGIT < n)
3149 u = (
unsigned long)(BIGUP(u) + ds[i]);
3159 if (BIGNUM_POSITIVE_P(x)) {
3167 rb_big_resize(x, n);
3174 if (RB_BIGNUM_TYPE_P(x)) {
3187rb_uint2big(uintptr_t n)
3191 BDIGIT *digits = BDIGITS(big);
3193#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3197 digits[i] = BIGLO(n);
3203 while (--i && !digits[i]) ;
3204 BIGNUM_SET_LEN(big, i+1);
3209rb_int2big(intptr_t n)
3216 u = 1 + (
VALUE)(-(n + 1));
3222 big = rb_uint2big(u);
3224 BIGNUM_SET_NEGATIVE_SIGN(big);
3230rb_uint2inum(uintptr_t n)
3233 return rb_uint2big(n);
3237rb_int2inum(intptr_t n)
3240 return rb_int2big(n);
3244rb_big_pack(
VALUE val,
unsigned long *buf,
long num_longs)
3246 rb_integer_pack(val, buf, num_longs,
sizeof(
long), 0,
3252rb_big_unpack(
unsigned long *buf,
long num_longs)
3254 return rb_integer_unpack(buf, num_longs,
sizeof(
long), 0,
3276rb_absint_size(
VALUE val,
int *nlz_bits_ret)
3280 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3282 int num_leading_zeros;
3291#if SIZEOF_BDIGIT >= SIZEOF_LONG
3296 for (i = 0; i < numberof(fixbuf); i++) {
3297 fixbuf[i] = BIGLO(v);
3303 de = fixbuf + numberof(fixbuf);
3307 de = dp + BIGNUM_LEN(val);
3309 while (dp < de && de[-1] == 0)
3316 num_leading_zeros = nlz(de[-1]);
3318 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3319 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3323absint_numwords_small(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3325 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3326 size_t div = val_numbits / word_numbits;
3327 size_t mod = val_numbits % word_numbits;
3330 numwords = mod == 0 ? div : div + 1;
3331 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3332 *nlz_bits_ret = nlz_bits;
3337absint_numwords_generic(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3339 static const BDIGIT char_bit[1] = { CHAR_BIT };
3340 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(numbytes))];
3341 BDIGIT val_numbits_bary[bdigit_roomof(
sizeof(numbytes) + 1)];
3342 BDIGIT nlz_bits_in_msbyte_bary[1];
3343 BDIGIT word_numbits_bary[bdigit_roomof(
sizeof(word_numbits))];
3344 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3345 BDIGIT mod_bary[numberof(word_numbits_bary)];
3346 BDIGIT one[1] = { 1 };
3352 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3361 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
3363 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3364 if (nlz_bits_in_msbyte)
3365 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3366 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1,
sizeof(word_numbits), 0,
3368 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3369 if (BARY_ZERO_P(mod_bary)) {
3373 BARY_ADD(div_bary, div_bary, one);
3374 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1,
sizeof(mod), 0,
3376 nlz_bits = word_numbits - mod;
3378 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1,
sizeof(numwords), 0,
3382#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3387 *nlz_bits_ret = nlz_bits;
3411rb_absint_numwords(
VALUE val,
size_t word_numbits,
size_t *nlz_bits_ret)
3414 int nlz_bits_in_msbyte;
3416 size_t nlz_bits = 0;
3418 if (word_numbits == 0)
3421 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3423 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3424 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3425#ifdef DEBUG_INTEGER_PACK
3427 size_t numwords0, nlz_bits0;
3428 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3429 assert(numwords0 == numwords);
3430 assert(nlz_bits0 == nlz_bits);
3436 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3438 if (numwords == (
size_t)-1)
3442 *nlz_bits_ret = nlz_bits;
3480 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3490#if SIZEOF_BDIGIT >= SIZEOF_LONG
3495 for (i = 0; i < numberof(fixbuf); i++) {
3496 fixbuf[i] = BIGLO(v);
3502 de = fixbuf + numberof(fixbuf);
3506 de = dp + BIGNUM_LEN(val);
3508 while (dp < de && de[-1] == 0)
3510 while (dp < de && dp[0] == 0)
3577rb_integer_pack(
VALUE val,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3582 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3595#if SIZEOF_BDIGIT >= SIZEOF_LONG
3600 for (i = 0; i < numberof(fixbuf); i++) {
3601 fixbuf[i] = BIGLO(v);
3607 num_bdigits = numberof(fixbuf);
3610 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3612 num_bdigits = BIGNUM_LEN(val);
3615 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3663rb_integer_unpack(
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3670 BDIGIT fixbuf[2] = { 0, 0 };
3672 validate_integer_pack_format(numwords, wordsize, nails, flags,
3683 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3685 if (LONG_MAX-1 < num_bdigits)
3692 val = bignew((
long)num_bdigits, 0);
3695 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3699 big_extend_carry(val);
3701 else if (num_bdigits == numberof(fixbuf)) {
3702 val = bignew((
long)num_bdigits+1, 0);
3703 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3704 BDIGITS(val)[num_bdigits++] = 1;
3707 ds[num_bdigits++] = 1;
3712 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3717 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3719 return LONG2FIX((
long)-(BDIGIT_DBL_SIGNED)u);
3720 val = bignew((
long)num_bdigits, 0 <= sign);
3721 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3725 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3727 BIGNUM_SET_SIGN(val, 0 <= sign);
3730 return bigtrunc(val);
3731 return bignorm(val);
3734#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3736NORETURN(
static inline void invalid_radix(
int base));
3737NORETURN(
static inline void invalid_integer(
VALUE s));
3740valid_radix_p(
int base)
3742 return (1 < base && base <= 36);
3746invalid_radix(
int base)
3752invalid_integer(
VALUE s)
3758str2big_scan_digits(
const char *s,
const char *str,
int base,
int badcheck,
size_t *num_digits_p, ssize_t *len_p)
3761 size_t num_digits = 0;
3762 const char *digits_start = str;
3763 const char *digits_end = str;
3764 ssize_t len = *len_p;
3774 if (badcheck && *str ==
'_')
return FALSE;
3776 while ((c = *str++) != 0) {
3779 if (badcheck)
return FALSE;
3782 nondigit = (char) c;
3784 else if ((c = conv_digit(c)) < 0 || c >= base) {
3792 if (len > 0 && !--len)
break;
3794 if (badcheck && nondigit)
return FALSE;
3795 if (badcheck && len) {
3797 while (*str &&
ISSPACE(*str)) {
3799 if (len > 0 && !--len)
break;
3805 *num_digits_p = num_digits;
3806 *len_p = digits_end - digits_start;
3813 const char *digits_start,
3814 const char *digits_end,
3827 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3828 z = bignew(num_bdigits, sign);
3832 for (p = digits_end; digits_start < p; p--) {
3833 if ((c = conv_digit(p[-1])) < 0)
3835 dd |= (BDIGIT_DBL)c << numbits;
3836 numbits += bits_per_digit;
3837 if (BITSPERDIG <= numbits) {
3840 numbits -= BITSPERDIG;
3846 assert((
size_t)(dp - BDIGITS(z)) == num_bdigits);
3854 const char *digits_start,
3855 const char *digits_end,
3868 z = bignew(num_bdigits, sign);
3870 BDIGITS_ZERO(zds, num_bdigits);
3872 for (p = digits_start; p < digits_end; p++) {
3873 if ((c = conv_digit(*p)) < 0)
3879 num += (BDIGIT_DBL)zds[i]*base;
3880 zds[i++] = BIGLO(num);
3889 assert(blen <= num_bdigits);
3898 const char *digits_start,
3899 const char *digits_end,
3902 int digits_per_bdigits_dbl,
3908 BDIGIT *uds, *vds, *tds;
3910 BDIGIT_DBL current_base;
3912 int power_level = 0;
3919 uds =
ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3920 vds = uds + num_bdigits;
3922 powerv = power_cache_get_power(base, power_level, NULL);
3927 m = digits_per_bdigits_dbl;
3928 if (num_digits < (
size_t)m)
3929 m = (int)num_digits;
3930 for (p = digits_end; digits_start < p; p--) {
3931 if ((c = conv_digit(p[-1])) < 0)
3933 dd = dd + c * current_base;
3934 current_base *= base;
3938 uds[i++] = BIGLO(dd);
3939 uds[i++] = (BDIGIT)BIGDN(dd);
3941 m = digits_per_bdigits_dbl;
3942 if (num_digits < (
size_t)m)
3943 m = (
int)num_digits;
3947 assert(i == num_bdigits);
3948 for (unit = 2; unit < num_bdigits; unit *= 2) {
3949 for (i = 0; i < num_bdigits; i += unit*2) {
3950 if (2*unit <= num_bdigits - i) {
3951 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
3952 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
3954 else if (unit <= num_bdigits - i) {
3955 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
3956 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
3959 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
3963 powerv = power_cache_get_power(base, power_level, NULL);
3968 BARY_TRUNC(uds, num_bdigits);
3969 z = bignew(num_bdigits, sign);
3970 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
3982 const char *digits_start,
3983 const char *digits_end,
3996 buf =
ALLOCV_N(
char, tmps, num_digits+1);
3998 for (q = digits_start; q < digits_end; q++) {
3999 if (conv_digit(*q) < 0)
4006 mpz_set_str(mz, buf, base);
4008 z = bignew(zn, sign);
4010 bdigits_from_mpz(mz, BDIGITS(z), &count);
4011 BDIGITS_ZERO(zds+count, zn-count);
4021static VALUE rb_cstr_parse_inum(
const char *str, ssize_t len,
char **endp,
int base);
4040rb_cstr_to_inum(
const char *str,
int base,
int badcheck)
4043 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4069rb_int_parse_cstr(
const char *str, ssize_t len,
char **endp,
size_t *ndigits,
4070 int base,
int flags)
4072 const char *
const s = str;
4080 const char *digits_start, *digits_end;
4081 size_t num_digits = 0;
4083 const ssize_t len0 = len;
4084 const int badcheck = !endp;
4087 if (len > 0 && len <= (n)) goto bad; \
4091#define ASSERT_LEN() do {\
4093 if (len0 >= 0) assert(s + len0 == str + len); \
4099 if (len && (flags & RB_INT_PARSE_SIGN)) {
4102 if (str[0] ==
'+') {
4105 else if (str[0] ==
'-') {
4112 if (str[0] ==
'0' && len > 1) {
4134 else if (base < -1) {
4141 else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4144 else if (base == 2) {
4145 if (str[0] ==
'0' && (str[1] ==
'b'||str[1] ==
'B')) {
4149 else if (base == 8) {
4150 if (str[0] ==
'0' && (str[1] ==
'o'||str[1] ==
'O')) {
4154 else if (base == 10) {
4155 if (str[0] ==
'0' && (str[1] ==
'd'||str[1] ==
'D')) {
4159 else if (base == 16) {
4160 if (str[0] ==
'0' && (str[1] ==
'x'||str[1] ==
'X')) {
4164 if (!valid_radix_p(base)) {
4165 invalid_radix(base);
4168 num_digits = str - s;
4169 if (*str ==
'0' && len != 1) {
4171 const char *end = len < 0 ? NULL : str + len;
4173 while ((c = *++str) ==
'0' ||
4174 ((flags & RB_INT_PARSE_UNDERSCORE) && c ==
'_')) {
4183 if (str == end)
break;
4186 if (end) len = end - str;
4190 if (c < 0 || c >= base) {
4191 if (!badcheck && num_digits) z =
INT2FIX(0);
4195 if (ndigits) *ndigits = num_digits;
4198 const char *end = &str[num_digits];
4199 if (num_digits > 0 && *end ==
'_' && (flags & RB_INT_PARSE_UNDERSCORE))
4201 if (endp) *endp = (
char *)end;
4202 if (ndigits) *ndigits += num_digits;
4204 if (num_digits == 0)
return Qnil;
4205 while (len < 0 ? *end : end < str + len) {
4214 long result = -(long)val;
4219 VALUE big = rb_uint2big(val);
4220 BIGNUM_SET_SIGN(big, sign);
4221 return bignorm(big);
4227 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4229 if (endp) *endp = (
char *)(str + len);
4230 if (ndigits) *ndigits += num_digits;
4231 digits_end = digits_start + len;
4234 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4235 bit_length(base-1));
4238 int digits_per_bdigits_dbl;
4239 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4240 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4243 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4244 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4249 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4250 z = str2big_normal(sign, digits_start, digits_end,
4254 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4255 num_bdigits, digits_per_bdigits_dbl, base);
4262 if (endp) *endp = (
char *)str;
4263 if (ndigits) *ndigits = num_digits;
4268rb_cstr_parse_inum(
const char *str, ssize_t len,
char **endp,
int base)
4270 return rb_int_parse_cstr(str, len, endp, NULL, base,
4271 RB_INT_PARSE_DEFAULT);
4275rb_str_convert_to_inum(
VALUE str,
int base,
int badcheck,
int raise_exception)
4285 ret = rb_cstr_parse_inum(s, len, (badcheck ? NULL : &end), base);
4288 if (!raise_exception)
return Qnil;
4289 invalid_integer(str);
4297rb_str_to_inum(
VALUE str,
int base,
int badcheck)
4299 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4303rb_str2big_poweroftwo(
VALUE arg,
int base,
int badcheck)
4306 const char *s, *str;
4307 const char *digits_start, *digits_end;
4312 if (!valid_radix_p(base) || !POW2_P(base)) {
4313 invalid_radix(base);
4318 len = RSTRING_LEN(arg);
4326 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4327 invalid_integer(arg);
4328 digits_end = digits_start + len;
4330 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4331 bit_length(base-1));
4339rb_str2big_normal(
VALUE arg,
int base,
int badcheck)
4342 const char *s, *str;
4343 const char *digits_start, *digits_end;
4348 int digits_per_bdigits_dbl;
4351 if (!valid_radix_p(base)) {
4352 invalid_radix(base);
4357 len = RSTRING_LEN(arg);
4358 if (len > 0 && *str ==
'-') {
4365 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4366 invalid_integer(arg);
4367 digits_end = digits_start + len;
4369 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4370 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4372 z = str2big_normal(positive_p, digits_start, digits_end,
4381rb_str2big_karatsuba(
VALUE arg,
int base,
int badcheck)
4384 const char *s, *str;
4385 const char *digits_start, *digits_end;
4390 int digits_per_bdigits_dbl;
4393 if (!valid_radix_p(base)) {
4394 invalid_radix(base);
4399 len = RSTRING_LEN(arg);
4400 if (len > 0 && *str ==
'-') {
4407 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4408 invalid_integer(arg);
4409 digits_end = digits_start + len;
4411 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4412 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4414 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4415 num_bdigits, digits_per_bdigits_dbl, base);
4424rb_str2big_gmp(
VALUE arg,
int base,
int badcheck)
4427 const char *s, *str;
4428 const char *digits_start, *digits_end;
4433 int digits_per_bdigits_dbl;
4436 if (!valid_radix_p(base)) {
4437 invalid_radix(base);
4442 len = RSTRING_LEN(arg);
4443 if (len > 0 && *str ==
'-') {
4450 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4451 invalid_integer(arg);
4452 digits_end = digits_start + len;
4454 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4455 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4457 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4471 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4472 BDIGIT *digits = BDIGITS(big);
4474#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4477 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4478 digits[i] = BIGLO(n);
4483 i = bdigit_roomof(SIZEOF_LONG_LONG);
4484 while (i-- && !digits[i]) ;
4485 BIGNUM_SET_LEN(big, i+1);
4503 big = rb_ull2big(u);
4505 BIGNUM_SET_NEGATIVE_SIGN(big);
4514 return rb_ull2big(n);
4521 return rb_ll2big(n);
4528rb_uint128t2big(uint128_t n)
4531 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4532 BDIGIT *digits = BDIGITS(big);
4534 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4535 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4538 i = bdigit_roomof(SIZEOF_INT128_T);
4539 while (i-- && !digits[i]) ;
4540 BIGNUM_SET_LEN(big, i+1);
4544MJIT_FUNC_EXPORTED
VALUE
4545rb_int128t2big(int128_t n)
4552 u = 1 + (uint128_t)(-(n + 1));
4558 big = rb_uint128t2big(u);
4560 BIGNUM_SET_NEGATIVE_SIGN(big);
4567rb_cstr2inum(
const char *str,
int base)
4569 return rb_cstr_to_inum(str, base, base==0);
4575 return rb_str_to_inum(str, base, base==0);
4579big_shift3(
VALUE x,
int lshift_p,
size_t shift_numdigits,
int shift_numbits)
4588 if (LONG_MAX < shift_numdigits) {
4591 s1 = shift_numdigits;
4594 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4596 BDIGITS_ZERO(zds, s1);
4598 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4603 if (LONG_MAX < shift_numdigits || (
size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4604 if (BIGNUM_POSITIVE_P(x) ||
4605 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4610 s1 = shift_numdigits;
4612 hibitsx = abs2twocomp(&x, &xn);
4620 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4621 twocomp2abs_bang(z, hibitsx != 0);
4632 size_t shift_numdigits;
4635 assert(POW2_P(CHAR_BIT));
4636 assert(POW2_P(BITSPERDIG));
4640 sign = rb_integer_pack(y, lens, numberof(lens),
sizeof(
size_t), 0,
4643 lshift_p = !lshift_p;
4647 if (1 < sign || CHAR_BIT <= lens[1])
4651 if (1 < sign || CHAR_BIT <= lens[1])
4654 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4655 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4656 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4657 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4661big_lshift(
VALUE x,
unsigned long shift)
4663 long s1 = shift/BITSPERDIG;
4664 int s2 = (int)(shift%BITSPERDIG);
4665 return big_shift3(x, 1, s1, s2);
4669big_rshift(
VALUE x,
unsigned long shift)
4671 long s1 = shift/BITSPERDIG;
4672 int s2 = (int)(shift%BITSPERDIG);
4673 return big_shift3(x, 0, s1, s2);
4676#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4678static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4679static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4682power_cache_init(
void)
4687power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret)
4703 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4704 rb_bug(
"too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4706 VALUE power = base36_power_cache[base - 2][power_level];
4709 if (power_level == 0) {
4711 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4712 power = bignew(2, 1);
4713 bdigitdbl2bary(BDIGITS(power), 2, dd);
4714 numdigits = numdigits0;
4717 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4721 base36_power_cache[base - 2][power_level] = power;
4722 base36_numdigits_cache[base - 2][power_level] = numdigits;
4723 rb_gc_register_mark_object(power);
4726 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4734 int hbase2_numdigits;
4742 if (LONG_MAX-1 < len)
4745 b2s->ptr = RSTRING_PTR(b2s->result);
4751big2str_2bdigits(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t taillen)
4755 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4756 int beginning = !b2s->ptr;
4760 num = bary2bdigitdbl(xds, xn);
4768 BDIGIT_DBL idx = num % b2s->base;
4770 p[--j] = ruby_digitmap[idx];
4772 len =
sizeof(buf) - j;
4773 big2str_alloc(b2s, len + taillen);
4774 MEMCPY(b2s->ptr, buf + j,
char, len);
4778 j = b2s->hbase2_numdigits;
4780 BDIGIT_DBL idx = num % b2s->base;
4782 p[--j] = ruby_digitmap[idx];
4784 len = b2s->hbase2_numdigits;
4790big2str_karatsuba(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t wn,
4791 int power_level,
size_t taillen)
4794 size_t half_numdigits, lower_numdigits;
4795 int lower_power_level;
4820 if (xn == 0 || bary_zero_p(xds, xn)) {
4823 power_cache_get_power(b2s->base, power_level, &len);
4824 memset(b2s->ptr,
'0', len);
4830 if (power_level == 0) {
4831 big2str_2bdigits(b2s, xds, xn, taillen);
4835 lower_power_level = power_level-1;
4836 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4840 half_numdigits = lower_numdigits;
4842 while (0 < lower_power_level &&
4844 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4845 lower_power_level--;
4846 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4851 if (lower_power_level == 0 &&
4853 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4855 len = half_numdigits * 2 - lower_numdigits;
4856 memset(b2s->ptr,
'0', len);
4859 big2str_2bdigits(b2s, xds, xn, taillen);
4867 if (lower_power_level != power_level-1 && b2s->ptr) {
4868 len = (half_numdigits - lower_numdigits) * 2;
4869 memset(b2s->ptr,
'0', len);
4873 shift = nlz(bds[bn-1]);
4875 qn = xn + BIGDIVREM_EXTRA_WORDS;
4880 tds = (BDIGIT *)bds;
4887 assert(qn + bn <= xn + wn);
4888 bary_small_lshift(tds, bds, bn, shift);
4889 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4892 bigdivrem_restoring(xds, qn, tds, bn);
4901 bary_small_rshift(rds, rds, rn, shift, 0);
4904 BARY_TRUNC(qds, qn);
4906 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4907 BARY_TRUNC(rds, rn);
4908 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4913big2str_base_poweroftwo(
VALUE x,
int base)
4915 int word_numbits = ffs(base) - 1;
4919 numwords = rb_absint_numwords(x, word_numbits, NULL);
4920 if (BIGNUM_NEGATIVE_P(x)) {
4921 if (LONG_MAX-1 < numwords)
4924 ptr = RSTRING_PTR(result);
4925 *ptr++ = BIGNUM_POSITIVE_P(x) ?
'+' :
'-';
4928 if (LONG_MAX < numwords)
4931 ptr = RSTRING_PTR(result);
4933 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4935 while (0 < numwords) {
4936 *ptr = ruby_digitmap[*(
unsigned char *)ptr];
4944rb_big2str_poweroftwo(
VALUE x,
int base)
4946 return big2str_base_poweroftwo(x, base);
4950big2str_generic(
VALUE x,
int base)
4960 BARY_TRUNC(xds, xn);
4966 if (!valid_radix_p(base))
4967 invalid_radix(base);
4969 if (xn >= LONG_MAX/BITSPERDIG) {
4974 power = power_cache_get_power(base, power_level, NULL);
4975 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
4976 (
size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
4978 power = power_cache_get_power(base, power_level, NULL);
4980 assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
4982 if ((
size_t)BIGNUM_LEN(power) <= xn) {
4996 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
4997 b2s_data.base = base;
4998 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5000 b2s_data.result =
Qnil;
5001 b2s_data.ptr = NULL;
5003 if (power_level == 0) {
5004 big2str_2bdigits(&b2s_data, xds, xn, 0);
5010 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5011 wds =
ALLOCV_N(BDIGIT, tmpw, xn + wn);
5012 MEMCPY(wds, xds, BDIGIT, xn);
5013 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5019 *b2s_data.ptr =
'\0';
5020 rb_str_resize(b2s_data.result, (
long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5023 return b2s_data.result;
5027rb_big2str_generic(
VALUE x,
int base)
5029 return big2str_generic(x, base);
5034big2str_gmp(
VALUE x,
int base)
5039 BDIGIT *xds = BDIGITS(x);
5040 size_t xn = BIGNUM_LEN(x);
5043 bdigits_to_mpz(mx, xds, xn);
5045 size = mpz_sizeinbase(mx, base);
5047 if (BIGNUM_NEGATIVE_P(x)) {
5054 mpz_get_str(RSTRING_PTR(str), base, mx);
5057 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] ==
'\0') {
5066rb_big2str_gmp(
VALUE x,
int base)
5068 return big2str_gmp(x, base);
5073rb_big2str1(
VALUE x,
int base)
5085 BARY_TRUNC(xds, xn);
5091 if (!valid_radix_p(base))
5092 invalid_radix(base);
5094 if (xn >= LONG_MAX/BITSPERDIG) {
5100 return big2str_base_poweroftwo(x, base);
5104 if (GMP_BIG2STR_DIGITS < xn) {
5105 return big2str_gmp(x, base);
5109 return big2str_generic(x, base);
5115 return rb_big2str1(x, base);
5121#if SIZEOF_LONG > SIZEOF_BDIGIT
5124 size_t len = BIGNUM_LEN(x);
5130 if (BIGSIZE(x) >
sizeof(
long)) {
5134#if SIZEOF_LONG <= SIZEOF_BDIGIT
5135 num = (
unsigned long)ds[0];
5138 for (i = 0; i < len; i++) {
5140 num += (
unsigned long)ds[len - i - 1];
5149 unsigned long num = big2ulong(x,
"unsigned long");
5151 if (BIGNUM_POSITIVE_P(x)) {
5155 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5156 return -(long)(num-1)-1;
5164 unsigned long num = big2ulong(x,
"long");
5166 if (BIGNUM_POSITIVE_P(x)) {
5167 if (num <= LONG_MAX)
5171 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5172 return -(long)(num-1)-1;
5182#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5185 size_t len = BIGNUM_LEN(x);
5187 BDIGIT *ds = BDIGITS(x);
5191 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5193#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5197 for (i = 0; i < len; i++) {
5199 num += ds[len - i - 1];
5208 unsigned LONG_LONG num = big2ull(x,
"unsigned long long");
5210 if (BIGNUM_POSITIVE_P(x)) {
5214 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5223 unsigned LONG_LONG num = big2ull(x,
"long long");
5225 if (BIGNUM_POSITIVE_P(x)) {
5226 if (num <= LLONG_MAX)
5230 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5245 double u = (d < 0)?-d:d;
5255 u /= (double)(BIGRAD);
5258 z = bignew(i, d>=0);
5259 digits = BDIGITS(z);
5273 return bignorm(dbl2big(d));
5280 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5281 BDIGIT *ds = BDIGITS(x), dl;
5284 bits = i * BITSPERDIG - nlz(ds[i-1]);
5285 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5289 if (bits > DBL_MANT_DIG+1)
5290 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5294 d = ds[i] + BIGRAD*d;
5297 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5298 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5306 BDIGIT mask = BDIGMAX;
5318 if (lo > INT_MAX / BITSPERDIG)
5320 else if (lo < INT_MIN / BITSPERDIG)
5323 d = ldexp(d, (
int)(lo * BITSPERDIG));
5327 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5334 double d = big2dbl(x);
5356 if (yd > 0.0)
return INT2FIX(-1);
5361#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5388 rel = rb_big_cmp(x, y);
5389 if (yf == 0.0 || rel !=
INT2FIX(0))
5396#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG
5397COMPILER_WARNING_PUSH
5398#if __has_warning("-Wimplicit-int-float-conversion")
5399COMPILER_WARNING_IGNORED(-Wimplicit-
int-
float-conversion)
5401static const double LONG_MAX_as_double = LONG_MAX;
5417#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5419 return RBOOL(xd == yd);
5422 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5426 return RBOOL(xn == yn);
5430 return rb_big_eq(x, y);
5443 if (sx < sy)
return INT2FIX(-1);
5447 else if (RB_BIGNUM_TYPE_P(y)) {
5448 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5449 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5450 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5453 else if (RB_FLOAT_TYPE_P(y)) {
5454 return rb_integer_float_cmp(x, y);
5459 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5476 rel = rb_big_cmp(x, y);
5478 else if (RB_FLOAT_TYPE_P(y)) {
5479 rel = rb_integer_float_cmp(x, y);
5484 case big_op_gt:
id =
'>';
break;
5485 case big_op_ge:
id = idGE;
break;
5486 case big_op_lt:
id =
'<';
break;
5487 case big_op_le:
id = idLE;
break;
5496 case big_op_gt:
return RBOOL(n > 0);
5497 case big_op_ge:
return RBOOL(n >= 0);
5498 case big_op_lt:
return RBOOL(n < 0);
5499 case big_op_le:
return RBOOL(n <= 0);
5507 return big_op(x, y, big_op_gt);
5513 return big_op(x, y, big_op_ge);
5519 return big_op(x, y, big_op_lt);
5525 return big_op(x, y, big_op_le);
5543 return RBOOL(bignorm(x) == y);
5545 else if (RB_BIGNUM_TYPE_P(y)) {
5547 else if (RB_FLOAT_TYPE_P(y)) {
5548 return rb_integer_float_eq(x, y);
5553 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5554 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5555 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5561 if (!RB_BIGNUM_TYPE_P(y))
return Qfalse;
5562 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5563 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5564 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5568rb_big_uminus(
VALUE x)
5570 VALUE z = rb_big_clone(x);
5580 VALUE z = rb_big_clone(x);
5581 BDIGIT *ds = BDIGITS(z);
5582 long n = BIGNUM_LEN(z);
5586 if (BIGNUM_POSITIVE_P(z)) {
5587 if (bary_add_one(ds, n)) {
5588 big_extend_carry(z);
5590 BIGNUM_SET_NEGATIVE_SIGN(z);
5594 if (bary_add_one(ds, n))
5597 BIGNUM_SET_POSITIVE_SIGN(z);
5607 BDIGIT *xds, *yds, *zds;
5612 zn = xn < yn ? yn : xn;
5620 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5621 bary_2comp(zds, zn);
5622 BIGNUM_SET_NEGATIVE_SIGN(z);
5631bigsub_int(
VALUE x,
long y0)
5636 BDIGIT_DBL_SIGNED num;
5647#if SIZEOF_BDIGIT < SIZEOF_LONG
5648 if (zn < bdigit_roomof(SIZEOF_LONG))
5649 zn = bdigit_roomof(SIZEOF_LONG);
5651 z = bignew(zn, BIGNUM_SIGN(x));
5654#if SIZEOF_BDIGIT >= SIZEOF_LONG
5656 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5657 if (xn == 1 && num < 0) {
5659 zds[0] = (BDIGIT)-num;
5663 zds[0] = BIGLO(num);
5671 for (i=0; i < xn; i++) {
5672 if (y == 0)
goto y_is_zero_x;
5673 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5674 zds[i] = BIGLO(num);
5678 for (; i < zn; i++) {
5679 if (y == 0)
goto y_is_zero_z;
5681 zds[i] = BIGLO(num);
5688 for (; i < xn; i++) {
5690 if (num == 0)
goto num_is_zero_x;
5692 zds[i] = BIGLO(num);
5695#if SIZEOF_BDIGIT < SIZEOF_LONG
5696 for (; i < zn; i++) {
5698 if (num == 0)
goto num_is_zero_z;
5699 zds[i] = BIGLO(num);
5705 for (; i < xn; i++) {
5709#if SIZEOF_BDIGIT < SIZEOF_LONG
5710 for (; i < zn; i++) {
5718 assert(num == 0 || num == -1);
5728bigadd_int(
VALUE x,
long y)
5743#if SIZEOF_BDIGIT < SIZEOF_LONG
5744 if (zn < bdigit_roomof(SIZEOF_LONG))
5745 zn = bdigit_roomof(SIZEOF_LONG);
5749 z = bignew(zn, BIGNUM_SIGN(x));
5752#if SIZEOF_BDIGIT >= SIZEOF_LONG
5753 num = (BDIGIT_DBL)xds[0] + y;
5754 zds[0] = BIGLO(num);
5762 for (i=0; i < xn; i++) {
5763 if (y == 0)
goto y_is_zero_x;
5764 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5765 zds[i] = BIGLO(num);
5769 for (; i < zn; i++) {
5770 if (y == 0)
goto y_is_zero_z;
5772 zds[i] = BIGLO(num);
5780 for (;i < xn; i++) {
5782 if (num == 0)
goto num_is_zero_x;
5783 num += (BDIGIT_DBL)xds[i];
5784 zds[i] = BIGLO(num);
5787 for (; i < zn; i++) {
5789 if (num == 0)
goto num_is_zero_z;
5790 zds[i] = BIGLO(num);
5795 for (;i < xn; i++) {
5799 for (; i < zn; i++) {
5816 sign = (sign == BIGNUM_SIGN(y));
5817 if (BIGNUM_SIGN(x) != sign) {
5818 if (sign)
return bigsub(y, x);
5819 return bigsub(x, y);
5822 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5823 len = BIGNUM_LEN(x) + 1;
5826 len = BIGNUM_LEN(y) + 1;
5828 z = bignew(len, sign);
5830 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5831 BDIGITS(x), BIGNUM_LEN(x),
5832 BDIGITS(y), BIGNUM_LEN(y));
5844 if ((n > 0) != BIGNUM_SIGN(x)) {
5848 return bigsub_int(x, n);
5853 return bigadd_int(x, n);
5855 else if (RB_BIGNUM_TYPE_P(y)) {
5856 return bignorm(bigadd(x, y, 1));
5858 else if (RB_FLOAT_TYPE_P(y)) {
5873 if ((n > 0) != BIGNUM_SIGN(x)) {
5877 return bigadd_int(x, n);
5882 return bigsub_int(x, n);
5884 else if (RB_BIGNUM_TYPE_P(y)) {
5885 return bignorm(bigadd(x, y, 0));
5887 else if (RB_FLOAT_TYPE_P(y)) {
5910 if (xn < NAIVE_MUL_DIGITS)
5911 bary_sq_fast(zds, zn, xds, xn);
5913 bary_mul(zds, zn, xds, xn, xds, xn);
5924 BDIGIT *xds, *yds, *zds;
5933 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5939 bary_mul(zds, zn, xds, xn, yds, yn);
5952 else if (RB_BIGNUM_TYPE_P(y)) {
5954 else if (RB_FLOAT_TYPE_P(y)) {
5961 return bignorm(bigmul0(x, y));
5967 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
5969 BDIGIT *xds, *yds, *zds;
5977 BARY_TRUNC(yds, yn);
5982 BARY_TRUNC(xds, xn);
5984 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
5985 if (divp) *divp = rb_int2big(0);
5986 if (modp) *modp = x;
5991 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5993 dd = bigdivrem_single(zds, xds, xn, dd);
5995 *modp = rb_uint2big((uintptr_t)dd);
5996 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
5998 if (divp) *divp = z;
6001 if (xn == 2 && yn == 2) {
6002 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6003 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6004 BDIGIT_DBL q0 = x0 / y0;
6005 BDIGIT_DBL r0 = x0 % y0;
6007 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6010 zds[1] = BIGLO(BIGDN(q0));
6014 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6017 zds[1] = BIGLO(BIGDN(r0));
6024 qn = xn + BIGDIVREM_EXTRA_WORDS;
6025 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6035 r = bignew(rn, BIGNUM_SIGN(x));
6043 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6062 bigdivrem(x, y, divp, &mod);
6063 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6064 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6065 if (modp) *modp = bigadd(mod, y, 1);
6081 else if (RB_BIGNUM_TYPE_P(y)) {
6083 else if (RB_FLOAT_TYPE_P(y)) {
6085 double dx = rb_big2dbl(x);
6086 return rb_flo_div_flo(
DBL2NUM(dx), y);
6092 v = rb_big_divide(x, y,
'/');
6099 bigdivmod(x, y, &z, 0);
6107 return rb_big_divide(x, y,
'/');
6113 return rb_big_divide(x, y, idDiv);
6124 else if (!RB_BIGNUM_TYPE_P(y)) {
6127 bigdivmod(x, y, 0, &z);
6140 else if (!RB_BIGNUM_TYPE_P(y)) {
6143 bigdivrem(x, y, 0, &z);
6156 else if (!RB_BIGNUM_TYPE_P(y)) {
6159 bigdivmod(x, y, &div, &mod);
6161 return rb_assoc_new(bignorm(div), bignorm(mod));
6165big_shift(
VALUE x,
long n)
6168 return big_lshift(x, 1+(
unsigned long)(-(n+1)));
6170 return big_rshift(x, (
unsigned long)n);
6174enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6184 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6185 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6186 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6187 else if (ex > 0) ex = 0;
6188 if (ex) x = big_shift(x, ex);
6190 bigdivrem(x, y, &z, 0);
6192#if SIZEOF_LONG > SIZEOF_INT
6195 if (l > INT_MAX)
return HUGE_VAL;
6196 if (l < INT_MIN)
return 0.0;
6199 return ldexp(big2dbl(z), (
int)l);
6208 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6209 ey -= DBL_BIGDIG * BITSPERDIG;
6210 if (ey) y = big_shift(y, ey);
6211 return big_fdiv(x, y, ey);
6218 y = dbl2big(ldexp(frexp(
RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6219 return big_fdiv(x, y, i - DBL_MANT_DIG);
6232 return big_fdiv_int(x, rb_int2big(
FIX2LONG(y)));
6234 else if (RB_BIGNUM_TYPE_P(y)) {
6235 return big_fdiv_int(x, y);
6237 else if (RB_FLOAT_TYPE_P(y)) {
6242 return big_fdiv_float(x, y);
6254 return DBL2NUM(rb_big_fdiv_double(x, y));
6265 if (y ==
INT2FIX(1))
return x;
6266 if (RB_FLOAT_TYPE_P(y)) {
6268 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6269 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6272 else if (RB_BIGNUM_TYPE_P(y)) {
6276 rb_warn(
"in a**b, b may be too big");
6292 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6293 const size_t BIGLEN_LIMIT = 32*1024*1024;
6295 if (xbits == (
size_t)-1 ||
6296 (xbits > BIGLEN_LIMIT) ||
6297 (xbits * yy > BIGLEN_LIMIT)) {
6298 rb_warn(
"in a**b, b may be too big");
6302 for (mask =
FIXNUM_MAX + 1; mask; mask >>= 1) {
6303 if (z) z = bigsq(z);
6305 z = z ? bigtrunc(bigmul0(z, x)) : x;
6315 return DBL2NUM(pow(rb_big2dbl(x), d));
6319bigand_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6327 if (y == 0)
return INT2FIX(0);
6328 if (xn == 0)
return hibitsx ?
LONG2NUM(y) : 0;
6329 hibitsy = 0 <= y ? 0 : BDIGMAX;
6331#if SIZEOF_BDIGIT >= SIZEOF_LONG
6339#if SIZEOF_BDIGIT < SIZEOF_LONG
6340 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6341 zn = bdigit_roomof(SIZEOF_LONG);
6347#if SIZEOF_BDIGIT >= SIZEOF_LONG
6349 zds[0] = xds[0] & BIGLO(y);
6351 for (i=0; i < xn; i++) {
6352 if (y == 0 || y == -1)
break;
6353 zds[i] = xds[i] & BIGLO(y);
6356 for (; i < zn; i++) {
6357 if (y == 0 || y == -1)
break;
6358 zds[i] = hibitsx & BIGLO(y);
6362 for (;i < xn; i++) {
6363 zds[i] = xds[i] & hibitsy;
6365 for (;i < zn; i++) {
6366 zds[i] = hibitsx & hibitsy;
6368 twocomp2abs_bang(z, hibitsx && hibitsy);
6377 BDIGIT *ds1, *ds2, *zds;
6378 long i, xn, yn, n1, n2;
6379 BDIGIT hibitsx, hibitsy;
6380 BDIGIT hibits1, hibits2;
6389 hibitsx = abs2twocomp(&x, &xn);
6391 return bigand_int(x, xn, hibitsx,
FIX2LONG(y));
6393 hibitsy = abs2twocomp(&y, &yn);
6395 tmpv = x; x = y; y = tmpv;
6396 tmpn = xn; xn = yn; yn = tmpn;
6397 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6412 for (i=0; i<n1; i++) {
6413 zds[i] = ds1[i] & ds2[i];
6416 zds[i] = hibits1 & ds2[i];
6418 twocomp2abs_bang(z, hibits1 && hibits2);
6425bigor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6433 if (y == -1)
return INT2FIX(-1);
6435 hibitsy = 0 <= y ? 0 : BDIGMAX;
6439#if SIZEOF_BDIGIT < SIZEOF_LONG
6440 if (zn < bdigit_roomof(SIZEOF_LONG))
6441 zn = bdigit_roomof(SIZEOF_LONG);
6446#if SIZEOF_BDIGIT >= SIZEOF_LONG
6448 zds[0] = xds[0] | BIGLO(y);
6450 goto y_is_fixed_point;
6453 for (i=0; i < xn; i++) {
6454 if (y == 0 || y == -1)
goto y_is_fixed_point;
6455 zds[i] = xds[i] | BIGLO(y);
6460 for (; i < zn; i++) {
6461 if (y == 0 || y == -1)
goto y_is_fixed_point;
6471 for (; i < xn; i++) {
6476 for (; i < zn; i++) {
6482 for (; i < zn; i++) {
6487 twocomp2abs_bang(z, hibitsx || hibitsy);
6496 BDIGIT *ds1, *ds2, *zds;
6497 long i, xn, yn, n1, n2;
6498 BDIGIT hibitsx, hibitsy;
6499 BDIGIT hibits1, hibits2;
6508 hibitsx = abs2twocomp(&x, &xn);
6510 return bigor_int(x, xn, hibitsx,
FIX2LONG(y));
6512 hibitsy = abs2twocomp(&y, &yn);
6514 tmpv = x; x = y; y = tmpv;
6515 tmpn = xn; xn = yn; yn = tmpn;
6516 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6531 for (i=0; i<n1; i++) {
6532 zds[i] = ds1[i] | ds2[i];
6535 zds[i] = hibits1 | ds2[i];
6537 twocomp2abs_bang(z, hibits1 || hibits2);
6544bigxor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6552 hibitsy = 0 <= y ? 0 : BDIGMAX;
6555#if SIZEOF_BDIGIT < SIZEOF_LONG
6556 if (zn < bdigit_roomof(SIZEOF_LONG))
6557 zn = bdigit_roomof(SIZEOF_LONG);
6562#if SIZEOF_BDIGIT >= SIZEOF_LONG
6564 zds[0] = xds[0] ^ BIGLO(y);
6566 for (i = 0; i < xn; i++) {
6567 zds[i] = xds[i] ^ BIGLO(y);
6570 for (; i < zn; i++) {
6571 zds[i] = hibitsx ^ BIGLO(y);
6575 for (; i < xn; i++) {
6576 zds[i] = xds[i] ^ hibitsy;
6578 for (; i < zn; i++) {
6579 zds[i] = hibitsx ^ hibitsy;
6581 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6590 BDIGIT *ds1, *ds2, *zds;
6591 long i, xn, yn, n1, n2;
6592 BDIGIT hibitsx, hibitsy;
6593 BDIGIT hibits1, hibits2;
6602 hibitsx = abs2twocomp(&x, &xn);
6604 return bigxor_int(x, xn, hibitsx,
FIX2LONG(y));
6606 hibitsy = abs2twocomp(&y, &yn);
6608 tmpv = x; x = y; y = tmpv;
6609 tmpn = xn; xn = yn; yn = tmpn;
6610 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6622 for (i=0; i<n1; i++) {
6623 zds[i] = ds1[i] ^ ds2[i];
6626 zds[i] = hibitsx ^ ds2[i];
6628 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6638 size_t shift_numdigits;
6644 unsigned long shift;
6651 shift = 1+(
unsigned long)(-(l+1));
6653 shift_numbits = (int)(shift & (BITSPERDIG-1));
6654 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6655 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6657 else if (RB_BIGNUM_TYPE_P(y)) {
6658 return bignorm(big_shift2(x, 1, y));
6668 size_t shift_numdigits;
6674 unsigned long shift;
6681 shift = 1+(
unsigned long)(-(l+1));
6683 shift_numbits = (int)(shift & (BITSPERDIG-1));
6684 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6685 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6687 else if (RB_BIGNUM_TYPE_P(y)) {
6688 return bignorm(big_shift2(x, 0, y));
6703 if (RB_BIGNUM_TYPE_P(y)) {
6704 if (BIGNUM_NEGATIVE_P(y))
6707 if (BIGSIZE(y) >
sizeof(
size_t)) {
6710#if SIZEOF_SIZE_T <= SIZEOF_LONG
6711 shift = big2ulong(y,
"long");
6713 shift = big2ull(y,
"long long");
6721 s1 = shift/BITSPERDIG;
6722 s2 = shift%BITSPERDIG;
6723 bit = (BDIGIT)1 << s2;
6725 if (s1 >= BIGNUM_LEN(x))
6729 if (BIGNUM_POSITIVE_P(x))
6731 if (xds[s1] & (bit-1))
6733 for (i = 0; i < s1; i++)
6744 hash =
rb_memhash(BDIGITS(x),
sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6767 return rb_assoc_new(y, x);
6772 return rb_assoc_new(y, x);
6779 if (BIGNUM_NEGATIVE_P(x)) {
6780 x = rb_big_clone(x);
6781 BIGNUM_SET_POSITIVE_SIGN(x);
6789 return BIGNUM_SIGN(x);
6793rb_big_size(
VALUE big)
6795 return BIGSIZE(big);
6799rb_big_size_m(
VALUE big)
6805rb_big_bit_length(
VALUE big)
6810 static const BDIGIT char_bit[1] = { CHAR_BIT };
6811 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(
size_t))];
6813 BDIGIT result_bary[bdigit_roomof(
sizeof(
size_t)+1)];
6815 numbytes = rb_absint_size(big, &nlz_bits);
6820 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6821 if (nlz_bits != CHAR_BIT-1) {
6830 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6831 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6834 nlz_bary[0] = nlz_bits;
6836 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
6838 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6839 BARY_SUB(result_bary, result_bary, nlz_bary);
6841 return rb_integer_unpack(result_bary, numberof(result_bary),
sizeof(BDIGIT), 0,
6846rb_big_odd_p(
VALUE num)
6848 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6852rb_big_even_p(
VALUE num)
6854 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6860unsigned long rb_ulong_isqrt(
unsigned long);
6861#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6862BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6863# ifdef ULL_TO_DOUBLE
6864# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6867# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6869#ifndef BDIGIT_DBL_TO_DOUBLE
6870# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
6874estimate_initial_sqrt(
VALUE *xp,
const size_t xn,
const BDIGIT *nds,
size_t len)
6876 enum {dbl_per_bdig = roomof(DBL_MANT_DIG,BITSPERDIG)};
6877 const int zbits = nlz(nds[len-1]);
6878 VALUE x = *xp = bignew_1(0, xn, 1);
6879 BDIGIT *xds = BDIGITS(x);
6880 BDIGIT_DBL d = bary2bdigitdbl(nds+len-dbl_per_bdig, dbl_per_bdig);
6882 int rshift = (int)((BITSPERDIG*2-zbits+(len&BITSPERDIG&1) - DBL_MANT_DIG + 1) & ~1);
6886 lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
6889 else if (rshift < 0) {
6891 d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
6893 f = sqrt(BDIGIT_DBL_TO_DOUBLE(d));
6894 d = (BDIGIT_DBL)ceil(f);
6895 if (BDIGIT_DBL_TO_DOUBLE(d) == f) {
6896 if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
6903 rshift += (2-(len&1))*BITSPERDIG/2;
6905 if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) {
6915 BDIGITS_ZERO(xds, xn-2);
6916 bdigitdbl2bary(&xds[xn-2], 2, d);
6918 if (!lowbits)
return NULL;
6923rb_big_isqrt(
VALUE n)
6925 BDIGIT *nds = BDIGITS(n);
6926 size_t len = BIGNUM_LEN(n);
6927 size_t xn = (len+1) / 2;
6932 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
6933#if SIZEOF_BDIGIT > SIZEOF_LONG
6939 else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) {
6940 size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
6941 VALUE t = bignew_1(0, tn, 1);
6942 BDIGIT *tds = BDIGITS(t);
6946 while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
6947 bary_cmp(tds, tn, xds, xn) < 0) {
6949 BARY_TRUNC(tds, tn);
6951 carry = bary_add(xds, xn, xds, xn, tds, tn);
6952 bary_small_rshift(xds, xds, xn, 1, carry);
6962bary_powm_gmp(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
const BDIGIT *mds,
size_t mn)
6970 bdigits_to_mpz(x, xds, xn);
6971 bdigits_to_mpz(y, yds, yn);
6972 bdigits_to_mpz(m, mds, mn);
6973 mpz_powm(z, x, y, m);
6974 bdigits_from_mpz(z, zds, &count);
6975 BDIGITS_ZERO(zds+count, zn-count);
6988 size_t xn, yn, mn, zn;
6996 assert(RB_BIGNUM_TYPE_P(m));
7002 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7003 if (nega_flg & BIGNUM_POSITIVE_P(z)) {
7004 z = rb_big_minus(z, m);
7009 return rb_big_norm(z);
7015 if (
RTEST(rb_int_odd_p(y))) {
7016 tmp = rb_int_mul(tmp, x);
7017 tmp = rb_int_modulo(tmp, m);
7019 x = rb_int_mul(x, x);
7020 x = rb_int_modulo(x, m);
7022 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7024 tmp = rb_int_mul(tmp, x);
7025 tmp = rb_int_modulo(tmp, m);
7027 x = rb_int_mul(x, x);
7028 x = rb_int_modulo(x, m);
7031 if (nega_flg && rb_int_positive_p(tmp)) {
7032 tmp = rb_int_minus(tmp, m);
7043int_pow_tmp1(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7050 if (
RTEST(rb_int_odd_p(y))) {
7051 tmp = (tmp * xx) % mm;
7053 xx = (xx * xx) % mm;
7055 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7057 tmp = (tmp * xx) % mm;
7059 xx = (xx * xx) % mm;
7062 if (nega_flg && tmp) {
7069int_pow_tmp2(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7077# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7082# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7086 if (
RTEST(rb_int_odd_p(y))) {
7087 tmp2 = MUL_MODULO(tmp2, xx, m);
7089 xx = MUL_MODULO(xx, xx, m);
7091 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7093 tmp2 = MUL_MODULO(tmp2, xx, m);
7095 xx = MUL_MODULO(xx, xx, m);
7103 if (nega_flg && tmp) {
7121rb_int_powm(
int const argc,
VALUE *
const argv,
VALUE const num)
7123 rb_check_arity(argc, 1, 2);
7126 return rb_int_pow(num, argv[0]);
7129 VALUE const a = num;
7130 VALUE const b = argv[0];
7136 if (rb_int_negative_p(b)) {
7140 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless all arguments are integers");
7143 if (rb_int_negative_p(m)) {
7144 m = rb_int_uminus(m);
7149 long const half_val = (long)HALF_LONG_MSB;
7152 if (mm == 1)
return INT2FIX(0);
7153 if (mm <= half_val) {
7154 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7157 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7163 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define REALLOC_N
Old name of RB_REALLOC_N.
#define ISSPACE
Old name of rb_isspace.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define xfree
Old name of ruby_xfree.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define NEGFIXABLE
Old name of RB_NEGFIXABLE.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define 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 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.
void rb_raise(VALUE exc, const char *fmt,...)
Exception entry point.
void rb_bug(const char *fmt,...)
Interpreter panic switch.
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_warn(const char *fmt,...)
Identical to rb_warning(), except it reports always regardless of runtime -W flag.
VALUE rb_eArgError
ArgumentError 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.
#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.
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.
VALUE rb_str_resize(VALUE str, long len)
Overwrites the length of the string.
void rb_thread_check_ints(void)
Checks for interrupts.
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
#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...
unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow)
Scans the passed string, assuming the string is a textual representation of an integer.
VALUE rb_sprintf(const char *fmt,...)
Ruby's extended sprintf(3).
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 RGENGC_WB_PROTECTED_BIGNUM
This is a compile-time flag to enable/disable write barrier for struct RBignum.
#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 VALUE
Type that represents a Ruby object.
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...