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