Ruby: bignum.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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