Ruby 4.1.0dev (2026-03-06 revision 9aca729140424bbf465c11ab8ab53e5cc6602c01)
bignum.c (9aca729140424bbf465c11ab8ab53e5cc6602c01)
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
2946
2947#ifndef BIGNUM_DEBUG
2948# define BIGNUM_DEBUG (0+RUBY_DEBUG)
2949#endif
2950
2951static int
2952bigzero_p(VALUE x)
2953{
2954 return bary_zero_p(BDIGITS(x), BIGNUM_LEN(x));
2955}
2956
2957int
2958rb_bigzero_p(VALUE x)
2959{
2960 return BIGZEROP(x);
2961}
2962
2963int
2964rb_cmpint(VALUE val, VALUE a, VALUE b)
2965{
2966 if (NIL_P(val)) {
2967 rb_cmperr_reason(a, b, "comparator returned nil");
2968 }
2969 if (FIXNUM_P(val)) {
2970 long l = FIX2LONG(val);
2971 if (l > 0) return 1;
2972 if (l < 0) return -1;
2973 return 0;
2974 }
2975 if (RB_BIGNUM_TYPE_P(val)) {
2976 if (BIGZEROP(val)) return 0;
2977 if (BIGNUM_SIGN(val)) return 1;
2978 return -1;
2979 }
2980 if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
2981 if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
2982 return 0;
2983}
2984
2985#define BIGNUM_SET_LEN(b,l) \
2986 (BIGNUM_EMBED_P(b) ? \
2987 (void)(RBASIC(b)->flags = \
2988 (RBASIC(b)->flags & ~BIGNUM_EMBED_LEN_MASK) | \
2989 ((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
2990 (void)(RBIGNUM(b)->as.heap.len = (l)))
2991
2992static size_t
2993big_embed_capa(VALUE big)
2994{
2995 size_t size = rb_gc_obj_slot_size(big) - offsetof(struct RBignum, as.ary);
2996 RUBY_ASSERT(size % sizeof(BDIGIT) == 0);
2997 size_t capa = size / sizeof(BDIGIT);
2998 RUBY_ASSERT(capa <= BIGNUM_EMBED_LEN_MAX);
2999 return capa;
3000}
3001
3002static size_t
3003big_embed_size(size_t capa)
3004{
3005 size_t size = offsetof(struct RBignum, as.ary) + (sizeof(BDIGIT) * capa);
3006 if (size < sizeof(struct RBignum)) {
3007 size = sizeof(struct RBignum);
3008 }
3009 return size;
3010}
3011
3012static bool
3013big_embeddable_p(size_t capa)
3014{
3015 if (capa > BIGNUM_EMBED_LEN_MAX) {
3016 return false;
3017 }
3018 return rb_gc_size_allocatable_p(big_embed_size(capa));
3019}
3020
3021static void
3022rb_big_realloc(VALUE big, size_t len)
3023{
3024 BDIGIT *ds;
3025 size_t embed_capa = big_embed_capa(big);
3026
3027 if (BIGNUM_EMBED_P(big)) {
3028 if (embed_capa < len) {
3029 ds = ALLOC_N(BDIGIT, len);
3030 MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, embed_capa);
3031 RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
3032 RBIGNUM(big)->as.heap.digits = ds;
3033 FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
3034 }
3035 }
3036 else {
3037 if (len <= embed_capa) {
3038 ds = RBIGNUM(big)->as.heap.digits;
3039 size_t old_len = RBIGNUM(big)->as.heap.len;
3040 FL_SET_RAW(big, BIGNUM_EMBED_FLAG);
3041 BIGNUM_SET_LEN(big, len);
3042 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, embed_capa * sizeof(BDIGIT));
3043 if (ds) {
3044 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
3045 SIZED_FREE_N(ds, old_len);
3046 }
3047 }
3048 else {
3049 if (BIGNUM_LEN(big) == 0) {
3050 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
3051 }
3052 else if (BIGNUM_LEN(big) != len) {
3053 SIZED_REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len, BIGNUM_LEN(big));
3054 }
3055 }
3056 }
3057}
3058
3059void
3060rb_big_resize(VALUE big, size_t len)
3061{
3062 rb_big_realloc(big, len);
3063 BIGNUM_SET_LEN(big, len);
3064}
3065
3066static VALUE
3067bignew_1(VALUE klass, size_t len, int sign)
3068{
3069 VALUE bigv;
3070
3071 if (big_embeddable_p(len)) {
3072 size_t size = big_embed_size(len);
3073 RUBY_ASSERT(rb_gc_size_allocatable_p(size));
3074 NEWOBJ_OF(big, struct RBignum, klass,
3075 T_BIGNUM | BIGNUM_EMBED_FLAG | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0),
3076 size, 0);
3077 bigv = (VALUE)big;
3078 BIGNUM_SET_SIGN(bigv, sign);
3079 BIGNUM_SET_LEN(bigv, len);
3080 (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, len * sizeof(BDIGIT));
3081 }
3082 else {
3083 NEWOBJ_OF(big, struct RBignum, klass,
3084 T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0), sizeof(struct RBignum), 0);
3085 bigv = (VALUE)big;
3086 BIGNUM_SET_SIGN(bigv, sign);
3087 big->as.heap.digits = ALLOC_N(BDIGIT, len);
3088 big->as.heap.len = len;
3089 }
3090 OBJ_FREEZE(bigv);
3091 return bigv;
3092}
3093
3094VALUE
3095rb_big_new(size_t len, int sign)
3096{
3097 VALUE obj = bignew(len, sign != 0);
3098 memset(BIGNUM_DIGITS(obj), 0, len * sizeof(BDIGIT));
3099 return obj;
3100}
3101
3102VALUE
3103rb_big_clone(VALUE x)
3104{
3105 size_t len = BIGNUM_LEN(x);
3106 VALUE z = bignew_1(CLASS_OF(x), len, BIGNUM_SIGN(x));
3107
3108 MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
3109 return z;
3110}
3111
3112static void
3113big_extend_carry(VALUE x)
3114{
3115 rb_big_resize(x, BIGNUM_LEN(x)+1);
3116 BDIGITS(x)[BIGNUM_LEN(x)-1] = 1;
3117}
3118
3119/* modify a bignum by 2's complement */
3120static void
3121get2comp(VALUE x)
3122{
3123 long i = BIGNUM_LEN(x);
3124 BDIGIT *ds = BDIGITS(x);
3125
3126 if (bary_2comp(ds, i)) {
3127 big_extend_carry(x);
3128 }
3129}
3130
3131void
3132rb_big_2comp(VALUE x) /* get 2's complement */
3133{
3134 get2comp(x);
3135}
3136
3137static BDIGIT
3138abs2twocomp(VALUE *xp, long *n_ret)
3139{
3140 VALUE x = *xp;
3141 long n = BIGNUM_LEN(x);
3142 BDIGIT *ds = BDIGITS(x);
3143 BDIGIT hibits = 0;
3144
3145 BARY_TRUNC(ds, n);
3146
3147 if (n != 0 && BIGNUM_NEGATIVE_P(x)) {
3148 VALUE z = bignew_1(CLASS_OF(x), n, 0);
3149 MEMCPY(BDIGITS(z), ds, BDIGIT, n);
3150 bary_2comp(BDIGITS(z), n);
3151 hibits = BDIGMAX;
3152 *xp = z;
3153 }
3154 *n_ret = n;
3155 return hibits;
3156}
3157
3158static void
3159twocomp2abs_bang(VALUE x, int hibits)
3160{
3161 BIGNUM_SET_SIGN(x, !hibits);
3162 if (hibits) {
3163 get2comp(x);
3164 }
3165}
3166
3167static inline VALUE
3168bigtrunc(VALUE x)
3169{
3170 size_t len = BIGNUM_LEN(x);
3171 BDIGIT *ds = BDIGITS(x);
3172
3173 if (len == 0) return x;
3174 while (--len && !ds[len]);
3175 if (BIGNUM_LEN(x) > len+1) {
3176 rb_big_resize(x, len+1);
3177 }
3178 return x;
3179}
3180
3181static inline VALUE
3182bigfixize(VALUE x)
3183{
3184 size_t n = BIGNUM_LEN(x);
3185 BDIGIT *ds = BDIGITS(x);
3186#if SIZEOF_BDIGIT < SIZEOF_LONG
3187 unsigned long u;
3188#else
3189 BDIGIT u;
3190#endif
3191
3192 BARY_TRUNC(ds, n);
3193
3194 if (n == 0) return INT2FIX(0);
3195
3196#if SIZEOF_BDIGIT < SIZEOF_LONG
3197 if (sizeof(long)/SIZEOF_BDIGIT < n)
3198 goto return_big;
3199 else {
3200 int i = (int)n;
3201 u = 0;
3202 while (i--) {
3203 u = (unsigned long)(BIGUP(u) + ds[i]);
3204 }
3205 }
3206#else /* SIZEOF_BDIGIT >= SIZEOF_LONG */
3207 if (1 < n)
3208 goto return_big;
3209 else
3210 u = ds[0];
3211#endif
3212
3213 if (BIGNUM_POSITIVE_P(x)) {
3214 if (POSFIXABLE(u)) return LONG2FIX((long)u);
3215 }
3216 else {
3217 if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u);
3218 }
3219
3220 return_big:
3221 rb_big_resize(x, n);
3222 return x;
3223}
3224
3225static VALUE
3226bignorm(VALUE x)
3227{
3228 if (RB_BIGNUM_TYPE_P(x)) {
3229 x = bigfixize(x);
3230 }
3231 return x;
3232}
3233
3234VALUE
3235rb_big_norm(VALUE x)
3236{
3237 return bignorm(x);
3238}
3239
3240VALUE
3241rb_uint2big(uintptr_t n)
3242{
3243 long i;
3244 VALUE big = bignew(bdigit_roomof(SIZEOF_VALUE), 1);
3245 BDIGIT *digits = BDIGITS(big);
3246
3247#if SIZEOF_BDIGIT >= SIZEOF_VALUE
3248 digits[0] = n;
3249#else
3250 for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
3251 digits[i] = BIGLO(n);
3252 n = BIGDN(n);
3253 }
3254#endif
3255
3256 i = bdigit_roomof(SIZEOF_VALUE);
3257 while (--i && !digits[i]) ;
3258 BIGNUM_SET_LEN(big, i+1);
3259 return big;
3260}
3261
3262VALUE
3263rb_int2big(intptr_t n)
3264{
3265 long neg = 0;
3266 VALUE u;
3267 VALUE big;
3268
3269 if (n < 0) {
3270 u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
3271 neg = 1;
3272 }
3273 else {
3274 u = n;
3275 }
3276 big = rb_uint2big(u);
3277 if (neg) {
3278 BIGNUM_SET_NEGATIVE_SIGN(big);
3279 }
3280 return big;
3281}
3282
3283VALUE
3284rb_uint2inum(uintptr_t n)
3285{
3286 if (POSFIXABLE(n)) return LONG2FIX(n);
3287 return rb_uint2big(n);
3288}
3289
3290VALUE
3291rb_int2inum(intptr_t n)
3292{
3293 if (FIXABLE(n)) return LONG2FIX(n);
3294 return rb_int2big(n);
3295}
3296
3297void
3298rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
3299{
3300 rb_integer_pack(val, buf, num_longs, sizeof(long), 0,
3303}
3304
3305VALUE
3306rb_big_unpack(unsigned long *buf, long num_longs)
3307{
3308 return rb_integer_unpack(buf, num_longs, sizeof(long), 0,
3311}
3312
3313/*
3314 * Calculate the number of bytes to be required to represent
3315 * the absolute value of the integer given as _val_.
3316 *
3317 * [val] an integer.
3318 * [nlz_bits_ret] number of leading zero bits in the most significant byte is returned if not NULL.
3319 *
3320 * This function returns ((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)
3321 * where val_numbits is the number of bits of abs(val).
3322 * This function should not overflow.
3323 *
3324 * If nlz_bits_ret is not NULL,
3325 * (return_value * CHAR_BIT - val_numbits) is stored in *nlz_bits_ret.
3326 * In this case, 0 <= *nlz_bits_ret < CHAR_BIT.
3327 *
3328 */
3329size_t
3330rb_absint_size(VALUE val, int *nlz_bits_ret)
3331{
3332 BDIGIT *dp;
3333 BDIGIT *de;
3334 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3335
3336 int num_leading_zeros;
3337
3338 val = rb_to_int(val);
3339
3340 if (FIXNUM_P(val)) {
3341 long v = FIX2LONG(val);
3342 if (v < 0) {
3343 v = -v;
3344 }
3345#if SIZEOF_BDIGIT >= SIZEOF_LONG
3346 fixbuf[0] = v;
3347#else
3348 {
3349 int i;
3350 for (i = 0; i < numberof(fixbuf); i++) {
3351 fixbuf[i] = BIGLO(v);
3352 v = BIGDN(v);
3353 }
3354 }
3355#endif
3356 dp = fixbuf;
3357 de = fixbuf + numberof(fixbuf);
3358 }
3359 else {
3360 dp = BDIGITS(val);
3361 de = dp + BIGNUM_LEN(val);
3362 }
3363 while (dp < de && de[-1] == 0)
3364 de--;
3365 if (dp == de) {
3366 if (nlz_bits_ret)
3367 *nlz_bits_ret = 0;
3368 return 0;
3369 }
3370 num_leading_zeros = nlz(de[-1]);
3371 if (nlz_bits_ret)
3372 *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
3373 return (de - dp) * SIZEOF_BDIGIT - num_leading_zeros / CHAR_BIT;
3374}
3375
3376static size_t
3377absint_numwords_small(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3378{
3379 size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
3380 size_t div = val_numbits / word_numbits;
3381 size_t mod = val_numbits % word_numbits;
3382 size_t numwords;
3383 size_t nlz_bits;
3384 numwords = mod == 0 ? div : div + 1;
3385 nlz_bits = mod == 0 ? 0 : word_numbits - mod;
3386 *nlz_bits_ret = nlz_bits;
3387 return numwords;
3388}
3389
3390static size_t
3391absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
3392{
3393 static const BDIGIT char_bit[1] = { CHAR_BIT };
3394 BDIGIT numbytes_bary[bdigit_roomof(sizeof(numbytes))];
3395 BDIGIT val_numbits_bary[bdigit_roomof(sizeof(numbytes) + 1)];
3396 BDIGIT nlz_bits_in_msbyte_bary[1];
3397 BDIGIT word_numbits_bary[bdigit_roomof(sizeof(word_numbits))];
3398 BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
3399 BDIGIT mod_bary[numberof(word_numbits_bary)];
3400 BDIGIT one[1] = { 1 };
3401 size_t nlz_bits;
3402 size_t mod;
3403 int sign;
3404 size_t numwords;
3405
3406 nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
3407
3408 /*
3409 * val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
3410 * div, mod = val_numbits.divmod(word_numbits)
3411 * numwords = mod == 0 ? div : div + 1
3412 * nlz_bits = mod == 0 ? 0 : word_numbits - mod
3413 */
3414
3415 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
3417 BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
3418 if (nlz_bits_in_msbyte)
3419 BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
3420 bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1, sizeof(word_numbits), 0,
3422 BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
3423 if (BARY_ZERO_P(mod_bary)) {
3424 nlz_bits = 0;
3425 }
3426 else {
3427 BARY_ADD(div_bary, div_bary, one);
3428 bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1, sizeof(mod), 0,
3430 nlz_bits = word_numbits - mod;
3431 }
3432 sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1, sizeof(numwords), 0,
3434
3435 if (sign == 2) {
3436#if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
3437 *nlz_bits_ret = 0;
3438#endif
3439 return (size_t)-1;
3440 }
3441 *nlz_bits_ret = nlz_bits;
3442 return numwords;
3443}
3444
3445/*
3446 * Calculate the number of words to be required to represent
3447 * the absolute value of the integer given as _val_.
3448 *
3449 * [val] an integer.
3450 * [word_numbits] number of bits in a word.
3451 * [nlz_bits_ret] number of leading zero bits in the most significant word is returned if not NULL.
3452 *
3453 * This function returns ((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)
3454 * where val_numbits is the number of bits of abs(val).
3455 *
3456 * This function can overflow.
3457 * When overflow occur, (size_t)-1 is returned.
3458 *
3459 * If nlz_bits_ret is not NULL and overflow is not occur,
3460 * (return_value * word_numbits - val_numbits) is stored in *nlz_bits_ret.
3461 * In this case, 0 <= *nlz_bits_ret < word_numbits.
3462 *
3463 */
3464size_t
3465rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
3466{
3467 size_t numbytes;
3468 int nlz_bits_in_msbyte;
3469 size_t numwords;
3470 size_t nlz_bits = 0;
3471
3472 if (word_numbits == 0)
3473 return (size_t)-1;
3474
3475 numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
3476
3477 if (numbytes <= SIZE_MAX / CHAR_BIT) {
3478 numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3479 if (debug_integer_pack) {
3480 size_t numwords0, nlz_bits0;
3481 numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
3482 RUBY_ASSERT(numwords0 == numwords);
3483 RUBY_ASSERT(nlz_bits0 == nlz_bits);
3484 (void)numwords0;
3485 }
3486 }
3487 else {
3488 numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
3489 }
3490 if (numwords == (size_t)-1)
3491 return numwords;
3492
3493 if (nlz_bits_ret)
3494 *nlz_bits_ret = nlz_bits;
3495
3496 return numwords;
3497}
3498
3499/* Test abs(val) consists only a bit or not.
3500 *
3501 * Returns 1 if abs(val) == 1 << n for some n >= 0.
3502 * Returns 0 otherwise.
3503 *
3504 * rb_absint_singlebit_p can be used to determine required buffer size
3505 * for rb_integer_pack used with INTEGER_PACK_2COMP (two's complement).
3506 *
3507 * Following example calculates number of bits required to
3508 * represent val in two's complement number, without sign bit.
3509 *
3510 * size_t size;
3511 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3512 * size = rb_absint_numwords(val, 1, NULL)
3513 * if (size == (size_t)-1) ...overflow...
3514 * if (neg && rb_absint_singlebit_p(val))
3515 * size--;
3516 *
3517 * Following example calculates number of bytes required to
3518 * represent val in two's complement number, with sign bit.
3519 *
3520 * size_t size;
3521 * int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : BIGNUM_NEGATIVE_P(val);
3522 * int nlz_bits;
3523 * size = rb_absint_size(val, &nlz_bits);
3524 * if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
3525 * size++;
3526 */
3527int
3528rb_absint_singlebit_p(VALUE val)
3529{
3530 BDIGIT *dp;
3531 BDIGIT *de;
3532 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3533 BDIGIT d;
3534
3535 val = rb_to_int(val);
3536
3537 if (FIXNUM_P(val)) {
3538 long v = FIX2LONG(val);
3539 if (v < 0) {
3540 v = -v;
3541 }
3542#if SIZEOF_BDIGIT >= SIZEOF_LONG
3543 fixbuf[0] = v;
3544#else
3545 {
3546 int i;
3547 for (i = 0; i < numberof(fixbuf); i++) {
3548 fixbuf[i] = BIGLO(v);
3549 v = BIGDN(v);
3550 }
3551 }
3552#endif
3553 dp = fixbuf;
3554 de = fixbuf + numberof(fixbuf);
3555 }
3556 else {
3557 dp = BDIGITS(val);
3558 de = dp + BIGNUM_LEN(val);
3559 }
3560 while (dp < de && de[-1] == 0)
3561 de--;
3562 while (dp < de && dp[0] == 0)
3563 dp++;
3564 if (dp == de) /* no bit set. */
3565 return 0;
3566 if (dp != de-1) /* two non-zero words. two bits set, at least. */
3567 return 0;
3568 d = *dp;
3569 return POW2_P(d);
3570}
3571
3572
3573/*
3574 * Export an integer into a buffer.
3575 *
3576 * This function fills the buffer specified by _words_ and _numwords_ as
3577 * val in the format specified by _wordsize_, _nails_ and _flags_.
3578 *
3579 * [val] Fixnum, Bignum or another integer like object which has to_int method.
3580 * [words] buffer to export abs(val).
3581 * [numwords] the size of given buffer as number of words.
3582 * [wordsize] the size of word as number of bytes.
3583 * [nails] number of padding bits in a word.
3584 * Most significant nails bits of each word are filled by zero.
3585 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3586 *
3587 * flags:
3588 * [INTEGER_PACK_MSWORD_FIRST] Store the most significant word as the first word.
3589 * [INTEGER_PACK_LSWORD_FIRST] Store the least significant word as the first word.
3590 * [INTEGER_PACK_MSBYTE_FIRST] Store the most significant byte in a word as the first byte in the word.
3591 * [INTEGER_PACK_LSBYTE_FIRST] Store the least significant byte in a word as the first byte in the word.
3592 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3593 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3594 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3595 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3596 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3597 *
3598 * This function fills the buffer specified by _words_
3599 * as abs(val) if INTEGER_PACK_2COMP is not specified in _flags_.
3600 * If INTEGER_PACK_2COMP is specified, 2's complement representation of val is
3601 * filled in the buffer.
3602 *
3603 * This function returns the signedness and overflow condition.
3604 * The overflow condition depends on INTEGER_PACK_2COMP.
3605 *
3606 * INTEGER_PACK_2COMP is not specified:
3607 * -2 : negative overflow. val <= -2**(numwords*(wordsize*CHAR_BIT-nails))
3608 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0
3609 * 0 : zero. val == 0
3610 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3611 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3612 *
3613 * INTEGER_PACK_2COMP is specified:
3614 * -2 : negative overflow. val < -2**(numwords*(wordsize*CHAR_BIT-nails))
3615 * -1 : negative without overflow. -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0
3616 * 0 : zero. val == 0
3617 * 1 : positive without overflow. 0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
3618 * 2 : positive overflow. 2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
3619 *
3620 * The value, -2**(numwords*(wordsize*CHAR_BIT-nails)), is representable
3621 * in 2's complement representation but not representable in absolute value.
3622 * So -1 is returned for the value if INTEGER_PACK_2COMP is specified
3623 * but returns -2 if INTEGER_PACK_2COMP is not specified.
3624 *
3625 * The least significant words are filled in the buffer when overflow occur.
3626 */
3627
3628int
3629rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3630{
3631 int sign;
3632 BDIGIT *ds;
3633 size_t num_bdigits;
3634 BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
3635
3636 RB_GC_GUARD(val) = rb_to_int(val);
3637
3638 if (FIXNUM_P(val)) {
3639 long v = FIX2LONG(val);
3640 if (v < 0) {
3641 sign = -1;
3642 v = -v;
3643 }
3644 else {
3645 sign = 1;
3646 }
3647#if SIZEOF_BDIGIT >= SIZEOF_LONG
3648 fixbuf[0] = v;
3649#else
3650 {
3651 int i;
3652 for (i = 0; i < numberof(fixbuf); i++) {
3653 fixbuf[i] = BIGLO(v);
3654 v = BIGDN(v);
3655 }
3656 }
3657#endif
3658 ds = fixbuf;
3659 num_bdigits = numberof(fixbuf);
3660 }
3661 else {
3662 sign = BIGNUM_POSITIVE_P(val) ? 1 : -1;
3663 ds = BDIGITS(val);
3664 num_bdigits = BIGNUM_LEN(val);
3665 }
3666
3667 return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
3668}
3669
3670/*
3671 * Import an integer from a buffer.
3672 *
3673 * [words] buffer to import.
3674 * [numwords] the size of given buffer as number of words.
3675 * [wordsize] the size of word as number of bytes.
3676 * [nails] number of padding bits in a word.
3677 * Most significant nails bits of each word are ignored.
3678 * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
3679 *
3680 * flags:
3681 * [INTEGER_PACK_MSWORD_FIRST] Interpret the first word as the most significant word.
3682 * [INTEGER_PACK_LSWORD_FIRST] Interpret the first word as the least significant word.
3683 * [INTEGER_PACK_MSBYTE_FIRST] Interpret the first byte in a word as the most significant byte in the word.
3684 * [INTEGER_PACK_LSBYTE_FIRST] Interpret the first byte in a word as the least significant byte in the word.
3685 * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
3686 * [INTEGER_PACK_2COMP] Use 2's complement representation.
3687 * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
3688 * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
3689 * [INTEGER_PACK_FORCE_BIGNUM] the result will be a Bignum
3690 * even if it is representable as a Fixnum.
3691 * [INTEGER_PACK_NEGATIVE] Returns non-positive value.
3692 * (Returns non-negative value if not specified.)
3693 * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
3694 *
3695 * This function returns the imported integer as Fixnum or Bignum.
3696 *
3697 * The range of the result value depends on INTEGER_PACK_2COMP and INTEGER_PACK_NEGATIVE.
3698 *
3699 * INTEGER_PACK_2COMP is not set:
3700 * 0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails)) if !INTEGER_PACK_NEGATIVE
3701 * -2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0 if INTEGER_PACK_NEGATIVE
3702 *
3703 * INTEGER_PACK_2COMP is set:
3704 * -2**(numwords*(wordsize*CHAR_BIT-nails)-1) <= val <= 2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1 if !INTEGER_PACK_NEGATIVE
3705 * -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1 if INTEGER_PACK_NEGATIVE
3706 *
3707 * INTEGER_PACK_2COMP without INTEGER_PACK_NEGATIVE means sign extension.
3708 * INTEGER_PACK_2COMP with INTEGER_PACK_NEGATIVE mean assuming the higher bits are 1.
3709 *
3710 * Note that this function returns 0 when numwords is zero and
3711 * INTEGER_PACK_2COMP is set but INTEGER_PACK_NEGATIVE is not set.
3712 */
3713
3714VALUE
3715rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
3716{
3717 VALUE val;
3718 size_t num_bdigits;
3719 int sign;
3720 int nlp_bits;
3721 BDIGIT *ds;
3722 BDIGIT fixbuf[2] = { 0, 0 };
3723
3724 validate_integer_pack_format(numwords, wordsize, nails, flags,
3734
3735 num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
3736
3737 if (LONG_MAX-1 < num_bdigits)
3738 rb_raise(rb_eArgError, "too big to unpack as an integer");
3739 if (num_bdigits <= numberof(fixbuf) && !(flags & INTEGER_PACK_FORCE_BIGNUM)) {
3740 val = Qfalse;
3741 ds = fixbuf;
3742 }
3743 else {
3744 val = bignew((long)num_bdigits, 0);
3745 ds = BDIGITS(val);
3746 }
3747 sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
3748
3749 if (sign == -2) {
3750 if (val) {
3751 big_extend_carry(val);
3752 }
3753 else if (num_bdigits == numberof(fixbuf)) {
3754 val = bignew((long)num_bdigits+1, 0);
3755 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3756 BDIGITS(val)[num_bdigits++] = 1;
3757 }
3758 else {
3759 ds[num_bdigits++] = 1;
3760 }
3761 }
3762
3763 if (!val) {
3764 BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
3765 if (u == 0)
3766 return LONG2FIX(0);
3767 if (0 < sign && POSFIXABLE(u))
3768 return LONG2FIX((long)u);
3769 if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
3770 NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u))
3771 return LONG2FIX((long)-(BDIGIT_DBL_SIGNED)u);
3772 val = bignew((long)num_bdigits, 0 <= sign);
3773 MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
3774 }
3775
3776 if ((flags & INTEGER_PACK_FORCE_BIGNUM) && sign != 0 &&
3777 bary_zero_p(BDIGITS(val), BIGNUM_LEN(val)))
3778 sign = 0;
3779 BIGNUM_SET_SIGN(val, 0 <= sign);
3780
3781 if (flags & INTEGER_PACK_FORCE_BIGNUM)
3782 return bigtrunc(val);
3783 return bignorm(val);
3784}
3785
3786#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
3787
3788NORETURN(static inline void invalid_radix(int base));
3789NORETURN(static inline void invalid_integer(VALUE s));
3790
3791static inline int
3792valid_radix_p(int base)
3793{
3794 return (1 < base && base <= 36);
3795}
3796
3797static inline void
3798invalid_radix(int base)
3799{
3800 rb_raise(rb_eArgError, "invalid radix %d", base);
3801}
3802
3803static inline void
3804invalid_integer(VALUE s)
3805{
3806 rb_raise(rb_eArgError, "invalid value for Integer(): %+"PRIsVALUE, s);
3807}
3808
3809static int
3810str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size_t *num_digits_p, ssize_t *len_p)
3811{
3812 char nondigit = 0;
3813 size_t num_digits = 0;
3814 const char *digits_start = str;
3815 const char *digits_end = str;
3816 ssize_t len = *len_p;
3817
3818 int c;
3819
3820 if (!len) {
3821 *num_digits_p = 0;
3822 *len_p = 0;
3823 return TRUE;
3824 }
3825
3826 if (badcheck && *str == '_') return FALSE;
3827
3828 while ((c = *str++) != 0) {
3829 if (c == '_') {
3830 if (nondigit) {
3831 if (badcheck) return FALSE;
3832 break;
3833 }
3834 nondigit = (char) c;
3835 }
3836 else if ((c = conv_digit(c)) < 0 || c >= base) {
3837 break;
3838 }
3839 else {
3840 nondigit = 0;
3841 num_digits++;
3842 digits_end = str;
3843 }
3844 if (len > 0 && !--len) break;
3845 }
3846 if (badcheck && nondigit) return FALSE;
3847 if (badcheck && len) {
3848 str--;
3849 while (*str && ISSPACE(*str)) {
3850 str++;
3851 if (len > 0 && !--len) break;
3852 }
3853 if (len && *str) {
3854 return FALSE;
3855 }
3856 }
3857 *num_digits_p = num_digits;
3858 *len_p = digits_end - digits_start;
3859 return TRUE;
3860}
3861
3862static VALUE
3863str2big_poweroftwo(
3864 int sign,
3865 const char *digits_start,
3866 const char *digits_end,
3867 size_t num_digits,
3868 int bits_per_digit)
3869{
3870 BDIGIT *dp;
3871 BDIGIT_DBL dd;
3872 int numbits;
3873
3874 size_t num_bdigits;
3875 const char *p;
3876 int c;
3877 VALUE z;
3878
3879 num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
3880 z = bignew(num_bdigits, sign);
3881 dp = BDIGITS(z);
3882 dd = 0;
3883 numbits = 0;
3884 for (p = digits_end; digits_start < p; p--) {
3885 if ((c = conv_digit(p[-1])) < 0)
3886 continue;
3887 dd |= (BDIGIT_DBL)c << numbits;
3888 numbits += bits_per_digit;
3889 if (BITSPERDIG <= numbits) {
3890 *dp++ = BIGLO(dd);
3891 dd = BIGDN(dd);
3892 numbits -= BITSPERDIG;
3893 }
3894 }
3895 if (numbits) {
3896 *dp++ = BIGLO(dd);
3897 }
3898 RUBY_ASSERT((size_t)(dp - BDIGITS(z)) == num_bdigits);
3899
3900 return z;
3901}
3902
3903static VALUE
3904str2big_normal(
3905 int sign,
3906 const char *digits_start,
3907 const char *digits_end,
3908 size_t num_bdigits,
3909 int base)
3910{
3911 size_t blen = 1;
3912 BDIGIT *zds;
3913 BDIGIT_DBL num;
3914
3915 size_t i;
3916 const char *p;
3917 int c;
3918 VALUE z;
3919
3920 z = bignew(num_bdigits, sign);
3921 zds = BDIGITS(z);
3922 BDIGITS_ZERO(zds, num_bdigits);
3923
3924 for (p = digits_start; p < digits_end; p++) {
3925 if ((c = conv_digit(*p)) < 0)
3926 continue;
3927 num = c;
3928 i = 0;
3929 for (;;) {
3930 while (i<blen) {
3931 num += (BDIGIT_DBL)zds[i]*base;
3932 zds[i++] = BIGLO(num);
3933 num = BIGDN(num);
3934 }
3935 if (num) {
3936 blen++;
3937 continue;
3938 }
3939 break;
3940 }
3941 RUBY_ASSERT(blen <= num_bdigits);
3942 }
3943
3944 return z;
3945}
3946
3947static VALUE
3948str2big_karatsuba(
3949 int sign,
3950 const char *digits_start,
3951 const char *digits_end,
3952 size_t num_digits,
3953 size_t num_bdigits,
3954 int digits_per_bdigits_dbl,
3955 int base)
3956{
3957 VALUE powerv;
3958 size_t unit;
3959 VALUE tmpuv = 0;
3960 BDIGIT *uds, *vds, *tds;
3961 BDIGIT_DBL dd;
3962 BDIGIT_DBL current_base;
3963 int m;
3964 int power_level = 0;
3965
3966 size_t i;
3967 const char *p;
3968 int c;
3969 VALUE z;
3970
3971 uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
3972 vds = uds + num_bdigits;
3973
3974 powerv = power_cache_get_power(base, power_level, NULL);
3975
3976 i = 0;
3977 dd = 0;
3978 current_base = 1;
3979 m = digits_per_bdigits_dbl;
3980 if (num_digits < (size_t)m)
3981 m = (int)num_digits;
3982 for (p = digits_end; digits_start < p; p--) {
3983 if ((c = conv_digit(p[-1])) < 0)
3984 continue;
3985 dd = dd + c * current_base;
3986 current_base *= base;
3987 num_digits--;
3988 m--;
3989 if (m == 0) {
3990 uds[i++] = BIGLO(dd);
3991 uds[i++] = (BDIGIT)BIGDN(dd);
3992 dd = 0;
3993 m = digits_per_bdigits_dbl;
3994 if (num_digits < (size_t)m)
3995 m = (int)num_digits;
3996 current_base = 1;
3997 }
3998 }
3999 RUBY_ASSERT(i == num_bdigits);
4000 for (unit = 2; unit < num_bdigits; unit *= 2) {
4001 for (i = 0; i < num_bdigits; i += unit*2) {
4002 if (2*unit <= num_bdigits - i) {
4003 bary_mul(vds+i, unit*2, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, unit);
4004 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
4005 }
4006 else if (unit <= num_bdigits - i) {
4007 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), BIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
4008 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
4009 }
4010 else {
4011 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
4012 }
4013 }
4014 power_level++;
4015 powerv = power_cache_get_power(base, power_level, NULL);
4016 tds = vds;
4017 vds = uds;
4018 uds = tds;
4019 }
4020 BARY_TRUNC(uds, num_bdigits);
4021 z = bignew(num_bdigits, sign);
4022 MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
4023
4024 if (tmpuv)
4025 ALLOCV_END(tmpuv);
4026
4027 return z;
4028}
4029
4030#if USE_GMP
4031static VALUE
4032str2big_gmp(
4033 int sign,
4034 const char *digits_start,
4035 const char *digits_end,
4036 size_t num_digits,
4037 size_t num_bdigits,
4038 int base)
4039{
4040 char *buf, *p;
4041 const char *q;
4042 VALUE tmps;
4043 mpz_t mz;
4044 VALUE z;
4045 BDIGIT *zds;
4046 size_t zn, count;
4047
4048 buf = ALLOCV_N(char, tmps, num_digits+1);
4049 p = buf;
4050 for (q = digits_start; q < digits_end; q++) {
4051 if (conv_digit(*q) < 0)
4052 continue;
4053 *p++ = *q;
4054 }
4055 *p = '\0';
4056
4057 mpz_init(mz);
4058 mpz_set_str(mz, buf, base);
4059 zn = num_bdigits;
4060 z = bignew(zn, sign);
4061 zds = BDIGITS(z);
4062 bdigits_from_mpz(mz, BDIGITS(z), &count);
4063 BDIGITS_ZERO(zds+count, zn-count);
4064 mpz_clear(mz);
4065
4066 if (tmps)
4067 ALLOCV_END(tmps);
4068
4069 return z;
4070}
4071#endif
4072
4073static VALUE rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base);
4074
4075/*
4076 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
4077 *
4078 * str: pointer to the string to be parsed.
4079 * should be NUL-terminated.
4080 * base: base of conversion, must be 2..36, or -36..0.
4081 * if +base+ > 0, the conversion is done according to the +base+
4082 * and unmatched prefix is parsed as a part of the result if
4083 * present.
4084 * if +base+ <= 0, the conversion is done according to the
4085 * prefix if present, in base <code>-base</code> if +base+ < -1,
4086 * or in base 10.
4087 * badcheck: if non-zero, +ArgumentError+ is raised when +str+ is not
4088 * valid as an Integer. if zero, Fixnum 0 is returned in
4089 * that case.
4090 */
4091VALUE
4092rb_cstr_to_inum(const char *str, int base, int badcheck)
4093{
4094 char *end;
4095 VALUE ret = rb_cstr_parse_inum(str, -1, (badcheck ? NULL : &end), base);
4096 if (NIL_P(ret)) {
4097 if (badcheck) rb_invalid_str(str, "Integer()");
4098 ret = INT2FIX(0);
4099 }
4100 return ret;
4101}
4102
4103/*
4104 * Parse +str+ as Ruby Integer, i.e., underscores, 0d and 0b prefixes.
4105 *
4106 * str: pointer to the string to be parsed.
4107 * should be NUL-terminated if +len+ is negative.
4108 * len: length of +str+ if >= 0. if +len+ is negative, +str+ should
4109 * be NUL-terminated.
4110 * endp: if non-NULL, the address after parsed part is stored. if
4111 * NULL, Qnil is returned when +str+ is not valid as an Integer.
4112 * ndigits: if non-NULL, the number of parsed digits is stored.
4113 * base: see +rb_cstr_to_inum+
4114 * flags: bitwise OR of below flags:
4115 * RB_INT_PARSE_SIGN: allow preceding spaces and +/- sign
4116 * RB_INT_PARSE_UNDERSCORE: allow an underscore between digits
4117 * RB_INT_PARSE_PREFIX: allow preceding prefix
4118 */
4119
4120VALUE
4121rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits,
4122 int base, int flags)
4123{
4124 const char *const s = str;
4125 char sign = 1;
4126 int c;
4127 VALUE z = Qnil;
4128
4129 unsigned long val;
4130 int ov;
4131
4132 const char *digits_start, *digits_end;
4133 size_t num_digits = 0;
4134 size_t num_bdigits;
4135 const ssize_t len0 = len;
4136 const int badcheck = !endp;
4137
4138#define ADV(n) do {\
4139 if (len > 0 && len <= (n)) goto bad; \
4140 str += (n); \
4141 len -= (n); \
4142 } while (0)
4143#define ASSERT_LEN() do {\
4144 RUBY_ASSERT(len != 0); \
4145 if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \
4146 } while (0)
4147
4148 if (!str) {
4149 goto bad;
4150 }
4151 if (len && (flags & RB_INT_PARSE_SIGN)) {
4152 while (ISSPACE(*str)) ADV(1);
4153
4154 if (str[0] == '+') {
4155 ADV(1);
4156 }
4157 else if (str[0] == '-') {
4158 ADV(1);
4159 sign = 0;
4160 }
4161 ASSERT_LEN();
4162 }
4163 if (base <= 0) {
4164 if (str[0] == '0' && len > 1) {
4165 switch (str[1]) {
4166 case 'x': case 'X':
4167 base = 16;
4168 ADV(2);
4169 break;
4170 case 'b': case 'B':
4171 base = 2;
4172 ADV(2);
4173 break;
4174 case 'o': case 'O':
4175 base = 8;
4176 ADV(2);
4177 break;
4178 case 'd': case 'D':
4179 base = 10;
4180 ADV(2);
4181 break;
4182 default:
4183 base = 8;
4184 }
4185 }
4186 else if (base < -1) {
4187 base = -base;
4188 }
4189 else {
4190 base = 10;
4191 }
4192 }
4193 else if (len == 1 || !(flags & RB_INT_PARSE_PREFIX)) {
4194 /* no prefix */
4195 }
4196 else if (base == 2) {
4197 if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
4198 ADV(2);
4199 }
4200 }
4201 else if (base == 8) {
4202 if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
4203 ADV(2);
4204 }
4205 }
4206 else if (base == 10) {
4207 if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
4208 ADV(2);
4209 }
4210 }
4211 else if (base == 16) {
4212 if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
4213 ADV(2);
4214 }
4215 }
4216 if (!valid_radix_p(base)) {
4217 invalid_radix(base);
4218 }
4219 if (!len) goto bad;
4220 num_digits = str - s;
4221 if (*str == '0' && len != 1) { /* squeeze preceding 0s */
4222 int us = 0;
4223 const char *end = len < 0 ? NULL : str + len;
4224 ++num_digits;
4225 while ((c = *++str) == '0' ||
4226 ((flags & RB_INT_PARSE_UNDERSCORE) && c == '_')) {
4227 if (c == '_') {
4228 if (++us >= 2)
4229 break;
4230 }
4231 else {
4232 ++num_digits;
4233 us = 0;
4234 }
4235 if (str == end) break;
4236 }
4237 if (!c || ISSPACE(c)) --str;
4238 if (end) len = end - str;
4239 }
4240 c = *str;
4241 c = conv_digit(c);
4242 if (c < 0 || c >= base) {
4243 if (!badcheck && num_digits) z = INT2FIX(0);
4244 goto bad;
4245 }
4246
4247 if (ndigits) *ndigits = num_digits;
4248 val = ruby_scan_digits(str, len, base, &num_digits, &ov);
4249 if (!ov) {
4250 const char *end = &str[num_digits];
4251 if (num_digits > 0 && *end == '_' && (flags & RB_INT_PARSE_UNDERSCORE))
4252 goto bigparse;
4253 if (endp) *endp = (char *)end;
4254 if (ndigits) *ndigits += num_digits;
4255 if (badcheck) {
4256 if (num_digits == 0) return Qnil; /* no number */
4257 while (len < 0 ? *end : end < str + len) {
4258 if (!ISSPACE(*end)) return Qnil; /* trailing garbage */
4259 end++;
4260 }
4261 }
4262
4263 if (POSFIXABLE(val)) {
4264 if (sign) return LONG2FIX(val);
4265 else {
4266 long result = -(long)val;
4267 return LONG2FIX(result);
4268 }
4269 }
4270 else {
4271 VALUE big = rb_uint2big(val);
4272 BIGNUM_SET_SIGN(big, sign);
4273 return bignorm(big);
4274 }
4275 }
4276
4277 bigparse:
4278 digits_start = str;
4279 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4280 goto bad;
4281 if (endp) *endp = (char *)(str + len);
4282 if (ndigits) *ndigits += num_digits;
4283 digits_end = digits_start + len;
4284
4285 if (POW2_P(base)) {
4286 z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
4287 bit_length(base-1));
4288 }
4289 else {
4290 int digits_per_bdigits_dbl;
4291 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4292 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4293
4294#if USE_GMP
4295 if (GMP_STR2BIG_DIGITS < num_bdigits) {
4296 z = str2big_gmp(sign, digits_start, digits_end, num_digits,
4297 num_bdigits, base);
4298 }
4299 else
4300#endif
4301 if (num_bdigits < KARATSUBA_MUL_DIGITS) {
4302 z = str2big_normal(sign, digits_start, digits_end,
4303 num_bdigits, base);
4304 }
4305 else {
4306 z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
4307 num_bdigits, digits_per_bdigits_dbl, base);
4308 }
4309 }
4310
4311 return bignorm(z);
4312
4313 bad:
4314 if (endp) *endp = (char *)str;
4315 if (ndigits) *ndigits = num_digits;
4316 return z;
4317}
4318
4319static VALUE
4320rb_cstr_parse_inum(const char *str, ssize_t len, char **endp, int base)
4321{
4322 return rb_int_parse_cstr(str, len, endp, NULL, base,
4323 RB_INT_PARSE_DEFAULT);
4324}
4325
4326VALUE
4327rb_str_convert_to_inum(VALUE str, int base, int badcheck, int raise_exception)
4328{
4329 VALUE ret;
4330 const char *s;
4331 long len;
4332 char *end;
4333
4334 StringValue(str);
4336 RSTRING_GETMEM(str, s, len);
4337 ret = rb_cstr_parse_inum(s, len, (badcheck ? NULL : &end), base);
4338 if (NIL_P(ret)) {
4339 if (badcheck) {
4340 if (!raise_exception) return Qnil;
4341 invalid_integer(str);
4342 }
4343 ret = INT2FIX(0);
4344 }
4345 return ret;
4346}
4347
4348VALUE
4349rb_str_to_inum(VALUE str, int base, int badcheck)
4350{
4351 return rb_str_convert_to_inum(str, base, badcheck, TRUE);
4352}
4353
4354VALUE
4355rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
4356{
4357 int positive_p = 1;
4358 const char *s, *str;
4359 const char *digits_start, *digits_end;
4360 size_t num_digits;
4361 ssize_t len;
4362 VALUE z;
4363
4364 if (!valid_radix_p(base) || !POW2_P(base)) {
4365 invalid_radix(base);
4366 }
4367
4369 s = str = StringValueCStr(arg);
4370 len = RSTRING_LEN(arg);
4371 if (*str == '-') {
4372 len--;
4373 str++;
4374 positive_p = 0;
4375 }
4376
4377 digits_start = str;
4378 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4379 invalid_integer(arg);
4380 digits_end = digits_start + len;
4381
4382 z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
4383 bit_length(base-1));
4384
4385 RB_GC_GUARD(arg);
4386
4387 return bignorm(z);
4388}
4389
4390VALUE
4391rb_str2big_normal(VALUE arg, int base, int badcheck)
4392{
4393 int positive_p = 1;
4394 const char *s, *str;
4395 const char *digits_start, *digits_end;
4396 size_t num_digits;
4397 ssize_t len;
4398 VALUE z;
4399
4400 int digits_per_bdigits_dbl;
4401 size_t num_bdigits;
4402
4403 if (!valid_radix_p(base)) {
4404 invalid_radix(base);
4405 }
4406
4408 s = str = StringValuePtr(arg);
4409 len = RSTRING_LEN(arg);
4410 if (len > 0 && *str == '-') {
4411 len--;
4412 str++;
4413 positive_p = 0;
4414 }
4415
4416 digits_start = str;
4417 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4418 invalid_integer(arg);
4419 digits_end = digits_start + len;
4420
4421 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4422 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4423
4424 z = str2big_normal(positive_p, digits_start, digits_end,
4425 num_bdigits, base);
4426
4427 RB_GC_GUARD(arg);
4428
4429 return bignorm(z);
4430}
4431
4432VALUE
4433rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
4434{
4435 int positive_p = 1;
4436 const char *s, *str;
4437 const char *digits_start, *digits_end;
4438 size_t num_digits;
4439 ssize_t len;
4440 VALUE z;
4441
4442 int digits_per_bdigits_dbl;
4443 size_t num_bdigits;
4444
4445 if (!valid_radix_p(base)) {
4446 invalid_radix(base);
4447 }
4448
4450 s = str = StringValuePtr(arg);
4451 len = RSTRING_LEN(arg);
4452 if (len > 0 && *str == '-') {
4453 len--;
4454 str++;
4455 positive_p = 0;
4456 }
4457
4458 digits_start = str;
4459 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4460 invalid_integer(arg);
4461 digits_end = digits_start + len;
4462
4463 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4464 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4465
4466 z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
4467 num_bdigits, digits_per_bdigits_dbl, base);
4468
4469 RB_GC_GUARD(arg);
4470
4471 return bignorm(z);
4472}
4473
4474#if USE_GMP
4475VALUE
4476rb_str2big_gmp(VALUE arg, int base, int badcheck)
4477{
4478 int positive_p = 1;
4479 const char *s, *str;
4480 const char *digits_start, *digits_end;
4481 size_t num_digits;
4482 ssize_t len;
4483 VALUE z;
4484
4485 int digits_per_bdigits_dbl;
4486 size_t num_bdigits;
4487
4488 if (!valid_radix_p(base)) {
4489 invalid_radix(base);
4490 }
4491
4493 s = str = StringValuePtr(arg);
4494 len = RSTRING_LEN(arg);
4495 if (len > 0 && *str == '-') {
4496 len--;
4497 str++;
4498 positive_p = 0;
4499 }
4500
4501 digits_start = str;
4502 if (!str2big_scan_digits(s, str, base, badcheck, &num_digits, &len))
4503 invalid_integer(arg);
4504 digits_end = digits_start + len;
4505
4506 maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
4507 num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
4508
4509 z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
4510
4511 RB_GC_GUARD(arg);
4512
4513 return bignorm(z);
4514}
4515#endif
4516
4517#if HAVE_LONG_LONG
4518
4519VALUE
4520rb_ull2big(unsigned LONG_LONG n)
4521{
4522 long i;
4523 VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
4524 BDIGIT *digits = BDIGITS(big);
4525
4526#if SIZEOF_BDIGIT >= SIZEOF_LONG_LONG
4527 digits[0] = n;
4528#else
4529 for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
4530 digits[i] = BIGLO(n);
4531 n = BIGDN(n);
4532 }
4533#endif
4534
4535 i = bdigit_roomof(SIZEOF_LONG_LONG);
4536 while (i-- && !digits[i]) ;
4537 BIGNUM_SET_LEN(big, i+1);
4538 return big;
4539}
4540
4541VALUE
4542rb_ll2big(LONG_LONG n)
4543{
4544 long neg = 0;
4545 unsigned LONG_LONG u;
4546 VALUE big;
4547
4548 if (n < 0) {
4549 u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
4550 neg = 1;
4551 }
4552 else {
4553 u = n;
4554 }
4555 big = rb_ull2big(u);
4556 if (neg) {
4557 BIGNUM_SET_NEGATIVE_SIGN(big);
4558 }
4559 return big;
4560}
4561
4562VALUE
4563rb_ull2inum(unsigned LONG_LONG n)
4564{
4565 if (POSFIXABLE(n)) return LONG2FIX((long)n);
4566 return rb_ull2big(n);
4567}
4568
4569VALUE
4571{
4572 if (FIXABLE(n)) return LONG2FIX((long)n);
4573 return rb_ll2big(n);
4574}
4575
4576#endif /* HAVE_LONG_LONG */
4577
4578#ifdef HAVE_INT128_T
4579VALUE
4580rb_uint128t2big(uint128_t n)
4581{
4582 long i;
4583 VALUE big = bignew(bdigit_roomof(SIZEOF_INT128_T), 1);
4584 BDIGIT *digits = BDIGITS(big);
4585
4586 for (i = 0; i < bdigit_roomof(SIZEOF_INT128_T); i++) {
4587 digits[i] = BIGLO(RSHIFT(n ,BITSPERDIG*i));
4588 }
4589
4590 i = bdigit_roomof(SIZEOF_INT128_T);
4591 while (i-- && !digits[i]) ;
4592 BIGNUM_SET_LEN(big, i+1);
4593 return big;
4594}
4595
4596VALUE
4597rb_int128t2big(int128_t n)
4598{
4599 int neg = 0;
4600 uint128_t u;
4601 VALUE big;
4602
4603 if (n < 0) {
4604 u = 1 + (uint128_t)(-(n + 1)); /* u = -n avoiding overflow */
4605 neg = 1;
4606 }
4607 else {
4608 u = n;
4609 }
4610 big = rb_uint128t2big(u);
4611 if (neg) {
4612 BIGNUM_SET_NEGATIVE_SIGN(big);
4613 }
4614 return big;
4615}
4616#endif
4617
4618VALUE
4619rb_cstr2inum(const char *str, int base)
4620{
4621 return rb_cstr_to_inum(str, base, base==0);
4622}
4623
4624VALUE
4625rb_str2inum(VALUE str, int base)
4626{
4627 return rb_str_to_inum(str, base, base==0);
4628}
4629
4630static VALUE
4631big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
4632{
4633 BDIGIT *xds, *zds;
4634 long s1;
4635 int s2;
4636 VALUE z;
4637 long xn;
4638
4639 if (lshift_p) {
4640 if (LONG_MAX < shift_numdigits) {
4641 too_big:
4642 rb_raise(rb_eRangeError, "shift width too big");
4643 }
4644 s1 = shift_numdigits;
4645 s2 = shift_numbits;
4646 if ((size_t)s1 != shift_numdigits) goto too_big;
4647 xn = BIGNUM_LEN(x);
4648 if (LONG_MAX/SIZEOF_BDIGIT <= xn+s1) goto too_big;
4649 z = bignew(xn+s1+1, BIGNUM_SIGN(x));
4650 zds = BDIGITS(z);
4651 BDIGITS_ZERO(zds, s1);
4652 xds = BDIGITS(x);
4653 zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
4654 }
4655 else {
4656 long zn;
4657 BDIGIT hibitsx;
4658 if (LONG_MAX < shift_numdigits || (size_t)BIGNUM_LEN(x) <= shift_numdigits) {
4659 if (BIGNUM_POSITIVE_P(x) ||
4660 bary_zero_p(BDIGITS(x), BIGNUM_LEN(x)))
4661 return INT2FIX(0);
4662 else
4663 return INT2FIX(-1);
4664 }
4665 s1 = shift_numdigits;
4666 s2 = shift_numbits;
4667 hibitsx = abs2twocomp(&x, &xn);
4668 xds = BDIGITS(x);
4669 if (xn <= s1) {
4670 return hibitsx ? INT2FIX(-1) : INT2FIX(0);
4671 }
4672 zn = xn - s1;
4673 z = bignew(zn, 0);
4674 zds = BDIGITS(z);
4675 bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
4676 twocomp2abs_bang(z, hibitsx != 0);
4677 }
4678 RB_GC_GUARD(x);
4679 return z;
4680}
4681
4682static VALUE
4683big_shift2(VALUE x, int lshift_p, VALUE y)
4684{
4685 int sign;
4686 size_t lens[2];
4687 size_t shift_numdigits;
4688 int shift_numbits;
4689
4690 RUBY_ASSERT(POW2_P(CHAR_BIT));
4691 RUBY_ASSERT(POW2_P(BITSPERDIG));
4692
4693 if (BIGZEROP(x))
4694 return INT2FIX(0);
4695 sign = rb_integer_pack(y, lens, numberof(lens), sizeof(size_t), 0,
4697 if (sign < 0) {
4698 lshift_p = !lshift_p;
4699 sign = -sign;
4700 }
4701 if (lshift_p) {
4702 if (1 < sign || CHAR_BIT <= lens[1])
4703 rb_raise(rb_eRangeError, "shift width too big");
4704 }
4705 else {
4706 if (1 < sign || CHAR_BIT <= lens[1])
4707 return BIGNUM_POSITIVE_P(x) ? INT2FIX(0) : INT2FIX(-1);
4708 }
4709 shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
4710 shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
4711 (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
4712 return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
4713}
4714
4715static VALUE
4716big_lshift(VALUE x, unsigned long shift)
4717{
4718 long s1 = shift/BITSPERDIG;
4719 int s2 = (int)(shift%BITSPERDIG);
4720 return big_shift3(x, 1, s1, s2);
4721}
4722
4723static VALUE
4724big_rshift(VALUE x, unsigned long shift)
4725{
4726 long s1 = shift/BITSPERDIG;
4727 int s2 = (int)(shift%BITSPERDIG);
4728 return big_shift3(x, 0, s1, s2);
4729}
4730
4731#define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
4732
4733static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4734static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
4735
4736static void
4737power_cache_init(void)
4738{
4739}
4740
4741static inline VALUE
4742power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
4743{
4744 /*
4745 * MAX_BASE36_POWER_TABLE_ENTRIES is big enough to that
4746 * base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1] fills whole memory.
4747 * So MAX_BASE36_POWER_TABLE_ENTRIES <= power_level is not possible to calculate.
4748 *
4749 * number-of-bytes =
4750 * log256(base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1]) =
4751 * log256(maxpow_in_bdigit_dbl(base)**(2**(MAX_BASE36_POWER_TABLE_ENTRIES-1))) =
4752 * log256(maxpow_in_bdigit_dbl(base)**(2**(SIZEOF_SIZE_T*CHAR_BIT))) =
4753 * (2**(SIZEOF_SIZE_T*CHAR_BIT))*log256(maxpow_in_bdigit_dbl(base)) =
4754 * (256**SIZEOF_SIZE_T)*log256(maxpow_in_bdigit_dbl(base)) >
4755 * (256**SIZEOF_SIZE_T)*(sizeof(BDIGIT_DBL)-1) >
4756 * 256**SIZEOF_SIZE_T
4757 */
4758 if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
4759 rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
4760
4761 VALUE power = base36_power_cache[base - 2][power_level];
4762 if (!power) {
4763 size_t numdigits;
4764 if (power_level == 0) {
4765 int numdigits0;
4766 BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
4767 power = bignew(2, 1);
4768 bdigitdbl2bary(BDIGITS(power), 2, dd);
4769 numdigits = numdigits0;
4770 }
4771 else {
4772 power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
4773 numdigits *= 2;
4774 }
4775 rb_obj_hide(power);
4776 base36_power_cache[base - 2][power_level] = power;
4777 base36_numdigits_cache[base - 2][power_level] = numdigits;
4778 rb_vm_register_global_object(power);
4779 }
4780 if (numdigits_ret)
4781 *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
4782 return power;
4783}
4784
4786 int negative;
4787 int base;
4788 BDIGIT_DBL hbase2;
4789 int hbase2_numdigits;
4790 VALUE result;
4791 char *ptr;
4792};
4793
4794static void
4795big2str_alloc(struct big2str_struct *b2s, size_t len)
4796{
4797 if (LONG_MAX-1 < len)
4798 rb_raise(rb_eArgError, "too big number");
4799 b2s->result = rb_usascii_str_new(0, (long)(len + 1)); /* plus one for sign */
4800 b2s->ptr = RSTRING_PTR(b2s->result);
4801 if (b2s->negative)
4802 *b2s->ptr++ = '-';
4803}
4804
4805static void
4806big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t taillen)
4807{
4808 size_t j;
4809 BDIGIT_DBL num;
4810 char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
4811 int beginning = !b2s->ptr;
4812 size_t len = 0;
4813
4814 RUBY_ASSERT(xn <= 2);
4815 num = bary2bdigitdbl(xds, xn);
4816
4817 if (beginning) {
4818 if (num == 0)
4819 return;
4820 p = buf;
4821 j = sizeof(buf);
4822 do {
4823 BDIGIT_DBL idx = num % b2s->base;
4824 num /= b2s->base;
4825 p[--j] = ruby_digitmap[idx];
4826 } while (num);
4827 len = sizeof(buf) - j;
4828 big2str_alloc(b2s, len + taillen);
4829 MEMCPY(b2s->ptr, buf + j, char, len);
4830 }
4831 else {
4832 p = b2s->ptr;
4833 j = b2s->hbase2_numdigits;
4834 do {
4835 BDIGIT_DBL idx = num % b2s->base;
4836 num /= b2s->base;
4837 p[--j] = ruby_digitmap[idx];
4838 } while (j);
4839 len = b2s->hbase2_numdigits;
4840 }
4841 b2s->ptr += len;
4842}
4843
4844static void
4845big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
4846 int power_level, size_t taillen)
4847{
4848 VALUE b;
4849 size_t half_numdigits, lower_numdigits;
4850 int lower_power_level;
4851 size_t bn;
4852 const BDIGIT *bds;
4853 size_t len;
4854
4855 /*
4856 * Precondition:
4857 * abs(x) < maxpow**(2**power_level)
4858 * where
4859 * maxpow = maxpow_in_bdigit_dbl(base, &numdigits)
4860 *
4861 * This function generates sequence of zeros, and then stringized abs(x) into b2s->ptr.
4862 *
4863 * b2s->ptr can be NULL.
4864 * It is allocated when the first character is generated via big2str_alloc.
4865 *
4866 * The prefix zeros should be generated if and only if b2s->ptr is not NULL.
4867 * When the zeros are generated, the zeros and abs(x) consists
4868 * numdigits*(2**power_level) characters at total.
4869 *
4870 * Note:
4871 * power_cache_get_power(base, power_level, &len) may not be cached yet. It should not be called.
4872 * power_cache_get_power(base, power_level-1, &len) should be cached already if 0 <= power_level-1.
4873 */
4874
4875 if (xn == 0 || bary_zero_p(xds, xn)) {
4876 if (b2s->ptr) {
4877 /* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
4878 power_cache_get_power(b2s->base, power_level, &len);
4879 memset(b2s->ptr, '0', len);
4880 b2s->ptr += len;
4881 }
4882 return;
4883 }
4884
4885 if (power_level == 0) {
4886 big2str_2bdigits(b2s, xds, xn, taillen);
4887 return;
4888 }
4889
4890 lower_power_level = power_level-1;
4891 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4892 bn = BIGNUM_LEN(b);
4893 bds = BDIGITS(b);
4894
4895 half_numdigits = lower_numdigits;
4896
4897 while (0 < lower_power_level &&
4898 (xn < bn ||
4899 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4900 lower_power_level--;
4901 b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
4902 bn = BIGNUM_LEN(b);
4903 bds = BDIGITS(b);
4904 }
4905
4906 if (lower_power_level == 0 &&
4907 (xn < bn ||
4908 (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
4909 if (b2s->ptr) {
4910 len = half_numdigits * 2 - lower_numdigits;
4911 memset(b2s->ptr, '0', len);
4912 b2s->ptr += len;
4913 }
4914 big2str_2bdigits(b2s, xds, xn, taillen);
4915 }
4916 else {
4917 BDIGIT *qds, *rds;
4918 size_t qn, rn;
4919 BDIGIT *tds;
4920 int shift;
4921
4922 if (lower_power_level != power_level-1 && b2s->ptr) {
4923 len = (half_numdigits - lower_numdigits) * 2;
4924 memset(b2s->ptr, '0', len);
4925 b2s->ptr += len;
4926 }
4927
4928 shift = nlz(bds[bn-1]);
4929
4930 qn = xn + BIGDIVREM_EXTRA_WORDS;
4931
4932 if (shift == 0) {
4933 /* bigdivrem_restoring will not modify y.
4934 * So use bds directly. */
4935 tds = (BDIGIT *)bds;
4936 xds[xn] = 0;
4937 }
4938 else {
4939 /* bigdivrem_restoring will modify y.
4940 * So use temporary buffer. */
4941 tds = xds + qn;
4942 RUBY_ASSERT(qn + bn <= xn + wn);
4943 bary_small_lshift(tds, bds, bn, shift);
4944 xds[xn] = bary_small_lshift(xds, xds, xn, shift);
4945 }
4946
4947 bigdivrem_restoring(xds, qn, tds, bn);
4948
4949 rds = xds;
4950 rn = bn;
4951
4952 qds = xds + bn;
4953 qn = qn - bn;
4954
4955 if (shift) {
4956 bary_small_rshift(rds, rds, rn, shift, 0);
4957 }
4958
4959 BARY_TRUNC(qds, qn);
4960 RUBY_ASSERT(qn <= bn);
4961 big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
4962 BARY_TRUNC(rds, rn);
4963 big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
4964 }
4965}
4966
4967static VALUE
4968big2str_base_poweroftwo(VALUE x, int base)
4969{
4970 int word_numbits = ffs(base) - 1;
4971 size_t numwords;
4972 VALUE result;
4973 char *ptr;
4974 numwords = rb_absint_numwords(x, word_numbits, NULL);
4975 if (BIGNUM_NEGATIVE_P(x)) {
4976 if (LONG_MAX-1 < numwords)
4977 rb_raise(rb_eArgError, "too big number");
4978 result = rb_usascii_str_new(0, 1+numwords);
4979 ptr = RSTRING_PTR(result);
4980 *ptr++ = BIGNUM_POSITIVE_P(x) ? '+' : '-';
4981 }
4982 else {
4983 if (LONG_MAX < numwords)
4984 rb_raise(rb_eArgError, "too big number");
4985 result = rb_usascii_str_new(0, numwords);
4986 ptr = RSTRING_PTR(result);
4987 }
4988 rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
4990 while (0 < numwords) {
4991 *ptr = ruby_digitmap[*(unsigned char *)ptr];
4992 ptr++;
4993 numwords--;
4994 }
4995 return result;
4996}
4997
4998VALUE
4999rb_big2str_poweroftwo(VALUE x, int base)
5000{
5001 return big2str_base_poweroftwo(x, base);
5002}
5003
5004static VALUE
5005big2str_generic(VALUE x, int base)
5006{
5007 BDIGIT *xds;
5008 size_t xn;
5009 struct big2str_struct b2s_data;
5010 int power_level;
5011 VALUE power;
5012
5013 xds = BDIGITS(x);
5014 xn = BIGNUM_LEN(x);
5015 BARY_TRUNC(xds, xn);
5016
5017 if (xn == 0) {
5018 return rb_usascii_str_new2("0");
5019 }
5020
5021 if (!valid_radix_p(base))
5022 invalid_radix(base);
5023
5024 if (xn >= LONG_MAX/BITSPERDIG) {
5025 rb_raise(rb_eRangeError, "bignum too big to convert into 'string'");
5026 }
5027
5028 power_level = 0;
5029 power = power_cache_get_power(base, power_level, NULL);
5030 while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
5031 (size_t)BIGNUM_LEN(power) <= (xn+1)/2) {
5032 power_level++;
5033 power = power_cache_get_power(base, power_level, NULL);
5034 }
5035 RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
5036
5037 if ((size_t)BIGNUM_LEN(power) <= xn) {
5038 /*
5039 * This increment guarantees x < power_cache_get_power(base, power_level)
5040 * without invoking it actually.
5041 * (power_cache_get_power(base, power_level) can be slow and not used
5042 * in big2str_karatsuba.)
5043 *
5044 * Although it is possible that x < power_cache_get_power(base, power_level-1),
5045 * it is no problem because big2str_karatsuba checks it and
5046 * doesn't affect the result when b2s_data.ptr is NULL.
5047 */
5048 power_level++;
5049 }
5050
5051 b2s_data.negative = BIGNUM_NEGATIVE_P(x);
5052 b2s_data.base = base;
5053 b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
5054
5055 b2s_data.result = Qnil;
5056 b2s_data.ptr = NULL;
5057
5058 if (power_level == 0) {
5059 big2str_2bdigits(&b2s_data, xds, xn, 0);
5060 }
5061 else {
5062 VALUE tmpw = 0;
5063 BDIGIT *wds;
5064 size_t wn;
5065 wn = power_level * BIGDIVREM_EXTRA_WORDS + BIGNUM_LEN(power);
5066 wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
5067 MEMCPY(wds, xds, BDIGIT, xn);
5068 big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
5069 if (tmpw)
5070 ALLOCV_END(tmpw);
5071 }
5072 RB_GC_GUARD(x);
5073
5074 *b2s_data.ptr = '\0';
5075 rb_str_resize(b2s_data.result, (long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
5076
5077 RB_GC_GUARD(x);
5078 return b2s_data.result;
5079}
5080
5081VALUE
5082rb_big2str_generic(VALUE x, int base)
5083{
5084 return big2str_generic(x, base);
5085}
5086
5087#if USE_GMP
5088static VALUE
5089big2str_gmp(VALUE x, int base)
5090{
5091 mpz_t mx;
5092 size_t size;
5093 VALUE str;
5094 BDIGIT *xds = BDIGITS(x);
5095 size_t xn = BIGNUM_LEN(x);
5096
5097 mpz_init(mx);
5098 bdigits_to_mpz(mx, xds, xn);
5099
5100 size = mpz_sizeinbase(mx, base);
5101
5102 if (BIGNUM_NEGATIVE_P(x)) {
5103 mpz_neg(mx, mx);
5104 str = rb_usascii_str_new(0, size+1);
5105 }
5106 else {
5107 str = rb_usascii_str_new(0, size);
5108 }
5109 mpz_get_str(RSTRING_PTR(str), base, mx);
5110 mpz_clear(mx);
5111
5112 if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\0') {
5113 rb_str_set_len(str, RSTRING_LEN(str)-1);
5114 }
5115
5116 RB_GC_GUARD(x);
5117 return str;
5118}
5119
5120VALUE
5121rb_big2str_gmp(VALUE x, int base)
5122{
5123 return big2str_gmp(x, base);
5124}
5125#endif
5126
5127static VALUE
5128rb_big2str1(VALUE x, int base)
5129{
5130 BDIGIT *xds;
5131 size_t xn;
5132
5133 if (FIXNUM_P(x)) {
5134 return rb_fix2str(x, base);
5135 }
5136
5137 bigtrunc(x);
5138 xds = BDIGITS(x);
5139 xn = BIGNUM_LEN(x);
5140 BARY_TRUNC(xds, xn);
5141
5142 if (xn == 0) {
5143 return rb_usascii_str_new2("0");
5144 }
5145
5146 if (!valid_radix_p(base))
5147 invalid_radix(base);
5148
5149 if (xn >= LONG_MAX/BITSPERDIG) {
5150 rb_raise(rb_eRangeError, "bignum too big to convert into 'string'");
5151 }
5152
5153 if (POW2_P(base)) {
5154 /* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
5155 return big2str_base_poweroftwo(x, base);
5156 }
5157
5158#if USE_GMP
5159 if (GMP_BIG2STR_DIGITS < xn) {
5160 return big2str_gmp(x, base);
5161 }
5162#endif
5163
5164 return big2str_generic(x, base);
5165}
5166
5167VALUE
5168rb_big2str(VALUE x, int base)
5169{
5170 return rb_big2str1(x, base);
5171}
5172
5173static unsigned long
5174big2ulong(VALUE x, const char *type)
5175{
5176#if SIZEOF_LONG > SIZEOF_BDIGIT
5177 size_t i;
5178#endif
5179 size_t len = BIGNUM_LEN(x);
5180 unsigned long num;
5181 BDIGIT *ds;
5182
5183 if (len == 0)
5184 return 0;
5185 if (BIGSIZE(x) > sizeof(long)) {
5186 rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type);
5187 }
5188 ds = BDIGITS(x);
5189#if SIZEOF_LONG <= SIZEOF_BDIGIT
5190 num = (unsigned long)ds[0];
5191#else
5192 num = 0;
5193 for (i = 0; i < len; i++) {
5194 num <<= BITSPERDIG;
5195 num += (unsigned long)ds[len - i - 1]; /* overflow is already checked */
5196 }
5197#endif
5198 return num;
5199}
5200
5201unsigned long
5202rb_big2ulong(VALUE x)
5203{
5204 unsigned long num = big2ulong(x, "unsigned long");
5205
5206 if (BIGNUM_POSITIVE_P(x)) {
5207 return num;
5208 }
5209 else {
5210 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5211 return -(long)(num-1)-1;
5212 }
5213 rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
5214}
5215
5216long
5217rb_big2long(VALUE x)
5218{
5219 unsigned long num = big2ulong(x, "long");
5220
5221 if (BIGNUM_POSITIVE_P(x)) {
5222 if (num <= LONG_MAX)
5223 return num;
5224 }
5225 else {
5226 if (num <= 1+(unsigned long)(-(LONG_MIN+1)))
5227 return -(long)(num-1)-1;
5228 }
5229 rb_raise(rb_eRangeError, "bignum too big to convert into 'long'");
5230}
5231
5232#if HAVE_LONG_LONG
5233
5234static unsigned LONG_LONG
5235big2ull(VALUE x, const char *type)
5236{
5237#if SIZEOF_LONG_LONG > SIZEOF_BDIGIT
5238 size_t i;
5239#endif
5240 size_t len = BIGNUM_LEN(x);
5241 unsigned LONG_LONG num;
5242 BDIGIT *ds = BDIGITS(x);
5243
5244 if (len == 0)
5245 return 0;
5246 if (BIGSIZE(x) > SIZEOF_LONG_LONG)
5247 rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type);
5248#if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT
5249 num = (unsigned LONG_LONG)ds[0];
5250#else
5251 num = 0;
5252 for (i = 0; i < len; i++) {
5253 num = BIGUP(num);
5254 num += ds[len - i - 1];
5255 }
5256#endif
5257 return num;
5258}
5259
5260unsigned LONG_LONG
5261rb_big2ull(VALUE x)
5262{
5263 unsigned LONG_LONG num = big2ull(x, "unsigned long long");
5264
5265 if (BIGNUM_POSITIVE_P(x)) {
5266 return num;
5267 }
5268 else {
5269 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5270 return -(LONG_LONG)(num-1)-1;
5271 }
5272 rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
5273}
5274
5276rb_big2ll(VALUE x)
5277{
5278 unsigned LONG_LONG num = big2ull(x, "long long");
5279
5280 if (BIGNUM_POSITIVE_P(x)) {
5281 if (num <= LLONG_MAX)
5282 return num;
5283 }
5284 else {
5285 if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
5286 return -(LONG_LONG)(num-1)-1;
5287 }
5288 rb_raise(rb_eRangeError, "bignum too big to convert into 'long long'");
5289}
5290
5291#endif /* HAVE_LONG_LONG */
5292
5293static VALUE
5294dbl2big(double d)
5295{
5296 long i = 0;
5297 BDIGIT c;
5298 BDIGIT *digits;
5299 VALUE z;
5300 double u = (d < 0)?-d:d;
5301
5302 if (isinf(d)) {
5303 rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
5304 }
5305 if (isnan(d)) {
5306 rb_raise(rb_eFloatDomainError, "NaN");
5307 }
5308
5309 while (1.0 <= u) {
5310 u /= (double)(BIGRAD);
5311 i++;
5312 }
5313 z = bignew(i, d>=0);
5314 digits = BDIGITS(z);
5315 while (i--) {
5316 u *= BIGRAD;
5317 c = (BDIGIT)u;
5318 u -= c;
5319 digits[i] = c;
5320 }
5321
5322 return z;
5323}
5324
5325VALUE
5326rb_dbl2big(double d)
5327{
5328 return bignorm(dbl2big(d));
5329}
5330
5331static double
5332big2dbl(VALUE x)
5333{
5334 double d = 0.0;
5335 long i = (bigtrunc(x), BIGNUM_LEN(x)), lo = 0, bits;
5336 BDIGIT *ds = BDIGITS(x), dl;
5337
5338 if (i) {
5339 bits = i * BITSPERDIG - nlz(ds[i-1]);
5340 if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
5341 d = HUGE_VAL;
5342 }
5343 else {
5344 if (bits > DBL_MANT_DIG+1)
5345 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
5346 else
5347 bits = 0;
5348 while (--i > lo) {
5349 d = ds[i] + BIGRAD*d;
5350 }
5351 dl = ds[i];
5352 if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
5353 int carry = (dl & ~(BDIGMAX << bits)) != 0;
5354 if (!carry) {
5355 while (i-- > 0) {
5356 carry = ds[i] != 0;
5357 if (carry) break;
5358 }
5359 }
5360 if (carry) {
5361 BDIGIT mask = BDIGMAX;
5362 BDIGIT bit = 1;
5363 mask <<= bits;
5364 bit <<= bits;
5365 dl &= mask;
5366 dl += bit;
5367 dl = BIGLO(dl);
5368 if (!dl) d += 1;
5369 }
5370 }
5371 d = dl + BIGRAD*d;
5372 if (lo) {
5373 if (lo > INT_MAX / BITSPERDIG)
5374 d = HUGE_VAL;
5375 else if (lo < INT_MIN / BITSPERDIG)
5376 d = 0.0;
5377 else
5378 d = ldexp(d, (int)(lo * BITSPERDIG));
5379 }
5380 }
5381 }
5382 if (BIGNUM_NEGATIVE_P(x)) d = -d;
5383 return d;
5384}
5385
5386double
5387rb_big2dbl(VALUE x)
5388{
5389 double d = big2dbl(x);
5390
5391 if (isinf(d)) {
5392 rb_warning("Integer out of Float range");
5393 if (d < 0.0)
5394 d = -HUGE_VAL;
5395 else
5396 d = HUGE_VAL;
5397 }
5398 return d;
5399}
5400
5401VALUE
5402rb_integer_float_cmp(VALUE x, VALUE y)
5403{
5404 double yd = RFLOAT_VALUE(y);
5405 double yi, yf;
5406 VALUE rel;
5407
5408 if (isnan(yd))
5409 return Qnil;
5410 if (isinf(yd)) {
5411 if (yd > 0.0) return INT2FIX(-1);
5412 else return INT2FIX(1);
5413 }
5414 yf = modf(yd, &yi);
5415 if (FIXNUM_P(x)) {
5416#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5417 double xd = (double)FIX2LONG(x);
5418 if (xd < yd)
5419 return INT2FIX(-1);
5420 if (xd > yd)
5421 return INT2FIX(1);
5422 return INT2FIX(0);
5423#else
5424 long xn, yn;
5425 if (yi < FIXNUM_MIN)
5426 return INT2FIX(1);
5427 if (FIXNUM_MAX+1 <= yi)
5428 return INT2FIX(-1);
5429 xn = FIX2LONG(x);
5430 yn = (long)yi;
5431 if (xn < yn)
5432 return INT2FIX(-1);
5433 if (xn > yn)
5434 return INT2FIX(1);
5435 if (yf < 0.0)
5436 return INT2FIX(1);
5437 if (0.0 < yf)
5438 return INT2FIX(-1);
5439 return INT2FIX(0);
5440#endif
5441 }
5442 y = rb_dbl2big(yi);
5443 rel = rb_big_cmp(x, y);
5444 if (yf == 0.0 || rel != INT2FIX(0))
5445 return rel;
5446 if (yf < 0.0)
5447 return INT2FIX(1);
5448 return INT2FIX(-1);
5449}
5450
5451#if SIZEOF_LONG * CHAR_BIT >= DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5452COMPILER_WARNING_PUSH
5453#if __has_warning("-Wimplicit-int-float-conversion")
5454COMPILER_WARNING_IGNORED(-Wimplicit-int-float-conversion)
5455#endif
5456static const double LONG_MAX_as_double = LONG_MAX;
5457COMPILER_WARNING_POP
5458#endif
5459
5460VALUE
5461rb_integer_float_eq(VALUE x, VALUE y)
5462{
5463 double yd = RFLOAT_VALUE(y);
5464 double yi, yf;
5465
5466 if (!isfinite(yd))
5467 return Qfalse;
5468 yf = modf(yd, &yi);
5469 if (yf != 0)
5470 return Qfalse;
5471 if (FIXNUM_P(x)) {
5472#if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
5473 double xd = (double)FIX2LONG(x);
5474 return RBOOL(xd == yd);
5475#else
5476 long xn, yn;
5477 if (yi < LONG_MIN || LONG_MAX_as_double <= yi)
5478 return Qfalse;
5479 xn = FIX2LONG(x);
5480 yn = (long)yi;
5481 return RBOOL(xn == yn);
5482#endif
5483 }
5484 y = rb_dbl2big(yi);
5485 return rb_big_eq(x, y);
5486}
5487
5488
5489VALUE
5490rb_big_cmp(VALUE x, VALUE y)
5491{
5492 if (FIXNUM_P(y)) {
5493 x = bigfixize(x);
5494 if (FIXNUM_P(x)) {
5495 /* SIGNED_VALUE and Fixnum have same sign-bits, same
5496 * order */
5497 SIGNED_VALUE sx = (SIGNED_VALUE)x, sy = (SIGNED_VALUE)y;
5498 if (sx < sy) return INT2FIX(-1);
5499 return INT2FIX(sx > sy);
5500 }
5501 }
5502 else if (RB_BIGNUM_TYPE_P(y)) {
5503 if (BIGNUM_SIGN(x) == BIGNUM_SIGN(y)) {
5504 int cmp = bary_cmp(BDIGITS(x), BIGNUM_LEN(x), BDIGITS(y), BIGNUM_LEN(y));
5505 return INT2FIX(BIGNUM_SIGN(x) ? cmp : -cmp);
5506 }
5507 }
5508 else if (RB_FLOAT_TYPE_P(y)) {
5509 return rb_integer_float_cmp(x, y);
5510 }
5511 else {
5512 return rb_num_coerce_cmp(x, y, idCmp);
5513 }
5514 return INT2FIX(BIGNUM_SIGN(x) ? 1 : -1);
5515}
5516
5517enum big_op_t {
5518 big_op_gt,
5519 big_op_ge,
5520 big_op_lt,
5521 big_op_le
5522};
5523
5524static VALUE
5525big_op(VALUE x, VALUE y, enum big_op_t op)
5526{
5527 VALUE rel;
5528 int n;
5529
5530 if (RB_INTEGER_TYPE_P(y)) {
5531 rel = rb_big_cmp(x, y);
5532 }
5533 else if (RB_FLOAT_TYPE_P(y)) {
5534 rel = rb_integer_float_cmp(x, y);
5535 }
5536 else {
5537 ID id = 0;
5538 switch (op) {
5539 case big_op_gt: id = '>'; break;
5540 case big_op_ge: id = idGE; break;
5541 case big_op_lt: id = '<'; break;
5542 case big_op_le: id = idLE; break;
5543 }
5544 return rb_num_coerce_relop(x, y, id);
5545 }
5546
5547 if (NIL_P(rel)) return Qfalse;
5548 n = FIX2INT(rel);
5549
5550 switch (op) {
5551 case big_op_gt: return RBOOL(n > 0);
5552 case big_op_ge: return RBOOL(n >= 0);
5553 case big_op_lt: return RBOOL(n < 0);
5554 case big_op_le: return RBOOL(n <= 0);
5555 }
5556 return Qundef;
5557}
5558
5559VALUE
5560rb_big_gt(VALUE x, VALUE y)
5561{
5562 return big_op(x, y, big_op_gt);
5563}
5564
5565VALUE
5566rb_big_ge(VALUE x, VALUE y)
5567{
5568 return big_op(x, y, big_op_ge);
5569}
5570
5571VALUE
5572rb_big_lt(VALUE x, VALUE y)
5573{
5574 return big_op(x, y, big_op_lt);
5575}
5576
5577VALUE
5578rb_big_le(VALUE x, VALUE y)
5579{
5580 return big_op(x, y, big_op_le);
5581}
5582
5583/*
5584 * call-seq:
5585 * big == obj -> true or false
5586 *
5587 * Returns <code>true</code> only if <i>obj</i> has the same value
5588 * as <i>big</i>. Contrast this with Integer#eql?, which requires
5589 * <i>obj</i> to be an Integer.
5590 *
5591 * 68719476736 == 68719476736.0 #=> true
5592 */
5593
5594VALUE
5595rb_big_eq(VALUE x, VALUE y)
5596{
5597 if (FIXNUM_P(y)) {
5598 return RBOOL(bignorm(x) == y);
5599 }
5600 else if (RB_BIGNUM_TYPE_P(y)) {
5601 }
5602 else if (RB_FLOAT_TYPE_P(y)) {
5603 return rb_integer_float_eq(x, y);
5604 }
5605 else {
5606 return rb_equal(y, x);
5607 }
5608 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5609 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5610 return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5611}
5612
5613VALUE
5614rb_big_eql(VALUE x, VALUE y)
5615{
5616 if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
5617 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y)) return Qfalse;
5618 if (BIGNUM_LEN(x) != BIGNUM_LEN(y)) return Qfalse;
5619 return RBOOL(MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,BIGNUM_LEN(y)) == 0);
5620}
5621
5622VALUE
5623rb_big_uminus(VALUE x)
5624{
5625 VALUE z = rb_big_clone(x);
5626
5627 BIGNUM_NEGATE(z);
5628
5629 return bignorm(z);
5630}
5631
5632VALUE
5633rb_big_comp(VALUE x)
5634{
5635 VALUE z = rb_big_clone(x);
5636 BDIGIT *ds = BDIGITS(z);
5637 long n = BIGNUM_LEN(z);
5638
5639 if (!n) return INT2FIX(-1);
5640
5641 if (BIGNUM_POSITIVE_P(z)) {
5642 if (bary_add_one(ds, n)) {
5643 big_extend_carry(z);
5644 }
5645 BIGNUM_SET_NEGATIVE_SIGN(z);
5646 }
5647 else {
5648 bary_neg(ds, n);
5649 if (bary_add_one(ds, n))
5650 return INT2FIX(-1);
5651 bary_neg(ds, n);
5652 BIGNUM_SET_POSITIVE_SIGN(z);
5653 }
5654
5655 return bignorm(z);
5656}
5657
5658static VALUE
5659bigsub(VALUE x, VALUE y)
5660{
5661 VALUE z;
5662 BDIGIT *xds, *yds, *zds;
5663 long xn, yn, zn;
5664
5665 xn = BIGNUM_LEN(x);
5666 yn = BIGNUM_LEN(y);
5667 zn = xn < yn ? yn : xn;
5668
5669 z = bignew(zn, 1);
5670
5671 xds = BDIGITS(x);
5672 yds = BDIGITS(y);
5673 zds = BDIGITS(z);
5674
5675 if (bary_sub(zds, zn, xds, xn, yds, yn)) {
5676 bary_2comp(zds, zn);
5677 BIGNUM_SET_NEGATIVE_SIGN(z);
5678 }
5679
5680 return z;
5681}
5682
5683static VALUE bigadd_int(VALUE x, long y);
5684
5685static VALUE
5686bigsub_int(VALUE x, long y0)
5687{
5688 VALUE z;
5689 BDIGIT *xds, *zds;
5690 long xn, zn;
5691 BDIGIT_DBL_SIGNED num;
5692 long i, y;
5693
5694 y = y0;
5695 xds = BDIGITS(x);
5696 xn = BIGNUM_LEN(x);
5697
5698 if (xn == 0)
5699 return LONG2NUM(-y0);
5700
5701 zn = xn;
5702#if SIZEOF_BDIGIT < SIZEOF_LONG
5703 if (zn < bdigit_roomof(SIZEOF_LONG))
5704 zn = bdigit_roomof(SIZEOF_LONG);
5705#endif
5706 z = bignew(zn, BIGNUM_SIGN(x));
5707 zds = BDIGITS(z);
5708
5709#if SIZEOF_BDIGIT >= SIZEOF_LONG
5710 RUBY_ASSERT(xn == zn);
5711 num = (BDIGIT_DBL_SIGNED)xds[0] - y;
5712 if (xn == 1 && num < 0) {
5713 BIGNUM_NEGATE(z);
5714 zds[0] = (BDIGIT)-num;
5715 RB_GC_GUARD(x);
5716 return bignorm(z);
5717 }
5718 zds[0] = BIGLO(num);
5719 num = BIGDN(num);
5720 i = 1;
5721 if (i < xn)
5722 goto y_is_zero_x;
5723 goto finish;
5724#else
5725 num = 0;
5726 for (i=0; i < xn; i++) {
5727 if (y == 0) goto y_is_zero_x;
5728 num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
5729 zds[i] = BIGLO(num);
5730 num = BIGDN(num);
5731 y = BIGDN(y);
5732 }
5733 for (; i < zn; i++) {
5734 if (y == 0) goto y_is_zero_z;
5735 num -= BIGLO(y);
5736 zds[i] = BIGLO(num);
5737 num = BIGDN(num);
5738 y = BIGDN(y);
5739 }
5740 goto finish;
5741#endif
5742
5743 for (; i < xn; i++) {
5744 y_is_zero_x:
5745 if (num == 0) goto num_is_zero_x;
5746 num += xds[i];
5747 zds[i] = BIGLO(num);
5748 num = BIGDN(num);
5749 }
5750#if SIZEOF_BDIGIT < SIZEOF_LONG
5751 for (; i < zn; i++) {
5752 y_is_zero_z:
5753 if (num == 0) goto num_is_zero_z;
5754 zds[i] = BIGLO(num);
5755 num = BIGDN(num);
5756 }
5757#endif
5758 goto finish;
5759
5760 for (; i < xn; i++) {
5761 num_is_zero_x:
5762 zds[i] = xds[i];
5763 }
5764#if SIZEOF_BDIGIT < SIZEOF_LONG
5765 for (; i < zn; i++) {
5766 num_is_zero_z:
5767 zds[i] = 0;
5768 }
5769#endif
5770 goto finish;
5771
5772 finish:
5773 RUBY_ASSERT(num == 0 || num == -1);
5774 if (num < 0) {
5775 get2comp(z);
5776 BIGNUM_NEGATE(z);
5777 }
5778 RB_GC_GUARD(x);
5779 return bignorm(z);
5780}
5781
5782static VALUE
5783bigadd_int(VALUE x, long y)
5784{
5785 VALUE z;
5786 BDIGIT *xds, *zds;
5787 long xn, zn;
5788 BDIGIT_DBL num;
5789 long i;
5790
5791 xds = BDIGITS(x);
5792 xn = BIGNUM_LEN(x);
5793
5794 if (xn == 0)
5795 return LONG2NUM(y);
5796
5797 zn = xn;
5798#if SIZEOF_BDIGIT < SIZEOF_LONG
5799 if (zn < bdigit_roomof(SIZEOF_LONG))
5800 zn = bdigit_roomof(SIZEOF_LONG);
5801#endif
5802 zn++;
5803
5804 z = bignew(zn, BIGNUM_SIGN(x));
5805 zds = BDIGITS(z);
5806
5807#if SIZEOF_BDIGIT >= SIZEOF_LONG
5808 num = (BDIGIT_DBL)xds[0] + y;
5809 zds[0] = BIGLO(num);
5810 num = BIGDN(num);
5811 i = 1;
5812 if (i < xn)
5813 goto y_is_zero_x;
5814 goto y_is_zero_z;
5815#else
5816 num = 0;
5817 for (i=0; i < xn; i++) {
5818 if (y == 0) goto y_is_zero_x;
5819 num += (BDIGIT_DBL)xds[i] + BIGLO(y);
5820 zds[i] = BIGLO(num);
5821 num = BIGDN(num);
5822 y = BIGDN(y);
5823 }
5824 for (; i < zn; i++) {
5825 if (y == 0) goto y_is_zero_z;
5826 num += BIGLO(y);
5827 zds[i] = BIGLO(num);
5828 num = BIGDN(num);
5829 y = BIGDN(y);
5830 }
5831 goto finish;
5832
5833#endif
5834
5835 for (;i < xn; i++) {
5836 y_is_zero_x:
5837 if (num == 0) goto num_is_zero_x;
5838 num += (BDIGIT_DBL)xds[i];
5839 zds[i] = BIGLO(num);
5840 num = BIGDN(num);
5841 }
5842 for (; i < zn; i++) {
5843 y_is_zero_z:
5844 if (num == 0) goto num_is_zero_z;
5845 zds[i] = BIGLO(num);
5846 num = BIGDN(num);
5847 }
5848 goto finish;
5849
5850 for (;i < xn; i++) {
5851 num_is_zero_x:
5852 zds[i] = xds[i];
5853 }
5854 for (; i < zn; i++) {
5855 num_is_zero_z:
5856 zds[i] = 0;
5857 }
5858 goto finish;
5859
5860 finish:
5861 RB_GC_GUARD(x);
5862 return bignorm(z);
5863}
5864
5865static VALUE
5866bigadd(VALUE x, VALUE y, int sign)
5867{
5868 VALUE z;
5869 size_t len;
5870
5871 sign = (sign == BIGNUM_SIGN(y));
5872 if (BIGNUM_SIGN(x) != sign) {
5873 if (sign) return bigsub(y, x);
5874 return bigsub(x, y);
5875 }
5876
5877 if (BIGNUM_LEN(x) > BIGNUM_LEN(y)) {
5878 len = BIGNUM_LEN(x) + 1;
5879 }
5880 else {
5881 len = BIGNUM_LEN(y) + 1;
5882 }
5883 z = bignew(len, sign);
5884
5885 bary_add(BDIGITS(z), BIGNUM_LEN(z),
5886 BDIGITS(x), BIGNUM_LEN(x),
5887 BDIGITS(y), BIGNUM_LEN(y));
5888
5889 return z;
5890}
5891
5892VALUE
5893rb_big_plus(VALUE x, VALUE y)
5894{
5895 long n;
5896
5897 if (FIXNUM_P(y)) {
5898 n = FIX2LONG(y);
5899 if ((n > 0) != BIGNUM_SIGN(x)) {
5900 if (n < 0) {
5901 n = -n;
5902 }
5903 return bigsub_int(x, n);
5904 }
5905 if (n < 0) {
5906 n = -n;
5907 }
5908 return bigadd_int(x, n);
5909 }
5910 else if (RB_BIGNUM_TYPE_P(y)) {
5911 return bignorm(bigadd(x, y, 1));
5912 }
5913 else if (RB_FLOAT_TYPE_P(y)) {
5914 return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
5915 }
5916 else {
5917 return rb_num_coerce_bin(x, y, '+');
5918 }
5919}
5920
5921VALUE
5922rb_big_minus(VALUE x, VALUE y)
5923{
5924 long n;
5925
5926 if (FIXNUM_P(y)) {
5927 n = FIX2LONG(y);
5928 if ((n > 0) != BIGNUM_SIGN(x)) {
5929 if (n < 0) {
5930 n = -n;
5931 }
5932 return bigadd_int(x, n);
5933 }
5934 if (n < 0) {
5935 n = -n;
5936 }
5937 return bigsub_int(x, n);
5938 }
5939 else if (RB_BIGNUM_TYPE_P(y)) {
5940 return bignorm(bigadd(x, y, 0));
5941 }
5942 else if (RB_FLOAT_TYPE_P(y)) {
5943 return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
5944 }
5945 else {
5946 return rb_num_coerce_bin(x, y, '-');
5947 }
5948}
5949
5950static VALUE
5951bigsq(VALUE x)
5952{
5953 long xn, zn;
5954 VALUE z;
5955 BDIGIT *xds, *zds;
5956
5957 xn = BIGNUM_LEN(x);
5958 if (MUL_OVERFLOW_LONG_P(2, xn))
5959 rb_raise(rb_eArgError, "square overflow");
5960 zn = 2 * xn;
5961
5962 z = bignew(zn, 1);
5963
5964 xds = BDIGITS(x);
5965 zds = BDIGITS(z);
5966
5967 if (xn < NAIVE_MUL_DIGITS)
5968 bary_sq_fast(zds, zn, xds, xn);
5969 else
5970 bary_mul(zds, zn, xds, xn, xds, xn);
5971
5972 RB_GC_GUARD(x);
5973 return z;
5974}
5975
5976static VALUE
5977bigmul0(VALUE x, VALUE y)
5978{
5979 long xn, yn, zn;
5980 VALUE z;
5981 BDIGIT *xds, *yds, *zds;
5982
5983 if (x == y)
5984 return bigsq(x);
5985
5986 xn = BIGNUM_LEN(x);
5987 yn = BIGNUM_LEN(y);
5988 if (ADD_OVERFLOW_LONG_P(xn, yn))
5989 rb_raise(rb_eArgError, "multiplication overflow");
5990 zn = xn + yn;
5991
5992 z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
5993
5994 xds = BDIGITS(x);
5995 yds = BDIGITS(y);
5996 zds = BDIGITS(z);
5997
5998 bary_mul(zds, zn, xds, xn, yds, yn);
5999
6000 RB_GC_GUARD(x);
6001 RB_GC_GUARD(y);
6002 return z;
6003}
6004
6005VALUE
6006rb_big_mul(VALUE x, VALUE y)
6007{
6008 if (FIXNUM_P(y)) {
6009 y = rb_int2big(FIX2LONG(y));
6010 }
6011 else if (RB_BIGNUM_TYPE_P(y)) {
6012 }
6013 else if (RB_FLOAT_TYPE_P(y)) {
6014 return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
6015 }
6016 else {
6017 return rb_num_coerce_bin(x, y, '*');
6018 }
6019
6020 return bignorm(bigmul0(x, y));
6021}
6022
6023static VALUE
6024bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
6025{
6026 long xn = BIGNUM_LEN(x), yn = BIGNUM_LEN(y);
6027 VALUE z;
6028 BDIGIT *xds, *yds, *zds;
6029 BDIGIT dd;
6030
6031 VALUE q = Qnil, r = Qnil;
6032 BDIGIT *qds, *rds;
6033 long qn, rn;
6034
6035 yds = BDIGITS(y);
6036 BARY_TRUNC(yds, yn);
6037 if (yn == 0)
6039
6040 xds = BDIGITS(x);
6041 BARY_TRUNC(xds, xn);
6042
6043 if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
6044 if (divp) *divp = rb_int2big(0);
6045 if (modp) *modp = x;
6046 return Qnil;
6047 }
6048 if (yn == 1) {
6049 dd = yds[0];
6050 z = bignew(xn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6051 zds = BDIGITS(z);
6052 dd = bigdivrem_single(zds, xds, xn, dd);
6053 if (modp) {
6054 *modp = rb_uint2big((uintptr_t)dd);
6055 BIGNUM_SET_SIGN(*modp, BIGNUM_SIGN(x));
6056 }
6057 if (divp) *divp = z;
6058 return Qnil;
6059 }
6060 if (xn == 2 && yn == 2) {
6061 BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
6062 BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
6063 BDIGIT_DBL q0 = x0 / y0;
6064 BDIGIT_DBL r0 = x0 % y0;
6065 if (divp) {
6066 z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6067 zds = BDIGITS(z);
6068 zds[0] = BIGLO(q0);
6069 zds[1] = BIGLO(BIGDN(q0));
6070 *divp = z;
6071 }
6072 if (modp) {
6073 z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), BIGNUM_SIGN(x));
6074 zds = BDIGITS(z);
6075 zds[0] = BIGLO(r0);
6076 zds[1] = BIGLO(BIGDN(r0));
6077 *modp = z;
6078 }
6079 return Qnil;
6080 }
6081
6082 if (divp) {
6083 qn = xn + BIGDIVREM_EXTRA_WORDS;
6084 q = bignew(qn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
6085 qds = BDIGITS(q);
6086 }
6087 else {
6088 qn = 0;
6089 qds = NULL;
6090 }
6091
6092 if (modp) {
6093 rn = yn;
6094 r = bignew(rn, BIGNUM_SIGN(x));
6095 rds = BDIGITS(r);
6096 }
6097 else {
6098 rn = 0;
6099 rds = NULL;
6100 }
6101
6102 bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
6103
6104 if (divp) {
6105 bigtrunc(q);
6106 *divp = q;
6107 }
6108 if (modp) {
6109 bigtrunc(r);
6110 *modp = r;
6111 }
6112
6113 return Qnil;
6114}
6115
6116static void
6117bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
6118{
6119 VALUE mod;
6120
6121 bigdivrem(x, y, divp, &mod);
6122 if (BIGNUM_SIGN(x) != BIGNUM_SIGN(y) && !BIGZEROP(mod)) {
6123 if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
6124 if (modp) *modp = bigadd(mod, y, 1);
6125 }
6126 else if (modp) {
6127 *modp = mod;
6128 }
6129}
6130
6131
6132static VALUE
6133rb_big_divide(VALUE x, VALUE y, ID op)
6134{
6135 VALUE z;
6136
6137 if (FIXNUM_P(y)) {
6138 y = rb_int2big(FIX2LONG(y));
6139 }
6140 else if (RB_BIGNUM_TYPE_P(y)) {
6141 }
6142 else if (RB_FLOAT_TYPE_P(y)) {
6143 if (op == '/') {
6144 double dx = rb_big2dbl(x);
6145 return rb_flo_div_flo(DBL2NUM(dx), y);
6146 }
6147 else {
6148 VALUE v;
6149 double dy = RFLOAT_VALUE(y);
6150 if (dy == 0.0) rb_num_zerodiv();
6151 v = rb_big_divide(x, y, '/');
6152 return rb_dbl2big(RFLOAT_VALUE(v));
6153 }
6154 }
6155 else {
6156 return rb_num_coerce_bin(x, y, op);
6157 }
6158 bigdivmod(x, y, &z, 0);
6159
6160 return bignorm(z);
6161}
6162
6163VALUE
6164rb_big_div(VALUE x, VALUE y)
6165{
6166 return rb_big_divide(x, y, '/');
6167}
6168
6169VALUE
6170rb_big_idiv(VALUE x, VALUE y)
6171{
6172 return rb_big_divide(x, y, idDiv);
6173}
6174
6175VALUE
6176rb_big_modulo(VALUE x, VALUE y)
6177{
6178 VALUE z;
6179
6180 if (FIXNUM_P(y)) {
6181 y = rb_int2big(FIX2LONG(y));
6182 }
6183 else if (!RB_BIGNUM_TYPE_P(y)) {
6184 return rb_num_coerce_bin(x, y, '%');
6185 }
6186 bigdivmod(x, y, 0, &z);
6187
6188 return bignorm(z);
6189}
6190
6191VALUE
6192rb_big_remainder(VALUE x, VALUE y)
6193{
6194 VALUE z;
6195
6196 if (FIXNUM_P(y)) {
6197 y = rb_int2big(FIX2LONG(y));
6198 }
6199 else if (!RB_BIGNUM_TYPE_P(y)) {
6200 return rb_num_coerce_bin(x, y, rb_intern("remainder"));
6201 }
6202 bigdivrem(x, y, 0, &z);
6203
6204 return bignorm(z);
6205}
6206
6207VALUE
6208rb_big_divmod(VALUE x, VALUE y)
6209{
6210 VALUE div, mod;
6211
6212 if (FIXNUM_P(y)) {
6213 y = rb_int2big(FIX2LONG(y));
6214 }
6215 else if (!RB_BIGNUM_TYPE_P(y)) {
6216 return rb_num_coerce_bin(x, y, idDivmod);
6217 }
6218 bigdivmod(x, y, &div, &mod);
6219
6220 return rb_assoc_new(bignorm(div), bignorm(mod));
6221}
6222
6223static VALUE
6224big_shift(VALUE x, long n)
6225{
6226 if (n < 0)
6227 return big_lshift(x, 1+(unsigned long)(-(n+1)));
6228 else if (n > 0)
6229 return big_rshift(x, (unsigned long)n);
6230 return x;
6231}
6232
6233enum {DBL_BIGDIG = ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)};
6234
6235static double
6236big_fdiv(VALUE x, VALUE y, long ey)
6237{
6238 VALUE z;
6239 long l, ex;
6240
6241 bigtrunc(x);
6242 l = BIGNUM_LEN(x);
6243 ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
6244 ex -= 2 * DBL_BIGDIG * BITSPERDIG;
6245 if (ex > BITSPERDIG) ex -= BITSPERDIG;
6246 else if (ex > 0) ex = 0;
6247 if (ex) x = big_shift(x, ex);
6248
6249 bigdivrem(x, y, &z, 0);
6250 l = ex - ey;
6251#if SIZEOF_LONG > SIZEOF_INT
6252 {
6253 /* Visual C++ can't be here */
6254 if (l > INT_MAX) return HUGE_VAL;
6255 if (l < INT_MIN) return 0.0;
6256 }
6257#endif
6258 return ldexp(big2dbl(z), (int)l);
6259}
6260
6261static double
6262big_fdiv_int(VALUE x, VALUE y)
6263{
6264 long l, ey;
6265 bigtrunc(y);
6266 l = BIGNUM_LEN(y);
6267 ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
6268 ey -= DBL_BIGDIG * BITSPERDIG;
6269 if (ey) y = big_shift(y, ey);
6270 return big_fdiv(x, y, ey);
6271}
6272
6273static double
6274big_fdiv_float(VALUE x, VALUE y)
6275{
6276 int i;
6277 y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
6278 return big_fdiv(x, y, i - DBL_MANT_DIG);
6279}
6280
6281double
6282rb_big_fdiv_double(VALUE x, VALUE y)
6283{
6284 double dx, dy;
6285 VALUE v;
6286
6287 dx = big2dbl(x);
6288 if (FIXNUM_P(y)) {
6289 dy = (double)FIX2LONG(y);
6290 if (isinf(dx))
6291 return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
6292 }
6293 else if (RB_BIGNUM_TYPE_P(y)) {
6294 return big_fdiv_int(x, y);
6295 }
6296 else if (RB_FLOAT_TYPE_P(y)) {
6297 dy = RFLOAT_VALUE(y);
6298 if (isnan(dy))
6299 return dy;
6300 if (isinf(dx))
6301 return big_fdiv_float(x, y);
6302 }
6303 else {
6304 return NUM2DBL(rb_num_coerce_bin(x, y, idFdiv));
6305 }
6306 v = rb_flo_div_flo(DBL2NUM(dx), DBL2NUM(dy));
6307 return NUM2DBL(v);
6308}
6309
6310VALUE
6311rb_big_fdiv(VALUE x, VALUE y)
6312{
6313 return DBL2NUM(rb_big_fdiv_double(x, y));
6314}
6315
6316VALUE
6317rb_big_pow(VALUE x, VALUE y)
6318{
6319 double d;
6320 SIGNED_VALUE yy;
6321
6322 again:
6323 if (y == INT2FIX(0)) return INT2FIX(1);
6324 if (y == INT2FIX(1)) return x;
6325 if (RB_FLOAT_TYPE_P(y)) {
6326 d = RFLOAT_VALUE(y);
6327 if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
6328 return rb_dbl_complex_new_polar_pi(pow(-rb_big2dbl(x), d), d);
6329 }
6330 }
6331 else if (RB_BIGNUM_TYPE_P(y)) {
6332 y = bignorm(y);
6333 if (FIXNUM_P(y))
6334 goto again;
6335 rb_raise(rb_eArgError, "exponent is too large");
6336 }
6337 else if (FIXNUM_P(y)) {
6338 yy = FIX2LONG(y);
6339
6340 if (yy < 0) {
6341 x = rb_big_pow(x, LONG2NUM(-yy));
6342 if (RB_INTEGER_TYPE_P(x))
6343 return rb_rational_raw(INT2FIX(1), x);
6344 else
6345 return DBL2NUM(1.0 / NUM2DBL(x));
6346 }
6347 else {
6348 VALUE z = 0;
6349 SIGNED_VALUE mask;
6350 const size_t xbits = rb_absint_numwords(x, 1, NULL);
6351#if SIZEOF_SIZE_T == 4
6352 const size_t BIGLEN_LIMIT = 1ULL << 31; // 2 GB
6353#else // SIZEOF_SIZE_T == 8
6354 const size_t BIGLEN_LIMIT = 1ULL << 34; // 16 GB
6355#endif
6356
6357 if (xbits == (size_t)-1 ||
6358 (xbits > BIGLEN_LIMIT) ||
6359 MUL_OVERFLOW_LONG_P(yy, xbits) ||
6360 (xbits * yy > BIGLEN_LIMIT)) {
6361 rb_raise(rb_eArgError, "exponent is too large");
6362 }
6363 else {
6364 for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
6365 if (z) z = bigsq(z);
6366 if (yy & mask) {
6367 z = z ? bigtrunc(bigmul0(z, x)) : x;
6368 }
6369 }
6370 return bignorm(z);
6371 }
6372 }
6373 }
6374 else {
6375 return rb_num_coerce_bin(x, y, idPow);
6376 }
6377 return DBL2NUM(pow(rb_big2dbl(x), d));
6378}
6379
6380static VALUE
6381bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6382{
6383 VALUE z;
6384 BDIGIT *xds, *zds;
6385 long zn;
6386 long i;
6387 BDIGIT hibitsy;
6388
6389 if (y == 0) return INT2FIX(0);
6390 if (xn == 0) return hibitsx ? LONG2NUM(y) : INT2FIX(0);
6391 hibitsy = 0 <= y ? 0 : BDIGMAX;
6392 xds = BDIGITS(x);
6393#if SIZEOF_BDIGIT >= SIZEOF_LONG
6394 if (!hibitsy) {
6395 y &= xds[0];
6396 return LONG2NUM(y);
6397 }
6398#endif
6399
6400 zn = xn;
6401#if SIZEOF_BDIGIT < SIZEOF_LONG
6402 if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
6403 zn = bdigit_roomof(SIZEOF_LONG);
6404#endif
6405
6406 z = bignew(zn, 0);
6407 zds = BDIGITS(z);
6408
6409#if SIZEOF_BDIGIT >= SIZEOF_LONG
6410 i = 1;
6411 zds[0] = xds[0] & BIGLO(y);
6412#else
6413 for (i=0; i < xn; i++) {
6414 if (y == 0 || y == -1) break;
6415 zds[i] = xds[i] & BIGLO(y);
6416 y = BIGDN(y);
6417 }
6418 for (; i < zn; i++) {
6419 if (y == 0 || y == -1) break;
6420 zds[i] = hibitsx & BIGLO(y);
6421 y = BIGDN(y);
6422 }
6423#endif
6424 for (;i < xn; i++) {
6425 zds[i] = xds[i] & hibitsy;
6426 }
6427 for (;i < zn; i++) {
6428 zds[i] = hibitsx & hibitsy;
6429 }
6430 twocomp2abs_bang(z, hibitsx && hibitsy);
6431 RB_GC_GUARD(x);
6432 return bignorm(z);
6433}
6434
6435VALUE
6436rb_big_and(VALUE x, VALUE y)
6437{
6438 VALUE z;
6439 BDIGIT *ds1, *ds2, *zds;
6440 long i, xn, yn, n1, n2;
6441 BDIGIT hibitsx, hibitsy;
6442 BDIGIT hibits1, hibits2;
6443 VALUE tmpv;
6444 BDIGIT tmph;
6445 long tmpn;
6446
6447 if (!RB_INTEGER_TYPE_P(y)) {
6448 return rb_num_coerce_bit(x, y, '&');
6449 }
6450
6451 hibitsx = abs2twocomp(&x, &xn);
6452 if (FIXNUM_P(y)) {
6453 return bigand_int(x, xn, hibitsx, FIX2LONG(y));
6454 }
6455 hibitsy = abs2twocomp(&y, &yn);
6456 if (xn > yn) {
6457 tmpv = x; x = y; y = tmpv;
6458 tmpn = xn; xn = yn; yn = tmpn;
6459 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6460 }
6461 n1 = xn;
6462 n2 = yn;
6463 ds1 = BDIGITS(x);
6464 ds2 = BDIGITS(y);
6465 hibits1 = hibitsx;
6466 hibits2 = hibitsy;
6467
6468 if (!hibits1)
6469 n2 = n1;
6470
6471 z = bignew(n2, 0);
6472 zds = BDIGITS(z);
6473
6474 for (i=0; i<n1; i++) {
6475 zds[i] = ds1[i] & ds2[i];
6476 }
6477 for (; i<n2; i++) {
6478 zds[i] = hibits1 & ds2[i];
6479 }
6480 twocomp2abs_bang(z, hibits1 && hibits2);
6481 RB_GC_GUARD(x);
6482 RB_GC_GUARD(y);
6483 return bignorm(z);
6484}
6485
6486static VALUE
6487bigor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6488{
6489 VALUE z;
6490 BDIGIT *xds, *zds;
6491 long zn;
6492 long i;
6493 BDIGIT hibitsy;
6494
6495 if (y == -1) return INT2FIX(-1);
6496 if (xn == 0) return hibitsx ? INT2FIX(-1) : LONG2FIX(y);
6497 hibitsy = 0 <= y ? 0 : BDIGMAX;
6498 xds = BDIGITS(x);
6499
6500 zn = BIGNUM_LEN(x);
6501#if SIZEOF_BDIGIT < SIZEOF_LONG
6502 if (zn < bdigit_roomof(SIZEOF_LONG))
6503 zn = bdigit_roomof(SIZEOF_LONG);
6504#endif
6505 z = bignew(zn, 0);
6506 zds = BDIGITS(z);
6507
6508#if SIZEOF_BDIGIT >= SIZEOF_LONG
6509 i = 1;
6510 zds[0] = xds[0] | BIGLO(y);
6511 if (i < zn)
6512 goto y_is_fixed_point;
6513 goto finish;
6514#else
6515 for (i=0; i < xn; i++) {
6516 if (y == 0 || y == -1) goto y_is_fixed_point;
6517 zds[i] = xds[i] | BIGLO(y);
6518 y = BIGDN(y);
6519 }
6520 if (hibitsx)
6521 goto fill_hibits;
6522 for (; i < zn; i++) {
6523 if (y == 0 || y == -1) goto y_is_fixed_point;
6524 zds[i] = BIGLO(y);
6525 y = BIGDN(y);
6526 }
6527 goto finish;
6528#endif
6529
6530 y_is_fixed_point:
6531 if (hibitsy)
6532 goto fill_hibits;
6533 for (; i < xn; i++) {
6534 zds[i] = xds[i];
6535 }
6536 if (hibitsx)
6537 goto fill_hibits;
6538 for (; i < zn; i++) {
6539 zds[i] = 0;
6540 }
6541 goto finish;
6542
6543 fill_hibits:
6544 for (; i < zn; i++) {
6545 zds[i] = BDIGMAX;
6546 }
6547
6548 finish:
6549 twocomp2abs_bang(z, hibitsx || hibitsy);
6550 RB_GC_GUARD(x);
6551 return bignorm(z);
6552}
6553
6554VALUE
6555rb_big_or(VALUE x, VALUE y)
6556{
6557 VALUE z;
6558 BDIGIT *ds1, *ds2, *zds;
6559 long i, xn, yn, n1, n2;
6560 BDIGIT hibitsx, hibitsy;
6561 BDIGIT hibits1, hibits2;
6562 VALUE tmpv;
6563 BDIGIT tmph;
6564 long tmpn;
6565
6566 if (!RB_INTEGER_TYPE_P(y)) {
6567 return rb_num_coerce_bit(x, y, '|');
6568 }
6569
6570 hibitsx = abs2twocomp(&x, &xn);
6571 if (FIXNUM_P(y)) {
6572 return bigor_int(x, xn, hibitsx, FIX2LONG(y));
6573 }
6574 hibitsy = abs2twocomp(&y, &yn);
6575 if (xn > yn) {
6576 tmpv = x; x = y; y = tmpv;
6577 tmpn = xn; xn = yn; yn = tmpn;
6578 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6579 }
6580 n1 = xn;
6581 n2 = yn;
6582 ds1 = BDIGITS(x);
6583 ds2 = BDIGITS(y);
6584 hibits1 = hibitsx;
6585 hibits2 = hibitsy;
6586
6587 if (hibits1)
6588 n2 = n1;
6589
6590 z = bignew(n2, 0);
6591 zds = BDIGITS(z);
6592
6593 for (i=0; i<n1; i++) {
6594 zds[i] = ds1[i] | ds2[i];
6595 }
6596 for (; i<n2; i++) {
6597 zds[i] = hibits1 | ds2[i];
6598 }
6599 twocomp2abs_bang(z, hibits1 || hibits2);
6600 RB_GC_GUARD(x);
6601 RB_GC_GUARD(y);
6602 return bignorm(z);
6603}
6604
6605static VALUE
6606bigxor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
6607{
6608 VALUE z;
6609 BDIGIT *xds, *zds;
6610 long zn;
6611 long i;
6612 BDIGIT hibitsy;
6613
6614 hibitsy = 0 <= y ? 0 : BDIGMAX;
6615 xds = BDIGITS(x);
6616 zn = BIGNUM_LEN(x);
6617#if SIZEOF_BDIGIT < SIZEOF_LONG
6618 if (zn < bdigit_roomof(SIZEOF_LONG))
6619 zn = bdigit_roomof(SIZEOF_LONG);
6620#endif
6621 z = bignew(zn, 0);
6622 zds = BDIGITS(z);
6623
6624#if SIZEOF_BDIGIT >= SIZEOF_LONG
6625 i = 1;
6626 zds[0] = xds[0] ^ BIGLO(y);
6627#else
6628 for (i = 0; i < xn; i++) {
6629 zds[i] = xds[i] ^ BIGLO(y);
6630 y = BIGDN(y);
6631 }
6632 for (; i < zn; i++) {
6633 zds[i] = hibitsx ^ BIGLO(y);
6634 y = BIGDN(y);
6635 }
6636#endif
6637 for (; i < xn; i++) {
6638 zds[i] = xds[i] ^ hibitsy;
6639 }
6640 for (; i < zn; i++) {
6641 zds[i] = hibitsx ^ hibitsy;
6642 }
6643 twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
6644 RB_GC_GUARD(x);
6645 return bignorm(z);
6646}
6647
6648VALUE
6649rb_big_xor(VALUE x, VALUE y)
6650{
6651 VALUE z;
6652 BDIGIT *ds1, *ds2, *zds;
6653 long i, xn, yn, n1, n2;
6654 BDIGIT hibitsx, hibitsy;
6655 BDIGIT hibits1, hibits2;
6656 VALUE tmpv;
6657 BDIGIT tmph;
6658 long tmpn;
6659
6660 if (!RB_INTEGER_TYPE_P(y)) {
6661 return rb_num_coerce_bit(x, y, '^');
6662 }
6663
6664 hibitsx = abs2twocomp(&x, &xn);
6665 if (FIXNUM_P(y)) {
6666 return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
6667 }
6668 hibitsy = abs2twocomp(&y, &yn);
6669 if (xn > yn) {
6670 tmpv = x; x = y; y = tmpv;
6671 tmpn = xn; xn = yn; yn = tmpn;
6672 tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
6673 }
6674 n1 = xn;
6675 n2 = yn;
6676 ds1 = BDIGITS(x);
6677 ds2 = BDIGITS(y);
6678 hibits1 = hibitsx;
6679 hibits2 = hibitsy;
6680
6681 z = bignew(n2, 0);
6682 zds = BDIGITS(z);
6683
6684 for (i=0; i<n1; i++) {
6685 zds[i] = ds1[i] ^ ds2[i];
6686 }
6687 for (; i<n2; i++) {
6688 zds[i] = hibitsx ^ ds2[i];
6689 }
6690 twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
6691 RB_GC_GUARD(x);
6692 RB_GC_GUARD(y);
6693 return bignorm(z);
6694}
6695
6696VALUE
6697rb_big_lshift(VALUE x, VALUE y)
6698{
6699 int lshift_p;
6700 size_t shift_numdigits;
6701 int shift_numbits;
6702
6703 for (;;) {
6704 if (FIXNUM_P(y)) {
6705 long l = FIX2LONG(y);
6706 unsigned long shift;
6707 if (0 <= l) {
6708 lshift_p = 1;
6709 shift = l;
6710 }
6711 else {
6712 lshift_p = 0;
6713 shift = 1+(unsigned long)(-(l+1));
6714 }
6715 shift_numbits = (int)(shift & (BITSPERDIG-1));
6716 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6717 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6718 }
6719 else if (RB_BIGNUM_TYPE_P(y)) {
6720 return bignorm(big_shift2(x, 1, y));
6721 }
6722 y = rb_to_int(y);
6723 }
6724}
6725
6726VALUE
6727rb_big_rshift(VALUE x, VALUE y)
6728{
6729 int lshift_p;
6730 size_t shift_numdigits;
6731 int shift_numbits;
6732
6733 for (;;) {
6734 if (FIXNUM_P(y)) {
6735 long l = FIX2LONG(y);
6736 unsigned long shift;
6737 if (0 <= l) {
6738 lshift_p = 0;
6739 shift = l;
6740 }
6741 else {
6742 lshift_p = 1;
6743 shift = 1+(unsigned long)(-(l+1));
6744 }
6745 shift_numbits = (int)(shift & (BITSPERDIG-1));
6746 shift_numdigits = shift >> bit_length(BITSPERDIG-1);
6747 return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
6748 }
6749 else if (RB_BIGNUM_TYPE_P(y)) {
6750 return bignorm(big_shift2(x, 0, y));
6751 }
6752 y = rb_to_int(y);
6753 }
6754}
6755
6756VALUE
6757rb_big_aref(VALUE x, VALUE y)
6758{
6759 BDIGIT *xds;
6760 size_t shift;
6761 size_t i, s1, s2;
6762 long l;
6763 BDIGIT bit;
6764
6765 if (RB_BIGNUM_TYPE_P(y)) {
6766 if (BIGNUM_NEGATIVE_P(y))
6767 return INT2FIX(0);
6768 bigtrunc(y);
6769 if (BIGSIZE(y) > sizeof(size_t)) {
6770 return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
6771 }
6772#if SIZEOF_SIZE_T <= SIZEOF_LONG
6773 shift = big2ulong(y, "long");
6774#else
6775 shift = big2ull(y, "long long");
6776#endif
6777 }
6778 else {
6779 l = NUM2LONG(y);
6780 if (l < 0) return INT2FIX(0);
6781 shift = (size_t)l;
6782 }
6783 s1 = shift/BITSPERDIG;
6784 s2 = shift%BITSPERDIG;
6785 bit = (BDIGIT)1 << s2;
6786
6787 if (s1 >= BIGNUM_LEN(x))
6788 return BIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
6789
6790 xds = BDIGITS(x);
6791 if (BIGNUM_POSITIVE_P(x))
6792 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6793 if (xds[s1] & (bit-1))
6794 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6795 for (i = 0; i < s1; i++)
6796 if (xds[i])
6797 return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
6798 return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
6799}
6800
6801VALUE
6802rb_big_aref2(VALUE x, VALUE beg, VALUE len)
6803{
6804 BDIGIT *xds, *vds;
6805 VALUE v;
6806 size_t copy_begin, xn, shift;
6807 ssize_t begin, length, end;
6808 bool negative_add_one;
6809
6810 beg = rb_to_int(beg);
6811 len = rb_to_int(len);
6812 length = NUM2SSIZET(len);
6813 begin = NUM2SSIZET(beg);
6814 end = NUM2SSIZET(rb_int_plus(beg, len));
6815 shift = begin < 0 ? -begin : 0;
6816 xn = BIGNUM_LEN(x);
6817 xds = BDIGITS(x);
6818
6819 if (length < 0) return rb_big_rshift(x, beg);
6820 if (length == 0 || end <= 0) return INT2FIX(0);
6821 if (begin < 0) begin = 0;
6822
6823 if ((size_t)(end - 1) / BITSPERDIG >= xn) {
6824 /* end > xn * BITSPERDIG */
6825 end = xn * BITSPERDIG;
6826 }
6827
6828 if ((size_t)begin / BITSPERDIG < xn) {
6829 /* begin < xn * BITSPERDIG */
6830 size_t shift_bits, copy_end;
6831 copy_begin = begin / BITSPERDIG;
6832 shift_bits = begin % BITSPERDIG;
6833 copy_end = (end - 1) / BITSPERDIG + 1;
6834 v = bignew(copy_end - copy_begin, 1);
6835 vds = BDIGITS(v);
6836 MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
6837 negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
6838 v = bignorm(v);
6839 if (shift_bits) v = rb_int_rshift(v, SIZET2NUM(shift_bits));
6840 }
6841 else {
6842 /* Out of range */
6843 v = INT2FIX(0);
6844 negative_add_one = false;
6845 copy_begin = begin = end = 0;
6846 }
6847
6848 if (BIGNUM_NEGATIVE_P(x)) {
6849 size_t mask_size = length - shift;
6850 VALUE mask = rb_int_minus(rb_int_lshift(INT2FIX(1), SIZET2NUM(mask_size)), INT2FIX(1));
6851 v = rb_int_xor(v, mask);
6852 for (size_t i = 0; negative_add_one && i < copy_begin; i++) {
6853 if (xds[i]) negative_add_one = false;
6854 }
6855 if (negative_add_one) v = rb_int_plus(v, INT2FIX(1));
6856 v = rb_int_and(v, mask);
6857 }
6858 else {
6859 size_t mask_size = (size_t)end - begin;
6860 VALUE mask = rb_int_minus(rb_int_lshift(INT2FIX(1), SIZET2NUM(mask_size)), INT2FIX(1));
6861 v = rb_int_and(v, mask);
6862 }
6863 RB_GC_GUARD(x);
6864 if (shift) v = rb_int_lshift(v, SSIZET2NUM(shift));
6865 return v;
6866}
6867
6868VALUE
6869rb_big_hash(VALUE x)
6870{
6871 st_index_t hash;
6872
6873 hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*BIGNUM_LEN(x)) ^ BIGNUM_SIGN(x);
6874 return ST2FIX(hash);
6875}
6876
6877/*
6878 * call-seq:
6879 * int.coerce(numeric) -> array
6880 *
6881 * Returns an array with both a +numeric+ and a +int+ represented as
6882 * Integer objects or Float objects.
6883 *
6884 * This is achieved by converting +numeric+ to an Integer or a Float.
6885 *
6886 * A TypeError is raised if the +numeric+ is not an Integer or a Float
6887 * type.
6888 *
6889 * (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
6890 */
6891
6892static VALUE
6893rb_int_coerce(VALUE x, VALUE y)
6894{
6895 if (RB_INTEGER_TYPE_P(y)) {
6896 return rb_assoc_new(y, x);
6897 }
6898 else {
6899 x = rb_Float(x);
6900 y = rb_Float(y);
6901 return rb_assoc_new(y, x);
6902 }
6903}
6904
6905VALUE
6906rb_big_abs(VALUE x)
6907{
6908 if (BIGNUM_NEGATIVE_P(x)) {
6909 x = rb_big_clone(x);
6910 BIGNUM_SET_POSITIVE_SIGN(x);
6911 }
6912 return x;
6913}
6914
6915int
6916rb_big_sign(VALUE x)
6917{
6918 return BIGNUM_SIGN(x);
6919}
6920
6921size_t
6922rb_big_size(VALUE big)
6923{
6924 return BIGSIZE(big);
6925}
6926
6927VALUE
6928rb_big_size_m(VALUE big)
6929{
6930 return SIZET2NUM(rb_big_size(big));
6931}
6932
6933VALUE
6934rb_big_bit_length(VALUE big)
6935{
6936 int nlz_bits;
6937 size_t numbytes;
6938
6939 static const BDIGIT char_bit[1] = { CHAR_BIT };
6940 BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
6941 BDIGIT nlz_bary[1];
6942 BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
6943
6944 numbytes = rb_absint_size(big, &nlz_bits);
6945
6946 if (numbytes == 0)
6947 return LONG2FIX(0);
6948
6949 if (BIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
6950 if (nlz_bits != CHAR_BIT-1) {
6951 nlz_bits++;
6952 }
6953 else {
6954 nlz_bits = 0;
6955 numbytes--;
6956 }
6957 }
6958
6959 if (numbytes <= SIZE_MAX / CHAR_BIT) {
6960 return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
6961 }
6962
6963 nlz_bary[0] = nlz_bits;
6964
6965 bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
6967 BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
6968 BARY_SUB(result_bary, result_bary, nlz_bary);
6969
6970 return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
6972}
6973
6974VALUE
6975rb_big_odd_p(VALUE num)
6976{
6977 return RBOOL(BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1);
6978}
6979
6980VALUE
6981rb_big_even_p(VALUE num)
6982{
6983 if (BIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
6984 return Qfalse;
6985 }
6986 return Qtrue;
6987}
6988
6989unsigned long rb_ulong_isqrt(unsigned long);
6990#if SIZEOF_BDIGIT*2 > SIZEOF_LONG
6991BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
6992# ifdef ULL_TO_DOUBLE
6993# define BDIGIT_DBL_TO_DOUBLE(n) ULL_TO_DOUBLE(n)
6994# endif
6995#else
6996# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
6997#endif
6998#ifndef BDIGIT_DBL_TO_DOUBLE
6999# define BDIGIT_DBL_TO_DOUBLE(n) (double)(n)
7000#endif
7001
7002VALUE
7003rb_big_isqrt(VALUE n)
7004{
7005 BDIGIT *nds = BDIGITS(n);
7006 size_t len = BIGNUM_LEN(n);
7007
7008 if (len <= 2) {
7009 BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len));
7010#if SIZEOF_BDIGIT > SIZEOF_LONG
7011 return ULL2NUM(sq);
7012#else
7013 return ULONG2NUM(sq);
7014#endif
7015 }
7016 else {
7017 size_t shift = FIX2LONG(rb_big_bit_length(n)) / 4;
7018 VALUE n2 = rb_int_rshift(n, SIZET2NUM(2 * shift));
7019 VALUE x = FIXNUM_P(n2) ? LONG2FIX(rb_ulong_isqrt(FIX2ULONG(n2))) : rb_big_isqrt(n2);
7020 /* x = (x+n/x)/2 */
7021 x = rb_int_plus(rb_int_lshift(x, SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n, SIZET2NUM(shift + 1)), x));
7022 VALUE xx = rb_int_mul(x, x);
7023 while (rb_int_gt(xx, n)) {
7024 xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x), INT2FIX(1)));
7025 x = rb_int_minus(x, INT2FIX(1));
7026 }
7027 return x;
7028 }
7029}
7030
7031#if USE_GMP
7032static void
7033bary_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)
7034{
7035 mpz_t z, x, y, m;
7036 size_t count;
7037 mpz_init(x);
7038 mpz_init(y);
7039 mpz_init(m);
7040 mpz_init(z);
7041 bdigits_to_mpz(x, xds, xn);
7042 bdigits_to_mpz(y, yds, yn);
7043 bdigits_to_mpz(m, mds, mn);
7044 mpz_powm(z, x, y, m);
7045 bdigits_from_mpz(z, zds, &count);
7046 BDIGITS_ZERO(zds+count, zn-count);
7047 mpz_clear(x);
7048 mpz_clear(y);
7049 mpz_clear(m);
7050 mpz_clear(z);
7051}
7052#endif
7053
7054static VALUE
7055int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
7056{
7057#if USE_GMP
7058 VALUE z;
7059 size_t xn, yn, mn, zn;
7060
7061 if (FIXNUM_P(x)) {
7062 x = rb_int2big(FIX2LONG(x));
7063 }
7064 if (FIXNUM_P(y)) {
7065 y = rb_int2big(FIX2LONG(y));
7066 }
7067 RUBY_ASSERT(RB_BIGNUM_TYPE_P(m));
7068 xn = BIGNUM_LEN(x);
7069 yn = BIGNUM_LEN(y);
7070 mn = BIGNUM_LEN(m);
7071 zn = mn;
7072 z = bignew(zn, 1);
7073 bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
7074 if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
7075 z = rb_big_minus(z, m);
7076 }
7077 RB_GC_GUARD(x);
7078 RB_GC_GUARD(y);
7079 RB_GC_GUARD(m);
7080 return rb_big_norm(z);
7081#else
7082 VALUE tmp = LONG2FIX(1L);
7083 long yy;
7084
7085 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7086 if (RTEST(rb_int_odd_p(y))) {
7087 tmp = rb_int_mul(tmp, x);
7088 tmp = rb_int_modulo(tmp, m);
7089 }
7090 x = rb_int_mul(x, x);
7091 x = rb_int_modulo(x, m);
7092 }
7093 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7094 if (yy & 1L) {
7095 tmp = rb_int_mul(tmp, x);
7096 tmp = rb_int_modulo(tmp, m);
7097 }
7098 x = rb_int_mul(x, x);
7099 x = rb_int_modulo(x, m);
7100 }
7101
7102 if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
7103 tmp = rb_int_minus(tmp, m);
7104 }
7105 return tmp;
7106#endif
7107}
7108
7109/*
7110 * Integer#pow
7111 */
7112
7113static VALUE
7114int_pow_tmp1(VALUE x, VALUE y, long mm, int nega_flg)
7115{
7116 long xx = FIX2LONG(x);
7117 long tmp = 1L;
7118 long yy;
7119
7120 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7121 if (RTEST(rb_int_odd_p(y))) {
7122 tmp = (tmp * xx) % mm;
7123 }
7124 xx = (xx * xx) % mm;
7125 }
7126 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7127 if (yy & 1L) {
7128 tmp = (tmp * xx) % mm;
7129 }
7130 xx = (xx * xx) % mm;
7131 }
7132
7133 if (nega_flg && tmp) {
7134 tmp -= mm;
7135 }
7136 return LONG2FIX(tmp);
7137}
7138
7139static VALUE
7140int_pow_tmp2(VALUE x, VALUE y, long mm, int nega_flg)
7141{
7142 long tmp = 1L;
7143 long yy;
7144#ifdef DLONG
7145 const DLONG m = mm;
7146 long tmp2 = tmp;
7147 long xx = FIX2LONG(x);
7148# define MUL_MODULO(a, b, c) (long)(((DLONG)(a) * (DLONG)(b)) % (c))
7149#else
7150 const VALUE m = LONG2FIX(mm);
7151 VALUE tmp2 = LONG2FIX(tmp);
7152 VALUE xx = x;
7153# define MUL_MODULO(a, b, c) rb_int_modulo(rb_fix_mul_fix((a), (b)), (c))
7154#endif
7155
7156 for (/*NOP*/; ! FIXNUM_P(y); y = rb_big_rshift(y, LONG2FIX(1L))) {
7157 if (RTEST(rb_int_odd_p(y))) {
7158 tmp2 = MUL_MODULO(tmp2, xx, m);
7159 }
7160 xx = MUL_MODULO(xx, xx, m);
7161 }
7162 for (yy = FIX2LONG(y); yy; yy >>= 1L) {
7163 if (yy & 1L) {
7164 tmp2 = MUL_MODULO(tmp2, xx, m);
7165 }
7166 xx = MUL_MODULO(xx, xx, m);
7167 }
7168
7169#ifdef DLONG
7170 tmp = tmp2;
7171#else
7172 tmp = FIX2LONG(tmp2);
7173#endif
7174 if (nega_flg && tmp) {
7175 tmp -= mm;
7176 }
7177 return LONG2FIX(tmp);
7178}
7179
7180/*
7181 * Document-method: Integer#pow
7182 * call-seq:
7183 * integer.pow(numeric) -> numeric
7184 * integer.pow(integer, integer) -> integer
7185 *
7186 * Returns (modular) exponentiation as:
7187 *
7188 * a.pow(b) #=> same as a**b
7189 * a.pow(b, m) #=> same as (a**b) % m, but avoids huge temporary values
7190 */
7191VALUE
7192rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
7193{
7194 rb_check_arity(argc, 1, 2);
7195
7196 if (argc == 1) {
7197 return rb_int_pow(num, argv[0]);
7198 }
7199 else {
7200 VALUE const a = num;
7201 VALUE const b = argv[0];
7202 VALUE m = argv[1];
7203 int nega_flg = 0;
7204 if ( ! RB_INTEGER_TYPE_P(b)) {
7205 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless a 1st argument is integer");
7206 }
7207 if (rb_int_negative_p(b)) {
7208 rb_raise(rb_eRangeError, "Integer#pow() 1st argument cannot be negative when 2nd argument specified");
7209 }
7210 if (!RB_INTEGER_TYPE_P(m)) {
7211 rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
7212 }
7213
7214 if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
7215 /* shortcut; 0**x => 0 except for x == 0 */
7216 return INT2FIX(0);
7217 }
7218
7219 if (rb_int_negative_p(m)) {
7220 m = rb_int_uminus(m);
7221 nega_flg = 1;
7222 }
7223
7224 if (FIXNUM_P(m)) {
7225 long const half_val = (long)HALF_LONG_MSB;
7226 long const mm = FIX2LONG(m);
7227 if (!mm) rb_num_zerodiv();
7228 if (mm == 1) return INT2FIX(0);
7229 if (mm <= half_val) {
7230 return int_pow_tmp1(rb_int_modulo(a, m), b, mm, nega_flg);
7231 }
7232 else {
7233 return int_pow_tmp2(rb_int_modulo(a, m), b, mm, nega_flg);
7234 }
7235 }
7236 else {
7237 if (rb_bigzero_p(m)) rb_num_zerodiv();
7238 if (bignorm(m) == INT2FIX(1)) return INT2FIX(0);
7239 return int_pow_tmp3(rb_int_modulo(a, m), b, m, nega_flg);
7240 }
7241 }
7243}
7244
7245/*
7246 * Bignum objects hold integers outside the range of
7247 * Fixnum. Bignum objects are created
7248 * automatically when integer calculations would otherwise overflow a
7249 * Fixnum. When a calculation involving
7250 * Bignum objects returns a result that will fit in a
7251 * Fixnum, the result is automatically converted.
7252 *
7253 * For the purposes of the bitwise operations and <code>[]</code>, a
7254 * Bignum is treated as if it were an infinite-length
7255 * bitstring with 2's complement representation.
7256 *
7257 * While Fixnum values are immediate, Bignum
7258 * objects are not---assignment and parameter passing work with
7259 * references to objects, not the objects themselves.
7260 *
7261 */
7262
7263void
7264Init_Bignum(void)
7265{
7266 rb_define_method(rb_cInteger, "coerce", rb_int_coerce, 1);
7267
7268#if USE_GMP
7269 /* The version of loaded GMP. */
7270 rb_define_const(rb_cInteger, "GMP_VERSION", rb_sprintf("GMP %s", gmp_version));
7271#endif
7272
7273 power_cache_init();
7274}
#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:1422
VALUE rb_eTypeError
TypeError exception.
Definition error.c:1418
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:2824
VALUE rb_eFloatDomainError
FloatDomainError exception.
Definition numeric.c:202
void rb_warning(const char *fmt,...)
Issues a warning.
Definition error.c:497
VALUE rb_Float(VALUE val)
This is the logic behind Kernel#Float.
Definition object.c:3785
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:100
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
Definition object.c:176
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
Definition object.c:3365
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
Definition vm_eval.c:1117
#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:1783
#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:1465
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:1593
#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.