12#include "ruby/internal/config.h"
27#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
36#include "internal/bignum.h"
37#include "internal/complex.h"
38#include "internal/gc.h"
39#include "internal/numeric.h"
40#include "internal/object.h"
41#include "internal/sanitizers.h"
42#include "internal/variable.h"
43#include "internal/warnings.h"
47#include "ruby_assert.h"
59static const bool debug_integer_pack = (
60#ifdef DEBUG_INTEGER_PACK
67const char ruby_digitmap[] =
"0123456789abcdefghijklmnopqrstuvwxyz";
72const char ruby_decimal_digit_pairs[201] =
73 "00010203040506070809"
74 "10111213141516171819"
75 "20212223242526272829"
76 "30313233343536373839"
77 "40414243444546474849"
78 "50515253545556575859"
79 "60616263646566676869"
80 "70717273747576777879"
81 "80818283848586878889"
82 "90919293949596979899";
84#ifndef SIZEOF_BDIGIT_DBL
85# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
86# define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
88# define SIZEOF_BDIGIT_DBL SIZEOF_LONG
92STATIC_ASSERT(sizeof_bdigit_dbl,
sizeof(BDIGIT_DBL) == SIZEOF_BDIGIT_DBL);
93STATIC_ASSERT(sizeof_bdigit_dbl_signed,
sizeof(BDIGIT_DBL_SIGNED) == SIZEOF_BDIGIT_DBL);
94STATIC_ASSERT(sizeof_bdigit, SIZEOF_BDIGIT <=
sizeof(BDIGIT));
95STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGIT*2 <= SIZEOF_BDIGIT_DBL);
96STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
97STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
98STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
100#if SIZEOF_BDIGIT < SIZEOF_LONG
101STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
103STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
106#ifdef WORDS_BIGENDIAN
107# define HOST_BIGENDIAN_P 1
109# define HOST_BIGENDIAN_P 0
112#define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
113#define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
114#define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
115#define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
116#define POW2_P(x) (((x)&((x)-1))==0)
118#define BDIGITS(x) (BIGNUM_DIGITS(x))
119#define BITSPERDIG (SIZEOF_BDIGIT*CHAR_BIT)
120#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
121#define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
122#define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
123#define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
124#define BIGDN(x) RSHIFT((x),BITSPERDIG)
125#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
126#define BDIGMAX ((BDIGIT)(BIGRAD-1))
127#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
129#if SIZEOF_BDIGIT == 2
130# define swap_bdigit(x) swap16(x)
131#elif SIZEOF_BDIGIT == 4
132# define swap_bdigit(x) swap32(x)
133#elif SIZEOF_BDIGIT == 8
134# define swap_bdigit(x) swap64(x)
137#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
138 (BDIGITS(x)[0] == 0 && \
139 (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
140#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
141 BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
142 (size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
143 rb_absint_size(x, NULL))
145#define BIGDIVREM_EXTRA_WORDS 1
146#define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT)
147#define BARY_ARGS(ary) ary, numberof(ary)
149#define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
150#define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
151#define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
152#define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
153#define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
155#define BIGNUM_SET_NEGATIVE_SIGN(b) BIGNUM_SET_SIGN(b, 0)
156#define BIGNUM_SET_POSITIVE_SIGN(b) BIGNUM_SET_SIGN(b, 1)
158#define bignew(len,sign) bignew_1(rb_cInteger,(len),(sign))
160#define BDIGITS_ZERO(ptr, n) do { \
161 BDIGIT *bdigitz_zero_ptr = (ptr); \
162 size_t bdigitz_zero_n = (n); \
163 while (bdigitz_zero_n) { \
164 *bdigitz_zero_ptr++ = 0; \
169#define BARY_TRUNC(ds, n) do { \
170 while (0 < (n) && (ds)[(n)-1] == 0) \
174#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
175#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
177#define GMP_MUL_DIGITS 20
178#define KARATSUBA_MUL_DIGITS 70
179#define TOOM3_MUL_DIGITS 150
181#define GMP_DIV_DIGITS 20
182#define GMP_BIG2STR_DIGITS 20
183#define GMP_STR2BIG_DIGITS 20
185# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
187# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
190typedef 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);
192static mulfunc_t bary_mul_toom3_start;
193static mulfunc_t bary_mul_karatsuba_start;
194static BDIGIT bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y);
200static inline VALUE power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret);
202#if SIZEOF_BDIGIT <= SIZEOF_INT
203static int nlz(BDIGIT x) {
return nlz_int((
unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGIT) * CHAR_BIT; }
204#elif SIZEOF_BDIGIT <= SIZEOF_LONG
205static int nlz(BDIGIT x) {
return nlz_long((
unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
206#elif SIZEOF_BDIGIT <= SIZEOF_LONG_LONG
207static int nlz(BDIGIT x) {
return nlz_long_long((
unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
208#elif SIZEOF_BDIGIT <= SIZEOF_INT128_T
209static int nlz(BDIGIT x) {
return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGIT) * CHAR_BIT; }
212#define U16(a) ((uint16_t)(a))
213#define U32(a) ((uint32_t)(a))
215#define U64(a,b) (((uint64_t)(a) << 32) | (b))
218#define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
265#if SIZEOF_BDIGIT_DBL == 2
266static const int maxpow16_exp[35] = {
267 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
268 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
270static const uint16_t maxpow16_num[35] = {
271 U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
272 U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
273 U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
274 U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
275 U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
276 U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
277 U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
278 U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
279 U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
281#elif SIZEOF_BDIGIT_DBL == 4
282static const int maxpow32_exp[35] = {
283 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
284 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
286static const uint32_t maxpow32_num[35] = {
287 U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
288 U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
289 U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
290 U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
291 U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
292 U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
293 U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
294 U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
295 U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
297#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
298static const int maxpow64_exp[35] = {
299 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
300 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
303static const uint64_t maxpow64_num[35] = {
304 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
305 U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
306 U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
307 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
308 U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
309 U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
310 U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
311 U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
312 U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
313 U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
314 U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
315 U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
316 U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
317 U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
318 U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
319 U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
320 U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
321 U64(0x41c21cb8,0xe1000000),
323#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
324static const int maxpow128_exp[35] = {
325 127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
326 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
329static const uint128_t maxpow128_num[35] = {
330 U128(0x80000000,0x00000000,0x00000000,0x00000000),
331 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
332 U128(0x40000000,0x00000000,0x00000000,0x00000000),
333 U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
334 U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
335 U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
336 U128(0x40000000,0x00000000,0x00000000,0x00000000),
337 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
338 U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
339 U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
340 U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
341 U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
342 U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
343 U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
344 U128(0x10000000,0x00000000,0x00000000,0x00000000),
345 U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
346 U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
347 U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
348 U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
349 U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
350 U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
351 U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
352 U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
353 U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
354 U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
355 U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
356 U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
357 U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
358 U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
359 U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
360 U128(0x20000000,0x00000000,0x00000000,0x00000000),
361 U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
362 U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
363 U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
364 U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
369maxpow_in_bdigit_dbl(
int base,
int *exp_ret)
377#if SIZEOF_BDIGIT_DBL == 2
378 maxpow = maxpow16_num[base-2];
379 exponent = maxpow16_exp[base-2];
380#elif SIZEOF_BDIGIT_DBL == 4
381 maxpow = maxpow32_num[base-2];
382 exponent = maxpow32_exp[base-2];
383#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
384 maxpow = maxpow64_num[base-2];
385 exponent = maxpow64_exp[base-2];
386#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
387 maxpow = maxpow128_num[base-2];
388 exponent = maxpow128_exp[base-2];
392 while (maxpow <= BDIGIT_DBL_MAX / base) {
403static inline BDIGIT_DBL
404bary2bdigitdbl(
const BDIGIT *ds,
size_t n)
409 return ds[0] | BIGUP(ds[1]);
416bdigitdbl2bary(BDIGIT *ds,
size_t n, BDIGIT_DBL num)
421 ds[1] = (BDIGIT)BIGDN(num);
425bary_cmp(
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
436 for (i = 0; i < xn; i++)
437 if (xds[xn - i - 1] != yds[yn - i - 1])
441 return xds[xn - i - 1] < yds[yn - i - 1] ? -1 : 1;
445bary_small_lshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift)
451 for (i=0; i<n; i++) {
452 num = num | (BDIGIT_DBL)*xds++ << shift;
460bary_small_rshift(BDIGIT *zds,
const BDIGIT *xds,
size_t n,
int shift, BDIGIT higher_bdigit)
467 num = BIGUP(higher_bdigit);
468 for (i = 0; i < n; i++) {
469 BDIGIT x = xds[n - i - 1];
470 num = (num | x) >> shift;
471 zds[n - i - 1] = BIGLO(num);
477bary_zero_p(
const BDIGIT *xds,
size_t xn)
482 if (xds[--xn])
return 0;
488bary_neg(BDIGIT *ds,
size_t n)
491 for (i = 0; i < n; i++)
492 ds[n - i - 1] = BIGLO(~ds[n - i - 1]);
496bary_2comp(BDIGIT *ds,
size_t n)
499 for (i = 0; i < n; i++) {
507 ds[i] = BIGLO(~ds[i] + 1);
510 ds[i] = BIGLO(~ds[i]);
516bary_swap(BDIGIT *ds,
size_t num_bdigits)
519 BDIGIT *p2 = ds + num_bdigits - 1;
520 for (; p1 < p2; p1++, p2--) {
527#define INTEGER_PACK_WORDORDER_MASK \
528 (INTEGER_PACK_MSWORD_FIRST | \
529 INTEGER_PACK_LSWORD_FIRST)
530#define INTEGER_PACK_BYTEORDER_MASK \
531 (INTEGER_PACK_MSBYTE_FIRST | \
532 INTEGER_PACK_LSBYTE_FIRST | \
533 INTEGER_PACK_NATIVE_BYTE_ORDER)
536validate_integer_pack_format(
size_t numwords,
size_t wordsize,
size_t nails,
int flags,
int supported_flags)
538 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
539 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
541 if (flags & ~supported_flags) {
542 rb_raise(rb_eArgError,
"unsupported flags specified");
544 if (wordorder_bits == 0) {
546 rb_raise(rb_eArgError,
"word order not specified");
550 rb_raise(rb_eArgError,
"unexpected word order");
551 if (byteorder_bits == 0) {
552 rb_raise(rb_eArgError,
"byte order not specified");
557 rb_raise(rb_eArgError,
"unexpected byte order");
559 rb_raise(rb_eArgError,
"invalid wordsize: %"PRI_SIZE_PREFIX
"u", wordsize);
560 if (SSIZE_MAX < wordsize)
561 rb_raise(rb_eArgError,
"too big wordsize: %"PRI_SIZE_PREFIX
"u", wordsize);
562 if (wordsize <= nails / CHAR_BIT)
563 rb_raise(rb_eArgError,
"too big nails: %"PRI_SIZE_PREFIX
"u", nails);
564 if (SIZE_MAX / wordsize < numwords)
565 rb_raise(rb_eArgError,
"too big numwords * wordsize: %"PRI_SIZE_PREFIX
"u * %"PRI_SIZE_PREFIX
"u", numwords, wordsize);
569integer_pack_loop_setup(
570 size_t numwords,
size_t wordsize,
size_t nails,
int flags,
571 size_t *word_num_fullbytes_ret,
572 int *word_num_partialbits_ret,
573 size_t *word_start_ret,
574 ssize_t *word_step_ret,
575 size_t *word_last_ret,
576 size_t *byte_start_ret,
579 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
580 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
581 size_t word_num_fullbytes;
582 int word_num_partialbits;
589 word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
590 if (word_num_partialbits == CHAR_BIT)
591 word_num_partialbits = 0;
592 word_num_fullbytes = wordsize - (nails / CHAR_BIT);
593 if (word_num_partialbits != 0) {
594 word_num_fullbytes--;
598 word_start = wordsize*(numwords-1);
599 word_step = -(ssize_t)wordsize;
604 word_step = wordsize;
605 word_last = wordsize*(numwords-1);
609#ifdef WORDS_BIGENDIAN
616 byte_start = wordsize-1;
624 *word_num_partialbits_ret = word_num_partialbits;
625 *word_num_fullbytes_ret = word_num_fullbytes;
626 *word_start_ret = word_start;
627 *word_step_ret = word_step;
628 *word_last_ret = word_last;
629 *byte_start_ret = byte_start;
630 *byte_step_ret = byte_step;
634integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
636 if (*dpp < *dep && BITSPERDIG <= (
int)
sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
637 *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
638 *numbits_in_dd_p += BITSPERDIG;
640 else if (*dpp == *dep) {
642 *numbits_in_dd_p = (int)
sizeof(*ddp) * CHAR_BIT;
646static inline BDIGIT_DBL
647integer_pack_take_lowbits(
int n, BDIGIT_DBL *ddp,
int *numbits_in_dd_p)
650 ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
652 *numbits_in_dd_p -= n;
656#if !defined(WORDS_BIGENDIAN)
658bytes_2comp(
unsigned char *buf,
size_t len)
661 for (i = 0; i <
len; i++) {
662 signed char c = buf[i];
664 unsigned int e = d & 0xFF;
667 for (i = 0; i <
len; i++) {
677bary_pack(
int sign, BDIGIT *ds,
size_t num_bdigits,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
680 unsigned char *buf, *bufend;
683 de = ds + num_bdigits;
685 validate_integer_pack_format(numwords, wordsize, nails, flags,
694 while (dp < de && de[-1] == 0)
702 MEMZERO(words,
unsigned char, numwords * wordsize);
705 if (nails == 0 && numwords == 1) {
706 int need_swap = wordsize != 1 &&
712 *((
unsigned char *)words) = (
unsigned char)(d = dp[0]);
713 return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
715#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
716 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
717 uint16_t u = (uint16_t)(d = dp[0]);
718 if (need_swap) u = swap16(u);
719 *((uint16_t *)words) = u;
720 return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
723#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
724 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
725 uint32_t u = (uint32_t)(d = dp[0]);
726 if (need_swap) u = swap32(u);
727 *((uint32_t *)words) = u;
728 return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
731#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
732 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
733 uint64_t u = (uint64_t)(d = dp[0]);
734 if (need_swap) u = swap64(u);
735 *((uint64_t *)words) = u;
736 return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
743 *((
unsigned char *)words) = (
unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
744 return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
746#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
747 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
748 uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
749 if (need_swap) u = swap16(u);
750 *((uint16_t *)words) = u;
751 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
752 (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
755#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
756 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
757 uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
758 if (need_swap) u = swap32(u);
759 *((uint32_t *)words) = u;
760 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
761 (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
764#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
765 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
766 uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
767 if (need_swap) u = swap64(u);
768 *((uint64_t *)words) = u;
769 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
770 (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
775#if !defined(WORDS_BIGENDIAN)
776 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
779 size_t src_size = (de - dp) * SIZEOF_BDIGIT;
780 size_t dst_size = numwords * wordsize;
782 while (0 < src_size && ((
unsigned char *)ds)[src_size-1] == 0)
784 if (src_size <= dst_size) {
785 MEMCPY(words, dp,
char, src_size);
786 MEMZERO((
char*)words + src_size,
char, dst_size - src_size);
789 MEMCPY(words, dp,
char, dst_size);
793 int zero_p = bytes_2comp(words, dst_size);
794 if (zero_p && overflow) {
795 unsigned char *p = (
unsigned char *)dp;
796 if (dst_size == src_size-1 &&
807 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
808 wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words %
RUBY_ALIGNOF(BDIGIT) == 0) {
809 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
810 size_t src_num_bdigits = de - dp;
811 size_t dst_num_bdigits = numwords * bdigits_per_word;
816 if (src_num_bdigits <= dst_num_bdigits) {
817 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
818 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
821 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
825 int zero_p = bary_2comp(words, dst_num_bdigits);
826 if (zero_p && overflow &&
827 dst_num_bdigits == src_num_bdigits-1 &&
828 dp[dst_num_bdigits] == 1)
831 if (msbytefirst_p != HOST_BIGENDIAN_P) {
833 for (i = 0; i < dst_num_bdigits; i++) {
834 BDIGIT d = ((BDIGIT*)words)[i];
835 ((BDIGIT*)words)[i] = swap_bdigit(d);
838 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
841 for (i = 0; i < numwords; i++) {
842 bary_swap(p, bdigits_per_word);
843 p += bdigits_per_word;
847 bary_swap(words, dst_num_bdigits);
856 bufend = buf + numwords * wordsize;
863 if (de - dp == 1 && dp[0] == 1)
870 memset(buf,
'\0', bufend - buf);
872 else if (dp < de && buf < bufend) {
873 int word_num_partialbits;
874 size_t word_num_fullbytes;
880 size_t word_start, word_last;
881 unsigned char *wordp, *last_wordp;
885 integer_pack_loop_setup(numwords, wordsize, nails, flags,
886 &word_num_fullbytes, &word_num_partialbits,
887 &word_start, &word_step, &word_last, &byte_start, &byte_step);
889 wordp = buf + word_start;
890 last_wordp = buf + word_last;
896 integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
897#define TAKE_LOWBITS(n) \
898 integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
901 size_t index_in_word = 0;
902 unsigned char *bytep = wordp + byte_start;
903 while (index_in_word < word_num_fullbytes) {
905 *bytep = TAKE_LOWBITS(CHAR_BIT);
909 if (word_num_partialbits) {
911 *bytep = TAKE_LOWBITS(word_num_partialbits);
915 while (index_in_word < wordsize) {
921 if (wordp == last_wordp)
928 if (dp != de || 1 < dd) {
939 while (dp < de && *dp == 0)
951 int word_num_partialbits;
952 size_t word_num_fullbytes;
958 size_t word_start, word_last;
959 unsigned char *wordp, *last_wordp;
961 unsigned int partialbits_mask;
964 integer_pack_loop_setup(numwords, wordsize, nails, flags,
965 &word_num_fullbytes, &word_num_partialbits,
966 &word_start, &word_step, &word_last, &byte_start, &byte_step);
968 partialbits_mask = (1 << word_num_partialbits) - 1;
971 wordp = buf + word_start;
972 last_wordp = buf + word_last;
976 size_t index_in_word = 0;
977 unsigned char *bytep = wordp + byte_start;
978 while (index_in_word < word_num_fullbytes) {
979 carry += (
unsigned char)~*bytep;
980 *bytep = (
unsigned char)carry;
985 if (word_num_partialbits) {
986 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
987 *bytep = carry & partialbits_mask;
988 carry >>= word_num_partialbits;
993 if (wordp == last_wordp)
1006integer_unpack_num_bdigits_small(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1009 size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
1010 size_t num_bdigits = roomof(num_bits, BITSPERDIG);
1011 *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
1016integer_unpack_num_bdigits_generic(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1023 size_t num_bytes1 = wordsize * numwords;
1026 size_t q1 = numwords / CHAR_BIT;
1027 size_t r1 = numwords % CHAR_BIT;
1030 size_t num_bytes2 = num_bytes1 - nails * q1;
1033 size_t q2 = nails / CHAR_BIT;
1034 size_t r2 = nails % CHAR_BIT;
1037 size_t num_bytes3 = num_bytes2 - q2 * r1;
1040 size_t q3 = num_bytes3 / BITSPERDIG;
1041 size_t r3 = num_bytes3 % BITSPERDIG;
1044 size_t num_digits1 = CHAR_BIT * q3;
1057 if (CHAR_BIT * r3 >= r1 * r2) {
1058 size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
1059 size_t q4 = tmp1 / BITSPERDIG;
1060 int r4 = (int)(tmp1 % BITSPERDIG);
1061 size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
1066 size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
1067 size_t q4 = tmp1 / BITSPERDIG;
1068 int r4 = (int)(tmp1 % BITSPERDIG);
1069 size_t num_digits2 = num_digits1 - q4;
1076integer_unpack_num_bdigits(
size_t numwords,
size_t wordsize,
size_t nails,
int *nlp_bits_ret)
1080 if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
1081 num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
1082 if (debug_integer_pack) {
1084 size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
1091 num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
1097integer_unpack_push_bits(
int data,
int numbits, BDIGIT_DBL *ddp,
int *numbits_in_dd_p, BDIGIT **dpp)
1099 (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
1100 *numbits_in_dd_p += numbits;
1101 while (BITSPERDIG <= *numbits_in_dd_p) {
1102 *(*dpp)++ = BIGLO(*ddp);
1104 *numbits_in_dd_p -= BITSPERDIG;
1109integer_unpack_single_bdigit(BDIGIT u,
size_t size,
int flags, BDIGIT *dp)
1114 ((size == SIZEOF_BDIGIT && u == 0) ? -2 : -1) :
1115 ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
1117 u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
1127#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
1128#define reinterpret_cast(type, value) (type) \
1129 __builtin_assume_aligned((value), sizeof(*(type)NULL));
1131#define reinterpret_cast(type, value) (type)value
1135bary_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)
1138 const unsigned char *buf = words;
1143 de = dp + num_bdigits;
1146 if (nails == 0 && numwords == 1) {
1147 int need_swap = wordsize != 1 &&
1150 if (wordsize == 1) {
1151 return integer_unpack_single_bdigit(*(uint8_t *)buf,
sizeof(uint8_t), flags, dp);
1153#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
1154 if (wordsize == 2 && (uintptr_t)words %
RUBY_ALIGNOF(uint16_t) == 0) {
1155 uint16_t u = *reinterpret_cast(
const uint16_t *, buf);
1156 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
1159#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
1160 if (wordsize == 4 && (uintptr_t)words %
RUBY_ALIGNOF(uint32_t) == 0) {
1161 uint32_t u = *reinterpret_cast(
const uint32_t *, buf);
1162 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
1165#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
1166 if (wordsize == 8 && (uintptr_t)words %
RUBY_ALIGNOF(uint64_t) == 0) {
1167 uint64_t u = *reinterpret_cast(
const uint64_t *, buf);
1168 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
1171#undef reinterpret_cast
1173#if !defined(WORDS_BIGENDIAN)
1174 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1177 size_t src_size = numwords * wordsize;
1178 size_t dst_size = num_bdigits * SIZEOF_BDIGIT;
1179 MEMCPY(dp, words,
char, src_size);
1183 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1184 zero_p = bary_2comp(dp, num_bdigits);
1185 sign = zero_p ? -2 : -1;
1187 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
1188 memset((
char*)dp + src_size, 0xff, dst_size - src_size);
1189 bary_2comp(dp, num_bdigits);
1193 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1198 MEMZERO((
char*)dp + src_size,
char, dst_size - src_size);
1204 if (nails == 0 && SIZEOF_BDIGIT ==
sizeof(BDIGIT) &&
1205 wordsize % SIZEOF_BDIGIT == 0) {
1206 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
1210 MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
1211 if (mswordfirst_p) {
1212 bary_swap(dp, num_bdigits);
1214 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
1217 for (i = 0; i < numwords; i++) {
1218 bary_swap(p, bdigits_per_word);
1219 p += bdigits_per_word;
1222 if (msbytefirst_p != HOST_BIGENDIAN_P) {
1224 for (p = dp; p < de; p++) {
1226 *p = swap_bdigit(d);
1231 int zero_p = bary_2comp(dp, num_bdigits);
1232 sign = zero_p ? -2 : -1;
1234 else if (BDIGIT_MSB(de[-1])) {
1235 bary_2comp(dp, num_bdigits);
1249 if (num_bdigits != 0) {
1250 int word_num_partialbits;
1251 size_t word_num_fullbytes;
1257 size_t word_start, word_last;
1258 const unsigned char *wordp, *last_wordp;
1262 integer_pack_loop_setup(numwords, wordsize, nails, flags,
1263 &word_num_fullbytes, &word_num_partialbits,
1264 &word_start, &word_step, &word_last, &byte_start, &byte_step);
1266 wordp = buf + word_start;
1267 last_wordp = buf + word_last;
1272#define PUSH_BITS(data, numbits) \
1273 integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
1276 size_t index_in_word = 0;
1277 const unsigned char *bytep = wordp + byte_start;
1278 while (index_in_word < word_num_fullbytes) {
1279 PUSH_BITS(*bytep, CHAR_BIT);
1283 if (word_num_partialbits) {
1284 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
1289 if (wordp == last_wordp)
1308 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
1309 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
1318 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
1321 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
1327 if (sign == -1 && num_bdigits != 0) {
1328 bary_2comp(bdigits, num_bdigits);
1336bary_unpack(BDIGIT *bdigits,
size_t num_bdigits,
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
1338 size_t num_bdigits0;
1342 validate_integer_pack_format(numwords, wordsize, nails, flags,
1353 num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
1357 sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
1359 if (num_bdigits0 < num_bdigits) {
1360 BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
1362 bdigits[num_bdigits0] = 1;
1368bary_subb(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int borrow)
1370 BDIGIT_DBL_SIGNED num;
1377 sn = xn < yn ? xn : yn;
1379 num = borrow ? -1 : 0;
1380 for (i = 0; i < sn; i++) {
1381 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
1382 zds[i] = BIGLO(num);
1386 for (; i < xn; i++) {
1387 if (num == 0)
goto num_is_zero;
1389 zds[i] = BIGLO(num);
1394 for (; i < yn; i++) {
1396 zds[i] = BIGLO(num);
1400 if (num == 0)
goto num_is_zero;
1401 for (; i < zn; i++) {
1407 if (xds == zds && xn == zn)
1409 for (; i < xn; i++) {
1412 for (; i < zn; i++) {
1419bary_sub(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1421 return bary_subb(zds, zn, xds, xn, yds, yn, 0);
1425bary_sub_one(BDIGIT *zds,
size_t zn)
1427 return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
1431bary_addc(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn,
int carry)
1441 tds = xds; xds = yds; yds = tds;
1442 i = xn; xn = yn; yn = i;
1445 num = carry ? 1 : 0;
1446 for (i = 0; i < xn; i++) {
1447 num += (BDIGIT_DBL)xds[i] + yds[i];
1448 zds[i] = BIGLO(num);
1451 for (; i < yn; i++) {
1452 if (num == 0)
goto num_is_zero;
1454 zds[i] = BIGLO(num);
1457 for (; i < zn; i++) {
1458 if (num == 0)
goto num_is_zero;
1459 zds[i] = BIGLO(num);
1465 if (yds == zds && yn == zn)
1467 for (; i < yn; i++) {
1470 for (; i < zn; i++) {
1477bary_add(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1479 return bary_addc(zds, zn, xds, xn, yds, yn, 0);
1483bary_add_one(BDIGIT *ds,
size_t n)
1486 for (i = 0; i < n; i++) {
1487 BDIGIT_DBL n = ds[i];
1497bary_mul_single(BDIGIT *zds,
size_t zn, BDIGIT x, BDIGIT y)
1503 n = (BDIGIT_DBL)x * y;
1504 bdigitdbl2bary(zds, 2, n);
1505 BDIGITS_ZERO(zds + 2, zn - 2);
1509bary_muladd_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1521 for (j = 0; j < yn; j++) {
1522 BDIGIT_DBL ee = n + dd * yds[j];
1533 for (; j < zn; j++) {
1543static BDIGIT_DBL_SIGNED
1544bigdivrem_mulsub(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1548 BDIGIT_DBL_SIGNED num;
1557 BDIGIT_DBL_SIGNED ee;
1558 t2 += (BDIGIT_DBL)yds[i] * x;
1559 ee = num - BIGLO(t2);
1560 num = (BDIGIT_DBL_SIGNED)zds[i] + ee;
1561 if (ee) zds[i] = BIGLO(num);
1565 num -= (BDIGIT_DBL_SIGNED)t2;
1566 num += (BDIGIT_DBL_SIGNED)zds[yn];
1571bary_mulsub_1xN(BDIGIT *zds,
size_t zn, BDIGIT x,
const BDIGIT *yds,
size_t yn)
1573 BDIGIT_DBL_SIGNED num;
1577 num = bigdivrem_mulsub(zds, zn, x, yds, yn);
1578 zds[yn] = BIGLO(num);
1585bary_mul_normal(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
1591 BDIGITS_ZERO(zds, zn);
1592 for (i = 0; i < xn; i++) {
1593 bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
1600 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1601 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1602 bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
1613bary_sq_fast(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn)
1622 BDIGITS_ZERO(zds, zn);
1627 for (i = 0; i < xn-1; i++) {
1628 v = (BDIGIT_DBL)xds[i];
1631 c = (BDIGIT_DBL)zds[i + i] + v * v;
1632 zds[i + i] = BIGLO(c);
1637 for (j = i + 1; j < xn; j++) {
1638 w = (BDIGIT_DBL)xds[j];
1639 c += (BDIGIT_DBL)zds[i + j] + vl * w;
1640 zds[i + j] = BIGLO(c);
1646 c += (BDIGIT_DBL)zds[i + xn];
1647 zds[i + xn] = BIGLO(c);
1650 zds[i + xn + 1] += (BDIGIT)c;
1655 v = (BDIGIT_DBL)xds[i];
1658 c = (BDIGIT_DBL)zds[i + i] + v * v;
1659 zds[i + i] = BIGLO(c);
1662 zds[i + xn] += BIGLO(c);
1667rb_big_sq_fast(
VALUE x)
1669 size_t xn = BIGNUM_LEN(x), zn = 2 * xn;
1670 VALUE z = bignew(zn, 1);
1671 bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
1677max_size(
size_t a,
size_t b)
1679 return (a > b ? a : b);
1684bary_mul_balance_with_mulfunc(BDIGIT *
const zds,
const size_t zn,
1685 const BDIGIT *
const xds,
const size_t xn,
1686 const BDIGIT *
const yds,
const size_t yn,
1687 BDIGIT *wds,
size_t wn, mulfunc_t *
const mulfunc)
1694 RUBY_ASSERT(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
1696 BDIGITS_ZERO(zds, xn);
1705 const size_t r = yn % xn;
1706 if (2*xn + yn + max_size(xn-r, r) > zn) {
1714 const size_t r = (xn > (yn - n) ? (yn - n) : xn);
1715 const size_t tn = (xn + r);
1716 if (2 * (xn + r) <= zn - n) {
1717 BDIGIT *
const tds = zds + n + xn + r;
1718 mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
1719 BDIGITS_ZERO(zds + n + xn, r);
1720 bary_add(zds + n, tn,
1725 BDIGIT *
const tds = zds + n;
1732 rb_bug(
"wds is not enough: %" PRIdSIZE
" for %" PRIdSIZE, wn, xn);
1735 MEMCPY(wds, zds + n, BDIGIT, xn);
1736 mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
1737 bary_add(zds + n, tn,
1743 BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
1752 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1753 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1754 bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
1762bary_mul_karatsuba(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1767 int sub_p, borrow, carry1, carry2, carry3;
1773 const BDIGIT *xds0, *xds1, *yds0, *yds1;
1774 BDIGIT *zds0, *zds1, *zds2, *zds3;
1780 sq = xds == yds && xn == yn;
1830 if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
1831 bary_2comp(zds0, n);
1839 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
1842 if (bary_sub(wds, n, yds, n, yds+n, n)) {
1849 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
1856 borrow = !bary_2comp(zds1, 2*n);
1860 MEMCPY(wds, zds1, BDIGIT, n);
1864 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
1868 carry1 = bary_add(wds, n, wds, n, zds0, n);
1869 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
1873 carry2 = bary_add(zds1, n, zds1, n, wds, n);
1877 MEMCPY(wds, zds2, BDIGIT, n);
1881 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
1885 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
1889 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
1893 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
1898 bary_add_one(zds2, zn-2*n);
1900 if (carry1 + carry3 - borrow < 0)
1901 bary_sub_one(zds3, zn-3*n);
1902 else if (carry1 + carry3 - borrow > 0) {
1903 BDIGIT c = carry1 + carry3 - borrow;
1904 bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
1919 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1920 bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
1923 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1933 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1934 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1935 if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
1936 rb_raise(rb_eArgError,
"unexpected bignum length for karatsuba");
1937 bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
1944bary_mul_toom3(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn, BDIGIT *wds,
size_t wn)
1951 size_t x0n;
const BDIGIT *x0ds;
1952 size_t x1n;
const BDIGIT *x1ds;
1953 size_t x2n;
const BDIGIT *x2ds;
1954 size_t y0n;
const BDIGIT *y0ds;
1955 size_t y1n;
const BDIGIT *y1ds;
1956 size_t y2n;
const BDIGIT *y2ds;
1958 size_t u1n; BDIGIT *u1ds;
int u1p;
1959 size_t u2n; BDIGIT *u2ds;
int u2p;
1960 size_t u3n; BDIGIT *u3ds;
int u3p;
1962 size_t v1n; BDIGIT *v1ds;
int v1p;
1963 size_t v2n; BDIGIT *v2ds;
int v2p;
1964 size_t v3n; BDIGIT *v3ds;
int v3p;
1966 size_t t0n; BDIGIT *t0ds;
int t0p;
1967 size_t t1n; BDIGIT *t1ds;
int t1p;
1968 size_t t2n; BDIGIT *t2ds;
int t2p;
1969 size_t t3n; BDIGIT *t3ds;
int t3p;
1970 size_t t4n; BDIGIT *t4ds;
int t4p;
1972 size_t z0n; BDIGIT *z0ds;
1973 size_t z1n; BDIGIT *z1ds;
int z1p;
1974 size_t z2n; BDIGIT *z2ds;
int z2p;
1975 size_t z3n; BDIGIT *z3ds;
int z3p;
1976 size_t z4n; BDIGIT *z4ds;
1978 size_t zzn; BDIGIT *zzds;
1980 int sq = xds == yds && xn == yn;
1998 wnc += (t1n = 2*n+2);
1999 wnc += (t2n = 2*n+2);
2000 wnc += (t3n = 2*n+2);
2003 wnc += (z1n = 2*n+1);
2004 wnc += (z2n = 2*n+1);
2005 wnc += (z3n = 2*n+1);
2012 u1ds = wds; wds += u1n;
2013 u2ds = wds; wds += u2n;
2014 u3ds = wds; wds += u3n;
2016 v1ds = wds; wds += v1n;
2017 v2ds = wds; wds += v2n;
2018 v3ds = wds; wds += v3n;
2020 t0ds = wds; wds += t0n;
2021 t1ds = wds; wds += t1n;
2022 t2ds = wds; wds += t2n;
2023 t3ds = wds; wds += t3n;
2024 t4ds = wds; wds += t4n;
2026 z1ds = wds; wds += z1n;
2027 z2ds = wds; wds += z2n;
2028 z3ds = wds; wds += z3n;
2094 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
2098 if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
2099 bary_2comp(u2ds, u2n);
2107 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
2112 bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
2114 else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
2115 bary_2comp(u3ds, u3n);
2118 bary_small_lshift(u3ds, u3ds, u3n, 1);
2120 bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
2122 else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
2123 bary_2comp(u3ds, u3n);
2128 v1n = u1n; v1ds = u1ds; v1p = u1p;
2129 v2n = u2n; v2ds = u2ds; v2p = u2p;
2130 v3n = u3n; v3ds = u3ds; v3p = u3p;
2134 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
2139 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
2140 bary_2comp(v2ds, v2n);
2145 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
2150 bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
2152 else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
2153 bary_2comp(v3ds, v3n);
2156 bary_small_lshift(v3ds, v3ds, v3n, 1);
2158 bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
2160 else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
2161 bary_2comp(v3ds, v3n);
2167 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
2171 bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
2177 bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
2183 bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
2189 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
2197 z0n = t0n; z0ds = t0ds;
2200 z4n = t4n; z4ds = t4ds;
2205 if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
2206 bary_2comp(z3ds, z3n);
2212 bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
2214 bigdivrem_single(z3ds, z3ds, z3n, 3);
2219 if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
2220 bary_2comp(z1ds, z1n);
2226 bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
2228 bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
2233 if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
2234 bary_2comp(z2ds, z2n);
2240 bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
2246 if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
2247 bary_2comp(z3ds, z3n);
2253 bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
2255 bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
2257 bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
2260 if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
2261 bary_2comp(z3ds, z3n);
2268 bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
2271 if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
2272 bary_2comp(z2ds, z2n);
2278 if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
2279 bary_2comp(z2ds, z2n);
2284 bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
2289 if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
2290 bary_2comp(z1ds, z1n);
2295 bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
2302 MEMCPY(zzds, z0ds, BDIGIT, z0n);
2303 BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
2304 MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
2305 BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
2307 bary_add(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2309 bary_sub(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2311 bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2313 bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2315 bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2317 bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2319 BARY_TRUNC(zzds, zzn);
2320 MEMCPY(zds, zzds, BDIGIT, zzn);
2321 BDIGITS_ZERO(zds + zzn, zn - zzn);
2330 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2331 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2332 if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
2333 rb_raise(rb_eArgError,
"unexpected bignum length for toom3");
2334 bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
2342bdigits_to_mpz(mpz_t mp,
const BDIGIT *digits,
size_t len)
2344 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2345 mpz_import(mp,
len, -1,
sizeof(BDIGIT), 0, nails, digits);
2349bdigits_from_mpz(mpz_t mp, BDIGIT *digits,
size_t *
len)
2351 const size_t nails = (
sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2352 mpz_export(digits,
len, -1,
sizeof(BDIGIT), 0, nails, mp);
2356bary_mul_gmp(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2366 bdigits_to_mpz(x, xds, xn);
2367 if (xds == yds && xn == yn) {
2371 bdigits_to_mpz(y, yds, yn);
2374 bdigits_from_mpz(z, zds, &count);
2375 BDIGITS_ZERO(zds+count, zn-count);
2384 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2385 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2386 bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
2394bary_short_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2398 if (xn == 1 && yn == 1) {
2399 bary_mul_single(zds, zn, xds[0], yds[0]);
2402 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2409bary_sparse_p(
const BDIGIT *ds,
size_t n)
2413 if ( ds[2 * n / 5]) c++;
2414 if (c <= 1 && ds[ n / 2]) c++;
2415 if (c <= 1 && ds[3 * n / 5]) c++;
2417 return (c <= 1) ? 1 : 0;
2421bary_mul_precheck(BDIGIT **zdsp,
size_t *znp,
const BDIGIT **xdsp,
size_t *xnp,
const BDIGIT **ydsp,
size_t *ynp)
2425 BDIGIT *zds = *zdsp;
2427 const BDIGIT *xds = *xdsp;
2429 const BDIGIT *yds = *ydsp;
2437 if (xds[xn-1] == 0) {
2453 if (yds[yn-1] == 0) {
2469 BDIGITS_ZERO(zds, nlsz);
2478 tds = xds; xds = yds; yds = tds;
2479 tn = xn; xn = yn; yn = tn;
2485 BDIGITS_ZERO(zds, zn);
2490 MEMCPY(zds, yds, BDIGIT, yn);
2491 BDIGITS_ZERO(zds+yn, zn-yn);
2494 if (POW2_P(xds[0])) {
2495 zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
2496 BDIGITS_ZERO(zds+yn+1, zn-yn-1);
2499 if (yn == 1 && yds[0] == 1) {
2501 BDIGITS_ZERO(zds+1, zn-1);
2504 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2519bary_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)
2522 if (xn < KARATSUBA_MUL_DIGITS) {
2527 if (bary_sparse_p(xds, xn))
goto normal;
2528 if (bary_sparse_p(yds, yn)) {
2529 bary_short_mul(zds, zn, yds, yn, xds, xn);
2534 if (!KARATSUBA_BALANCED(xn, yn)) {
2535 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
2540 bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
2544 if (xds == yds && xn == yn) {
2545 bary_sq_fast(zds, zn, xds, xn);
2548 bary_short_mul(zds, zn, xds, xn, yds, yn);
2553bary_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)
2555 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2558 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2562bary_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)
2564 if (xn < TOOM3_MUL_DIGITS) {
2565 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2569 if (!TOOM3_BALANCED(xn, yn)) {
2570 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
2574 bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
2578bary_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)
2580 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2583 bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2587bary_mul(BDIGIT *zds,
size_t zn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2590 if (xn < NAIVE_MUL_DIGITS) {
2591 if (xds == yds && xn == yn)
2592 bary_sq_fast(zds, zn, xds, xn);
2594 bary_short_mul(zds, zn, xds, xn, yds, yn);
2599 if (yn < NAIVE_MUL_DIGITS) {
2600 bary_short_mul(zds, zn, yds, yn, xds, xn);
2606 bary_mul_gmp(zds, zn, xds, xn, yds, yn);
2608 bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
2615 volatile VALUE stop;
2619bigdivrem1(
void *ptr)
2622 size_t yn = bds->yn;
2623 size_t zn = bds->zn;
2624 BDIGIT *yds = bds->yds, *zds = bds->zds;
2625 BDIGIT_DBL_SIGNED num;
2633 if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
2634 else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
2636 num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
2641 num = bary_add(zds+zn-(yn+1), yn,
2655rb_big_stop(
void *ptr)
2662bigdivrem_single1(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
2669 bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
2675 t2 = x_higher_bdigit;
2676 for (i = 0; i < xn; i++) {
2677 t2 = BIGUP(t2) + xds[xn - i - 1];
2678 qds[xn - i - 1] = (BDIGIT)(t2 / y);
2686bigdivrem_single(BDIGIT *qds,
const BDIGIT *xds,
size_t xn, BDIGIT y)
2688 return bigdivrem_single1(qds, xds, xn, 0, y);
2692bigdivrem_restoring(BDIGIT *zds,
size_t zn, BDIGIT *yds,
size_t yn)
2701 for (ynzero = 0; !yds[ynzero]; ynzero++);
2703 if (ynzero+1 == yn) {
2705 r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
2710 bds.yn = yn - ynzero;
2711 bds.zds = zds + ynzero;
2712 bds.yds = yds + ynzero;
2714 bds.zn = zn - ynzero;
2715 if (bds.zn > 10000 || bds.yn > 10000) {
2720 if (bds.stop ==
Qtrue) {
2731bary_divmod_normal(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2738 RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2742 zn = xn + BIGDIVREM_EXTRA_WORDS;
2744 shift = nlz(yds[yn-1]);
2747 int alloc_z = !qds || qn < zn;
2748 if (alloc_y && alloc_z) {
2749 yyds =
ALLOCV_N(BDIGIT, tmpyz, yn+zn);
2753 yyds = alloc_y ?
ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
2754 zds = alloc_z ?
ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
2756 zds[xn] = bary_small_lshift(zds, xds, xn, shift);
2757 bary_small_lshift(yyds, yds, yn, shift);
2760 if (qds && zn <= qn)
2764 MEMCPY(zds, xds, BDIGIT, xn);
2768 yyds = (BDIGIT *)yds;
2771 bigdivrem_restoring(zds, zn, yyds, yn);
2775 bary_small_rshift(rds, zds, yn, shift, 0);
2777 MEMCPY(rds, zds, BDIGIT, yn);
2778 BDIGITS_ZERO(rds+yn, rn-yn);
2783 MEMMOVE(qds, zds+yn, BDIGIT, j);
2784 BDIGITS_ZERO(qds+j, qn-j);
2794 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2795 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2798 BARY_TRUNC(yds, yn);
2801 BARY_TRUNC(xds, xn);
2803 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2806 qn = xn + BIGDIVREM_EXTRA_WORDS;
2807 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2811 r = bignew(rn, BIGNUM_SIGN(x));
2814 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2827bary_divmod_gmp(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2832 RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2839 if (qds) mpz_init(q);
2840 if (rds) mpz_init(r);
2842 bdigits_to_mpz(x, xds, xn);
2843 bdigits_to_mpz(y, yds, yn);
2846 mpz_fdiv_q(q, x, y);
2849 mpz_fdiv_r(r, x, y);
2852 mpz_fdiv_qr(q, r, x, y);
2859 bdigits_from_mpz(q, qds, &count);
2860 BDIGITS_ZERO(qds+count, qn-count);
2865 bdigits_from_mpz(r, rds, &count);
2866 BDIGITS_ZERO(rds+count, rn-count);
2874 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2875 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2878 BARY_TRUNC(yds, yn);
2881 BARY_TRUNC(xds, xn);
2883 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2887 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2891 r = bignew(rn, BIGNUM_SIGN(x));
2894 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2907bary_divmod_branch(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2910 if (GMP_DIV_DIGITS < xn) {
2911 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2915 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2919bary_divmod(BDIGIT *qds,
size_t qn, BDIGIT *rds,
size_t rn,
const BDIGIT *xds,
size_t xn,
const BDIGIT *yds,
size_t yn)
2924 BARY_TRUNC(yds, yn);
2928 BARY_TRUNC(xds, xn);
2930 BDIGITS_ZERO(qds, qn);
2931 BDIGITS_ZERO(rds, rn);
2935 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
2936 MEMCPY(rds, xds, BDIGIT, xn);
2937 BDIGITS_ZERO(rds+xn, rn-xn);
2938 BDIGITS_ZERO(qds, qn);
2941 MEMCPY(qds, xds, BDIGIT, xn);
2942 BDIGITS_ZERO(qds+xn, qn-xn);
2943 rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
2944 BDIGITS_ZERO(rds+1, rn-1);
2946 else if (xn == 2 && yn == 2) {
2947 BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
2948 BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
2949 BDIGIT_DBL q = x / y;
2950 BDIGIT_DBL r = x % y;
2952 qds[1] = BIGLO(BIGDN(q));
2953 BDIGITS_ZERO(qds+2, qn-2);
2955 rds[1] = BIGLO(BIGDN(r));
2956 BDIGITS_ZERO(rds+2, rn-2);
2959 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
2966 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2979 rb_cmperr_reason(a, b,
"comparator returned nil");
2983 if (l > 0)
return 1;
2984 if (l < 0)
return -1;
2987 if (RB_BIGNUM_TYPE_P(val)) {
2988 if (BIGZEROP(val))
return 0;
2989 if (BIGNUM_SIGN(val))
return 1;
2997#define BIGNUM_SET_LEN(b,l) \
2998 (BIGNUM_EMBED_P(b) ? \
2999 (void)(RBASIC(b)->flags = \
3000 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
3001 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
3002 (void)(RBIGNUM(b)->as.heap.len = (l)))
3005big_embed_capa(
VALUE big)
3007 size_t size = rb_obj_shape_slot_size(big) - offsetof(
struct RBignum, as.ary);
3009 size_t capa = size /
sizeof(BDIGIT);
3015big_embed_size(
size_t capa)
3017 size_t size = offsetof(
struct RBignum, as.ary) + (
sizeof(BDIGIT) *
capa);
3018 if (size <
sizeof(
struct RBignum)) {
3019 size =
sizeof(
struct RBignum);
3025big_embeddable_p(
size_t capa)
3027 if (
capa > BIGNUM_EMBED_LEN_MAX) {
3030 return rb_gc_size_allocatable_p(big_embed_size(
capa));
3034rb_big_realloc(
VALUE big,
size_t len)
3037 size_t embed_capa = big_embed_capa(big);
3039 if (BIGNUM_EMBED_P(big)) {
3040 if (embed_capa <
len) {
3042 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, embed_capa);
3043 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
3044 RBIGNUM(big)->as.heap.digits = ds;
3049 if (
len <= embed_capa) {
3050 ds = RBIGNUM(big)->as.heap.digits;
3051 size_t old_len = RBIGNUM(big)->as.heap.len;
3053 BIGNUM_SET_LEN(big,
len);
3054 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)RBIGNUM(big)->as.ary, embed_capa *
sizeof(BDIGIT));
3056 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT,
len);
3057 SIZED_FREE_N(ds, old_len);
3061 if (BIGNUM_LEN(big) == 0) {
3062 RBIGNUM(big)->as.heap.digits =
ALLOC_N(BDIGIT,
len);
3064 else if (BIGNUM_LEN(big) !=
len) {
3065 SIZED_REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT,
len, BIGNUM_LEN(big));
3074 rb_big_realloc(big,
len);
3075 BIGNUM_SET_LEN(big,
len);
3079bignew_1(
VALUE klass,
size_t len,
int sign)
3083 if (big_embeddable_p(
len)) {
3084 size_t size = big_embed_size(
len);
3086 NEWOBJ_OF(big,
struct RBignum, klass,
T_BIGNUM | BIGNUM_EMBED_FLAG, size);
3088 BIGNUM_SET_SIGN(bigv, sign);
3089 BIGNUM_SET_LEN(bigv,
len);
3090 (void)VALGRIND_MAKE_MEM_UNDEFINED((
void*)big->as.ary,
len *
sizeof(BDIGIT));
3095 BIGNUM_SET_SIGN(bigv, sign);
3097 big->as.heap.len =
len;
3104rb_big_new(
size_t len,
int sign)
3106 VALUE obj = bignew(
len, sign != 0);
3107 memset(BIGNUM_DIGITS(obj), 0,
len *
sizeof(BDIGIT));
3114 size_t len = BIGNUM_LEN(x);
3117 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT,
len);
3122big_extend_carry(
VALUE x)
3124 rb_big_resize(x, BIGNUM_LEN(x)+1);
3125 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3132 long i = BIGNUM_LEN(x);
3133 BDIGIT *ds = BDIGITS(x);
3135 if (bary_2comp(ds, i)) {
3136 big_extend_carry(x);
3147abs2twocomp(
VALUE *xp,
long *n_ret)
3150 long n = BIGNUM_LEN(x);
3151 BDIGIT *ds = BDIGITS(x);
3156 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3158 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3159 bary_2comp(BDIGITS(z), n);
3168twocomp2abs_bang(
VALUE x,
int hibits)
3170 BIGNUM_SET_SIGN(x, !hibits);
3179 size_t len = BIGNUM_LEN(x);
3180 BDIGIT *ds = BDIGITS(x);
3182 if (
len == 0)
return x;
3183 while (--
len && !ds[
len]);
3184 if (BIGNUM_LEN(x) >
len+1) {
3185 rb_big_resize(x,
len+1);
3193 size_t n = BIGNUM_LEN(x);
3194 BDIGIT *ds = BDIGITS(x);
3195#if SIZEOF_BDIGIT < SIZEOF_LONG
3203 if (n == 0)
return INT2FIX(0);
3205#if SIZEOF_BDIGIT < SIZEOF_LONG
3206 if (
sizeof(
long)/SIZEOF_BDIGIT < n)
3212 u = (
unsigned long)(BIGUP(u) + ds[i]);
3222 if (BIGNUM_POSITIVE_P(x)) {
3230 rb_big_resize(x, n);
3237 if (RB_BIGNUM_TYPE_P(x)) {
3250rb_uint2big(uintptr_t n)
3254 BDIGIT *digits = BDIGITS(big);
3256#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3260 digits[i] = BIGLO(n);
3266 while (--i && !digits[i]) ;
3267 BIGNUM_SET_LEN(big, i+1);
3272rb_int2big(intptr_t n)
3279 u = 1 + (
VALUE)(-(n + 1));
3285 big = rb_uint2big(u);
3287 BIGNUM_SET_NEGATIVE_SIGN(big);
3293rb_uint2inum(uintptr_t n)
3296 return rb_uint2big(n);
3300rb_int2inum(intptr_t n)
3303 return rb_int2big(n);
3307rb_big_pack(
VALUE val,
unsigned long *buf,
long num_longs)
3309 rb_integer_pack(val, buf, num_longs,
sizeof(
long), 0,
3315rb_big_unpack(
unsigned long *buf,
long num_longs)
3317 return rb_integer_unpack(buf, num_longs,
sizeof(
long), 0,
3339rb_absint_size(
VALUE val,
int *nlz_bits_ret)
3343 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3345 int num_leading_zeros;
3354#if SIZEOF_BDIGIT >= SIZEOF_LONG
3359 for (i = 0; i < numberof(fixbuf); i++) {
3360 fixbuf[i] = BIGLO(v);
3366 de = fixbuf + numberof(fixbuf);
3370 de = dp + BIGNUM_LEN(val);
3372 while (dp < de && de[-1] == 0)
3379 num_leading_zeros = nlz(de[-1]);
3381 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3382 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3386absint_numwords_small(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3388 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3389 size_t div = val_numbits / word_numbits;
3390 size_t mod = val_numbits % word_numbits;
3393 numwords = mod == 0 ? div : div + 1;
3394 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3395 *nlz_bits_ret = nlz_bits;
3400absint_numwords_generic(
size_t numbytes,
int nlz_bits_in_msbyte,
size_t word_numbits,
size_t *nlz_bits_ret)
3402 static const BDIGIT char_bit[1] = { CHAR_BIT };
3403 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(numbytes))];
3404 BDIGIT val_numbits_bary[bdigit_roomof(
sizeof(numbytes) + 1)];
3405 BDIGIT nlz_bits_in_msbyte_bary[1];
3406 BDIGIT word_numbits_bary[bdigit_roomof(
sizeof(word_numbits))];
3407 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3408 BDIGIT mod_bary[numberof(word_numbits_bary)];
3409 BDIGIT one[1] = { 1 };
3415 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3424 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
3426 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3427 if (nlz_bits_in_msbyte)
3428 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3429 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1,
sizeof(word_numbits), 0,
3431 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3432 if (BARY_ZERO_P(mod_bary)) {
3436 BARY_ADD(div_bary, div_bary, one);
3437 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1,
sizeof(mod), 0,
3439 nlz_bits = word_numbits - mod;
3441 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1,
sizeof(numwords), 0,
3447 *nlz_bits_ret = nlz_bits;
3471rb_absint_numwords(
VALUE val,
size_t word_numbits,
size_t *nlz_bits_ret)
3474 int nlz_bits_in_msbyte;
3476 size_t nlz_bits = 0;
3478 if (word_numbits == 0)
3481 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3483 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3484 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3485 if (debug_integer_pack) {
3486 size_t numwords0, nlz_bits0;
3487 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3494 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3496 if (numwords == (
size_t)-1)
3500 *nlz_bits_ret = nlz_bits;
3538 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3548#if SIZEOF_BDIGIT >= SIZEOF_LONG
3553 for (i = 0; i < numberof(fixbuf); i++) {
3554 fixbuf[i] = BIGLO(v);
3560 de = fixbuf + numberof(fixbuf);
3564 de = dp + BIGNUM_LEN(val);
3566 while (dp < de && de[-1] == 0)
3568 while (dp < de && dp[0] == 0)
3635rb_integer_pack(
VALUE val,
void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3640 BDIGIT fixbuf[bdigit_roomof(
sizeof(
long))];
3653#if SIZEOF_BDIGIT >= SIZEOF_LONG
3658 for (i = 0; i < numberof(fixbuf); i++) {
3659 fixbuf[i] = BIGLO(v);
3665 num_bdigits = numberof(fixbuf);
3668 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3670 num_bdigits = BIGNUM_LEN(val);
3673 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3721rb_integer_unpack(
const void *words,
size_t numwords,
size_t wordsize,
size_t nails,
int flags)
3728 BDIGIT fixbuf[2] = { 0, 0 };
3730 validate_integer_pack_format(numwords, wordsize, nails, flags,
3741 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3743 if (LONG_MAX-1 < num_bdigits)
3744 rb_raise(rb_eArgError,
"too big to unpack as an integer");
3750 val = bignew((
long)num_bdigits, 0);
3753 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3757 big_extend_carry(val);
3759 else if (num_bdigits == numberof(fixbuf)) {
3760 val = bignew((
long)num_bdigits+1, 0);
3761 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3762 BDIGITS(val)[num_bdigits++] = 1;
3765 ds[num_bdigits++] = 1;
3770 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3775 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3777 return LONG2FIX((
long)-(BDIGIT_DBL_SIGNED)u);
3778 val = bignew((
long)num_bdigits, 0 <= sign);
3779 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3783 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3785 BIGNUM_SET_SIGN(val, 0 <= sign);
3788 return bigtrunc(val);
3789 return bignorm(val);
3792#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3794NORETURN(
static inline void invalid_radix(
int base));
3795NORETURN(
static inline void invalid_integer(
VALUE s));
3798valid_radix_p(
int base)
3800 return (1 < base && base <= 36);
3804invalid_radix(
int base)
3806 rb_raise(rb_eArgError,
"invalid radix %d", base);
3810invalid_integer(
VALUE s)
3812 rb_raise(rb_eArgError,
"invalid value for Integer(): %+"PRIsVALUE, s);
3816str2big_scan_digits(
const char *s,
const char *str,
int base,
int badcheck,
size_t *num_digits_p, ssize_t *len_p)
3819 size_t num_digits = 0;
3820 const char *digits_start = str;
3821 const char *digits_end = str;
3822 ssize_t
len = *len_p;
3832 if (badcheck && *str ==
'_')
return FALSE;
3834 while ((c = *str++) != 0) {
3837 if (badcheck)
return FALSE;
3840 nondigit = (char) c;
3842 else if ((c = conv_digit(c)) < 0 || c >= base) {
3850 if (
len > 0 && !--
len)
break;
3852 if (badcheck && nondigit)
return FALSE;
3853 if (badcheck &&
len) {
3855 while (*str &&
ISSPACE(*str)) {
3857 if (
len > 0 && !--
len)
break;
3863 *num_digits_p = num_digits;
3864 *len_p = digits_end - digits_start;
3871 const char *digits_start,
3872 const char *digits_end,
3885 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3886 z = bignew(num_bdigits, sign);
3890 for (p = digits_end; digits_start < p; p--) {
3891 if ((c = conv_digit(p[-1])) < 0)
3893 dd |= (BDIGIT_DBL)c << numbits;
3894 numbits += bits_per_digit;
3895 if (BITSPERDIG <= numbits) {
3898 numbits -= BITSPERDIG;
3904 RUBY_ASSERT((
size_t)(dp - BDIGITS(z)) == num_bdigits);
3912 const char *digits_start,
3913 const char *digits_end,
3926 z = bignew(num_bdigits, sign);
3928 BDIGITS_ZERO(zds, num_bdigits);
3930 for (p = digits_start; p < digits_end; p++) {
3931 if ((c = conv_digit(*p)) < 0)
3937 num += (BDIGIT_DBL)zds[i]*base;
3938 zds[i++] = BIGLO(num);
3956 const char *digits_start,
3957 const char *digits_end,
3960 int digits_per_bdigits_dbl,
3966 BDIGIT *uds, *vds, *tds;
3968 BDIGIT_DBL current_base;
3970 int power_level = 0;
3977 uds =
ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3978 vds = uds + num_bdigits;
3980 powerv = power_cache_get_power(base, power_level, NULL);
3985 m = digits_per_bdigits_dbl;
3986 if (num_digits < (
size_t)m)
3987 m = (int)num_digits;
3988 for (p = digits_end; digits_start < p; p--) {
3989 if ((c = conv_digit(p[-1])) < 0)
3991 dd = dd + c * current_base;
3992 current_base *= base;
3996 uds[i++] = BIGLO(dd);
3997 uds[i++] = (BDIGIT)BIGDN(dd);
3999 m = digits_per_bdigits_dbl;
4000 if (num_digits < (
size_t)m)
4001 m = (
int)num_digits;
4006 for (unit = 2; unit < num_bdigits; unit *= 2) {
4007 for (i = 0; i < num_bdigits; i += unit*2) {
4008 if (2*unit <= num_bdigits - i) {
4009 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
4010 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
4012 else if (unit <= num_bdigits - i) {
4013 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
4014 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
4017 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
4021 powerv = power_cache_get_power(base, power_level, NULL);
4026 BARY_TRUNC(uds, num_bdigits);
4027 z = bignew(num_bdigits, sign);
4028 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
4040 const char *digits_start,
4041 const char *digits_end,
4054 buf =
ALLOCV_N(
char, tmps, num_digits+1);
4056 for (q = digits_start; q < digits_end; q++) {
4057 if (conv_digit(*q) < 0)
4064 mpz_set_str(mz, buf, base);
4066 z = bignew(zn, sign);
4068 bdigits_from_mpz(mz, BDIGITS(z), &count);
4069 BDIGITS_ZERO(zds+count, zn-count);
4079static VALUE rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base);
4098rb_cstr_to_inum(
const char *str,
int base,
int badcheck)
4101 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4127rb_int_parse_cstr(
const char *str, ssize_t
len,
char **endp,
size_t *ndigits,
4128 int base,
int flags)
4130 const char *
const s = str;
4138 const char *digits_start, *digits_end;
4139 size_t num_digits = 0;
4141 const ssize_t len0 =
len;
4142 const int badcheck = !endp;
4145 if (len > 0 && len <= (n)) goto bad; \
4149#define ASSERT_LEN() do {\
4150 RUBY_ASSERT(len != 0); \
4151 if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
4160 if (str[0] ==
'+') {
4163 else if (str[0] ==
'-') {
4170 if (str[0] ==
'0' &&
len > 1) {
4192 else if (base < -1) {
4202 else if (base == 2) {
4203 if (str[0] ==
'0' && (str[1] ==
'b'||str[1] ==
'B')) {
4207 else if (base == 8) {
4208 if (str[0] ==
'0' && (str[1] ==
'o'||str[1] ==
'O')) {
4212 else if (base == 10) {
4213 if (str[0] ==
'0' && (str[1] ==
'd'||str[1] ==
'D')) {
4217 else if (base == 16) {
4218 if (str[0] ==
'0' && (str[1] ==
'x'||str[1] ==
'X')) {
4222 if (!valid_radix_p(base)) {
4223 invalid_radix(base);
4226 num_digits = str - s;
4227 if (*str ==
'0' &&
len != 1) {
4229 const char *end =
len < 0 ? NULL : str +
len;
4231 while ((c = *++str) ==
'0' ||
4241 if (str == end)
break;
4244 if (end)
len = end - str;
4248 if (c < 0 || c >= base) {
4249 if (!badcheck && num_digits) z =
INT2FIX(0);
4253 if (ndigits) *ndigits = num_digits;
4254 val = ruby_scan_digits(str,
len, base, &num_digits, &ov);
4256 const char *end = &str[num_digits];
4259 if (endp) *endp = (
char *)end;
4260 if (ndigits) *ndigits += num_digits;
4262 if (num_digits == 0)
return Qnil;
4263 while (
len < 0 ? *end : end < str +
len) {
4272 long result = -(long)val;
4277 VALUE big = rb_uint2big(val);
4278 BIGNUM_SET_SIGN(big, sign);
4279 return bignorm(big);
4285 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4287 if (endp) *endp = (
char *)(str +
len);
4288 if (ndigits) *ndigits += num_digits;
4289 digits_end = digits_start +
len;
4292 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4293 bit_length(base-1));
4296 int digits_per_bdigits_dbl;
4297 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4298 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4301 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4302 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4307 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4308 z = str2big_normal(sign, digits_start, digits_end,
4312 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4313 num_bdigits, digits_per_bdigits_dbl, base);
4320 if (endp) *endp = (
char *)str;
4321 if (ndigits) *ndigits = num_digits;
4326rb_cstr_parse_inum(
const char *str, ssize_t
len,
char **endp,
int base)
4328 return rb_int_parse_cstr(str,
len, endp, NULL, base,
4333rb_str_convert_to_inum(
VALUE str,
int base,
int badcheck,
int raise_exception)
4343 ret = rb_cstr_parse_inum(s,
len, (badcheck ? NULL : &end), base);
4346 if (!raise_exception)
return Qnil;
4347 invalid_integer(str);
4355rb_str_to_inum(
VALUE str,
int base,
int badcheck)
4357 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4361rb_str2big_poweroftwo(
VALUE arg,
int base,
int badcheck)
4364 const char *s, *str;
4365 const char *digits_start, *digits_end;
4370 if (!valid_radix_p(base) || !POW2_P(base)) {
4371 invalid_radix(base);
4376 len = RSTRING_LEN(arg);
4384 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4385 invalid_integer(arg);
4386 digits_end = digits_start +
len;
4388 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4389 bit_length(base-1));
4397rb_str2big_normal(
VALUE arg,
int base,
int badcheck)
4400 const char *s, *str;
4401 const char *digits_start, *digits_end;
4406 int digits_per_bdigits_dbl;
4409 if (!valid_radix_p(base)) {
4410 invalid_radix(base);
4415 len = RSTRING_LEN(arg);
4416 if (
len > 0 && *str ==
'-') {
4423 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4424 invalid_integer(arg);
4425 digits_end = digits_start +
len;
4427 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4428 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4430 z = str2big_normal(positive_p, digits_start, digits_end,
4439rb_str2big_karatsuba(
VALUE arg,
int base,
int badcheck)
4442 const char *s, *str;
4443 const char *digits_start, *digits_end;
4448 int digits_per_bdigits_dbl;
4451 if (!valid_radix_p(base)) {
4452 invalid_radix(base);
4457 len = RSTRING_LEN(arg);
4458 if (
len > 0 && *str ==
'-') {
4465 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4466 invalid_integer(arg);
4467 digits_end = digits_start +
len;
4469 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4470 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4472 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4473 num_bdigits, digits_per_bdigits_dbl, base);
4482rb_str2big_gmp(
VALUE arg,
int base,
int badcheck)
4485 const char *s, *str;
4486 const char *digits_start, *digits_end;
4491 int digits_per_bdigits_dbl;
4494 if (!valid_radix_p(base)) {
4495 invalid_radix(base);
4500 len = RSTRING_LEN(arg);
4501 if (
len > 0 && *str ==
'-') {
4508 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &
len))
4509 invalid_integer(arg);
4510 digits_end = digits_start +
len;
4512 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4513 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4515 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4529 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4530 BDIGIT *digits = BDIGITS(big);
4532#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4535 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4536 digits[i] = BIGLO(n);
4541 i = bdigit_roomof(SIZEOF_LONG_LONG);
4542 while (i-- && !digits[i]) ;
4543 BIGNUM_SET_LEN(big, i+1);
4561 big = rb_ull2big(u);
4563 BIGNUM_SET_NEGATIVE_SIGN(big);
4572 return rb_ull2big(n);
4579 return rb_ll2big(n);
4586rb_uint128t2big(uint128_t n)
4589 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4590 BDIGIT *digits = BDIGITS(big);
4592 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4593 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4596 i = bdigit_roomof(SIZEOF_INT128_T);
4597 while (i-- && !digits[i]) ;
4598 BIGNUM_SET_LEN(big, i+1);
4603rb_int128t2big(int128_t n)
4610 u = 1 + (uint128_t)(-(n + 1));
4616 big = rb_uint128t2big(u);
4618 BIGNUM_SET_NEGATIVE_SIGN(big);
4625rb_cstr2inum(
const char *str,
int base)
4627 return rb_cstr_to_inum(str, base, base==0);
4633 return rb_str_to_inum(str, base, base==0);
4637big_shift3(
VALUE x,
int lshift_p,
size_t shift_numdigits,
int shift_numbits)
4646 if (LONG_MAX < shift_numdigits) {
4650 s1 = shift_numdigits;
4652 if ((
size_t)s1 != shift_numdigits)
goto too_big;
4654 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1)
goto too_big;
4655 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4657 BDIGITS_ZERO(zds, s1);
4659 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4664 if (LONG_MAX < shift_numdigits || (
size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4665 if (BIGNUM_POSITIVE_P(x) ||
4666 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4671 s1 = shift_numdigits;
4673 hibitsx = abs2twocomp(&x, &xn);
4681 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4682 twocomp2abs_bang(z, hibitsx != 0);
4693 size_t shift_numdigits;
4701 sign = rb_integer_pack(y, lens, numberof(lens),
sizeof(
size_t), 0,
4704 lshift_p = !lshift_p;
4708 if (1 < sign || CHAR_BIT <= lens[1])
4712 if (1 < sign || CHAR_BIT <= lens[1])
4715 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4716 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4717 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4718 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4722big_lshift(
VALUE x,
unsigned long shift)
4724 long s1 = shift/BITSPERDIG;
4725 int s2 = (int)(shift%BITSPERDIG);
4726 return big_shift3(x, 1, s1, s2);
4730big_rshift(
VALUE x,
unsigned long shift)
4732 long s1 = shift/BITSPERDIG;
4733 int s2 = (int)(shift%BITSPERDIG);
4734 return big_shift3(x, 0, s1, s2);
4737#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4739static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4740static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4743power_cache_init(
void)
4748power_cache_get_power(
int base,
int power_level,
size_t *numdigits_ret)
4764 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4765 rb_bug(
"too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4767 VALUE power = rbimpl_atomic_value_load(&base36_power_cache[base - 2][power_level], RBIMPL_ATOMIC_ACQUIRE);
4770 if (power_level == 0) {
4772 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4773 power = bignew(2, 1);
4774 bdigitdbl2bary(BDIGITS(power), 2, dd);
4775 numdigits = numdigits0;
4778 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4782 base36_numdigits_cache[base - 2][power_level] = numdigits;
4784 VALUE old = rbimpl_atomic_value_cas(&base36_power_cache[base - 2][power_level], 0, power,
4785 RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_ACQUIRE);
4790 rb_vm_register_global_object(power);
4794 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4802 int hbase2_numdigits;
4810 if (LONG_MAX-1 <
len)
4811 rb_raise(rb_eArgError,
"too big number");
4813 b2s->ptr = RSTRING_PTR(b2s->result);
4819big2str_2bdigits(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t taillen)
4823 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4824 int beginning = !b2s->ptr;
4828 num = bary2bdigitdbl(xds, xn);
4835 if (b2s->base == 10) {
4838 while (num >= 100) {
4839 BDIGIT_DBL idx = (num % 100) * 2;
4842 p[j] = ruby_decimal_digit_pairs[idx];
4843 p[j + 1] = ruby_decimal_digit_pairs[idx + 1];
4846 BDIGIT_DBL idx = num * 2;
4848 p[j] = ruby_decimal_digit_pairs[idx];
4849 p[j + 1] = ruby_decimal_digit_pairs[idx + 1];
4853 p[--j] = (char)(
'0' + num);
4858 BDIGIT_DBL idx = num % b2s->base;
4860 p[--j] = ruby_digitmap[idx];
4863 len =
sizeof(buf) - j;
4864 big2str_alloc(b2s,
len + taillen);
4869 j = b2s->hbase2_numdigits;
4870 if (b2s->base == 10) {
4875 while (num >= 100) {
4876 BDIGIT_DBL idx = (num % 100) * 2;
4879 p[j] = ruby_decimal_digit_pairs[idx];
4880 p[j + 1] = ruby_decimal_digit_pairs[idx + 1];
4883 BDIGIT_DBL idx = num * 2;
4885 p[j] = ruby_decimal_digit_pairs[idx];
4886 p[j + 1] = ruby_decimal_digit_pairs[idx + 1];
4889 p[--j] = (char)(
'0' + num);
4898 BDIGIT_DBL idx = num % b2s->base;
4900 p[--j] = ruby_digitmap[idx];
4903 len = b2s->hbase2_numdigits;
4909big2str_karatsuba(
struct big2str_struct *b2s, BDIGIT *xds,
size_t xn,
size_t wn,
4910 int power_level,
size_t taillen)
4913 size_t half_numdigits, lower_numdigits;
4914 int lower_power_level;
4939 if (xn == 0 || bary_zero_p(xds, xn)) {
4942 power_cache_get_power(b2s->base, power_level, &
len);
4943 memset(b2s->ptr,
'0',
len);
4949 if (power_level == 0) {
4950 big2str_2bdigits(b2s, xds, xn, taillen);
4954 lower_power_level = power_level-1;
4955 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4959 half_numdigits = lower_numdigits;
4961 while (0 < lower_power_level &&
4963 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4964 lower_power_level--;
4965 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4970 if (lower_power_level == 0 &&
4972 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4974 len = half_numdigits * 2 - lower_numdigits;
4975 memset(b2s->ptr,
'0',
len);
4978 big2str_2bdigits(b2s, xds, xn, taillen);
4986 if (lower_power_level != power_level-1 && b2s->ptr) {
4987 len = (half_numdigits - lower_numdigits) * 2;
4988 memset(b2s->ptr,
'0',
len);
4992 shift = nlz(bds[bn-1]);
4994 qn = xn + BIGDIVREM_EXTRA_WORDS;
4999 tds = (BDIGIT *)bds;
5007 bary_small_lshift(tds, bds, bn, shift);
5008 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
5011 bigdivrem_restoring(xds, qn, tds, bn);
5020 bary_small_rshift(rds, rds, rn, shift, 0);
5023 BARY_TRUNC(qds, qn);
5025 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
5026 BARY_TRUNC(rds, rn);
5027 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
5032big2str_base_poweroftwo(
VALUE x,
int base)
5034 int word_numbits = ffs(base) - 1;
5038 numwords = rb_absint_numwords(x, word_numbits, NULL);
5039 if (BIGNUM_NEGATIVE_P(x)) {
5040 if (LONG_MAX-1 < numwords)
5041 rb_raise(rb_eArgError,
"too big number");
5043 ptr = RSTRING_PTR(result);
5044 *ptr++ = BIGNUM_POSITIVE_P(x) ?
'+' :
'-';
5047 if (LONG_MAX < numwords)
5048 rb_raise(rb_eArgError,
"too big number");
5050 ptr = RSTRING_PTR(result);
5052 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
5054 while (0 < numwords) {
5055 *ptr = ruby_digitmap[*(
unsigned char *)ptr];
5063rb_big2str_poweroftwo(
VALUE x,
int base)
5065 return big2str_base_poweroftwo(x, base);
5069big2str_generic(
VALUE x,
int base)
5079 BARY_TRUNC(xds, xn);
5085 if (!valid_radix_p(base))
5086 invalid_radix(base);
5088 if (xn >= LONG_MAX/BITSPERDIG) {
5089 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5093 power = power_cache_get_power(base, power_level, NULL);
5094 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
5095 (
size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
5097 power = power_cache_get_power(base, power_level, NULL);
5099 RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
5101 if ((
size_t)BIGNUM_LEN(power) <= xn) {
5115 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5116 b2s_data.base = base;
5117 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5119 b2s_data.result =
Qnil;
5120 b2s_data.ptr = NULL;
5122 if (power_level == 0) {
5123 big2str_2bdigits(&b2s_data, xds, xn, 0);
5129 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5130 wds =
ALLOCV_N(BDIGIT, tmpw, xn + wn);
5131 MEMCPY(wds, xds, BDIGIT, xn);
5132 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5138 *b2s_data.ptr =
'\0';
5139 rb_str_resize(b2s_data.result, (
long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5142 return b2s_data.result;
5146rb_big2str_generic(
VALUE x,
int base)
5148 return big2str_generic(x, base);
5153big2str_gmp(
VALUE x,
int base)
5158 BDIGIT *xds = BDIGITS(x);
5159 size_t xn = BIGNUM_LEN(x);
5162 bdigits_to_mpz(mx, xds, xn);
5164 size = mpz_sizeinbase(mx, base);
5166 if (BIGNUM_NEGATIVE_P(x)) {
5173 mpz_get_str(RSTRING_PTR(str), base, mx);
5176 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] ==
'\0') {
5185rb_big2str_gmp(
VALUE x,
int base)
5187 return big2str_gmp(x, base);
5192rb_big2str1(
VALUE x,
int base)
5204 BARY_TRUNC(xds, xn);
5210 if (!valid_radix_p(base))
5211 invalid_radix(base);
5213 if (xn >= LONG_MAX/BITSPERDIG) {
5214 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'string'");
5219 return big2str_base_poweroftwo(x, base);
5223 if (GMP_BIG2STR_DIGITS < xn) {
5224 return big2str_gmp(x, base);
5228 return big2str_generic(x, base);
5234 return rb_big2str1(x, base);
5240#if SIZEOF_LONG > SIZEOF_BDIGIT
5243 size_t len = BIGNUM_LEN(x);
5249 if (BIGSIZE(x) >
sizeof(
long)) {
5253#if SIZEOF_LONG <= SIZEOF_BDIGIT
5254 num = (
unsigned long)ds[0];
5257 for (i = 0; i <
len; i++) {
5259 num += (
unsigned long)ds[
len - i - 1];
5268 unsigned long num = big2ulong(x,
"unsigned long");
5270 if (BIGNUM_POSITIVE_P(x)) {
5274 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5275 return -(long)(num-1)-1;
5277 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long");
5283 unsigned long num = big2ulong(x,
"long");
5285 if (BIGNUM_POSITIVE_P(x)) {
5286 if (num <= LONG_MAX)
5290 if (num <= 1+(
unsigned long)(-(LONG_MIN+1)))
5291 return -(long)(num-1)-1;
5293 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long'");
5301#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5304 size_t len = BIGNUM_LEN(x);
5306 BDIGIT *ds = BDIGITS(x);
5310 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5312#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5316 for (i = 0; i <
len; i++) {
5318 num += ds[
len - i - 1];
5327 unsigned LONG_LONG num = big2ull(x,
"unsigned long long");
5329 if (BIGNUM_POSITIVE_P(x)) {
5333 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5336 rb_raise(
rb_eRangeError,
"bignum out of range of unsigned long long");
5342 unsigned LONG_LONG num = big2ull(x,
"long long");
5344 if (BIGNUM_POSITIVE_P(x)) {
5345 if (num <= LLONG_MAX)
5349 if (num <= 1+(
unsigned LONG_LONG)(-(LLONG_MIN+1)))
5352 rb_raise(
rb_eRangeError,
"bignum too big to convert into 'long long'");
5364 double u = (d < 0)?-d:d;
5374 u /= (double)(BIGRAD);
5377 z = bignew(i, d>=0);
5378 digits = BDIGITS(z);
5392 return bignorm(dbl2big(d));
5399 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5400 BDIGIT *ds = BDIGITS(x), dl;
5403 bits = i * BITSPERDIG - nlz(ds[i-1]);
5404 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5408 if (bits > DBL_MANT_DIG+1)
5409 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5413 d = ds[i] + BIGRAD*d;
5416 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5417 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5425 BDIGIT mask = BDIGMAX;
5437 if (lo > INT_MAX / BITSPERDIG)
5439 else if (lo < INT_MIN / BITSPERDIG)
5442 d = ldexp(d, (
int)(lo * BITSPERDIG));
5446 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5453 double d = big2dbl(x);
5475 if (yd > 0.0)
return INT2FIX(-1);
5480#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5507 rel = rb_big_cmp(x, y);
5508 if (yf == 0.0 || rel !=
INT2FIX(0))
5515#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG
5516COMPILER_WARNING_PUSH
5517#if __has_warning("-Wimplicit-int-float-conversion")
5518COMPILER_WARNING_IGNORED(-Wimplicit-
int-
float-conversion)
5520static const double LONG_MAX_as_double = LONG_MAX;
5536#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG
5538 return RBOOL(xd == yd);
5541 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5545 return RBOOL(xn == yn);
5549 return rb_big_eq(x, y);
5562 if (sx < sy)
return INT2FIX(-1);
5566 else if (RB_BIGNUM_TYPE_P(y)) {
5567 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5568 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5569 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5573 return rb_integer_float_cmp(x, y);
5578 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5595 rel = rb_big_cmp(x, y);
5598 rel = rb_integer_float_cmp(x, y);
5603 case big_op_gt:
id =
'>';
break;
5604 case big_op_ge:
id = idGE;
break;
5605 case big_op_lt:
id =
'<';
break;
5606 case big_op_le:
id = idLE;
break;
5615 case big_op_gt:
return RBOOL(n > 0);
5616 case big_op_ge:
return RBOOL(n >= 0);
5617 case big_op_lt:
return RBOOL(n < 0);
5618 case big_op_le:
return RBOOL(n <= 0);
5626 return big_op(x, y, big_op_gt);
5632 return big_op(x, y, big_op_ge);
5638 return big_op(x, y, big_op_lt);
5644 return big_op(x, y, big_op_le);
5662 return RBOOL(bignorm(x) == y);
5664 else if (RB_BIGNUM_TYPE_P(y)) {
5667 return rb_integer_float_eq(x, y);
5672 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5673 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5674 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5680 if (!RB_BIGNUM_TYPE_P(y))
return Qfalse;
5681 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y))
return Qfalse;
5682 if (BIGNUM_LEN(x) != BIGNUM_LEN(y))
return Qfalse;
5683 return RBOOL(
MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5687rb_big_uminus(
VALUE x)
5689 VALUE z = rb_big_clone(x);
5699 VALUE z = rb_big_clone(x);
5700 BDIGIT *ds = BDIGITS(z);
5701 long n = BIGNUM_LEN(z);
5705 if (BIGNUM_POSITIVE_P(z)) {
5706 if (bary_add_one(ds, n)) {
5707 big_extend_carry(z);
5709 BIGNUM_SET_NEGATIVE_SIGN(z);
5713 if (bary_add_one(ds, n))
5716 BIGNUM_SET_POSITIVE_SIGN(z);
5726 BDIGIT *xds, *yds, *zds;
5731 zn = xn < yn ? yn : xn;
5739 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5740 bary_2comp(zds, zn);
5741 BIGNUM_SET_NEGATIVE_SIGN(z);
5750bigsub_int(
VALUE x,
long y0)
5755 BDIGIT_DBL_SIGNED num;
5766#if SIZEOF_BDIGIT < SIZEOF_LONG
5767 if (zn < bdigit_roomof(SIZEOF_LONG))
5768 zn = bdigit_roomof(SIZEOF_LONG);
5770 z = bignew(zn, BIGNUM_SIGN(x));
5773#if SIZEOF_BDIGIT >= SIZEOF_LONG
5775 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5776 if (xn == 1 && num < 0) {
5778 zds[0] = (BDIGIT)-num;
5782 zds[0] = BIGLO(num);
5790 for (i=0; i < xn; i++) {
5791 if (y == 0)
goto y_is_zero_x;
5792 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5793 zds[i] = BIGLO(num);
5797 for (; i < zn; i++) {
5798 if (y == 0)
goto y_is_zero_z;
5800 zds[i] = BIGLO(num);
5807 for (; i < xn; i++) {
5809 if (num == 0)
goto num_is_zero_x;
5811 zds[i] = BIGLO(num);
5814#if SIZEOF_BDIGIT < SIZEOF_LONG
5815 for (; i < zn; i++) {
5817 if (num == 0)
goto num_is_zero_z;
5818 zds[i] = BIGLO(num);
5824 for (; i < xn; i++) {
5828#if SIZEOF_BDIGIT < SIZEOF_LONG
5829 for (; i < zn; i++) {
5847bigadd_int(
VALUE x,
long y)
5862#if SIZEOF_BDIGIT < SIZEOF_LONG
5863 if (zn < bdigit_roomof(SIZEOF_LONG))
5864 zn = bdigit_roomof(SIZEOF_LONG);
5868 z = bignew(zn, BIGNUM_SIGN(x));
5871#if SIZEOF_BDIGIT >= SIZEOF_LONG
5872 num = (BDIGIT_DBL)xds[0] + y;
5873 zds[0] = BIGLO(num);
5881 for (i=0; i < xn; i++) {
5882 if (y == 0)
goto y_is_zero_x;
5883 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5884 zds[i] = BIGLO(num);
5888 for (; i < zn; i++) {
5889 if (y == 0)
goto y_is_zero_z;
5891 zds[i] = BIGLO(num);
5899 for (;i < xn; i++) {
5901 if (num == 0)
goto num_is_zero_x;
5902 num += (BDIGIT_DBL)xds[i];
5903 zds[i] = BIGLO(num);
5906 for (; i < zn; i++) {
5908 if (num == 0)
goto num_is_zero_z;
5909 zds[i] = BIGLO(num);
5914 for (;i < xn; i++) {
5918 for (; i < zn; i++) {
5935 sign = (sign == BIGNUM_SIGN(y));
5936 if (BIGNUM_SIGN(x) != sign) {
5937 if (sign)
return bigsub(y, x);
5938 return bigsub(x, y);
5941 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5942 len = BIGNUM_LEN(x) + 1;
5945 len = BIGNUM_LEN(y) + 1;
5947 z = bignew(
len, sign);
5949 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5950 BDIGITS(x), BIGNUM_LEN(x),
5951 BDIGITS(y), BIGNUM_LEN(y));
5963 if ((n > 0) != BIGNUM_SIGN(x)) {
5967 return bigsub_int(x, n);
5972 return bigadd_int(x, n);
5974 else if (RB_BIGNUM_TYPE_P(y)) {
5975 return bignorm(bigadd(x, y, 1));
5992 if ((n > 0) != BIGNUM_SIGN(x)) {
5996 return bigadd_int(x, n);
6001 return bigsub_int(x, n);
6003 else if (RB_BIGNUM_TYPE_P(y)) {
6004 return bignorm(bigadd(x, y, 0));
6022 if (MUL_OVERFLOW_LONG_P(2, xn))
6023 rb_raise(rb_eArgError,
"square overflow");
6031 if (xn < NAIVE_MUL_DIGITS)
6032 bary_sq_fast(zds, zn, xds, xn);
6034 bary_mul(zds, zn, xds, xn, xds, xn);
6045 BDIGIT *xds, *yds, *zds;
6052 if (ADD_OVERFLOW_LONG_P(xn, yn))
6053 rb_raise(rb_eArgError,
"multiplication overflow");
6056 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6062 bary_mul(zds, zn, xds, xn, yds, yn);
6075 else if (RB_BIGNUM_TYPE_P(y)) {
6084 return bignorm(bigmul0(x, y));
6090 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
6092 BDIGIT *xds, *yds, *zds;
6100 BARY_TRUNC(yds, yn);
6105 BARY_TRUNC(xds, xn);
6107 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
6108 if (divp) *divp = rb_int2big(0);
6109 if (modp) *modp = x;
6114 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6116 dd = bigdivrem_single(zds, xds, xn, dd);
6118 *modp = rb_uint2big((uintptr_t)dd);
6119 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6121 if (divp) *divp = z;
6124 if (xn == 2 && yn == 2) {
6125 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6126 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6127 BDIGIT_DBL q0 = x0 / y0;
6128 BDIGIT_DBL r0 = x0 % y0;
6130 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6133 zds[1] = BIGLO(BIGDN(q0));
6137 z = bignew(bdigit_roomof(
sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6140 zds[1] = BIGLO(BIGDN(r0));
6147 qn = xn + BIGDIVREM_EXTRA_WORDS;
6148 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6158 r = bignew(rn, BIGNUM_SIGN(x));
6166 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6185 bigdivrem(x, y, divp, &mod);
6186 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6187 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6188 if (modp) *modp = bigadd(mod, y, 1);
6204 else if (RB_BIGNUM_TYPE_P(y)) {
6208 double dx = rb_big2dbl(x);
6209 return rb_flo_div_flo(
DBL2NUM(dx), y);
6215 v = rb_big_divide(x, y,
'/');
6222 bigdivmod(x, y, &z, 0);
6230 return rb_big_divide(x, y,
'/');
6236 return rb_big_divide(x, y, idDiv);
6247 else if (!RB_BIGNUM_TYPE_P(y)) {
6250 bigdivmod(x, y, 0, &z);
6263 else if (!RB_BIGNUM_TYPE_P(y)) {
6266 bigdivrem(x, y, 0, &z);
6279 else if (!RB_BIGNUM_TYPE_P(y)) {
6282 bigdivmod(x, y, &div, &mod);
6288big_shift(
VALUE x,
long n)
6291 return big_lshift(x, 1+(
unsigned long)(-(n+1)));
6293 return big_rshift(x, (
unsigned long)n);
6297enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6307 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6308 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6309 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6310 else if (ex > 0) ex = 0;
6311 if (ex) x = big_shift(x, ex);
6313 bigdivrem(x, y, &z, 0);
6315#if SIZEOF_LONG > SIZEOF_INT
6318 if (l > INT_MAX)
return HUGE_VAL;
6319 if (l < INT_MIN)
return 0.0;
6322 return ldexp(big2dbl(z), (
int)l);
6331 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6332 ey -= DBL_BIGDIG * BITSPERDIG;
6333 if (ey) y = big_shift(y, ey);
6334 return big_fdiv(x, y, ey);
6341 y = dbl2big(ldexp(frexp(
RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6342 return big_fdiv(x, y, i - DBL_MANT_DIG);
6355 return big_fdiv_int(x, rb_int2big(
FIX2LONG(y)));
6357 else if (RB_BIGNUM_TYPE_P(y)) {
6358 return big_fdiv_int(x, y);
6365 return big_fdiv_float(x, y);
6383 if (y ==
INT2FIX(1))
return x;
6386 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6387 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6390 else if (RB_BIGNUM_TYPE_P(y)) {
6394 rb_raise(rb_eArgError,
"exponent is too large");
6409 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6410#if SIZEOF_SIZE_T == 4
6411 const size_t BIGLEN_LIMIT = 1ULL << 31;
6413 const size_t BIGLEN_LIMIT = 1ULL << 34;
6416 if (xbits == (
size_t)-1 ||
6417 (xbits > BIGLEN_LIMIT) ||
6418 MUL_OVERFLOW_LONG_P(yy, xbits) ||
6419 (xbits * yy > BIGLEN_LIMIT)) {
6420 rb_raise(rb_eArgError,
"exponent is too large");
6423 for (mask =
FIXNUM_MAX + 1; mask; mask >>= 1) {
6424 if (z) z = bigsq(z);
6426 z = z ? bigtrunc(bigmul0(z, x)) : x;
6436 return DBL2NUM(pow(rb_big2dbl(x), d));
6440bigand_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6448 if (y == 0)
return INT2FIX(0);
6450 hibitsy = 0 <= y ? 0 : BDIGMAX;
6452#if SIZEOF_BDIGIT >= SIZEOF_LONG
6460#if SIZEOF_BDIGIT < SIZEOF_LONG
6461 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6462 zn = bdigit_roomof(SIZEOF_LONG);
6468#if SIZEOF_BDIGIT >= SIZEOF_LONG
6470 zds[0] = xds[0] & BIGLO(y);
6472 for (i=0; i < xn; i++) {
6473 if (y == 0 || y == -1)
break;
6474 zds[i] = xds[i] & BIGLO(y);
6477 for (; i < zn; i++) {
6478 if (y == 0 || y == -1)
break;
6479 zds[i] = hibitsx & BIGLO(y);
6483 for (;i < xn; i++) {
6484 zds[i] = xds[i] & hibitsy;
6486 for (;i < zn; i++) {
6487 zds[i] = hibitsx & hibitsy;
6489 twocomp2abs_bang(z, hibitsx && hibitsy);
6498 BDIGIT *ds1, *ds2, *zds;
6499 long i, xn, yn, n1, n2;
6500 BDIGIT hibitsx, hibitsy;
6501 BDIGIT hibits1, hibits2;
6510 hibitsx = abs2twocomp(&x, &xn);
6512 return bigand_int(x, xn, hibitsx,
FIX2LONG(y));
6514 hibitsy = abs2twocomp(&y, &yn);
6516 tmpv = x; x = y; y = tmpv;
6517 tmpn = xn; xn = yn; yn = tmpn;
6518 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6533 for (i=0; i<n1; i++) {
6534 zds[i] = ds1[i] & ds2[i];
6537 zds[i] = hibits1 & ds2[i];
6539 twocomp2abs_bang(z, hibits1 && hibits2);
6546bigor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6554 if (y == -1)
return INT2FIX(-1);
6556 hibitsy = 0 <= y ? 0 : BDIGMAX;
6560#if SIZEOF_BDIGIT < SIZEOF_LONG
6561 if (zn < bdigit_roomof(SIZEOF_LONG))
6562 zn = bdigit_roomof(SIZEOF_LONG);
6567#if SIZEOF_BDIGIT >= SIZEOF_LONG
6569 zds[0] = xds[0] | BIGLO(y);
6571 goto y_is_fixed_point;
6574 for (i=0; i < xn; i++) {
6575 if (y == 0 || y == -1)
goto y_is_fixed_point;
6576 zds[i] = xds[i] | BIGLO(y);
6581 for (; i < zn; i++) {
6582 if (y == 0 || y == -1)
goto y_is_fixed_point;
6592 for (; i < xn; i++) {
6597 for (; i < zn; i++) {
6603 for (; i < zn; i++) {
6608 twocomp2abs_bang(z, hibitsx || hibitsy);
6617 BDIGIT *ds1, *ds2, *zds;
6618 long i, xn, yn, n1, n2;
6619 BDIGIT hibitsx, hibitsy;
6620 BDIGIT hibits1, hibits2;
6629 hibitsx = abs2twocomp(&x, &xn);
6631 return bigor_int(x, xn, hibitsx,
FIX2LONG(y));
6633 hibitsy = abs2twocomp(&y, &yn);
6635 tmpv = x; x = y; y = tmpv;
6636 tmpn = xn; xn = yn; yn = tmpn;
6637 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6652 for (i=0; i<n1; i++) {
6653 zds[i] = ds1[i] | ds2[i];
6656 zds[i] = hibits1 | ds2[i];
6658 twocomp2abs_bang(z, hibits1 || hibits2);
6665bigxor_int(
VALUE x,
long xn, BDIGIT hibitsx,
long y)
6673 hibitsy = 0 <= y ? 0 : BDIGMAX;
6676#if SIZEOF_BDIGIT < SIZEOF_LONG
6677 if (zn < bdigit_roomof(SIZEOF_LONG))
6678 zn = bdigit_roomof(SIZEOF_LONG);
6683#if SIZEOF_BDIGIT >= SIZEOF_LONG
6685 zds[0] = xds[0] ^ BIGLO(y);
6687 for (i = 0; i < xn; i++) {
6688 zds[i] = xds[i] ^ BIGLO(y);
6691 for (; i < zn; i++) {
6692 zds[i] = hibitsx ^ BIGLO(y);
6696 for (; i < xn; i++) {
6697 zds[i] = xds[i] ^ hibitsy;
6699 for (; i < zn; i++) {
6700 zds[i] = hibitsx ^ hibitsy;
6702 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6711 BDIGIT *ds1, *ds2, *zds;
6712 long i, xn, yn, n1, n2;
6713 BDIGIT hibitsx, hibitsy;
6714 BDIGIT hibits1, hibits2;
6723 hibitsx = abs2twocomp(&x, &xn);
6725 return bigxor_int(x, xn, hibitsx,
FIX2LONG(y));
6727 hibitsy = abs2twocomp(&y, &yn);
6729 tmpv = x; x = y; y = tmpv;
6730 tmpn = xn; xn = yn; yn = tmpn;
6731 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6743 for (i=0; i<n1; i++) {
6744 zds[i] = ds1[i] ^ ds2[i];
6747 zds[i] = hibitsx ^ ds2[i];
6749 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6759 size_t shift_numdigits;
6765 unsigned long shift;
6772 shift = 1+(
unsigned long)(-(l+1));
6774 shift_numbits = (int)(shift & (BITSPERDIG-1));
6775 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6776 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6778 else if (RB_BIGNUM_TYPE_P(y)) {
6779 return bignorm(big_shift2(x, 1, y));
6789 size_t shift_numdigits;
6795 unsigned long shift;
6802 shift = 1+(
unsigned long)(-(l+1));
6804 shift_numbits = (int)(shift & (BITSPERDIG-1));
6805 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6806 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6808 else if (RB_BIGNUM_TYPE_P(y)) {
6809 return bignorm(big_shift2(x, 0, y));
6824 if (RB_BIGNUM_TYPE_P(y)) {
6825 if (BIGNUM_NEGATIVE_P(y))
6828 if (BIGSIZE(y) >
sizeof(
size_t)) {
6831#if SIZEOF_SIZE_T <= SIZEOF_LONG
6832 shift = big2ulong(y,
"long");
6834 shift = big2ull(y,
"long long");
6842 s1 = shift/BITSPERDIG;
6843 s2 = shift%BITSPERDIG;
6844 bit = (BDIGIT)1 << s2;
6846 if (s1 >= BIGNUM_LEN(x))
6850 if (BIGNUM_POSITIVE_P(x))
6852 if (xds[s1] & (bit-1))
6854 for (i = 0; i < s1; i++)
6865 size_t copy_begin, xn, shift;
6866 ssize_t begin, length, end;
6867 bool negative_add_one;
6874 shift = begin < 0 ? -begin : 0;
6878 if (length < 0)
return rb_big_rshift(x, beg);
6879 if (length == 0 || end <= 0)
return INT2FIX(0);
6880 if (begin < 0) begin = 0;
6882 if ((
size_t)(end - 1) / BITSPERDIG >= xn) {
6884 end = xn * BITSPERDIG;
6887 if ((
size_t)begin / BITSPERDIG < xn) {
6889 size_t shift_bits, copy_end;
6890 copy_begin = begin / BITSPERDIG;
6891 shift_bits = begin % BITSPERDIG;
6892 copy_end = (end - 1) / BITSPERDIG + 1;
6893 v = bignew(copy_end - copy_begin, 1);
6895 MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
6896 negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
6898 if (shift_bits) v = rb_int_rshift(v,
SIZET2NUM(shift_bits));
6903 negative_add_one =
false;
6904 copy_begin = begin = end = 0;
6907 if (BIGNUM_NEGATIVE_P(x)) {
6908 size_t mask_size = length - shift;
6910 v = rb_int_xor(v, mask);
6911 for (
size_t i = 0; negative_add_one && i < copy_begin; i++) {
6912 if (xds[i]) negative_add_one =
false;
6914 if (negative_add_one) v = rb_int_plus(v,
INT2FIX(1));
6915 v = rb_int_and(v, mask);
6918 size_t mask_size = (size_t)end - begin;
6920 v = rb_int_and(v, mask);
6923 if (shift) v = rb_int_lshift(v,
SSIZET2NUM(shift));
6932 hash =
rb_memhash(BDIGITS(x),
sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6967 if (BIGNUM_NEGATIVE_P(x)) {
6968 x = rb_big_clone(x);
6969 BIGNUM_SET_POSITIVE_SIGN(x);
6977 return BIGNUM_SIGN(x);
6981rb_big_size(
VALUE big)
6983 return BIGSIZE(big);
6987rb_big_size_m(
VALUE big)
6993rb_big_bit_length(
VALUE big)
6998 static const BDIGIT char_bit[1] = { CHAR_BIT };
6999 BDIGIT numbytes_bary[bdigit_roomof(
sizeof(
size_t))];
7001 BDIGIT result_bary[bdigit_roomof(
sizeof(
size_t)+1)];
7003 numbytes = rb_absint_size(big, &nlz_bits);
7008 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
7009 if (nlz_bits != CHAR_BIT-1) {
7018 if (numbytes <= SIZE_MAX / CHAR_BIT) {
7019 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
7022 nlz_bary[0] = nlz_bits;
7024 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1,
sizeof(numbytes), 0,
7026 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
7027 BARY_SUB(result_bary, result_bary, nlz_bary);
7029 return rb_integer_unpack(result_bary, numberof(result_bary),
sizeof(BDIGIT), 0,
7034rb_big_bit_count(
VALUE big)
7036 if (BIGNUM_NEGATIVE_P(big))
7037 rb_raise(rb_eArgError,
"bit_count is undefined for negative integers");
7039 BDIGIT *ds = BDIGITS(big);
7040 size_t n = BIGNUM_LEN(big);
7044 count += rb_popcount64((uint64_t)ds[n]);
7051rb_big_odd_p(
VALUE num)
7053 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
7057rb_big_even_p(
VALUE num)
7059 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
7065unsigned long rb_ulong_isqrt(
unsigned long);
7066#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
7067BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
7068# ifdef ULL_TO_DOUBLE
7069# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
7072# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
7074#ifndef BDIGIT_DBL_TO_DOUBLE
7075# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
7079rb_big_isqrt(
VALUE n)
7081 BDIGIT *nds = BDIGITS(n);
7082 size_t len = BIGNUM_LEN(n);
7085 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds,
len));
7086#if SIZEOF_BDIGIT > SIZEOF_LONG
7093 size_t shift =
FIX2LONG(rb_big_bit_length(n)) / 4;
7097 x = rb_int_plus(rb_int_lshift(x,
SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n,
SIZET2NUM(shift + 1)), x));
7098 VALUE xx = rb_int_mul(x, x);
7099 while (rb_int_gt(xx, n)) {
7100 xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x),
INT2FIX(1)));
7101 x = rb_int_minus(x,
INT2FIX(1));
7109bary_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)
7117 bdigits_to_mpz(x, xds, xn);
7118 bdigits_to_mpz(y, yds, yn);
7119 bdigits_to_mpz(m, mds, mn);
7120 mpz_powm(z, x, y, m);
7121 bdigits_from_mpz(z, zds, &count);
7122 BDIGITS_ZERO(zds+count, zn-count);
7135 size_t xn, yn, mn, zn;
7149 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7150 if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
7151 z = rb_big_minus(z, m);
7156 return rb_big_norm(z);
7162 if (
RTEST(rb_int_odd_p(y))) {
7163 tmp = rb_int_mul(tmp, x);
7164 tmp = rb_int_modulo(tmp, m);
7166 x = rb_int_mul(x, x);
7167 x = rb_int_modulo(x, m);
7169 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7171 tmp = rb_int_mul(tmp, x);
7172 tmp = rb_int_modulo(tmp, m);
7174 x = rb_int_mul(x, x);
7175 x = rb_int_modulo(x, m);
7178 if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
7179 tmp = rb_int_minus(tmp, m);
7190int_pow_tmp1(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7197 if (
RTEST(rb_int_odd_p(y))) {
7198 tmp = (tmp * xx) % mm;
7200 xx = (xx * xx) % mm;
7202 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7204 tmp = (tmp * xx) % mm;
7206 xx = (xx * xx) % mm;
7209 if (nega_flg && tmp) {
7216int_pow_tmp2(
VALUE x,
VALUE y,
long mm,
int nega_flg)
7224# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7229# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7233 if (
RTEST(rb_int_odd_p(y))) {
7234 tmp2 = MUL_MODULO(tmp2, xx, m);
7236 xx = MUL_MODULO(xx, xx, m);
7238 for (yy =
FIX2LONG(y); yy; yy >>= 1L) {
7240 tmp2 = MUL_MODULO(tmp2, xx, m);
7242 xx = MUL_MODULO(xx, xx, m);
7250 if (nega_flg && tmp) {
7268rb_int_powm(
int const argc,
VALUE *
const argv,
VALUE const num)
7273 return rb_int_pow(num, argv[0]);
7276 VALUE const a = num;
7277 VALUE const b = argv[0];
7281 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7283 if (rb_int_negative_p(b)) {
7284 rb_raise(
rb_eRangeError,
"Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7287 rb_raise(
rb_eTypeError,
"Integer#pow() 2nd argument not allowed unless all arguments are integers");
7290 if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
7295 if (rb_int_negative_p(m)) {
7296 m = rb_int_uminus(m);
7301 long const half_val = (long)HALF_LONG_MSB;
7304 if (mm == 1)
return INT2FIX(0);
7305 if (mm <= half_val) {
7306 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7309 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7315 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7346 rb_define_const(
rb_cInteger,
"GMP_VERSION", rb_sprintf(
"GMP %s", gmp_version));
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
#define RUBY_DEBUG
Define this macro when you want assertions.
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define NUM2SSIZET
Old name of RB_NUM2SSIZE.
#define ISSPACE
Old name of rb_isspace.
#define RFLOAT_VALUE
Old name of rb_float_value.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define NEGFIXABLE
Old name of RB_NEGFIXABLE.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define ULONG2NUM
Old name of RB_ULONG2NUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SSIZET2NUM
Old name of RB_SSIZE2NUM.
#define CLASS_OF
Old name of rb_class_of.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define FIXABLE
Old name of RB_FIXABLE.
#define LONG2FIX
Old name of RB_INT2FIX.
#define FIX2INT
Old name of RB_FIX2INT.
#define FIX2ULONG
Old name of RB_FIX2ULONG.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define NUM2DBL
Old name of rb_num2dbl.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define FIXNUM_MIN
Old name of RUBY_FIXNUM_MIN.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define POSFIXABLE
Old name of RB_POSFIXABLE.
#define DBL2NUM
Old name of rb_float_new.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define ALLOCV_END
Old name of RB_ALLOCV_END.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
void rb_invalid_str(const char *str, const char *type)
Honestly I don't understand the name, but it raises an instance of rb_eArgError.
VALUE rb_eFloatDomainError
FloatDomainError exception.
void rb_warning(const char *fmt,...)
Issues a warning.
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
VALUE rb_cInteger
Module class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Identical to rb_ary_new_from_values(), except it expects exactly two parameters.
#define RB_INT_PARSE_UNDERSCORE
Allows underscores between digits.
#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 RB_INT_PARSE_SIGN
Allows a leading sign (+ or -).
#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 RB_INT_PARSE_DEFAULT
Default flags (all features enabled).
#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 RB_INT_PARSE_PREFIX
Allows a base prefix (0x, 0b, 0o, 0d).
#define INTEGER_PACK_LSWORD_FIRST
Stores/interprets the least significant word as the first word.
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
void rb_num_zerodiv(void)
Just always raises an exception.
VALUE rb_fix2str(VALUE val, int base)
Generates a place-value representation of the given Fixnum, with given radix.
VALUE rb_num_coerce_bit(VALUE lhs, VALUE rhs, ID op)
This one is optimised for bitwise operations, but the API is identical to rb_num_coerce_bin().
VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_cmp(), except for return values.
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
VALUE rb_rational_raw(VALUE num, VALUE den)
Identical to rb_rational_new(), except it skips argument validations.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
void rb_thread_check_ints(void)
Checks for interrupts.
int capa
Designed capacity of the buffer.
int len
Length of the buffer.
#define RB_NOGVL_UBF_ASYNC_SAFE
Passing this flag to rb_nogvl() indicates that the passed UBF is async-signal-safe.
void * rb_nogvl(void *(*func)(void *), void *data1, rb_unblock_function_t *ubf, void *data2, int flags)
Identical to rb_thread_call_without_gvl(), except it additionally takes "flags" that change the behav...
#define RB_NOGVL_OFFLOAD_SAFE
Passing this flag to rb_nogvl() indicates that the passed function is safe to offload to a background...
VALUE rb_ull2inum(unsigned LONG_LONG num)
Converts a C's unsigned long long into an instance of rb_cInteger.
VALUE rb_ll2inum(LONG_LONG num)
Converts a C's long long into an instance of rb_cInteger.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define MEMCMP(p1, p2, type, n)
Handy macro to call memcmp.
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
VALUE type(ANYARGS)
ANYARGS-ed function type.
#define StringValue(v)
Ensures that the parameter object is a String.
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define RTEST
This is an old name of RB_TEST.
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
uintptr_t VALUE
Type that represents a Ruby object.
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
#define RBIMPL_WARNING_IGNORED(flag)
Suppresses a warning.
#define RBIMPL_WARNING_PUSH()
Pushes compiler warning state.
#define RBIMPL_WARNING_POP()
Pops compiler warning state.