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