Ruby: bignum.c Source File

Ruby 3.3.6p108 (2024-11-05 revision 75015d4c1f6965b5e85e96fb309f1f2129f933c0)

bignum.c
1/**********************************************************************
2
3 bignum.c -
4
5 $Author$
6 created at: Fri Jun 10 00:48:55 JST 1994
7
8 Copyright (C) 1993-2007 Yukihiro Matsumoto
9
10**********************************************************************/
11
12#include "ruby/internal/config.h"
13
14#include <ctype.h>
15#include <float.h>
16#include <math.h>
17
18#ifdef HAVE_STRINGS_H
19# include <strings.h>
20#endif
21
22#ifdef HAVE_IEEEFP_H
23# include <ieeefp.h>
24#endif
25
26#if !defined(USE_GMP)
27#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
28# define USE_GMP 1
29#else
30# define USE_GMP 0
31#endif
32#endif
33#if USE_GMP
34# include <gmp.h>
35#endif
36
37#include "id.h"
38#include "internal.h"
39#include "internal/bignum.h"
40#include "internal/complex.h"
41#include "internal/gc.h"
42#include "internal/numeric.h"
43#include "internal/object.h"
44#include "internal/sanitizers.h"
45#include "internal/variable.h"
46#include "internal/warnings.h"
47#include "ruby/thread.h"
48#include "ruby/util.h"
49#include "ruby_assert.h"
50
51static const bool debug_integer_pack = (
52#ifdef DEBUG_INTEGER_PACK
53 DEBUG_INTEGER_PACK+0
54#else
55 RUBY_DEBUG
56#endif
57 ) != 0;
58
59const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
60
61#ifndef SIZEOF_BDIGIT_DBL
62# if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
63# define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
64# else
65# define SIZEOF_BDIGIT_DBL SIZEOF_LONG
66# endif
67#endif
68
69STATIC_ASSERT(sizeof_bdigit_dbl, sizeof(BDIGIT_DBL) == SIZEOF_BDIGIT_DBL);
70STATIC_ASSERT(sizeof_bdigit_dbl_signed, sizeof(BDIGIT_DBL_SIGNED) == SIZEOF_BDIGIT_DBL);
71STATIC_ASSERT(sizeof_bdigit, SIZEOF_BDIGIT <= sizeof(BDIGIT));
72STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGIT*2 <= SIZEOF_BDIGIT_DBL);
73STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
74STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
75STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
76STATIC_ASSERT(rbignum_embed_len_max, BIGNUM_EMBED_LEN_MAX <= (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT));
77
78#if SIZEOF_BDIGIT < SIZEOF_LONG
79STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
80#else
81STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGIT % SIZEOF_LONG == 0);
82#endif
83
84#ifdef WORDS_BIGENDIAN
85# define HOST_BIGENDIAN_P 1
86#else
87# define HOST_BIGENDIAN_P 0
88#endif
89/* (!LSHIFTABLE(d, n) ? 0 : (n)) is the same as n but suppress a warning, C4293, by Visual Studio. */
90#define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
91#define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
92#define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
93#define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
94#define POW2_P(x) (((x)&((x)-1))==0)
95
96#define BDIGITS(x) (BIGNUM_DIGITS(x))
97#define BITSPERDIG (SIZEOF_BDIGIT*CHAR_BIT)
98#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
99#define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
100#define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
101#define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
102#define BIGDN(x) RSHIFT((x),BITSPERDIG)
103#define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
104#define BDIGMAX ((BDIGIT)(BIGRAD-1))
105#define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
106
107#if SIZEOF_BDIGIT == 2
108# define swap_bdigit(x) swap16(x)
109#elif SIZEOF_BDIGIT == 4
110# define swap_bdigit(x) swap32(x)
111#elif SIZEOF_BDIGIT == 8
112# define swap_bdigit(x) swap64(x)
113#endif
114
115#define BIGZEROP(x) (BIGNUM_LEN(x) == 0 || \
116 (BDIGITS(x)[0] == 0 && \
117 (BIGNUM_LEN(x) == 1 || bigzero_p(x))))
118#define BIGSIZE(x) (BIGNUM_LEN(x) == 0 ? (size_t)0 : \
119 BDIGITS(x)[BIGNUM_LEN(x)-1] ? \
120 (size_t)(BIGNUM_LEN(x)*SIZEOF_BDIGIT - nlz(BDIGITS(x)[BIGNUM_LEN(x)-1])/CHAR_BIT) : \
121 rb_absint_size(x, NULL))
122
123#define BIGDIVREM_EXTRA_WORDS 1
124#define bdigit_roomof(n) roomof(n, SIZEOF_BDIGIT)
125#define BARY_ARGS(ary) ary, numberof(ary)
126
127#define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
128#define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
129#define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
130#define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
131#define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
132
133#define BIGNUM_SET_NEGATIVE_SIGN(b) BIGNUM_SET_SIGN(b, 0)
134#define BIGNUM_SET_POSITIVE_SIGN(b) BIGNUM_SET_SIGN(b, 1)
135
136#define bignew(len,sign) bignew_1(rb_cInteger,(len),(sign))
137
138#define BDIGITS_ZERO(ptr, n) do { \
139 BDIGIT *bdigitz_zero_ptr = (ptr); \
140 size_t bdigitz_zero_n = (n); \
141 while (bdigitz_zero_n) { \
142 *bdigitz_zero_ptr++ = 0; \
143 bdigitz_zero_n--; \
144 } \
145} while (0)
146
147#define BARY_TRUNC(ds, n) do { \
148 while (0 < (n) && (ds)[(n)-1] == 0) \
149 (n)--; \
150 } while (0)
151
152#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
153#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
154
155#define GMP_MUL_DIGITS 20
156#define KARATSUBA_MUL_DIGITS 70
157#define TOOM3_MUL_DIGITS 150
158
159#define GMP_DIV_DIGITS 20
160#define GMP_BIG2STR_DIGITS 20
161#define GMP_STR2BIG_DIGITS 20
162#if USE_GMP
163# define NAIVE_MUL_DIGITS GMP_MUL_DIGITS
164#else
165# define NAIVE_MUL_DIGITS KARATSUBA_MUL_DIGITS
166#endif
167
168typedef 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);
169
170static mulfunc_t bary_mul_toom3_start;
171static mulfunc_t bary_mul_karatsuba_start;
172static BDIGIT bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y);
173
174static VALUE bignew_1(VALUE klass, size_t len, int sign);
175static inline VALUE bigtrunc(VALUE x);
176
177static VALUE bigsq(VALUE x);
178static inline VALUE power_cache_get_power(int base, int power_level, size_t *numdigits_ret);
179
180#if SIZEOF_BDIGIT <= SIZEOF_INT
181static int nlz(BDIGIT x) { return nlz_int((unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGIT) * CHAR_BIT; }
182#elif SIZEOF_BDIGIT <= SIZEOF_LONG
183static int nlz(BDIGIT x) { return nlz_long((unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
184#elif SIZEOF_BDIGIT <= SIZEOF_LONG_LONG
185static int nlz(BDIGIT x) { return nlz_long_long((unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGIT) * CHAR_BIT; }
186#elif SIZEOF_BDIGIT <= SIZEOF_INT128_T
187static int nlz(BDIGIT x) { return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGIT) * CHAR_BIT; }
188#endif
189
190#define U16(a) ((uint16_t)(a))
191#define U32(a) ((uint32_t)(a))
192#ifdef HAVE_UINT64_T
193#define U64(a,b) (((uint64_t)(a) << 32) | (b))
194#endif
195#ifdef HAVE_UINT128_T
196#define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
197#endif
198
199/* The following script, maxpow.rb, generates the tables follows.
200
201def big(n, bits)
202 ns = []
203 ((bits+31)/32).times {
204 ns << sprintf("0x%08x", n & 0xffff_ffff)
205 n >>= 32
206 }
207 "U#{bits}(" + ns.reverse.join(",") + ")"
208end
209def values(ary, width, indent)
210 lines = [""]
211 ary.each {|e|
212 lines << "" if !ary.last.empty? && width < (lines.last + e + ", ").length
213 lines.last << e + ", "
214 }
215 lines.map {|line| " " * indent + line.chomp(" ") + "\n" }.join
216end
217[16,32,64,128].each {|bits|
218 max = 2**bits-1
219 exps = []
220 nums = []
221 2.upto(36) {|base|
222 exp = 0
223 n = 1
224 while n * base <= max
225 exp += 1
226 n *= base
227 end
228 exps << exp.to_s
229 nums << big(n, bits)
230 }
231 puts "#ifdef HAVE_UINT#{bits}_T"
232 puts "static const int maxpow#{bits}_exp[35] = {"
233 print values(exps, 70, 4)
234 puts "};"
235 puts "static const uint#{bits}_t maxpow#{bits}_num[35] = {"
236 print values(nums, 70, 4)
237 puts "};"
238 puts "#endif"
239}
240
241 */
242
243#if SIZEOF_BDIGIT_DBL == 2
244static const int maxpow16_exp[35] = {
245 15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
246 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
247};
248static const uint16_t maxpow16_num[35] = {
249 U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
250 U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
251 U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
252 U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
253 U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
254 U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
255 U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
256 U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
257 U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
258};
259#elif SIZEOF_BDIGIT_DBL == 4
260static const int maxpow32_exp[35] = {
261 31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
262 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
263};
264static const uint32_t maxpow32_num[35] = {
265 U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
266 U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
267 U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
268 U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
269 U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
270 U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
271 U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
272 U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
273 U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
274};
275#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
276static const int maxpow64_exp[35] = {
277 63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
278 15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
279 12,
280};
281static const uint64_t maxpow64_num[35] = {
282 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
283 U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
284 U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
285 U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
286 U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
287 U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
288 U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
289 U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
290 U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
291 U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
292 U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
293 U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
294 U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
295 U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
296 U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
297 U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
298 U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
299 U64(0x41c21cb8,0xe1000000),
300};
301#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
302static const int maxpow128_exp[35] = {
303 127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
304 30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
305 24,
306};
307static const uint128_t maxpow128_num[35] = {
308 U128(0x80000000,0x00000000,0x00000000,0x00000000),
309 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
310 U128(0x40000000,0x00000000,0x00000000,0x00000000),
311 U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
312 U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
313 U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
314 U128(0x40000000,0x00000000,0x00000000,0x00000000),
315 U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
316 U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
317 U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
318 U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
319 U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
320 U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
321 U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
322 U128(0x10000000,0x00000000,0x00000000,0x00000000),
323 U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
324 U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
325 U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
326 U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
327 U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
328 U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
329 U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
330 U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
331 U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
332 U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
333 U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
334 U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
335 U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
336 U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
337 U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
338 U128(0x20000000,0x00000000,0x00000000,0x00000000),
339 U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
340 U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
341 U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
342 U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
343};
344#endif
345
346static BDIGIT_DBL
347maxpow_in_bdigit_dbl(int base, int *exp_ret)
348{
349 BDIGIT_DBL maxpow;
350 int exponent;
351
352 assert(2 <= base && base <= 36);
353
354 {
355#if SIZEOF_BDIGIT_DBL == 2
356 maxpow = maxpow16_num[base-2];
357 exponent = maxpow16_exp[base-2];
358#elif SIZEOF_BDIGIT_DBL == 4
359 maxpow = maxpow32_num[base-2];
360 exponent = maxpow32_exp[base-2];
361#elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
362 maxpow = maxpow64_num[base-2];
363 exponent = maxpow64_exp[base-2];
364#elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
365 maxpow = maxpow128_num[base-2];
366 exponent = maxpow128_exp[base-2];
367#else
368 maxpow = base;
369 exponent = 1;
370 while (maxpow <= BDIGIT_DBL_MAX / base) {
371 maxpow *= base;
372 exponent++;
373 }
374#endif
375 }
376
377 *exp_ret = exponent;
378 return maxpow;
379}
380
381static inline BDIGIT_DBL
382bary2bdigitdbl(const BDIGIT *ds, size_t n)
383{
384 assert(n <= 2);
385
386 if (n == 2)
387 return ds[0] | BIGUP(ds[1]);
388 if (n == 1)
389 return ds[0];
390 return 0;
391}
392
393static inline void
394bdigitdbl2bary(BDIGIT *ds, size_t n, BDIGIT_DBL num)
395{
396 assert(n == 2);
397
398 ds[0] = BIGLO(num);
399 ds[1] = (BDIGIT)BIGDN(num);
400}
401
402static int
403bary_cmp(const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
404{
405 size_t i;
406 BARY_TRUNC(xds, xn);
407 BARY_TRUNC(yds, yn);
408
409 if (xn < yn)
410 return -1;
411 if (xn > yn)
412 return 1;
413
414 for (i = 0; i < xn; i++)
415 if (xds[xn - i - 1] != yds[yn - i - 1])
416 break;
417 if (i == xn)
418 return 0;
419 return xds[xn - i - 1] < yds[yn - i - 1] ? -1 : 1;
420}
421
422static BDIGIT
423bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
424{
425 size_t i;
426 BDIGIT_DBL num = 0;
427 assert(0 <= shift && shift < BITSPERDIG);
428
429 for (i=0; i<n; i++) {
430 num = num | (BDIGIT_DBL)*xds++ << shift;
431 *zds++ = BIGLO(num);
432 num = BIGDN(num);
433 }
434 return BIGLO(num);
435}
436
437static void
438bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT higher_bdigit)
439{
440 size_t i;
441 BDIGIT_DBL num = 0;
442
443 assert(0 <= shift && shift < BITSPERDIG);
444
445 num = BIGUP(higher_bdigit);
446 for (i = 0; i < n; i++) {
447 BDIGIT x = xds[n - i - 1];
448 num = (num | x) >> shift;
449 zds[n - i - 1] = BIGLO(num);
450 num = BIGUP(x);
451 }
452}
453
454static int
455bary_zero_p(const BDIGIT *xds, size_t xn)
456{
457 if (xn == 0)
458 return 1;
459 do {
460 if (xds[--xn]) return 0;
461 } while (xn);
462 return 1;
463}
464
465static void
466bary_neg(BDIGIT *ds, size_t n)
467{
468 size_t i;
469 for (i = 0; i < n; i++)
470 ds[n - i - 1] = BIGLO(~ds[n - i - 1]);
471}
472
473static int
474bary_2comp(BDIGIT *ds, size_t n)
475{
476 size_t i;
477 for (i = 0; i < n; i++) {
478 if (ds[i] != 0) {
479 goto non_zero;
480 }
481 }
482 return 1;
483
484 non_zero:
485 ds[i] = BIGLO(~ds[i] + 1);
486 i++;
487 for (; i < n; i++) {
488 ds[i] = BIGLO(~ds[i]);
489 }
490 return 0;
491}
492
493static void
494bary_swap(BDIGIT *ds, size_t num_bdigits)
495{
496 BDIGIT *p1 = ds;
497 BDIGIT *p2 = ds + num_bdigits - 1;
498 for (; p1 < p2; p1++, p2--) {
499 BDIGIT tmp = *p1;
500 *p1 = *p2;
501 *p2 = tmp;
502 }
503}
504
505#define INTEGER_PACK_WORDORDER_MASK \
506 (INTEGER_PACK_MSWORD_FIRST | \
507 INTEGER_PACK_LSWORD_FIRST)
508#define INTEGER_PACK_BYTEORDER_MASK \
509 (INTEGER_PACK_MSBYTE_FIRST | \
510 INTEGER_PACK_LSBYTE_FIRST | \
511 INTEGER_PACK_NATIVE_BYTE_ORDER)
512
513static void
514validate_integer_pack_format(size_t numwords, size_t wordsize, size_t nails, int flags, int supported_flags)
515{
516 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
517 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
518
519 if (flags & ~supported_flags) {
520 rb_raise(rb_eArgError, "unsupported flags specified");
521 }
522 if (wordorder_bits == 0) {
523 if (1 < numwords)
524 rb_raise(rb_eArgError, "word order not specified");
525 }
526 else if (wordorder_bits != INTEGER_PACK_MSWORD_FIRST &&
527 wordorder_bits != INTEGER_PACK_LSWORD_FIRST)
528 rb_raise(rb_eArgError, "unexpected word order");
529 if (byteorder_bits == 0) {
530 rb_raise(rb_eArgError, "byte order not specified");
531 }
532 else if (byteorder_bits != INTEGER_PACK_MSBYTE_FIRST &&
533 byteorder_bits != INTEGER_PACK_LSBYTE_FIRST &&
534 byteorder_bits != INTEGER_PACK_NATIVE_BYTE_ORDER)
535 rb_raise(rb_eArgError, "unexpected byte order");
536 if (wordsize == 0)
537 rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
538 if (SSIZE_MAX < wordsize)
539 rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
540 if (wordsize <= nails / CHAR_BIT)
541 rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails);
542 if (SIZE_MAX / wordsize < numwords)
543 rb_raise(rb_eArgError, "too big numwords * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", numwords, wordsize);
544}
545
546static void
547integer_pack_loop_setup(
548 size_t numwords, size_t wordsize, size_t nails, int flags,
549 size_t *word_num_fullbytes_ret,
550 int *word_num_partialbits_ret,
551 size_t *word_start_ret,
552 ssize_t *word_step_ret,
553 size_t *word_last_ret,
554 size_t *byte_start_ret,
555 int *byte_step_ret)
556{
557 int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
558 int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
559 size_t word_num_fullbytes;
560 int word_num_partialbits;
561 size_t word_start;
562 ssize_t word_step;
563 size_t word_last;
564 size_t byte_start;
565 int byte_step;
566
567 word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
568 if (word_num_partialbits == CHAR_BIT)
569 word_num_partialbits = 0;
570 word_num_fullbytes = wordsize - (nails / CHAR_BIT);
571 if (word_num_partialbits != 0) {
572 word_num_fullbytes--;
573 }
574
575 if (wordorder_bits == INTEGER_PACK_MSWORD_FIRST) {
576 word_start = wordsize*(numwords-1);
577 word_step = -(ssize_t)wordsize;
578 word_last = 0;
579 }
580 else {
581 word_start = 0;
582 word_step = wordsize;
583 word_last = wordsize*(numwords-1);
584 }
585
586 if (byteorder_bits == INTEGER_PACK_NATIVE_BYTE_ORDER) {
587#ifdef WORDS_BIGENDIAN
588 byteorder_bits = INTEGER_PACK_MSBYTE_FIRST;
589#else
590 byteorder_bits = INTEGER_PACK_LSBYTE_FIRST;
591#endif
592 }
593 if (byteorder_bits == INTEGER_PACK_MSBYTE_FIRST) {
594 byte_start = wordsize-1;
595 byte_step = -1;
596 }
597 else {
598 byte_start = 0;
599 byte_step = 1;
600 }
601
602 *word_num_partialbits_ret = word_num_partialbits;
603 *word_num_fullbytes_ret = word_num_fullbytes;
604 *word_start_ret = word_start;
605 *word_step_ret = word_step;
606 *word_last_ret = word_last;
607 *byte_start_ret = byte_start;
608 *byte_step_ret = byte_step;
609}
610
611static inline void
612integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
613{
614 if (*dpp < *dep && BITSPERDIG <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
615 *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
616 *numbits_in_dd_p += BITSPERDIG;
617 }
618 else if (*dpp == *dep) {
619 /* higher bits are infinity zeros */
620 *numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT;
621 }
622}
623
624static inline BDIGIT_DBL
625integer_pack_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
626{
627 BDIGIT_DBL ret;
628 ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
629 *ddp >>= n;
630 *numbits_in_dd_p -= n;
631 return ret;
632}
633
634#if !defined(WORDS_BIGENDIAN)
635static int
636bytes_2comp(unsigned char *buf, size_t len)
637{
638 size_t i;
639 for (i = 0; i < len; i++) {
640 signed char c = buf[i];
641 signed int d = ~c;
642 unsigned int e = d & 0xFF;
643 buf[i] = e;
644 }
645 for (i = 0; i < len; i++) {
646 buf[i]++;
647 if (buf[i] != 0)
648 return 0;
649 }
650 return 1;
651}
652#endif
653
654static int
655bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
656{
657 BDIGIT *dp, *de;
658 unsigned char *buf, *bufend;
659
660 dp = ds;
661 de = ds + num_bdigits;
662
663 validate_integer_pack_format(numwords, wordsize, nails, flags,
664 INTEGER_PACK_MSWORD_FIRST|
665 INTEGER_PACK_LSWORD_FIRST|
666 INTEGER_PACK_MSBYTE_FIRST|
667 INTEGER_PACK_LSBYTE_FIRST|
668 INTEGER_PACK_NATIVE_BYTE_ORDER|
669 INTEGER_PACK_2COMP|
670 INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
671
672 while (dp < de && de[-1] == 0)
673 de--;
674 if (dp == de) {
675 sign = 0;
676 }
677
678 if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) {
679 if (sign == 0) {
680 MEMZERO(words, unsigned char, numwords * wordsize);
681 return 0;
682 }
683 if (nails == 0 && numwords == 1) {
684 int need_swap = wordsize != 1 &&
685 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER &&
686 ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P);
687 if (0 < sign || !(flags & INTEGER_PACK_2COMP)) {
688 BDIGIT d;
689 if (wordsize == 1) {
690 *((unsigned char *)words) = (unsigned char)(d = dp[0]);
691 return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
692 }
693#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
694 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
695 uint16_t u = (uint16_t)(d = dp[0]);
696 if (need_swap) u = swap16(u);
697 *((uint16_t *)words) = u;
698 return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
699 }
700#endif
701#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
702 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
703 uint32_t u = (uint32_t)(d = dp[0]);
704 if (need_swap) u = swap32(u);
705 *((uint32_t *)words) = u;
706 return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
707 }
708#endif
709#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
710 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
711 uint64_t u = (uint64_t)(d = dp[0]);
712 if (need_swap) u = swap64(u);
713 *((uint64_t *)words) = u;
714 return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
715 }
716#endif
717 }
718 else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */
719 BDIGIT_DBL_SIGNED d;
720 if (wordsize == 1) {
721 *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
722 return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
723 }
724#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
725 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
726 uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
727 if (need_swap) u = swap16(u);
728 *((uint16_t *)words) = u;
729 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
730 (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
731 }
732#endif
733#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
734 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
735 uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
736 if (need_swap) u = swap32(u);
737 *((uint32_t *)words) = u;
738 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
739 (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
740 }
741#endif
742#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
743 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
744 uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
745 if (need_swap) u = swap64(u);
746 *((uint64_t *)words) = u;
747 return (wordsize == SIZEOF_BDIGIT && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
748 (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
749 }
750#endif
751 }
752 }
753#if !defined(WORDS_BIGENDIAN)
754 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
755 (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST &&
756 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) {
757 size_t src_size = (de - dp) * SIZEOF_BDIGIT;
758 size_t dst_size = numwords * wordsize;
759 int overflow = 0;
760 while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0)
761 src_size--;
762 if (src_size <= dst_size) {
763 MEMCPY(words, dp, char, src_size);
764 MEMZERO((char*)words + src_size, char, dst_size - src_size);
765 }
766 else {
767 MEMCPY(words, dp, char, dst_size);
768 overflow = 1;
769 }
770 if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
771 int zero_p = bytes_2comp(words, dst_size);
772 if (zero_p && overflow) {
773 unsigned char *p = (unsigned char *)dp;
774 if (dst_size == src_size-1 &&
775 p[dst_size] == 1) {
776 overflow = 0;
777 }
778 }
779 }
780 if (overflow)
781 sign *= 2;
782 return sign;
783 }
784#endif
785 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
786 wordsize % SIZEOF_BDIGIT == 0 && (uintptr_t)words % RUBY_ALIGNOF(BDIGIT) == 0) {
787 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
788 size_t src_num_bdigits = de - dp;
789 size_t dst_num_bdigits = numwords * bdigits_per_word;
790 int overflow = 0;
791 int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
792 int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
793 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
794 if (src_num_bdigits <= dst_num_bdigits) {
795 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
796 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
797 }
798 else {
799 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
800 overflow = 1;
801 }
802 if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
803 int zero_p = bary_2comp(words, dst_num_bdigits);
804 if (zero_p && overflow &&
805 dst_num_bdigits == src_num_bdigits-1 &&
806 dp[dst_num_bdigits] == 1)
807 overflow = 0;
808 }
809 if (msbytefirst_p != HOST_BIGENDIAN_P) {
810 size_t i;
811 for (i = 0; i < dst_num_bdigits; i++) {
812 BDIGIT d = ((BDIGIT*)words)[i];
813 ((BDIGIT*)words)[i] = swap_bdigit(d);
814 }
815 }
816 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
817 size_t i;
818 BDIGIT *p = words;
819 for (i = 0; i < numwords; i++) {
820 bary_swap(p, bdigits_per_word);
821 p += bdigits_per_word;
822 }
823 }
824 if (mswordfirst_p) {
825 bary_swap(words, dst_num_bdigits);
826 }
827 if (overflow)
828 sign *= 2;
829 return sign;
830 }
831 }
832
833 buf = words;
834 bufend = buf + numwords * wordsize;
835
836 if (buf == bufend) {
837 /* overflow if non-zero*/
838 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
839 sign *= 2;
840 else {
841 if (de - dp == 1 && dp[0] == 1)
842 sign = -1; /* val == -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
843 else
844 sign = -2; /* val < -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
845 }
846 }
847 else if (dp == de) {
848 memset(buf, '\0', bufend - buf);
849 }
850 else if (dp < de && buf < bufend) {
851 int word_num_partialbits;
852 size_t word_num_fullbytes;
853
854 ssize_t word_step;
855 size_t byte_start;
856 int byte_step;
857
858 size_t word_start, word_last;
859 unsigned char *wordp, *last_wordp;
860 BDIGIT_DBL dd;
861 int numbits_in_dd;
862
863 integer_pack_loop_setup(numwords, wordsize, nails, flags,
864 &word_num_fullbytes, &word_num_partialbits,
865 &word_start, &word_step, &word_last, &byte_start, &byte_step);
866
867 wordp = buf + word_start;
868 last_wordp = buf + word_last;
869
870 dd = 0;
871 numbits_in_dd = 0;
872
873#define FILL_DD \
874 integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
875#define TAKE_LOWBITS(n) \
876 integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
877
878 while (1) {
879 size_t index_in_word = 0;
880 unsigned char *bytep = wordp + byte_start;
881 while (index_in_word < word_num_fullbytes) {
882 FILL_DD;
883 *bytep = TAKE_LOWBITS(CHAR_BIT);
884 bytep += byte_step;
885 index_in_word++;
886 }
887 if (word_num_partialbits) {
888 FILL_DD;
889 *bytep = TAKE_LOWBITS(word_num_partialbits);
890 bytep += byte_step;
891 index_in_word++;
892 }
893 while (index_in_word < wordsize) {
894 *bytep = 0;
895 bytep += byte_step;
896 index_in_word++;
897 }
898
899 if (wordp == last_wordp)
900 break;
901
902 wordp += word_step;
903 }
904 FILL_DD;
905 /* overflow tests */
906 if (dp != de || 1 < dd) {
907 /* 2**(numwords*(wordsize*CHAR_BIT-nails)+1) <= abs(val) */
908 sign *= 2;
909 }
910 else if (dd == 1) {
911 /* 2**(numwords*(wordsize*CHAR_BIT-nails)) <= abs(val) < 2**(numwords*(wordsize*CHAR_BIT-nails)+1) */
912 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
913 sign *= 2;
914 else { /* overflow_2comp && sign == -1 */
915 /* test lower bits are all zero. */
916 dp = ds;
917 while (dp < de && *dp == 0)
918 dp++;
919 if (de - dp == 1 && /* only one non-zero word. */
920 POW2_P(*dp)) /* *dp contains only one bit set. */
921 sign = -1; /* val == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
922 else
923 sign = -2; /* val < -2**(numwords*(wordsize*CHAR_BIT-nails)) */
924 }
925 }
926 }
927
928 if ((flags & INTEGER_PACK_2COMP) && (sign < 0 && numwords != 0)) {
929 int word_num_partialbits;
930 size_t word_num_fullbytes;
931
932 ssize_t word_step;
933 size_t byte_start;
934 int byte_step;
935
936 size_t word_start, word_last;
937 unsigned char *wordp, *last_wordp;
938
939 unsigned int partialbits_mask;
940 int carry;
941
942 integer_pack_loop_setup(numwords, wordsize, nails, flags,
943 &word_num_fullbytes, &word_num_partialbits,
944 &word_start, &word_step, &word_last, &byte_start, &byte_step);
945
946 partialbits_mask = (1 << word_num_partialbits) - 1;
947
948 buf = words;
949 wordp = buf + word_start;
950 last_wordp = buf + word_last;
951
952 carry = 1;
953 while (1) {
954 size_t index_in_word = 0;
955 unsigned char *bytep = wordp + byte_start;
956 while (index_in_word < word_num_fullbytes) {
957 carry += (unsigned char)~*bytep;
958 *bytep = (unsigned char)carry;
959 carry >>= CHAR_BIT;
960 bytep += byte_step;
961 index_in_word++;
962 }
963 if (word_num_partialbits) {
964 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
965 *bytep = carry & partialbits_mask;
966 carry >>= word_num_partialbits;
967 bytep += byte_step;
968 index_in_word++;
969 }
970
971 if (wordp == last_wordp)
972 break;
973
974 wordp += word_step;
975 }
976 }
977
978 return sign;
979#undef FILL_DD
980#undef TAKE_LOWBITS
981}
982
983static size_t
984integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
985{
986 /* nlp_bits stands for number of leading padding bits */
987 size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
988 size_t num_bdigits = roomof(num_bits, BITSPERDIG);
989 *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
990 return num_bdigits;
991}
992
993static size_t
994integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
995{
996 /* BITSPERDIG = SIZEOF_BDIGIT * CHAR_BIT */
997 /* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
998 /* num_bdigits = roomof(num_bits, BITSPERDIG) */
999
1000 /* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
1001 size_t num_bytes1 = wordsize * numwords;
1002
1003 /* q1 * CHAR_BIT + r1 = numwords */
1004 size_t q1 = numwords / CHAR_BIT;
1005 size_t r1 = numwords % CHAR_BIT;
1006
1007 /* num_bits = CHAR_BIT * num_bytes1 - nails * (q1 * CHAR_BIT + r1) = CHAR_BIT * num_bytes2 - nails * r1 */
1008 size_t num_bytes2 = num_bytes1 - nails * q1;
1009
1010 /* q2 * CHAR_BIT + r2 = nails */
1011 size_t q2 = nails / CHAR_BIT;
1012 size_t r2 = nails % CHAR_BIT;
1013
1014 /* num_bits = CHAR_BIT * num_bytes2 - (q2 * CHAR_BIT + r2) * r1 = CHAR_BIT * num_bytes3 - r1 * r2 */
1015 size_t num_bytes3 = num_bytes2 - q2 * r1;
1016
1017 /* q3 * BITSPERDIG + r3 = num_bytes3 */
1018 size_t q3 = num_bytes3 / BITSPERDIG;
1019 size_t r3 = num_bytes3 % BITSPERDIG;
1020
1021 /* num_bits = CHAR_BIT * (q3 * BITSPERDIG + r3) - r1 * r2 = BITSPERDIG * num_digits1 + CHAR_BIT * r3 - r1 * r2 */
1022 size_t num_digits1 = CHAR_BIT * q3;
1023
1024 /*
1025 * if CHAR_BIT * r3 >= r1 * r2
1026 * CHAR_BIT * r3 - r1 * r2 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2))
1027 * q4 * BITSPERDIG + r4 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2)
1028 * num_bits = BITSPERDIG * num_digits1 + CHAR_BIT * BITSPERDIG - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
1029 * else
1030 * q4 * BITSPERDIG + r4 = -(CHAR_BIT * r3 - r1 * r2)
1031 * num_bits = BITSPERDIG * num_digits1 - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
1032 * end
1033 */
1034
1035 if (CHAR_BIT * r3 >= r1 * r2) {
1036 size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
1037 size_t q4 = tmp1 / BITSPERDIG;
1038 int r4 = (int)(tmp1 % BITSPERDIG);
1039 size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
1040 *nlp_bits_ret = r4;
1041 return num_digits2;
1042 }
1043 else {
1044 size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
1045 size_t q4 = tmp1 / BITSPERDIG;
1046 int r4 = (int)(tmp1 % BITSPERDIG);
1047 size_t num_digits2 = num_digits1 - q4;
1048 *nlp_bits_ret = r4;
1049 return num_digits2;
1050 }
1051}
1052
1053static size_t
1054integer_unpack_num_bdigits(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
1055{
1056 size_t num_bdigits;
1057
1058 if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
1059 num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
1060 if (debug_integer_pack) {
1061 int nlp_bits1;
1062 size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
1063 assert(num_bdigits == num_bdigits1);
1064 assert(*nlp_bits_ret == nlp_bits1);
1065 (void)num_bdigits1;
1066 }
1067 }
1068 else {
1069 num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
1070 }
1071 return num_bdigits;
1072}
1073
1074static inline void
1075integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
1076{
1077 (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
1078 *numbits_in_dd_p += numbits;
1079 while (BITSPERDIG <= *numbits_in_dd_p) {
1080 *(*dpp)++ = BIGLO(*ddp);
1081 *ddp = BIGDN(*ddp);
1082 *numbits_in_dd_p -= BITSPERDIG;
1083 }
1084}
1085
1086static int
1087integer_unpack_single_bdigit(BDIGIT u, size_t size, int flags, BDIGIT *dp)
1088{
1089 int sign;
1090 if (flags & INTEGER_PACK_2COMP) {
1091 sign = (flags & INTEGER_PACK_NEGATIVE) ?
1092 ((size == SIZEOF_BDIGIT && u == 0) ? -2 : -1) :
1093 ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
1094 if (sign < 0) {
1095 u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
1096 u = BIGLO(1 + ~u);
1097 }
1098 }
1099 else
1100 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1101 *dp = u;
1102 return sign;
1103}
1104
1105#ifdef HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED
1106#define reinterpret_cast(type, value) (type) \
1107 __builtin_assume_aligned((value), sizeof(*(type)NULL));
1108#else
1109#define reinterpret_cast(type, value) (type)value
1110#endif
1111
1112static int
1113bary_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)
1114{
1115 int sign;
1116 const unsigned char *buf = words;
1117 BDIGIT *dp;
1118 BDIGIT *de;
1119
1120 dp = bdigits;
1121 de = dp + num_bdigits;
1122
1123 if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) {
1124 if (nails == 0 && numwords == 1) {
1125 int need_swap = wordsize != 1 &&
1126 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER &&
1127 ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P);
1128 if (wordsize == 1) {
1129 return integer_unpack_single_bdigit(*(uint8_t *)buf, sizeof(uint8_t), flags, dp);
1130 }
1131#if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGIT
1132 if (wordsize == 2 && (uintptr_t)words % RUBY_ALIGNOF(uint16_t) == 0) {
1133 uint16_t u = *reinterpret_cast(const uint16_t *, buf);
1134 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
1135 }
1136#endif
1137#if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGIT
1138 if (wordsize == 4 && (uintptr_t)words % RUBY_ALIGNOF(uint32_t) == 0) {
1139 uint32_t u = *reinterpret_cast(const uint32_t *, buf);
1140 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
1141 }
1142#endif
1143#if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGIT
1144 if (wordsize == 8 && (uintptr_t)words % RUBY_ALIGNOF(uint64_t) == 0) {
1145 uint64_t u = *reinterpret_cast(const uint64_t *, buf);
1146 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
1147 }
1148#endif
1149#undef reinterpret_cast
1150 }
1151#if !defined(WORDS_BIGENDIAN)
1152 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
1153 (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST &&
1154 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) {
1155 size_t src_size = numwords * wordsize;
1156 size_t dst_size = num_bdigits * SIZEOF_BDIGIT;
1157 MEMCPY(dp, words, char, src_size);
1158 if (flags & INTEGER_PACK_2COMP) {
1159 if (flags & INTEGER_PACK_NEGATIVE) {
1160 int zero_p;
1161 memset((char*)dp + src_size, 0xff, dst_size - src_size);
1162 zero_p = bary_2comp(dp, num_bdigits);
1163 sign = zero_p ? -2 : -1;
1164 }
1165 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
1166 memset((char*)dp + src_size, 0xff, dst_size - src_size);
1167 bary_2comp(dp, num_bdigits);
1168 sign = -1;
1169 }
1170 else {
1171 MEMZERO((char*)dp + src_size, char, dst_size - src_size);
1172 sign = 1;
1173 }
1174 }
1175 else {
1176 MEMZERO((char*)dp + src_size, char, dst_size - src_size);
1177 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1178 }
1179 return sign;
1180 }
1181#endif
1182 if (nails == 0 && SIZEOF_BDIGIT == sizeof(BDIGIT) &&
1183 wordsize % SIZEOF_BDIGIT == 0) {
1184 size_t bdigits_per_word = wordsize / SIZEOF_BDIGIT;
1185 int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
1186 int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
1187 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
1188 MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
1189 if (mswordfirst_p) {
1190 bary_swap(dp, num_bdigits);
1191 }
1192 if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
1193 size_t i;
1194 BDIGIT *p = dp;
1195 for (i = 0; i < numwords; i++) {
1196 bary_swap(p, bdigits_per_word);
1197 p += bdigits_per_word;
1198 }
1199 }
1200 if (msbytefirst_p != HOST_BIGENDIAN_P) {
1201 BDIGIT *p;
1202 for (p = dp; p < de; p++) {
1203 BDIGIT d = *p;
1204 *p = swap_bdigit(d);
1205 }
1206 }
1207 if (flags & INTEGER_PACK_2COMP) {
1208 if (flags & INTEGER_PACK_NEGATIVE) {
1209 int zero_p = bary_2comp(dp, num_bdigits);
1210 sign = zero_p ? -2 : -1;
1211 }
1212 else if (BDIGIT_MSB(de[-1])) {
1213 bary_2comp(dp, num_bdigits);
1214 sign = -1;
1215 }
1216 else {
1217 sign = 1;
1218 }
1219 }
1220 else {
1221 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1222 }
1223 return sign;
1224 }
1225 }
1226
1227 if (num_bdigits != 0) {
1228 int word_num_partialbits;
1229 size_t word_num_fullbytes;
1230
1231 ssize_t word_step;
1232 size_t byte_start;
1233 int byte_step;
1234
1235 size_t word_start, word_last;
1236 const unsigned char *wordp, *last_wordp;
1237 BDIGIT_DBL dd;
1238 int numbits_in_dd;
1239
1240 integer_pack_loop_setup(numwords, wordsize, nails, flags,
1241 &word_num_fullbytes, &word_num_partialbits,
1242 &word_start, &word_step, &word_last, &byte_start, &byte_step);
1243
1244 wordp = buf + word_start;
1245 last_wordp = buf + word_last;
1246
1247 dd = 0;
1248 numbits_in_dd = 0;
1249
1250#define PUSH_BITS(data, numbits) \
1251 integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
1252
1253 while (1) {
1254 size_t index_in_word = 0;
1255 const unsigned char *bytep = wordp + byte_start;
1256 while (index_in_word < word_num_fullbytes) {
1257 PUSH_BITS(*bytep, CHAR_BIT);
1258 bytep += byte_step;
1259 index_in_word++;
1260 }
1261 if (word_num_partialbits) {
1262 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
1263 bytep += byte_step;
1264 index_in_word++;
1265 }
1266
1267 if (wordp == last_wordp)
1268 break;
1269
1270 wordp += word_step;
1271 }
1272 if (dd)
1273 *dp++ = (BDIGIT)dd;
1274 assert(dp <= de);
1275 while (dp < de)
1276 *dp++ = 0;
1277#undef PUSH_BITS
1278 }
1279
1280 if (!(flags & INTEGER_PACK_2COMP)) {
1281 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
1282 }
1283 else {
1284 if (nlp_bits) {
1285 if ((flags & INTEGER_PACK_NEGATIVE) ||
1286 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
1287 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
1288 sign = -1;
1289 }
1290 else {
1291 sign = 1;
1292 }
1293 }
1294 else {
1295 if (flags & INTEGER_PACK_NEGATIVE) {
1296 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
1297 }
1298 else {
1299 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
1300 sign = -1;
1301 else
1302 sign = 1;
1303 }
1304 }
1305 if (sign == -1 && num_bdigits != 0) {
1306 bary_2comp(bdigits, num_bdigits);
1307 }
1308 }
1309
1310 return sign;
1311}
1312
1313static void
1314bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
1315{
1316 size_t num_bdigits0;
1317 int nlp_bits;
1318 int sign;
1319
1320 validate_integer_pack_format(numwords, wordsize, nails, flags,
1321 INTEGER_PACK_MSWORD_FIRST|
1322 INTEGER_PACK_LSWORD_FIRST|
1323 INTEGER_PACK_MSBYTE_FIRST|
1324 INTEGER_PACK_LSBYTE_FIRST|
1325 INTEGER_PACK_NATIVE_BYTE_ORDER|
1326 INTEGER_PACK_2COMP|
1327 INTEGER_PACK_FORCE_BIGNUM|
1328 INTEGER_PACK_NEGATIVE|
1329 INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
1330
1331 num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
1332
1333 assert(num_bdigits0 <= num_bdigits);
1334
1335 sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
1336
1337 if (num_bdigits0 < num_bdigits) {
1338 BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
1339 if (sign == -2) {
1340 bdigits[num_bdigits0] = 1;
1341 }
1342 }
1343}
1344
1345static int
1346bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int borrow)
1347{
1348 BDIGIT_DBL_SIGNED num;
1349 size_t i;
1350 size_t sn;
1351
1352 assert(xn <= zn);
1353 assert(yn <= zn);
1354
1355 sn = xn < yn ? xn : yn;
1356
1357 num = borrow ? -1 : 0;
1358 for (i = 0; i < sn; i++) {
1359 num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
1360 zds[i] = BIGLO(num);
1361 num = BIGDN(num);
1362 }
1363 if (yn <= xn) {
1364 for (; i < xn; i++) {
1365 if (num == 0) goto num_is_zero;
1366 num += xds[i];
1367 zds[i] = BIGLO(num);
1368 num = BIGDN(num);
1369 }
1370 }
1371 else {
1372 for (; i < yn; i++) {
1373 num -= yds[i];
1374 zds[i] = BIGLO(num);
1375 num = BIGDN(num);
1376 }
1377 }
1378 if (num == 0) goto num_is_zero;
1379 for (; i < zn; i++) {
1380 zds[i] = BDIGMAX;
1381 }
1382 return 1;
1383
1384 num_is_zero:
1385 if (xds == zds && xn == zn)
1386 return 0;
1387 for (; i < xn; i++) {
1388 zds[i] = xds[i];
1389 }
1390 for (; i < zn; i++) {
1391 zds[i] = 0;
1392 }
1393 return 0;
1394}
1395
1396static int
1397bary_sub(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1398{
1399 return bary_subb(zds, zn, xds, xn, yds, yn, 0);
1400}
1401
1402static int
1403bary_sub_one(BDIGIT *zds, size_t zn)
1404{
1405 return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
1406}
1407
1408static int
1409bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int carry)
1410{
1411 BDIGIT_DBL num;
1412 size_t i;
1413
1414 assert(xn <= zn);
1415 assert(yn <= zn);
1416
1417 if (xn > yn) {
1418 const BDIGIT *tds;
1419 tds = xds; xds = yds; yds = tds;
1420 i = xn; xn = yn; yn = i;
1421 }
1422
1423 num = carry ? 1 : 0;
1424 for (i = 0; i < xn; i++) {
1425 num += (BDIGIT_DBL)xds[i] + yds[i];
1426 zds[i] = BIGLO(num);
1427 num = BIGDN(num);
1428 }
1429 for (; i < yn; i++) {
1430 if (num == 0) goto num_is_zero;
1431 num += yds[i];
1432 zds[i] = BIGLO(num);
1433 num = BIGDN(num);
1434 }
1435 for (; i < zn; i++) {
1436 if (num == 0) goto num_is_zero;
1437 zds[i] = BIGLO(num);
1438 num = BIGDN(num);
1439 }
1440 return num != 0;
1441
1442 num_is_zero:
1443 if (yds == zds && yn == zn)
1444 return 0;
1445 for (; i < yn; i++) {
1446 zds[i] = yds[i];
1447 }
1448 for (; i < zn; i++) {
1449 zds[i] = 0;
1450 }
1451 return 0;
1452}
1453
1454static int
1455bary_add(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1456{
1457 return bary_addc(zds, zn, xds, xn, yds, yn, 0);
1458}
1459
1460static int
1461bary_add_one(BDIGIT *ds, size_t n)
1462{
1463 size_t i;
1464 for (i = 0; i < n; i++) {
1465 BDIGIT_DBL n = ds[i];
1466 n += 1;
1467 ds[i] = BIGLO(n);
1468 if (ds[i] != 0)
1469 return 0;
1470 }
1471 return 1;
1472}
1473
1474static void
1475bary_mul_single(BDIGIT *zds, size_t zn, BDIGIT x, BDIGIT y)
1476{
1477 BDIGIT_DBL n;
1478
1479 assert(2 <= zn);
1480
1481 n = (BDIGIT_DBL)x * y;
1482 bdigitdbl2bary(zds, 2, n);
1483 BDIGITS_ZERO(zds + 2, zn - 2);
1484}
1485
1486static int
1487bary_muladd_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1488{
1489 BDIGIT_DBL n;
1490 BDIGIT_DBL dd;
1491 size_t j;
1492
1493 assert(zn > yn);
1494
1495 if (x == 0)
1496 return 0;
1497 dd = x;
1498 n = 0;
1499 for (j = 0; j < yn; j++) {
1500 BDIGIT_DBL ee = n + dd * yds[j];
1501 if (ee) {
1502 n = zds[j] + ee;
1503 zds[j] = BIGLO(n);
1504 n = BIGDN(n);
1505 }
1506 else {
1507 n = 0;
1508 }
1509
1510 }
1511 for (; j < zn; j++) {
1512 if (n == 0)
1513 break;
1514 n += zds[j];
1515 zds[j] = BIGLO(n);
1516 n = BIGDN(n);
1517 }
1518 return n != 0;
1519}
1520
1521static BDIGIT_DBL_SIGNED
1522bigdivrem_mulsub(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1523{
1524 size_t i;
1525 BDIGIT_DBL t2;
1526 BDIGIT_DBL_SIGNED num;
1527
1528 assert(zn == yn + 1);
1529
1530 num = 0;
1531 t2 = 0;
1532 i = 0;
1533
1534 do {
1535 BDIGIT_DBL_SIGNED ee;
1536 t2 += (BDIGIT_DBL)yds[i] * x;
1537 ee = num - BIGLO(t2);
1538 num = (BDIGIT_DBL_SIGNED)zds[i] + ee;
1539 if (ee) zds[i] = BIGLO(num);
1540 num = BIGDN(num);
1541 t2 = BIGDN(t2);
1542 } while (++i < yn);
1543 num -= (BDIGIT_DBL_SIGNED)t2;
1544 num += (BDIGIT_DBL_SIGNED)zds[yn]; /* borrow from high digit; don't update */
1545 return num;
1546}
1547
1548static int
1549bary_mulsub_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
1550{
1551 BDIGIT_DBL_SIGNED num;
1552
1553 assert(zn == yn + 1);
1554
1555 num = bigdivrem_mulsub(zds, zn, x, yds, yn);
1556 zds[yn] = BIGLO(num);
1557 if (BIGDN(num))
1558 return 1;
1559 return 0;
1560}
1561
1562static void
1563bary_mul_normal(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
1564{
1565 size_t i;
1566
1567 assert(xn + yn <= zn);
1568
1569 BDIGITS_ZERO(zds, zn);
1570 for (i = 0; i < xn; i++) {
1571 bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
1572 }
1573}
1574
1575 VALUE
1576rb_big_mul_normal(VALUE x, VALUE y)
1577{
1578 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1579 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1580 bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
1581 RB_GC_GUARD(x);
1582 RB_GC_GUARD(y);
1583 return z;
1584}
1585
1586/* efficient squaring (2 times faster than normal multiplication)
1587 * ref: Handbook of Applied Cryptography, Algorithm 14.16
1588 * https://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
1589 */
1590static void
1591bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
1592{
1593 size_t i, j;
1594 BDIGIT_DBL c, v, w;
1595 BDIGIT vl;
1596 int vh;
1597
1598 assert(xn * 2 <= zn);
1599
1600 BDIGITS_ZERO(zds, zn);
1601
1602 if (xn == 0)
1603 return;
1604
1605 for (i = 0; i < xn-1; i++) {
1606 v = (BDIGIT_DBL)xds[i];
1607 if (!v)
1608 continue;
1609 c = (BDIGIT_DBL)zds[i + i] + v * v;
1610 zds[i + i] = BIGLO(c);
1611 c = BIGDN(c);
1612 v *= 2;
1613 vl = BIGLO(v);
1614 vh = (int)BIGDN(v);
1615 for (j = i + 1; j < xn; j++) {
1616 w = (BDIGIT_DBL)xds[j];
1617 c += (BDIGIT_DBL)zds[i + j] + vl * w;
1618 zds[i + j] = BIGLO(c);
1619 c = BIGDN(c);
1620 if (vh)
1621 c += w;
1622 }
1623 if (c) {
1624 c += (BDIGIT_DBL)zds[i + xn];
1625 zds[i + xn] = BIGLO(c);
1626 c = BIGDN(c);
1627 if (c)
1628 zds[i + xn + 1] += (BDIGIT)c;
1629 }
1630 }
1631
1632 /* i == xn-1 */
1633 v = (BDIGIT_DBL)xds[i];
1634 if (!v)
1635 return;
1636 c = (BDIGIT_DBL)zds[i + i] + v * v;
1637 zds[i + i] = BIGLO(c);
1638 c = BIGDN(c);
1639 if (c) {
1640 zds[i + xn] += BIGLO(c);
1641 }
1642}
1643
1644 VALUE
1645rb_big_sq_fast(VALUE x)
1646{
1647 size_t xn = BIGNUM_LEN(x), zn = 2 * xn;
1648 VALUE z = bignew(zn, 1);
1649 bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
1650 RB_GC_GUARD(x);
1651 return z;
1652}
1653
1654static inline size_t
1655max_size(size_t a, size_t b)
1656{
1657 return (a > b ? a : b);
1658}
1659
1660/* balancing multiplication by slicing larger argument */
1661static void
1662bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn,
1663 const BDIGIT *const xds, const size_t xn,
1664 const BDIGIT *const yds, const size_t yn,
1665 BDIGIT *wds, size_t wn, mulfunc_t *const mulfunc)
1666{
1667 VALUE work = 0;
1668 size_t n;
1669
1670 assert(xn + yn <= zn);
1671 assert(xn <= yn);
1672 assert(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
1673
1674 BDIGITS_ZERO(zds, xn);
1675
1676 if (wn < xn) {
1677 /* The condition when a new buffer is needed:
1678 * 1. (2(xn+r) > zn-(yn-r)) => (2xn+r > zn-yn), at the last
1679 * iteration (or r == 0)
1680 * 2. (2(xn+xn) > zn-(yn-r-xn)) => (3xn-r > zn-yn), at the
1681 * previous iteration.
1682 */
1683 const size_t r = yn % xn;
1684 if (2*xn + yn + max_size(xn-r, r) > zn) {
1685 wn = xn;
1686 wds = ALLOCV_N(BDIGIT, work, wn);
1687 }
1688 }
1689
1690 n = 0;
1691 while (yn > n) {
1692 const size_t r = (xn > (yn - n) ? (yn - n) : xn);
1693 const size_t tn = (xn + r);
1694 if (2 * (xn + r) <= zn - n) {
1695 BDIGIT *const tds = zds + n + xn + r;
1696 mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
1697 BDIGITS_ZERO(zds + n + xn, r);
1698 bary_add(zds + n, tn,
1699 zds + n, tn,
1700 tds, tn);
1701 }
1702 else {
1703 BDIGIT *const tds = zds + n;
1704 if (wn < xn) {
1705 /* xn is invariant, only once here */
1706#if 0
1707 wn = xn;
1708 wds = ALLOCV_N(BDIGIT, work, wn);
1709#else
1710 rb_bug("wds is not enough: %" PRIdSIZE " for %" PRIdSIZE, wn, xn);
1711#endif
1712 }
1713 MEMCPY(wds, zds + n, BDIGIT, xn);
1714 mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
1715 bary_add(zds + n, tn,
1716 zds + n, tn,
1717 wds, xn);
1718 }
1719 n += r;
1720 }
1721 BDIGITS_ZERO(zds+xn+yn, zn - (xn+yn));
1722
1723 if (work)
1724 ALLOCV_END(work);
1725}
1726
1727 VALUE
1728rb_big_mul_balance(VALUE x, VALUE y)
1729{
1730 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1731 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1732 bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
1733 RB_GC_GUARD(x);
1734 RB_GC_GUARD(y);
1735 return z;
1736}
1737
1738/* multiplication by karatsuba method */
1739static void
1740bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
1741{
1742 VALUE work = 0;
1743
1744 size_t n;
1745 int sub_p, borrow, carry1, carry2, carry3;
1746
1747 int odd_y = 0;
1748 int odd_xy = 0;
1749 int sq;
1750
1751 const BDIGIT *xds0, *xds1, *yds0, *yds1;
1752 BDIGIT *zds0, *zds1, *zds2, *zds3;
1753
1754 assert(xn + yn <= zn);
1755 assert(xn <= yn);
1756 assert(yn < 2 * xn);
1757
1758 sq = xds == yds && xn == yn;
1759
1760 if (yn & 1) {
1761 odd_y = 1;
1762 yn--;
1763 if (yn < xn) {
1764 odd_xy = 1;
1765 xn--;
1766 }
1767 }
1768
1769 n = yn / 2;
1770
1771 assert(n < xn);
1772
1773 if (wn < n) {
1774 /* This function itself needs only n BDIGITs for work area.
1775 * However this function calls bary_mul_karatsuba and
1776 * bary_mul_balance recursively.
1777 * 2n BDIGITs are enough to avoid allocations in
1778 * the recursively called functions.
1779 */
1780 wn = 2*n;
1781 wds = ALLOCV_N(BDIGIT, work, wn);
1782 }
1783
1784 /* Karatsuba algorithm:
1785 *
1786 * x = x0 + r*x1
1787 * y = y0 + r*y1
1788 * z = x*y
1789 * = (x0 + r*x1) * (y0 + r*y1)
1790 * = x0*y0 + r*(x1*y0 + x0*y1) + r*r*x1*y1
1791 * = x0*y0 + r*(x0*y0 + x1*y1 - (x1-x0)*(y1-y0)) + r*r*x1*y1
1792 * = x0*y0 + r*(x0*y0 + x1*y1 - (x0-x1)*(y0-y1)) + r*r*x1*y1
1793 */
1794
1795 xds0 = xds;
1796 xds1 = xds + n;
1797 yds0 = yds;
1798 yds1 = yds + n;
1799 zds0 = zds;
1800 zds1 = zds + n;
1801 zds2 = zds + 2*n;
1802 zds3 = zds + 3*n;
1803
1804 sub_p = 1;
1805
1806 /* zds0:? zds1:? zds2:? zds3:? wds:? */
1807
1808 if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
1809 bary_2comp(zds0, n);
1810 sub_p = !sub_p;
1811 }
1812
1813 /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:? */
1814
1815 if (sq) {
1816 sub_p = 1;
1817 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
1818 }
1819 else {
1820 if (bary_sub(wds, n, yds, n, yds+n, n)) {
1821 bary_2comp(wds, n);
1822 sub_p = !sub_p;
1823 }
1824
1825 /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:|y1-y0| */
1826
1827 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
1828 }
1829
1830 /* zds0:|x1-x0| zds1,zds2:|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
1831
1832 borrow = 0;
1833 if (sub_p) {
1834 borrow = !bary_2comp(zds1, 2*n);
1835 }
1836 /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
1837
1838 MEMCPY(wds, zds1, BDIGIT, n);
1839
1840 /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
1841
1842 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
1843
1844 /* zds0,zds1:x0*y0 zds2:hi(-?|x1-x0|*|y1-y0|) zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
1845
1846 carry1 = bary_add(wds, n, wds, n, zds0, n);
1847 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
1848
1849 /* zds0,zds1:x0*y0 zds2:hi(x0*y0-?|x1-x0|*|y1-y0|) zds3:? wds:lo(x0*y0-?|x1-x0|*|y1-y0|) */
1850
1851 carry2 = bary_add(zds1, n, zds1, n, wds, n);
1852
1853 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2:hi(x0*y0-?|x1-x0|*|y1-y0|) zds3:? wds:lo(x0*y0-?|x1-x0|*|y1-y0|) */
1854
1855 MEMCPY(wds, zds2, BDIGIT, n);
1856
1857 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2:_ zds3:? wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1858
1859 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
1860
1861 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|) zds2,zds3:x1*y1 wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1862
1863 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
1864
1865 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1 wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1866
1867 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
1868
1869 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1+hi(x1*y1) wds:hi(x0*y0-?|x1-x0|*|y1-y0|) */
1870
1871 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
1872
1873 /* zds0:lo(x0*y0) zds1:hi(x0*y0)+lo(x0*y0-?|x1-x0|*|y1-y0|)+lo(x1*y1) zds2,zds3:x1*y1+hi(x1*y1)+hi(x0*y0-?|x1-x0|*|y1-y0|) wds:_ */
1874
1875 if (carry2)
1876 bary_add_one(zds2, zn-2*n);
1877
1878 if (carry1 + carry3 - borrow < 0)
1879 bary_sub_one(zds3, zn-3*n);
1880 else if (carry1 + carry3 - borrow > 0) {
1881 BDIGIT c = carry1 + carry3 - borrow;
1882 bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
1883 }
1884
1885 /*
1886 if (SIZEOF_BDIGIT * zn <= 16) {
1887 uint128_t z, x, y;
1888 ssize_t i;
1889 for (x = 0, i = xn-1; 0 <= i; i--) { x <<= SIZEOF_BDIGIT*CHAR_BIT; x |= xds[i]; }
1890 for (y = 0, i = yn-1; 0 <= i; i--) { y <<= SIZEOF_BDIGIT*CHAR_BIT; y |= yds[i]; }
1891 for (z = 0, i = zn-1; 0 <= i; i--) { z <<= SIZEOF_BDIGIT*CHAR_BIT; z |= zds[i]; }
1892 assert(z == x * y);
1893 }
1894 */
1895
1896 if (odd_xy) {
1897 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1898 bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
1899 }
1900 else if (odd_y) {
1901 bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
1902 }
1903
1904 if (work)
1905 ALLOCV_END(work);
1906}
1907
1908 VALUE
1909rb_big_mul_karatsuba(VALUE x, VALUE y)
1910{
1911 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
1912 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
1913 if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
1914 rb_raise(rb_eArgError, "unexpected bignum length for karatsuba");
1915 bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
1916 RB_GC_GUARD(x);
1917 RB_GC_GUARD(y);
1918 return z;
1919}
1920
1921static void
1922bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
1923{
1924 size_t n;
1925 size_t wnc;
1926 VALUE work = 0;
1927
1928 /* "p" stands for "positive". Actually it means "non-negative", though. */
1929 size_t x0n; const BDIGIT *x0ds;
1930 size_t x1n; const BDIGIT *x1ds;
1931 size_t x2n; const BDIGIT *x2ds;
1932 size_t y0n; const BDIGIT *y0ds;
1933 size_t y1n; const BDIGIT *y1ds;
1934 size_t y2n; const BDIGIT *y2ds;
1935
1936 size_t u1n; BDIGIT *u1ds; int u1p;
1937 size_t u2n; BDIGIT *u2ds; int u2p;
1938 size_t u3n; BDIGIT *u3ds; int u3p;
1939
1940 size_t v1n; BDIGIT *v1ds; int v1p;
1941 size_t v2n; BDIGIT *v2ds; int v2p;
1942 size_t v3n; BDIGIT *v3ds; int v3p;
1943
1944 size_t t0n; BDIGIT *t0ds; int t0p;
1945 size_t t1n; BDIGIT *t1ds; int t1p;
1946 size_t t2n; BDIGIT *t2ds; int t2p;
1947 size_t t3n; BDIGIT *t3ds; int t3p;
1948 size_t t4n; BDIGIT *t4ds; int t4p;
1949
1950 size_t z0n; BDIGIT *z0ds;
1951 size_t z1n; BDIGIT *z1ds; int z1p;
1952 size_t z2n; BDIGIT *z2ds; int z2p;
1953 size_t z3n; BDIGIT *z3ds; int z3p;
1954 size_t z4n; BDIGIT *z4ds;
1955
1956 size_t zzn; BDIGIT *zzds;
1957
1958 int sq = xds == yds && xn == yn;
1959
1960 assert(xn <= yn); /* assume y >= x */
1961 assert(xn + yn <= zn);
1962
1963 n = (yn + 2) / 3;
1964 assert(2*n < xn);
1965
1966 wnc = 0;
1967
1968 wnc += (u1n = n+1); /* BITSPERDIG*n+2 bits */
1969 wnc += (u2n = n+1); /* BITSPERDIG*n+1 bits */
1970 wnc += (u3n = n+1); /* BITSPERDIG*n+3 bits */
1971 wnc += (v1n = n+1); /* BITSPERDIG*n+2 bits */
1972 wnc += (v2n = n+1); /* BITSPERDIG*n+1 bits */
1973 wnc += (v3n = n+1); /* BITSPERDIG*n+3 bits */
1974
1975 wnc += (t0n = 2*n); /* BITSPERDIG*2*n bits */
1976 wnc += (t1n = 2*n+2); /* BITSPERDIG*2*n+4 bits but bary_mul needs u1n+v1n */
1977 wnc += (t2n = 2*n+2); /* BITSPERDIG*2*n+2 bits but bary_mul needs u2n+v2n */
1978 wnc += (t3n = 2*n+2); /* BITSPERDIG*2*n+6 bits but bary_mul needs u3n+v3n */
1979 wnc += (t4n = 2*n); /* BITSPERDIG*2*n bits */
1980
1981 wnc += (z1n = 2*n+1); /* BITSPERDIG*2*n+5 bits */
1982 wnc += (z2n = 2*n+1); /* BITSPERDIG*2*n+6 bits */
1983 wnc += (z3n = 2*n+1); /* BITSPERDIG*2*n+8 bits */
1984
1985 if (wn < wnc) {
1986 wn = wnc * 3 / 2; /* Allocate working memory for whole recursion at once. */
1987 wds = ALLOCV_N(BDIGIT, work, wn);
1988 }
1989
1990 u1ds = wds; wds += u1n;
1991 u2ds = wds; wds += u2n;
1992 u3ds = wds; wds += u3n;
1993
1994 v1ds = wds; wds += v1n;
1995 v2ds = wds; wds += v2n;
1996 v3ds = wds; wds += v3n;
1997
1998 t0ds = wds; wds += t0n;
1999 t1ds = wds; wds += t1n;
2000 t2ds = wds; wds += t2n;
2001 t3ds = wds; wds += t3n;
2002 t4ds = wds; wds += t4n;
2003
2004 z1ds = wds; wds += z1n;
2005 z2ds = wds; wds += z2n;
2006 z3ds = wds; wds += z3n;
2007
2008 wn -= wnc;
2009
2010 zzds = u1ds;
2011 zzn = 6*n+1;
2012
2013 x0n = n;
2014 x1n = n;
2015 x2n = xn - 2*n;
2016 x0ds = xds;
2017 x1ds = xds + n;
2018 x2ds = xds + 2*n;
2019
2020 if (sq) {
2021 y0n = x0n;
2022 y1n = x1n;
2023 y2n = x2n;
2024 y0ds = x0ds;
2025 y1ds = x1ds;
2026 y2ds = x2ds;
2027 }
2028 else {
2029 y0n = n;
2030 y1n = n;
2031 y2n = yn - 2*n;
2032 y0ds = yds;
2033 y1ds = yds + n;
2034 y2ds = yds + 2*n;
2035 }
2036
2037 /*
2038 * ref. https://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
2039 *
2040 * x(b) = x0 * b^0 + x1 * b^1 + x2 * b^2
2041 * y(b) = y0 * b^0 + y1 * b^1 + y2 * b^2
2042 *
2043 * z(b) = x(b) * y(b)
2044 * z(b) = z0 * b^0 + z1 * b^1 + z2 * b^2 + z3 * b^3 + z4 * b^4
2045 * where:
2046 * z0 = x0 * y0
2047 * z1 = x0 * y1 + x1 * y0
2048 * z2 = x0 * y2 + x1 * y1 + x2 * y0
2049 * z3 = x1 * y2 + x2 * y1
2050 * z4 = x2 * y2
2051 *
2052 * Toom3 method (a.k.a. Toom-Cook method):
2053 * (Step1) calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4),
2054 * where:
2055 * b0 = 0, b1 = 1, b2 = -1, b3 = -2, b4 = inf,
2056 * z(0) = x(0) * y(0) = x0 * y0
2057 * z(1) = x(1) * y(1) = (x0 + x1 + x2) * (y0 + y1 + y2)
2058 * z(-1) = x(-1) * y(-1) = (x0 - x1 + x2) * (y0 - y1 + y2)
2059 * z(-2) = x(-2) * y(-2) = (x0 - 2 * (x1 - 2 * x2)) * (y0 - 2 * (y1 - 2 * y2))
2060 * z(inf) = x(inf) * y(inf) = x2 * y2
2061 *
2062 * (Step2) interpolating z0, z1, z2, z3 and z4.
2063 *
2064 * (Step3) Substituting base value into b of the polynomial z(b),
2065 */
2066
2067 /*
2068 * [Step1] calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4)
2069 */
2070
2071 /* u1 <- x0 + x2 */
2072 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
2073 u1p = 1;
2074
2075 /* x(-1) : u2 <- u1 - x1 = x0 - x1 + x2 */
2076 if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
2077 bary_2comp(u2ds, u2n);
2078 u2p = 0;
2079 }
2080 else {
2081 u2p = 1;
2082 }
2083
2084 /* x(1) : u1 <- u1 + x1 = x0 + x1 + x2 */
2085 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
2086
2087 /* x(-2) : u3 <- 2 * (u2 + x2) - x0 = x0 - 2 * (x1 - 2 * x2) */
2088 u3p = 1;
2089 if (u2p) {
2090 bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
2091 }
2092 else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
2093 bary_2comp(u3ds, u3n);
2094 u3p = 0;
2095 }
2096 bary_small_lshift(u3ds, u3ds, u3n, 1);
2097 if (!u3p) {
2098 bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
2099 }
2100 else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
2101 bary_2comp(u3ds, u3n);
2102 u3p = 0;
2103 }
2104
2105 if (sq) {
2106 v1n = u1n; v1ds = u1ds; v1p = u1p;
2107 v2n = u2n; v2ds = u2ds; v2p = u2p;
2108 v3n = u3n; v3ds = u3ds; v3p = u3p;
2109 }
2110 else {
2111 /* v1 <- y0 + y2 */
2112 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
2113 v1p = 1;
2114
2115 /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
2116 v2p = 1;
2117 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
2118 bary_2comp(v2ds, v2n);
2119 v2p = 0;
2120 }
2121
2122 /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
2123 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
2124
2125 /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
2126 v3p = 1;
2127 if (v2p) {
2128 bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
2129 }
2130 else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
2131 bary_2comp(v3ds, v3n);
2132 v3p = 0;
2133 }
2134 bary_small_lshift(v3ds, v3ds, v3n, 1);
2135 if (!v3p) {
2136 bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
2137 }
2138 else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
2139 bary_2comp(v3ds, v3n);
2140 v3p = 0;
2141 }
2142 }
2143
2144 /* z(0) : t0 <- x0 * y0 */
2145 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
2146 t0p = 1;
2147
2148 /* z(1) : t1 <- u1 * v1 */
2149 bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
2150 t1p = u1p == v1p;
2151 assert(t1ds[t1n-1] == 0);
2152 t1n--;
2153
2154 /* z(-1) : t2 <- u2 * v2 */
2155 bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
2156 t2p = u2p == v2p;
2157 assert(t2ds[t2n-1] == 0);
2158 t2n--;
2159
2160 /* z(-2) : t3 <- u3 * v3 */
2161 bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
2162 t3p = u3p == v3p;
2163 assert(t3ds[t3n-1] == 0);
2164 t3n--;
2165
2166 /* z(inf) : t4 <- x2 * y2 */
2167 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
2168 t4p = 1;
2169
2170 /*
2171 * [Step2] interpolating z0, z1, z2, z3 and z4.
2172 */
2173
2174 /* z0 <- z(0) == t0 */
2175 z0n = t0n; z0ds = t0ds;
2176
2177 /* z4 <- z(inf) == t4 */
2178 z4n = t4n; z4ds = t4ds;
2179
2180 /* z3 <- (z(-2) - z(1)) / 3 == (t3 - t1) / 3 */
2181 if (t3p == t1p) {
2182 z3p = t3p;
2183 if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
2184 bary_2comp(z3ds, z3n);
2185 z3p = !z3p;
2186 }
2187 }
2188 else {
2189 z3p = t3p;
2190 bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
2191 }
2192 bigdivrem_single(z3ds, z3ds, z3n, 3);
2193
2194 /* z1 <- (z(1) - z(-1)) / 2 == (t1 - t2) / 2 */
2195 if (t1p == t2p) {
2196 z1p = t1p;
2197 if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
2198 bary_2comp(z1ds, z1n);
2199 z1p = !z1p;
2200 }
2201 }
2202 else {
2203 z1p = t1p;
2204 bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
2205 }
2206 bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
2207
2208 /* z2 <- z(-1) - z(0) == t2 - t0 */
2209 if (t2p == t0p) {
2210 z2p = t2p;
2211 if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
2212 bary_2comp(z2ds, z2n);
2213 z2p = !z2p;
2214 }
2215 }
2216 else {
2217 z2p = t2p;
2218 bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
2219 }
2220
2221 /* z3 <- (z2 - z3) / 2 + 2 * z(inf) == (z2 - z3) / 2 + 2 * t4 */
2222 if (z2p == z3p) {
2223 z3p = z2p;
2224 if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
2225 bary_2comp(z3ds, z3n);
2226 z3p = !z3p;
2227 }
2228 }
2229 else {
2230 z3p = z2p;
2231 bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
2232 }
2233 bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
2234 if (z3p == t4p) {
2235 bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
2236 }
2237 else {
2238 if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
2239 bary_2comp(z3ds, z3n);
2240 z3p = !z3p;
2241 }
2242 }
2243
2244 /* z2 <- z2 + z1 - z(inf) == z2 + z1 - t4 */
2245 if (z2p == z1p) {
2246 bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
2247 }
2248 else {
2249 if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
2250 bary_2comp(z2ds, z2n);
2251 z2p = !z2p;
2252 }
2253 }
2254
2255 if (z2p == t4p) {
2256 if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
2257 bary_2comp(z2ds, z2n);
2258 z2p = !z2p;
2259 }
2260 }
2261 else {
2262 bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
2263 }
2264
2265 /* z1 <- z1 - z3 */
2266 if (z1p == z3p) {
2267 if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
2268 bary_2comp(z1ds, z1n);
2269 z1p = !z1p;
2270 }
2271 }
2272 else {
2273 bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
2274 }
2275
2276 /*
2277 * [Step3] Substituting base value into b of the polynomial z(b),
2278 */
2279
2280 MEMCPY(zzds, z0ds, BDIGIT, z0n);
2281 BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
2282 MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
2283 BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
2284 if (z1p)
2285 bary_add(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2286 else
2287 bary_sub(zzds + n, zzn - n, zzds + n, zzn - n, z1ds, z1n);
2288 if (z2p)
2289 bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2290 else
2291 bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
2292 if (z3p)
2293 bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2294 else
2295 bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
2296
2297 BARY_TRUNC(zzds, zzn);
2298 MEMCPY(zds, zzds, BDIGIT, zzn);
2299 BDIGITS_ZERO(zds + zzn, zn - zzn);
2300
2301 if (work)
2302 ALLOCV_END(work);
2303}
2304
2305 VALUE
2306rb_big_mul_toom3(VALUE x, VALUE y)
2307{
2308 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2309 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2310 if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
2311 rb_raise(rb_eArgError, "unexpected bignum length for toom3");
2312 bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
2313 RB_GC_GUARD(x);
2314 RB_GC_GUARD(y);
2315 return z;
2316}
2317
2318#if USE_GMP
2319static inline void
2320bdigits_to_mpz(mpz_t mp, const BDIGIT *digits, size_t len)
2321{
2322 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2323 mpz_import(mp, len, -1, sizeof(BDIGIT), 0, nails, digits);
2324}
2325
2326static inline void
2327bdigits_from_mpz(mpz_t mp, BDIGIT *digits, size_t *len)
2328{
2329 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
2330 mpz_export(digits, len, -1, sizeof(BDIGIT), 0, nails, mp);
2331}
2332
2333static void
2334bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2335{
2336 mpz_t x, y, z;
2337 size_t count;
2338
2339 assert(xn + yn <= zn);
2340
2341 mpz_init(x);
2342 mpz_init(y);
2343 mpz_init(z);
2344 bdigits_to_mpz(x, xds, xn);
2345 if (xds == yds && xn == yn) {
2346 mpz_mul(z, x, x);
2347 }
2348 else {
2349 bdigits_to_mpz(y, yds, yn);
2350 mpz_mul(z, x, y);
2351 }
2352 bdigits_from_mpz(z, zds, &count);
2353 BDIGITS_ZERO(zds+count, zn-count);
2354 mpz_clear(x);
2355 mpz_clear(y);
2356 mpz_clear(z);
2357}
2358
2359 VALUE
2360rb_big_mul_gmp(VALUE x, VALUE y)
2361{
2362 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), zn = xn + yn;
2363 VALUE z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2364 bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
2365 RB_GC_GUARD(x);
2366 RB_GC_GUARD(y);
2367 return z;
2368}
2369#endif
2370
2371static void
2372bary_short_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2373{
2374 assert(xn + yn <= zn);
2375
2376 if (xn == 1 && yn == 1) {
2377 bary_mul_single(zds, zn, xds[0], yds[0]);
2378 }
2379 else {
2380 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2381 rb_thread_check_ints();
2382 }
2383}
2384
2385/* determine whether a bignum is sparse or not by random sampling */
2386static inline int
2387bary_sparse_p(const BDIGIT *ds, size_t n)
2388{
2389 long c = 0;
2390
2391 if ( ds[2 * n / 5]) c++;
2392 if (c <= 1 && ds[ n / 2]) c++;
2393 if (c <= 1 && ds[3 * n / 5]) c++;
2394
2395 return (c <= 1) ? 1 : 0;
2396}
2397
2398static int
2399bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp, const BDIGIT **ydsp, size_t *ynp)
2400{
2401 size_t nlsz; /* number of least significant zero BDIGITs */
2402
2403 BDIGIT *zds = *zdsp;
2404 size_t zn = *znp;
2405 const BDIGIT *xds = *xdsp;
2406 size_t xn = *xnp;
2407 const BDIGIT *yds = *ydsp;
2408 size_t yn = *ynp;
2409
2410 assert(xn + yn <= zn);
2411
2412 nlsz = 0;
2413
2414 while (0 < xn) {
2415 if (xds[xn-1] == 0) {
2416 xn--;
2417 }
2418 else {
2419 do {
2420 if (xds[0] != 0)
2421 break;
2422 xds++;
2423 xn--;
2424 nlsz++;
2425 } while (0 < xn);
2426 break;
2427 }
2428 }
2429
2430 while (0 < yn) {
2431 if (yds[yn-1] == 0) {
2432 yn--;
2433 }
2434 else {
2435 do {
2436 if (yds[0] != 0)
2437 break;
2438 yds++;
2439 yn--;
2440 nlsz++;
2441 } while (0 < yn);
2442 break;
2443 }
2444 }
2445
2446 if (nlsz) {
2447 BDIGITS_ZERO(zds, nlsz);
2448 zds += nlsz;
2449 zn -= nlsz;
2450 }
2451
2452 /* make sure that y is longer than x */
2453 if (xn > yn) {
2454 const BDIGIT *tds;
2455 size_t tn;
2456 tds = xds; xds = yds; yds = tds;
2457 tn = xn; xn = yn; yn = tn;
2458 }
2459 assert(xn <= yn);
2460
2461 if (xn <= 1) {
2462 if (xn == 0) {
2463 BDIGITS_ZERO(zds, zn);
2464 return 1;
2465 }
2466
2467 if (xds[0] == 1) {
2468 MEMCPY(zds, yds, BDIGIT, yn);
2469 BDIGITS_ZERO(zds+yn, zn-yn);
2470 return 1;
2471 }
2472 if (POW2_P(xds[0])) {
2473 zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
2474 BDIGITS_ZERO(zds+yn+1, zn-yn-1);
2475 return 1;
2476 }
2477 if (yn == 1 && yds[0] == 1) {
2478 zds[0] = xds[0];
2479 BDIGITS_ZERO(zds+1, zn-1);
2480 return 1;
2481 }
2482 bary_mul_normal(zds, zn, xds, xn, yds, yn);
2483 return 1;
2484 }
2485
2486 *zdsp = zds;
2487 *znp = zn;
2488 *xdsp = xds;
2489 *xnp = xn;
2490 *ydsp = yds;
2491 *ynp = yn;
2492
2493 return 0;
2494}
2495
2496static void
2497bary_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)
2498{
2499 /* normal multiplication when x is small */
2500 if (xn < KARATSUBA_MUL_DIGITS) {
2501 goto normal;
2502 }
2503
2504 /* normal multiplication when x or y is a sparse bignum */
2505 if (bary_sparse_p(xds, xn)) goto normal;
2506 if (bary_sparse_p(yds, yn)) {
2507 bary_short_mul(zds, zn, yds, yn, xds, xn);
2508 return;
2509 }
2510
2511 /* balance multiplication by slicing y when x is much smaller than y */
2512 if (!KARATSUBA_BALANCED(xn, yn)) {
2513 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
2514 return;
2515 }
2516
2517 /* multiplication by karatsuba method */
2518 bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
2519 return;
2520
2521 normal:
2522 if (xds == yds && xn == yn) {
2523 bary_sq_fast(zds, zn, xds, xn);
2524 }
2525 else {
2526 bary_short_mul(zds, zn, xds, xn, yds, yn);
2527 }
2528}
2529
2530static void
2531bary_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)
2532{
2533 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2534 return;
2535
2536 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2537}
2538
2539static void
2540bary_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)
2541{
2542 if (xn < TOOM3_MUL_DIGITS) {
2543 bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2544 return;
2545 }
2546
2547 if (!TOOM3_BALANCED(xn, yn)) {
2548 bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
2549 return;
2550 }
2551
2552 bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
2553}
2554
2555static void
2556bary_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)
2557{
2558 if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
2559 return;
2560
2561 bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
2562}
2563
2564static void
2565bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2566{
2567 if (xn <= yn) {
2568 if (xn < NAIVE_MUL_DIGITS) {
2569 if (xds == yds && xn == yn)
2570 bary_sq_fast(zds, zn, xds, xn);
2571 else
2572 bary_short_mul(zds, zn, xds, xn, yds, yn);
2573 return;
2574 }
2575 }
2576 else {
2577 if (yn < NAIVE_MUL_DIGITS) {
2578 bary_short_mul(zds, zn, yds, yn, xds, xn);
2579 return;
2580 }
2581 }
2582
2583#if USE_GMP
2584 bary_mul_gmp(zds, zn, xds, xn, yds, yn);
2585#else
2586 bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
2587#endif
2588}
2589
2590 struct big_div_struct {
2591 size_t yn, zn;
2592 BDIGIT *yds, *zds;
2593 volatile VALUE stop;
2594};
2595
2596static void *
2597bigdivrem1(void *ptr)
2598{
2599 struct big_div_struct *bds = (struct big_div_struct*)ptr;
2600 size_t yn = bds->yn;
2601 size_t zn = bds->zn;
2602 BDIGIT *yds = bds->yds, *zds = bds->zds;
2603 BDIGIT_DBL_SIGNED num;
2604 BDIGIT q;
2605
2606 do {
2607 if (bds->stop) {
2608 bds->zn = zn;
2609 return 0;
2610 }
2611 if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
2612 else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
2613 if (q) {
2614 num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
2615 q,
2616 yds, yn);
2617 while (num) { /* "add back" required */
2618 q--;
2619 num = bary_add(zds+zn-(yn+1), yn,
2620 zds+zn-(yn+1), yn,
2621 yds, yn);
2622 num--;
2623 }
2624 }
2625 zn--;
2626 zds[zn] = q;
2627 } while (zn > yn);
2628 return 0;
2629}
2630
2631/* async-signal-safe */
2632static void
2633rb_big_stop(void *ptr)
2634{
2635 struct big_div_struct *bds = ptr;
2636 bds->stop = Qtrue;
2637}
2638
2639static BDIGIT
2640bigdivrem_single1(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
2641{
2642 assert(0 < xn);
2643 assert(x_higher_bdigit < y);
2644 if (POW2_P(y)) {
2645 BDIGIT r;
2646 r = xds[0] & (y-1);
2647 bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
2648 return r;
2649 }
2650 else {
2651 size_t i;
2652 BDIGIT_DBL t2;
2653 t2 = x_higher_bdigit;
2654 for (i = 0; i < xn; i++) {
2655 t2 = BIGUP(t2) + xds[xn - i - 1];
2656 qds[xn - i - 1] = (BDIGIT)(t2 / y);
2657 t2 %= y;
2658 }
2659 return (BDIGIT)t2;
2660 }
2661}
2662
2663static BDIGIT
2664bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y)
2665{
2666 return bigdivrem_single1(qds, xds, xn, 0, y);
2667}
2668
2669static void
2670bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
2671{
2672 struct big_div_struct bds;
2673 size_t ynzero;
2674
2675 assert(yn < zn);
2676 assert(BDIGIT_MSB(yds[yn-1]));
2677 assert(zds[zn-1] < yds[yn-1]);
2678
2679 for (ynzero = 0; !yds[ynzero]; ynzero++);
2680
2681 if (ynzero+1 == yn) {
2682 BDIGIT r;
2683 r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
2684 zds[ynzero] = r;
2685 return;
2686 }
2687
2688 bds.yn = yn - ynzero;
2689 bds.zds = zds + ynzero;
2690 bds.yds = yds + ynzero;
2691 bds.stop = Qfalse;
2692 bds.zn = zn - ynzero;
2693 if (bds.zn > 10000 || bds.yn > 10000) {
2694 retry:
2695 bds.stop = Qfalse;
2696 rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE);
2697
2698 if (bds.stop == Qtrue) {
2699 /* execute trap handler, but exception was not raised. */
2700 goto retry;
2701 }
2702 }
2703 else {
2704 bigdivrem1(&bds);
2705 }
2706}
2707
2708static void
2709bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2710{
2711 int shift;
2712 BDIGIT *zds, *yyds;
2713 size_t zn;
2714 VALUE tmpyz = 0;
2715
2716 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2717 assert(qds ? (xn - yn + 1) <= qn : 1);
2718 assert(rds ? yn <= rn : 1);
2719
2720 zn = xn + BIGDIVREM_EXTRA_WORDS;
2721
2722 shift = nlz(yds[yn-1]);
2723 if (shift) {
2724 int alloc_y = !rds;
2725 int alloc_z = !qds || qn < zn;
2726 if (alloc_y && alloc_z) {
2727 yyds = ALLOCV_N(BDIGIT, tmpyz, yn+zn);
2728 zds = yyds + yn;
2729 }
2730 else {
2731 yyds = alloc_y ? ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
2732 zds = alloc_z ? ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
2733 }
2734 zds[xn] = bary_small_lshift(zds, xds, xn, shift);
2735 bary_small_lshift(yyds, yds, yn, shift);
2736 }
2737 else {
2738 if (qds && zn <= qn)
2739 zds = qds;
2740 else
2741 zds = ALLOCV_N(BDIGIT, tmpyz, zn);
2742 MEMCPY(zds, xds, BDIGIT, xn);
2743 zds[xn] = 0;
2744 /* bigdivrem_restoring will not modify y.
2745 * So use yds directly. */
2746 yyds = (BDIGIT *)yds;
2747 }
2748
2749 bigdivrem_restoring(zds, zn, yyds, yn);
2750
2751 if (rds) {
2752 if (shift)
2753 bary_small_rshift(rds, zds, yn, shift, 0);
2754 else
2755 MEMCPY(rds, zds, BDIGIT, yn);
2756 BDIGITS_ZERO(rds+yn, rn-yn);
2757 }
2758
2759 if (qds) {
2760 size_t j = zn - yn;
2761 MEMMOVE(qds, zds+yn, BDIGIT, j);
2762 BDIGITS_ZERO(qds+j, qn-j);
2763 }
2764
2765 if (tmpyz)
2766 ALLOCV_END(tmpyz);
2767}
2768
2769 VALUE
2770rb_big_divrem_normal(VALUE x, VALUE y)
2771{
2772 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2773 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2774 VALUE q, r;
2775
2776 BARY_TRUNC(yds, yn);
2777 if (yn == 0)
2778 rb_num_zerodiv();
2779 BARY_TRUNC(xds, xn);
2780
2781 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2782 return rb_assoc_new(LONG2FIX(0), x);
2783
2784 qn = xn + BIGDIVREM_EXTRA_WORDS;
2785 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2786 qds = BDIGITS(q);
2787
2788 rn = yn;
2789 r = bignew(rn, BIGNUM_SIGN(x));
2790 rds = BDIGITS(r);
2791
2792 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2793
2794 bigtrunc(q);
2795 bigtrunc(r);
2796
2797 RB_GC_GUARD(x);
2798 RB_GC_GUARD(y);
2799
2800 return rb_assoc_new(q, r);
2801}
2802
2803#if USE_GMP
2804static void
2805bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2806{
2807 mpz_t x, y, q, r;
2808 size_t count;
2809
2810 assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
2811 assert(qds ? (xn - yn + 1) <= qn : 1);
2812 assert(rds ? yn <= rn : 1);
2813 assert(qds || rds);
2814
2815 mpz_init(x);
2816 mpz_init(y);
2817 if (qds) mpz_init(q);
2818 if (rds) mpz_init(r);
2819
2820 bdigits_to_mpz(x, xds, xn);
2821 bdigits_to_mpz(y, yds, yn);
2822
2823 if (!rds) {
2824 mpz_fdiv_q(q, x, y);
2825 }
2826 else if (!qds) {
2827 mpz_fdiv_r(r, x, y);
2828 }
2829 else {
2830 mpz_fdiv_qr(q, r, x, y);
2831 }
2832
2833 mpz_clear(x);
2834 mpz_clear(y);
2835
2836 if (qds) {
2837 bdigits_from_mpz(q, qds, &count);
2838 BDIGITS_ZERO(qds+count, qn-count);
2839 mpz_clear(q);
2840 }
2841
2842 if (rds) {
2843 bdigits_from_mpz(r, rds, &count);
2844 BDIGITS_ZERO(rds+count, rn-count);
2845 mpz_clear(r);
2846 }
2847}
2848
2849 VALUE
2850rb_big_divrem_gmp(VALUE x, VALUE y)
2851{
2852 size_t xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y), qn, rn;
2853 BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
2854 VALUE q, r;
2855
2856 BARY_TRUNC(yds, yn);
2857 if (yn == 0)
2858 rb_num_zerodiv();
2859 BARY_TRUNC(xds, xn);
2860
2861 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
2862 return rb_assoc_new(LONG2FIX(0), x);
2863
2864 qn = xn - yn + 1;
2865 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
2866 qds = BDIGITS(q);
2867
2868 rn = yn;
2869 r = bignew(rn, BIGNUM_SIGN(x));
2870 rds = BDIGITS(r);
2871
2872 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2873
2874 bigtrunc(q);
2875 bigtrunc(r);
2876
2877 RB_GC_GUARD(x);
2878 RB_GC_GUARD(y);
2879
2880 return rb_assoc_new(q, r);
2881}
2882#endif
2883
2884static void
2885bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2886{
2887#if USE_GMP
2888 if (GMP_DIV_DIGITS < xn) {
2889 bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
2890 return;
2891 }
2892#endif
2893 bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
2894}
2895
2896static void
2897bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
2898{
2899 assert(xn <= qn);
2900 assert(yn <= rn);
2901
2902 BARY_TRUNC(yds, yn);
2903 if (yn == 0)
2904 rb_num_zerodiv();
2905
2906 BARY_TRUNC(xds, xn);
2907 if (xn == 0) {
2908 BDIGITS_ZERO(qds, qn);
2909 BDIGITS_ZERO(rds, rn);
2910 return;
2911 }
2912
2913 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
2914 MEMCPY(rds, xds, BDIGIT, xn);
2915 BDIGITS_ZERO(rds+xn, rn-xn);
2916 BDIGITS_ZERO(qds, qn);
2917 }
2918 else if (yn == 1) {
2919 MEMCPY(qds, xds, BDIGIT, xn);
2920 BDIGITS_ZERO(qds+xn, qn-xn);
2921 rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
2922 BDIGITS_ZERO(rds+1, rn-1);
2923 }
2924 else if (xn == 2 && yn == 2) {
2925 BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
2926 BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
2927 BDIGIT_DBL q = x / y;
2928 BDIGIT_DBL r = x % y;
2929 qds[0] = BIGLO(q);
2930 qds[1] = BIGLO(BIGDN(q));
2931 BDIGITS_ZERO(qds+2, qn-2);
2932 rds[0] = BIGLO(r);
2933 rds[1] = BIGLO(BIGDN(r));
2934 BDIGITS_ZERO(rds+2, rn-2);
2935 }
2936 else {
2937 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
2938 }
2939}
2940
2941
2942#ifndef BIGNUM_DEBUG
2943# define BIGNUM_DEBUG (0+RUBY_DEBUG)
2944#endif
2945
2946static int
2947bigzero_p(VALUE x)
2948{
2949 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2950}
2951
2952int
2953rb_bigzero_p(VALUE x)
2954{
2955 return BIGZEROP(x);
2956}
2957
2958int
2959rb_cmpint(VALUE val, VALUE a, VALUE b)
2960{
2961 if (NIL_P(val)) {
2962 rb_cmperr(a, b);
2963 }
2964 if (FIXNUM_P(val)) {
2965 long l = FIX2LONG(val);
2966 if (l > 0) return 1;
2967 if (l < 0) return -1;
2968 return 0;
2969 }
2970 if (RB_BIGNUM_TYPE_P(val)) {
2971 if (BIGZEROP(val)) return 0;
2972 if (BIGNUM_SIGN(val)) return 1;
2973 return -1;
2974 }
2975 if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
2976 if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
2977 return 0;
2978}
2979
2980#define BIGNUM_SET_LEN(b,l) \
2981 (BIGNUM_EMBED_P(b) ? \
2982 (void)(RBASIC(b)->flags = \
2983 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2984 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2985 (void)(RBIGNUM(b)->as.heap.len = (l)))
2986
2987static void
2988rb_big_realloc(VALUE big, size_t len)
2989{
2990 BDIGIT *ds;
2991 if (BIGNUM_EMBED_P(big)) {
2992 if (BIGNUM_EMBED_LEN_MAX < len) {
2993 ds = ALLOC_N(BDIGIT, len);
2994 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
2995 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
2996 RBIGNUM(big)->as.heap.digits = ds;
2997 FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
2998 }
2999 }
3000 else {
3001 if (len <= BIGNUM_EMBED_LEN_MAX) {
3002 ds = RBIGNUM(big)->as.heap.digits;
3003 FL_SET_RAW(big, BIGNUM_EMBED_FLAG);
3004 BIGNUM_SET_LEN(big, len);
3005 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
3006 if (ds) {
3007 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
3008 xfree(ds);
3009 }
3010 }
3011 else {
3012 if (BIGNUM_LEN(big) == 0) {
3013 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
3014 }
3015 else {
3016 REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
3017 }
3018 }
3019 }
3020}
3021
3022void
3023rb_big_resize(VALUE big, size_t len)
3024{
3025 rb_big_realloc(big, len);
3026 BIGNUM_SET_LEN(big, len);
3027}
3028
3029static VALUE
3030bignew_1(VALUE klass, size_t len, int sign)
3031{
3032 NEWOBJ_OF(big, struct RBignum, klass,
3033 T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0), sizeof(struct RBignum), 0);
3034 VALUE bigv = (VALUE)big;
3035 BIGNUM_SET_SIGN(bigv, sign);
3036 if (len <= BIGNUM_EMBED_LEN_MAX) {
3037 FL_SET_RAW(bigv, BIGNUM_EMBED_FLAG);
3038 BIGNUM_SET_LEN(bigv, len);
3039 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, sizeof(big->as.ary));
3040 }
3041 else {
3042 big->as.heap.digits = ALLOC_N(BDIGIT, len);
3043 big->as.heap.len = len;
3044 }
3045 OBJ_FREEZE(bigv);
3046 return bigv;
3047}
3048
3049 VALUE
3050rb_big_new(size_t len, int sign)
3051{
3052 return bignew(len, sign != 0);
3053}
3054
3055 VALUE
3056rb_big_clone(VALUE x)
3057{
3058 size_t len = BIGNUM_LEN(x);
3059 VALUE z = bignew_1(CLASS_OF(x), len, BIGNUM_SIGN(x));
3060
3061 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
3062 return z;
3063}
3064
3065static void
3066big_extend_carry(VALUE x)
3067{
3068 rb_big_resize(x, BIGNUM_LEN(x)+1);
3069 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3070}
3071
3072/* modify a bignum by 2's complement */
3073static void
3074get2comp(VALUE x)
3075{
3076 long i = BIGNUM_LEN(x);
3077 BDIGIT *ds = BDIGITS(x);
3078
3079 if (bary_2comp(ds, i)) {
3080 big_extend_carry(x);
3081 }
3082}
3083
3084void
3085rb_big_2comp(VALUE x) /* get 2's complement */
3086{
3087 get2comp(x);
3088}
3089
3090static BDIGIT
3091abs2twocomp(VALUE *xp, long *n_ret)
3092{
3093 VALUE x = *xp;
3094 long n = BIGNUM_LEN(x);
3095 BDIGIT *ds = BDIGITS(x);
3096 BDIGIT hibits = 0;
3097
3098 BARY_TRUNC(ds, n);
3099
3100 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3101 VALUE z = bignew_1(CLASS_OF(x), n, 0);
3102 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3103 bary_2comp(BDIGITS(z), n);
3104 hibits = BDIGMAX;
3105 *xp = z;
3106 }
3107 *n_ret = n;
3108 return hibits;
3109}
3110
3111static void
3112twocomp2abs_bang(VALUE x, int hibits)
3113{
3114 BIGNUM_SET_SIGN(x, !hibits);
3115 if (hibits) {
3116 get2comp(x);
3117 }
3118}
3119
3120static inline VALUE
3121bigtrunc(VALUE x)
3122{
3123 size_t len = BIGNUM_LEN(x);
3124 BDIGIT *ds = BDIGITS(x);
3125
3126 if (len == 0) return x;
3127 while (--len && !ds[len]);
3128 if (BIGNUM_LEN(x) > len+1) {
3129 rb_big_resize(x, len+1);
3130 }
3131 return x;
3132}
3133
3134static inline VALUE
3135bigfixize(VALUE x)
3136{
3137 size_t n = BIGNUM_LEN(x);
3138 BDIGIT *ds = BDIGITS(x);
3139#if SIZEOF_BDIGIT < SIZEOF_LONG
3140 unsigned long u;
3141#else
3142 BDIGIT u;
3143#endif
3144
3145 BARY_TRUNC(ds, n);
3146
3147 if (n == 0) return INT2FIX(0);
3148
3149#if SIZEOF_BDIGIT < SIZEOF_LONG
3150 if (sizeof(long)/SIZEOF_BDIGIT < n)
3151 goto return_big;
3152 else {
3153 int i = (int)n;
3154 u = 0;
3155 while (i--) {
3156 u = (unsigned long)(BIGUP(u) + ds[i]);
3157 }
3158 }
3159#else /* SIZEOF_BDIGIT >= SIZEOF_LONG */
3160 if (1 < n)
3161 goto return_big;
3162 else
3163 u = ds[0];
3164#endif
3165
3166 if (BIGNUM_POSITIVE_P(x)) {
3167 if (POSFIXABLE(u)) return LONG2FIX((long)u);
3168 }
3169 else {
3170 if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u);
3171 }
3172
3173 return_big:
3174 rb_big_resize(x, n);
3175 return x;
3176}
3177
3178static VALUE
3179bignorm(VALUE x)
3180{
3181 if (RB_BIGNUM_TYPE_P(x)) {
3182 x = bigfixize(x);
3183 }
3184 return x;
3185}
3186
3187 VALUE
3188rb_big_norm(VALUE x)
3189{
3190 return bignorm(x);
3191}
3192
3193 VALUE
3194rb_uint2big(uintptr_t n)
3195{
3196 long i;
3197 VALUE big = bignew(bdigit_roomof(SIZEOF_VALUE), 1);
3198 BDIGIT *digits = BDIGITS(big);
3199
3200#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3201 digits[0] = n;
3202#else
3203 for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
3204 digits[i] = BIGLO(n);
3205 n = BIGDN(n);
3206 }
3207#endif
3208
3209 i = bdigit_roomof(SIZEOF_VALUE);
3210 while (--i && !digits[i]) ;
3211 BIGNUM_SET_LEN(big, i+1);
3212 return big;
3213}
3214
3215 VALUE
3216rb_int2big(intptr_t n)
3217{
3218 long neg = 0;
3219 VALUE u;
3220 VALUE big;
3221
3222 if (n < 0) {
3223 u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
3224 neg = 1;
3225 }
3226 else {
3227 u = n;
3228 }
3229 big = rb_uint2big(u);
3230 if (neg) {
3231 BIGNUM_SET_NEGATIVE_SIGN(big);
3232 }
3233 return big;
3234}
3235
3236 VALUE
3237rb_uint2inum(uintptr_t n)
3238{
3239 if (POSFIXABLE(n)) return LONG2FIX(n);
3240 return rb_uint2big(n);
3241}
3242
3243 VALUE
3244rb_int2inum(intptr_t n)
3245{
3246 if (FIXABLE(n)) return LONG2FIX(n);
3247 return rb_int2big(n);
3248}
3249
3250void
3251rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
3252{
3253 rb_integer_pack(val, buf, num_longs, sizeof(long), 0,
3254 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
3255 INTEGER_PACK_2COMP);
3256}
3257
3258 VALUE
3259rb_big_unpack(unsigned long *buf, long num_longs)
3260{
3261 return rb_integer_unpack(buf, num_longs, sizeof(long), 0,
3262 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
3263 INTEGER_PACK_2COMP);
3264}
3265
3266/*
3267 * Calculate the number of bytes to be required to represent
3268 * the absolute value of the integer given as _val_.
3269 *
3270 * [val] an integer.
3271 * [nlz_bits_ret] number of leading zero bits in the most significant byte is returned if not NULL.
3272 *
3273 * This function returns ((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)
3274 * where val_numbits is the number of bits of abs(val).
3275 * This function should not overflow.
3276 *
3277 * If nlz_bits_ret is not NULL,
3278 * (return_value * CHAR_BIT - val_numbits) is stored in *nlz_bits_ret.
3279 * In this case, 0 <= *nlz_bits_ret < CHAR_BIT.
3280 *
3281 */
3282size_t
3283rb_absint_size(VALUE val, int *nlz_bits_ret)
3284{
3285 BDIGIT *dp;
3286 BDIGIT *de;
3287 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3288
3289 int num_leading_zeros;
3290
3291 val = rb_to_int(val);
3292
3293 if (FIXNUM_P(val)) {
3294 long v = FIX2LONG(val);
3295 if (v < 0) {
3296 v = -v;
3297 }
3298#if SIZEOF_BDIGIT >= SIZEOF_LONG
3299 fixbuf[0] = v;
3300#else
3301 {
3302 int i;
3303 for (i = 0; i < numberof(fixbuf); i++) {
3304 fixbuf[i] = BIGLO(v);
3305 v = BIGDN(v);
3306 }
3307 }
3308#endif
3309 dp = fixbuf;
3310 de = fixbuf + numberof(fixbuf);
3311 }
3312 else {
3313 dp = BDIGITS(val);
3314 de = dp + BIGNUM_LEN(val);
3315 }
3316 while (dp < de && de[-1] == 0)
3317 de--;
3318 if (dp == de) {
3319 if (nlz_bits_ret)
3320 *nlz_bits_ret = 0;
3321 return 0;
3322 }
3323 num_leading_zeros = nlz(de[-1]);
3324 if (nlz_bits_ret)
3325 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3326 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3327}
3328
3329static size_t
3330absint_numwords_small(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3331{
3332 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3333 size_t div = val_numbits / word_numbits;
3334 size_t mod = val_numbits % word_numbits;
3335 size_t numwords;
3336 size_t nlz_bits;
3337 numwords = mod == 0 ? div : div + 1;
3338 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3339 *nlz_bits_ret = nlz_bits;
3340 return numwords;
3341}
3342
3343static size_t
3344absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3345{
3346 static const BDIGIT char_bit[1] = { CHAR_BIT };
3347 BDIGIT numbytes_bary[bdigit_roomof(sizeof(numbytes))];
3348 BDIGIT val_numbits_bary[bdigit_roomof(sizeof(numbytes) + 1)];
3349 BDIGIT nlz_bits_in_msbyte_bary[1];
3350 BDIGIT word_numbits_bary[bdigit_roomof(sizeof(word_numbits))];
3351 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3352 BDIGIT mod_bary[numberof(word_numbits_bary)];
3353 BDIGIT one[1] = { 1 };
3354 size_t nlz_bits;
3355 size_t mod;
3356 int sign;
3357 size_t numwords;
3358
3359 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3360
3361 /*
3362 * val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
3363 * div, mod = val_numbits.divmod(word_numbits)
3364 * numwords = mod == 0 ? div : div + 1
3365 * nlz_bits = mod == 0 ? 0 : word_numbits - mod
3366 */
3367
3368 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
3369 INTEGER_PACK_NATIVE_BYTE_ORDER);
3370 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3371 if (nlz_bits_in_msbyte)
3372 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3373 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1, sizeof(word_numbits), 0,
3374 INTEGER_PACK_NATIVE_BYTE_ORDER);
3375 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3376 if (BARY_ZERO_P(mod_bary)) {
3377 nlz_bits = 0;
3378 }
3379 else {
3380 BARY_ADD(div_bary, div_bary, one);
3381 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1, sizeof(mod), 0,
3382 INTEGER_PACK_NATIVE_BYTE_ORDER);
3383 nlz_bits = word_numbits - mod;
3384 }
3385 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1, sizeof(numwords), 0,
3386 INTEGER_PACK_NATIVE_BYTE_ORDER);
3387
3388 if (sign == 2) {
3389#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3390 *nlz_bits_ret = 0;
3391#endif
3392 return (size_t)-1;
3393 }
3394 *nlz_bits_ret = nlz_bits;
3395 return numwords;
3396}
3397
3398/*
3399 * Calculate the number of words to be required to represent
3400 * the absolute value of the integer given as _val_.
3401 *
3402 * [val] an integer.
3403 * [word_numbits] number of bits in a word.
3404 * [nlz_bits_ret] number of leading zero bits in the most significant word is returned if not NULL.
3405 *
3406 * This function returns ((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)
3407 * where val_numbits is the number of bits of abs(val).
3408 *
3409 * This function can overflow.
3410 * When overflow occur, (size_t)-1 is returned.
3411 *
3412 * If nlz_bits_ret is not NULL and overflow is not occur,
3413 * (return_value * word_numbits - val_numbits) is stored in *nlz_bits_ret.
3414 * In this case, 0 <= *nlz_bits_ret < word_numbits.
3415 *
3416 */
3417size_t
3418rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
3419{
3420 size_t numbytes;
3421 int nlz_bits_in_msbyte;
3422 size_t numwords;
3423 size_t nlz_bits = 0;
3424
3425 if (word_numbits == 0)
3426 return (size_t)-1;
3427
3428 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3429
3430 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3431 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3432 if (debug_integer_pack) {
3433 size_t numwords0, nlz_bits0;
3434 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3435 assert(numwords0 == numwords);
3436 assert(nlz_bits0 == nlz_bits);
3437 (void)numwords0;
3438 }
3439 }
3440 else {
3441 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3442 }
3443 if (numwords == (size_t)-1)
3444 return numwords;
3445
3446 if (nlz_bits_ret)
3447 *nlz_bits_ret = nlz_bits;
3448
3449 return numwords;
3450}
3451
3452/* Test abs(val) consists only a bit or not.
3453 *
3454 * Returns 1 if abs(val) == 1 << n for some n >= 0.
3455 * Returns 0 otherwise.
3456 *
3457 * rb_absint_singlebit_p can be used to determine required buffer size
3458 * for rb_integer_pack used with INTEGER_PACK_2COMP (two's complement).
3459 *
3460 * Following example calculates number of bits required to
3461 * represent val in two's complement number, without sign bit.
3462 *
3463 * size_t size;
3464 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3465 * size = rb_absint_numwords(val, 1, NULL)
3466 * if (size == (size_t)-1) ...overflow...
3467 * if (neg && rb_absint_singlebit_p(val))
3468 * size--;
3469 *
3470 * Following example calculates number of bytes required to
3471 * represent val in two's complement number, with sign bit.
3472 *
3473 * size_t size;
3474 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3475 * int nlz_bits;
3476 * size = rb_absint_size(val, &nlz_bits);
3477 * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
3478 * size++;
3479 */
3480int
3481rb_absint_singlebit_p(VALUE val)
3482{
3483 BDIGIT *dp;
3484 BDIGIT *de;
3485 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3486 BDIGIT d;
3487
3488 val = rb_to_int(val);
3489
3490 if (FIXNUM_P(val)) {
3491 long v = FIX2LONG(val);
3492 if (v < 0) {
3493 v = -v;
3494 }
3495#if SIZEOF_BDIGIT >= SIZEOF_LONG
3496 fixbuf[0] = v;
3497#else
3498 {
3499 int i;
3500 for (i = 0; i < numberof(fixbuf); i++) {
3501 fixbuf[i] = BIGLO(v);
3502 v = BIGDN(v);
3503 }
3504 }
3505#endif
3506 dp = fixbuf;
3507 de = fixbuf + numberof(fixbuf);
3508 }
3509 else {
3510 dp = BDIGITS(val);
3511 de = dp + BIGNUM_LEN(val);
3512 }
3513 while (dp < de && de[-1] == 0)
3514 de--;
3515 while (dp < de && dp[0] == 0)
3516 dp++;
3517 if (dp == de) /* no bit set. */
3518 return 0;
3519 if (dp != de-1) /* two non-zero words. two bits set, at least. */
3520 return 0;
3521 d = *dp;
3522 return POW2_P(d);
3523}
3524
3525
3526/*
3527 * Export an integer into a buffer.
3528 *
3529 * This function fills the buffer specified by _words_ and _numwords_ as
3530 * val in the format specified by _wordsize_, _nails_ and _flags_.
3531 *
3532 * [val] Fixnum, Bignum or another integer like object which has to_int method.
3533 * [words] buffer to export abs(val).
3534 * [numwords] the size of given buffer as number of words.
3535 * [wordsize] the size of word as number of bytes.
3536 * [nails] number of padding bits in a word.
3537 * Most significant nails bits of each word are filled by zero.
3538 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3539 *
3540 * flags:
3541 * [INTEGER_PACK_MSWORD_FIRST] Store the most significant word as the first word.
3542 * [INTEGER_PACK_LSWORD_FIRST] Store the least significant word as the first word.
3543 * [INTEGER_PACK_MSBYTE_FIRST] Store the most significant byte in a word as the first byte in the word.
3544 * [INTEGER_PACK_LSBYTE_FIRST] Store the least significant byte in a word as the first byte in the word.
3545 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3546 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3547 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3548 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3549 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3550 *
3551 * This function fills the buffer specified by _words_
3552 * as abs(val) if INTEGER_PACK_2COMP is not specified in _flags_.
3553 * If INTEGER_PACK_2COMP is specified, 2's complement representation of val is
3554 * filled in the buffer.
3555 *
3556 * This function returns the signedness and overflow condition.
3557 * The overflow condition depends on INTEGER_PACK_2COMP.
3558 *
3559 * INTEGER_PACK_2COMP is not specified:
3560 * -2 : negative overflow. val <= -2**(numwords*(wordsize*CHAR_BIT-nails))
3561 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0
3562 * 0 : zero. val == 0
3563 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3564 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3565 *
3566 * INTEGER_PACK_2COMP is specified:
3567 * -2 : negative overflow. val < -2**(numwords*(wordsize*CHAR_BIT-nails))
3568 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0
3569 * 0 : zero. val == 0
3570 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3571 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3572 *
3573 * The value, -2**(numwords*(wordsize*CHAR_BIT-nails)), is representable
3574 * in 2's complement representation but not representable in absolute value.
3575 * So -1 is returned for the value if INTEGER_PACK_2COMP is specified
3576 * but returns -2 if INTEGER_PACK_2COMP is not specified.
3577 *
3578 * The least significant words are filled in the buffer when overflow occur.
3579 */
3580
3581int
3582rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3583{
3584 int sign;
3585 BDIGIT *ds;
3586 size_t num_bdigits;
3587 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3588
3589 RB_GC_GUARD(val) = rb_to_int(val);
3590
3591 if (FIXNUM_P(val)) {
3592 long v = FIX2LONG(val);
3593 if (v < 0) {
3594 sign = -1;
3595 v = -v;
3596 }
3597 else {
3598 sign = 1;
3599 }
3600#if SIZEOF_BDIGIT >= SIZEOF_LONG
3601 fixbuf[0] = v;
3602#else
3603 {
3604 int i;
3605 for (i = 0; i < numberof(fixbuf); i++) {
3606 fixbuf[i] = BIGLO(v);
3607 v = BIGDN(v);
3608 }
3609 }
3610#endif
3611 ds = fixbuf;
3612 num_bdigits = numberof(fixbuf);
3613 }
3614 else {
3615 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3616 ds = BDIGITS(val);
3617 num_bdigits = BIGNUM_LEN(val);
3618 }
3619
3620 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3621}
3622
3623/*
3624 * Import an integer from a buffer.
3625 *
3626 * [words] buffer to import.
3627 * [numwords] the size of given buffer as number of words.
3628 * [wordsize] the size of word as number of bytes.
3629 * [nails] number of padding bits in a word.
3630 * Most significant nails bits of each word are ignored.
3631 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3632 *
3633 * flags:
3634 * [INTEGER_PACK_MSWORD_FIRST] Interpret the first word as the most significant word.
3635 * [INTEGER_PACK_LSWORD_FIRST] Interpret the first word as the least significant word.
3636 * [INTEGER_PACK_MSBYTE_FIRST] Interpret the first byte in a word as the most significant byte in the word.
3637 * [INTEGER_PACK_LSBYTE_FIRST] Interpret the first byte in a word as the least significant byte in the word.
3638 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3639 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3640 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3641 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3642 * [INTEGER_PACK_FORCE_BIGNUM] the result will be a Bignum
3643 * even if it is representable as a Fixnum.
3644 * [INTEGER_PACK_NEGATIVE] Returns non-positive value.
3645 * (Returns non-negative value if not specified.)
3646 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3647 *
3648 * This function returns the imported integer as Fixnum or Bignum.
3649 *
3650 * The range of the result value depends on INTEGER_PACK_2COMP and INTEGER_PACK_NEGATIVE.
3651 *
3652 * INTEGER_PACK_2COMP is not set:
3653 * 0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails)) if !INTEGER_PACK_NEGATIVE
3654 * -2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0 if INTEGER_PACK_NEGATIVE
3655 *
3656 * INTEGER_PACK_2COMP is set:
3657 * -2**(numwords*(wordsize*CHAR_BIT-nails)-1) <= val <= 2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1 if !INTEGER_PACK_NEGATIVE
3658 * -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1 if INTEGER_PACK_NEGATIVE
3659 *
3660 * INTEGER_PACK_2COMP without INTEGER_PACK_NEGATIVE means sign extension.
3661 * INTEGER_PACK_2COMP with INTEGER_PACK_NEGATIVE mean assuming the higher bits are 1.
3662 *
3663 * Note that this function returns 0 when numwords is zero and
3664 * INTEGER_PACK_2COMP is set but INTEGER_PACK_NEGATIVE is not set.
3665 */
3666
3667 VALUE
3668rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3669{
3670 VALUE val;
3671 size_t num_bdigits;
3672 int sign;
3673 int nlp_bits;
3674 BDIGIT *ds;
3675 BDIGIT fixbuf[2] = { 0, 0 };
3676
3677 validate_integer_pack_format(numwords, wordsize, nails, flags,
3678 INTEGER_PACK_MSWORD_FIRST|
3679 INTEGER_PACK_LSWORD_FIRST|
3680 INTEGER_PACK_MSBYTE_FIRST|
3681 INTEGER_PACK_LSBYTE_FIRST|
3682 INTEGER_PACK_NATIVE_BYTE_ORDER|
3683 INTEGER_PACK_2COMP|
3684 INTEGER_PACK_FORCE_BIGNUM|
3685 INTEGER_PACK_NEGATIVE|
3686 INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
3687
3688 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3689
3690 if (LONG_MAX-1 < num_bdigits)
3691 rb_raise(rb_eArgError, "too big to unpack as an integer");
3692 if (num_bdigits <= numberof(fixbuf) && !(flags & INTEGER_PACK_FORCE_BIGNUM)) {
3693 val = Qfalse;
3694 ds = fixbuf;
3695 }
3696 else {
3697 val = bignew((long)num_bdigits, 0);
3698 ds = BDIGITS(val);
3699 }
3700 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3701
3702 if (sign == -2) {
3703 if (val) {
3704 big_extend_carry(val);
3705 }
3706 else if (num_bdigits == numberof(fixbuf)) {
3707 val = bignew((long)num_bdigits+1, 0);
3708 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3709 BDIGITS(val)[num_bdigits++] = 1;
3710 }
3711 else {
3712 ds[num_bdigits++] = 1;
3713 }
3714 }
3715
3716 if (!val) {
3717 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3718 if (u == 0)
3719 return LONG2FIX(0);
3720 if (0 < sign && POSFIXABLE(u))
3721 return LONG2FIX((long)u);
3722 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3723 NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u))
3724 return LONG2FIX((long)-(BDIGIT_DBL_SIGNED)u);
3725 val = bignew((long)num_bdigits, 0 <= sign);
3726 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3727 }
3728
3729 if ((flags & INTEGER_PACK_FORCE_BIGNUM) && sign != 0 &&
3730 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3731 sign = 0;
3732 BIGNUM_SET_SIGN(val, 0 <= sign);
3733
3734 if (flags & INTEGER_PACK_FORCE_BIGNUM)
3735 return bigtrunc(val);
3736 return bignorm(val);
3737}
3738
3739#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3740
3741NORETURN(static inline void invalid_radix(int base));
3742NORETURN(static inline void invalid_integer(VALUE s));
3743
3744static inline int
3745valid_radix_p(int base)
3746{
3747 return (1 < base && base <= 36);
3748}
3749
3750static inline void
3751invalid_radix(int base)
3752{
3753 rb_raise(rb_eArgError, "invalid radix %d", base);
3754}
3755
3756static inline void
3757invalid_integer(VALUE s)
3758{
3759 rb_raise(rb_eArgError, "invalid value for Integer(): %+"PRIsVALUE, s);
3760}
3761
3762static int
3763str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size_t *num_digits_p, ssize_t *len_p)
3764{
3765 char nondigit = 0;
3766 size_t num_digits = 0;
3767 const char *digits_start = str;
3768 const char *digits_end = str;
3769 ssize_t len = *len_p;
3770
3771 int c;
3772
3773 if (!len) {
3774 *num_digits_p = 0;
3775 *len_p = 0;
3776 return TRUE;
3777 }
3778
3779 if (badcheck && *str == '_') return FALSE;
3780
3781 while ((c = *str++) != 0) {
3782 if (c == '_') {
3783 if (nondigit) {
3784 if (badcheck) return FALSE;
3785 break;
3786 }
3787 nondigit = (char) c;
3788 }
3789 else if ((c = conv_digit(c)) < 0 || c >= base) {
3790 break;
3791 }
3792 else {
3793 nondigit = 0;
3794 num_digits++;
3795 digits_end = str;
3796 }
3797 if (len > 0 && !--len) break;
3798 }
3799 if (badcheck && nondigit) return FALSE;
3800 if (badcheck && len) {
3801 str--;
3802 while (*str && ISSPACE(*str)) {
3803 str++;
3804 if (len > 0 && !--len) break;
3805 }
3806 if (len && *str) {
3807 return FALSE;
3808 }
3809 }
3810 *num_digits_p = num_digits;
3811 *len_p = digits_end - digits_start;
3812 return TRUE;
3813}
3814
3815static VALUE
3816str2big_poweroftwo(
3817 int sign,
3818 const char *digits_start,
3819 const char *digits_end,
3820 size_t num_digits,
3821 int bits_per_digit)
3822{
3823 BDIGIT *dp;
3824 BDIGIT_DBL dd;
3825 int numbits;
3826
3827 size_t num_bdigits;
3828 const char *p;
3829 int c;
3830 VALUE z;
3831
3832 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3833 z = bignew(num_bdigits, sign);
3834 dp = BDIGITS(z);
3835 dd = 0;
3836 numbits = 0;
3837 for (p = digits_end; digits_start < p; p--) {
3838 if ((c = conv_digit(p[-1])) < 0)
3839 continue;
3840 dd |= (BDIGIT_DBL)c << numbits;
3841 numbits += bits_per_digit;
3842 if (BITSPERDIG <= numbits) {
3843 *dp++ = BIGLO(dd);
3844 dd = BIGDN(dd);
3845 numbits -= BITSPERDIG;
3846 }
3847 }
3848 if (numbits) {
3849 *dp++ = BIGLO(dd);
3850 }
3851 assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
3852
3853 return z;
3854}
3855
3856static VALUE
3857str2big_normal(
3858 int sign,
3859 const char *digits_start,
3860 const char *digits_end,
3861 size_t num_bdigits,
3862 int base)
3863{
3864 size_t blen = 1;
3865 BDIGIT *zds;
3866 BDIGIT_DBL num;
3867
3868 size_t i;
3869 const char *p;
3870 int c;
3871 VALUE z;
3872
3873 z = bignew(num_bdigits, sign);
3874 zds = BDIGITS(z);
3875 BDIGITS_ZERO(zds, num_bdigits);
3876
3877 for (p = digits_start; p < digits_end; p++) {
3878 if ((c = conv_digit(*p)) < 0)
3879 continue;
3880 num = c;
3881 i = 0;
3882 for (;;) {
3883 while (i<blen) {
3884 num += (BDIGIT_DBL)zds[i]*base;
3885 zds[i++] = BIGLO(num);
3886 num = BIGDN(num);
3887 }
3888 if (num) {
3889 blen++;
3890 continue;
3891 }
3892 break;
3893 }
3894 assert(blen <= num_bdigits);
3895 }
3896
3897 return z;
3898}
3899
3900static VALUE
3901str2big_karatsuba(
3902 int sign,
3903 const char *digits_start,
3904 const char *digits_end,
3905 size_t num_digits,
3906 size_t num_bdigits,
3907 int digits_per_bdigits_dbl,
3908 int base)
3909{
3910 VALUE powerv;
3911 size_t unit;
3912 VALUE tmpuv = 0;
3913 BDIGIT *uds, *vds, *tds;
3914 BDIGIT_DBL dd;
3915 BDIGIT_DBL current_base;
3916 int m;
3917 int power_level = 0;
3918
3919 size_t i;
3920 const char *p;
3921 int c;
3922 VALUE z;
3923
3924 uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3925 vds = uds + num_bdigits;
3926
3927 powerv = power_cache_get_power(base, power_level, NULL);
3928
3929 i = 0;
3930 dd = 0;
3931 current_base = 1;
3932 m = digits_per_bdigits_dbl;
3933 if (num_digits < (size_t)m)
3934 m = (int)num_digits;
3935 for (p = digits_end; digits_start < p; p--) {
3936 if ((c = conv_digit(p[-1])) < 0)
3937 continue;
3938 dd = dd + c * current_base;
3939 current_base *= base;
3940 num_digits--;
3941 m--;
3942 if (m == 0) {
3943 uds[i++] = BIGLO(dd);
3944 uds[i++] = (BDIGIT)BIGDN(dd);
3945 dd = 0;
3946 m = digits_per_bdigits_dbl;
3947 if (num_digits < (size_t)m)
3948 m = (int)num_digits;
3949 current_base = 1;
3950 }
3951 }
3952 assert(i == num_bdigits);
3953 for (unit = 2; unit < num_bdigits; unit *= 2) {
3954 for (i = 0; i < num_bdigits; i += unit*2) {
3955 if (2*unit <= num_bdigits - i) {
3956 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
3957 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
3958 }
3959 else if (unit <= num_bdigits - i) {
3960 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
3961 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
3962 }
3963 else {
3964 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
3965 }
3966 }
3967 power_level++;
3968 powerv = power_cache_get_power(base, power_level, NULL);
3969 tds = vds;
3970 vds = uds;
3971 uds = tds;
3972 }
3973 BARY_TRUNC(uds, num_bdigits);
3974 z = bignew(num_bdigits, sign);
3975 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
3976
3977 if (tmpuv)
3978 ALLOCV_END(tmpuv);
3979
3980 return z;
3981}
3982
3983#if USE_GMP
3984static VALUE
3985str2big_gmp(
3986 int sign,
3987 const char *digits_start,
3988 const char *digits_end,
3989 size_t num_digits,
3990 size_t num_bdigits,
3991 int base)
3992{
3993 char *buf, *p;
3994 const char *q;
3995 VALUE tmps;
3996 mpz_t mz;
3997 VALUE z;
3998 BDIGIT *zds;
3999 size_t zn, count;
4000
4001 buf = ALLOCV_N(char, tmps, num_digits+1);
4002 p = buf;
4003 for (q = digits_start; q < digits_end; q++) {
4004 if (conv_digit(*q) < 0)
4005 continue;
4006 *p++ = *q;
4007 }
4008 *p = '\0';
4009
4010 mpz_init(mz);
4011 mpz_set_str(mz, buf, base);
4012 zn = num_bdigits;
4013 z = bignew(zn, sign);
4014 zds = BDIGITS(z);
4015 bdigits_from_mpz(mz, BDIGITS(z), &count);
4016 BDIGITS_ZERO(zds+count, zn-count);
4017 mpz_clear(mz);
4018
4019 if (tmps)
4020 ALLOCV_END(tmps);
4021
4022 return z;
4023}
4024#endif
4025
4026static VALUE rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base);
4027
4028/*
4029 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
4030 *
4031 * str: pointer to the string to be parsed.
4032 * should be NUL-terminated.
4033 * base: base of conversion, must be 2..36, or -36..0.
4034 * if +base+ > 0, the conversion is done according to the +base+
4035 * and unmatched prefix is parsed as a part of the result if
4036 * present.
4037 * if +base+ <= 0, the conversion is done according to the
4038 * prefix if present, in base <code>-base</code> if +base+ < -1,
4039 * or in base 10.
4040 * badcheck: if non-zero, +ArgumentError+ is raised when +str+ is not
4041 * valid as an Integer. if zero, Fixnum 0 is returned in
4042 * that case.
4043 */
4044 VALUE
4045rb_cstr_to_inum(const char *str, int base, int badcheck)
4046{
4047 char *end;
4048 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4049 if (NIL_P(ret)) {
4050 if (badcheck) rb_invalid_str(str, "Integer()");
4051 ret = INT2FIX(0);
4052 }
4053 return ret;
4054}
4055
4056/*
4057 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
4058 *
4059 * str: pointer to the string to be parsed.
4060 * should be NUL-terminated if +len+ is negative.
4061 * len: length of +str+ if >= 0. if +len+ is negative, +str+ should
4062 * be NUL-terminated.
4063 * endp: if non-NULL, the address after parsed part is stored. if
4064 * NULL, Qnil is returned when +str+ is not valid as an Integer.
4065 * ndigits: if non-NULL, the number of parsed digits is stored.
4066 * base: see +rb_cstr_to_inum+
4067 * flags: bitwise OR of below flags:
4068 * RB_INT_PARSE_SIGN: allow preceding spaces and +/- sign
4069 * RB_INT_PARSE_UNDERSCORE: allow an underscore between digits
4070 * RB_INT_PARSE_PREFIX: allow preceding prefix
4071 */
4072
4073 VALUE
4074rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
4075 int base, int flags)
4076{
4077 const char *const s = str;
4078 char sign = 1;
4079 int c;
4080 VALUE z = Qnil;
4081
4082 unsigned long val;
4083 int ov;
4084
4085 const char *digits_start, *digits_end;
4086 size_t num_digits = 0;
4087 size_t num_bdigits;
4088 const ssize_t len0 = len;
4089 const int badcheck = !endp;
4090
4091#define ADV(n) do {\
4092 if (len > 0 && len <= (n)) goto bad; \
4093 str += (n); \
4094 len -= (n); \
4095 } while (0)
4096#define ASSERT_LEN() do {\
4097 assert(len != 0); \
4098 if (len0 >= 0) assert(s + len0 == str + len); \
4099 } while (0)
4100
4101 if (!str) {
4102 goto bad;
4103 }
4104 if (len && (flags & RB_INT_PARSE_SIGN)) {
4105 while (ISSPACE(*str)) ADV(1);
4106
4107 if (str[0] == '+') {
4108 ADV(1);
4109 }
4110 else if (str[0] == '-') {
4111 ADV(1);
4112 sign = 0;
4113 }
4114 ASSERT_LEN();
4115 }
4116 if (base <= 0) {
4117 if (str[0] == '0' && len > 1) {
4118 switch (str[1]) {
4119 case 'x': case 'X':
4120 base = 16;
4121 ADV(2);
4122 break;
4123 case 'b': case 'B':
4124 base = 2;
4125 ADV(2);
4126 break;
4127 case 'o': case 'O':
4128 base = 8;
4129 ADV(2);
4130 break;
4131 case 'd': case 'D':
4132 base = 10;
4133 ADV(2);
4134 break;
4135 default:
4136 base = 8;
4137 }
4138 }
4139 else if (base < -1) {
4140 base = -base;
4141 }
4142 else {
4143 base = 10;
4144 }
4145 }
4146 else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4147 /* no prefix */
4148 }
4149 else if (base == 2) {
4150 if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
4151 ADV(2);
4152 }
4153 }
4154 else if (base == 8) {
4155 if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
4156 ADV(2);
4157 }
4158 }
4159 else if (base == 10) {
4160 if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
4161 ADV(2);
4162 }
4163 }
4164 else if (base == 16) {
4165 if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
4166 ADV(2);
4167 }
4168 }
4169 if (!valid_radix_p(base)) {
4170 invalid_radix(base);
4171 }
4172 if (!len) goto bad;
4173 num_digits = str - s;
4174 if (*str == '0' && len != 1) { /* squeeze preceding 0s */
4175 int us = 0;
4176 const char *end = len < 0 ? NULL : str + len;
4177 ++num_digits;
4178 while ((c = *++str) == '0' ||
4179 ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
4180 if (c == '_') {
4181 if (++us >= 2)
4182 break;
4183 }
4184 else {
4185 ++num_digits;
4186 us = 0;
4187 }
4188 if (str == end) break;
4189 }
4190 if (!c || ISSPACE(c)) --str;
4191 if (end) len = end - str;
4192 }
4193 c = *str;
4194 c = conv_digit(c);
4195 if (c < 0 || c >= base) {
4196 if (!badcheck && num_digits) z = INT2FIX(0);
4197 goto bad;
4198 }
4199
4200 if (ndigits) *ndigits = num_digits;
4201 val = ruby_scan_digits(str, len, base, &num_digits, &ov);
4202 if (!ov) {
4203 const char *end = &str[num_digits];
4204 if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
4205 goto bigparse;
4206 if (endp) *endp = (char *)end;
4207 if (ndigits) *ndigits += num_digits;
4208 if (badcheck) {
4209 if (num_digits == 0) return Qnil; /* no number */
4210 while (len < 0 ? *end : end < str + len) {
4211 if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
4212 end++;
4213 }
4214 }
4215
4216 if (POSFIXABLE(val)) {
4217 if (sign) return LONG2FIX(val);
4218 else {
4219 long result = -(long)val;
4220 return LONG2FIX(result);
4221 }
4222 }
4223 else {
4224 VALUE big = rb_uint2big(val);
4225 BIGNUM_SET_SIGN(big, sign);
4226 return bignorm(big);
4227 }
4228 }
4229
4230 bigparse:
4231 digits_start = str;
4232 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4233 goto bad;
4234 if (endp) *endp = (char *)(str + len);
4235 if (ndigits) *ndigits += num_digits;
4236 digits_end = digits_start + len;
4237
4238 if (POW2_P(base)) {
4239 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4240 bit_length(base-1));
4241 }
4242 else {
4243 int digits_per_bdigits_dbl;
4244 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4245 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4246
4247#if USE_GMP
4248 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4249 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4250 num_bdigits, base);
4251 }
4252 else
4253#endif
4254 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4255 z = str2big_normal(sign, digits_start, digits_end,
4256 num_bdigits, base);
4257 }
4258 else {
4259 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4260 num_bdigits, digits_per_bdigits_dbl, base);
4261 }
4262 }
4263
4264 return bignorm(z);
4265
4266 bad:
4267 if (endp) *endp = (char *)str;
4268 if (ndigits) *ndigits = num_digits;
4269 return z;
4270}
4271
4272static VALUE
4273rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
4274{
4275 return rb_int_parse_cstr(str, len, endp, NULL, base,
4276 RB_INT_PARSE_DEFAULT);
4277}
4278
4279 VALUE
4280rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception)
4281{
4282 VALUE ret;
4283 const char *s;
4284 long len;
4285 char *end;
4286
4287 StringValue(str);
4288 rb_must_asciicompat(str);
4289 RSTRING_GETMEM(str, s, len);
4290 ret = rb_cstr_parse_inum(s, len, (badcheck ? NULL : &end), base);
4291 if (NIL_P(ret)) {
4292 if (badcheck) {
4293 if (!raise_exception) return Qnil;
4294 invalid_integer(str);
4295 }
4296 ret = INT2FIX(0);
4297 }
4298 return ret;
4299}
4300
4301 VALUE
4302rb_str_to_inum(VALUE str, int base, int badcheck)
4303{
4304 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4305}
4306
4307 VALUE
4308rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
4309{
4310 int positive_p = 1;
4311 const char *s, *str;
4312 const char *digits_start, *digits_end;
4313 size_t num_digits;
4314 ssize_t len;
4315 VALUE z;
4316
4317 if (!valid_radix_p(base) || !POW2_P(base)) {
4318 invalid_radix(base);
4319 }
4320
4321 rb_must_asciicompat(arg);
4322 s = str = StringValueCStr(arg);
4323 len = RSTRING_LEN(arg);
4324 if (*str == '-') {
4325 len--;
4326 str++;
4327 positive_p = 0;
4328 }
4329
4330 digits_start = str;
4331 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4332 invalid_integer(arg);
4333 digits_end = digits_start + len;
4334
4335 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4336 bit_length(base-1));
4337
4338 RB_GC_GUARD(arg);
4339
4340 return bignorm(z);
4341}
4342
4343 VALUE
4344rb_str2big_normal(VALUE arg, int base, int badcheck)
4345{
4346 int positive_p = 1;
4347 const char *s, *str;
4348 const char *digits_start, *digits_end;
4349 size_t num_digits;
4350 ssize_t len;
4351 VALUE z;
4352
4353 int digits_per_bdigits_dbl;
4354 size_t num_bdigits;
4355
4356 if (!valid_radix_p(base)) {
4357 invalid_radix(base);
4358 }
4359
4360 rb_must_asciicompat(arg);
4361 s = str = StringValuePtr(arg);
4362 len = RSTRING_LEN(arg);
4363 if (len > 0 && *str == '-') {
4364 len--;
4365 str++;
4366 positive_p = 0;
4367 }
4368
4369 digits_start = str;
4370 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4371 invalid_integer(arg);
4372 digits_end = digits_start + len;
4373
4374 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4375 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4376
4377 z = str2big_normal(positive_p, digits_start, digits_end,
4378 num_bdigits, base);
4379
4380 RB_GC_GUARD(arg);
4381
4382 return bignorm(z);
4383}
4384
4385 VALUE
4386rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
4387{
4388 int positive_p = 1;
4389 const char *s, *str;
4390 const char *digits_start, *digits_end;
4391 size_t num_digits;
4392 ssize_t len;
4393 VALUE z;
4394
4395 int digits_per_bdigits_dbl;
4396 size_t num_bdigits;
4397
4398 if (!valid_radix_p(base)) {
4399 invalid_radix(base);
4400 }
4401
4402 rb_must_asciicompat(arg);
4403 s = str = StringValuePtr(arg);
4404 len = RSTRING_LEN(arg);
4405 if (len > 0 && *str == '-') {
4406 len--;
4407 str++;
4408 positive_p = 0;
4409 }
4410
4411 digits_start = str;
4412 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4413 invalid_integer(arg);
4414 digits_end = digits_start + len;
4415
4416 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4417 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4418
4419 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4420 num_bdigits, digits_per_bdigits_dbl, base);
4421
4422 RB_GC_GUARD(arg);
4423
4424 return bignorm(z);
4425}
4426
4427#if USE_GMP
4428 VALUE
4429rb_str2big_gmp(VALUE arg, int base, int badcheck)
4430{
4431 int positive_p = 1;
4432 const char *s, *str;
4433 const char *digits_start, *digits_end;
4434 size_t num_digits;
4435 ssize_t len;
4436 VALUE z;
4437
4438 int digits_per_bdigits_dbl;
4439 size_t num_bdigits;
4440
4441 if (!valid_radix_p(base)) {
4442 invalid_radix(base);
4443 }
4444
4445 rb_must_asciicompat(arg);
4446 s = str = StringValuePtr(arg);
4447 len = RSTRING_LEN(arg);
4448 if (len > 0 && *str == '-') {
4449 len--;
4450 str++;
4451 positive_p = 0;
4452 }
4453
4454 digits_start = str;
4455 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4456 invalid_integer(arg);
4457 digits_end = digits_start + len;
4458
4459 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4460 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4461
4462 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4463
4464 RB_GC_GUARD(arg);
4465
4466 return bignorm(z);
4467}
4468#endif
4469
4470#if HAVE_LONG_LONG
4471
4472static VALUE
4473rb_ull2big(unsigned LONG_LONG n)
4474{
4475 long i;
4476 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4477 BDIGIT *digits = BDIGITS(big);
4478
4479#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4480 digits[0] = n;
4481#else
4482 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4483 digits[i] = BIGLO(n);
4484 n = BIGDN(n);
4485 }
4486#endif
4487
4488 i = bdigit_roomof(SIZEOF_LONG_LONG);
4489 while (i-- && !digits[i]) ;
4490 BIGNUM_SET_LEN(big, i+1);
4491 return big;
4492}
4493
4494static VALUE
4495rb_ll2big(LONG_LONG n)
4496{
4497 long neg = 0;
4498 unsigned LONG_LONG u;
4499 VALUE big;
4500
4501 if (n < 0) {
4502 u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
4503 neg = 1;
4504 }
4505 else {
4506 u = n;
4507 }
4508 big = rb_ull2big(u);
4509 if (neg) {
4510 BIGNUM_SET_NEGATIVE_SIGN(big);
4511 }
4512 return big;
4513}
4514
4515 VALUE
4516 rb_ull2inum(unsigned LONG_LONG n)
4517{
4518 if (POSFIXABLE(n)) return LONG2FIX((long)n);
4519 return rb_ull2big(n);
4520}
4521
4522 VALUE
4523 rb_ll2inum(LONG_LONG n)
4524{
4525 if (FIXABLE(n)) return LONG2FIX((long)n);
4526 return rb_ll2big(n);
4527}
4528
4529#endif /* HAVE_LONG_LONG */
4530
4531#ifdef HAVE_INT128_T
4532static VALUE
4533rb_uint128t2big(uint128_t n)
4534{
4535 long i;
4536 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4537 BDIGIT *digits = BDIGITS(big);
4538
4539 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4540 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4541 }
4542
4543 i = bdigit_roomof(SIZEOF_INT128_T);
4544 while (i-- && !digits[i]) ;
4545 BIGNUM_SET_LEN(big, i+1);
4546 return big;
4547}
4548
4549 VALUE
4550rb_int128t2big(int128_t n)
4551{
4552 int neg = 0;
4553 uint128_t u;
4554 VALUE big;
4555
4556 if (n < 0) {
4557 u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
4558 neg = 1;
4559 }
4560 else {
4561 u = n;
4562 }
4563 big = rb_uint128t2big(u);
4564 if (neg) {
4565 BIGNUM_SET_NEGATIVE_SIGN(big);
4566 }
4567 return big;
4568}
4569#endif
4570
4571 VALUE
4572rb_cstr2inum(const char *str, int base)
4573{
4574 return rb_cstr_to_inum(str, base, base==0);
4575}
4576
4577 VALUE
4578rb_str2inum(VALUE str, int base)
4579{
4580 return rb_str_to_inum(str, base, base==0);
4581}
4582
4583static VALUE
4584big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
4585{
4586 BDIGIT *xds, *zds;
4587 long s1;
4588 int s2;
4589 VALUE z;
4590 long xn;
4591
4592 if (lshift_p) {
4593 if (LONG_MAX < shift_numdigits) {
4594 too_big:
4595 rb_raise(rb_eRangeError, "shift width too big");
4596 }
4597 s1 = shift_numdigits;
4598 s2 = shift_numbits;
4599 if ((size_t)s1 != shift_numdigits) goto too_big;
4600 xn = BIGNUM_LEN(x);
4601 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1) goto too_big;
4602 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4603 zds = BDIGITS(z);
4604 BDIGITS_ZERO(zds, s1);
4605 xds = BDIGITS(x);
4606 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4607 }
4608 else {
4609 long zn;
4610 BDIGIT hibitsx;
4611 if (LONG_MAX < shift_numdigits || (size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4612 if (BIGNUM_POSITIVE_P(x) ||
4613 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4614 return INT2FIX(0);
4615 else
4616 return INT2FIX(-1);
4617 }
4618 s1 = shift_numdigits;
4619 s2 = shift_numbits;
4620 hibitsx = abs2twocomp(&x, &xn);
4621 xds = BDIGITS(x);
4622 if (xn <= s1) {
4623 return hibitsx ? INT2FIX(-1) : INT2FIX(0);
4624 }
4625 zn = xn - s1;
4626 z = bignew(zn, 0);
4627 zds = BDIGITS(z);
4628 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4629 twocomp2abs_bang(z, hibitsx != 0);
4630 }
4631 RB_GC_GUARD(x);
4632 return z;
4633}
4634
4635static VALUE
4636big_shift2(VALUE x, int lshift_p, VALUE y)
4637{
4638 int sign;
4639 size_t lens[2];
4640 size_t shift_numdigits;
4641 int shift_numbits;
4642
4643 assert(POW2_P(CHAR_BIT));
4644 assert(POW2_P(BITSPERDIG));
4645
4646 if (BIGZEROP(x))
4647 return INT2FIX(0);
4648 sign = rb_integer_pack(y, lens, numberof(lens), sizeof(size_t), 0,
4649 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
4650 if (sign < 0) {
4651 lshift_p = !lshift_p;
4652 sign = -sign;
4653 }
4654 if (lshift_p) {
4655 if (1 < sign || CHAR_BIT <= lens[1])
4656 rb_raise(rb_eRangeError, "shift width too big");
4657 }
4658 else {
4659 if (1 < sign || CHAR_BIT <= lens[1])
4660 return BIGNUM_POSITIVE_P(x) ? INT2FIX(0) : INT2FIX(-1);
4661 }
4662 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4663 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4664 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4665 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4666}
4667
4668static VALUE
4669big_lshift(VALUE x, unsigned long shift)
4670{
4671 long s1 = shift/BITSPERDIG;
4672 int s2 = (int)(shift%BITSPERDIG);
4673 return big_shift3(x, 1, s1, s2);
4674}
4675
4676static VALUE
4677big_rshift(VALUE x, unsigned long shift)
4678{
4679 long s1 = shift/BITSPERDIG;
4680 int s2 = (int)(shift%BITSPERDIG);
4681 return big_shift3(x, 0, s1, s2);
4682}
4683
4684#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4685
4686static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4687static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4688
4689static void
4690power_cache_init(void)
4691{
4692}
4693
4694static inline VALUE
4695power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
4696{
4697 /*
4698 * MAX_BASE36_POWER_TABLE_ENTRIES is big enough to that
4699 * base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1] fills whole memory.
4700 * So MAX_BASE36_POWER_TABLE_ENTRIES <= power_level is not possible to calculate.
4701 *
4702 * number-of-bytes =
4703 * log256(base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1]) =
4704 * log256(maxpow_in_bdigit_dbl(base)**(2**(MAX_BASE36_POWER_TABLE_ENTRIES-1))) =
4705 * log256(maxpow_in_bdigit_dbl(base)**(2**(SIZEOF_SIZE_T*CHAR_BIT))) =
4706 * (2**(SIZEOF_SIZE_T*CHAR_BIT))*log256(maxpow_in_bdigit_dbl(base)) =
4707 * (256**SIZEOF_SIZE_T)*log256(maxpow_in_bdigit_dbl(base)) >
4708 * (256**SIZEOF_SIZE_T)*(sizeof(BDIGIT_DBL)-1) >
4709 * 256**SIZEOF_SIZE_T
4710 */
4711 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4712 rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4713
4714 VALUE power = base36_power_cache[base - 2][power_level];
4715 if (!power) {
4716 size_t numdigits;
4717 if (power_level == 0) {
4718 int numdigits0;
4719 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4720 power = bignew(2, 1);
4721 bdigitdbl2bary(BDIGITS(power), 2, dd);
4722 numdigits = numdigits0;
4723 }
4724 else {
4725 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4726 numdigits *= 2;
4727 }
4728 rb_obj_hide(power);
4729 base36_power_cache[base - 2][power_level] = power;
4730 base36_numdigits_cache[base - 2][power_level] = numdigits;
4731 rb_gc_register_mark_object(power);
4732 }
4733 if (numdigits_ret)
4734 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4735 return power;
4736}
4737
4738 struct big2str_struct {
4739 int negative;
4740 int base;
4741 BDIGIT_DBL hbase2;
4742 int hbase2_numdigits;
4743 VALUE result;
4744 char *ptr;
4745};
4746
4747static void
4748big2str_alloc(struct big2str_struct *b2s, size_t len)
4749{
4750 if (LONG_MAX-1 < len)
4751 rb_raise(rb_eArgError, "too big number");
4752 b2s->result = rb_usascii_str_new(0, (long)(len + 1)); /* plus one for sign */
4753 b2s->ptr = RSTRING_PTR(b2s->result);
4754 if (b2s->negative)
4755 *b2s->ptr++ = '-';
4756}
4757
4758static void
4759big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t taillen)
4760{
4761 size_t j;
4762 BDIGIT_DBL num;
4763 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4764 int beginning = !b2s->ptr;
4765 size_t len = 0;
4766
4767 assert(xn <= 2);
4768 num = bary2bdigitdbl(xds, xn);
4769
4770 if (beginning) {
4771 if (num == 0)
4772 return;
4773 p = buf;
4774 j = sizeof(buf);
4775 do {
4776 BDIGIT_DBL idx = num % b2s->base;
4777 num /= b2s->base;
4778 p[--j] = ruby_digitmap[idx];
4779 } while (num);
4780 len = sizeof(buf) - j;
4781 big2str_alloc(b2s, len + taillen);
4782 MEMCPY(b2s->ptr, buf + j, char, len);
4783 }
4784 else {
4785 p = b2s->ptr;
4786 j = b2s->hbase2_numdigits;
4787 do {
4788 BDIGIT_DBL idx = num % b2s->base;
4789 num /= b2s->base;
4790 p[--j] = ruby_digitmap[idx];
4791 } while (j);
4792 len = b2s->hbase2_numdigits;
4793 }
4794 b2s->ptr += len;
4795}
4796
4797static void
4798big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
4799 int power_level, size_t taillen)
4800{
4801 VALUE b;
4802 size_t half_numdigits, lower_numdigits;
4803 int lower_power_level;
4804 size_t bn;
4805 const BDIGIT *bds;
4806 size_t len;
4807
4808 /*
4809 * Precondition:
4810 * abs(x) < maxpow**(2**power_level)
4811 * where
4812 * maxpow = maxpow_in_bdigit_dbl(base, &numdigits)
4813 *
4814 * This function generates sequence of zeros, and then stringized abs(x) into b2s->ptr.
4815 *
4816 * b2s->ptr can be NULL.
4817 * It is allocated when the first character is generated via big2str_alloc.
4818 *
4819 * The prefix zeros should be generated if and only if b2s->ptr is not NULL.
4820 * When the zeros are generated, the zeros and abs(x) consists
4821 * numdigits*(2**power_level) characters at total.
4822 *
4823 * Note:
4824 * power_cache_get_power(base, power_level, &len) may not be cached yet. It should not be called.
4825 * power_cache_get_power(base, power_level-1, &len) should be cached already if 0 <= power_level-1.
4826 */
4827
4828 if (xn == 0 || bary_zero_p(xds, xn)) {
4829 if (b2s->ptr) {
4830 /* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
4831 power_cache_get_power(b2s->base, power_level, &len);
4832 memset(b2s->ptr, '0', len);
4833 b2s->ptr += len;
4834 }
4835 return;
4836 }
4837
4838 if (power_level == 0) {
4839 big2str_2bdigits(b2s, xds, xn, taillen);
4840 return;
4841 }
4842
4843 lower_power_level = power_level-1;
4844 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4845 bn = BIGNUM_LEN(b);
4846 bds = BDIGITS(b);
4847
4848 half_numdigits = lower_numdigits;
4849
4850 while (0 < lower_power_level &&
4851 (xn < bn ||
4852 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4853 lower_power_level--;
4854 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4855 bn = BIGNUM_LEN(b);
4856 bds = BDIGITS(b);
4857 }
4858
4859 if (lower_power_level == 0 &&
4860 (xn < bn ||
4861 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4862 if (b2s->ptr) {
4863 len = half_numdigits * 2 - lower_numdigits;
4864 memset(b2s->ptr, '0', len);
4865 b2s->ptr += len;
4866 }
4867 big2str_2bdigits(b2s, xds, xn, taillen);
4868 }
4869 else {
4870 BDIGIT *qds, *rds;
4871 size_t qn, rn;
4872 BDIGIT *tds;
4873 int shift;
4874
4875 if (lower_power_level != power_level-1 && b2s->ptr) {
4876 len = (half_numdigits - lower_numdigits) * 2;
4877 memset(b2s->ptr, '0', len);
4878 b2s->ptr += len;
4879 }
4880
4881 shift = nlz(bds[bn-1]);
4882
4883 qn = xn + BIGDIVREM_EXTRA_WORDS;
4884
4885 if (shift == 0) {
4886 /* bigdivrem_restoring will not modify y.
4887 * So use bds directly. */
4888 tds = (BDIGIT *)bds;
4889 xds[xn] = 0;
4890 }
4891 else {
4892 /* bigdivrem_restoring will modify y.
4893 * So use temporary buffer. */
4894 tds = xds + qn;
4895 assert(qn + bn <= xn + wn);
4896 bary_small_lshift(tds, bds, bn, shift);
4897 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4898 }
4899
4900 bigdivrem_restoring(xds, qn, tds, bn);
4901
4902 rds = xds;
4903 rn = bn;
4904
4905 qds = xds + bn;
4906 qn = qn - bn;
4907
4908 if (shift) {
4909 bary_small_rshift(rds, rds, rn, shift, 0);
4910 }
4911
4912 BARY_TRUNC(qds, qn);
4913 assert(qn <= bn);
4914 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4915 BARY_TRUNC(rds, rn);
4916 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4917 }
4918}
4919
4920static VALUE
4921big2str_base_poweroftwo(VALUE x, int base)
4922{
4923 int word_numbits = ffs(base) - 1;
4924 size_t numwords;
4925 VALUE result;
4926 char *ptr;
4927 numwords = rb_absint_numwords(x, word_numbits, NULL);
4928 if (BIGNUM_NEGATIVE_P(x)) {
4929 if (LONG_MAX-1 < numwords)
4930 rb_raise(rb_eArgError, "too big number");
4931 result = rb_usascii_str_new(0, 1+numwords);
4932 ptr = RSTRING_PTR(result);
4933 *ptr++ = BIGNUM_POSITIVE_P(x) ? '+' : '-';
4934 }
4935 else {
4936 if (LONG_MAX < numwords)
4937 rb_raise(rb_eArgError, "too big number");
4938 result = rb_usascii_str_new(0, numwords);
4939 ptr = RSTRING_PTR(result);
4940 }
4941 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4942 INTEGER_PACK_BIG_ENDIAN);
4943 while (0 < numwords) {
4944 *ptr = ruby_digitmap[*(unsigned char *)ptr];
4945 ptr++;
4946 numwords--;
4947 }
4948 return result;
4949}
4950
4951 VALUE
4952rb_big2str_poweroftwo(VALUE x, int base)
4953{
4954 return big2str_base_poweroftwo(x, base);
4955}
4956
4957static VALUE
4958big2str_generic(VALUE x, int base)
4959{
4960 BDIGIT *xds;
4961 size_t xn;
4962 struct big2str_struct b2s_data;
4963 int power_level;
4964 VALUE power;
4965
4966 xds = BDIGITS(x);
4967 xn = BIGNUM_LEN(x);
4968 BARY_TRUNC(xds, xn);
4969
4970 if (xn == 0) {
4971 return rb_usascii_str_new2("0");
4972 }
4973
4974 if (!valid_radix_p(base))
4975 invalid_radix(base);
4976
4977 if (xn >= LONG_MAX/BITSPERDIG) {
4978 rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
4979 }
4980
4981 power_level = 0;
4982 power = power_cache_get_power(base, power_level, NULL);
4983 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
4984 (size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
4985 power_level++;
4986 power = power_cache_get_power(base, power_level, NULL);
4987 }
4988 assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
4989
4990 if ((size_t)BIGNUM_LEN(power) <= xn) {
4991 /*
4992 * This increment guarantees x < power_cache_get_power(base, power_level)
4993 * without invoking it actually.
4994 * (power_cache_get_power(base, power_level) can be slow and not used
4995 * in big2str_karatsuba.)
4996 *
4997 * Although it is possible that x < power_cache_get_power(base, power_level-1),
4998 * it is no problem because big2str_karatsuba checks it and
4999 * doesn't affect the result when b2s_data.ptr is NULL.
5000 */
5001 power_level++;
5002 }
5003
5004 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5005 b2s_data.base = base;
5006 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5007
5008 b2s_data.result = Qnil;
5009 b2s_data.ptr = NULL;
5010
5011 if (power_level == 0) {
5012 big2str_2bdigits(&b2s_data, xds, xn, 0);
5013 }
5014 else {
5015 VALUE tmpw = 0;
5016 BDIGIT *wds;
5017 size_t wn;
5018 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5019 wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
5020 MEMCPY(wds, xds, BDIGIT, xn);
5021 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5022 if (tmpw)
5023 ALLOCV_END(tmpw);
5024 }
5025 RB_GC_GUARD(x);
5026
5027 *b2s_data.ptr = '\0';
5028 rb_str_resize(b2s_data.result, (long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5029
5030 RB_GC_GUARD(x);
5031 return b2s_data.result;
5032}
5033
5034 VALUE
5035rb_big2str_generic(VALUE x, int base)
5036{
5037 return big2str_generic(x, base);
5038}
5039
5040#if USE_GMP
5041static VALUE
5042big2str_gmp(VALUE x, int base)
5043{
5044 mpz_t mx;
5045 size_t size;
5046 VALUE str;
5047 BDIGIT *xds = BDIGITS(x);
5048 size_t xn = BIGNUM_LEN(x);
5049
5050 mpz_init(mx);
5051 bdigits_to_mpz(mx, xds, xn);
5052
5053 size = mpz_sizeinbase(mx, base);
5054
5055 if (BIGNUM_NEGATIVE_P(x)) {
5056 mpz_neg(mx, mx);
5057 str = rb_usascii_str_new(0, size+1);
5058 }
5059 else {
5060 str = rb_usascii_str_new(0, size);
5061 }
5062 mpz_get_str(RSTRING_PTR(str), base, mx);
5063 mpz_clear(mx);
5064
5065 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\0') {
5066 rb_str_set_len(str, RSTRING_LEN(str)-1);
5067 }
5068
5069 RB_GC_GUARD(x);
5070 return str;
5071}
5072
5073 VALUE
5074rb_big2str_gmp(VALUE x, int base)
5075{
5076 return big2str_gmp(x, base);
5077}
5078#endif
5079
5080static VALUE
5081rb_big2str1(VALUE x, int base)
5082{
5083 BDIGIT *xds;
5084 size_t xn;
5085
5086 if (FIXNUM_P(x)) {
5087 return rb_fix2str(x, base);
5088 }
5089
5090 bigtrunc(x);
5091 xds = BDIGITS(x);
5092 xn = BIGNUM_LEN(x);
5093 BARY_TRUNC(xds, xn);
5094
5095 if (xn == 0) {
5096 return rb_usascii_str_new2("0");
5097 }
5098
5099 if (!valid_radix_p(base))
5100 invalid_radix(base);
5101
5102 if (xn >= LONG_MAX/BITSPERDIG) {
5103 rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
5104 }
5105
5106 if (POW2_P(base)) {
5107 /* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
5108 return big2str_base_poweroftwo(x, base);
5109 }
5110
5111#if USE_GMP
5112 if (GMP_BIG2STR_DIGITS < xn) {
5113 return big2str_gmp(x, base);
5114 }
5115#endif
5116
5117 return big2str_generic(x, base);
5118}
5119
5120 VALUE
5121rb_big2str(VALUE x, int base)
5122{
5123 return rb_big2str1(x, base);
5124}
5125
5126static unsigned long
5127big2ulong(VALUE x, const char *type)
5128{
5129#if SIZEOF_LONG > SIZEOF_BDIGIT
5130 size_t i;
5131#endif
5132 size_t len = BIGNUM_LEN(x);
5133 unsigned long num;
5134 BDIGIT *ds;
5135
5136 if (len == 0)
5137 return 0;
5138 if (BIGSIZE(x) > sizeof(long)) {
5139 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
5140 }
5141 ds = BDIGITS(x);
5142#if SIZEOF_LONG <= SIZEOF_BDIGIT
5143 num = (unsigned long)ds[0];
5144#else
5145 num = 0;
5146 for (i = 0; i < len; i++) {
5147 num <<= BITSPERDIG;
5148 num += (unsigned long)ds[len - i - 1]; /* overflow is already checked */
5149 }
5150#endif
5151 return num;
5152}
5153
5154unsigned long
5155rb_big2ulong(VALUE x)
5156{
5157 unsigned long num = big2ulong(x, "unsigned long");
5158
5159 if (BIGNUM_POSITIVE_P(x)) {
5160 return num;
5161 }
5162 else {
5163 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5164 return -(long)(num-1)-1;
5165 }
5166 rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
5167}
5168
5169long
5170rb_big2long(VALUE x)
5171{
5172 unsigned long num = big2ulong(x, "long");
5173
5174 if (BIGNUM_POSITIVE_P(x)) {
5175 if (num <= LONG_MAX)
5176 return num;
5177 }
5178 else {
5179 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5180 return -(long)(num-1)-1;
5181 }
5182 rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
5183}
5184
5185#if HAVE_LONG_LONG
5186
5187static unsigned LONG_LONG
5188big2ull(VALUE x, const char *type)
5189{
5190#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5191 size_t i;
5192#endif
5193 size_t len = BIGNUM_LEN(x);
5194 unsigned LONG_LONG num;
5195 BDIGIT *ds = BDIGITS(x);
5196
5197 if (len == 0)
5198 return 0;
5199 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5200 rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
5201#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5202 num = (unsigned LONG_LONG)ds[0];
5203#else
5204 num = 0;
5205 for (i = 0; i < len; i++) {
5206 num = BIGUP(num);
5207 num += ds[len - i - 1];
5208 }
5209#endif
5210 return num;
5211}
5212
5213unsigned LONG_LONG
5214rb_big2ull(VALUE x)
5215{
5216 unsigned LONG_LONG num = big2ull(x, "unsigned long long");
5217
5218 if (BIGNUM_POSITIVE_P(x)) {
5219 return num;
5220 }
5221 else {
5222 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5223 return -(LONG_LONG)(num-1)-1;
5224 }
5225 rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
5226}
5227
5228 LONG_LONG
5229rb_big2ll(VALUE x)
5230{
5231 unsigned LONG_LONG num = big2ull(x, "long long");
5232
5233 if (BIGNUM_POSITIVE_P(x)) {
5234 if (num <= LLONG_MAX)
5235 return num;
5236 }
5237 else {
5238 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5239 return -(LONG_LONG)(num-1)-1;
5240 }
5241 rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
5242}
5243
5244#endif /* HAVE_LONG_LONG */
5245
5246static VALUE
5247dbl2big(double d)
5248{
5249 long i = 0;
5250 BDIGIT c;
5251 BDIGIT *digits;
5252 VALUE z;
5253 double u = (d < 0)?-d:d;
5254
5255 if (isinf(d)) {
5256 rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
5257 }
5258 if (isnan(d)) {
5259 rb_raise(rb_eFloatDomainError, "NaN");
5260 }
5261
5262 while (1.0 <= u) {
5263 u /= (double)(BIGRAD);
5264 i++;
5265 }
5266 z = bignew(i, d>=0);
5267 digits = BDIGITS(z);
5268 while (i--) {
5269 u *= BIGRAD;
5270 c = (BDIGIT)u;
5271 u -= c;
5272 digits[i] = c;
5273 }
5274
5275 return z;
5276}
5277
5278 VALUE
5279rb_dbl2big(double d)
5280{
5281 return bignorm(dbl2big(d));
5282}
5283
5284static double
5285big2dbl(VALUE x)
5286{
5287 double d = 0.0;
5288 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5289 BDIGIT *ds = BDIGITS(x), dl;
5290
5291 if (i) {
5292 bits = i * BITSPERDIG - nlz(ds[i-1]);
5293 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5294 d = HUGE_VAL;
5295 }
5296 else {
5297 if (bits > DBL_MANT_DIG+1)
5298 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5299 else
5300 bits = 0;
5301 while (--i > lo) {
5302 d = ds[i] + BIGRAD*d;
5303 }
5304 dl = ds[i];
5305 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5306 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5307 if (!carry) {
5308 while (i-- > 0) {
5309 carry = ds[i] != 0;
5310 if (carry) break;
5311 }
5312 }
5313 if (carry) {
5314 BDIGIT mask = BDIGMAX;
5315 BDIGIT bit = 1;
5316 mask <<= bits;
5317 bit <<= bits;
5318 dl &= mask;
5319 dl += bit;
5320 dl = BIGLO(dl);
5321 if (!dl) d += 1;
5322 }
5323 }
5324 d = dl + BIGRAD*d;
5325 if (lo) {
5326 if (lo > INT_MAX / BITSPERDIG)
5327 d = HUGE_VAL;
5328 else if (lo < INT_MIN / BITSPERDIG)
5329 d = 0.0;
5330 else
5331 d = ldexp(d, (int)(lo * BITSPERDIG));
5332 }
5333 }
5334 }
5335 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5336 return d;
5337}
5338
5339double
5340rb_big2dbl(VALUE x)
5341{
5342 double d = big2dbl(x);
5343
5344 if (isinf(d)) {
5345 rb_warning("Integer out of Float range");
5346 if (d < 0.0)
5347 d = -HUGE_VAL;
5348 else
5349 d = HUGE_VAL;
5350 }
5351 return d;
5352}
5353
5354 VALUE
5355rb_integer_float_cmp(VALUE x, VALUE y)
5356{
5357 double yd = RFLOAT_VALUE(y);
5358 double yi, yf;
5359 VALUE rel;
5360
5361 if (isnan(yd))
5362 return Qnil;
5363 if (isinf(yd)) {
5364 if (yd > 0.0) return INT2FIX(-1);
5365 else return INT2FIX(1);
5366 }
5367 yf = modf(yd, &yi);
5368 if (FIXNUM_P(x)) {
5369#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5370 double xd = (double)FIX2LONG(x);
5371 if (xd < yd)
5372 return INT2FIX(-1);
5373 if (xd > yd)
5374 return INT2FIX(1);
5375 return INT2FIX(0);
5376#else
5377 long xn, yn;
5378 if (yi < FIXNUM_MIN)
5379 return INT2FIX(1);
5380 if (FIXNUM_MAX+1 <= yi)
5381 return INT2FIX(-1);
5382 xn = FIX2LONG(x);
5383 yn = (long)yi;
5384 if (xn < yn)
5385 return INT2FIX(-1);
5386 if (xn > yn)
5387 return INT2FIX(1);
5388 if (yf < 0.0)
5389 return INT2FIX(1);
5390 if (0.0 < yf)
5391 return INT2FIX(-1);
5392 return INT2FIX(0);
5393#endif
5394 }
5395 y = rb_dbl2big(yi);
5396 rel = rb_big_cmp(x, y);
5397 if (yf == 0.0 || rel != INT2FIX(0))
5398 return rel;
5399 if (yf < 0.0)
5400 return INT2FIX(1);
5401 return INT2FIX(-1);
5402}
5403
5404#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5405COMPILER_WARNING_PUSH
5406#if __has_warning("-Wimplicit-int-float-conversion")
5407COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
5408#endif
5409static const double LONG_MAX_as_double = LONG_MAX;
5410COMPILER_WARNING_POP
5411#endif
5412
5413 VALUE
5414rb_integer_float_eq(VALUE x, VALUE y)
5415{
5416 double yd = RFLOAT_VALUE(y);
5417 double yi, yf;
5418
5419 if (!isfinite(yd))
5420 return Qfalse;
5421 yf = modf(yd, &yi);
5422 if (yf != 0)
5423 return Qfalse;
5424 if (FIXNUM_P(x)) {
5425#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5426 double xd = (double)FIX2LONG(x);
5427 return RBOOL(xd == yd);
5428#else
5429 long xn, yn;
5430 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5431 return Qfalse;
5432 xn = FIX2LONG(x);
5433 yn = (long)yi;
5434 return RBOOL(xn == yn);
5435#endif
5436 }
5437 y = rb_dbl2big(yi);
5438 return rb_big_eq(x, y);
5439}
5440
5441
5442 VALUE
5443rb_big_cmp(VALUE x, VALUE y)
5444{
5445 if (FIXNUM_P(y)) {
5446 x = bigfixize(x);
5447 if (FIXNUM_P(x)) {
5448 /* SIGNED_VALUE and Fixnum have same sign-bits, same
5449 * order */
5450 SIGNED_VALUE sx = (SIGNED_VALUE)x, sy = (SIGNED_VALUE)y;
5451 if (sx < sy) return INT2FIX(-1);
5452 return INT2FIX(sx > sy);
5453 }
5454 }
5455 else if (RB_BIGNUM_TYPE_P(y)) {
5456 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5457 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5458 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5459 }
5460 }
5461 else if (RB_FLOAT_TYPE_P(y)) {
5462 return rb_integer_float_cmp(x, y);
5463 }
5464 else {
5465 return rb_num_coerce_cmp(x, y, idCmp);
5466 }
5467 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5468}
5469
5470enum big_op_t {
5471 big_op_gt,
5472 big_op_ge,
5473 big_op_lt,
5474 big_op_le
5475};
5476
5477static VALUE
5478big_op(VALUE x, VALUE y, enum big_op_t op)
5479{
5480 VALUE rel;
5481 int n;
5482
5483 if (RB_INTEGER_TYPE_P(y)) {
5484 rel = rb_big_cmp(x, y);
5485 }
5486 else if (RB_FLOAT_TYPE_P(y)) {
5487 rel = rb_integer_float_cmp(x, y);
5488 }
5489 else {
5490 ID id = 0;
5491 switch (op) {
5492 case big_op_gt: id = '>'; break;
5493 case big_op_ge: id = idGE; break;
5494 case big_op_lt: id = '<'; break;
5495 case big_op_le: id = idLE; break;
5496 }
5497 return rb_num_coerce_relop(x, y, id);
5498 }
5499
5500 if (NIL_P(rel)) return Qfalse;
5501 n = FIX2INT(rel);
5502
5503 switch (op) {
5504 case big_op_gt: return RBOOL(n > 0);
5505 case big_op_ge: return RBOOL(n >= 0);
5506 case big_op_lt: return RBOOL(n < 0);
5507 case big_op_le: return RBOOL(n <= 0);
5508 }
5509 return Qundef;
5510}
5511
5512 VALUE
5513rb_big_gt(VALUE x, VALUE y)
5514{
5515 return big_op(x, y, big_op_gt);
5516}
5517
5518 VALUE
5519rb_big_ge(VALUE x, VALUE y)
5520{
5521 return big_op(x, y, big_op_ge);
5522}
5523
5524 VALUE
5525rb_big_lt(VALUE x, VALUE y)
5526{
5527 return big_op(x, y, big_op_lt);
5528}
5529
5530 VALUE
5531rb_big_le(VALUE x, VALUE y)
5532{
5533 return big_op(x, y, big_op_le);
5534}
5535
5536/*
5537 * call-seq:
5538 * big == obj -> true or false
5539 *
5540 * Returns <code>true</code> only if <i>obj</i> has the same value
5541 * as <i>big</i>. Contrast this with Integer#eql?, which requires
5542 * <i>obj</i> to be an Integer.
5543 *
5544 * 68719476736 == 68719476736.0 #=> true
5545 */
5546
5547 VALUE
5548rb_big_eq(VALUE x, VALUE y)
5549{
5550 if (FIXNUM_P(y)) {
5551 return RBOOL(bignorm(x) == y);
5552 }
5553 else if (RB_BIGNUM_TYPE_P(y)) {
5554 }
5555 else if (RB_FLOAT_TYPE_P(y)) {
5556 return rb_integer_float_eq(x, y);
5557 }
5558 else {
5559 return rb_equal(y, x);
5560 }
5561 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5562 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5563 return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5564}
5565
5566 VALUE
5567rb_big_eql(VALUE x, VALUE y)
5568{
5569 if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
5570 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5571 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5572 return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5573}
5574
5575 VALUE
5576rb_big_uminus(VALUE x)
5577{
5578 VALUE z = rb_big_clone(x);
5579
5580 BIGNUM_NEGATE(z);
5581
5582 return bignorm(z);
5583}
5584
5585 VALUE
5586rb_big_comp(VALUE x)
5587{
5588 VALUE z = rb_big_clone(x);
5589 BDIGIT *ds = BDIGITS(z);
5590 long n = BIGNUM_LEN(z);
5591
5592 if (!n) return INT2FIX(-1);
5593
5594 if (BIGNUM_POSITIVE_P(z)) {
5595 if (bary_add_one(ds, n)) {
5596 big_extend_carry(z);
5597 }
5598 BIGNUM_SET_NEGATIVE_SIGN(z);
5599 }
5600 else {
5601 bary_neg(ds, n);
5602 if (bary_add_one(ds, n))
5603 return INT2FIX(-1);
5604 bary_neg(ds, n);
5605 BIGNUM_SET_POSITIVE_SIGN(z);
5606 }
5607
5608 return bignorm(z);
5609}
5610
5611static VALUE
5612bigsub(VALUE x, VALUE y)
5613{
5614 VALUE z;
5615 BDIGIT *xds, *yds, *zds;
5616 long xn, yn, zn;
5617
5618 xn = BIGNUM_LEN(x);
5619 yn = BIGNUM_LEN(y);
5620 zn = xn < yn ? yn : xn;
5621
5622 z = bignew(zn, 1);
5623
5624 xds = BDIGITS(x);
5625 yds = BDIGITS(y);
5626 zds = BDIGITS(z);
5627
5628 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5629 bary_2comp(zds, zn);
5630 BIGNUM_SET_NEGATIVE_SIGN(z);
5631 }
5632
5633 return z;
5634}
5635
5636static VALUE bigadd_int(VALUE x, long y);
5637
5638static VALUE
5639bigsub_int(VALUE x, long y0)
5640{
5641 VALUE z;
5642 BDIGIT *xds, *zds;
5643 long xn, zn;
5644 BDIGIT_DBL_SIGNED num;
5645 long i, y;
5646
5647 y = y0;
5648 xds = BDIGITS(x);
5649 xn = BIGNUM_LEN(x);
5650
5651 if (xn == 0)
5652 return LONG2NUM(-y0);
5653
5654 zn = xn;
5655#if SIZEOF_BDIGIT < SIZEOF_LONG
5656 if (zn < bdigit_roomof(SIZEOF_LONG))
5657 zn = bdigit_roomof(SIZEOF_LONG);
5658#endif
5659 z = bignew(zn, BIGNUM_SIGN(x));
5660 zds = BDIGITS(z);
5661
5662#if SIZEOF_BDIGIT >= SIZEOF_LONG
5663 assert(xn == zn);
5664 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5665 if (xn == 1 && num < 0) {
5666 BIGNUM_NEGATE(z);
5667 zds[0] = (BDIGIT)-num;
5668 RB_GC_GUARD(x);
5669 return bignorm(z);
5670 }
5671 zds[0] = BIGLO(num);
5672 num = BIGDN(num);
5673 i = 1;
5674 if (i < xn)
5675 goto y_is_zero_x;
5676 goto finish;
5677#else
5678 num = 0;
5679 for (i=0; i < xn; i++) {
5680 if (y == 0) goto y_is_zero_x;
5681 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5682 zds[i] = BIGLO(num);
5683 num = BIGDN(num);
5684 y = BIGDN(y);
5685 }
5686 for (; i < zn; i++) {
5687 if (y == 0) goto y_is_zero_z;
5688 num -= BIGLO(y);
5689 zds[i] = BIGLO(num);
5690 num = BIGDN(num);
5691 y = BIGDN(y);
5692 }
5693 goto finish;
5694#endif
5695
5696 for (; i < xn; i++) {
5697 y_is_zero_x:
5698 if (num == 0) goto num_is_zero_x;
5699 num += xds[i];
5700 zds[i] = BIGLO(num);
5701 num = BIGDN(num);
5702 }
5703#if SIZEOF_BDIGIT < SIZEOF_LONG
5704 for (; i < zn; i++) {
5705 y_is_zero_z:
5706 if (num == 0) goto num_is_zero_z;
5707 zds[i] = BIGLO(num);
5708 num = BIGDN(num);
5709 }
5710#endif
5711 goto finish;
5712
5713 for (; i < xn; i++) {
5714 num_is_zero_x:
5715 zds[i] = xds[i];
5716 }
5717#if SIZEOF_BDIGIT < SIZEOF_LONG
5718 for (; i < zn; i++) {
5719 num_is_zero_z:
5720 zds[i] = 0;
5721 }
5722#endif
5723 goto finish;
5724
5725 finish:
5726 assert(num == 0 || num == -1);
5727 if (num < 0) {
5728 get2comp(z);
5729 BIGNUM_NEGATE(z);
5730 }
5731 RB_GC_GUARD(x);
5732 return bignorm(z);
5733}
5734
5735static VALUE
5736bigadd_int(VALUE x, long y)
5737{
5738 VALUE z;
5739 BDIGIT *xds, *zds;
5740 long xn, zn;
5741 BDIGIT_DBL num;
5742 long i;
5743
5744 xds = BDIGITS(x);
5745 xn = BIGNUM_LEN(x);
5746
5747 if (xn == 0)
5748 return LONG2NUM(y);
5749
5750 zn = xn;
5751#if SIZEOF_BDIGIT < SIZEOF_LONG
5752 if (zn < bdigit_roomof(SIZEOF_LONG))
5753 zn = bdigit_roomof(SIZEOF_LONG);
5754#endif
5755 zn++;
5756
5757 z = bignew(zn, BIGNUM_SIGN(x));
5758 zds = BDIGITS(z);
5759
5760#if SIZEOF_BDIGIT >= SIZEOF_LONG
5761 num = (BDIGIT_DBL)xds[0] + y;
5762 zds[0] = BIGLO(num);
5763 num = BIGDN(num);
5764 i = 1;
5765 if (i < xn)
5766 goto y_is_zero_x;
5767 goto y_is_zero_z;
5768#else
5769 num = 0;
5770 for (i=0; i < xn; i++) {
5771 if (y == 0) goto y_is_zero_x;
5772 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5773 zds[i] = BIGLO(num);
5774 num = BIGDN(num);
5775 y = BIGDN(y);
5776 }
5777 for (; i < zn; i++) {
5778 if (y == 0) goto y_is_zero_z;
5779 num += BIGLO(y);
5780 zds[i] = BIGLO(num);
5781 num = BIGDN(num);
5782 y = BIGDN(y);
5783 }
5784 goto finish;
5785
5786#endif
5787
5788 for (;i < xn; i++) {
5789 y_is_zero_x:
5790 if (num == 0) goto num_is_zero_x;
5791 num += (BDIGIT_DBL)xds[i];
5792 zds[i] = BIGLO(num);
5793 num = BIGDN(num);
5794 }
5795 for (; i < zn; i++) {
5796 y_is_zero_z:
5797 if (num == 0) goto num_is_zero_z;
5798 zds[i] = BIGLO(num);
5799 num = BIGDN(num);
5800 }
5801 goto finish;
5802
5803 for (;i < xn; i++) {
5804 num_is_zero_x:
5805 zds[i] = xds[i];
5806 }
5807 for (; i < zn; i++) {
5808 num_is_zero_z:
5809 zds[i] = 0;
5810 }
5811 goto finish;
5812
5813 finish:
5814 RB_GC_GUARD(x);
5815 return bignorm(z);
5816}
5817
5818static VALUE
5819bigadd(VALUE x, VALUE y, int sign)
5820{
5821 VALUE z;
5822 size_t len;
5823
5824 sign = (sign == BIGNUM_SIGN(y));
5825 if (BIGNUM_SIGN(x) != sign) {
5826 if (sign) return bigsub(y, x);
5827 return bigsub(x, y);
5828 }
5829
5830 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5831 len = BIGNUM_LEN(x) + 1;
5832 }
5833 else {
5834 len = BIGNUM_LEN(y) + 1;
5835 }
5836 z = bignew(len, sign);
5837
5838 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5839 BDIGITS(x), BIGNUM_LEN(x),
5840 BDIGITS(y), BIGNUM_LEN(y));
5841
5842 return z;
5843}
5844
5845 VALUE
5846rb_big_plus(VALUE x, VALUE y)
5847{
5848 long n;
5849
5850 if (FIXNUM_P(y)) {
5851 n = FIX2LONG(y);
5852 if ((n > 0) != BIGNUM_SIGN(x)) {
5853 if (n < 0) {
5854 n = -n;
5855 }
5856 return bigsub_int(x, n);
5857 }
5858 if (n < 0) {
5859 n = -n;
5860 }
5861 return bigadd_int(x, n);
5862 }
5863 else if (RB_BIGNUM_TYPE_P(y)) {
5864 return bignorm(bigadd(x, y, 1));
5865 }
5866 else if (RB_FLOAT_TYPE_P(y)) {
5867 return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
5868 }
5869 else {
5870 return rb_num_coerce_bin(x, y, '+');
5871 }
5872}
5873
5874 VALUE
5875rb_big_minus(VALUE x, VALUE y)
5876{
5877 long n;
5878
5879 if (FIXNUM_P(y)) {
5880 n = FIX2LONG(y);
5881 if ((n > 0) != BIGNUM_SIGN(x)) {
5882 if (n < 0) {
5883 n = -n;
5884 }
5885 return bigadd_int(x, n);
5886 }
5887 if (n < 0) {
5888 n = -n;
5889 }
5890 return bigsub_int(x, n);
5891 }
5892 else if (RB_BIGNUM_TYPE_P(y)) {
5893 return bignorm(bigadd(x, y, 0));
5894 }
5895 else if (RB_FLOAT_TYPE_P(y)) {
5896 return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
5897 }
5898 else {
5899 return rb_num_coerce_bin(x, y, '-');
5900 }
5901}
5902
5903static VALUE
5904bigsq(VALUE x)
5905{
5906 long xn, zn;
5907 VALUE z;
5908 BDIGIT *xds, *zds;
5909
5910 xn = BIGNUM_LEN(x);
5911 zn = 2 * xn;
5912
5913 z = bignew(zn, 1);
5914
5915 xds = BDIGITS(x);
5916 zds = BDIGITS(z);
5917
5918 if (xn < NAIVE_MUL_DIGITS)
5919 bary_sq_fast(zds, zn, xds, xn);
5920 else
5921 bary_mul(zds, zn, xds, xn, xds, xn);
5922
5923 RB_GC_GUARD(x);
5924 return z;
5925}
5926
5927static VALUE
5928bigmul0(VALUE x, VALUE y)
5929{
5930 long xn, yn, zn;
5931 VALUE z;
5932 BDIGIT *xds, *yds, *zds;
5933
5934 if (x == y)
5935 return bigsq(x);
5936
5937 xn = BIGNUM_LEN(x);
5938 yn = BIGNUM_LEN(y);
5939 zn = xn + yn;
5940
5941 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5942
5943 xds = BDIGITS(x);
5944 yds = BDIGITS(y);
5945 zds = BDIGITS(z);
5946
5947 bary_mul(zds, zn, xds, xn, yds, yn);
5948
5949 RB_GC_GUARD(x);
5950 RB_GC_GUARD(y);
5951 return z;
5952}
5953
5954 VALUE
5955rb_big_mul(VALUE x, VALUE y)
5956{
5957 if (FIXNUM_P(y)) {
5958 y = rb_int2big(FIX2LONG(y));
5959 }
5960 else if (RB_BIGNUM_TYPE_P(y)) {
5961 }
5962 else if (RB_FLOAT_TYPE_P(y)) {
5963 return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
5964 }
5965 else {
5966 return rb_num_coerce_bin(x, y, '*');
5967 }
5968
5969 return bignorm(bigmul0(x, y));
5970}
5971
5972static VALUE
5973bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
5974{
5975 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
5976 VALUE z;
5977 BDIGIT *xds, *yds, *zds;
5978 BDIGIT dd;
5979
5980 VALUE q = Qnil, r = Qnil;
5981 BDIGIT *qds, *rds;
5982 long qn, rn;
5983
5984 yds = BDIGITS(y);
5985 BARY_TRUNC(yds, yn);
5986 if (yn == 0)
5987 rb_num_zerodiv();
5988
5989 xds = BDIGITS(x);
5990 BARY_TRUNC(xds, xn);
5991
5992 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
5993 if (divp) *divp = rb_int2big(0);
5994 if (modp) *modp = x;
5995 return Qnil;
5996 }
5997 if (yn == 1) {
5998 dd = yds[0];
5999 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6000 zds = BDIGITS(z);
6001 dd = bigdivrem_single(zds, xds, xn, dd);
6002 if (modp) {
6003 *modp = rb_uint2big((uintptr_t)dd);
6004 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6005 }
6006 if (divp) *divp = z;
6007 return Qnil;
6008 }
6009 if (xn == 2 && yn == 2) {
6010 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6011 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6012 BDIGIT_DBL q0 = x0 / y0;
6013 BDIGIT_DBL r0 = x0 % y0;
6014 if (divp) {
6015 z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6016 zds = BDIGITS(z);
6017 zds[0] = BIGLO(q0);
6018 zds[1] = BIGLO(BIGDN(q0));
6019 *divp = z;
6020 }
6021 if (modp) {
6022 z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6023 zds = BDIGITS(z);
6024 zds[0] = BIGLO(r0);
6025 zds[1] = BIGLO(BIGDN(r0));
6026 *modp = z;
6027 }
6028 return Qnil;
6029 }
6030
6031 if (divp) {
6032 qn = xn + BIGDIVREM_EXTRA_WORDS;
6033 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6034 qds = BDIGITS(q);
6035 }
6036 else {
6037 qn = 0;
6038 qds = NULL;
6039 }
6040
6041 if (modp) {
6042 rn = yn;
6043 r = bignew(rn, BIGNUM_SIGN(x));
6044 rds = BDIGITS(r);
6045 }
6046 else {
6047 rn = 0;
6048 rds = NULL;
6049 }
6050
6051 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6052
6053 if (divp) {
6054 bigtrunc(q);
6055 *divp = q;
6056 }
6057 if (modp) {
6058 bigtrunc(r);
6059 *modp = r;
6060 }
6061
6062 return Qnil;
6063}
6064
6065static void
6066bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
6067{
6068 VALUE mod;
6069
6070 bigdivrem(x, y, divp, &mod);
6071 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6072 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6073 if (modp) *modp = bigadd(mod, y, 1);
6074 }
6075 else if (modp) {
6076 *modp = mod;
6077 }
6078}
6079
6080
6081static VALUE
6082rb_big_divide(VALUE x, VALUE y, ID op)
6083{
6084 VALUE z;
6085
6086 if (FIXNUM_P(y)) {
6087 y = rb_int2big(FIX2LONG(y));
6088 }
6089 else if (RB_BIGNUM_TYPE_P(y)) {
6090 }
6091 else if (RB_FLOAT_TYPE_P(y)) {
6092 if (op == '/') {
6093 double dx = rb_big2dbl(x);
6094 return rb_flo_div_flo(DBL2NUM(dx), y);
6095 }
6096 else {
6097 VALUE v;
6098 double dy = RFLOAT_VALUE(y);
6099 if (dy == 0.0) rb_num_zerodiv();
6100 v = rb_big_divide(x, y, '/');
6101 return rb_dbl2big(RFLOAT_VALUE(v));
6102 }
6103 }
6104 else {
6105 return rb_num_coerce_bin(x, y, op);
6106 }
6107 bigdivmod(x, y, &z, 0);
6108
6109 return bignorm(z);
6110}
6111
6112 VALUE
6113rb_big_div(VALUE x, VALUE y)
6114{
6115 return rb_big_divide(x, y, '/');
6116}
6117
6118 VALUE
6119rb_big_idiv(VALUE x, VALUE y)
6120{
6121 return rb_big_divide(x, y, idDiv);
6122}
6123
6124 VALUE
6125rb_big_modulo(VALUE x, VALUE y)
6126{
6127 VALUE z;
6128
6129 if (FIXNUM_P(y)) {
6130 y = rb_int2big(FIX2LONG(y));
6131 }
6132 else if (!RB_BIGNUM_TYPE_P(y)) {
6133 return rb_num_coerce_bin(x, y, '%');
6134 }
6135 bigdivmod(x, y, 0, &z);
6136
6137 return bignorm(z);
6138}
6139
6140 VALUE
6141rb_big_remainder(VALUE x, VALUE y)
6142{
6143 VALUE z;
6144
6145 if (FIXNUM_P(y)) {
6146 y = rb_int2big(FIX2LONG(y));
6147 }
6148 else if (!RB_BIGNUM_TYPE_P(y)) {
6149 return rb_num_coerce_bin(x, y, rb_intern("remainder"));
6150 }
6151 bigdivrem(x, y, 0, &z);
6152
6153 return bignorm(z);
6154}
6155
6156 VALUE
6157rb_big_divmod(VALUE x, VALUE y)
6158{
6159 VALUE div, mod;
6160
6161 if (FIXNUM_P(y)) {
6162 y = rb_int2big(FIX2LONG(y));
6163 }
6164 else if (!RB_BIGNUM_TYPE_P(y)) {
6165 return rb_num_coerce_bin(x, y, idDivmod);
6166 }
6167 bigdivmod(x, y, &div, &mod);
6168
6169 return rb_assoc_new(bignorm(div), bignorm(mod));
6170}
6171
6172static VALUE
6173big_shift(VALUE x, long n)
6174{
6175 if (n < 0)
6176 return big_lshift(x, 1+(unsigned long)(-(n+1)));
6177 else if (n > 0)
6178 return big_rshift(x, (unsigned long)n);
6179 return x;
6180}
6181
6182enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6183
6184static double
6185big_fdiv(VALUE x, VALUE y, long ey)
6186{
6187 VALUE z;
6188 long l, ex;
6189
6190 bigtrunc(x);
6191 l = BIGNUM_LEN(x);
6192 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6193 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6194 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6195 else if (ex > 0) ex = 0;
6196 if (ex) x = big_shift(x, ex);
6197
6198 bigdivrem(x, y, &z, 0);
6199 l = ex - ey;
6200#if SIZEOF_LONG > SIZEOF_INT
6201 {
6202 /* Visual C++ can't be here */
6203 if (l > INT_MAX) return HUGE_VAL;
6204 if (l < INT_MIN) return 0.0;
6205 }
6206#endif
6207 return ldexp(big2dbl(z), (int)l);
6208}
6209
6210static double
6211big_fdiv_int(VALUE x, VALUE y)
6212{
6213 long l, ey;
6214 bigtrunc(y);
6215 l = BIGNUM_LEN(y);
6216 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6217 ey -= DBL_BIGDIG * BITSPERDIG;
6218 if (ey) y = big_shift(y, ey);
6219 return big_fdiv(x, y, ey);
6220}
6221
6222static double
6223big_fdiv_float(VALUE x, VALUE y)
6224{
6225 int i;
6226 y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6227 return big_fdiv(x, y, i - DBL_MANT_DIG);
6228}
6229
6230double
6231rb_big_fdiv_double(VALUE x, VALUE y)
6232{
6233 double dx, dy;
6234 VALUE v;
6235
6236 dx = big2dbl(x);
6237 if (FIXNUM_P(y)) {
6238 dy = (double)FIX2LONG(y);
6239 if (isinf(dx))
6240 return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
6241 }
6242 else if (RB_BIGNUM_TYPE_P(y)) {
6243 return big_fdiv_int(x, y);
6244 }
6245 else if (RB_FLOAT_TYPE_P(y)) {
6246 dy = RFLOAT_VALUE(y);
6247 if (isnan(dy))
6248 return dy;
6249 if (isinf(dx))
6250 return big_fdiv_float(x, y);
6251 }
6252 else {
6253 return NUM2DBL(rb_num_coerce_bin(x, y, idFdiv));
6254 }
6255 v = rb_flo_div_flo(DBL2NUM(dx), DBL2NUM(dy));
6256 return NUM2DBL(v);
6257}
6258
6259 VALUE
6260rb_big_fdiv(VALUE x, VALUE y)
6261{
6262 return DBL2NUM(rb_big_fdiv_double(x, y));
6263}
6264
6265 VALUE
6266rb_big_pow(VALUE x, VALUE y)
6267{
6268 double d;
6269 SIGNED_VALUE yy;
6270
6271 again:
6272 if (y == INT2FIX(0)) return INT2FIX(1);
6273 if (y == INT2FIX(1)) return x;
6274 if (RB_FLOAT_TYPE_P(y)) {
6275 d = RFLOAT_VALUE(y);
6276 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6277 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6278 }
6279 }
6280 else if (RB_BIGNUM_TYPE_P(y)) {
6281 y = bignorm(y);
6282 if (FIXNUM_P(y))
6283 goto again;
6284 rb_warn("in a**b, b may be too big");
6285 d = rb_big2dbl(y);
6286 }
6287 else if (FIXNUM_P(y)) {
6288 yy = FIX2LONG(y);
6289
6290 if (yy < 0) {
6291 x = rb_big_pow(x, LONG2NUM(-yy));
6292 if (RB_INTEGER_TYPE_P(x))
6293 return rb_rational_raw(INT2FIX(1), x);
6294 else
6295 return DBL2NUM(1.0 / NUM2DBL(x));
6296 }
6297 else {
6298 VALUE z = 0;
6299 SIGNED_VALUE mask;
6300 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6301 const size_t BIGLEN_LIMIT = 32*1024*1024;
6302
6303 if (xbits == (size_t)-1 ||
6304 (xbits > BIGLEN_LIMIT) ||
6305 (xbits * yy > BIGLEN_LIMIT)) {
6306 rb_warn("in a**b, b may be too big");
6307 d = (double)yy;
6308 }
6309 else {
6310 for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
6311 if (z) z = bigsq(z);
6312 if (yy & mask) {
6313 z = z ? bigtrunc(bigmul0(z, x)) : x;
6314 }
6315 }
6316 return bignorm(z);
6317 }
6318 }
6319 }
6320 else {
6321 return rb_num_coerce_bin(x, y, idPow);
6322 }
6323 return DBL2NUM(pow(rb_big2dbl(x), d));
6324}
6325
6326static VALUE
6327bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6328{
6329 VALUE z;
6330 BDIGIT *xds, *zds;
6331 long zn;
6332 long i;
6333 BDIGIT hibitsy;
6334
6335 if (y == 0) return INT2FIX(0);
6336 if (xn == 0) return hibitsx ? LONG2NUM(y) : 0;
6337 hibitsy = 0 <= y ? 0 : BDIGMAX;
6338 xds = BDIGITS(x);
6339#if SIZEOF_BDIGIT >= SIZEOF_LONG
6340 if (!hibitsy) {
6341 y &= xds[0];
6342 return LONG2NUM(y);
6343 }
6344#endif
6345
6346 zn = xn;
6347#if SIZEOF_BDIGIT < SIZEOF_LONG
6348 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6349 zn = bdigit_roomof(SIZEOF_LONG);
6350#endif
6351
6352 z = bignew(zn, 0);
6353 zds = BDIGITS(z);
6354
6355#if SIZEOF_BDIGIT >= SIZEOF_LONG
6356 i = 1;
6357 zds[0] = xds[0] & BIGLO(y);
6358#else
6359 for (i=0; i < xn; i++) {
6360 if (y == 0 || y == -1) break;
6361 zds[i] = xds[i] & BIGLO(y);
6362 y = BIGDN(y);
6363 }
6364 for (; i < zn; i++) {
6365 if (y == 0 || y == -1) break;
6366 zds[i] = hibitsx & BIGLO(y);
6367 y = BIGDN(y);
6368 }
6369#endif
6370 for (;i < xn; i++) {
6371 zds[i] = xds[i] & hibitsy;
6372 }
6373 for (;i < zn; i++) {
6374 zds[i] = hibitsx & hibitsy;
6375 }
6376 twocomp2abs_bang(z, hibitsx && hibitsy);
6377 RB_GC_GUARD(x);
6378 return bignorm(z);
6379}
6380
6381 VALUE
6382rb_big_and(VALUE x, VALUE y)
6383{
6384 VALUE z;
6385 BDIGIT *ds1, *ds2, *zds;
6386 long i, xn, yn, n1, n2;
6387 BDIGIT hibitsx, hibitsy;
6388 BDIGIT hibits1, hibits2;
6389 VALUE tmpv;
6390 BDIGIT tmph;
6391 long tmpn;
6392
6393 if (!RB_INTEGER_TYPE_P(y)) {
6394 return rb_num_coerce_bit(x, y, '&');
6395 }
6396
6397 hibitsx = abs2twocomp(&x, &xn);
6398 if (FIXNUM_P(y)) {
6399 return bigand_int(x, xn, hibitsx, FIX2LONG(y));
6400 }
6401 hibitsy = abs2twocomp(&y, &yn);
6402 if (xn > yn) {
6403 tmpv = x; x = y; y = tmpv;
6404 tmpn = xn; xn = yn; yn = tmpn;
6405 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6406 }
6407 n1 = xn;
6408 n2 = yn;
6409 ds1 = BDIGITS(x);
6410 ds2 = BDIGITS(y);
6411 hibits1 = hibitsx;
6412 hibits2 = hibitsy;
6413
6414 if (!hibits1)
6415 n2 = n1;
6416
6417 z = bignew(n2, 0);
6418 zds = BDIGITS(z);
6419
6420 for (i=0; i<n1; i++) {
6421 zds[i] = ds1[i] & ds2[i];
6422 }
6423 for (; i<n2; i++) {
6424 zds[i] = hibits1 & ds2[i];
6425 }
6426 twocomp2abs_bang(z, hibits1 && hibits2);
6427 RB_GC_GUARD(x);
6428 RB_GC_GUARD(y);
6429 return bignorm(z);
6430}
6431
6432static VALUE
6433bigor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6434{
6435 VALUE z;
6436 BDIGIT *xds, *zds;
6437 long zn;
6438 long i;
6439 BDIGIT hibitsy;
6440
6441 if (y == -1) return INT2FIX(-1);
6442 if (xn == 0) return hibitsx ? INT2FIX(-1) : LONG2FIX(y);
6443 hibitsy = 0 <= y ? 0 : BDIGMAX;
6444 xds = BDIGITS(x);
6445
6446 zn = BIGNUM_LEN(x);
6447#if SIZEOF_BDIGIT < SIZEOF_LONG
6448 if (zn < bdigit_roomof(SIZEOF_LONG))
6449 zn = bdigit_roomof(SIZEOF_LONG);
6450#endif
6451 z = bignew(zn, 0);
6452 zds = BDIGITS(z);
6453
6454#if SIZEOF_BDIGIT >= SIZEOF_LONG
6455 i = 1;
6456 zds[0] = xds[0] | BIGLO(y);
6457 if (i < zn)
6458 goto y_is_fixed_point;
6459 goto finish;
6460#else
6461 for (i=0; i < xn; i++) {
6462 if (y == 0 || y == -1) goto y_is_fixed_point;
6463 zds[i] = xds[i] | BIGLO(y);
6464 y = BIGDN(y);
6465 }
6466 if (hibitsx)
6467 goto fill_hibits;
6468 for (; i < zn; i++) {
6469 if (y == 0 || y == -1) goto y_is_fixed_point;
6470 zds[i] = BIGLO(y);
6471 y = BIGDN(y);
6472 }
6473 goto finish;
6474#endif
6475
6476 y_is_fixed_point:
6477 if (hibitsy)
6478 goto fill_hibits;
6479 for (; i < xn; i++) {
6480 zds[i] = xds[i];
6481 }
6482 if (hibitsx)
6483 goto fill_hibits;
6484 for (; i < zn; i++) {
6485 zds[i] = 0;
6486 }
6487 goto finish;
6488
6489 fill_hibits:
6490 for (; i < zn; i++) {
6491 zds[i] = BDIGMAX;
6492 }
6493
6494 finish:
6495 twocomp2abs_bang(z, hibitsx || hibitsy);
6496 RB_GC_GUARD(x);
6497 return bignorm(z);
6498}
6499
6500 VALUE
6501rb_big_or(VALUE x, VALUE y)
6502{
6503 VALUE z;
6504 BDIGIT *ds1, *ds2, *zds;
6505 long i, xn, yn, n1, n2;
6506 BDIGIT hibitsx, hibitsy;
6507 BDIGIT hibits1, hibits2;
6508 VALUE tmpv;
6509 BDIGIT tmph;
6510 long tmpn;
6511
6512 if (!RB_INTEGER_TYPE_P(y)) {
6513 return rb_num_coerce_bit(x, y, '|');
6514 }
6515
6516 hibitsx = abs2twocomp(&x, &xn);
6517 if (FIXNUM_P(y)) {
6518 return bigor_int(x, xn, hibitsx, FIX2LONG(y));
6519 }
6520 hibitsy = abs2twocomp(&y, &yn);
6521 if (xn > yn) {
6522 tmpv = x; x = y; y = tmpv;
6523 tmpn = xn; xn = yn; yn = tmpn;
6524 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6525 }
6526 n1 = xn;
6527 n2 = yn;
6528 ds1 = BDIGITS(x);
6529 ds2 = BDIGITS(y);
6530 hibits1 = hibitsx;
6531 hibits2 = hibitsy;
6532
6533 if (hibits1)
6534 n2 = n1;
6535
6536 z = bignew(n2, 0);
6537 zds = BDIGITS(z);
6538
6539 for (i=0; i<n1; i++) {
6540 zds[i] = ds1[i] | ds2[i];
6541 }
6542 for (; i<n2; i++) {
6543 zds[i] = hibits1 | ds2[i];
6544 }
6545 twocomp2abs_bang(z, hibits1 || hibits2);
6546 RB_GC_GUARD(x);
6547 RB_GC_GUARD(y);
6548 return bignorm(z);
6549}
6550
6551static VALUE
6552bigxor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6553{
6554 VALUE z;
6555 BDIGIT *xds, *zds;
6556 long zn;
6557 long i;
6558 BDIGIT hibitsy;
6559
6560 hibitsy = 0 <= y ? 0 : BDIGMAX;
6561 xds = BDIGITS(x);
6562 zn = BIGNUM_LEN(x);
6563#if SIZEOF_BDIGIT < SIZEOF_LONG
6564 if (zn < bdigit_roomof(SIZEOF_LONG))
6565 zn = bdigit_roomof(SIZEOF_LONG);
6566#endif
6567 z = bignew(zn, 0);
6568 zds = BDIGITS(z);
6569
6570#if SIZEOF_BDIGIT >= SIZEOF_LONG
6571 i = 1;
6572 zds[0] = xds[0] ^ BIGLO(y);
6573#else
6574 for (i = 0; i < xn; i++) {
6575 zds[i] = xds[i] ^ BIGLO(y);
6576 y = BIGDN(y);
6577 }
6578 for (; i < zn; i++) {
6579 zds[i] = hibitsx ^ BIGLO(y);
6580 y = BIGDN(y);
6581 }
6582#endif
6583 for (; i < xn; i++) {
6584 zds[i] = xds[i] ^ hibitsy;
6585 }
6586 for (; i < zn; i++) {
6587 zds[i] = hibitsx ^ hibitsy;
6588 }
6589 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6590 RB_GC_GUARD(x);
6591 return bignorm(z);
6592}
6593
6594 VALUE
6595rb_big_xor(VALUE x, VALUE y)
6596{
6597 VALUE z;
6598 BDIGIT *ds1, *ds2, *zds;
6599 long i, xn, yn, n1, n2;
6600 BDIGIT hibitsx, hibitsy;
6601 BDIGIT hibits1, hibits2;
6602 VALUE tmpv;
6603 BDIGIT tmph;
6604 long tmpn;
6605
6606 if (!RB_INTEGER_TYPE_P(y)) {
6607 return rb_num_coerce_bit(x, y, '^');
6608 }
6609
6610 hibitsx = abs2twocomp(&x, &xn);
6611 if (FIXNUM_P(y)) {
6612 return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
6613 }
6614 hibitsy = abs2twocomp(&y, &yn);
6615 if (xn > yn) {
6616 tmpv = x; x = y; y = tmpv;
6617 tmpn = xn; xn = yn; yn = tmpn;
6618 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6619 }
6620 n1 = xn;
6621 n2 = yn;
6622 ds1 = BDIGITS(x);
6623 ds2 = BDIGITS(y);
6624 hibits1 = hibitsx;
6625 hibits2 = hibitsy;
6626
6627 z = bignew(n2, 0);
6628 zds = BDIGITS(z);
6629
6630 for (i=0; i<n1; i++) {
6631 zds[i] = ds1[i] ^ ds2[i];
6632 }
6633 for (; i<n2; i++) {
6634 zds[i] = hibitsx ^ ds2[i];
6635 }
6636 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6637 RB_GC_GUARD(x);
6638 RB_GC_GUARD(y);
6639 return bignorm(z);
6640}
6641
6642 VALUE
6643rb_big_lshift(VALUE x, VALUE y)
6644{
6645 int lshift_p;
6646 size_t shift_numdigits;
6647 int shift_numbits;
6648
6649 for (;;) {
6650 if (FIXNUM_P(y)) {
6651 long l = FIX2LONG(y);
6652 unsigned long shift;
6653 if (0 <= l) {
6654 lshift_p = 1;
6655 shift = l;
6656 }
6657 else {
6658 lshift_p = 0;
6659 shift = 1+(unsigned long)(-(l+1));
6660 }
6661 shift_numbits = (int)(shift & (BITSPERDIG-1));
6662 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6663 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6664 }
6665 else if (RB_BIGNUM_TYPE_P(y)) {
6666 return bignorm(big_shift2(x, 1, y));
6667 }
6668 y = rb_to_int(y);
6669 }
6670}
6671
6672 VALUE
6673rb_big_rshift(VALUE x, VALUE y)
6674{
6675 int lshift_p;
6676 size_t shift_numdigits;
6677 int shift_numbits;
6678
6679 for (;;) {
6680 if (FIXNUM_P(y)) {
6681 long l = FIX2LONG(y);
6682 unsigned long shift;
6683 if (0 <= l) {
6684 lshift_p = 0;
6685 shift = l;
6686 }
6687 else {
6688 lshift_p = 1;
6689 shift = 1+(unsigned long)(-(l+1));
6690 }
6691 shift_numbits = (int)(shift & (BITSPERDIG-1));
6692 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6693 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6694 }
6695 else if (RB_BIGNUM_TYPE_P(y)) {
6696 return bignorm(big_shift2(x, 0, y));
6697 }
6698 y = rb_to_int(y);
6699 }
6700}
6701
6702 VALUE
6703rb_big_aref(VALUE x, VALUE y)
6704{
6705 BDIGIT *xds;
6706 size_t shift;
6707 size_t i, s1, s2;
6708 long l;
6709 BDIGIT bit;
6710
6711 if (RB_BIGNUM_TYPE_P(y)) {
6712 if (BIGNUM_NEGATIVE_P(y))
6713 return INT2FIX(0);
6714 bigtrunc(y);
6715 if (BIGSIZE(y) > sizeof(size_t)) {
6716 return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
6717 }
6718#if SIZEOF_SIZE_T <= SIZEOF_LONG
6719 shift = big2ulong(y, "long");
6720#else
6721 shift = big2ull(y, "long long");
6722#endif
6723 }
6724 else {
6725 l = NUM2LONG(y);
6726 if (l < 0) return INT2FIX(0);
6727 shift = (size_t)l;
6728 }
6729 s1 = shift/BITSPERDIG;
6730 s2 = shift%BITSPERDIG;
6731 bit = (BDIGIT)1 << s2;
6732
6733 if (s1 >= BIGNUM_LEN(x))
6734 return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
6735
6736 xds = BDIGITS(x);
6737 if (BIGNUM_POSITIVE_P(x))
6738 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6739 if (xds[s1] & (bit-1))
6740 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6741 for (i = 0; i < s1; i++)
6742 if (xds[i])
6743 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6744 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6745}
6746
6747 VALUE
6748rb_big_hash(VALUE x)
6749{
6750 st_index_t hash;
6751
6752 hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6753 return ST2FIX(hash);
6754}
6755
6756/*
6757 * call-seq:
6758 * int.coerce(numeric) -> array
6759 *
6760 * Returns an array with both a +numeric+ and a +int+ represented as
6761 * Integer objects or Float objects.
6762 *
6763 * This is achieved by converting +numeric+ to an Integer or a Float.
6764 *
6765 * A TypeError is raised if the +numeric+ is not an Integer or a Float
6766 * type.
6767 *
6768 * (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
6769 */
6770
6771static VALUE
6772rb_int_coerce(VALUE x, VALUE y)
6773{
6774 if (RB_INTEGER_TYPE_P(y)) {
6775 return rb_assoc_new(y, x);
6776 }
6777 else {
6778 x = rb_Float(x);
6779 y = rb_Float(y);
6780 return rb_assoc_new(y, x);
6781 }
6782}
6783
6784 VALUE
6785rb_big_abs(VALUE x)
6786{
6787 if (BIGNUM_NEGATIVE_P(x)) {
6788 x = rb_big_clone(x);
6789 BIGNUM_SET_POSITIVE_SIGN(x);
6790 }
6791 return x;
6792}
6793
6794int
6795rb_big_sign(VALUE x)
6796{
6797 return BIGNUM_SIGN(x);
6798}
6799
6800size_t
6801rb_big_size(VALUE big)
6802{
6803 return BIGSIZE(big);
6804}
6805
6806 VALUE
6807rb_big_size_m(VALUE big)
6808{
6809 return SIZET2NUM(rb_big_size(big));
6810}
6811
6812 VALUE
6813rb_big_bit_length(VALUE big)
6814{
6815 int nlz_bits;
6816 size_t numbytes;
6817
6818 static const BDIGIT char_bit[1] = { CHAR_BIT };
6819 BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
6820 BDIGIT nlz_bary[1];
6821 BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
6822
6823 numbytes = rb_absint_size(big, &nlz_bits);
6824
6825 if (numbytes == 0)
6826 return LONG2FIX(0);
6827
6828 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6829 if (nlz_bits != CHAR_BIT-1) {
6830 nlz_bits++;
6831 }
6832 else {
6833 nlz_bits = 0;
6834 numbytes--;
6835 }
6836 }
6837
6838 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6839 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6840 }
6841
6842 nlz_bary[0] = nlz_bits;
6843
6844 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
6845 INTEGER_PACK_NATIVE_BYTE_ORDER);
6846 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6847 BARY_SUB(result_bary, result_bary, nlz_bary);
6848
6849 return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
6850 INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
6851}
6852
6853 VALUE
6854rb_big_odd_p(VALUE num)
6855{
6856 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6857}
6858
6859 VALUE
6860rb_big_even_p(VALUE num)
6861{
6862 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6863 return Qfalse;
6864 }
6865 return Qtrue;
6866}
6867
6868unsigned long rb_ulong_isqrt(unsigned long);
6869#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6870BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6871# ifdef ULL_TO_DOUBLE
6872# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6873# endif
6874#else
6875# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6876#endif
6877#ifndef BDIGIT_DBL_TO_DOUBLE
6878# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
6879#endif
6880
6881static BDIGIT *
6882estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
6883{
6884 enum {dbl_per_bdig = roomof(DBL_MANT_DIG,BITSPERDIG)};
6885 const int zbits = nlz(nds[len-1]);
6886 VALUE x = *xp = bignew_1(0, xn, 1); /* division may release the GVL */
6887 BDIGIT *xds = BDIGITS(x);
6888 BDIGIT_DBL d = bary2bdigitdbl(nds+len-dbl_per_bdig, dbl_per_bdig);
6889 BDIGIT lowbits = 1;
6890 int rshift = (int)((BITSPERDIG*2-zbits+(len&BITSPERDIG&1) - DBL_MANT_DIG + 1) & ~1);
6891 double f;
6892
6893 if (rshift > 0) {
6894 lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift);
6895 d >>= rshift;
6896 }
6897 else if (rshift < 0) {
6898 d <<= -rshift;
6899 d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift);
6900 }
6901 f = sqrt(BDIGIT_DBL_TO_DOUBLE(d));
6902 d = (BDIGIT_DBL)ceil(f);
6903 if (BDIGIT_DBL_TO_DOUBLE(d) == f) {
6904 if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig)))
6905 ++d;
6906 }
6907 else {
6908 lowbits = 1;
6909 }
6910 rshift /= 2;
6911 rshift += (2-(len&1))*BITSPERDIG/2;
6912 if (rshift >= 0) {
6913 if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) {
6914 /* (d << rshift) does cause overflow.
6915 * example: Integer.sqrt(0xffff_ffff_ffff_ffff ** 2)
6916 */
6917 d = ~(BDIGIT_DBL)0;
6918 }
6919 else {
6920 d <<= rshift;
6921 }
6922 }
6923 BDIGITS_ZERO(xds, xn-2);
6924 bdigitdbl2bary(&xds[xn-2], 2, d);
6925
6926 if (!lowbits) return NULL; /* special case, exact result */
6927 return xds;
6928}
6929
6930 VALUE
6931rb_big_isqrt(VALUE n)
6932{
6933 BDIGIT *nds = BDIGITS(n);
6934 size_t len = BIGNUM_LEN(n);
6935 size_t xn = (len+1) / 2;
6936 VALUE x;
6937 BDIGIT *xds;
6938
6939 if (len <= 2) {
6940 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
6941#if SIZEOF_BDIGIT > SIZEOF_LONG
6942 return ULL2NUM(sq);
6943#else
6944 return ULONG2NUM(sq);
6945#endif
6946 }
6947 else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) {
6948 size_t tn = xn + BIGDIVREM_EXTRA_WORDS;
6949 VALUE t = bignew_1(0, tn, 1);
6950 BDIGIT *tds = BDIGITS(t);
6951 tn = BIGNUM_LEN(t);
6952
6953 /* t = n/x */
6954 while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn),
6955 bary_cmp(tds, tn, xds, xn) < 0) {
6956 int carry;
6957 BARY_TRUNC(tds, tn);
6958 /* x = (x+t)/2 */
6959 carry = bary_add(xds, xn, xds, xn, tds, tn);
6960 bary_small_rshift(xds, xds, xn, 1, carry);
6961 tn = BIGNUM_LEN(t);
6962 }
6963 }
6964 RBASIC_SET_CLASS_RAW(x, rb_cInteger);
6965 return x;
6966}
6967
6968#if USE_GMP
6969static void
6970bary_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)
6971{
6972 mpz_t z, x, y, m;
6973 size_t count;
6974 mpz_init(x);
6975 mpz_init(y);
6976 mpz_init(m);
6977 mpz_init(z);
6978 bdigits_to_mpz(x, xds, xn);
6979 bdigits_to_mpz(y, yds, yn);
6980 bdigits_to_mpz(m, mds, mn);
6981 mpz_powm(z, x, y, m);
6982 bdigits_from_mpz(z, zds, &count);
6983 BDIGITS_ZERO(zds+count, zn-count);
6984 mpz_clear(x);
6985 mpz_clear(y);
6986 mpz_clear(m);
6987 mpz_clear(z);
6988}
6989#endif
6990
6991static VALUE
6992int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
6993{
6994#if USE_GMP
6995 VALUE z;
6996 size_t xn, yn, mn, zn;
6997
6998 if (FIXNUM_P(x)) {
6999 x = rb_int2big(FIX2LONG(x));
7000 }
7001 if (FIXNUM_P(y)) {
7002 y = rb_int2big(FIX2LONG(y));
7003 }
7004 assert(RB_BIGNUM_TYPE_P(m));
7005 xn = BIGNUM_LEN(x);
7006 yn = BIGNUM_LEN(y);
7007 mn = BIGNUM_LEN(m);
7008 zn = mn;
7009 z = bignew(zn, 1);
7010 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7011 if (nega_flg & BIGNUM_POSITIVE_P(z)) {
7012 z = rb_big_minus(z, m);
7013 }
7014 RB_GC_GUARD(x);
7015 RB_GC_GUARD(y);
7016 RB_GC_GUARD(m);
7017 return rb_big_norm(z);
7018#else
7019 VALUE tmp = LONG2FIX(1L);
7020 long yy;
7021
7022 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7023 if (RTEST(rb_int_odd_p(y))) {
7024 tmp = rb_int_mul(tmp, x);
7025 tmp = rb_int_modulo(tmp, m);
7026 }
7027 x = rb_int_mul(x, x);
7028 x = rb_int_modulo(x, m);
7029 }
7030 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7031 if (yy & 1L) {
7032 tmp = rb_int_mul(tmp, x);
7033 tmp = rb_int_modulo(tmp, m);
7034 }
7035 x = rb_int_mul(x, x);
7036 x = rb_int_modulo(x, m);
7037 }
7038
7039 if (nega_flg && rb_int_positive_p(tmp)) {
7040 tmp = rb_int_minus(tmp, m);
7041 }
7042 return tmp;
7043#endif
7044}
7045
7046/*
7047 * Integer#pow
7048 */
7049
7050static VALUE
7051int_pow_tmp1(VALUE x, VALUE y, long mm, int nega_flg)
7052{
7053 long xx = FIX2LONG(x);
7054 long tmp = 1L;
7055 long yy;
7056
7057 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7058 if (RTEST(rb_int_odd_p(y))) {
7059 tmp = (tmp * xx) % mm;
7060 }
7061 xx = (xx * xx) % mm;
7062 }
7063 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7064 if (yy & 1L) {
7065 tmp = (tmp * xx) % mm;
7066 }
7067 xx = (xx * xx) % mm;
7068 }
7069
7070 if (nega_flg && tmp) {
7071 tmp -= mm;
7072 }
7073 return LONG2FIX(tmp);
7074}
7075
7076static VALUE
7077int_pow_tmp2(VALUE x, VALUE y, long mm, int nega_flg)
7078{
7079 long tmp = 1L;
7080 long yy;
7081#ifdef DLONG
7082 const DLONG m = mm;
7083 long tmp2 = tmp;
7084 long xx = FIX2LONG(x);
7085# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7086#else
7087 const VALUE m = LONG2FIX(mm);
7088 VALUE tmp2 = LONG2FIX(tmp);
7089 VALUE xx = x;
7090# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7091#endif
7092
7093 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7094 if (RTEST(rb_int_odd_p(y))) {
7095 tmp2 = MUL_MODULO(tmp2, xx, m);
7096 }
7097 xx = MUL_MODULO(xx, xx, m);
7098 }
7099 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7100 if (yy & 1L) {
7101 tmp2 = MUL_MODULO(tmp2, xx, m);
7102 }
7103 xx = MUL_MODULO(xx, xx, m);
7104 }
7105
7106#ifdef DLONG
7107 tmp = tmp2;
7108#else
7109 tmp = FIX2LONG(tmp2);
7110#endif
7111 if (nega_flg && tmp) {
7112 tmp -= mm;
7113 }
7114 return LONG2FIX(tmp);
7115}
7116
7117/*
7118 * Document-method: Integer#pow
7119 * call-seq:
7120 * integer.pow(numeric) -> numeric
7121 * integer.pow(integer, integer) -> integer
7122 *
7123 * Returns (modular) exponentiation as:
7124 *
7125 * a.pow(b) #=> same as a**b
7126 * a.pow(b, m) #=> same as (a**b) % m, but avoids huge temporary values
7127 */
7128 VALUE
7129rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
7130{
7131 rb_check_arity(argc, 1, 2);
7132
7133 if (argc == 1) {
7134 return rb_int_pow(num, argv[0]);
7135 }
7136 else {
7137 VALUE const a = num;
7138 VALUE const b = argv[0];
7139 VALUE m = argv[1];
7140 int nega_flg = 0;
7141 if ( ! RB_INTEGER_TYPE_P(b)) {
7142 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7143 }
7144 if (rb_int_negative_p(b)) {
7145 rb_raise(rb_eRangeError, "Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7146 }
7147 if (!RB_INTEGER_TYPE_P(m)) {
7148 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
7149 }
7150
7151 if (rb_int_negative_p(m)) {
7152 m = rb_int_uminus(m);
7153 nega_flg = 1;
7154 }
7155
7156 if (FIXNUM_P(m)) {
7157 long const half_val = (long)HALF_LONG_MSB;
7158 long const mm = FIX2LONG(m);
7159 if (!mm) rb_num_zerodiv();
7160 if (mm == 1) return INT2FIX(0);
7161 if (mm <= half_val) {
7162 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7163 }
7164 else {
7165 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7166 }
7167 }
7168 else {
7169 if (rb_bigzero_p(m)) rb_num_zerodiv();
7170 if (bignorm(m) == INT2FIX(1)) return INT2FIX(0);
7171 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7172 }
7173 }
7174 UNREACHABLE_RETURN(Qnil);
7175}
7176
7177/*
7178 * Bignum objects hold integers outside the range of
7179 * Fixnum. Bignum objects are created
7180 * automatically when integer calculations would otherwise overflow a
7181 * Fixnum. When a calculation involving
7182 * Bignum objects returns a result that will fit in a
7183 * Fixnum, the result is automatically converted.
7184 *
7185 * For the purposes of the bitwise operations and <code>[]</code>, a
7186 * Bignum is treated as if it were an infinite-length
7187 * bitstring with 2's complement representation.
7188 *
7189 * While Fixnum values are immediate, Bignum
7190 * objects are not---assignment and parameter passing work with
7191 * references to objects, not the objects themselves.
7192 *
7193 */
7194
7195void
7196Init_Bignum(void)
7197{
7198 rb_define_method(rb_cInteger, "coerce", rb_int_coerce, 1);
7199
7200#if USE_GMP
7201 /* The version of loaded GMP. */
7202 rb_define_const(rb_cInteger, "GMP_VERSION", rb_sprintf("GMP %s", gmp_version));
7203#endif
7204
7205 power_cache_init();
7206}
RUBY_DEBUG
#define RUBY_DEBUG
Define this macro when you want assertions.
Definition assert.h:87
LONG_LONG
#define LONG_LONG
Definition long_long.h:38
RUBY_ALIGNOF
#define RUBY_ALIGNOF
Wraps (or simulates) alignof.
Definition stdalign.h:28
rb_define_method
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
Definition cxxanyargs.hpp:670
NEWOBJ_OF
#define NEWOBJ_OF
Old name of RB_NEWOBJ_OF.
Definition newobj.h:61
RB_INTEGER_TYPE_P
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
Definition value_type.h:87
FL_UNSET_RAW
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
Definition fl_type.h:134
REALLOC_N
#define REALLOC_N
Old name of RB_REALLOC_N.
Definition memory.h:397
ISSPACE
#define ISSPACE
Old name of rb_isspace.
Definition ctype.h:88
RFLOAT_VALUE
#define RFLOAT_VALUE
Old name of rb_float_value.
Definition double.h:28
xfree
#define xfree
Old name of ruby_xfree.
Definition xmalloc.h:58
Qundef
#define Qundef
Old name of RUBY_Qundef.
Definition special_consts.h:62
INT2FIX
#define INT2FIX
Old name of RB_INT2FIX.
Definition long.h:48
NEGFIXABLE
#define NEGFIXABLE
Old name of RB_NEGFIXABLE.
Definition fixnum.h:28
T_BIGNUM
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
Definition value_type.h:57
OBJ_FREEZE
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
Definition fl_type.h:135
ULONG2NUM
#define ULONG2NUM
Old name of RB_ULONG2NUM.
Definition long.h:60
UNREACHABLE_RETURN
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
Definition assume.h:29
CLASS_OF
#define CLASS_OF
Old name of rb_class_of.
Definition globals.h:203
SIZET2NUM
#define SIZET2NUM
Old name of RB_SIZE2NUM.
Definition size_t.h:62
FIXABLE
#define FIXABLE
Old name of RB_FIXABLE.
Definition fixnum.h:25
LONG2FIX
#define LONG2FIX
Old name of RB_INT2FIX.
Definition long.h:49
FIX2INT
#define FIX2INT
Old name of RB_FIX2INT.
Definition int.h:41
ALLOC_N
#define ALLOC_N
Old name of RB_ALLOC_N.
Definition memory.h:393
NUM2DBL
#define NUM2DBL
Old name of rb_num2dbl.
Definition double.h:27
LONG2NUM
#define LONG2NUM
Old name of RB_LONG2NUM.
Definition long.h:50
rb_usascii_str_new2
#define rb_usascii_str_new2
Old name of rb_usascii_str_new_cstr.
Definition string.h:1680
ULL2NUM
#define ULL2NUM
Old name of RB_ULL2NUM.
Definition long_long.h:31
FIXNUM_MIN
#define FIXNUM_MIN
Old name of RUBY_FIXNUM_MIN.
Definition fixnum.h:27
Qtrue
#define Qtrue
Old name of RUBY_Qtrue.
Definition special_consts.h:61
ST2FIX
#define ST2FIX
Old name of RB_ST2FIX.
Definition st_data_t.h:33
FIXNUM_MAX
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
Definition fixnum.h:26
Qnil
#define Qnil
Old name of RUBY_Qnil.
Definition special_consts.h:60
Qfalse
#define Qfalse
Old name of RUBY_Qfalse.
Definition special_consts.h:59
FIX2LONG
#define FIX2LONG
Old name of RB_FIX2LONG.
Definition long.h:46
NIL_P
#define NIL_P
Old name of RB_NIL_P.
Definition special_consts.h:55
ALLOCV_N
#define ALLOCV_N
Old name of RB_ALLOCV_N.
Definition memory.h:399
FL_WB_PROTECTED
#define FL_WB_PROTECTED
Old name of RUBY_FL_WB_PROTECTED.
Definition fl_type.h:59
POSFIXABLE
#define POSFIXABLE
Old name of RB_POSFIXABLE.
Definition fixnum.h:29
DBL2NUM
#define DBL2NUM
Old name of rb_float_new.
Definition double.h:29
NUM2LONG
#define NUM2LONG
Old name of RB_NUM2LONG.
Definition long.h:51
FIXNUM_P
#define FIXNUM_P
Old name of RB_FIXNUM_P.
Definition special_consts.h:53
FL_SET_RAW
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
Definition fl_type.h:130
ALLOCV_END
#define ALLOCV_END
Old name of RB_ALLOCV_END.
Definition memory.h:400
rb_eRangeError
VALUE rb_eRangeError
RangeError exception.
Definition error.c:1348
rb_eTypeError
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1344
rb_invalid_str
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.
Definition error.c:2476
rb_eFloatDomainError
VALUE rb_eFloatDomainError
FloatDomainError exception.
Definition numeric.c:201
rb_warn
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition error.c:423
rb_warning
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:454
rb_Float
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
Definition object.c:3548
rb_cInteger
VALUE rb_cInteger
Module class.
Definition numeric.c:198
rb_equal
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:147
rb_to_int
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3145
rb_funcall
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1121
RGENGC_WB_PROTECTED_BIGNUM
#define RGENGC_WB_PROTECTED_BIGNUM
This is a compile-time flag to enable/disable write barrier for struct RBignum.
Definition gc.h:583
INTEGER_PACK_MSBYTE_FIRST
#define INTEGER_PACK_MSBYTE_FIRST
Stores/interprets the most significant byte in a word as the first byte in the word.
Definition bignum.h:534
INTEGER_PACK_LSBYTE_FIRST
#define INTEGER_PACK_LSBYTE_FIRST
Stores/interprets the least significant byte in a word as the first byte in the word.
Definition bignum.h:540
INTEGER_PACK_NATIVE_BYTE_ORDER
#define INTEGER_PACK_NATIVE_BYTE_ORDER
Means either INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST, depending on the host processor'...
Definition bignum.h:546
INTEGER_PACK_FORCE_BIGNUM
#define INTEGER_PACK_FORCE_BIGNUM
Always generates a bignum object even if the integer can be representable using fixnum scheme (unpack...
Definition bignum.h:558
INTEGER_PACK_BIG_ENDIAN
#define INTEGER_PACK_BIG_ENDIAN
Big endian combination.
Definition bignum.h:572
INTEGER_PACK_2COMP
#define INTEGER_PACK_2COMP
Uses 2's complement representation.
Definition bignum.h:549
INTEGER_PACK_NEGATIVE
#define INTEGER_PACK_NEGATIVE
Interprets the input as a signed negative number (unpack only).
Definition bignum.h:564
INTEGER_PACK_MSWORD_FIRST
#define INTEGER_PACK_MSWORD_FIRST
Stores/interprets the most significant word as the first word.
Definition bignum.h:525
INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
#define INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
Uses "generic" implementation (handy on test).
Definition bignum.h:552
INTEGER_PACK_LSWORD_FIRST
#define INTEGER_PACK_LSWORD_FIRST
Stores/interprets the least significant word as the first word.
Definition bignum.h:528
rb_check_arity
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
Definition error.h:280
rb_num_zerodiv
void rb_num_zerodiv(void)
Just always raises an exception.
Definition numeric.c:206
rb_fix2str
VALUE rb_fix2str(VALUE val, int base)
Generates a place-value representation of the given Fixnum, with given radix.
Definition numeric.c:3845
rb_num_coerce_bit
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().
Definition numeric.c:4923
rb_num_coerce_relop
VALUE rb_num_coerce_relop(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_cmp(), except for return values.
Definition numeric.c:499
rb_num_coerce_cmp
VALUE rb_num_coerce_cmp(VALUE lhs, VALUE rhs, ID op)
Identical to rb_num_coerce_bin(), except for return values.
Definition numeric.c:484
rb_num_coerce_bin
VALUE rb_num_coerce_bin(VALUE lhs, VALUE rhs, ID op)
Coerced binary operation.
Definition numeric.c:477
rb_rational_raw
VALUE rb_rational_raw(VALUE num, VALUE den)
Identical to rb_rational_new(), except it skips argument validations.
Definition rational.c:1955
rb_memhash
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
Definition random.c:1747
rb_usascii_str_new
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
Definition string.h:1532
rb_must_asciicompat
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
Definition string.c:2530
rb_thread_check_ints
void rb_thread_check_ints(void)
Checks for interrupts.
Definition thread.c:1418
rb_define_const
void rb_define_const(VALUE klass, const char *name, VALUE val)
Defines a Ruby level constant under a namespace.
Definition variable.c:3690
len
int len
Length of the buffer.
Definition io.h:8
thread.h
RB_NOGVL_UBF_ASYNC_SAFE
#define RB_NOGVL_UBF_ASYNC_SAFE
Passing this flag to rb_nogvl() indicates that the passed UBF is async-signal-safe.
Definition thread.h:60
rb_nogvl
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...
Definition thread.c:1523
util.h
rb_ull2inum
VALUE rb_ull2inum(unsigned LONG_LONG num)
Converts a C's unsigned long long into an instance of rb_cInteger.
rb_ll2inum
VALUE rb_ll2inum(LONG_LONG num)
Converts a C's long long into an instance of rb_cInteger.
MEMCPY
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
Definition memory.h:366
MEMCMP
#define MEMCMP(p1, p2, type, n)
Handy macro to call memcmp.
Definition memory.h:391
MEMZERO
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
Definition memory.h:354
RB_GC_GUARD
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
Definition memory.h:161
MEMMOVE
#define MEMMOVE(p1, p2, type, n)
Handy macro to call memmove.
Definition memory.h:378
ruby::backward::cxxanyargs::type
VALUE type(ANYARGS)
ANYARGS-ed function type.
Definition cxxanyargs.hpp:56
StringValue
#define StringValue(v)
Ensures that the parameter object is a String.
Definition rstring.h:66
StringValuePtr
#define StringValuePtr(v)
Identical to StringValue, except it returns a char*.
Definition rstring.h:76
RSTRING_GETMEM
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
Definition rstring.h:488
StringValueCStr
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
Definition rstring.h:89
RTEST
#define RTEST
This is an old name of RB_TEST.
Definition special_consts.h:51
RBignum
Definition bignum.h:100
big2str_struct
Definition bignum.c:4738
big_div_struct
Definition bignum.c:2590
SIGNED_VALUE
intptr_t SIGNED_VALUE
A signed integer type that has the same width with VALUE.
Definition value.h:63
ID
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
Definition value.h:52
SIZEOF_VALUE
#define SIZEOF_VALUE
Identical to sizeof(VALUE), except it is a macro that can also be used inside of preprocessor directi...
Definition value.h:69
VALUE
uintptr_t VALUE
Type that represents a Ruby object.
Definition value.h:40
RB_FLOAT_TYPE_P
static bool RB_FLOAT_TYPE_P(VALUE obj)
Queries if the object is an instance of rb_cFloat.
Definition value_type.h:263