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