Ruby: bignum.c Source File

Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)

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