Ruby: bignum.c Source File

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

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