bignum.c

Go to the documentation of this file.
00001 /**********************************************************************
00002 
00003   bignum.c -
00004 
00005   $Author: nagachika $
00006   created at: Fri Jun 10 00:48:55 JST 1994
00007 
00008   Copyright (C) 1993-2007 Yukihiro Matsumoto
00009 
00010 **********************************************************************/
00011 
00012 #include "ruby/ruby.h"
00013 #include "ruby/thread.h"
00014 #include "ruby/util.h"
00015 #include "internal.h"
00016 
00017 #ifdef HAVE_STRINGS_H
00018 #include <strings.h>
00019 #endif
00020 #include <math.h>
00021 #include <float.h>
00022 #include <ctype.h>
00023 #ifdef HAVE_IEEEFP_H
00024 #include <ieeefp.h>
00025 #endif
00026 #include <assert.h>
00027 
00028 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
00029 #define USE_GMP
00030 #include <gmp.h>
00031 #endif
00032 
00033 #define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
00034 
00035 VALUE rb_cBignum;
00036 const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
00037 
00038 #ifndef SIZEOF_BDIGIT_DBL
00039 # if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
00040 #  define SIZEOF_BDIGIT_DBL SIZEOF_LONG_LONG
00041 # else
00042 #  define SIZEOF_BDIGIT_DBL SIZEOF_LONG
00043 # endif
00044 #endif
00045 
00046 STATIC_ASSERT(sizeof_bdigit_dbl, sizeof(BDIGIT_DBL) == SIZEOF_BDIGIT_DBL);
00047 STATIC_ASSERT(sizeof_bdigit_dbl_signed, sizeof(BDIGIT_DBL_SIGNED) == SIZEOF_BDIGIT_DBL);
00048 STATIC_ASSERT(sizeof_bdigit, SIZEOF_BDIGITS <= sizeof(BDIGIT));
00049 STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGITS*2 <= SIZEOF_BDIGIT_DBL);
00050 STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
00051 STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
00052 STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
00053 STATIC_ASSERT(rbignum_embed_len_max, RBIGNUM_EMBED_LEN_MAX <= (RBIGNUM_EMBED_LEN_MASK >> RBIGNUM_EMBED_LEN_SHIFT));
00054 
00055 #if SIZEOF_BDIGITS < SIZEOF_LONG
00056 STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGITS == 0);
00057 #else
00058 STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_BDIGITS % SIZEOF_LONG == 0);
00059 #endif
00060 
00061 #ifdef WORDS_BIGENDIAN
00062 #   define HOST_BIGENDIAN_P 1
00063 #else
00064 #   define HOST_BIGENDIAN_P 0
00065 #endif
00066 #define ALIGNOF(type) ((int)offsetof(struct { char f1; type f2; }, f2))
00067 /* (!LSHIFTABLE(d, n) ? 0 : (n)) is same as n but suppress a warning, C4293, by Visual Studio.  */
00068 #define LSHIFTABLE(d, n) ((n) < sizeof(d) * CHAR_BIT)
00069 #define LSHIFTX(d, n) (!LSHIFTABLE(d, n) ? 0 : ((d) << (!LSHIFTABLE(d, n) ? 0 : (n))))
00070 #define CLEAR_LOWBITS(d, numbits) ((d) & LSHIFTX(~((d)*0), (numbits)))
00071 #define FILL_LOWBITS(d, numbits) ((d) | (LSHIFTX(((d)*0+1), (numbits))-1))
00072 #define POW2_P(x) (((x)&((x)-1))==0)
00073 
00074 #define BDIGITS(x) (RBIGNUM_DIGITS(x))
00075 #define BITSPERDIG (SIZEOF_BDIGITS*CHAR_BIT)
00076 #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
00077 #define BIGRAD_HALF ((BDIGIT)(BIGRAD >> 1))
00078 #define BDIGIT_MSB(d) (((d) & BIGRAD_HALF) != 0)
00079 #define BIGUP(x) LSHIFTX(((x) + (BDIGIT_DBL)0), BITSPERDIG)
00080 #define BIGDN(x) RSHIFT((x),BITSPERDIG)
00081 #define BIGLO(x) ((BDIGIT)((x) & BDIGMAX))
00082 #define BDIGMAX ((BDIGIT)(BIGRAD-1))
00083 #define BDIGIT_DBL_MAX (~(BDIGIT_DBL)0)
00084 
00085 #if SIZEOF_BDIGITS == 2
00086 #   define swap_bdigit(x) swap16(x)
00087 #elif SIZEOF_BDIGITS == 4
00088 #   define swap_bdigit(x) swap32(x)
00089 #elif SIZEOF_BDIGITS == 8
00090 #   define swap_bdigit(x) swap64(x)
00091 #endif
00092 
00093 #define BIGZEROP(x) (RBIGNUM_LEN(x) == 0 || \
00094                      (BDIGITS(x)[0] == 0 && \
00095                       (RBIGNUM_LEN(x) == 1 || bigzero_p(x))))
00096 #define BIGSIZE(x) (RBIGNUM_LEN(x) == 0 ? (size_t)0 : \
00097     BDIGITS(x)[RBIGNUM_LEN(x)-1] ? \
00098         (size_t)(RBIGNUM_LEN(x)*SIZEOF_BDIGITS - nlz(BDIGITS(x)[RBIGNUM_LEN(x)-1])/CHAR_BIT) : \
00099     rb_absint_size(x, NULL))
00100 
00101 #define BIGDIVREM_EXTRA_WORDS 1
00102 #define roomof(n, m) ((long)(((n)+(m)-1) / (m)))
00103 #define bdigit_roomof(n) roomof(n, SIZEOF_BDIGITS)
00104 #define BARY_ARGS(ary) ary, numberof(ary)
00105 
00106 #define BARY_ADD(z, x, y) bary_add(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
00107 #define BARY_SUB(z, x, y) bary_sub(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
00108 #define BARY_SHORT_MUL(z, x, y) bary_short_mul(BARY_ARGS(z), BARY_ARGS(x), BARY_ARGS(y))
00109 #define BARY_DIVMOD(q, r, x, y) bary_divmod(BARY_ARGS(q), BARY_ARGS(r), BARY_ARGS(x), BARY_ARGS(y))
00110 #define BARY_ZERO_P(x) bary_zero_p(BARY_ARGS(x))
00111 
00112 #define RBIGNUM_SET_NEGATIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 0)
00113 #define RBIGNUM_SET_POSITIVE_SIGN(b) RBIGNUM_SET_SIGN(b, 1)
00114 
00115 #define bignew(len,sign) bignew_1(rb_cBignum,(len),(sign))
00116 
00117 #define BDIGITS_ZERO(ptr, n) do { \
00118   BDIGIT *bdigitz_zero_ptr = (ptr); \
00119   size_t bdigitz_zero_n = (n); \
00120   while (bdigitz_zero_n) { \
00121     *bdigitz_zero_ptr++ = 0; \
00122     bdigitz_zero_n--; \
00123   } \
00124 } while (0)
00125 
00126 #define BARY_TRUNC(ds, n) do { \
00127         while (0 < (n) && (ds)[(n)-1] == 0) \
00128             (n)--; \
00129     } while (0)
00130 
00131 #define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))
00132 #define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))
00133 
00134 #define GMP_MUL_DIGITS 20
00135 #define KARATSUBA_MUL_DIGITS 70
00136 #define TOOM3_MUL_DIGITS 150
00137 
00138 #define GMP_DIV_DIGITS 20
00139 #define GMP_BIG2STR_DIGITS 20
00140 #define GMP_STR2BIG_DIGITS 20
00141 
00142 typedef 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);
00143 
00144 static mulfunc_t bary_mul_toom3_start;
00145 static mulfunc_t bary_mul_karatsuba_start;
00146 static BDIGIT bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y);
00147 static void bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn);
00148 
00149 static VALUE bigmul0(VALUE x, VALUE y);
00150 static void bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn);
00151 static VALUE bignew_1(VALUE klass, long len, int sign);
00152 static inline VALUE bigtrunc(VALUE x);
00153 
00154 static VALUE bigsq(VALUE x);
00155 static void bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp);
00156 static inline VALUE power_cache_get_power(int base, int power_level, size_t *numdigits_ret);
00157 
00158 #if SIZEOF_BDIGITS <= SIZEOF_INT
00159 static int nlz(BDIGIT x) { return nlz_int((unsigned int)x) - (SIZEOF_INT-SIZEOF_BDIGITS) * CHAR_BIT; }
00160 #elif SIZEOF_BDIGITS <= SIZEOF_LONG
00161 static int nlz(BDIGIT x) { return nlz_long((unsigned long)x) - (SIZEOF_LONG-SIZEOF_BDIGITS) * CHAR_BIT; }
00162 #elif SIZEOF_BDIGITS <= SIZEOF_LONG_LONG
00163 static int nlz(BDIGIT x) { return nlz_long_long((unsigned LONG_LONG)x) - (SIZEOF_LONG_LONG-SIZEOF_BDIGITS) * CHAR_BIT; }
00164 #elif SIZEOF_BDIGITS <= SIZEOF_INT128_T
00165 static int nlz(BDIGIT x) { return nlz_int128((uint128_t)x) - (SIZEOF_INT128_T-SIZEOF_BDIGITS) * CHAR_BIT; }
00166 #endif
00167 
00168 #define U16(a) ((uint16_t)(a))
00169 #define U32(a) ((uint32_t)(a))
00170 #ifdef HAVE_UINT64_T
00171 #define U64(a,b) (((uint64_t)(a) << 32) | (b))
00172 #endif
00173 #ifdef HAVE_UINT128_T
00174 #define U128(a,b,c,d) (((uint128_t)U64(a,b) << 64) | U64(c,d))
00175 #endif
00176 
00177 /* The following scirpt, maxpow.rb, generates the tables follows.
00178 
00179 def big(n, bits)
00180   ns = []
00181   ((bits+31)/32).times {
00182     ns << sprintf("0x%08x", n & 0xffff_ffff)
00183     n >>= 32
00184   }
00185   "U#{bits}(" + ns.reverse.join(",") + ")"
00186 end
00187 def values(ary, width, indent)
00188   lines = [""]
00189   ary.each {|e|
00190     lines << "" if !ary.last.empty? && width < (lines.last + e + ", ").length
00191     lines.last << e + ", "
00192   }
00193   lines.map {|line| " " * indent + line.chomp(" ") + "\n" }.join
00194 end
00195 [16,32,64,128].each {|bits|
00196   max = 2**bits-1
00197   exps = []
00198   nums = []
00199   2.upto(36) {|base|
00200     exp = 0
00201     n = 1
00202     while n * base <= max
00203       exp += 1
00204       n *= base
00205     end
00206     exps << exp.to_s
00207     nums << big(n, bits)
00208   }
00209   puts "#ifdef HAVE_UINT#{bits}_T"
00210   puts "static const int maxpow#{bits}_exp[35] = {"
00211   print values(exps, 70, 4)
00212   puts "};"
00213   puts "static const uint#{bits}_t maxpow#{bits}_num[35] = {"
00214   print values(nums, 70, 4)
00215   puts "};"
00216   puts "#endif"
00217 }
00218 
00219  */
00220 
00221 #if SIZEOF_BDIGIT_DBL == 2
00222 static const int maxpow16_exp[35] = {
00223     15, 10, 7, 6, 6, 5, 5, 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3,
00224     3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
00225 };
00226 static const uint16_t maxpow16_num[35] = {
00227     U16(0x00008000), U16(0x0000e6a9), U16(0x00004000), U16(0x00003d09),
00228     U16(0x0000b640), U16(0x000041a7), U16(0x00008000), U16(0x0000e6a9),
00229     U16(0x00002710), U16(0x00003931), U16(0x00005100), U16(0x00006f91),
00230     U16(0x00009610), U16(0x0000c5c1), U16(0x00001000), U16(0x00001331),
00231     U16(0x000016c8), U16(0x00001acb), U16(0x00001f40), U16(0x0000242d),
00232     U16(0x00002998), U16(0x00002f87), U16(0x00003600), U16(0x00003d09),
00233     U16(0x000044a8), U16(0x00004ce3), U16(0x000055c0), U16(0x00005f45),
00234     U16(0x00006978), U16(0x0000745f), U16(0x00008000), U16(0x00008c61),
00235     U16(0x00009988), U16(0x0000a77b), U16(0x0000b640),
00236 };
00237 #elif SIZEOF_BDIGIT_DBL == 4
00238 static const int maxpow32_exp[35] = {
00239     31, 20, 15, 13, 12, 11, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
00240     7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
00241 };
00242 static const uint32_t maxpow32_num[35] = {
00243     U32(0x80000000), U32(0xcfd41b91), U32(0x40000000), U32(0x48c27395),
00244     U32(0x81bf1000), U32(0x75db9c97), U32(0x40000000), U32(0xcfd41b91),
00245     U32(0x3b9aca00), U32(0x8c8b6d2b), U32(0x19a10000), U32(0x309f1021),
00246     U32(0x57f6c100), U32(0x98c29b81), U32(0x10000000), U32(0x18754571),
00247     U32(0x247dbc80), U32(0x3547667b), U32(0x4c4b4000), U32(0x6b5a6e1d),
00248     U32(0x94ace180), U32(0xcaf18367), U32(0x0b640000), U32(0x0e8d4a51),
00249     U32(0x1269ae40), U32(0x17179149), U32(0x1cb91000), U32(0x23744899),
00250     U32(0x2b73a840), U32(0x34e63b41), U32(0x40000000), U32(0x4cfa3cc1),
00251     U32(0x5c13d840), U32(0x6d91b519), U32(0x81bf1000),
00252 };
00253 #elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
00254 static const int maxpow64_exp[35] = {
00255     63, 40, 31, 27, 24, 22, 21, 20, 19, 18, 17, 17, 16, 16, 15, 15, 15,
00256     15, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12,
00257     12,
00258 };
00259 static const uint64_t maxpow64_num[35] = {
00260     U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
00261     U64(0x40000000,0x00000000), U64(0x6765c793,0xfa10079d),
00262     U64(0x41c21cb8,0xe1000000), U64(0x36427987,0x50226111),
00263     U64(0x80000000,0x00000000), U64(0xa8b8b452,0x291fe821),
00264     U64(0x8ac72304,0x89e80000), U64(0x4d28cb56,0xc33fa539),
00265     U64(0x1eca170c,0x00000000), U64(0x780c7372,0x621bd74d),
00266     U64(0x1e39a505,0x7d810000), U64(0x5b27ac99,0x3df97701),
00267     U64(0x10000000,0x00000000), U64(0x27b95e99,0x7e21d9f1),
00268     U64(0x5da0e1e5,0x3c5c8000), U64(0xd2ae3299,0xc1c4aedb),
00269     U64(0x16bcc41e,0x90000000), U64(0x2d04b7fd,0xd9c0ef49),
00270     U64(0x5658597b,0xcaa24000), U64(0xa0e20737,0x37609371),
00271     U64(0x0c29e980,0x00000000), U64(0x14adf4b7,0x320334b9),
00272     U64(0x226ed364,0x78bfa000), U64(0x383d9170,0xb85ff80b),
00273     U64(0x5a3c23e3,0x9c000000), U64(0x8e651373,0x88122bcd),
00274     U64(0xdd41bb36,0xd259e000), U64(0x0aee5720,0xee830681),
00275     U64(0x10000000,0x00000000), U64(0x172588ad,0x4f5f0981),
00276     U64(0x211e44f7,0xd02c1000), U64(0x2ee56725,0xf06e5c71),
00277     U64(0x41c21cb8,0xe1000000),
00278 };
00279 #elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
00280 static const int maxpow128_exp[35] = {
00281     127, 80, 63, 55, 49, 45, 42, 40, 38, 37, 35, 34, 33, 32, 31, 31, 30,
00282     30, 29, 29, 28, 28, 27, 27, 27, 26, 26, 26, 26, 25, 25, 25, 25, 24,
00283     24,
00284 };
00285 static const uint128_t maxpow128_num[35] = {
00286     U128(0x80000000,0x00000000,0x00000000,0x00000000),
00287     U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
00288     U128(0x40000000,0x00000000,0x00000000,0x00000000),
00289     U128(0xd0cf4b50,0xcfe20765,0xfff4b4e3,0xf741cf6d),
00290     U128(0x6558e2a0,0x921fe069,0x42860000,0x00000000),
00291     U128(0x5080c7b7,0xd0e31ba7,0x5911a67d,0xdd3d35e7),
00292     U128(0x40000000,0x00000000,0x00000000,0x00000000),
00293     U128(0x6f32f1ef,0x8b18a2bc,0x3cea5978,0x9c79d441),
00294     U128(0x4b3b4ca8,0x5a86c47a,0x098a2240,0x00000000),
00295     U128(0xffd1390a,0x0adc2fb8,0xdabbb817,0x4d95c99b),
00296     U128(0x2c6fdb36,0x4c25e6c0,0x00000000,0x00000000),
00297     U128(0x384bacd6,0x42c343b4,0xe90c4272,0x13506d29),
00298     U128(0x31f5db32,0xa34aced6,0x0bf13a0e,0x00000000),
00299     U128(0x20753ada,0xfd1e839f,0x53686d01,0x3143ee01),
00300     U128(0x10000000,0x00000000,0x00000000,0x00000000),
00301     U128(0x68ca11d6,0xb4f6d1d1,0xfaa82667,0x8073c2f1),
00302     U128(0x223e493b,0xb3bb69ff,0xa4b87d6c,0x40000000),
00303     U128(0xad62418d,0x14ea8247,0x01c4b488,0x6cc66f59),
00304     U128(0x2863c1f5,0xcdae42f9,0x54000000,0x00000000),
00305     U128(0xa63fd833,0xb9386b07,0x36039e82,0xbe651b25),
00306     U128(0x1d1f7a9c,0xd087a14d,0x28cdf3d5,0x10000000),
00307     U128(0x651b5095,0xc2ea8fc1,0xb30e2c57,0x77aaf7e1),
00308     U128(0x0ddef20e,0xff760000,0x00000000,0x00000000),
00309     U128(0x29c30f10,0x29939b14,0x6664242d,0x97d9f649),
00310     U128(0x786a435a,0xe9558b0e,0x6aaf6d63,0xa8000000),
00311     U128(0x0c5afe6f,0xf302bcbf,0x94fd9829,0xd87f5079),
00312     U128(0x1fce575c,0xe1692706,0x07100000,0x00000000),
00313     U128(0x4f34497c,0x8597e144,0x36e91802,0x00528229),
00314     U128(0xbf3a8e1d,0x41ef2170,0x7802130d,0x84000000),
00315     U128(0x0e7819e1,0x7f1eb0fb,0x6ee4fb89,0x01d9531f),
00316     U128(0x20000000,0x00000000,0x00000000,0x00000000),
00317     U128(0x4510460d,0xd9e879c0,0x14a82375,0x2f22b321),
00318     U128(0x91abce3c,0x4b4117ad,0xe76d35db,0x22000000),
00319     U128(0x08973ea3,0x55d75bc2,0x2e42c391,0x727d69e1),
00320     U128(0x10e425c5,0x6daffabc,0x35c10000,0x00000000),
00321 };
00322 #endif
00323 
00324 static BDIGIT_DBL
00325 maxpow_in_bdigit_dbl(int base, int *exp_ret)
00326 {
00327     BDIGIT_DBL maxpow;
00328     int exponent;
00329 
00330     assert(2 <= base && base <= 36);
00331 
00332     {
00333 #if SIZEOF_BDIGIT_DBL == 2
00334         maxpow = maxpow16_num[base-2];
00335         exponent = maxpow16_exp[base-2];
00336 #elif SIZEOF_BDIGIT_DBL == 4
00337         maxpow = maxpow32_num[base-2];
00338         exponent = maxpow32_exp[base-2];
00339 #elif SIZEOF_BDIGIT_DBL == 8 && defined HAVE_UINT64_T
00340         maxpow = maxpow64_num[base-2];
00341         exponent = maxpow64_exp[base-2];
00342 #elif SIZEOF_BDIGIT_DBL == 16 && defined HAVE_UINT128_T
00343         maxpow = maxpow128_num[base-2];
00344         exponent = maxpow128_exp[base-2];
00345 #else
00346         maxpow = base;
00347         exponent = 1;
00348         while (maxpow <= BDIGIT_DBL_MAX / base) {
00349             maxpow *= base;
00350             exponent++;
00351         }
00352 #endif
00353     }
00354 
00355     *exp_ret = exponent;
00356     return maxpow;
00357 }
00358 
00359 static inline BDIGIT_DBL
00360 bary2bdigitdbl(const BDIGIT *ds, size_t n)
00361 {
00362     assert(n <= 2);
00363 
00364     if (n == 2)
00365         return ds[0] | BIGUP(ds[1]);
00366     if (n == 1)
00367         return ds[0];
00368     return 0;
00369 }
00370 
00371 static inline void
00372 bdigitdbl2bary(BDIGIT *ds, size_t n, BDIGIT_DBL num)
00373 {
00374     assert(n == 2);
00375 
00376     ds[0] = BIGLO(num);
00377     ds[1] = (BDIGIT)BIGDN(num);
00378 }
00379 
00380 static int
00381 bary_cmp(const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
00382 {
00383     BARY_TRUNC(xds, xn);
00384     BARY_TRUNC(yds, yn);
00385 
00386     if (xn < yn)
00387         return -1;
00388     if (xn > yn)
00389         return 1;
00390 
00391     while (xn-- && xds[xn] == yds[xn])
00392         ;
00393     if (xn == (size_t)-1)
00394         return 0;
00395     return xds[xn] < yds[xn] ? -1 : 1;
00396 }
00397 
00398 static BDIGIT
00399 bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift)
00400 {
00401     size_t i;
00402     BDIGIT_DBL num = 0;
00403     assert(0 <= shift && shift < BITSPERDIG);
00404 
00405     for (i=0; i<n; i++) {
00406         num = num | (BDIGIT_DBL)*xds++ << shift;
00407         *zds++ = BIGLO(num);
00408         num = BIGDN(num);
00409     }
00410     return BIGLO(num);
00411 }
00412 
00413 static void
00414 bary_small_rshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift, BDIGIT higher_bdigit)
00415 {
00416     BDIGIT_DBL num = 0;
00417     BDIGIT x;
00418 
00419     assert(0 <= shift && shift < BITSPERDIG);
00420 
00421     num = BIGUP(higher_bdigit);
00422     while (n--) {
00423         num = (num | xds[n]) >> shift;
00424         x = xds[n];
00425         zds[n] = BIGLO(num);
00426         num = BIGUP(x);
00427     }
00428 }
00429 
00430 static int
00431 bary_zero_p(BDIGIT *xds, size_t xn)
00432 {
00433     if (xn == 0)
00434         return 1;
00435     do {
00436         if (xds[--xn]) return 0;
00437     } while (xn);
00438     return 1;
00439 }
00440 
00441 static void
00442 bary_neg(BDIGIT *ds, size_t n)
00443 {
00444     while (n--)
00445         ds[n] = BIGLO(~ds[n]);
00446 }
00447 
00448 static int
00449 bary_2comp(BDIGIT *ds, size_t n)
00450 {
00451     size_t i;
00452     i = 0;
00453     for (i = 0; i < n; i++) {
00454         if (ds[i] != 0) {
00455             goto non_zero;
00456         }
00457     }
00458     return 1;
00459 
00460   non_zero:
00461     ds[i] = BIGLO(~ds[i] + 1);
00462     i++;
00463     for (; i < n; i++) {
00464         ds[i] = BIGLO(~ds[i]);
00465     }
00466     return 0;
00467 }
00468 
00469 static void
00470 bary_swap(BDIGIT *ds, size_t num_bdigits)
00471 {
00472     BDIGIT *p1 = ds;
00473     BDIGIT *p2 = ds + num_bdigits - 1;
00474     for (; p1 < p2; p1++, p2--) {
00475         BDIGIT tmp = *p1;
00476         *p1 = *p2;
00477         *p2 = tmp;
00478     }
00479 }
00480 
00481 #define INTEGER_PACK_WORDORDER_MASK \
00482     (INTEGER_PACK_MSWORD_FIRST | \
00483      INTEGER_PACK_LSWORD_FIRST)
00484 #define INTEGER_PACK_BYTEORDER_MASK \
00485     (INTEGER_PACK_MSBYTE_FIRST | \
00486      INTEGER_PACK_LSBYTE_FIRST | \
00487      INTEGER_PACK_NATIVE_BYTE_ORDER)
00488 
00489 static void
00490 validate_integer_pack_format(size_t numwords, size_t wordsize, size_t nails, int flags, int supported_flags)
00491 {
00492     int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
00493     int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
00494 
00495     if (flags & ~supported_flags) {
00496         rb_raise(rb_eArgError, "unsupported flags specified");
00497     }
00498     if (wordorder_bits == 0) {
00499         if (1 < numwords)
00500             rb_raise(rb_eArgError, "word order not specified");
00501     }
00502     else if (wordorder_bits != INTEGER_PACK_MSWORD_FIRST &&
00503         wordorder_bits != INTEGER_PACK_LSWORD_FIRST)
00504         rb_raise(rb_eArgError, "unexpected word order");
00505     if (byteorder_bits == 0) {
00506         rb_raise(rb_eArgError, "byte order not specified");
00507     }
00508     else if (byteorder_bits != INTEGER_PACK_MSBYTE_FIRST &&
00509         byteorder_bits != INTEGER_PACK_LSBYTE_FIRST &&
00510         byteorder_bits != INTEGER_PACK_NATIVE_BYTE_ORDER)
00511         rb_raise(rb_eArgError, "unexpected byte order");
00512     if (wordsize == 0)
00513         rb_raise(rb_eArgError, "invalid wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
00514     if (SSIZE_MAX < wordsize)
00515         rb_raise(rb_eArgError, "too big wordsize: %"PRI_SIZE_PREFIX"u", wordsize);
00516     if (wordsize <= nails / CHAR_BIT)
00517         rb_raise(rb_eArgError, "too big nails: %"PRI_SIZE_PREFIX"u", nails);
00518     if (SIZE_MAX / wordsize < numwords)
00519         rb_raise(rb_eArgError, "too big numwords * wordsize: %"PRI_SIZE_PREFIX"u * %"PRI_SIZE_PREFIX"u", numwords, wordsize);
00520 }
00521 
00522 static void
00523 integer_pack_loop_setup(
00524     size_t numwords, size_t wordsize, size_t nails, int flags,
00525     size_t *word_num_fullbytes_ret,
00526     int *word_num_partialbits_ret,
00527     size_t *word_start_ret,
00528     ssize_t *word_step_ret,
00529     size_t *word_last_ret,
00530     size_t *byte_start_ret,
00531     int *byte_step_ret)
00532 {
00533     int wordorder_bits = flags & INTEGER_PACK_WORDORDER_MASK;
00534     int byteorder_bits = flags & INTEGER_PACK_BYTEORDER_MASK;
00535     size_t word_num_fullbytes;
00536     int word_num_partialbits;
00537     size_t word_start;
00538     ssize_t word_step;
00539     size_t word_last;
00540     size_t byte_start;
00541     int byte_step;
00542 
00543     word_num_partialbits = CHAR_BIT - (int)(nails % CHAR_BIT);
00544     if (word_num_partialbits == CHAR_BIT)
00545         word_num_partialbits = 0;
00546     word_num_fullbytes = wordsize - (nails / CHAR_BIT);
00547     if (word_num_partialbits != 0) {
00548         word_num_fullbytes--;
00549     }
00550 
00551     if (wordorder_bits == INTEGER_PACK_MSWORD_FIRST) {
00552         word_start = wordsize*(numwords-1);
00553         word_step = -(ssize_t)wordsize;
00554         word_last = 0;
00555     }
00556     else {
00557         word_start = 0;
00558         word_step = wordsize;
00559         word_last = wordsize*(numwords-1);
00560     }
00561 
00562     if (byteorder_bits == INTEGER_PACK_NATIVE_BYTE_ORDER) {
00563 #ifdef WORDS_BIGENDIAN
00564         byteorder_bits = INTEGER_PACK_MSBYTE_FIRST;
00565 #else
00566         byteorder_bits = INTEGER_PACK_LSBYTE_FIRST;
00567 #endif
00568     }
00569     if (byteorder_bits == INTEGER_PACK_MSBYTE_FIRST) {
00570         byte_start = wordsize-1;
00571         byte_step = -1;
00572     }
00573     else {
00574         byte_start = 0;
00575         byte_step = 1;
00576     }
00577 
00578     *word_num_partialbits_ret = word_num_partialbits;
00579     *word_num_fullbytes_ret = word_num_fullbytes;
00580     *word_start_ret = word_start;
00581     *word_step_ret = word_step;
00582     *word_last_ret = word_last;
00583     *byte_start_ret = byte_start;
00584     *byte_step_ret = byte_step;
00585 }
00586 
00587 static inline void
00588 integer_pack_fill_dd(BDIGIT **dpp, BDIGIT **dep, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
00589 {
00590     if (*dpp < *dep && BITSPERDIG <= (int)sizeof(*ddp) * CHAR_BIT - *numbits_in_dd_p) {
00591         *ddp |= (BDIGIT_DBL)(*(*dpp)++) << *numbits_in_dd_p;
00592         *numbits_in_dd_p += BITSPERDIG;
00593     }
00594     else if (*dpp == *dep) {
00595         /* higher bits are infinity zeros */
00596         *numbits_in_dd_p = (int)sizeof(*ddp) * CHAR_BIT;
00597     }
00598 }
00599 
00600 static inline BDIGIT_DBL
00601 integer_pack_take_lowbits(int n, BDIGIT_DBL *ddp, int *numbits_in_dd_p)
00602 {
00603     BDIGIT_DBL ret;
00604     ret = (*ddp) & (((BDIGIT_DBL)1 << n) - 1);
00605     *ddp >>= n;
00606     *numbits_in_dd_p -= n;
00607     return ret;
00608 }
00609 
00610 #if !defined(WORDS_BIGENDIAN)
00611 static int
00612 bytes_2comp(unsigned char *buf, size_t len)
00613 {
00614     size_t i;
00615     for (i = 0; i < len; i++)
00616         buf[i] = ~buf[i];
00617     for (i = 0; i < len; i++) {
00618         buf[i]++;
00619         if (buf[i] != 0)
00620             return 0;
00621     }
00622     return 1;
00623 }
00624 #endif
00625 
00626 static int
00627 bary_pack(int sign, BDIGIT *ds, size_t num_bdigits, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
00628 {
00629     BDIGIT *dp, *de;
00630     unsigned char *buf, *bufend;
00631 
00632     dp = ds;
00633     de = ds + num_bdigits;
00634 
00635     validate_integer_pack_format(numwords, wordsize, nails, flags,
00636             INTEGER_PACK_MSWORD_FIRST|
00637             INTEGER_PACK_LSWORD_FIRST|
00638             INTEGER_PACK_MSBYTE_FIRST|
00639             INTEGER_PACK_LSBYTE_FIRST|
00640             INTEGER_PACK_NATIVE_BYTE_ORDER|
00641             INTEGER_PACK_2COMP|
00642             INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
00643 
00644     while (dp < de && de[-1] == 0)
00645         de--;
00646     if (dp == de) {
00647         sign = 0;
00648     }
00649 
00650     if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) {
00651         if (sign == 0) {
00652             MEMZERO(words, unsigned char, numwords * wordsize);
00653             return 0;
00654         }
00655         if (nails == 0 && numwords == 1) {
00656             int need_swap = wordsize != 1 &&
00657                 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER &&
00658                 ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P);
00659             if (0 < sign || !(flags & INTEGER_PACK_2COMP)) {
00660                 BDIGIT d;
00661                 if (wordsize == 1) {
00662                     *((unsigned char *)words) = (unsigned char)(d = dp[0]);
00663                     return ((1 < de - dp || CLEAR_LOWBITS(d, 8) != 0) ? 2 : 1) * sign;
00664                 }
00665 #if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS
00666                 if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) {
00667                     uint16_t u = (uint16_t)(d = dp[0]);
00668                     if (need_swap) u = swap16(u);
00669                     *((uint16_t *)words) = u;
00670                     return ((1 < de - dp || CLEAR_LOWBITS(d, 16) != 0) ? 2 : 1) * sign;
00671                 }
00672 #endif
00673 #if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS
00674                 if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) {
00675                     uint32_t u = (uint32_t)(d = dp[0]);
00676                     if (need_swap) u = swap32(u);
00677                     *((uint32_t *)words) = u;
00678                     return ((1 < de - dp || CLEAR_LOWBITS(d, 32) != 0) ? 2 : 1) * sign;
00679                 }
00680 #endif
00681 #if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS
00682                 if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) {
00683                     uint64_t u = (uint64_t)(d = dp[0]);
00684                     if (need_swap) u = swap64(u);
00685                     *((uint64_t *)words) = u;
00686                     return ((1 < de - dp || CLEAR_LOWBITS(d, 64) != 0) ? 2 : 1) * sign;
00687                 }
00688 #endif
00689             }
00690             else { /* sign < 0 && (flags & INTEGER_PACK_2COMP) */
00691                 BDIGIT_DBL_SIGNED d;
00692                 if (wordsize == 1) {
00693                     *((unsigned char *)words) = (unsigned char)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
00694                     return (1 < de - dp || FILL_LOWBITS(d, 8) != -1) ? -2 : -1;
00695                 }
00696 #if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS
00697                 if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) {
00698                     uint16_t u = (uint16_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
00699                     if (need_swap) u = swap16(u);
00700                     *((uint16_t *)words) = u;
00701                     return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
00702                         (1 < de - dp || FILL_LOWBITS(d, 16) != -1) ? -2 : -1;
00703                 }
00704 #endif
00705 #if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS
00706                 if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) {
00707                     uint32_t u = (uint32_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
00708                     if (need_swap) u = swap32(u);
00709                     *((uint32_t *)words) = u;
00710                     return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
00711                         (1 < de - dp || FILL_LOWBITS(d, 32) != -1) ? -2 : -1;
00712                 }
00713 #endif
00714 #if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS
00715                 if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) {
00716                     uint64_t u = (uint64_t)(d = -(BDIGIT_DBL_SIGNED)dp[0]);
00717                     if (need_swap) u = swap64(u);
00718                     *((uint64_t *)words) = u;
00719                     return (wordsize == SIZEOF_BDIGITS && de - dp == 2 && dp[1] == 1 && dp[0] == 0) ? -1 :
00720                         (1 < de - dp || FILL_LOWBITS(d, 64) != -1) ? -2 : -1;
00721                 }
00722 #endif
00723             }
00724         }
00725 #if !defined(WORDS_BIGENDIAN)
00726         if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
00727             (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST &&
00728             (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) {
00729             size_t src_size = (de - dp) * SIZEOF_BDIGITS;
00730             size_t dst_size = numwords * wordsize;
00731             int overflow = 0;
00732             while (0 < src_size && ((unsigned char *)ds)[src_size-1] == 0)
00733                 src_size--;
00734             if (src_size <= dst_size) {
00735                 MEMCPY(words, dp, char, src_size);
00736                 MEMZERO((char*)words + src_size, char, dst_size - src_size);
00737             }
00738             else {
00739                 MEMCPY(words, dp, char, dst_size);
00740                 overflow = 1;
00741             }
00742             if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
00743                 int zero_p = bytes_2comp(words, dst_size);
00744                 if (zero_p && overflow) {
00745                     unsigned char *p = (unsigned char *)dp;
00746                     if (dst_size == src_size-1 &&
00747                         p[dst_size] == 1) {
00748                         overflow = 0;
00749                     }
00750                 }
00751             }
00752             if (overflow)
00753                 sign *= 2;
00754             return sign;
00755         }
00756 #endif
00757         if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
00758             wordsize % SIZEOF_BDIGITS == 0 && (uintptr_t)words % ALIGNOF(BDIGIT) == 0) {
00759             size_t bdigits_per_word = wordsize / SIZEOF_BDIGITS;
00760             size_t src_num_bdigits = de - dp;
00761             size_t dst_num_bdigits = numwords * bdigits_per_word;
00762             int overflow = 0;
00763             int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
00764             int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
00765                 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
00766             if (src_num_bdigits <= dst_num_bdigits) {
00767                 MEMCPY(words, dp, BDIGIT, src_num_bdigits);
00768                 BDIGITS_ZERO((BDIGIT*)words + src_num_bdigits, dst_num_bdigits - src_num_bdigits);
00769             }
00770             else {
00771                 MEMCPY(words, dp, BDIGIT, dst_num_bdigits);
00772                 overflow = 1;
00773             }
00774             if (sign < 0 && (flags & INTEGER_PACK_2COMP)) {
00775                 int zero_p = bary_2comp(words, dst_num_bdigits);
00776                 if (zero_p && overflow &&
00777                     dst_num_bdigits == src_num_bdigits-1 &&
00778                     dp[dst_num_bdigits] == 1)
00779                     overflow = 0;
00780             }
00781             if (msbytefirst_p != HOST_BIGENDIAN_P) {
00782                 size_t i;
00783                 for (i = 0; i < dst_num_bdigits; i++) {
00784                     BDIGIT d = ((BDIGIT*)words)[i];
00785                     ((BDIGIT*)words)[i] = swap_bdigit(d);
00786                 }
00787             }
00788             if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
00789                 size_t i;
00790                 BDIGIT *p = words;
00791                 for (i = 0; i < numwords; i++) {
00792                     bary_swap(p, bdigits_per_word);
00793                     p += bdigits_per_word;
00794                 }
00795             }
00796             if (mswordfirst_p) {
00797                 bary_swap(words, dst_num_bdigits);
00798             }
00799             if (overflow)
00800                 sign *= 2;
00801             return sign;
00802         }
00803     }
00804 
00805     buf = words;
00806     bufend = buf + numwords * wordsize;
00807 
00808     if (buf == bufend) {
00809         /* overflow if non-zero*/
00810         if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
00811             sign *= 2;
00812         else {
00813             if (de - dp == 1 && dp[0] == 1)
00814                 sign = -1; /* val == -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
00815             else
00816                 sign = -2; /* val < -1 == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
00817         }
00818     }
00819     else if (dp == de) {
00820         memset(buf, '\0', bufend - buf);
00821     }
00822     else if (dp < de && buf < bufend) {
00823         int word_num_partialbits;
00824         size_t word_num_fullbytes;
00825 
00826         ssize_t word_step;
00827         size_t byte_start;
00828         int byte_step;
00829 
00830         size_t word_start, word_last;
00831         unsigned char *wordp, *last_wordp;
00832         BDIGIT_DBL dd;
00833         int numbits_in_dd;
00834 
00835         integer_pack_loop_setup(numwords, wordsize, nails, flags,
00836             &word_num_fullbytes, &word_num_partialbits,
00837             &word_start, &word_step, &word_last, &byte_start, &byte_step);
00838 
00839         wordp = buf + word_start;
00840         last_wordp = buf + word_last;
00841 
00842         dd = 0;
00843         numbits_in_dd = 0;
00844 
00845 #define FILL_DD \
00846     integer_pack_fill_dd(&dp, &de, &dd, &numbits_in_dd)
00847 #define TAKE_LOWBITS(n) \
00848     integer_pack_take_lowbits(n, &dd, &numbits_in_dd)
00849 
00850         while (1) {
00851             size_t index_in_word = 0;
00852             unsigned char *bytep = wordp + byte_start;
00853             while (index_in_word < word_num_fullbytes) {
00854                 FILL_DD;
00855                 *bytep = TAKE_LOWBITS(CHAR_BIT);
00856                 bytep += byte_step;
00857                 index_in_word++;
00858             }
00859             if (word_num_partialbits) {
00860                 FILL_DD;
00861                 *bytep = TAKE_LOWBITS(word_num_partialbits);
00862                 bytep += byte_step;
00863                 index_in_word++;
00864             }
00865             while (index_in_word < wordsize) {
00866                 *bytep = 0;
00867                 bytep += byte_step;
00868                 index_in_word++;
00869             }
00870 
00871             if (wordp == last_wordp)
00872                 break;
00873 
00874             wordp += word_step;
00875         }
00876         FILL_DD;
00877         /* overflow tests */
00878         if (dp != de || 1 < dd) {
00879             /* 2**(numwords*(wordsize*CHAR_BIT-nails)+1) <= abs(val) */
00880             sign *= 2;
00881         }
00882         else if (dd == 1) {
00883             /* 2**(numwords*(wordsize*CHAR_BIT-nails)) <= abs(val) < 2**(numwords*(wordsize*CHAR_BIT-nails)+1) */
00884             if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
00885                 sign *= 2;
00886             else { /* overflow_2comp && sign == -1 */
00887                 /* test lower bits are all zero. */
00888                 dp = ds;
00889                 while (dp < de && *dp == 0)
00890                     dp++;
00891                 if (de - dp == 1 && /* only one non-zero word. */
00892                     POW2_P(*dp)) /* *dp contains only one bit set. */
00893                     sign = -1; /* val == -2**(numwords*(wordsize*CHAR_BIT-nails)) */
00894                 else
00895                     sign = -2; /* val < -2**(numwords*(wordsize*CHAR_BIT-nails)) */
00896             }
00897         }
00898     }
00899 
00900     if ((flags & INTEGER_PACK_2COMP) && (sign < 0 && numwords != 0)) {
00901         unsigned char *buf;
00902 
00903         int word_num_partialbits;
00904         size_t word_num_fullbytes;
00905 
00906         ssize_t word_step;
00907         size_t byte_start;
00908         int byte_step;
00909 
00910         size_t word_start, word_last;
00911         unsigned char *wordp, *last_wordp;
00912 
00913         unsigned int partialbits_mask;
00914         int carry;
00915 
00916         integer_pack_loop_setup(numwords, wordsize, nails, flags,
00917             &word_num_fullbytes, &word_num_partialbits,
00918             &word_start, &word_step, &word_last, &byte_start, &byte_step);
00919 
00920         partialbits_mask = (1 << word_num_partialbits) - 1;
00921 
00922         buf = words;
00923         wordp = buf + word_start;
00924         last_wordp = buf + word_last;
00925 
00926         carry = 1;
00927         while (1) {
00928             size_t index_in_word = 0;
00929             unsigned char *bytep = wordp + byte_start;
00930             while (index_in_word < word_num_fullbytes) {
00931                 carry += (unsigned char)~*bytep;
00932                 *bytep = (unsigned char)carry;
00933                 carry >>= CHAR_BIT;
00934                 bytep += byte_step;
00935                 index_in_word++;
00936             }
00937             if (word_num_partialbits) {
00938                 carry += (*bytep & partialbits_mask) ^ partialbits_mask;
00939                 *bytep = carry & partialbits_mask;
00940                 carry >>= word_num_partialbits;
00941                 bytep += byte_step;
00942                 index_in_word++;
00943             }
00944 
00945             if (wordp == last_wordp)
00946                 break;
00947 
00948             wordp += word_step;
00949         }
00950     }
00951 
00952     return sign;
00953 #undef FILL_DD
00954 #undef TAKE_LOWBITS
00955 }
00956 
00957 static size_t
00958 integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
00959 {
00960     /* nlp_bits stands for number of leading padding bits */
00961     size_t num_bits = (wordsize * CHAR_BIT - nails) * numwords;
00962     size_t num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG;
00963     *nlp_bits_ret = (int)(num_bdigits * BITSPERDIG - num_bits);
00964     return num_bdigits;
00965 }
00966 
00967 static size_t
00968 integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
00969 {
00970     /* BITSPERDIG = SIZEOF_BDIGITS * CHAR_BIT */
00971     /* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
00972     /* num_bdigits = (num_bits + BITSPERDIG - 1) / BITSPERDIG */
00973 
00974     /* num_bits = CHAR_BIT * (wordsize * numwords) - nails * numwords = CHAR_BIT * num_bytes1 - nails * numwords */
00975     size_t num_bytes1 = wordsize * numwords;
00976 
00977     /* q1 * CHAR_BIT + r1 = numwords */
00978     size_t q1 = numwords / CHAR_BIT;
00979     size_t r1 = numwords % CHAR_BIT;
00980 
00981     /* num_bits = CHAR_BIT * num_bytes1 - nails * (q1 * CHAR_BIT + r1) = CHAR_BIT * num_bytes2 - nails * r1 */
00982     size_t num_bytes2 = num_bytes1 - nails * q1;
00983 
00984     /* q2 * CHAR_BIT + r2 = nails */
00985     size_t q2 = nails / CHAR_BIT;
00986     size_t r2 = nails % CHAR_BIT;
00987 
00988     /* num_bits = CHAR_BIT * num_bytes2 - (q2 * CHAR_BIT + r2) * r1 = CHAR_BIT * num_bytes3 - r1 * r2 */
00989     size_t num_bytes3 = num_bytes2 - q2 * r1;
00990 
00991     /* q3 * BITSPERDIG + r3 = num_bytes3 */
00992     size_t q3 = num_bytes3 / BITSPERDIG;
00993     size_t r3 = num_bytes3 % BITSPERDIG;
00994 
00995     /* num_bits = CHAR_BIT * (q3 * BITSPERDIG + r3) - r1 * r2 = BITSPERDIG * num_digits1 + CHAR_BIT * r3 - r1 * r2 */
00996     size_t num_digits1 = CHAR_BIT * q3;
00997 
00998     /*
00999      * if CHAR_BIT * r3 >= r1 * r2
01000      *   CHAR_BIT * r3 - r1 * r2 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2))
01001      *   q4 * BITSPERDIG + r4 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2)
01002      *   num_bits = BITSPERDIG * num_digits1 + CHAR_BIT * BITSPERDIG - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
01003      * else
01004      *   q4 * BITSPERDIG + r4 = -(CHAR_BIT * r3 - r1 * r2)
01005      *   num_bits = BITSPERDIG * num_digits1 - (q4 * BITSPERDIG + r4) = BITSPERDIG * num_digits2 - r4
01006      * end
01007      */
01008 
01009     if (CHAR_BIT * r3 >= r1 * r2) {
01010         size_t tmp1 = CHAR_BIT * BITSPERDIG - (CHAR_BIT * r3 - r1 * r2);
01011         size_t q4 = tmp1 / BITSPERDIG;
01012         int r4 = (int)(tmp1 % BITSPERDIG);
01013         size_t num_digits2 = num_digits1 + CHAR_BIT - q4;
01014         *nlp_bits_ret = r4;
01015         return num_digits2;
01016     }
01017     else {
01018         size_t tmp1 = r1 * r2 - CHAR_BIT * r3;
01019         size_t q4 = tmp1 / BITSPERDIG;
01020         int r4 = (int)(tmp1 % BITSPERDIG);
01021         size_t num_digits2 = num_digits1 - q4;
01022         *nlp_bits_ret = r4;
01023         return num_digits2;
01024     }
01025 }
01026 
01027 static size_t
01028 integer_unpack_num_bdigits(size_t numwords, size_t wordsize, size_t nails, int *nlp_bits_ret)
01029 {
01030     size_t num_bdigits;
01031 
01032     if (numwords <= (SIZE_MAX - (BITSPERDIG-1)) / CHAR_BIT / wordsize) {
01033         num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails, nlp_bits_ret);
01034 #ifdef DEBUG_INTEGER_PACK
01035         {
01036             int nlp_bits1;
01037             size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, &nlp_bits1);
01038             assert(num_bdigits == num_bdigits1);
01039             assert(*nlp_bits_ret == nlp_bits1);
01040         }
01041 #endif
01042     }
01043     else {
01044         num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails, nlp_bits_ret);
01045     }
01046     return num_bdigits;
01047 }
01048 
01049 static inline void
01050 integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
01051 {
01052     (*ddp) |= ((BDIGIT_DBL)data) << (*numbits_in_dd_p);
01053     *numbits_in_dd_p += numbits;
01054     while (BITSPERDIG <= *numbits_in_dd_p) {
01055         *(*dpp)++ = BIGLO(*ddp);
01056         *ddp = BIGDN(*ddp);
01057         *numbits_in_dd_p -= BITSPERDIG;
01058     }
01059 }
01060 
01061 static int
01062 integer_unpack_single_bdigit(BDIGIT u, size_t size, int flags, BDIGIT *dp)
01063 {
01064     int sign;
01065     if (flags & INTEGER_PACK_2COMP) {
01066         sign = (flags & INTEGER_PACK_NEGATIVE) ?
01067             ((size == SIZEOF_BDIGITS && u == 0) ? -2 : -1) :
01068             ((u >> (size * CHAR_BIT - 1)) ? -1 : 1);
01069         if (sign < 0) {
01070             u |= LSHIFTX(BDIGMAX, size * CHAR_BIT);
01071             u = BIGLO(1 + ~u);
01072         }
01073     }
01074     else
01075         sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
01076     *dp = u;
01077     return sign;
01078 }
01079 
01080 static int
01081 bary_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)
01082 {
01083     int sign;
01084     const unsigned char *buf = words;
01085     BDIGIT *dp;
01086     BDIGIT *de;
01087 
01088     dp = bdigits;
01089     de = dp + num_bdigits;
01090 
01091     if (!(flags & INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION)) {
01092         if (nails == 0 && numwords == 1) {
01093             int need_swap = wordsize != 1 &&
01094                 (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_NATIVE_BYTE_ORDER &&
01095                 ((flags & INTEGER_PACK_MSBYTE_FIRST) ? !HOST_BIGENDIAN_P : HOST_BIGENDIAN_P);
01096             if (wordsize == 1) {
01097                 return integer_unpack_single_bdigit(*(uint8_t *)buf, sizeof(uint8_t), flags, dp);
01098             }
01099 #if defined(HAVE_UINT16_T) && 2 <= SIZEOF_BDIGITS
01100             if (wordsize == 2 && (uintptr_t)words % ALIGNOF(uint16_t) == 0) {
01101                 uint16_t u = *(uint16_t *)buf;
01102                 return integer_unpack_single_bdigit(need_swap ? swap16(u) : u, sizeof(uint16_t), flags, dp);
01103             }
01104 #endif
01105 #if defined(HAVE_UINT32_T) && 4 <= SIZEOF_BDIGITS
01106             if (wordsize == 4 && (uintptr_t)words % ALIGNOF(uint32_t) == 0) {
01107                 uint32_t u = *(uint32_t *)buf;
01108                 return integer_unpack_single_bdigit(need_swap ? swap32(u) : u, sizeof(uint32_t), flags, dp);
01109             }
01110 #endif
01111 #if defined(HAVE_UINT64_T) && 8 <= SIZEOF_BDIGITS
01112             if (wordsize == 8 && (uintptr_t)words % ALIGNOF(uint64_t) == 0) {
01113                 uint64_t u = *(uint64_t *)buf;
01114                 return integer_unpack_single_bdigit(need_swap ? swap64(u) : u, sizeof(uint64_t), flags, dp);
01115             }
01116 #endif
01117         }
01118 #if !defined(WORDS_BIGENDIAN)
01119         if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
01120             (flags & INTEGER_PACK_WORDORDER_MASK) == INTEGER_PACK_LSWORD_FIRST &&
01121             (flags & INTEGER_PACK_BYTEORDER_MASK) != INTEGER_PACK_MSBYTE_FIRST) {
01122             size_t src_size = numwords * wordsize;
01123             size_t dst_size = num_bdigits * SIZEOF_BDIGITS;
01124             MEMCPY(dp, words, char, src_size);
01125             if (flags & INTEGER_PACK_2COMP) {
01126                 if (flags & INTEGER_PACK_NEGATIVE) {
01127                     int zero_p;
01128                     memset((char*)dp + src_size, 0xff, dst_size - src_size);
01129                     zero_p = bary_2comp(dp, num_bdigits);
01130                     sign = zero_p ? -2 : -1;
01131                 }
01132                 else if (buf[src_size-1] >> (CHAR_BIT-1)) {
01133                     memset((char*)dp + src_size, 0xff, dst_size - src_size);
01134                     bary_2comp(dp, num_bdigits);
01135                     sign = -1;
01136                 }
01137                 else {
01138                     MEMZERO((char*)dp + src_size, char, dst_size - src_size);
01139                     sign = 1;
01140                 }
01141             }
01142             else {
01143                 MEMZERO((char*)dp + src_size, char, dst_size - src_size);
01144                 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
01145             }
01146             return sign;
01147         }
01148 #endif
01149         if (nails == 0 && SIZEOF_BDIGITS == sizeof(BDIGIT) &&
01150             wordsize % SIZEOF_BDIGITS == 0) {
01151             size_t bdigits_per_word = wordsize / SIZEOF_BDIGITS;
01152             int mswordfirst_p = (flags & INTEGER_PACK_MSWORD_FIRST) != 0;
01153             int msbytefirst_p = (flags & INTEGER_PACK_NATIVE_BYTE_ORDER) ? HOST_BIGENDIAN_P :
01154                 (flags & INTEGER_PACK_MSBYTE_FIRST) != 0;
01155             MEMCPY(dp, words, BDIGIT, numwords*bdigits_per_word);
01156             if (mswordfirst_p) {
01157                 bary_swap(dp, num_bdigits);
01158             }
01159             if (mswordfirst_p ? !msbytefirst_p : msbytefirst_p) {
01160                 size_t i;
01161                 BDIGIT *p = dp;
01162                 for (i = 0; i < numwords; i++) {
01163                     bary_swap(p, bdigits_per_word);
01164                     p += bdigits_per_word;
01165                 }
01166             }
01167             if (msbytefirst_p != HOST_BIGENDIAN_P) {
01168                 BDIGIT *p;
01169                 for (p = dp; p < de; p++) {
01170                     BDIGIT d = *p;
01171                     *p = swap_bdigit(d);
01172                 }
01173             }
01174             if (flags & INTEGER_PACK_2COMP) {
01175                 if (flags & INTEGER_PACK_NEGATIVE) {
01176                     int zero_p = bary_2comp(dp, num_bdigits);
01177                     sign = zero_p ? -2 : -1;
01178                 }
01179                 else if (BDIGIT_MSB(de[-1])) {
01180                     bary_2comp(dp, num_bdigits);
01181                     sign = -1;
01182                 }
01183                 else {
01184                     sign = 1;
01185                 }
01186             }
01187             else {
01188                 sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
01189             }
01190             return sign;
01191         }
01192     }
01193 
01194     if (num_bdigits != 0) {
01195         int word_num_partialbits;
01196         size_t word_num_fullbytes;
01197 
01198         ssize_t word_step;
01199         size_t byte_start;
01200         int byte_step;
01201 
01202         size_t word_start, word_last;
01203         const unsigned char *wordp, *last_wordp;
01204         BDIGIT_DBL dd;
01205         int numbits_in_dd;
01206 
01207         integer_pack_loop_setup(numwords, wordsize, nails, flags,
01208             &word_num_fullbytes, &word_num_partialbits,
01209             &word_start, &word_step, &word_last, &byte_start, &byte_step);
01210 
01211         wordp = buf + word_start;
01212         last_wordp = buf + word_last;
01213 
01214         dd = 0;
01215         numbits_in_dd = 0;
01216 
01217 #define PUSH_BITS(data, numbits) \
01218         integer_unpack_push_bits(data, numbits, &dd, &numbits_in_dd, &dp)
01219 
01220         while (1) {
01221             size_t index_in_word = 0;
01222             const unsigned char *bytep = wordp + byte_start;
01223             while (index_in_word < word_num_fullbytes) {
01224                 PUSH_BITS(*bytep, CHAR_BIT);
01225                 bytep += byte_step;
01226                 index_in_word++;
01227             }
01228             if (word_num_partialbits) {
01229                 PUSH_BITS(*bytep & ((1 << word_num_partialbits) - 1), word_num_partialbits);
01230                 bytep += byte_step;
01231                 index_in_word++;
01232             }
01233 
01234             if (wordp == last_wordp)
01235                 break;
01236 
01237             wordp += word_step;
01238         }
01239         if (dd)
01240             *dp++ = (BDIGIT)dd;
01241         assert(dp <= de);
01242         while (dp < de)
01243             *dp++ = 0;
01244 #undef PUSH_BITS
01245     }
01246 
01247     if (!(flags & INTEGER_PACK_2COMP)) {
01248         sign = (flags & INTEGER_PACK_NEGATIVE) ? -1 : 1;
01249     }
01250     else {
01251         if (nlp_bits) {
01252             if ((flags & INTEGER_PACK_NEGATIVE) ||
01253                 (bdigits[num_bdigits-1] >> (BITSPERDIG - nlp_bits - 1))) {
01254                 bdigits[num_bdigits-1] |= BIGLO(BDIGMAX << (BITSPERDIG - nlp_bits));
01255                 sign = -1;
01256             }
01257             else {
01258                 sign = 1;
01259             }
01260         }
01261         else {
01262             if (flags & INTEGER_PACK_NEGATIVE) {
01263                 sign = bary_zero_p(bdigits, num_bdigits) ? -2 : -1;
01264             }
01265             else {
01266                 if (num_bdigits != 0 && BDIGIT_MSB(bdigits[num_bdigits-1]))
01267                     sign = -1;
01268                 else
01269                     sign = 1;
01270             }
01271         }
01272         if (sign == -1 && num_bdigits != 0) {
01273             bary_2comp(bdigits, num_bdigits);
01274         }
01275     }
01276 
01277     return sign;
01278 }
01279 
01280 static void
01281 bary_unpack(BDIGIT *bdigits, size_t num_bdigits, const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
01282 {
01283     size_t num_bdigits0;
01284     int nlp_bits;
01285     int sign;
01286 
01287     validate_integer_pack_format(numwords, wordsize, nails, flags,
01288             INTEGER_PACK_MSWORD_FIRST|
01289             INTEGER_PACK_LSWORD_FIRST|
01290             INTEGER_PACK_MSBYTE_FIRST|
01291             INTEGER_PACK_LSBYTE_FIRST|
01292             INTEGER_PACK_NATIVE_BYTE_ORDER|
01293             INTEGER_PACK_2COMP|
01294             INTEGER_PACK_FORCE_BIGNUM|
01295             INTEGER_PACK_NEGATIVE|
01296             INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
01297 
01298     num_bdigits0 = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
01299 
01300     assert(num_bdigits0 <= num_bdigits);
01301 
01302     sign = bary_unpack_internal(bdigits, num_bdigits0, words, numwords, wordsize, nails, flags, nlp_bits);
01303 
01304     if (num_bdigits0 < num_bdigits) {
01305         BDIGITS_ZERO(bdigits + num_bdigits0, num_bdigits - num_bdigits0);
01306         if (sign == -2) {
01307             bdigits[num_bdigits0] = 1;
01308         }
01309     }
01310 }
01311 
01312 static int
01313 bary_subb(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int borrow)
01314 {
01315     BDIGIT_DBL_SIGNED num;
01316     size_t i;
01317     size_t sn;
01318 
01319     assert(xn <= zn);
01320     assert(yn <= zn);
01321 
01322     sn = xn < yn ? xn : yn;
01323 
01324     num = borrow ? -1 : 0;
01325     for (i = 0; i < sn; i++) {
01326         num += (BDIGIT_DBL_SIGNED)xds[i] - yds[i];
01327         zds[i] = BIGLO(num);
01328         num = BIGDN(num);
01329     }
01330     if (yn <= xn) {
01331         for (; i < xn; i++) {
01332             if (num == 0) goto num_is_zero;
01333             num += xds[i];
01334             zds[i] = BIGLO(num);
01335             num = BIGDN(num);
01336         }
01337     }
01338     else {
01339         for (; i < yn; i++) {
01340             num -= yds[i];
01341             zds[i] = BIGLO(num);
01342             num = BIGDN(num);
01343         }
01344     }
01345     if (num == 0) goto num_is_zero;
01346     for (; i < zn; i++) {
01347         zds[i] = BDIGMAX;
01348     }
01349     return 1;
01350 
01351   num_is_zero:
01352     if (xds == zds && xn == zn)
01353         return 0;
01354     for (; i < xn; i++) {
01355         zds[i] = xds[i];
01356     }
01357     for (; i < zn; i++) {
01358         zds[i] = 0;
01359     }
01360     return 0;
01361 }
01362 
01363 static int
01364 bary_sub(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
01365 {
01366     return bary_subb(zds, zn, xds, xn, yds, yn, 0);
01367 }
01368 
01369 static int
01370 bary_sub_one(BDIGIT *zds, size_t zn)
01371 {
01372     return bary_subb(zds, zn, zds, zn, NULL, 0, 1);
01373 }
01374 
01375 static int
01376 bary_addc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, int carry)
01377 {
01378     BDIGIT_DBL num;
01379     size_t i;
01380 
01381     assert(xn <= zn);
01382     assert(yn <= zn);
01383 
01384     if (xn > yn) {
01385         const BDIGIT *tds;
01386         tds = xds; xds = yds; yds = tds;
01387         i = xn; xn = yn; yn = i;
01388     }
01389 
01390     num = carry ? 1 : 0;
01391     for (i = 0; i < xn; i++) {
01392         num += (BDIGIT_DBL)xds[i] + yds[i];
01393         zds[i] = BIGLO(num);
01394         num = BIGDN(num);
01395     }
01396     for (; i < yn; i++) {
01397         if (num == 0) goto num_is_zero;
01398         num += yds[i];
01399         zds[i] = BIGLO(num);
01400         num = BIGDN(num);
01401     }
01402     for (; i < zn; i++) {
01403         if (num == 0) goto num_is_zero;
01404         zds[i] = BIGLO(num);
01405         num = BIGDN(num);
01406     }
01407     return num != 0;
01408 
01409   num_is_zero:
01410     if (yds == zds && yn == zn)
01411         return 0;
01412     for (; i < yn; i++) {
01413         zds[i] = yds[i];
01414     }
01415     for (; i < zn; i++) {
01416         zds[i] = 0;
01417     }
01418     return 0;
01419 }
01420 
01421 static int
01422 bary_add(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
01423 {
01424     return bary_addc(zds, zn, xds, xn, yds, yn, 0);
01425 }
01426 
01427 static int
01428 bary_add_one(BDIGIT *ds, size_t n)
01429 {
01430     size_t i;
01431     for (i = 0; i < n; i++) {
01432         ds[i] = BIGLO(ds[i]+1);
01433         if (ds[i] != 0)
01434             return 0;
01435     }
01436     return 1;
01437 }
01438 
01439 static void
01440 bary_mul_single(BDIGIT *zds, size_t zn, BDIGIT x, BDIGIT y)
01441 {
01442     BDIGIT_DBL n;
01443 
01444     assert(2 <= zn);
01445 
01446     n = (BDIGIT_DBL)x * y;
01447     bdigitdbl2bary(zds, 2, n);
01448     BDIGITS_ZERO(zds + 2, zn - 2);
01449 }
01450 
01451 static int
01452 bary_muladd_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
01453 {
01454     BDIGIT_DBL n;
01455     BDIGIT_DBL dd;
01456     size_t j;
01457 
01458     assert(zn > yn);
01459 
01460     if (x == 0)
01461         return 0;
01462     dd = x;
01463     n = 0;
01464     for (j = 0; j < yn; j++) {
01465         BDIGIT_DBL ee = n + dd * yds[j];
01466         if (ee) {
01467             n = zds[j] + ee;
01468             zds[j] = BIGLO(n);
01469             n = BIGDN(n);
01470         }
01471         else {
01472             n = 0;
01473         }
01474 
01475     }
01476     for (; j < zn; j++) {
01477         if (n == 0)
01478             break;
01479         n += zds[j];
01480         zds[j] = BIGLO(n);
01481         n = BIGDN(n);
01482     }
01483     return n != 0;
01484 }
01485 
01486 static BDIGIT_DBL_SIGNED
01487 bigdivrem_mulsub(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
01488 {
01489     size_t i;
01490     BDIGIT_DBL t2;
01491     BDIGIT_DBL_SIGNED num;
01492 
01493     assert(zn == yn + 1);
01494 
01495     num = 0;
01496     t2 = 0;
01497     i = 0;
01498 
01499     do {
01500         BDIGIT_DBL ee;
01501         t2 += (BDIGIT_DBL)yds[i] * x;
01502         ee = num - BIGLO(t2);
01503         num = (BDIGIT_DBL)zds[i] + ee;
01504         if (ee) zds[i] = BIGLO(num);
01505         num = BIGDN(num);
01506         t2 = BIGDN(t2);
01507     } while (++i < yn);
01508     num += zds[i] - t2; /* borrow from high digit; don't update */
01509     return num;
01510 }
01511 
01512 static int
01513 bary_mulsub_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn)
01514 {
01515     BDIGIT_DBL_SIGNED num;
01516 
01517     assert(zn == yn + 1);
01518 
01519     num = bigdivrem_mulsub(zds, zn, x, yds, yn);
01520     zds[yn] = BIGLO(num);
01521     if (BIGDN(num))
01522         return 1;
01523     return 0;
01524 }
01525 
01526 static void
01527 bary_mul_normal(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
01528 {
01529     size_t i;
01530 
01531     assert(xn + yn <= zn);
01532 
01533     BDIGITS_ZERO(zds, zn);
01534     for (i = 0; i < xn; i++) {
01535         bary_muladd_1xN(zds+i, zn-i, xds[i], yds, yn);
01536     }
01537 }
01538 
01539 VALUE
01540 rb_big_mul_normal(VALUE x, VALUE y)
01541 {
01542     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
01543     VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
01544     bary_mul_normal(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
01545     RB_GC_GUARD(x);
01546     RB_GC_GUARD(y);
01547     return z;
01548 }
01549 
01550 /* efficient squaring (2 times faster than normal multiplication)
01551  * ref: Handbook of Applied Cryptography, Algorithm 14.16
01552  *      http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
01553  */
01554 static void
01555 bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn)
01556 {
01557     size_t i, j;
01558     BDIGIT_DBL c, v, w;
01559     BDIGIT vl;
01560     int vh;
01561 
01562     assert(xn * 2 <= zn);
01563 
01564     BDIGITS_ZERO(zds, zn);
01565 
01566     if (xn == 0)
01567         return;
01568 
01569     for (i = 0; i < xn-1; i++) {
01570         v = (BDIGIT_DBL)xds[i];
01571         if (!v)
01572             continue;
01573         c = (BDIGIT_DBL)zds[i + i] + v * v;
01574         zds[i + i] = BIGLO(c);
01575         c = BIGDN(c);
01576         v *= 2;
01577         vl = BIGLO(v);
01578         vh = (int)BIGDN(v);
01579         for (j = i + 1; j < xn; j++) {
01580             w = (BDIGIT_DBL)xds[j];
01581             c += (BDIGIT_DBL)zds[i + j] + vl * w;
01582             zds[i + j] = BIGLO(c);
01583             c = BIGDN(c);
01584             if (vh)
01585                 c += w;
01586         }
01587         if (c) {
01588             c += (BDIGIT_DBL)zds[i + xn];
01589             zds[i + xn] = BIGLO(c);
01590             c = BIGDN(c);
01591             if (c)
01592                 zds[i + xn + 1] += (BDIGIT)c;
01593         }
01594     }
01595 
01596     /* i == xn-1 */
01597     v = (BDIGIT_DBL)xds[i];
01598     if (!v)
01599         return;
01600     c = (BDIGIT_DBL)zds[i + i] + v * v;
01601     zds[i + i] = BIGLO(c);
01602     c = BIGDN(c);
01603     if (c) {
01604         zds[i + xn] += BIGLO(c);
01605     }
01606 }
01607 
01608 VALUE
01609 rb_big_sq_fast(VALUE x)
01610 {
01611     size_t xn = RBIGNUM_LEN(x), zn = 2 * xn;
01612     VALUE z = bignew(zn, 1);
01613     bary_sq_fast(BDIGITS(z), zn, BDIGITS(x), xn);
01614     RB_GC_GUARD(x);
01615     return z;
01616 }
01617 
01618 /* balancing multiplication by slicing larger argument */
01619 static void
01620 bary_mul_balance_with_mulfunc(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn, mulfunc_t *mulfunc)
01621 {
01622     VALUE work = 0;
01623     size_t yn0 = yn;
01624     size_t r, n;
01625 
01626     assert(xn + yn <= zn);
01627     assert(xn <= yn);
01628     assert(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn));
01629 
01630     BDIGITS_ZERO(zds, xn);
01631 
01632     n = 0;
01633     while (yn > 0) {
01634         BDIGIT *tds;
01635         size_t tn;
01636         r = xn > yn ? yn : xn;
01637         tn = xn + r;
01638         if (2 * (xn + r) <= zn - n) {
01639             tds = zds + n + xn + r;
01640             mulfunc(tds, tn, xds, xn, yds + n, r, wds, wn);
01641             BDIGITS_ZERO(zds + n + xn, r);
01642             bary_add(zds + n, tn,
01643                      zds + n, tn,
01644                      tds, tn);
01645         }
01646         else {
01647             if (wn < xn) {
01648                 wn = xn;
01649                 wds = ALLOCV_N(BDIGIT, work, wn);
01650             }
01651             tds = zds + n;
01652             MEMCPY(wds, zds + n, BDIGIT, xn);
01653             mulfunc(tds, tn, xds, xn, yds + n, r, wds+xn, wn-xn);
01654             bary_add(zds + n, tn,
01655                      zds + n, tn,
01656                      wds, xn);
01657         }
01658         yn -= r;
01659         n += r;
01660     }
01661     BDIGITS_ZERO(zds+xn+yn0, zn - (xn+yn0));
01662 
01663     if (work)
01664         ALLOCV_END(work);
01665 }
01666 
01667 VALUE
01668 rb_big_mul_balance(VALUE x, VALUE y)
01669 {
01670     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
01671     VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
01672     bary_mul_balance_with_mulfunc(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0, bary_mul_toom3_start);
01673     RB_GC_GUARD(x);
01674     RB_GC_GUARD(y);
01675     return z;
01676 }
01677 
01678 /* multiplication by karatsuba method */
01679 static void
01680 bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
01681 {
01682     VALUE work = 0;
01683 
01684     size_t n;
01685     int sub_p, borrow, carry1, carry2, carry3;
01686 
01687     int odd_y = 0;
01688     int odd_xy = 0;
01689     int sq;
01690 
01691     const BDIGIT *xds0, *xds1, *yds0, *yds1;
01692     BDIGIT *zds0, *zds1, *zds2, *zds3;
01693 
01694     assert(xn + yn <= zn);
01695     assert(xn <= yn);
01696     assert(yn < 2 * xn);
01697 
01698     sq = xds == yds && xn == yn;
01699 
01700     if (yn & 1) {
01701         odd_y = 1;
01702         yn--;
01703         if (yn < xn) {
01704             odd_xy = 1;
01705             xn--;
01706         }
01707     }
01708 
01709     n = yn / 2;
01710 
01711     assert(n < xn);
01712 
01713     if (wn < n) {
01714         /* This function itself needs only n BDIGITs for work area.
01715          * However this function calls bary_mul_karatsuba and
01716          * bary_mul_balance recursively.
01717          * 2n BDIGITs are enough to avoid allocations in
01718          * the recursively called functions.
01719          */
01720         wn = 2*n;
01721         wds = ALLOCV_N(BDIGIT, work, wn);
01722     }
01723 
01724     /* Karatsuba algorithm:
01725      *
01726      * x = x0 + r*x1
01727      * y = y0 + r*y1
01728      * z = x*y
01729      *   = (x0 + r*x1) * (y0 + r*y1)
01730      *   = x0*y0 + r*(x1*y0 + x0*y1) + r*r*x1*y1
01731      *   = x0*y0 + r*(x0*y0 + x1*y1 - (x1-x0)*(y1-y0)) + r*r*x1*y1
01732      *   = x0*y0 + r*(x0*y0 + x1*y1 - (x0-x1)*(y0-y1)) + r*r*x1*y1
01733      */
01734 
01735     xds0 = xds;
01736     xds1 = xds + n;
01737     yds0 = yds;
01738     yds1 = yds + n;
01739     zds0 = zds;
01740     zds1 = zds + n;
01741     zds2 = zds + 2*n;
01742     zds3 = zds + 3*n;
01743 
01744     sub_p = 1;
01745 
01746     /* zds0:? zds1:? zds2:? zds3:? wds:? */
01747 
01748     if (bary_sub(zds0, n, xds, n, xds+n, xn-n)) {
01749         bary_2comp(zds0, n);
01750         sub_p = !sub_p;
01751     }
01752 
01753     /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:? */
01754 
01755     if (sq) {
01756         sub_p = 1;
01757         bary_mul_karatsuba_start(zds1, 2*n, zds0, n, zds0, n, wds, wn);
01758     }
01759     else {
01760         if (bary_sub(wds, n, yds, n, yds+n, n)) {
01761             bary_2comp(wds, n);
01762             sub_p = !sub_p;
01763         }
01764 
01765         /* zds0:|x1-x0| zds1:? zds2:? zds3:? wds:|y1-y0| */
01766 
01767         bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
01768     }
01769 
01770     /* zds0:|x1-x0| zds1,zds2:|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
01771 
01772     borrow = 0;
01773     if (sub_p) {
01774         borrow = !bary_2comp(zds1, 2*n);
01775     }
01776     /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:|y1-y0| */
01777 
01778     MEMCPY(wds, zds1, BDIGIT, n);
01779 
01780     /* zds0:|x1-x0| zds1,zds2:-?|x1-x0|*|y1-y0| zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
01781 
01782     bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
01783 
01784     /* zds0,zds1:x0*y0 zds2:hi(-?|x1-x0|*|y1-y0|) zds3:? wds:lo(-?|x1-x0|*|y1-y0|) */
01785 
01786     carry1 = bary_add(wds, n, wds, n, zds0, n);
01787     carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
01788 
01789     /* zds0,zds1:x0*y0 zds2:hi(x0*y0-?|x1-x0|*|y1-y0|) zds3:? wds:lo(x0*y0-?|x1-x0|*|y1-y0|) */
01790 
01791     carry2 = bary_add(zds1, n, zds1, n, wds, n);
01792 
01793     /* 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|) */
01794 
01795     MEMCPY(wds, zds2, BDIGIT, n);
01796 
01797     /* 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|) */
01798 
01799     bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
01800 
01801     /* 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|) */
01802 
01803     carry3 = bary_add(zds1, n, zds1, n, zds2, n);
01804 
01805     /* 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|) */
01806 
01807     carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
01808 
01809     /* 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|) */
01810 
01811     bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
01812 
01813     /* 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:_ */
01814 
01815     if (carry2)
01816         bary_add_one(zds2, zn-2*n);
01817 
01818     if (carry1 + carry3 - borrow < 0)
01819         bary_sub_one(zds3, zn-3*n);
01820     else if (carry1 + carry3 - borrow > 0) {
01821         BDIGIT c = carry1 + carry3 - borrow;
01822         bary_add(zds3, zn-3*n, zds3, zn-3*n, &c, 1);
01823     }
01824 
01825     /*
01826     if (SIZEOF_BDIGITS * zn <= 16) {
01827         uint128_t z, x, y;
01828         ssize_t i;
01829         for (x = 0, i = xn-1; 0 <= i; i--) { x <<= SIZEOF_BDIGITS*CHAR_BIT; x |= xds[i]; }
01830         for (y = 0, i = yn-1; 0 <= i; i--) { y <<= SIZEOF_BDIGITS*CHAR_BIT; y |= yds[i]; }
01831         for (z = 0, i = zn-1; 0 <= i; i--) { z <<= SIZEOF_BDIGITS*CHAR_BIT; z |= zds[i]; }
01832         assert(z == x * y);
01833     }
01834     */
01835 
01836     if (odd_xy) {
01837         bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
01838         bary_muladd_1xN(zds+xn, zn-xn, xds[xn], yds, yn+1);
01839     }
01840     else if (odd_y) {
01841         bary_muladd_1xN(zds+yn, zn-yn, yds[yn], xds, xn);
01842     }
01843 
01844     if (work)
01845         ALLOCV_END(work);
01846 }
01847 
01848 VALUE
01849 rb_big_mul_karatsuba(VALUE x, VALUE y)
01850 {
01851     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
01852     VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
01853     if (!((xn <= yn && yn < 2) || KARATSUBA_BALANCED(xn, yn)))
01854         rb_raise(rb_eArgError, "unexpected bignum length for karatsuba");
01855     bary_mul_karatsuba(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
01856     RB_GC_GUARD(x);
01857     RB_GC_GUARD(y);
01858     return z;
01859 }
01860 
01861 static void
01862 bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn, BDIGIT *wds, size_t wn)
01863 {
01864     size_t n;
01865     size_t wnc;
01866     VALUE work = 0;
01867 
01868     /* "p" stands for "positive".  Actually it means "non-negative", though. */
01869     size_t x0n; const BDIGIT *x0ds;
01870     size_t x1n; const BDIGIT *x1ds;
01871     size_t x2n; const BDIGIT *x2ds;
01872     size_t y0n; const BDIGIT *y0ds;
01873     size_t y1n; const BDIGIT *y1ds;
01874     size_t y2n; const BDIGIT *y2ds;
01875 
01876     size_t u1n; BDIGIT *u1ds; int u1p;
01877     size_t u2n; BDIGIT *u2ds; int u2p;
01878     size_t u3n; BDIGIT *u3ds; int u3p;
01879 
01880     size_t v1n; BDIGIT *v1ds; int v1p;
01881     size_t v2n; BDIGIT *v2ds; int v2p;
01882     size_t v3n; BDIGIT *v3ds; int v3p;
01883 
01884     size_t t0n; BDIGIT *t0ds; int t0p;
01885     size_t t1n; BDIGIT *t1ds; int t1p;
01886     size_t t2n; BDIGIT *t2ds; int t2p;
01887     size_t t3n; BDIGIT *t3ds; int t3p;
01888     size_t t4n; BDIGIT *t4ds; int t4p;
01889 
01890     size_t z0n; BDIGIT *z0ds;
01891     size_t z1n; BDIGIT *z1ds; int z1p;
01892     size_t z2n; BDIGIT *z2ds; int z2p;
01893     size_t z3n; BDIGIT *z3ds; int z3p;
01894     size_t z4n; BDIGIT *z4ds;
01895 
01896     size_t zzn; BDIGIT *zzds;
01897 
01898     int sq = xds == yds && xn == yn;
01899 
01900     assert(xn <= yn);  /* assume y >= x */
01901     assert(xn + yn <= zn);
01902 
01903     n = (yn + 2) / 3;
01904     assert(2*n < xn);
01905 
01906     wnc = 0;
01907 
01908     wnc += (u1n = n+1); /* BITSPERDIG*n+2 bits */
01909     wnc += (u2n = n+1); /* BITSPERDIG*n+1 bits */
01910     wnc += (u3n = n+1); /* BITSPERDIG*n+3 bits */
01911     wnc += (v1n = n+1); /* BITSPERDIG*n+2 bits */
01912     wnc += (v2n = n+1); /* BITSPERDIG*n+1 bits */
01913     wnc += (v3n = n+1); /* BITSPERDIG*n+3 bits */
01914 
01915     wnc += (t0n = 2*n); /* BITSPERDIG*2*n bits */
01916     wnc += (t1n = 2*n+2); /* BITSPERDIG*2*n+4 bits but bary_mul needs u1n+v1n */
01917     wnc += (t2n = 2*n+2); /* BITSPERDIG*2*n+2 bits but bary_mul needs u2n+v2n */
01918     wnc += (t3n = 2*n+2); /* BITSPERDIG*2*n+6 bits but bary_mul needs u3n+v3n */
01919     wnc += (t4n = 2*n); /* BITSPERDIG*2*n bits */
01920 
01921     wnc += (z1n = 2*n+1); /* BITSPERDIG*2*n+5 bits */
01922     wnc += (z2n = 2*n+1); /* BITSPERDIG*2*n+6 bits */
01923     wnc += (z3n = 2*n+1); /* BITSPERDIG*2*n+8 bits */
01924 
01925     if (wn < wnc) {
01926         wn = wnc * 3 / 2; /* Allocate working memory for whole recursion at once. */
01927         wds = ALLOCV_N(BDIGIT, work, wn);
01928     }
01929 
01930     u1ds = wds; wds += u1n;
01931     u2ds = wds; wds += u2n;
01932     u3ds = wds; wds += u3n;
01933 
01934     v1ds = wds; wds += v1n;
01935     v2ds = wds; wds += v2n;
01936     v3ds = wds; wds += v3n;
01937 
01938     t0ds = wds; wds += t0n;
01939     t1ds = wds; wds += t1n;
01940     t2ds = wds; wds += t2n;
01941     t3ds = wds; wds += t3n;
01942     t4ds = wds; wds += t4n;
01943 
01944     z1ds = wds; wds += z1n;
01945     z2ds = wds; wds += z2n;
01946     z3ds = wds; wds += z3n;
01947 
01948     wn -= wnc;
01949 
01950     zzds = u1ds;
01951     zzn = 6*n+1;
01952 
01953     x0n = n;
01954     x1n = n;
01955     x2n = xn - 2*n;
01956     x0ds = xds;
01957     x1ds = xds + n;
01958     x2ds = xds + 2*n;
01959 
01960     if (sq) {
01961         y0n = x0n;
01962         y1n = x1n;
01963         y2n = x2n;
01964         y0ds = x0ds;
01965         y1ds = x1ds;
01966         y2ds = x2ds;
01967     }
01968     else {
01969         y0n = n;
01970         y1n = n;
01971         y2n = yn - 2*n;
01972         y0ds = yds;
01973         y1ds = yds + n;
01974         y2ds = yds + 2*n;
01975     }
01976 
01977     /*
01978      * ref. http://en.wikipedia.org/wiki/Toom%E2%80%93Cook_multiplication
01979      *
01980      * x(b) = x0 * b^0 + x1 * b^1 + x2 * b^2
01981      * y(b) = y0 * b^0 + y1 * b^1 + y2 * b^2
01982      *
01983      * z(b) = x(b) * y(b)
01984      * z(b) = z0 * b^0 + z1 * b^1 + z2 * b^2 + z3 * b^3 + z4 * b^4
01985      * where:
01986      *   z0 = x0 * y0
01987      *   z1 = x0 * y1 + x1 * y0
01988      *   z2 = x0 * y2 + x1 * y1 + x2 * y0
01989      *   z3 = x1 * y2 + x2 * y1
01990      *   z4 = x2 * y2
01991      *
01992      * Toom3 method (a.k.a. Toom-Cook method):
01993      * (Step1) calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4),
01994      * where:
01995      *   b0 = 0, b1 = 1, b2 = -1, b3 = -2, b4 = inf,
01996      *   z(0)   = x(0)   * y(0)   = x0 * y0
01997      *   z(1)   = x(1)   * y(1)   = (x0 + x1 + x2) * (y0 + y1 + y2)
01998      *   z(-1)  = x(-1)  * y(-1)  = (x0 - x1 + x2) * (y0 - y1 + y2)
01999      *   z(-2)  = x(-2)  * y(-2)  = (x0 - 2 * (x1 - 2 * x2)) * (y0 - 2 * (y1 - 2 * y2))
02000      *   z(inf) = x(inf) * y(inf) = x2 * y2
02001      *
02002      * (Step2) interpolating z0, z1, z2, z3 and z4.
02003      *
02004      * (Step3) Substituting base value into b of the polynomial z(b),
02005      */
02006 
02007     /*
02008      * [Step1] calculating 5 points z(b0), z(b1), z(b2), z(b3), z(b4)
02009      */
02010 
02011     /* u1 <- x0 + x2 */
02012     bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
02013     u1p = 1;
02014 
02015     /* x(-1) : u2 <- u1 - x1 = x0 - x1 + x2 */
02016     if (bary_sub(u2ds, u2n, u1ds, u1n, x1ds, x1n)) {
02017         bary_2comp(u2ds, u2n);
02018         u2p = 0;
02019     }
02020     else {
02021         u2p = 1;
02022     }
02023 
02024     /* x(1) : u1 <- u1 + x1 = x0 + x1 + x2 */
02025     bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
02026 
02027     /* x(-2) : u3 <- 2 * (u2 + x2) - x0 = x0 - 2 * (x1 - 2 * x2) */
02028     u3p = 1;
02029     if (u2p) {
02030         bary_add(u3ds, u3n, u2ds, u2n, x2ds, x2n);
02031     }
02032     else if (bary_sub(u3ds, u3n, x2ds, x2n, u2ds, u2n)) {
02033         bary_2comp(u3ds, u3n);
02034         u3p = 0;
02035     }
02036     bary_small_lshift(u3ds, u3ds, u3n, 1);
02037     if (!u3p) {
02038         bary_add(u3ds, u3n, u3ds, u3n, x0ds, x0n);
02039     }
02040     else if (bary_sub(u3ds, u3n, u3ds, u3n, x0ds, x0n)) {
02041         bary_2comp(u3ds, u3n);
02042         u3p = 0;
02043     }
02044 
02045     if (sq) {
02046         v1n = u1n; v1ds = u1ds; v1p = u1p;
02047         v2n = u2n; v2ds = u2ds; v2p = u2p;
02048         v3n = u3n; v3ds = u3ds; v3p = u3p;
02049     }
02050     else {
02051         /* v1 <- y0 + y2 */
02052         bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
02053         v1p = 1;
02054 
02055         /* y(-1) : v2 <- v1 - y1 = y0 - y1 + y2 */
02056         v2p = 1;
02057         if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
02058             bary_2comp(v2ds, v2n);
02059             v2p = 0;
02060         }
02061 
02062         /* y(1) : v1 <- v1 + y1 = y0 + y1 + y2 */
02063         bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
02064 
02065         /* y(-2) : v3 <- 2 * (v2 + y2) - y0 = y0 - 2 * (y1 - 2 * y2) */
02066         v3p = 1;
02067         if (v2p) {
02068             bary_add(v3ds, v3n, v2ds, v2n, y2ds, y2n);
02069         }
02070         else if (bary_sub(v3ds, v3n, y2ds, y2n, v2ds, v2n)) {
02071             bary_2comp(v3ds, v3n);
02072             v3p = 0;
02073         }
02074         bary_small_lshift(v3ds, v3ds, v3n, 1);
02075         if (!v3p) {
02076             bary_add(v3ds, v3n, v3ds, v3n, y0ds, y0n);
02077         }
02078         else if (bary_sub(v3ds, v3n, v3ds, v3n, y0ds, y0n)) {
02079             bary_2comp(v3ds, v3n);
02080             v3p = 0;
02081         }
02082     }
02083 
02084     /* z(0) : t0 <- x0 * y0 */
02085     bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
02086     t0p = 1;
02087 
02088     /* z(1) : t1 <- u1 * v1 */
02089     bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn);
02090     t1p = u1p == v1p;
02091     assert(t1ds[t1n-1] == 0);
02092     t1n--;
02093 
02094     /* z(-1) : t2 <- u2 * v2 */
02095     bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn);
02096     t2p = u2p == v2p;
02097     assert(t2ds[t2n-1] == 0);
02098     t2n--;
02099 
02100     /* z(-2) : t3 <- u3 * v3 */
02101     bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn);
02102     t3p = u3p == v3p;
02103     assert(t3ds[t3n-1] == 0);
02104     t3n--;
02105 
02106     /* z(inf) : t4 <- x2 * y2 */
02107     bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
02108     t4p = 1;
02109 
02110     /*
02111      * [Step2] interpolating z0, z1, z2, z3 and z4.
02112      */
02113 
02114     /* z0 <- z(0) == t0 */
02115     z0n = t0n; z0ds = t0ds;
02116 
02117     /* z4 <- z(inf) == t4 */
02118     z4n = t4n; z4ds = t4ds;
02119 
02120     /* z3 <- (z(-2) - z(1)) / 3 == (t3 - t1) / 3 */
02121     if (t3p == t1p) {
02122         z3p = t3p;
02123         if (bary_sub(z3ds, z3n, t3ds, t3n, t1ds, t1n)) {
02124             bary_2comp(z3ds, z3n);
02125             z3p = !z3p;
02126         }
02127     }
02128     else {
02129         z3p = t3p;
02130         bary_add(z3ds, z3n, t3ds, t3n, t1ds, t1n);
02131     }
02132     bigdivrem_single(z3ds, z3ds, z3n, 3);
02133 
02134     /* z1 <- (z(1) - z(-1)) / 2 == (t1 - t2) / 2 */
02135     if (t1p == t2p) {
02136         z1p = t1p;
02137         if (bary_sub(z1ds, z1n, t1ds, t1n, t2ds, t2n)) {
02138             bary_2comp(z1ds, z1n);
02139             z1p = !z1p;
02140         }
02141     }
02142     else {
02143         z1p = t1p;
02144         bary_add(z1ds, z1n, t1ds, t1n, t2ds, t2n);
02145     }
02146     bary_small_rshift(z1ds, z1ds, z1n, 1, 0);
02147 
02148     /* z2 <- z(-1) - z(0) == t2 - t0 */
02149     if (t2p == t0p) {
02150         z2p = t2p;
02151         if (bary_sub(z2ds, z2n, t2ds, t2n, t0ds, t0n)) {
02152             bary_2comp(z2ds, z2n);
02153             z2p = !z2p;
02154         }
02155     }
02156     else {
02157         z2p = t2p;
02158         bary_add(z2ds, z2n, t2ds, t2n, t0ds, t0n);
02159     }
02160 
02161     /* z3 <- (z2 - z3) / 2 + 2 * z(inf) == (z2 - z3) / 2 + 2 * t4 */
02162     if (z2p == z3p) {
02163         z3p = z2p;
02164         if (bary_sub(z3ds, z3n, z2ds, z2n, z3ds, z3n)) {
02165             bary_2comp(z3ds, z3n);
02166             z3p = !z3p;
02167         }
02168     }
02169     else {
02170         z3p = z2p;
02171         bary_add(z3ds, z3n, z2ds, z2n, z3ds, z3n);
02172     }
02173     bary_small_rshift(z3ds, z3ds, z3n, 1, 0);
02174     if (z3p == t4p) {
02175         bary_muladd_1xN(z3ds, z3n, 2, t4ds, t4n);
02176     }
02177     else {
02178         if (bary_mulsub_1xN(z3ds, z3n, 2, t4ds, t4n)) {
02179             bary_2comp(z3ds, z3n);
02180             z3p = !z3p;
02181         }
02182     }
02183 
02184     /* z2 <- z2 + z1 - z(inf) == z2 + z1 - t4 */
02185     if (z2p == z1p) {
02186         bary_add(z2ds, z2n, z2ds, z2n, z1ds, z1n);
02187     }
02188     else {
02189         if (bary_sub(z2ds, z2n, z2ds, z2n, z1ds, z1n)) {
02190             bary_2comp(z2ds, z2n);
02191             z2p = !z2p;
02192         }
02193     }
02194 
02195     if (z2p == t4p) {
02196         if (bary_sub(z2ds, z2n, z2ds, z2n, t4ds, t4n)) {
02197             bary_2comp(z2ds, z2n);
02198             z2p = !z2p;
02199         }
02200     }
02201     else {
02202         bary_add(z2ds, z2n, z2ds, z2n, t4ds, t4n);
02203     }
02204 
02205     /* z1 <- z1 - z3 */
02206     if (z1p == z3p) {
02207         if (bary_sub(z1ds, z1n, z1ds, z1n, z3ds, z3n)) {
02208             bary_2comp(z1ds, z1n);
02209             z1p = !z1p;
02210         }
02211     }
02212     else {
02213         bary_add(z1ds, z1n, z1ds, z1n, z3ds, z3n);
02214     }
02215 
02216     /*
02217      * [Step3] Substituting base value into b of the polynomial z(b),
02218      */
02219 
02220     MEMCPY(zzds, z0ds, BDIGIT, z0n);
02221     BDIGITS_ZERO(zzds + z0n, 4*n - z0n);
02222     MEMCPY(zzds + 4*n, z4ds, BDIGIT, z4n);
02223     BDIGITS_ZERO(zzds + 4*n + z4n, zzn - (4*n + z4n));
02224     if (z1p)
02225         bary_add(zzds +   n, zzn -   n, zzds +   n, zzn -   n, z1ds, z1n);
02226     else
02227         bary_sub(zzds +   n, zzn -   n, zzds +   n, zzn -   n, z1ds, z1n);
02228     if (z2p)
02229         bary_add(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
02230     else
02231         bary_sub(zzds + 2*n, zzn - 2*n, zzds + 2*n, zzn - 2*n, z2ds, z2n);
02232     if (z3p)
02233         bary_add(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
02234     else
02235         bary_sub(zzds + 3*n, zzn - 3*n, zzds + 3*n, zzn - 3*n, z3ds, z3n);
02236 
02237     BARY_TRUNC(zzds, zzn);
02238     MEMCPY(zds, zzds, BDIGIT, zzn);
02239     BDIGITS_ZERO(zds + zzn, zn - zzn);
02240 
02241     if (work)
02242         ALLOCV_END(work);
02243 }
02244 
02245 VALUE
02246 rb_big_mul_toom3(VALUE x, VALUE y)
02247 {
02248     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
02249     VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02250     if (xn > yn || yn < 3 || !TOOM3_BALANCED(xn,yn))
02251         rb_raise(rb_eArgError, "unexpected bignum length for toom3");
02252     bary_mul_toom3(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, NULL, 0);
02253     RB_GC_GUARD(x);
02254     RB_GC_GUARD(y);
02255     return z;
02256 }
02257 
02258 #ifdef USE_GMP
02259 static void
02260 bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02261 {
02262     const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGITS)*CHAR_BIT;
02263     mpz_t x, y, z;
02264     size_t count;
02265 
02266     assert(xn + yn <= zn);
02267 
02268     mpz_init(x);
02269     mpz_init(y);
02270     mpz_init(z);
02271     mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
02272     if (xds == yds && xn == yn) {
02273         mpz_mul(z, x, x);
02274     }
02275     else {
02276         mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
02277         mpz_mul(z, x, y);
02278     }
02279     mpz_export(zds, &count, -1, sizeof(BDIGIT), 0, nails, z);
02280     BDIGITS_ZERO(zds+count, zn-count);
02281     mpz_clear(x);
02282     mpz_clear(y);
02283     mpz_clear(z);
02284 }
02285 
02286 VALUE
02287 rb_big_mul_gmp(VALUE x, VALUE y)
02288 {
02289     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;
02290     VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02291     bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);
02292     RB_GC_GUARD(x);
02293     RB_GC_GUARD(y);
02294     return z;
02295 }
02296 #endif
02297 
02298 static void
02299 bary_short_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02300 {
02301     assert(xn + yn <= zn);
02302 
02303     if (xn == 1 && yn == 1) {
02304         bary_mul_single(zds, zn, xds[0], yds[0]);
02305     }
02306     else {
02307         bary_mul_normal(zds, zn, xds, xn, yds, yn);
02308         rb_thread_check_ints();
02309     }
02310 }
02311 
02312 /* determine whether a bignum is sparse or not by random sampling */
02313 static inline int
02314 bary_sparse_p(const BDIGIT *ds, size_t n)
02315 {
02316     long c = 0;
02317 
02318     if (          ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
02319     if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
02320     if (c <= 1 && ds[rb_genrand_ulong_limited(n / 2) + n / 4]) c++;
02321 
02322     return (c <= 1) ? 1 : 0;
02323 }
02324 
02325 static int
02326 bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp, const BDIGIT **ydsp, size_t *ynp)
02327 {
02328     size_t nlsz; /* number of least significant zero BDIGITs */
02329 
02330     BDIGIT *zds = *zdsp;
02331     size_t zn = *znp;
02332     const BDIGIT *xds = *xdsp;
02333     size_t xn = *xnp;
02334     const BDIGIT *yds = *ydsp;
02335     size_t yn = *ynp;
02336 
02337     assert(xn + yn <= zn);
02338 
02339     nlsz = 0;
02340 
02341     while (0 < xn) {
02342         if (xds[xn-1] == 0) {
02343             xn--;
02344         }
02345         else {
02346             do {
02347                 if (xds[0] != 0)
02348                     break;
02349                 xds++;
02350                 xn--;
02351                 nlsz++;
02352             } while (0 < xn);
02353             break;
02354         }
02355     }
02356 
02357     while (0 < yn) {
02358         if (yds[yn-1] == 0) {
02359             yn--;
02360         }
02361         else {
02362             do {
02363                 if (xds[0] != 0)
02364                     break;
02365                 yds++;
02366                 yn--;
02367                 nlsz++;
02368             } while (0 < yn);
02369             break;
02370         }
02371     }
02372 
02373     if (nlsz) {
02374         BDIGITS_ZERO(zds, nlsz);
02375         zds += nlsz;
02376         zn -= nlsz;
02377     }
02378 
02379     /* make sure that y is longer than x */
02380     if (xn > yn) {
02381         const BDIGIT *tds;
02382         size_t tn;
02383         tds = xds; xds = yds; yds = tds;
02384         tn = xn; xn = yn; yn = tn;
02385     }
02386     assert(xn <= yn);
02387 
02388     if (xn <= 1) {
02389         if (xn == 0) {
02390             BDIGITS_ZERO(zds, zn);
02391             return 1;
02392         }
02393 
02394         if (xds[0] == 1) {
02395             MEMCPY(zds, yds, BDIGIT, yn);
02396             BDIGITS_ZERO(zds+yn, zn-yn);
02397             return 1;
02398         }
02399         if (POW2_P(xds[0])) {
02400             zds[yn] = bary_small_lshift(zds, yds, yn, bit_length(xds[0])-1);
02401             BDIGITS_ZERO(zds+yn+1, zn-yn-1);
02402             return 1;
02403         }
02404         if (yn == 1 && yds[0] == 1) {
02405             zds[0] = xds[0];
02406             BDIGITS_ZERO(zds+1, zn-1);
02407             return 1;
02408         }
02409         bary_mul_normal(zds, zn, xds, xn, yds, yn);
02410         return 1;
02411     }
02412 
02413     *zdsp = zds;
02414     *znp = zn;
02415     *xdsp = xds;
02416     *xnp = xn;
02417     *ydsp = yds;
02418     *ynp = yn;
02419 
02420     return 0;
02421 }
02422 
02423 static void
02424 bary_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)
02425 {
02426     /* normal multiplication when x is small */
02427     if (xn < KARATSUBA_MUL_DIGITS) {
02428       normal:
02429         if (xds == yds && xn == yn)
02430             bary_sq_fast(zds, zn, xds, xn);
02431         else
02432             bary_short_mul(zds, zn, xds, xn, yds, yn);
02433         return;
02434     }
02435 
02436     /* normal multiplication when x or y is a sparse bignum */
02437     if (bary_sparse_p(xds, xn)) goto normal;
02438     if (bary_sparse_p(yds, yn)) {
02439         bary_short_mul(zds, zn, yds, yn, xds, xn);
02440         return;
02441     }
02442 
02443     /* balance multiplication by slicing y when x is much smaller than y */
02444     if (!KARATSUBA_BALANCED(xn, yn)) {
02445         bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_karatsuba_start);
02446         return;
02447     }
02448 
02449     /* multiplication by karatsuba method */
02450     bary_mul_karatsuba(zds, zn, xds, xn, yds, yn, wds, wn);
02451 }
02452 
02453 static void
02454 bary_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)
02455 {
02456     if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
02457         return;
02458 
02459     bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
02460 }
02461 
02462 static void
02463 bary_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)
02464 {
02465     if (xn < TOOM3_MUL_DIGITS) {
02466         bary_mul_karatsuba_branch(zds, zn, xds, xn, yds, yn, wds, wn);
02467         return;
02468     }
02469 
02470     if (!TOOM3_BALANCED(xn, yn)) {
02471         bary_mul_balance_with_mulfunc(zds, zn, xds, xn, yds, yn, wds, wn, bary_mul_toom3_start);
02472         return;
02473     }
02474 
02475     bary_mul_toom3(zds, zn, xds, xn, yds, yn, wds, wn);
02476 }
02477 
02478 static void
02479 bary_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)
02480 {
02481     if (bary_mul_precheck(&zds, &zn, &xds, &xn, &yds, &yn))
02482         return;
02483 
02484     bary_mul_toom3_branch(zds, zn, xds, xn, yds, yn, wds, wn);
02485 }
02486 
02487 static void
02488 bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02489 {
02490 #ifdef USE_GMP
02491     const size_t naive_threshold = GMP_MUL_DIGITS;
02492 #else
02493     const size_t naive_threshold = KARATSUBA_MUL_DIGITS;
02494 #endif
02495     if (xn <= yn) {
02496         if (xn < naive_threshold) {
02497             if (xds == yds && xn == yn)
02498                 bary_sq_fast(zds, zn, xds, xn);
02499             else
02500                 bary_short_mul(zds, zn, xds, xn, yds, yn);
02501             return;
02502         }
02503     }
02504     else {
02505         if (yn < naive_threshold) {
02506             bary_short_mul(zds, zn, yds, yn, xds, xn);
02507             return;
02508         }
02509     }
02510 
02511 #ifdef USE_GMP
02512     bary_mul_gmp(zds, zn, xds, xn, yds, yn);
02513 #else
02514     bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);
02515 #endif
02516 }
02517 
02518 struct big_div_struct {
02519     size_t yn, zn;
02520     BDIGIT *yds, *zds;
02521     volatile VALUE stop;
02522 };
02523 
02524 static void *
02525 bigdivrem1(void *ptr)
02526 {
02527     struct big_div_struct *bds = (struct big_div_struct*)ptr;
02528     size_t yn = bds->yn;
02529     size_t zn = bds->zn;
02530     BDIGIT *yds = bds->yds, *zds = bds->zds;
02531     BDIGIT_DBL_SIGNED num;
02532     BDIGIT q;
02533 
02534     do {
02535         if (bds->stop) {
02536             bds->zn = zn;
02537             return 0;
02538         }
02539         if (zds[zn-1] == yds[yn-1]) q = BDIGMAX;
02540         else q = (BDIGIT)((BIGUP(zds[zn-1]) + zds[zn-2])/yds[yn-1]);
02541         if (q) {
02542             num = bigdivrem_mulsub(zds+zn-(yn+1), yn+1,
02543                                    q,
02544                                    yds, yn);
02545             while (num) { /* "add back" required */
02546                 q--;
02547                 num = bary_add(zds+zn-(yn+1), yn,
02548                                zds+zn-(yn+1), yn,
02549                                yds, yn);
02550                 num--;
02551             }
02552         }
02553         zn--;
02554         zds[zn] = q;
02555     } while (zn > yn);
02556     return 0;
02557 }
02558 
02559 static void
02560 rb_big_stop(void *ptr)
02561 {
02562     struct big_div_struct *bds = ptr;
02563     bds->stop = Qtrue;
02564 }
02565 
02566 static BDIGIT
02567 bigdivrem_single1(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT x_higher_bdigit, BDIGIT y)
02568 {
02569     assert(0 < xn);
02570     assert(x_higher_bdigit < y);
02571     if (POW2_P(y)) {
02572         BDIGIT r;
02573         r = xds[0] & (y-1);
02574         bary_small_rshift(qds, xds, xn, bit_length(y)-1, x_higher_bdigit);
02575         return r;
02576     }
02577     else {
02578         size_t i;
02579         BDIGIT_DBL t2;
02580         t2 = x_higher_bdigit;
02581         i = xn;
02582         while (i--) {
02583             t2 = BIGUP(t2) + xds[i];
02584             qds[i] = (BDIGIT)(t2 / y);
02585             t2 %= y;
02586         }
02587         return (BDIGIT)t2;
02588     }
02589 }
02590 
02591 static BDIGIT
02592 bigdivrem_single(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT y)
02593 {
02594     return bigdivrem_single1(qds, xds, xn, 0, y);
02595 }
02596 
02597 static void
02598 bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
02599 {
02600     struct big_div_struct bds;
02601     size_t ynzero;
02602 
02603     assert(yn < zn);
02604     assert(BDIGIT_MSB(yds[yn-1]));
02605     assert(zds[zn-1] < yds[yn-1]);
02606 
02607     for (ynzero = 0; !yds[ynzero]; ynzero++);
02608 
02609     if (ynzero+1 == yn) {
02610         BDIGIT r;
02611         r = bigdivrem_single1(zds+yn, zds+ynzero, zn-yn, zds[zn-1], yds[ynzero]);
02612         zds[ynzero] = r;
02613         return;
02614     }
02615 
02616     bds.yn = yn - ynzero;
02617     bds.zds = zds + ynzero;
02618     bds.yds = yds + ynzero;
02619     bds.stop = Qfalse;
02620     bds.zn = zn - ynzero;
02621     if (bds.zn > 10000 || bds.yn > 10000) {
02622       retry:
02623         bds.stop = Qfalse;
02624         rb_thread_call_without_gvl(bigdivrem1, &bds, rb_big_stop, &bds);
02625 
02626         if (bds.stop == Qtrue) {
02627             /* execute trap handler, but exception was not raised. */
02628             goto retry;
02629         }
02630     }
02631     else {
02632         bigdivrem1(&bds);
02633     }
02634 }
02635 
02636 static void
02637 bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02638 {
02639     int shift;
02640     BDIGIT *zds, *yyds;
02641     size_t zn;
02642     VALUE tmpyz = 0;
02643 
02644     assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
02645     assert(qds ? (xn - yn + 1) <= qn : 1);
02646     assert(rds ? yn <= rn : 1);
02647 
02648     zn = xn + BIGDIVREM_EXTRA_WORDS;
02649 
02650     shift = nlz(yds[yn-1]);
02651     if (shift) {
02652         int alloc_y = !rds;
02653         int alloc_z = !qds || qn < zn;
02654         if (alloc_y && alloc_z) {
02655             yyds = ALLOCV_N(BDIGIT, tmpyz, yn+zn);
02656             zds = yyds + yn;
02657         }
02658         else {
02659             yyds = alloc_y ? ALLOCV_N(BDIGIT, tmpyz, yn) : rds;
02660             zds = alloc_z ? ALLOCV_N(BDIGIT, tmpyz, zn) : qds;
02661         }
02662         zds[xn] = bary_small_lshift(zds, xds, xn, shift);
02663         bary_small_lshift(yyds, yds, yn, shift);
02664     }
02665     else {
02666         if (qds && zn <= qn)
02667             zds = qds;
02668         else
02669             zds = ALLOCV_N(BDIGIT, tmpyz, zn);
02670         MEMCPY(zds, xds, BDIGIT, xn);
02671         zds[xn] = 0;
02672         /* bigdivrem_restoring will not modify y.
02673          * So use yds directly.  */
02674         yyds = (BDIGIT *)yds;
02675     }
02676 
02677     bigdivrem_restoring(zds, zn, yyds, yn);
02678 
02679     if (rds) {
02680         if (shift)
02681             bary_small_rshift(rds, zds, yn, shift, 0);
02682         else
02683             MEMCPY(rds, zds, BDIGIT, yn);
02684         BDIGITS_ZERO(rds+yn, rn-yn);
02685     }
02686 
02687     if (qds) {
02688         size_t j = zn - yn;
02689         MEMMOVE(qds, zds+yn, BDIGIT, j);
02690         BDIGITS_ZERO(qds+j, qn-j);
02691     }
02692 
02693     if (tmpyz)
02694         ALLOCV_END(tmpyz);
02695 }
02696 
02697 VALUE
02698 rb_big_divrem_normal(VALUE x, VALUE y)
02699 {
02700     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), qn, rn;
02701     BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
02702     VALUE q, r;
02703 
02704     BARY_TRUNC(yds, yn);
02705     if (yn == 0)
02706         rb_num_zerodiv();
02707     BARY_TRUNC(xds, xn);
02708 
02709     if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
02710         return rb_assoc_new(LONG2FIX(0), x);
02711 
02712     qn = xn + BIGDIVREM_EXTRA_WORDS;
02713     q = bignew(qn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02714     qds = BDIGITS(q);
02715 
02716     rn = yn;
02717     r = bignew(rn, RBIGNUM_SIGN(x));
02718     rds = BDIGITS(r);
02719 
02720     bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
02721 
02722     bigtrunc(q);
02723     bigtrunc(r);
02724 
02725     RB_GC_GUARD(x);
02726     RB_GC_GUARD(y);
02727 
02728     return rb_assoc_new(q, r);
02729 }
02730 
02731 #ifdef USE_GMP
02732 static void
02733 bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02734 {
02735     const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGITS)*CHAR_BIT;
02736     mpz_t x, y, q, r;
02737     size_t count;
02738 
02739     assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1]));
02740     assert(qds ? (xn - yn + 1) <= qn : 1);
02741     assert(rds ? yn <= rn : 1);
02742     assert(qds || rds);
02743 
02744     mpz_init(x);
02745     mpz_init(y);
02746     if (qds) mpz_init(q);
02747     if (rds) mpz_init(r);
02748 
02749     mpz_import(x, xn, -1, sizeof(BDIGIT), 0, nails, xds);
02750     mpz_import(y, yn, -1, sizeof(BDIGIT), 0, nails, yds);
02751 
02752     if (!rds) {
02753         mpz_fdiv_q(q, x, y);
02754     }
02755     else if (!qds) {
02756         mpz_fdiv_r(r, x, y);
02757     }
02758     else {
02759         mpz_fdiv_qr(q, r, x, y);
02760     }
02761 
02762     mpz_clear(x);
02763     mpz_clear(y);
02764 
02765     if (qds) {
02766         mpz_export(qds, &count, -1, sizeof(BDIGIT), 0, nails, q);
02767         BDIGITS_ZERO(qds+count, qn-count);
02768         mpz_clear(q);
02769     }
02770 
02771     if (rds) {
02772         mpz_export(rds, &count, -1, sizeof(BDIGIT), 0, nails, r);
02773         BDIGITS_ZERO(rds+count, rn-count);
02774         mpz_clear(r);
02775     }
02776 }
02777 
02778 VALUE
02779 rb_big_divrem_gmp(VALUE x, VALUE y)
02780 {
02781     size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), qn, rn;
02782     BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds;
02783     VALUE q, r;
02784 
02785     BARY_TRUNC(yds, yn);
02786     if (yn == 0)
02787         rb_num_zerodiv();
02788     BARY_TRUNC(xds, xn);
02789 
02790     if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1]))
02791         return rb_assoc_new(LONG2FIX(0), x);
02792 
02793     qn = xn - yn + 1;
02794     q = bignew(qn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
02795     qds = BDIGITS(q);
02796 
02797     rn = yn;
02798     r = bignew(rn, RBIGNUM_SIGN(x));
02799     rds = BDIGITS(r);
02800 
02801     bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
02802 
02803     bigtrunc(q);
02804     bigtrunc(r);
02805 
02806     RB_GC_GUARD(x);
02807     RB_GC_GUARD(y);
02808 
02809     return rb_assoc_new(q, r);
02810 }
02811 #endif
02812 
02813 static void
02814 bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02815 {
02816 #ifdef USE_GMP
02817     if (GMP_DIV_DIGITS < xn) {
02818         bary_divmod_gmp(qds, qn, rds, rn, xds, xn, yds, yn);
02819         return;
02820     }
02821 #endif
02822     bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn);
02823 }
02824 
02825 static void
02826 bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)
02827 {
02828     assert(xn <= qn);
02829     assert(yn <= rn);
02830 
02831     BARY_TRUNC(yds, yn);
02832     if (yn == 0)
02833         rb_num_zerodiv();
02834 
02835     BARY_TRUNC(xds, xn);
02836     if (xn == 0) {
02837         BDIGITS_ZERO(qds, qn);
02838         BDIGITS_ZERO(rds, rn);
02839         return;
02840     }
02841 
02842     if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
02843         MEMCPY(rds, xds, BDIGIT, xn);
02844         BDIGITS_ZERO(rds+xn, rn-xn);
02845         BDIGITS_ZERO(qds, qn);
02846     }
02847     else if (yn == 1) {
02848         MEMCPY(qds, xds, BDIGIT, xn);
02849         BDIGITS_ZERO(qds+xn, qn-xn);
02850         rds[0] = bigdivrem_single(qds, xds, xn, yds[0]);
02851         BDIGITS_ZERO(rds+1, rn-1);
02852     }
02853     else if (xn == 2 && yn == 2) {
02854         BDIGIT_DBL x = bary2bdigitdbl(xds, 2);
02855         BDIGIT_DBL y = bary2bdigitdbl(yds, 2);
02856         BDIGIT_DBL q = x / y;
02857         BDIGIT_DBL r = x % y;
02858         qds[0] = BIGLO(q);
02859         qds[1] = BIGLO(BIGDN(q));
02860         BDIGITS_ZERO(qds+2, qn-2);
02861         rds[0] = BIGLO(r);
02862         rds[1] = BIGLO(BIGDN(r));
02863         BDIGITS_ZERO(rds+2, rn-2);
02864     }
02865     else {
02866         bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
02867     }
02868 }
02869 
02870 
02871 #define BIGNUM_DEBUG 0
02872 #if BIGNUM_DEBUG
02873 #define ON_DEBUG(x) do { x; } while (0)
02874 static void
02875 dump_bignum(VALUE x)
02876 {
02877     long i;
02878     printf("%c0x0", RBIGNUM_SIGN(x) ? '+' : '-');
02879     for (i = RBIGNUM_LEN(x); i--; ) {
02880         printf("_%0*"PRIxBDIGIT, SIZEOF_BDIGITS*2, BDIGITS(x)[i]);
02881     }
02882     printf(", len=%lu", RBIGNUM_LEN(x));
02883     puts("");
02884 }
02885 
02886 static VALUE
02887 rb_big_dump(VALUE x)
02888 {
02889     dump_bignum(x);
02890     return x;
02891 }
02892 #else
02893 #define ON_DEBUG(x)
02894 #endif
02895 
02896 static int
02897 bigzero_p(VALUE x)
02898 {
02899     return bary_zero_p(BDIGITS(x), RBIGNUM_LEN(x));
02900 }
02901 
02902 int
02903 rb_bigzero_p(VALUE x)
02904 {
02905     return BIGZEROP(x);
02906 }
02907 
02908 int
02909 rb_cmpint(VALUE val, VALUE a, VALUE b)
02910 {
02911     if (NIL_P(val)) {
02912         rb_cmperr(a, b);
02913     }
02914     if (FIXNUM_P(val)) {
02915         long l = FIX2LONG(val);
02916         if (l > 0) return 1;
02917         if (l < 0) return -1;
02918         return 0;
02919     }
02920     if (RB_BIGNUM_TYPE_P(val)) {
02921         if (BIGZEROP(val)) return 0;
02922         if (RBIGNUM_SIGN(val)) return 1;
02923         return -1;
02924     }
02925     if (RTEST(rb_funcall(val, '>', 1, INT2FIX(0)))) return 1;
02926     if (RTEST(rb_funcall(val, '<', 1, INT2FIX(0)))) return -1;
02927     return 0;
02928 }
02929 
02930 #define RBIGNUM_SET_LEN(b,l) \
02931     ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
02932      (void)(RBASIC(b)->flags = \
02933             (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
02934             ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
02935      (void)(RBIGNUM(b)->as.heap.len = (l)))
02936 
02937 static void
02938 rb_big_realloc(VALUE big, long len)
02939 {
02940     BDIGIT *ds;
02941     if (RBASIC(big)->flags & RBIGNUM_EMBED_FLAG) {
02942         if (RBIGNUM_EMBED_LEN_MAX < len) {
02943             ds = ALLOC_N(BDIGIT, len);
02944             MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, RBIGNUM_EMBED_LEN_MAX);
02945             RBIGNUM(big)->as.heap.len = RBIGNUM_LEN(big);
02946             RBIGNUM(big)->as.heap.digits = ds;
02947             RBASIC(big)->flags &= ~RBIGNUM_EMBED_FLAG;
02948         }
02949     }
02950     else {
02951         if (len <= RBIGNUM_EMBED_LEN_MAX) {
02952             ds = RBIGNUM(big)->as.heap.digits;
02953             RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
02954             RBIGNUM_SET_LEN(big, len);
02955             (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
02956             if (ds) {
02957                 MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
02958                 xfree(ds);
02959             }
02960         }
02961         else {
02962             if (RBIGNUM_LEN(big) == 0) {
02963                 RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
02964             }
02965             else {
02966                 REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
02967             }
02968         }
02969     }
02970 }
02971 
02972 void
02973 rb_big_resize(VALUE big, long len)
02974 {
02975     rb_big_realloc(big, len);
02976     RBIGNUM_SET_LEN(big, len);
02977 }
02978 
02979 static VALUE
02980 bignew_1(VALUE klass, long len, int sign)
02981 {
02982     NEWOBJ_OF(big, struct RBignum, klass, T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0));
02983     RBIGNUM_SET_SIGN(big, sign?1:0);
02984     if (len <= RBIGNUM_EMBED_LEN_MAX) {
02985         RBASIC(big)->flags |= RBIGNUM_EMBED_FLAG;
02986         RBIGNUM_SET_LEN(big, len);
02987         (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, sizeof(RBIGNUM(big)->as.ary));
02988     }
02989     else {
02990         RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
02991         RBIGNUM(big)->as.heap.len = len;
02992     }
02993     OBJ_FREEZE(big);
02994     return (VALUE)big;
02995 }
02996 
02997 VALUE
02998 rb_big_new(long len, int sign)
02999 {
03000     return bignew(len, sign != 0);
03001 }
03002 
03003 VALUE
03004 rb_big_clone(VALUE x)
03005 {
03006     long len = RBIGNUM_LEN(x);
03007     VALUE z = bignew_1(CLASS_OF(x), len, RBIGNUM_SIGN(x));
03008 
03009     MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, len);
03010     return z;
03011 }
03012 
03013 static void
03014 big_extend_carry(VALUE x)
03015 {
03016     rb_big_resize(x, RBIGNUM_LEN(x)+1);
03017     BDIGITS(x)[RBIGNUM_LEN(x)-1] = 1;
03018 }
03019 
03020 /* modify a bignum by 2's complement */
03021 static void
03022 get2comp(VALUE x)
03023 {
03024     long i = RBIGNUM_LEN(x);
03025     BDIGIT *ds = BDIGITS(x);
03026 
03027     if (bary_2comp(ds, i)) {
03028         big_extend_carry(x);
03029     }
03030 }
03031 
03032 void
03033 rb_big_2comp(VALUE x)                   /* get 2's complement */
03034 {
03035     get2comp(x);
03036 }
03037 
03038 static BDIGIT
03039 abs2twocomp(VALUE *xp, long *n_ret)
03040 {
03041     VALUE x = *xp;
03042     long n = RBIGNUM_LEN(x);
03043     BDIGIT *ds = BDIGITS(x);
03044     BDIGIT hibits = 0;
03045 
03046     BARY_TRUNC(ds, n);
03047 
03048     if (n != 0 && RBIGNUM_NEGATIVE_P(x)) {
03049         VALUE z = bignew_1(CLASS_OF(x), n, 0);
03050         MEMCPY(BDIGITS(z), ds, BDIGIT, n);
03051         bary_2comp(BDIGITS(z), n);
03052         hibits = BDIGMAX;
03053         *xp = z;
03054     }
03055     *n_ret = n;
03056     return hibits;
03057 }
03058 
03059 static void
03060 twocomp2abs_bang(VALUE x, int hibits)
03061 {
03062     RBIGNUM_SET_SIGN(x, !hibits);
03063     if (hibits) {
03064         get2comp(x);
03065     }
03066 }
03067 
03068 static inline VALUE
03069 bigtrunc(VALUE x)
03070 {
03071     long len = RBIGNUM_LEN(x);
03072     BDIGIT *ds = BDIGITS(x);
03073 
03074     if (len == 0) return x;
03075     while (--len && !ds[len]);
03076     if (RBIGNUM_LEN(x) > len+1) {
03077         rb_big_resize(x, len+1);
03078     }
03079     return x;
03080 }
03081 
03082 static inline VALUE
03083 bigfixize(VALUE x)
03084 {
03085     size_t n = RBIGNUM_LEN(x);
03086     BDIGIT *ds = BDIGITS(x);
03087 #if SIZEOF_BDIGITS < SIZEOF_LONG
03088     unsigned long u;
03089 #else
03090     BDIGIT u;
03091 #endif
03092 
03093     BARY_TRUNC(ds, n);
03094 
03095     if (n == 0) return INT2FIX(0);
03096 
03097 #if SIZEOF_BDIGITS < SIZEOF_LONG
03098     if (sizeof(long)/SIZEOF_BDIGITS < n)
03099         goto return_big;
03100     else {
03101         int i = (int)n;
03102         u = 0;
03103         while (i--) {
03104             u = (unsigned long)(BIGUP(u) + ds[i]);
03105         }
03106     }
03107 #else /* SIZEOF_BDIGITS >= SIZEOF_LONG */
03108     if (1 < n)
03109         goto return_big;
03110     else
03111         u = ds[0];
03112 #endif
03113 
03114     if (RBIGNUM_POSITIVE_P(x)) {
03115         if (POSFIXABLE(u)) return LONG2FIX((long)u);
03116     }
03117     else {
03118         if (u <= -FIXNUM_MIN) return LONG2FIX(-(long)u);
03119     }
03120 
03121   return_big:
03122     rb_big_resize(x, n);
03123     return x;
03124 }
03125 
03126 static VALUE
03127 bignorm(VALUE x)
03128 {
03129     if (RB_BIGNUM_TYPE_P(x)) {
03130         x = bigfixize(x);
03131     }
03132     return x;
03133 }
03134 
03135 VALUE
03136 rb_big_norm(VALUE x)
03137 {
03138     return bignorm(x);
03139 }
03140 
03141 VALUE
03142 rb_uint2big(VALUE n)
03143 {
03144     long i;
03145     VALUE big = bignew(bdigit_roomof(SIZEOF_VALUE), 1);
03146     BDIGIT *digits = BDIGITS(big);
03147 
03148 #if SIZEOF_BDIGITS >= SIZEOF_VALUE
03149     digits[0] = n;
03150 #else
03151     for (i = 0; i < bdigit_roomof(SIZEOF_VALUE); i++) {
03152         digits[i] = BIGLO(n);
03153         n = BIGDN(n);
03154     }
03155 #endif
03156 
03157     i = bdigit_roomof(SIZEOF_VALUE);
03158     while (--i && !digits[i]) ;
03159     RBIGNUM_SET_LEN(big, i+1);
03160     return big;
03161 }
03162 
03163 VALUE
03164 rb_int2big(SIGNED_VALUE n)
03165 {
03166     long neg = 0;
03167     VALUE u;
03168     VALUE big;
03169 
03170     if (n < 0) {
03171         u = 1 + (VALUE)(-(n + 1)); /* u = -n avoiding overflow */
03172         neg = 1;
03173     }
03174     else {
03175         u = n;
03176     }
03177     big = rb_uint2big(u);
03178     if (neg) {
03179         RBIGNUM_SET_SIGN(big, 0);
03180     }
03181     return big;
03182 }
03183 
03184 VALUE
03185 rb_uint2inum(VALUE n)
03186 {
03187     if (POSFIXABLE(n)) return LONG2FIX(n);
03188     return rb_uint2big(n);
03189 }
03190 
03191 VALUE
03192 rb_int2inum(SIGNED_VALUE n)
03193 {
03194     if (FIXABLE(n)) return LONG2FIX(n);
03195     return rb_int2big(n);
03196 }
03197 
03198 void
03199 rb_big_pack(VALUE val, unsigned long *buf, long num_longs)
03200 {
03201     rb_integer_pack(val, buf, num_longs, sizeof(long), 0,
03202             INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
03203             INTEGER_PACK_2COMP);
03204 }
03205 
03206 VALUE
03207 rb_big_unpack(unsigned long *buf, long num_longs)
03208 {
03209     return rb_integer_unpack(buf, num_longs, sizeof(long), 0,
03210             INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
03211             INTEGER_PACK_2COMP);
03212 }
03213 
03214 /*
03215  * Calculate the number of bytes to be required to represent
03216  * the absolute value of the integer given as _val_.
03217  *
03218  * [val] an integer.
03219  * [nlz_bits_ret] number of leading zero bits in the most significant byte is returned if not NULL.
03220  *
03221  * This function returns ((val_numbits * CHAR_BIT + CHAR_BIT - 1) / CHAR_BIT)
03222  * where val_numbits is the number of bits of abs(val).
03223  * This function should not overflow.
03224  *
03225  * If nlz_bits_ret is not NULL,
03226  * (return_value * CHAR_BIT - val_numbits) is stored in *nlz_bits_ret.
03227  * In this case, 0 <= *nlz_bits_ret < CHAR_BIT.
03228  *
03229  */
03230 size_t
03231 rb_absint_size(VALUE val, int *nlz_bits_ret)
03232 {
03233     BDIGIT *dp;
03234     BDIGIT *de;
03235     BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
03236 
03237     int num_leading_zeros;
03238 
03239     val = rb_to_int(val);
03240 
03241     if (FIXNUM_P(val)) {
03242         long v = FIX2LONG(val);
03243         if (v < 0) {
03244             v = -v;
03245         }
03246 #if SIZEOF_BDIGITS >= SIZEOF_LONG
03247         fixbuf[0] = v;
03248 #else
03249         {
03250             int i;
03251             for (i = 0; i < numberof(fixbuf); i++) {
03252                 fixbuf[i] = BIGLO(v);
03253                 v = BIGDN(v);
03254             }
03255         }
03256 #endif
03257         dp = fixbuf;
03258         de = fixbuf + numberof(fixbuf);
03259     }
03260     else {
03261         dp = BDIGITS(val);
03262         de = dp + RBIGNUM_LEN(val);
03263     }
03264     while (dp < de && de[-1] == 0)
03265         de--;
03266     if (dp == de) {
03267         if (nlz_bits_ret)
03268             *nlz_bits_ret = 0;
03269         return 0;
03270     }
03271     num_leading_zeros = nlz(de[-1]);
03272     if (nlz_bits_ret)
03273         *nlz_bits_ret = num_leading_zeros % CHAR_BIT;
03274     return (de - dp) * SIZEOF_BDIGITS - num_leading_zeros / CHAR_BIT;
03275 }
03276 
03277 static size_t
03278 absint_numwords_small(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
03279 {
03280     size_t val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte;
03281     size_t div = val_numbits / word_numbits;
03282     size_t mod = val_numbits % word_numbits;
03283     size_t numwords;
03284     size_t nlz_bits;
03285     numwords = mod == 0 ? div : div + 1;
03286     nlz_bits = mod == 0 ? 0 : word_numbits - mod;
03287     *nlz_bits_ret = nlz_bits;
03288     return numwords;
03289 }
03290 
03291 static size_t
03292 absint_numwords_generic(size_t numbytes, int nlz_bits_in_msbyte, size_t word_numbits, size_t *nlz_bits_ret)
03293 {
03294     static const BDIGIT char_bit[1] = { CHAR_BIT };
03295     BDIGIT numbytes_bary[bdigit_roomof(sizeof(numbytes))];
03296     BDIGIT val_numbits_bary[bdigit_roomof(sizeof(numbytes) + 1)];
03297     BDIGIT nlz_bits_in_msbyte_bary[1];
03298     BDIGIT word_numbits_bary[bdigit_roomof(sizeof(word_numbits))];
03299     BDIGIT div_bary[numberof(val_numbits_bary) + BIGDIVREM_EXTRA_WORDS];
03300     BDIGIT mod_bary[numberof(word_numbits_bary)];
03301     BDIGIT one[1] = { 1 };
03302     size_t nlz_bits;
03303     size_t mod;
03304     int sign;
03305     size_t numwords;
03306 
03307     nlz_bits_in_msbyte_bary[0] = nlz_bits_in_msbyte;
03308 
03309     /*
03310      * val_numbits = numbytes * CHAR_BIT - nlz_bits_in_msbyte
03311      * div, mod = val_numbits.divmod(word_numbits)
03312      * numwords = mod == 0 ? div : div + 1
03313      * nlz_bits = mod == 0 ? 0 : word_numbits - mod
03314      */
03315 
03316     bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
03317         INTEGER_PACK_NATIVE_BYTE_ORDER);
03318     BARY_SHORT_MUL(val_numbits_bary, numbytes_bary, char_bit);
03319     if (nlz_bits_in_msbyte)
03320         BARY_SUB(val_numbits_bary, val_numbits_bary, nlz_bits_in_msbyte_bary);
03321     bary_unpack(BARY_ARGS(word_numbits_bary), &word_numbits, 1, sizeof(word_numbits), 0,
03322         INTEGER_PACK_NATIVE_BYTE_ORDER);
03323     BARY_DIVMOD(div_bary, mod_bary, val_numbits_bary, word_numbits_bary);
03324     if (BARY_ZERO_P(mod_bary)) {
03325         nlz_bits = 0;
03326     }
03327     else {
03328         BARY_ADD(div_bary, div_bary, one);
03329         bary_pack(+1, BARY_ARGS(mod_bary), &mod, 1, sizeof(mod), 0,
03330             INTEGER_PACK_NATIVE_BYTE_ORDER);
03331         nlz_bits = word_numbits - mod;
03332     }
03333     sign = bary_pack(+1, BARY_ARGS(div_bary), &numwords, 1, sizeof(numwords), 0,
03334         INTEGER_PACK_NATIVE_BYTE_ORDER);
03335 
03336     if (sign == 2) {
03337 #if defined __GNUC__ && (__GNUC__ == 4 && __GNUC_MINOR__ == 4)
03338         *nlz_bits_ret = 0;
03339 #endif
03340         return (size_t)-1;
03341     }
03342     *nlz_bits_ret = nlz_bits;
03343     return numwords;
03344 }
03345 
03346 /*
03347  * Calculate the number of words to be required to represent
03348  * the absolute value of the integer given as _val_.
03349  *
03350  * [val] an integer.
03351  * [word_numbits] number of bits in a word.
03352  * [nlz_bits_ret] number of leading zero bits in the most significant word is returned if not NULL.
03353  *
03354  * This function returns ((val_numbits * CHAR_BIT + word_numbits - 1) / word_numbits)
03355  * where val_numbits is the number of bits of abs(val).
03356  *
03357  * This function can overflow.
03358  * When overflow occur, (size_t)-1 is returned.
03359  *
03360  * If nlz_bits_ret is not NULL and overflow is not occur,
03361  * (return_value * word_numbits - val_numbits) is stored in *nlz_bits_ret.
03362  * In this case, 0 <= *nlz_bits_ret < word_numbits.
03363  *
03364  */
03365 size_t
03366 rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret)
03367 {
03368     size_t numbytes;
03369     int nlz_bits_in_msbyte;
03370     size_t numwords;
03371     size_t nlz_bits;
03372 
03373     if (word_numbits == 0)
03374         return (size_t)-1;
03375 
03376     numbytes = rb_absint_size(val, &nlz_bits_in_msbyte);
03377 
03378     if (numbytes <= SIZE_MAX / CHAR_BIT) {
03379         numwords = absint_numwords_small(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
03380 #ifdef DEBUG_INTEGER_PACK
03381         {
03382             size_t numwords0, nlz_bits0;
03383             numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0);
03384             assert(numwords0 == numwords);
03385             assert(nlz_bits0 == nlz_bits);
03386         }
03387 #endif
03388     }
03389     else {
03390         numwords = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits);
03391     }
03392     if (numwords == (size_t)-1)
03393         return numwords;
03394 
03395     if (nlz_bits_ret)
03396         *nlz_bits_ret = nlz_bits;
03397 
03398     return numwords;
03399 }
03400 
03401 /* Test abs(val) consists only a bit or not.
03402  *
03403  * Returns 1 if abs(val) == 1 << n for some n >= 0.
03404  * Returns 0 otherwise.
03405  *
03406  * rb_absint_singlebit_p can be used to determine required buffer size
03407  * for rb_integer_pack used with INTEGER_PACK_2COMP (two's complement).
03408  *
03409  * Following example calculates number of bits required to
03410  * represent val in two's complement number, without sign bit.
03411  *
03412  *   size_t size;
03413  *   int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val);
03414  *   size = rb_absint_numwords(val, 1, NULL)
03415  *   if (size == (size_t)-1) ...overflow...
03416  *   if (neg && rb_absint_singlebit_p(val))
03417  *     size--;
03418  *
03419  * Following example calculates number of bytes required to
03420  * represent val in two's complement number, with sign bit.
03421  *
03422  *   size_t size;
03423  *   int neg = FIXNUM_P(val) ? FIX2LONG(val) < 0 : RBIGNUM_NEGATIVE_P(val);
03424  *   int nlz_bits;
03425  *   size = rb_absint_size(val, &nlz_bits);
03426  *   if (nlz_bits == 0 && !(neg && rb_absint_singlebit_p(val)))
03427  *     size++;
03428  */
03429 int
03430 rb_absint_singlebit_p(VALUE val)
03431 {
03432     BDIGIT *dp;
03433     BDIGIT *de;
03434     BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
03435     BDIGIT d;
03436 
03437     val = rb_to_int(val);
03438 
03439     if (FIXNUM_P(val)) {
03440         long v = FIX2LONG(val);
03441         if (v < 0) {
03442             v = -v;
03443         }
03444 #if SIZEOF_BDIGITS >= SIZEOF_LONG
03445         fixbuf[0] = v;
03446 #else
03447         {
03448             int i;
03449             for (i = 0; i < numberof(fixbuf); i++) {
03450                 fixbuf[i] = BIGLO(v);
03451                 v = BIGDN(v);
03452             }
03453         }
03454 #endif
03455         dp = fixbuf;
03456         de = fixbuf + numberof(fixbuf);
03457     }
03458     else {
03459         dp = BDIGITS(val);
03460         de = dp + RBIGNUM_LEN(val);
03461     }
03462     while (dp < de && de[-1] == 0)
03463         de--;
03464     while (dp < de && dp[0] == 0)
03465         dp++;
03466     if (dp == de) /* no bit set. */
03467         return 0;
03468     if (dp != de-1) /* two non-zero words. two bits set, at least. */
03469         return 0;
03470     d = *dp;
03471     return POW2_P(d);
03472 }
03473 
03474 
03475 /*
03476  * Export an integer into a buffer.
03477  *
03478  * This function fills the buffer specified by _words_ and _numwords_ as
03479  * val in the format specified by _wordsize_, _nails_ and _flags_.
03480  *
03481  * [val] Fixnum, Bignum or another integer like object which has to_int method.
03482  * [words] buffer to export abs(val).
03483  * [numwords] the size of given buffer as number of words.
03484  * [wordsize] the size of word as number of bytes.
03485  * [nails] number of padding bits in a word.
03486  *   Most significant nails bits of each word are filled by zero.
03487  * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
03488  *
03489  * flags:
03490  * [INTEGER_PACK_MSWORD_FIRST] Store the most significant word as the first word.
03491  * [INTEGER_PACK_LSWORD_FIRST] Store the least significant word as the first word.
03492  * [INTEGER_PACK_MSBYTE_FIRST] Store the most significant byte in a word as the first byte in the word.
03493  * [INTEGER_PACK_LSBYTE_FIRST] Store the least significant byte in a word as the first byte in the word.
03494  * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
03495  * [INTEGER_PACK_2COMP] Use 2's complement representation.
03496  * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
03497  * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
03498  * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
03499  *
03500  * This function fills the buffer specified by _words_
03501  * as abs(val) if INTEGER_PACK_2COMP is not specified in _flags_.
03502  * If INTEGER_PACK_2COMP is specified, 2's complement representation of val is
03503  * filled in the buffer.
03504  *
03505  * This function returns the signedness and overflow condition.
03506  * The overflow condition depends on INTEGER_PACK_2COMP.
03507  *
03508  * INTEGER_PACK_2COMP is not specified:
03509  *   -2 : negative overflow.  val <= -2**(numwords*(wordsize*CHAR_BIT-nails))
03510  *   -1 : negative without overflow.  -2**(numwords*(wordsize*CHAR_BIT-nails)) < val < 0
03511  *   0 : zero.  val == 0
03512  *   1 : positive without overflow.  0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
03513  *   2 : positive overflow.  2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
03514  *
03515  * INTEGER_PACK_2COMP is specified:
03516  *   -2 : negative overflow.  val < -2**(numwords*(wordsize*CHAR_BIT-nails))
03517  *   -1 : negative without overflow.  -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val < 0
03518  *   0 : zero.  val == 0
03519  *   1 : positive without overflow.  0 < val < 2**(numwords*(wordsize*CHAR_BIT-nails))
03520  *   2 : positive overflow.  2**(numwords*(wordsize*CHAR_BIT-nails)) <= val
03521  *
03522  * The value, -2**(numwords*(wordsize*CHAR_BIT-nails)), is representable
03523  * in 2's complement representation but not representable in absolute value.
03524  * So -1 is returned for the value if INTEGER_PACK_2COMP is specified
03525  * but returns -2 if INTEGER_PACK_2COMP is not specified.
03526  *
03527  * The least significant words are filled in the buffer when overflow occur.
03528  */
03529 
03530 int
03531 rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
03532 {
03533     int sign;
03534     BDIGIT *ds;
03535     size_t num_bdigits;
03536     BDIGIT fixbuf[bdigit_roomof(sizeof(long))];
03537 
03538     RB_GC_GUARD(val) = rb_to_int(val);
03539 
03540     if (FIXNUM_P(val)) {
03541         long v = FIX2LONG(val);
03542         if (v < 0) {
03543             sign = -1;
03544             v = -v;
03545         }
03546         else {
03547             sign = 1;
03548         }
03549 #if SIZEOF_BDIGITS >= SIZEOF_LONG
03550         fixbuf[0] = v;
03551 #else
03552         {
03553             int i;
03554             for (i = 0; i < numberof(fixbuf); i++) {
03555                 fixbuf[i] = BIGLO(v);
03556                 v = BIGDN(v);
03557             }
03558         }
03559 #endif
03560         ds = fixbuf;
03561         num_bdigits = numberof(fixbuf);
03562     }
03563     else {
03564         sign = RBIGNUM_POSITIVE_P(val) ? 1 : -1;
03565         ds = BDIGITS(val);
03566         num_bdigits = RBIGNUM_LEN(val);
03567     }
03568 
03569     return bary_pack(sign, ds, num_bdigits, words, numwords, wordsize, nails, flags);
03570 }
03571 
03572 /*
03573  * Import an integer into a buffer.
03574  *
03575  * [words] buffer to import.
03576  * [numwords] the size of given buffer as number of words.
03577  * [wordsize] the size of word as number of bytes.
03578  * [nails] number of padding bits in a word.
03579  *   Most significant nails bits of each word are ignored.
03580  * [flags] bitwise or of constants which name starts "INTEGER_PACK_".
03581  *
03582  * flags:
03583  * [INTEGER_PACK_MSWORD_FIRST] Interpret the first word as the most significant word.
03584  * [INTEGER_PACK_LSWORD_FIRST] Interpret the first word as the least significant word.
03585  * [INTEGER_PACK_MSBYTE_FIRST] Interpret the first byte in a word as the most significant byte in the word.
03586  * [INTEGER_PACK_LSBYTE_FIRST] Interpret the first byte in a word as the least significant byte in the word.
03587  * [INTEGER_PACK_NATIVE_BYTE_ORDER] INTEGER_PACK_MSBYTE_FIRST or INTEGER_PACK_LSBYTE_FIRST corresponding to the host's endian.
03588  * [INTEGER_PACK_2COMP] Use 2's complement representation.
03589  * [INTEGER_PACK_LITTLE_ENDIAN] Same as INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_LSBYTE_FIRST
03590  * [INTEGER_PACK_BIG_ENDIAN] Same as INTEGER_PACK_MSWORD_FIRST|INTEGER_PACK_MSBYTE_FIRST
03591  * [INTEGER_PACK_FORCE_BIGNUM] the result will be a Bignum
03592  *   even if it is representable as a Fixnum.
03593  * [INTEGER_PACK_NEGATIVE] Returns non-positive value.
03594  *   (Returns non-negative value if not specified.)
03595  * [INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION] Use generic implementation (for test and debug).
03596  *
03597  * This function returns the imported integer as Fixnum or Bignum.
03598  *
03599  * The range of the result value depends on INTEGER_PACK_2COMP and INTEGER_PACK_NEGATIVE.
03600  *
03601  * INTEGER_PACK_2COMP is not set:
03602  *   0 <= val < 2**(numwords*(wordsize*CHAR_BIT-nails)) if !INTEGER_PACK_NEGATIVE
03603  *   -2**(numwords*(wordsize*CHAR_BIT-nails)) < val <= 0 if INTEGER_PACK_NEGATIVE
03604  *
03605  * INTEGER_PACK_2COMP is set:
03606  *   -2**(numwords*(wordsize*CHAR_BIT-nails)-1) <= val <= 2**(numwords*(wordsize*CHAR_BIT-nails)-1)-1 if !INTEGER_PACK_NEGATIVE
03607  *   -2**(numwords*(wordsize*CHAR_BIT-nails)) <= val <= -1 if INTEGER_PACK_NEGATIVE
03608  *
03609  * INTEGER_PACK_2COMP without INTEGER_PACK_NEGATIVE means sign extension.
03610  * INTEGER_PACK_2COMP with INTEGER_PACK_NEGATIVE mean assuming the higher bits are 1.
03611  *
03612  * Note that this function returns 0 when numwords is zero and
03613  * INTEGER_PACK_2COMP is set but INTEGER_PACK_NEGATIVE is not set.
03614  */
03615 
03616 VALUE
03617 rb_integer_unpack(const void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
03618 {
03619     VALUE val;
03620     size_t num_bdigits;
03621     int sign;
03622     int nlp_bits;
03623     BDIGIT *ds;
03624     BDIGIT fixbuf[2] = { 0, 0 };
03625 
03626     validate_integer_pack_format(numwords, wordsize, nails, flags,
03627             INTEGER_PACK_MSWORD_FIRST|
03628             INTEGER_PACK_LSWORD_FIRST|
03629             INTEGER_PACK_MSBYTE_FIRST|
03630             INTEGER_PACK_LSBYTE_FIRST|
03631             INTEGER_PACK_NATIVE_BYTE_ORDER|
03632             INTEGER_PACK_2COMP|
03633             INTEGER_PACK_FORCE_BIGNUM|
03634             INTEGER_PACK_NEGATIVE|
03635             INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION);
03636 
03637     num_bdigits = integer_unpack_num_bdigits(numwords, wordsize, nails, &nlp_bits);
03638 
03639     if (LONG_MAX-1 < num_bdigits)
03640         rb_raise(rb_eArgError, "too big to unpack as an integer");
03641     if (num_bdigits <= numberof(fixbuf) && !(flags & INTEGER_PACK_FORCE_BIGNUM)) {
03642         val = Qfalse;
03643         ds = fixbuf;
03644     }
03645     else {
03646         val = bignew((long)num_bdigits, 0);
03647         ds = BDIGITS(val);
03648     }
03649     sign = bary_unpack_internal(ds, num_bdigits, words, numwords, wordsize, nails, flags, nlp_bits);
03650 
03651     if (sign == -2) {
03652         if (val) {
03653             big_extend_carry(val);
03654         }
03655         else if (num_bdigits == numberof(fixbuf)) {
03656             val = bignew((long)num_bdigits+1, 0);
03657             MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
03658             BDIGITS(val)[num_bdigits++] = 1;
03659         }
03660         else {
03661             ds[num_bdigits++] = 1;
03662         }
03663     }
03664 
03665     if (!val) {
03666         BDIGIT_DBL u = fixbuf[0] + BIGUP(fixbuf[1]);
03667         if (u == 0)
03668             return LONG2FIX(0);
03669         if (0 < sign && POSFIXABLE(u))
03670             return LONG2FIX(u);
03671         if (sign < 0 && BDIGIT_MSB(fixbuf[1]) == 0 &&
03672                 NEGFIXABLE(-(BDIGIT_DBL_SIGNED)u))
03673             return LONG2FIX(-(BDIGIT_DBL_SIGNED)u);
03674         val = bignew((long)num_bdigits, 0 <= sign);
03675         MEMCPY(BDIGITS(val), fixbuf, BDIGIT, num_bdigits);
03676     }
03677 
03678     if ((flags & INTEGER_PACK_FORCE_BIGNUM) && sign != 0 &&
03679         bary_zero_p(BDIGITS(val), RBIGNUM_LEN(val)))
03680         sign = 0;
03681     RBIGNUM_SET_SIGN(val, 0 <= sign);
03682 
03683     if (flags & INTEGER_PACK_FORCE_BIGNUM)
03684         return bigtrunc(val);
03685     return bignorm(val);
03686 }
03687 
03688 #define QUAD_SIZE 8
03689 
03690 void
03691 rb_quad_pack(char *buf, VALUE val)
03692 {
03693     rb_integer_pack(val, buf, 1, QUAD_SIZE, 0,
03694             INTEGER_PACK_NATIVE_BYTE_ORDER|
03695             INTEGER_PACK_2COMP);
03696 }
03697 
03698 VALUE
03699 rb_quad_unpack(const char *buf, int signed_p)
03700 {
03701     return rb_integer_unpack(buf, 1, QUAD_SIZE, 0,
03702             INTEGER_PACK_NATIVE_BYTE_ORDER|
03703             (signed_p ? INTEGER_PACK_2COMP : 0));
03704 }
03705 
03706 #define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
03707 
03708 static void
03709 str2big_scan_digits(const char *s, const char *str, int base, int badcheck, size_t *num_digits_p, size_t *len_p)
03710 {
03711     char nondigit = 0;
03712     size_t num_digits = 0;
03713     const char *digits_start = str;
03714     const char *digits_end = str;
03715 
03716     int c;
03717 
03718     if (badcheck && *str == '_') goto bad;
03719 
03720     while ((c = *str++) != 0) {
03721         if (c == '_') {
03722             if (nondigit) {
03723                 if (badcheck) goto bad;
03724                 break;
03725             }
03726             nondigit = (char) c;
03727             continue;
03728         }
03729         else if ((c = conv_digit(c)) < 0) {
03730             break;
03731         }
03732         if (c >= base) break;
03733         nondigit = 0;
03734         num_digits++;
03735         digits_end = str;
03736     }
03737     if (badcheck) {
03738         str--;
03739         if (s+1 < str && str[-1] == '_') goto bad;
03740         while (*str && ISSPACE(*str)) str++;
03741         if (*str) {
03742           bad:
03743             rb_invalid_str(s, "Integer()");
03744         }
03745     }
03746     *num_digits_p = num_digits;
03747     *len_p = digits_end - digits_start;
03748 }
03749 
03750 static VALUE
03751 str2big_poweroftwo(
03752     int sign,
03753     const char *digits_start,
03754     const char *digits_end,
03755     size_t num_digits,
03756     int bits_per_digit)
03757 {
03758     BDIGIT *dp;
03759     BDIGIT_DBL dd;
03760     int numbits;
03761 
03762     size_t num_bdigits;
03763     const char *p;
03764     int c;
03765     VALUE z;
03766 
03767     num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
03768     z = bignew(num_bdigits, sign);
03769     dp = BDIGITS(z);
03770     dd = 0;
03771     numbits = 0;
03772     for (p = digits_end; digits_start < p; p--) {
03773         if ((c = conv_digit(p[-1])) < 0)
03774             continue;
03775         dd |= (BDIGIT_DBL)c << numbits;
03776         numbits += bits_per_digit;
03777         if (BITSPERDIG <= numbits) {
03778             *dp++ = BIGLO(dd);
03779             dd = BIGDN(dd);
03780             numbits -= BITSPERDIG;
03781         }
03782     }
03783     if (numbits) {
03784         *dp++ = BIGLO(dd);
03785     }
03786     assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
03787 
03788     return z;
03789 }
03790 
03791 static VALUE
03792 str2big_normal(
03793     int sign,
03794     const char *digits_start,
03795     const char *digits_end,
03796     size_t num_bdigits,
03797     int base)
03798 {
03799     size_t blen = 1;
03800     BDIGIT *zds;
03801     BDIGIT_DBL num;
03802 
03803     size_t i;
03804     const char *p;
03805     int c;
03806     VALUE z;
03807 
03808     z = bignew(num_bdigits, sign);
03809     zds = BDIGITS(z);
03810     BDIGITS_ZERO(zds, num_bdigits);
03811 
03812     for (p = digits_start; p < digits_end; p++) {
03813         if ((c = conv_digit(*p)) < 0)
03814             continue;
03815         num = c;
03816         i = 0;
03817         for (;;) {
03818             while (i<blen) {
03819                 num += (BDIGIT_DBL)zds[i]*base;
03820                 zds[i++] = BIGLO(num);
03821                 num = BIGDN(num);
03822             }
03823             if (num) {
03824                 blen++;
03825                 continue;
03826             }
03827             break;
03828         }
03829         assert(blen <= num_bdigits);
03830     }
03831 
03832     return z;
03833 }
03834 
03835 static VALUE
03836 str2big_karatsuba(
03837     int sign,
03838     const char *digits_start,
03839     const char *digits_end,
03840     size_t num_digits,
03841     size_t num_bdigits,
03842     int digits_per_bdigits_dbl,
03843     int base)
03844 {
03845     VALUE powerv;
03846     size_t unit;
03847     VALUE tmpuv = 0;
03848     BDIGIT *uds, *vds, *tds;
03849     BDIGIT_DBL dd;
03850     BDIGIT_DBL current_base;
03851     int m;
03852     int power_level = 0;
03853 
03854     size_t i;
03855     const char *p;
03856     int c;
03857     VALUE z;
03858 
03859     uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
03860     vds = uds + num_bdigits;
03861 
03862     powerv = power_cache_get_power(base, power_level, NULL);
03863 
03864     i = 0;
03865     dd = 0;
03866     current_base = 1;
03867     m = digits_per_bdigits_dbl;
03868     if (num_digits < (size_t)m)
03869         m = (int)num_digits;
03870     for (p = digits_end; digits_start < p; p--) {
03871         if ((c = conv_digit(p[-1])) < 0)
03872             continue;
03873         dd = dd + c * current_base;
03874         current_base *= base;
03875         num_digits--;
03876         m--;
03877         if (m == 0) {
03878             uds[i++] = BIGLO(dd);
03879             uds[i++] = (BDIGIT)BIGDN(dd);
03880             dd = 0;
03881             m = digits_per_bdigits_dbl;
03882             if (num_digits < (size_t)m)
03883                 m = (int)num_digits;
03884             current_base = 1;
03885         }
03886     }
03887     assert(i == num_bdigits);
03888     for (unit = 2; unit < num_bdigits; unit *= 2) {
03889         for (i = 0; i < num_bdigits; i += unit*2) {
03890             if (2*unit <= num_bdigits - i) {
03891                 bary_mul(vds+i, unit*2, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, unit);
03892                 bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
03893             }
03894             else if (unit <= num_bdigits - i) {
03895                 bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
03896                 bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
03897             }
03898             else {
03899                 MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
03900             }
03901         }
03902         power_level++;
03903         powerv = power_cache_get_power(base, power_level, NULL);
03904         tds = vds;
03905         vds = uds;
03906         uds = tds;
03907     }
03908     BARY_TRUNC(uds, num_bdigits);
03909     z = bignew(num_bdigits, sign);
03910     MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
03911 
03912     if (tmpuv)
03913         ALLOCV_END(tmpuv);
03914 
03915     return z;
03916 }
03917 
03918 #ifdef USE_GMP
03919 static VALUE
03920 str2big_gmp(
03921     int sign,
03922     const char *digits_start,
03923     const char *digits_end,
03924     size_t num_digits,
03925     size_t num_bdigits,
03926     int base)
03927 {
03928     const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGITS)*CHAR_BIT;
03929     char *buf, *p;
03930     const char *q;
03931     VALUE tmps;
03932     mpz_t mz;
03933     VALUE z;
03934     BDIGIT *zds;
03935     size_t zn, count;
03936 
03937     buf = ALLOCV_N(char, tmps, num_digits+1);
03938     p = buf;
03939     for (q = digits_start; q < digits_end; q++) {
03940         if (conv_digit(*q) < 0)
03941             continue;
03942         *p++ = *q;
03943     }
03944     *p = '\0';
03945 
03946     mpz_init(mz);
03947     mpz_set_str(mz, buf, base);
03948     zn = num_bdigits;
03949     z = bignew(zn, sign);
03950     zds = BDIGITS(z);
03951     mpz_export(BDIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
03952     BDIGITS_ZERO(zds+count, zn-count);
03953     mpz_clear(mz);
03954 
03955     if (tmps)
03956         ALLOCV_END(tmps);
03957 
03958     return z;
03959 }
03960 #endif
03961 
03962 VALUE
03963 rb_cstr_to_inum(const char *str, int base, int badcheck)
03964 {
03965     const char *s = str;
03966     char sign = 1;
03967     int c;
03968     VALUE z;
03969 
03970     int bits_per_digit;
03971 
03972     const char *digits_start, *digits_end;
03973     size_t num_digits;
03974     size_t num_bdigits;
03975     size_t len;
03976 
03977     if (!str) {
03978         if (badcheck) {
03979           bad:
03980             rb_invalid_str(s, "Integer()");
03981         }
03982         return INT2FIX(0);
03983     }
03984     while (ISSPACE(*str)) str++;
03985 
03986     if (str[0] == '+') {
03987         str++;
03988     }
03989     else if (str[0] == '-') {
03990         str++;
03991         sign = 0;
03992     }
03993     if (str[0] == '+' || str[0] == '-') {
03994         if (badcheck) goto bad;
03995         return INT2FIX(0);
03996     }
03997     if (base <= 0) {
03998         if (str[0] == '0') {
03999             switch (str[1]) {
04000               case 'x': case 'X':
04001                 base = 16;
04002                 str += 2;
04003                 break;
04004               case 'b': case 'B':
04005                 base = 2;
04006                 str += 2;
04007                 break;
04008               case 'o': case 'O':
04009                 base = 8;
04010                 str += 2;
04011                 break;
04012               case 'd': case 'D':
04013                 base = 10;
04014                 str += 2;
04015                 break;
04016               default:
04017                 base = 8;
04018             }
04019         }
04020         else if (base < -1) {
04021             base = -base;
04022         }
04023         else {
04024             base = 10;
04025         }
04026     }
04027     else if (base == 2) {
04028         if (str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
04029             str += 2;
04030         }
04031     }
04032     else if (base == 8) {
04033         if (str[0] == '0' && (str[1] == 'o'||str[1] == 'O')) {
04034             str += 2;
04035         }
04036     }
04037     else if (base == 10) {
04038         if (str[0] == '0' && (str[1] == 'd'||str[1] == 'D')) {
04039             str += 2;
04040         }
04041     }
04042     else if (base == 16) {
04043         if (str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
04044             str += 2;
04045         }
04046     }
04047     if (base < 2 || 36 < base) {
04048         rb_raise(rb_eArgError, "invalid radix %d", base);
04049     }
04050     if (*str == '0') {          /* squeeze preceding 0s */
04051         int us = 0;
04052         while ((c = *++str) == '0' || c == '_') {
04053             if (c == '_') {
04054                 if (++us >= 2)
04055                     break;
04056             } else
04057                 us = 0;
04058         }
04059         if (!(c = *str) || ISSPACE(c)) --str;
04060     }
04061     c = *str;
04062     c = conv_digit(c);
04063     if (c < 0 || c >= base) {
04064         if (badcheck) goto bad;
04065         return INT2FIX(0);
04066     }
04067 
04068     bits_per_digit = bit_length(base-1);
04069     if (bits_per_digit * strlen(str) <= sizeof(long) * CHAR_BIT) {
04070         char *end;
04071         unsigned long val = STRTOUL(str, &end, base);
04072 
04073         if (str < end && *end == '_') goto bigparse;
04074         if (badcheck) {
04075             if (end == str) goto bad; /* no number */
04076             while (*end && ISSPACE(*end)) end++;
04077             if (*end) goto bad;       /* trailing garbage */
04078         }
04079 
04080         if (POSFIXABLE(val)) {
04081             if (sign) return LONG2FIX(val);
04082             else {
04083                 long result = -(long)val;
04084                 return LONG2FIX(result);
04085             }
04086         }
04087         else {
04088             VALUE big = rb_uint2big(val);
04089             RBIGNUM_SET_SIGN(big, sign);
04090             return bignorm(big);
04091         }
04092     }
04093 
04094   bigparse:
04095     digits_start = str;
04096     str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
04097     digits_end = digits_start + len;
04098 
04099     if (POW2_P(base)) {
04100         z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
04101                 bits_per_digit);
04102     }
04103     else {
04104         int digits_per_bdigits_dbl;
04105         maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
04106         num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
04107 
04108 #ifdef USE_GMP
04109         if (GMP_STR2BIG_DIGITS < num_bdigits) {
04110             z = str2big_gmp(sign, digits_start, digits_end, num_digits,
04111                     num_bdigits, base);
04112         }
04113         else
04114 #endif
04115         if (num_bdigits < KARATSUBA_MUL_DIGITS) {
04116             z = str2big_normal(sign, digits_start, digits_end,
04117                     num_bdigits, base);
04118         }
04119         else {
04120             z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
04121                     num_bdigits, digits_per_bdigits_dbl, base);
04122         }
04123     }
04124 
04125     return bignorm(z);
04126 }
04127 
04128 VALUE
04129 rb_str_to_inum(VALUE str, int base, int badcheck)
04130 {
04131     char *s;
04132     long len;
04133     VALUE v = 0;
04134     VALUE ret;
04135 
04136     StringValue(str);
04137     rb_must_asciicompat(str);
04138     if (badcheck) {
04139         s = StringValueCStr(str);
04140     }
04141     else {
04142         s = RSTRING_PTR(str);
04143     }
04144     if (s) {
04145         len = RSTRING_LEN(str);
04146         if (s[len]) {           /* no sentinel somehow */
04147             char *p = ALLOCV(v, len+1);
04148 
04149             MEMCPY(p, s, char, len);
04150             p[len] = '\0';
04151             s = p;
04152         }
04153     }
04154     ret = rb_cstr_to_inum(s, base, badcheck);
04155     if (v)
04156         ALLOCV_END(v);
04157     return ret;
04158 }
04159 
04160 VALUE
04161 rb_str2big_poweroftwo(VALUE arg, int base, int badcheck)
04162 {
04163     int positive_p = 1;
04164     const char *s, *str;
04165     const char *digits_start, *digits_end;
04166     size_t num_digits;
04167     size_t len;
04168     VALUE z;
04169 
04170     if (base < 2 || 36 < base || !POW2_P(base)) {
04171         rb_raise(rb_eArgError, "invalid radix %d", base);
04172     }
04173 
04174     rb_must_asciicompat(arg);
04175     s = str = StringValueCStr(arg);
04176     if (*str == '-') {
04177         str++;
04178         positive_p = 0;
04179     }
04180 
04181     digits_start = str;
04182     str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
04183     digits_end = digits_start + len;
04184 
04185     z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits,
04186             bit_length(base-1));
04187 
04188     RB_GC_GUARD(arg);
04189 
04190     return bignorm(z);
04191 }
04192 
04193 VALUE
04194 rb_str2big_normal(VALUE arg, int base, int badcheck)
04195 {
04196     int positive_p = 1;
04197     const char *s, *str;
04198     const char *digits_start, *digits_end;
04199     size_t num_digits;
04200     size_t len;
04201     VALUE z;
04202 
04203     int digits_per_bdigits_dbl;
04204     size_t num_bdigits;
04205 
04206     if (base < 2 || 36 < base) {
04207         rb_raise(rb_eArgError, "invalid radix %d", base);
04208     }
04209 
04210     rb_must_asciicompat(arg);
04211     s = str = StringValueCStr(arg);
04212     if (*str == '-') {
04213         str++;
04214         positive_p = 0;
04215     }
04216 
04217     digits_start = str;
04218     str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
04219     digits_end = digits_start + len;
04220 
04221     maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
04222     num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
04223 
04224     z = str2big_normal(positive_p, digits_start, digits_end,
04225             num_bdigits, base);
04226 
04227     RB_GC_GUARD(arg);
04228 
04229     return bignorm(z);
04230 }
04231 
04232 VALUE
04233 rb_str2big_karatsuba(VALUE arg, int base, int badcheck)
04234 {
04235     int positive_p = 1;
04236     const char *s, *str;
04237     const char *digits_start, *digits_end;
04238     size_t num_digits;
04239     size_t len;
04240     VALUE z;
04241 
04242     int digits_per_bdigits_dbl;
04243     size_t num_bdigits;
04244 
04245     if (base < 2 || 36 < base) {
04246         rb_raise(rb_eArgError, "invalid radix %d", base);
04247     }
04248 
04249     rb_must_asciicompat(arg);
04250     s = str = StringValueCStr(arg);
04251     if (*str == '-') {
04252         str++;
04253         positive_p = 0;
04254     }
04255 
04256     digits_start = str;
04257     str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
04258     digits_end = digits_start + len;
04259 
04260     maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
04261     num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
04262 
04263     z = str2big_karatsuba(positive_p, digits_start, digits_end, num_digits,
04264             num_bdigits, digits_per_bdigits_dbl, base);
04265 
04266     RB_GC_GUARD(arg);
04267 
04268     return bignorm(z);
04269 }
04270 
04271 #ifdef USE_GMP
04272 VALUE
04273 rb_str2big_gmp(VALUE arg, int base, int badcheck)
04274 {
04275     int positive_p = 1;
04276     const char *s, *str;
04277     const char *digits_start, *digits_end;
04278     size_t num_digits;
04279     size_t len;
04280     VALUE z;
04281 
04282     int digits_per_bdigits_dbl;
04283     size_t num_bdigits;
04284 
04285     if (base < 2 || 36 < base) {
04286         rb_raise(rb_eArgError, "invalid radix %d", base);
04287     }
04288 
04289     rb_must_asciicompat(arg);
04290     s = str = StringValueCStr(arg);
04291     if (*str == '-') {
04292         str++;
04293         positive_p = 0;
04294     }
04295 
04296     digits_start = str;
04297     str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
04298     digits_end = digits_start + len;
04299 
04300     maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
04301     num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
04302 
04303     z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
04304 
04305     RB_GC_GUARD(arg);
04306 
04307     return bignorm(z);
04308 }
04309 #endif
04310 
04311 #if HAVE_LONG_LONG
04312 
04313 static VALUE
04314 rb_ull2big(unsigned LONG_LONG n)
04315 {
04316     long i;
04317     VALUE big = bignew(bdigit_roomof(SIZEOF_LONG_LONG), 1);
04318     BDIGIT *digits = BDIGITS(big);
04319 
04320 #if SIZEOF_BDIGITS >= SIZEOF_LONG_LONG
04321     digits[0] = n;
04322 #else
04323     for (i = 0; i < bdigit_roomof(SIZEOF_LONG_LONG); i++) {
04324         digits[i] = BIGLO(n);
04325         n = BIGDN(n);
04326     }
04327 #endif
04328 
04329     i = bdigit_roomof(SIZEOF_LONG_LONG);
04330     while (i-- && !digits[i]) ;
04331     RBIGNUM_SET_LEN(big, i+1);
04332     return big;
04333 }
04334 
04335 static VALUE
04336 rb_ll2big(LONG_LONG n)
04337 {
04338     long neg = 0;
04339     unsigned LONG_LONG u;
04340     VALUE big;
04341 
04342     if (n < 0) {
04343         u = 1 + (unsigned LONG_LONG)(-(n + 1)); /* u = -n avoiding overflow */
04344         neg = 1;
04345     }
04346     else {
04347         u = n;
04348     }
04349     big = rb_ull2big(u);
04350     if (neg) {
04351         RBIGNUM_SET_SIGN(big, 0);
04352     }
04353     return big;
04354 }
04355 
04356 VALUE
04357 rb_ull2inum(unsigned LONG_LONG n)
04358 {
04359     if (POSFIXABLE(n)) return LONG2FIX(n);
04360     return rb_ull2big(n);
04361 }
04362 
04363 VALUE
04364 rb_ll2inum(LONG_LONG n)
04365 {
04366     if (FIXABLE(n)) return LONG2FIX(n);
04367     return rb_ll2big(n);
04368 }
04369 
04370 #endif  /* HAVE_LONG_LONG */
04371 
04372 VALUE
04373 rb_cstr2inum(const char *str, int base)
04374 {
04375     return rb_cstr_to_inum(str, base, base==0);
04376 }
04377 
04378 VALUE
04379 rb_str2inum(VALUE str, int base)
04380 {
04381     return rb_str_to_inum(str, base, base==0);
04382 }
04383 
04384 static VALUE
04385 big_shift3(VALUE x, int lshift_p, size_t shift_numdigits, int shift_numbits)
04386 {
04387     BDIGIT *xds, *zds;
04388     long s1;
04389     int s2;
04390     VALUE z;
04391     long xn;
04392 
04393     if (lshift_p) {
04394         if (LONG_MAX < shift_numdigits) {
04395             rb_raise(rb_eArgError, "too big number");
04396         }
04397         s1 = shift_numdigits;
04398         s2 = shift_numbits;
04399         xn = RBIGNUM_LEN(x);
04400         z = bignew(xn+s1+1, RBIGNUM_SIGN(x));
04401         zds = BDIGITS(z);
04402         BDIGITS_ZERO(zds, s1);
04403         xds = BDIGITS(x);
04404         zds[xn+s1] = bary_small_lshift(zds+s1, xds, xn, s2);
04405     }
04406     else {
04407         long zn;
04408         BDIGIT hibitsx;
04409         if (LONG_MAX < shift_numdigits || (size_t)RBIGNUM_LEN(x) <= shift_numdigits) {
04410             if (RBIGNUM_POSITIVE_P(x) ||
04411                 bary_zero_p(BDIGITS(x), RBIGNUM_LEN(x)))
04412                 return INT2FIX(0);
04413             else
04414                 return INT2FIX(-1);
04415         }
04416         s1 = shift_numdigits;
04417         s2 = shift_numbits;
04418         hibitsx = abs2twocomp(&x, &xn);
04419         xds = BDIGITS(x);
04420         if (xn <= s1) {
04421             return hibitsx ? INT2FIX(-1) : INT2FIX(0);
04422         }
04423         zn = xn - s1;
04424         z = bignew(zn, 0);
04425         zds = BDIGITS(z);
04426         bary_small_rshift(zds, xds+s1, zn, s2, hibitsx != 0 ? BDIGMAX : 0);
04427         twocomp2abs_bang(z, hibitsx != 0);
04428     }
04429     RB_GC_GUARD(x);
04430     return z;
04431 }
04432 
04433 static VALUE
04434 big_shift2(VALUE x, int lshift_p, VALUE y)
04435 {
04436     int sign;
04437     size_t lens[2];
04438     size_t shift_numdigits;
04439     int shift_numbits;
04440 
04441     assert(POW2_P(CHAR_BIT));
04442     assert(POW2_P(BITSPERDIG));
04443 
04444     if (BIGZEROP(x))
04445         return INT2FIX(0);
04446     sign = rb_integer_pack(y, lens, numberof(lens), sizeof(size_t), 0,
04447         INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
04448     if (sign < 0) {
04449         lshift_p = !lshift_p;
04450         sign = -sign;
04451     }
04452     if (lshift_p) {
04453         if (1 < sign || CHAR_BIT <= lens[1])
04454             rb_raise(rb_eRangeError, "shift width too big");
04455     }
04456     else {
04457         if (1 < sign || CHAR_BIT <= lens[1])
04458             return RBIGNUM_POSITIVE_P(x) ? INT2FIX(0) : INT2FIX(-1);
04459     }
04460     shift_numbits = (int)(lens[0] & (BITSPERDIG-1));
04461     shift_numdigits = (lens[0] >> bit_length(BITSPERDIG-1)) |
04462       (lens[1] << (CHAR_BIT*SIZEOF_SIZE_T - bit_length(BITSPERDIG-1)));
04463     return big_shift3(x, lshift_p, shift_numdigits, shift_numbits);
04464 }
04465 
04466 static VALUE
04467 big_lshift(VALUE x, unsigned long shift)
04468 {
04469     long s1 = shift/BITSPERDIG;
04470     int s2 = (int)(shift%BITSPERDIG);
04471     return big_shift3(x, 1, s1, s2);
04472 }
04473 
04474 static VALUE
04475 big_rshift(VALUE x, unsigned long shift)
04476 {
04477     long s1 = shift/BITSPERDIG;
04478     int s2 = (int)(shift%BITSPERDIG);
04479     return big_shift3(x, 0, s1, s2);
04480 }
04481 
04482 #define MAX_BASE36_POWER_TABLE_ENTRIES (SIZEOF_SIZE_T * CHAR_BIT + 1)
04483 
04484 static VALUE base36_power_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
04485 static size_t base36_numdigits_cache[35][MAX_BASE36_POWER_TABLE_ENTRIES];
04486 
04487 static void
04488 power_cache_init(void)
04489 {
04490     int i, j;
04491     for (i = 0; i < 35; ++i) {
04492         for (j = 0; j < MAX_BASE36_POWER_TABLE_ENTRIES; ++j) {
04493             base36_power_cache[i][j] = Qnil;
04494         }
04495     }
04496 }
04497 
04498 static inline VALUE
04499 power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
04500 {
04501     /*
04502      * MAX_BASE36_POWER_TABLE_ENTRIES is big enough to that
04503      * base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1] fills whole memory.
04504      * So MAX_BASE36_POWER_TABLE_ENTRIES <= power_level is not possible to calculate.
04505      *
04506      * number-of-bytes =
04507      * log256(base36_power_cache[base][MAX_BASE36_POWER_TABLE_ENTRIES-1]) =
04508      * log256(maxpow_in_bdigit_dbl(base)**(2**(MAX_BASE36_POWER_TABLE_ENTRIES-1))) =
04509      * log256(maxpow_in_bdigit_dbl(base)**(2**(SIZEOF_SIZE_T*CHAR_BIT))) =
04510      * (2**(SIZEOF_SIZE_T*CHAR_BIT))*log256(maxpow_in_bdigit_dbl(base)) =
04511      * (256**SIZEOF_SIZE_T)*log256(maxpow_in_bdigit_dbl(base)) >
04512      * (256**SIZEOF_SIZE_T)*(sizeof(BDIGIT_DBL)-1) >
04513      * 256**SIZEOF_SIZE_T
04514      */
04515     if (MAX_BASE36_POWER_TABLE_ENTRIES <= power_level)
04516         rb_bug("too big power number requested: maxpow_in_bdigit_dbl(%d)**(2**%d)", base, power_level);
04517 
04518     if (NIL_P(base36_power_cache[base - 2][power_level])) {
04519         VALUE power;
04520         size_t numdigits;
04521         if (power_level == 0) {
04522             int numdigits0;
04523             BDIGIT_DBL dd = maxpow_in_bdigit_dbl(base, &numdigits0);
04524             power = bignew(2, 1);
04525             bdigitdbl2bary(BDIGITS(power), 2, dd);
04526             numdigits = numdigits0;
04527         }
04528         else {
04529             power = bigtrunc(bigsq(power_cache_get_power(base, power_level - 1, &numdigits)));
04530             numdigits *= 2;
04531         }
04532         rb_obj_hide(power);
04533         base36_power_cache[base - 2][power_level] = power;
04534         base36_numdigits_cache[base - 2][power_level] = numdigits;
04535         rb_gc_register_mark_object(power);
04536     }
04537     if (numdigits_ret)
04538         *numdigits_ret = base36_numdigits_cache[base - 2][power_level];
04539     return base36_power_cache[base - 2][power_level];
04540 }
04541 
04542 /*
04543  * deprecated.  (used only from deprecated rb_big2str0)
04544  *
04545  * big2str_muraken_find_n1
04546  *
04547  * Let a natural number x is given by:
04548  * x = 2^0 * x_0 + 2^1 * x_1 + ... + 2^(B*n_0 - 1) * x_{B*n_0 - 1},
04549  * where B is BITSPERDIG (i.e. BDIGITS*CHAR_BIT) and n_0 is
04550  * RBIGNUM_LEN(x).
04551  *
04552  * Now, we assume n_1 = min_n \{ n | 2^(B*n_0/2) <= b_1^(n_1) \}, so
04553  * it is realized that 2^(B*n_0) <= {b_1}^{2*n_1}, where b_1 is a
04554  * given radix number. And then, we have n_1 <= (B*n_0) /
04555  * (2*log_2(b_1)), therefore n_1 is given by ceil((B*n_0) /
04556  * (2*log_2(b_1))).
04557  */
04558 static long
04559 big2str_find_n1(VALUE x, int base)
04560 {
04561     static const double log_2[] = {
04562         1.0,              1.58496250072116, 2.0,
04563         2.32192809488736, 2.58496250072116, 2.8073549220576,
04564         3.0,              3.16992500144231, 3.32192809488736,
04565         3.4594316186373,  3.58496250072116, 3.70043971814109,
04566         3.8073549220576,  3.90689059560852, 4.0,
04567         4.08746284125034, 4.16992500144231, 4.24792751344359,
04568         4.32192809488736, 4.39231742277876, 4.4594316186373,
04569         4.52356195605701, 4.58496250072116, 4.64385618977472,
04570         4.70043971814109, 4.75488750216347, 4.8073549220576,
04571         4.85798099512757, 4.90689059560852, 4.95419631038688,
04572         5.0,              5.04439411935845, 5.08746284125034,
04573         5.12928301694497, 5.16992500144231
04574     };
04575     long bits;
04576 
04577     if (base < 2 || 36 < base)
04578         rb_bug("invalid radix %d", base);
04579 
04580     if (FIXNUM_P(x)) {
04581         bits = (SIZEOF_LONG*CHAR_BIT - 1)/2 + 1;
04582     }
04583     else if (BIGZEROP(x)) {
04584         return 0;
04585     }
04586     else if (RBIGNUM_LEN(x) >= LONG_MAX/BITSPERDIG) {
04587         rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
04588     }
04589     else {
04590         bits = BITSPERDIG*RBIGNUM_LEN(x);
04591     }
04592 
04593     /* @shyouhei note: vvvvvvvvvvvvv this cast is suspicious.  But I believe it is OK, because if that cast loses data, this x value is too big, and should have raised RangeError. */
04594     return (long)ceil(((double)bits)/log_2[base - 2]);
04595 }
04596 
04597 struct big2str_struct {
04598     int negative;
04599     int base;
04600     BDIGIT_DBL hbase2;
04601     int hbase2_numdigits;
04602     VALUE result;
04603     char *ptr;
04604 };
04605 
04606 static void
04607 big2str_alloc(struct big2str_struct *b2s, size_t len)
04608 {
04609     if (LONG_MAX-1 < len)
04610         rb_raise(rb_eArgError, "too big number");
04611     b2s->result = rb_usascii_str_new(0, (long)(len + 1)); /* plus one for sign */
04612     b2s->ptr = RSTRING_PTR(b2s->result);
04613     if (b2s->negative)
04614         *b2s->ptr++ = '-';
04615 }
04616 
04617 static void
04618 big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t taillen)
04619 {
04620     size_t j;
04621     BDIGIT_DBL num;
04622     char buf[SIZEOF_BDIGIT_DBL*CHAR_BIT], *p;
04623     int beginning = !b2s->ptr;
04624     size_t len = 0;
04625 
04626     assert(xn <= 2);
04627     num = bary2bdigitdbl(xds, xn);
04628 
04629     if (beginning) {
04630         if (num == 0)
04631             return;
04632         p = buf;
04633         j = sizeof(buf);
04634         do {
04635             p[--j] = ruby_digitmap[num % b2s->base];
04636             num /= b2s->base;
04637         } while (num);
04638         len = sizeof(buf) - j;
04639         big2str_alloc(b2s, len + taillen);
04640         MEMCPY(b2s->ptr, buf + j, char, len);
04641     }
04642     else {
04643         p = b2s->ptr;
04644         j = b2s->hbase2_numdigits;
04645         do {
04646             p[--j] = ruby_digitmap[num % b2s->base];
04647             num /= b2s->base;
04648         } while (j);
04649         len = b2s->hbase2_numdigits;
04650     }
04651     b2s->ptr += len;
04652 }
04653 
04654 static void
04655 big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn,
04656                   int power_level, size_t taillen)
04657 {
04658     VALUE b;
04659     size_t half_numdigits, lower_numdigits;
04660     int lower_power_level;
04661     size_t bn;
04662     const BDIGIT *bds;
04663     size_t len;
04664 
04665     /*
04666      * Precondition:
04667      * abs(x) < maxpow**(2**power_level)
04668      * where
04669      *   maxpow = maxpow_in_bdigit_dbl(base, &numdigits)
04670      *
04671      * This function generates sequence of zeros, and then stringized abs(x) into b2s->ptr.
04672      *
04673      * b2s->ptr can be NULL.
04674      * It is allocated when the first character is generated via big2str_alloc.
04675      *
04676      * The prefix zeros should be generated if and only if b2s->ptr is not NULL.
04677      * When the zeros are generated, the zeros and abs(x) consists
04678      * numdigits*(2**power_level) characters at total.
04679      *
04680      * Note:
04681      * power_cache_get_power(base, power_level, &len) may not be cached yet. It should not be called.
04682      * power_cache_get_power(base, power_level-1, &len) should be cached already if 0 <= power_level-1.
04683      */
04684 
04685     if (xn == 0 || bary_zero_p(xds, xn)) {
04686         if (b2s->ptr) {
04687             /* When x is zero, power_cache_get_power(base, power_level) should be cached already. */
04688             power_cache_get_power(b2s->base, power_level, &len);
04689             memset(b2s->ptr, '0', len);
04690             b2s->ptr += len;
04691         }
04692         return;
04693     }
04694 
04695     if (power_level == 0) {
04696         big2str_2bdigits(b2s, xds, xn, taillen);
04697         return;
04698     }
04699 
04700     lower_power_level = power_level-1;
04701     b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
04702     bn = RBIGNUM_LEN(b);
04703     bds = BDIGITS(b);
04704 
04705     half_numdigits = lower_numdigits;
04706 
04707     while (0 < lower_power_level &&
04708             (xn < bn ||
04709              (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
04710         lower_power_level--;
04711         b = power_cache_get_power(b2s->base, lower_power_level, &lower_numdigits);
04712         bn = RBIGNUM_LEN(b);
04713         bds = BDIGITS(b);
04714     }
04715 
04716     if (lower_power_level == 0 &&
04717             (xn < bn ||
04718              (xn == bn && bary_cmp(xds, xn, bds, bn) < 0))) {
04719         if (b2s->ptr) {
04720             len = half_numdigits * 2 - lower_numdigits;
04721             memset(b2s->ptr, '0', len);
04722             b2s->ptr += len;
04723         }
04724         big2str_2bdigits(b2s, xds, xn, taillen);
04725     }
04726     else {
04727         BDIGIT *qds, *rds;
04728         size_t qn, rn;
04729         BDIGIT *tds;
04730         int shift;
04731 
04732         if (lower_power_level != power_level-1 && b2s->ptr) {
04733             len = (half_numdigits - lower_numdigits) * 2;
04734             memset(b2s->ptr, '0', len);
04735             b2s->ptr += len;
04736         }
04737 
04738         shift = nlz(bds[bn-1]);
04739 
04740         qn = xn + BIGDIVREM_EXTRA_WORDS;
04741 
04742         if (shift == 0) {
04743             /* bigdivrem_restoring will not modify y.
04744              * So use bds directly.  */
04745             tds = (BDIGIT *)bds;
04746             xds[xn] = 0;
04747         }
04748         else {
04749             /* bigdivrem_restoring will modify y.
04750              * So use temporary buffer.  */
04751             tds = xds + qn;
04752             assert(qn + bn <= xn + wn);
04753             bary_small_lshift(tds, bds, bn, shift);
04754             xds[xn] = bary_small_lshift(xds, xds, xn, shift);
04755         }
04756 
04757         bigdivrem_restoring(xds, qn, tds, bn);
04758 
04759         rds = xds;
04760         rn = bn;
04761 
04762         qds = xds + bn;
04763         qn = qn - bn;
04764 
04765         if (shift) {
04766             bary_small_rshift(rds, rds, rn, shift, 0);
04767         }
04768 
04769         BARY_TRUNC(qds, qn);
04770         assert(qn <= bn);
04771         big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen);
04772         BARY_TRUNC(rds, rn);
04773         big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen);
04774     }
04775 }
04776 
04777 static VALUE
04778 big2str_base_poweroftwo(VALUE x, int base)
04779 {
04780     int word_numbits = ffs(base) - 1;
04781     size_t numwords;
04782     VALUE result;
04783     char *ptr;
04784     numwords = rb_absint_numwords(x, word_numbits, NULL);
04785     if (RBIGNUM_NEGATIVE_P(x)) {
04786         if (LONG_MAX-1 < numwords)
04787             rb_raise(rb_eArgError, "too big number");
04788         result = rb_usascii_str_new(0, 1+numwords);
04789         ptr = RSTRING_PTR(result);
04790         *ptr++ = RBIGNUM_POSITIVE_P(x) ? '+' : '-';
04791     }
04792     else {
04793         if (LONG_MAX < numwords)
04794             rb_raise(rb_eArgError, "too big number");
04795         result = rb_usascii_str_new(0, numwords);
04796         ptr = RSTRING_PTR(result);
04797     }
04798     rb_integer_pack(x, ptr, numwords, 1, CHAR_BIT-word_numbits,
04799                     INTEGER_PACK_BIG_ENDIAN);
04800     while (0 < numwords) {
04801         *ptr = ruby_digitmap[*(unsigned char *)ptr];
04802         ptr++;
04803         numwords--;
04804     }
04805     return result;
04806 }
04807 
04808 VALUE
04809 rb_big2str_poweroftwo(VALUE x, int base)
04810 {
04811     return big2str_base_poweroftwo(x, base);
04812 }
04813 
04814 static VALUE
04815 big2str_generic(VALUE x, int base)
04816 {
04817     BDIGIT *xds;
04818     size_t xn;
04819     struct big2str_struct b2s_data;
04820     int power_level;
04821     VALUE power;
04822 
04823     xds = BDIGITS(x);
04824     xn = RBIGNUM_LEN(x);
04825     BARY_TRUNC(xds, xn);
04826 
04827     if (xn == 0) {
04828         return rb_usascii_str_new2("0");
04829     }
04830 
04831     if (base < 2 || 36 < base)
04832         rb_raise(rb_eArgError, "invalid radix %d", base);
04833 
04834     if (xn >= LONG_MAX/BITSPERDIG) {
04835         rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
04836     }
04837 
04838     power_level = 0;
04839     power = power_cache_get_power(base, power_level, NULL);
04840     while (power_level < MAX_BASE36_POWER_TABLE_ENTRIES &&
04841            (size_t)RBIGNUM_LEN(power) <= (xn+1)/2) {
04842         power_level++;
04843         power = power_cache_get_power(base, power_level, NULL);
04844     }
04845     assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES);
04846 
04847     if ((size_t)RBIGNUM_LEN(power) <= xn) {
04848         /*
04849          * This increment guarantees x < power_cache_get_power(base, power_level)
04850          * without invoking it actually.
04851          * (power_cache_get_power(base, power_level) can be slow and not used
04852          * in big2str_karatsuba.)
04853          *
04854          * Although it is possible that x < power_cache_get_power(base, power_level-1),
04855          * it is no problem because big2str_karatsuba checks it and
04856          * doesn't affect the result when b2s_data.ptr is NULL.
04857          */
04858         power_level++;
04859     }
04860 
04861     b2s_data.negative = RBIGNUM_NEGATIVE_P(x);
04862     b2s_data.base = base;
04863     b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
04864 
04865     b2s_data.result = Qnil;
04866     b2s_data.ptr = NULL;
04867 
04868     if (power_level == 0) {
04869         big2str_2bdigits(&b2s_data, xds, xn, 0);
04870     }
04871     else {
04872         VALUE tmpw = 0;
04873         BDIGIT *wds;
04874         size_t wn;
04875         wn = power_level * BIGDIVREM_EXTRA_WORDS + RBIGNUM_LEN(power);
04876         wds = ALLOCV_N(BDIGIT, tmpw, xn + wn);
04877         MEMCPY(wds, xds, BDIGIT, xn);
04878         big2str_karatsuba(&b2s_data, wds, xn, wn, power_level, 0);
04879         if (tmpw)
04880             ALLOCV_END(tmpw);
04881     }
04882     RB_GC_GUARD(x);
04883 
04884     *b2s_data.ptr = '\0';
04885     rb_str_resize(b2s_data.result, (long)(b2s_data.ptr - RSTRING_PTR(b2s_data.result)));
04886 
04887     RB_GC_GUARD(x);
04888     return b2s_data.result;
04889 }
04890 
04891 VALUE
04892 rb_big2str_generic(VALUE x, int base)
04893 {
04894     return big2str_generic(x, base);
04895 }
04896 
04897 #ifdef USE_GMP
04898 VALUE
04899 big2str_gmp(VALUE x, int base)
04900 {
04901     const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGITS)*CHAR_BIT;
04902     mpz_t mx;
04903     size_t size;
04904     VALUE str;
04905     BDIGIT *xds = BDIGITS(x);
04906     size_t xn = RBIGNUM_LEN(x);
04907 
04908     mpz_init(mx);
04909     mpz_import(mx, xn, -1, sizeof(BDIGIT), 0, nails, xds);
04910 
04911     size = mpz_sizeinbase(mx, base);
04912 
04913     if (RBIGNUM_NEGATIVE_P(x)) {
04914         mpz_neg(mx, mx);
04915         str = rb_usascii_str_new(0, size+1);
04916     }
04917     else {
04918         str = rb_usascii_str_new(0, size);
04919     }
04920     mpz_get_str(RSTRING_PTR(str), base, mx);
04921     mpz_clear(mx);
04922 
04923     if (RSTRING_PTR(str)[RSTRING_LEN(str)-1] == '\0') {
04924         rb_str_set_len(str, RSTRING_LEN(str)-1);
04925     }
04926 
04927     RB_GC_GUARD(x);
04928     return str;
04929 }
04930 
04931 VALUE
04932 rb_big2str_gmp(VALUE x, int base)
04933 {
04934     return big2str_gmp(x, base);
04935 }
04936 #endif
04937 
04938 static VALUE
04939 rb_big2str1(VALUE x, int base)
04940 {
04941     BDIGIT *xds;
04942     size_t xn;
04943 
04944     if (FIXNUM_P(x)) {
04945         return rb_fix2str(x, base);
04946     }
04947 
04948     bigtrunc(x);
04949     xds = BDIGITS(x);
04950     xn = RBIGNUM_LEN(x);
04951     BARY_TRUNC(xds, xn);
04952 
04953     if (xn == 0) {
04954         return rb_usascii_str_new2("0");
04955     }
04956 
04957     if (base < 2 || 36 < base)
04958         rb_raise(rb_eArgError, "invalid radix %d", base);
04959 
04960     if (xn >= LONG_MAX/BITSPERDIG) {
04961         rb_raise(rb_eRangeError, "bignum too big to convert into `string'");
04962     }
04963 
04964     if (POW2_P(base)) {
04965         /* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
04966         return big2str_base_poweroftwo(x, base);
04967     }
04968 
04969 #ifdef USE_GMP
04970     if (GMP_BIG2STR_DIGITS < xn) {
04971         return big2str_gmp(x, base);
04972     }
04973 #endif
04974 
04975     return big2str_generic(x, base);
04976 }
04977 
04978 /* deprecated */
04979 VALUE
04980 rb_big2str0(VALUE x, int base, int trim)
04981 {
04982     VALUE str;
04983     long oldlen;
04984     long n2;
04985 
04986     str = rb_big2str1(x, base);
04987 
04988     if (trim || FIXNUM_P(x) || BIGZEROP(x))
04989         return str;
04990 
04991     oldlen = RSTRING_LEN(str);
04992     if (oldlen && RSTRING_PTR(str)[0] != '-') {
04993         rb_str_resize(str, oldlen+1);
04994         MEMMOVE(RSTRING_PTR(str)+1, RSTRING_PTR(str), char, oldlen);
04995         RSTRING_PTR(str)[0] = '+';
04996     }
04997 
04998     n2 = big2str_find_n1(x, base);
04999 
05000     oldlen = RSTRING_LEN(str);
05001     if (oldlen-1 < n2) {
05002         long off = n2 - (oldlen-1);
05003         rb_str_resize(str, n2+1);
05004         MEMMOVE(RSTRING_PTR(str)+1+off, RSTRING_PTR(str)+1, char, oldlen-1);
05005         memset(RSTRING_PTR(str)+1, '0', off);
05006     }
05007 
05008     RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
05009 
05010     return str;
05011 }
05012 
05013 VALUE
05014 rb_big2str(VALUE x, int base)
05015 {
05016     return rb_big2str1(x, base);
05017 }
05018 
05019 /*
05020  *  call-seq:
05021  *     big.to_s(base=10)   ->  string
05022  *
05023  *  Returns a string containing the representation of <i>big</i> radix
05024  *  <i>base</i> (2 through 36).
05025  *
05026  *     12345654321.to_s         #=> "12345654321"
05027  *     12345654321.to_s(2)      #=> "1011011111110110111011110000110001"
05028  *     12345654321.to_s(8)      #=> "133766736061"
05029  *     12345654321.to_s(16)     #=> "2dfdbbc31"
05030  *     78546939656932.to_s(36)  #=> "rubyrules"
05031  */
05032 
05033 static VALUE
05034 rb_big_to_s(int argc, VALUE *argv, VALUE x)
05035 {
05036     int base;
05037 
05038     if (argc == 0) base = 10;
05039     else {
05040         VALUE b;
05041 
05042         rb_scan_args(argc, argv, "01", &b);
05043         base = NUM2INT(b);
05044     }
05045     return rb_big2str(x, base);
05046 }
05047 
05048 static unsigned long
05049 big2ulong(VALUE x, const char *type)
05050 {
05051     long len = RBIGNUM_LEN(x);
05052     unsigned long num;
05053     BDIGIT *ds;
05054 
05055     if (len == 0)
05056         return 0;
05057     if (BIGSIZE(x) > sizeof(long)) {
05058         rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
05059     }
05060     ds = BDIGITS(x);
05061 #if SIZEOF_LONG <= SIZEOF_BDIGITS
05062     num = (unsigned long)ds[0];
05063 #else
05064     num = 0;
05065     while (len--) {
05066         num <<= BITSPERDIG;
05067         num += (unsigned long)ds[len]; /* overflow is already checked */
05068     }
05069 #endif
05070     return num;
05071 }
05072 
05073 /* deprecated */
05074 VALUE
05075 rb_big2ulong_pack(VALUE x)
05076 {
05077     unsigned long num;
05078     rb_integer_pack(x, &num, 1, sizeof(num), 0,
05079         INTEGER_PACK_NATIVE_BYTE_ORDER|INTEGER_PACK_2COMP);
05080     return num;
05081 }
05082 
05083 VALUE
05084 rb_big2ulong(VALUE x)
05085 {
05086     unsigned long num = big2ulong(x, "unsigned long");
05087 
05088     if (RBIGNUM_POSITIVE_P(x)) {
05089         return num;
05090     }
05091     else {
05092         if (num <= LONG_MAX)
05093             return -(long)num;
05094         if (num == 1+(unsigned long)(-(LONG_MIN+1)))
05095             return LONG_MIN;
05096     }
05097     rb_raise(rb_eRangeError, "bignum out of range of unsigned long");
05098 }
05099 
05100 SIGNED_VALUE
05101 rb_big2long(VALUE x)
05102 {
05103     unsigned long num = big2ulong(x, "long");
05104 
05105     if (RBIGNUM_POSITIVE_P(x)) {
05106         if (num <= LONG_MAX)
05107             return num;
05108     }
05109     else {
05110         if (num <= LONG_MAX)
05111             return -(long)num;
05112         if (num == 1+(unsigned long)(-(LONG_MIN+1)))
05113             return LONG_MIN;
05114     }
05115     rb_raise(rb_eRangeError, "bignum too big to convert into `long'");
05116 }
05117 
05118 #if HAVE_LONG_LONG
05119 
05120 static unsigned LONG_LONG
05121 big2ull(VALUE x, const char *type)
05122 {
05123     long len = RBIGNUM_LEN(x);
05124     unsigned LONG_LONG num;
05125     BDIGIT *ds = BDIGITS(x);
05126 
05127     if (len == 0)
05128         return 0;
05129     if (BIGSIZE(x) > SIZEOF_LONG_LONG)
05130         rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
05131 #if SIZEOF_LONG_LONG <= SIZEOF_BDIGITS
05132     num = (unsigned LONG_LONG)ds[0];
05133 #else
05134     num = 0;
05135     while (len--) {
05136         num = BIGUP(num);
05137         num += ds[len];
05138     }
05139 #endif
05140     return num;
05141 }
05142 
05143 unsigned LONG_LONG
05144 rb_big2ull(VALUE x)
05145 {
05146     unsigned LONG_LONG num = big2ull(x, "unsigned long long");
05147 
05148     if (RBIGNUM_POSITIVE_P(x)) {
05149         return num;
05150     }
05151     else {
05152         if (num <= LLONG_MAX)
05153             return -(LONG_LONG)num;
05154         if (num == 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
05155             return LLONG_MIN;
05156     }
05157     rb_raise(rb_eRangeError, "bignum out of range of unsigned long long");
05158 }
05159 
05160 LONG_LONG
05161 rb_big2ll(VALUE x)
05162 {
05163     unsigned LONG_LONG num = big2ull(x, "long long");
05164 
05165     if (RBIGNUM_POSITIVE_P(x)) {
05166         if (num <= LLONG_MAX)
05167             return num;
05168     }
05169     else {
05170         if (num <= LLONG_MAX)
05171             return -(LONG_LONG)num;
05172         if (num == 1+(unsigned LONG_LONG)(-(LLONG_MIN+1)))
05173             return LLONG_MIN;
05174     }
05175     rb_raise(rb_eRangeError, "bignum too big to convert into `long long'");
05176 }
05177 
05178 #endif  /* HAVE_LONG_LONG */
05179 
05180 static VALUE
05181 dbl2big(double d)
05182 {
05183     long i = 0;
05184     BDIGIT c;
05185     BDIGIT *digits;
05186     VALUE z;
05187     double u = (d < 0)?-d:d;
05188 
05189     if (isinf(d)) {
05190         rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
05191     }
05192     if (isnan(d)) {
05193         rb_raise(rb_eFloatDomainError, "NaN");
05194     }
05195 
05196     while (1.0 <= u) {
05197         u /= (double)(BIGRAD);
05198         i++;
05199     }
05200     z = bignew(i, d>=0);
05201     digits = BDIGITS(z);
05202     while (i--) {
05203         u *= BIGRAD;
05204         c = (BDIGIT)u;
05205         u -= c;
05206         digits[i] = c;
05207     }
05208 
05209     return z;
05210 }
05211 
05212 VALUE
05213 rb_dbl2big(double d)
05214 {
05215     return bignorm(dbl2big(d));
05216 }
05217 
05218 static double
05219 big2dbl(VALUE x)
05220 {
05221     double d = 0.0;
05222     long i = (bigtrunc(x), RBIGNUM_LEN(x)), lo = 0, bits;
05223     BDIGIT *ds = BDIGITS(x), dl;
05224 
05225     if (i) {
05226         bits = i * BITSPERDIG - nlz(ds[i-1]);
05227         if (bits > DBL_MANT_DIG+DBL_MAX_EXP) {
05228             d = HUGE_VAL;
05229         }
05230         else {
05231             if (bits > DBL_MANT_DIG+1)
05232                 lo = (bits -= DBL_MANT_DIG+1) / BITSPERDIG;
05233             else
05234                 bits = 0;
05235             while (--i > lo) {
05236                 d = ds[i] + BIGRAD*d;
05237             }
05238             dl = ds[i];
05239             if (bits && (dl & ((BDIGIT)1 << (bits %= BITSPERDIG)))) {
05240                 int carry = (dl & ~(BDIGMAX << bits)) != 0;
05241                 if (!carry) {
05242                     while (i-- > 0) {
05243                         carry = ds[i] != 0;
05244                         if (carry) break;
05245                     }
05246                 }
05247                 if (carry) {
05248                     dl &= BDIGMAX << bits;
05249                     dl = BIGLO(dl + ((BDIGIT)1 << bits));
05250                     if (!dl) d += 1;
05251                 }
05252             }
05253             d = dl + BIGRAD*d;
05254             if (lo) {
05255                 if (lo > INT_MAX / BITSPERDIG)
05256                     d = HUGE_VAL;
05257                 else if (lo < INT_MIN / BITSPERDIG)
05258                     d = 0.0;
05259                 else
05260                     d = ldexp(d, (int)(lo * BITSPERDIG));
05261             }
05262         }
05263     }
05264     if (!RBIGNUM_SIGN(x)) d = -d;
05265     return d;
05266 }
05267 
05268 double
05269 rb_big2dbl(VALUE x)
05270 {
05271     double d = big2dbl(x);
05272 
05273     if (isinf(d)) {
05274         rb_warning("Bignum out of Float range");
05275         if (d < 0.0)
05276             d = -HUGE_VAL;
05277         else
05278             d = HUGE_VAL;
05279     }
05280     return d;
05281 }
05282 
05283 /*
05284  *  call-seq:
05285  *     big.to_f -> float
05286  *
05287  *  Converts <i>big</i> to a <code>Float</code>. If <i>big</i> doesn't
05288  *  fit in a <code>Float</code>, the result is infinity.
05289  *
05290  */
05291 
05292 static VALUE
05293 rb_big_to_f(VALUE x)
05294 {
05295     return DBL2NUM(rb_big2dbl(x));
05296 }
05297 
05298 VALUE
05299 rb_integer_float_cmp(VALUE x, VALUE y)
05300 {
05301     double yd = RFLOAT_VALUE(y);
05302     double yi, yf;
05303     VALUE rel;
05304 
05305     if (isnan(yd))
05306         return Qnil;
05307     if (isinf(yd)) {
05308         if (yd > 0.0) return INT2FIX(-1);
05309         else return INT2FIX(1);
05310     }
05311     yf = modf(yd, &yi);
05312     if (FIXNUM_P(x)) {
05313 #if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
05314         double xd = (double)FIX2LONG(x);
05315         if (xd < yd)
05316             return INT2FIX(-1);
05317         if (xd > yd)
05318             return INT2FIX(1);
05319         return INT2FIX(0);
05320 #else
05321         long xn, yn;
05322         if (yi < FIXNUM_MIN)
05323             return INT2FIX(1);
05324         if (FIXNUM_MAX+1 <= yi)
05325             return INT2FIX(-1);
05326         xn = FIX2LONG(x);
05327         yn = (long)yi;
05328         if (xn < yn)
05329             return INT2FIX(-1);
05330         if (xn > yn)
05331             return INT2FIX(1);
05332         if (yf < 0.0)
05333             return INT2FIX(1);
05334         if (0.0 < yf)
05335             return INT2FIX(-1);
05336         return INT2FIX(0);
05337 #endif
05338     }
05339     y = rb_dbl2big(yi);
05340     rel = rb_big_cmp(x, y);
05341     if (yf == 0.0 || rel != INT2FIX(0))
05342         return rel;
05343     if (yf < 0.0)
05344         return INT2FIX(1);
05345     return INT2FIX(-1);
05346 }
05347 
05348 VALUE
05349 rb_integer_float_eq(VALUE x, VALUE y)
05350 {
05351     double yd = RFLOAT_VALUE(y);
05352     double yi, yf;
05353 
05354     if (isnan(yd) || isinf(yd))
05355         return Qfalse;
05356     yf = modf(yd, &yi);
05357     if (yf != 0)
05358         return Qfalse;
05359     if (FIXNUM_P(x)) {
05360 #if SIZEOF_LONG * CHAR_BIT < DBL_MANT_DIG /* assume FLT_RADIX == 2 */
05361         double xd = (double)FIX2LONG(x);
05362         if (xd != yd)
05363             return Qfalse;
05364         return Qtrue;
05365 #else
05366         long xn, yn;
05367         if (yi < LONG_MIN || LONG_MAX < yi)
05368             return Qfalse;
05369         xn = FIX2LONG(x);
05370         yn = (long)yi;
05371         if (xn != yn)
05372             return Qfalse;
05373         return Qtrue;
05374 #endif
05375     }
05376     y = rb_dbl2big(yi);
05377     return rb_big_eq(x, y);
05378 }
05379 
05380 /*
05381  *  call-seq:
05382  *     big <=> numeric   -> -1, 0, +1 or nil
05383  *
05384  *  Comparison---Returns -1, 0, or +1 depending on whether +big+ is
05385  *  less than, equal to, or greater than +numeric+. This is the
05386  *  basis for the tests in Comparable.
05387  *
05388  *  +nil+ is returned if the two values are incomparable.
05389  *
05390  */
05391 
05392 VALUE
05393 rb_big_cmp(VALUE x, VALUE y)
05394 {
05395     int cmp;
05396 
05397     if (FIXNUM_P(y)) {
05398         y = rb_int2big(FIX2LONG(y));
05399     }
05400     else if (RB_BIGNUM_TYPE_P(y)) {
05401     }
05402     else if (RB_FLOAT_TYPE_P(y)) {
05403         return rb_integer_float_cmp(x, y);
05404     }
05405     else {
05406         return rb_num_coerce_cmp(x, y, rb_intern("<=>"));
05407     }
05408 
05409     if (RBIGNUM_SIGN(x) > RBIGNUM_SIGN(y)) return INT2FIX(1);
05410     if (RBIGNUM_SIGN(x) < RBIGNUM_SIGN(y)) return INT2FIX(-1);
05411 
05412     cmp = bary_cmp(BDIGITS(x), RBIGNUM_LEN(x), BDIGITS(y), RBIGNUM_LEN(y));
05413     if (RBIGNUM_SIGN(x))
05414         return INT2FIX(cmp);
05415     else
05416         return INT2FIX(-cmp);
05417 }
05418 
05419 enum big_op_t {
05420     big_op_gt,
05421     big_op_ge,
05422     big_op_lt,
05423     big_op_le
05424 };
05425 
05426 static VALUE
05427 big_op(VALUE x, VALUE y, enum big_op_t op)
05428 {
05429     VALUE rel;
05430     int n;
05431 
05432     if (FIXNUM_P(y) || RB_BIGNUM_TYPE_P(y)) {
05433         rel = rb_big_cmp(x, y);
05434     }
05435     else if (RB_FLOAT_TYPE_P(y)) {
05436         rel = rb_integer_float_cmp(x, y);
05437     }
05438     else {
05439         ID id = 0;
05440         switch (op) {
05441           case big_op_gt: id = '>'; break;
05442           case big_op_ge: id = rb_intern(">="); break;
05443           case big_op_lt: id = '<'; break;
05444           case big_op_le: id = rb_intern("<="); break;
05445         }
05446         return rb_num_coerce_relop(x, y, id);
05447     }
05448 
05449     if (NIL_P(rel)) return Qfalse;
05450     n = FIX2INT(rel);
05451 
05452     switch (op) {
05453         case big_op_gt: return n >  0 ? Qtrue : Qfalse;
05454         case big_op_ge: return n >= 0 ? Qtrue : Qfalse;
05455         case big_op_lt: return n <  0 ? Qtrue : Qfalse;
05456         case big_op_le: return n <= 0 ? Qtrue : Qfalse;
05457     }
05458     return Qundef;
05459 }
05460 
05461 /*
05462  * call-seq:
05463  *   big > real  ->  true or false
05464  *
05465  * Returns <code>true</code> if the value of <code>big</code> is
05466  * greater than that of <code>real</code>.
05467  */
05468 
05469 static VALUE
05470 big_gt(VALUE x, VALUE y)
05471 {
05472     return big_op(x, y, big_op_gt);
05473 }
05474 
05475 /*
05476  * call-seq:
05477  *   big >= real  ->  true or false
05478  *
05479  * Returns <code>true</code> if the value of <code>big</code> is
05480  * greater than or equal to that of <code>real</code>.
05481  */
05482 
05483 static VALUE
05484 big_ge(VALUE x, VALUE y)
05485 {
05486     return big_op(x, y, big_op_ge);
05487 }
05488 
05489 /*
05490  * call-seq:
05491  *   big < real  ->  true or false
05492  *
05493  * Returns <code>true</code> if the value of <code>big</code> is
05494  * less than that of <code>real</code>.
05495  */
05496 
05497 static VALUE
05498 big_lt(VALUE x, VALUE y)
05499 {
05500     return big_op(x, y, big_op_lt);
05501 }
05502 
05503 /*
05504  * call-seq:
05505  *   big <= real  ->  true or false
05506  *
05507  * Returns <code>true</code> if the value of <code>big</code> is
05508  * less than or equal to that of <code>real</code>.
05509  */
05510 
05511 static VALUE
05512 big_le(VALUE x, VALUE y)
05513 {
05514     return big_op(x, y, big_op_le);
05515 }
05516 
05517 /*
05518  *  call-seq:
05519  *     big == obj  -> true or false
05520  *
05521  *  Returns <code>true</code> only if <i>obj</i> has the same value
05522  *  as <i>big</i>. Contrast this with <code>Bignum#eql?</code>, which
05523  *  requires <i>obj</i> to be a <code>Bignum</code>.
05524  *
05525  *     68719476736 == 68719476736.0   #=> true
05526  */
05527 
05528 VALUE
05529 rb_big_eq(VALUE x, VALUE y)
05530 {
05531     if (FIXNUM_P(y)) {
05532         if (bignorm(x) == y) return Qtrue;
05533         y = rb_int2big(FIX2LONG(y));
05534     }
05535     else if (RB_BIGNUM_TYPE_P(y)) {
05536     }
05537     else if (RB_FLOAT_TYPE_P(y)) {
05538         return rb_integer_float_eq(x, y);
05539     }
05540     else {
05541         return rb_equal(y, x);
05542     }
05543     if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
05544     if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
05545     if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
05546     return Qtrue;
05547 }
05548 
05549 /*
05550  *  call-seq:
05551  *     big.eql?(obj)   -> true or false
05552  *
05553  *  Returns <code>true</code> only if <i>obj</i> is a
05554  *  <code>Bignum</code> with the same value as <i>big</i>. Contrast this
05555  *  with <code>Bignum#==</code>, which performs type conversions.
05556  *
05557  *     68719476736.eql?(68719476736.0)   #=> false
05558  */
05559 
05560 VALUE
05561 rb_big_eql(VALUE x, VALUE y)
05562 {
05563     if (!RB_BIGNUM_TYPE_P(y)) return Qfalse;
05564     if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y)) return Qfalse;
05565     if (RBIGNUM_LEN(x) != RBIGNUM_LEN(y)) return Qfalse;
05566     if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM_LEN(y)) != 0) return Qfalse;
05567     return Qtrue;
05568 }
05569 
05570 /*
05571  * call-seq:
05572  *    -big   ->  integer
05573  *
05574  * Unary minus (returns an integer whose value is 0-big)
05575  */
05576 
05577 VALUE
05578 rb_big_uminus(VALUE x)
05579 {
05580     VALUE z = rb_big_clone(x);
05581 
05582     RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
05583 
05584     return bignorm(z);
05585 }
05586 
05587 /*
05588  * call-seq:
05589  *     ~big  ->  integer
05590  *
05591  * Inverts the bits in big. As Bignums are conceptually infinite
05592  * length, the result acts as if it had an infinite number of one
05593  * bits to the left. In hex representations, this is displayed
05594  * as two periods to the left of the digits.
05595  *
05596  *   sprintf("%X", ~0x1122334455)    #=> "..FEEDDCCBBAA"
05597  */
05598 
05599 static VALUE
05600 rb_big_neg(VALUE x)
05601 {
05602     VALUE z = rb_big_clone(x);
05603     BDIGIT *ds = BDIGITS(z);
05604     long n = RBIGNUM_LEN(z);
05605 
05606     if (!n) return INT2FIX(-1);
05607 
05608     if (RBIGNUM_POSITIVE_P(z)) {
05609         if (bary_add_one(ds, n)) {
05610             big_extend_carry(z);
05611         }
05612         RBIGNUM_SET_NEGATIVE_SIGN(z);
05613     }
05614     else {
05615         bary_neg(ds, n);
05616         if (bary_add_one(ds, n))
05617             return INT2FIX(-1);
05618         bary_neg(ds, n);
05619         RBIGNUM_SET_POSITIVE_SIGN(z);
05620     }
05621 
05622     return bignorm(z);
05623 }
05624 
05625 static VALUE
05626 bigsub(VALUE x, VALUE y)
05627 {
05628     VALUE z;
05629     BDIGIT *xds, *yds, *zds;
05630     long xn, yn, zn;
05631 
05632     xn = RBIGNUM_LEN(x);
05633     yn = RBIGNUM_LEN(y);
05634     zn = xn < yn ? yn : xn;
05635 
05636     z = bignew(zn, 1);
05637 
05638     xds = BDIGITS(x);
05639     yds = BDIGITS(y);
05640     zds = BDIGITS(z);
05641 
05642     if (bary_sub(zds, zn, xds, xn, yds, yn)) {
05643         bary_2comp(zds, zn);
05644         RBIGNUM_SET_NEGATIVE_SIGN(z);
05645     }
05646 
05647     return z;
05648 }
05649 
05650 static VALUE bigadd_int(VALUE x, long y);
05651 
05652 static VALUE
05653 bigsub_int(VALUE x, long y0)
05654 {
05655     VALUE z;
05656     BDIGIT *xds, *zds;
05657     long xn, zn;
05658     BDIGIT_DBL_SIGNED num;
05659     long i, y;
05660 
05661     y = y0;
05662     xds = BDIGITS(x);
05663     xn = RBIGNUM_LEN(x);
05664 
05665     if (xn == 0)
05666         return LONG2NUM(-y0);
05667 
05668     zn = xn;
05669 #if SIZEOF_BDIGITS < SIZEOF_LONG
05670     if (zn < bdigit_roomof(SIZEOF_LONG))
05671         zn = bdigit_roomof(SIZEOF_LONG);
05672 #endif
05673     z = bignew(zn, RBIGNUM_SIGN(x));
05674     zds = BDIGITS(z);
05675 
05676 #if SIZEOF_BDIGITS >= SIZEOF_LONG
05677     assert(xn == zn);
05678     num = (BDIGIT_DBL_SIGNED)xds[0] - y;
05679     if (xn == 1 && num < 0) {
05680         RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
05681         zds[0] = (BDIGIT)-num;
05682         RB_GC_GUARD(x);
05683         return bignorm(z);
05684     }
05685     zds[0] = BIGLO(num);
05686     num = BIGDN(num);
05687     i = 1;
05688     if (i < xn)
05689         goto y_is_zero_x;
05690     goto finish;
05691 #else
05692     num = 0;
05693     for (i=0; i < xn; i++) {
05694         if (y == 0) goto y_is_zero_x;
05695         num += (BDIGIT_DBL_SIGNED)xds[i] - BIGLO(y);
05696         zds[i] = BIGLO(num);
05697         num = BIGDN(num);
05698         y = BIGDN(y);
05699     }
05700     for (; i < zn; i++) {
05701         if (y == 0) goto y_is_zero_z;
05702         num -= BIGLO(y);
05703         zds[i] = BIGLO(num);
05704         num = BIGDN(num);
05705         y = BIGDN(y);
05706     }
05707     goto finish;
05708 #endif
05709 
05710     for (; i < xn; i++) {
05711       y_is_zero_x:
05712         if (num == 0) goto num_is_zero_x;
05713         num += xds[i];
05714         zds[i] = BIGLO(num);
05715         num = BIGDN(num);
05716     }
05717 #if SIZEOF_BDIGITS < SIZEOF_LONG
05718     for (; i < zn; i++) {
05719       y_is_zero_z:
05720         if (num == 0) goto num_is_zero_z;
05721         zds[i] = BIGLO(num);
05722         num = BIGDN(num);
05723     }
05724 #endif
05725     goto finish;
05726 
05727     for (; i < xn; i++) {
05728       num_is_zero_x:
05729         zds[i] = xds[i];
05730     }
05731 #if SIZEOF_BDIGITS < SIZEOF_LONG
05732     for (; i < zn; i++) {
05733       num_is_zero_z:
05734         zds[i] = 0;
05735     }
05736 #endif
05737     goto finish;
05738 
05739   finish:
05740     assert(num == 0 || num == -1);
05741     if (num < 0) {
05742         get2comp(z);
05743         RBIGNUM_SET_SIGN(z, !RBIGNUM_SIGN(x));
05744     }
05745     RB_GC_GUARD(x);
05746     return bignorm(z);
05747 }
05748 
05749 static VALUE
05750 bigadd_int(VALUE x, long y)
05751 {
05752     VALUE z;
05753     BDIGIT *xds, *zds;
05754     long xn, zn;
05755     BDIGIT_DBL num;
05756     long i;
05757 
05758     xds = BDIGITS(x);
05759     xn = RBIGNUM_LEN(x);
05760 
05761     if (xn == 0)
05762         return LONG2NUM(y);
05763 
05764     zn = xn;
05765 #if SIZEOF_BDIGITS < SIZEOF_LONG
05766     if (zn < bdigit_roomof(SIZEOF_LONG))
05767         zn = bdigit_roomof(SIZEOF_LONG);
05768 #endif
05769     zn++;
05770 
05771     z = bignew(zn, RBIGNUM_SIGN(x));
05772     zds = BDIGITS(z);
05773 
05774 #if SIZEOF_BDIGITS >= SIZEOF_LONG
05775     num = (BDIGIT_DBL)xds[0] + y;
05776     zds[0] = BIGLO(num);
05777     num = BIGDN(num);
05778     i = 1;
05779     if (i < xn)
05780         goto y_is_zero_x;
05781     goto y_is_zero_z;
05782 #else
05783     num = 0;
05784     for (i=0; i < xn; i++) {
05785         if (y == 0) goto y_is_zero_x;
05786         num += (BDIGIT_DBL)xds[i] + BIGLO(y);
05787         zds[i] = BIGLO(num);
05788         num = BIGDN(num);
05789         y = BIGDN(y);
05790     }
05791     for (; i < zn; i++) {
05792         if (y == 0) goto y_is_zero_z;
05793         num += BIGLO(y);
05794         zds[i] = BIGLO(num);
05795         num = BIGDN(num);
05796         y = BIGDN(y);
05797     }
05798     goto finish;
05799 
05800 #endif
05801 
05802     for (;i < xn; i++) {
05803       y_is_zero_x:
05804         if (num == 0) goto num_is_zero_x;
05805         num += (BDIGIT_DBL)xds[i];
05806         zds[i] = BIGLO(num);
05807         num = BIGDN(num);
05808     }
05809     for (; i < zn; i++) {
05810       y_is_zero_z:
05811         if (num == 0) goto num_is_zero_z;
05812         zds[i] = BIGLO(num);
05813         num = BIGDN(num);
05814     }
05815     goto finish;
05816 
05817     for (;i < xn; i++) {
05818       num_is_zero_x:
05819         zds[i] = xds[i];
05820     }
05821     for (; i < zn; i++) {
05822       num_is_zero_z:
05823         zds[i] = 0;
05824     }
05825     goto finish;
05826 
05827   finish:
05828     RB_GC_GUARD(x);
05829     return bignorm(z);
05830 }
05831 
05832 static VALUE
05833 bigadd(VALUE x, VALUE y, int sign)
05834 {
05835     VALUE z;
05836     long len;
05837 
05838     sign = (sign == RBIGNUM_SIGN(y));
05839     if (RBIGNUM_SIGN(x) != sign) {
05840         if (sign) return bigsub(y, x);
05841         return bigsub(x, y);
05842     }
05843 
05844     if (RBIGNUM_LEN(x) > RBIGNUM_LEN(y)) {
05845         len = RBIGNUM_LEN(x) + 1;
05846     }
05847     else {
05848         len = RBIGNUM_LEN(y) + 1;
05849     }
05850     z = bignew(len, sign);
05851 
05852     bary_add(BDIGITS(z), RBIGNUM_LEN(z),
05853              BDIGITS(x), RBIGNUM_LEN(x),
05854              BDIGITS(y), RBIGNUM_LEN(y));
05855 
05856     return z;
05857 }
05858 
05859 /*
05860  *  call-seq:
05861  *     big + other  -> Numeric
05862  *
05863  *  Adds big and other, returning the result.
05864  */
05865 
05866 VALUE
05867 rb_big_plus(VALUE x, VALUE y)
05868 {
05869     long n;
05870 
05871     if (FIXNUM_P(y)) {
05872         n = FIX2LONG(y);
05873         if ((n > 0) != RBIGNUM_SIGN(x)) {
05874             if (n < 0) {
05875                 n = -n;
05876             }
05877             return bigsub_int(x, n);
05878         }
05879         if (n < 0) {
05880             n = -n;
05881         }
05882         return bigadd_int(x, n);
05883     }
05884     else if (RB_BIGNUM_TYPE_P(y)) {
05885         return bignorm(bigadd(x, y, 1));
05886     }
05887     else if (RB_FLOAT_TYPE_P(y)) {
05888         return DBL2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y));
05889     }
05890     else {
05891         return rb_num_coerce_bin(x, y, '+');
05892     }
05893 }
05894 
05895 /*
05896  *  call-seq:
05897  *     big - other  -> Numeric
05898  *
05899  *  Subtracts other from big, returning the result.
05900  */
05901 
05902 VALUE
05903 rb_big_minus(VALUE x, VALUE y)
05904 {
05905     long n;
05906 
05907     if (FIXNUM_P(y)) {
05908         n = FIX2LONG(y);
05909         if ((n > 0) != RBIGNUM_SIGN(x)) {
05910             if (n < 0) {
05911                 n = -n;
05912             }
05913             return bigadd_int(x, n);
05914         }
05915         if (n < 0) {
05916             n = -n;
05917         }
05918         return bigsub_int(x, n);
05919     }
05920     else if (RB_BIGNUM_TYPE_P(y)) {
05921         return bignorm(bigadd(x, y, 0));
05922     }
05923     else if (RB_FLOAT_TYPE_P(y)) {
05924         return DBL2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y));
05925     }
05926     else {
05927         return rb_num_coerce_bin(x, y, '-');
05928     }
05929 }
05930 
05931 static VALUE
05932 bigsq(VALUE x)
05933 {
05934     long xn, zn;
05935     VALUE z;
05936     BDIGIT *xds, *zds;
05937 
05938     xn = RBIGNUM_LEN(x);
05939     zn = 2 * xn;
05940 
05941     z = bignew(zn, 1);
05942 
05943     xds = BDIGITS(x);
05944     zds = BDIGITS(z);
05945 
05946 #ifdef USE_GMP
05947     if (xn < GMP_MUL_DIGITS)
05948         bary_sq_fast(zds, zn, xds, xn);
05949     else
05950         bary_mul(zds, zn, xds, xn, xds, xn);
05951 #else
05952     if (xn < KARATSUBA_MUL_DIGITS)
05953         bary_sq_fast(zds, zn, xds, xn);
05954     else
05955         bary_mul(zds, zn, xds, xn, xds, xn);
05956 #endif
05957 
05958     RB_GC_GUARD(x);
05959     return z;
05960 }
05961 
05962 static VALUE
05963 bigmul0(VALUE x, VALUE y)
05964 {
05965     long xn, yn, zn;
05966     VALUE z;
05967     BDIGIT *xds, *yds, *zds;
05968 
05969     if (x == y)
05970         return bigsq(x);
05971 
05972     xn = RBIGNUM_LEN(x);
05973     yn = RBIGNUM_LEN(y);
05974     zn = xn + yn;
05975 
05976     z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
05977 
05978     xds = BDIGITS(x);
05979     yds = BDIGITS(y);
05980     zds = BDIGITS(z);
05981 
05982     bary_mul(zds, zn, xds, xn, yds, yn);
05983 
05984     RB_GC_GUARD(x);
05985     RB_GC_GUARD(y);
05986     return z;
05987 }
05988 
05989 /*
05990  *  call-seq:
05991  *     big * other  -> Numeric
05992  *
05993  *  Multiplies big and other, returning the result.
05994  */
05995 
05996 VALUE
05997 rb_big_mul(VALUE x, VALUE y)
05998 {
05999     if (FIXNUM_P(y)) {
06000         y = rb_int2big(FIX2LONG(y));
06001     }
06002     else if (RB_BIGNUM_TYPE_P(y)) {
06003     }
06004     else if (RB_FLOAT_TYPE_P(y)) {
06005         return DBL2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y));
06006     }
06007     else {
06008         return rb_num_coerce_bin(x, y, '*');
06009     }
06010 
06011     return bignorm(bigmul0(x, y));
06012 }
06013 
06014 static VALUE
06015 bigdivrem(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
06016 {
06017     long xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y);
06018     VALUE z;
06019     BDIGIT *xds, *yds, *zds;
06020     BDIGIT dd;
06021 
06022     VALUE q = Qnil, r = Qnil;
06023     BDIGIT *qds, *rds;
06024     long qn, rn;
06025 
06026     yds = BDIGITS(y);
06027     BARY_TRUNC(yds, yn);
06028     if (yn == 0)
06029         rb_num_zerodiv();
06030 
06031     xds = BDIGITS(x);
06032     BARY_TRUNC(xds, xn);
06033 
06034     if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) {
06035         if (divp) *divp = rb_int2big(0);
06036         if (modp) *modp = x;
06037         return Qnil;
06038     }
06039     if (yn == 1) {
06040         dd = yds[0];
06041         z = bignew(xn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
06042         zds = BDIGITS(z);
06043         dd = bigdivrem_single(zds, xds, xn, dd);
06044         if (modp) {
06045             *modp = rb_uint2big((VALUE)dd);
06046             RBIGNUM_SET_SIGN(*modp, RBIGNUM_SIGN(x));
06047         }
06048         if (divp) *divp = z;
06049         return Qnil;
06050     }
06051     if (xn == 2 && yn == 2) {
06052         BDIGIT_DBL x0 = bary2bdigitdbl(xds, 2);
06053         BDIGIT_DBL y0 = bary2bdigitdbl(yds, 2);
06054         BDIGIT_DBL q0 = x0 / y0;
06055         BDIGIT_DBL r0 = x0 % y0;
06056         if (divp) {
06057             z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
06058             zds = BDIGITS(z);
06059             zds[0] = BIGLO(q0);
06060             zds[1] = BIGLO(BIGDN(q0));
06061             *divp = z;
06062         }
06063         if (modp) {
06064             z = bignew(bdigit_roomof(sizeof(BDIGIT_DBL)), RBIGNUM_SIGN(x));
06065             zds = BDIGITS(z);
06066             zds[0] = BIGLO(r0);
06067             zds[1] = BIGLO(BIGDN(r0));
06068             *modp = z;
06069         }
06070         return Qnil;
06071     }
06072 
06073     if (divp) {
06074         qn = xn + BIGDIVREM_EXTRA_WORDS;
06075         q = bignew(qn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));
06076         qds = BDIGITS(q);
06077     }
06078     else {
06079         qn = 0;
06080         qds = NULL;
06081     }
06082 
06083     if (modp) {
06084         rn = yn;
06085         r = bignew(rn, RBIGNUM_SIGN(x));
06086         rds = BDIGITS(r);
06087     }
06088     else {
06089         rn = 0;
06090         rds = NULL;
06091     }
06092 
06093     bary_divmod_branch(qds, qn, rds, rn, xds, xn, yds, yn);
06094 
06095     if (divp) {
06096         bigtrunc(q);
06097         *divp = q;
06098     }
06099     if (modp) {
06100         bigtrunc(r);
06101         *modp = r;
06102     }
06103 
06104     return Qnil;
06105 }
06106 
06107 static void
06108 bigdivmod(VALUE x, VALUE y, volatile VALUE *divp, volatile VALUE *modp)
06109 {
06110     VALUE mod;
06111 
06112     bigdivrem(x, y, divp, &mod);
06113     if (RBIGNUM_SIGN(x) != RBIGNUM_SIGN(y) && !BIGZEROP(mod)) {
06114         if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
06115         if (modp) *modp = bigadd(mod, y, 1);
06116     }
06117     else if (modp) {
06118         *modp = mod;
06119     }
06120 }
06121 
06122 
06123 static VALUE
06124 rb_big_divide(VALUE x, VALUE y, ID op)
06125 {
06126     VALUE z;
06127 
06128     if (FIXNUM_P(y)) {
06129         y = rb_int2big(FIX2LONG(y));
06130     }
06131     else if (RB_BIGNUM_TYPE_P(y)) {
06132     }
06133     else if (RB_FLOAT_TYPE_P(y)) {
06134         if (op == '/') {
06135             return DBL2NUM(rb_big2dbl(x) / RFLOAT_VALUE(y));
06136         }
06137         else {
06138             double dy = RFLOAT_VALUE(y);
06139             if (dy == 0.0) rb_num_zerodiv();
06140             return rb_dbl2big(rb_big2dbl(x) / dy);
06141         }
06142     }
06143     else {
06144         return rb_num_coerce_bin(x, y, op);
06145     }
06146     bigdivmod(x, y, &z, 0);
06147 
06148     return bignorm(z);
06149 }
06150 
06151 /*
06152  *  call-seq:
06153  *     big / other     -> Numeric
06154  *
06155  * Performs division: the class of the resulting object depends on
06156  * the class of <code>numeric</code> and on the magnitude of the
06157  * result.
06158  */
06159 
06160 VALUE
06161 rb_big_div(VALUE x, VALUE y)
06162 {
06163     return rb_big_divide(x, y, '/');
06164 }
06165 
06166 /*
06167  *  call-seq:
06168  *     big.div(other)  -> integer
06169  *
06170  * Performs integer division: returns integer value.
06171  */
06172 
06173 VALUE
06174 rb_big_idiv(VALUE x, VALUE y)
06175 {
06176     return rb_big_divide(x, y, rb_intern("div"));
06177 }
06178 
06179 /*
06180  *  call-seq:
06181  *     big % other         -> Numeric
06182  *     big.modulo(other)   -> Numeric
06183  *
06184  *  Returns big modulo other. See Numeric.divmod for more
06185  *  information.
06186  */
06187 
06188 VALUE
06189 rb_big_modulo(VALUE x, VALUE y)
06190 {
06191     VALUE z;
06192 
06193     if (FIXNUM_P(y)) {
06194         y = rb_int2big(FIX2LONG(y));
06195     }
06196     else if (!RB_BIGNUM_TYPE_P(y)) {
06197         return rb_num_coerce_bin(x, y, '%');
06198     }
06199     bigdivmod(x, y, 0, &z);
06200 
06201     return bignorm(z);
06202 }
06203 
06204 /*
06205  *  call-seq:
06206  *     big.remainder(numeric)    -> number
06207  *
06208  *  Returns the remainder after dividing <i>big</i> by <i>numeric</i>.
06209  *
06210  *     -1234567890987654321.remainder(13731)      #=> -6966
06211  *     -1234567890987654321.remainder(13731.24)   #=> -9906.22531493148
06212  */
06213 static VALUE
06214 rb_big_remainder(VALUE x, VALUE y)
06215 {
06216     VALUE z;
06217 
06218     if (FIXNUM_P(y)) {
06219         y = rb_int2big(FIX2LONG(y));
06220     }
06221     else if (!RB_BIGNUM_TYPE_P(y)) {
06222         return rb_num_coerce_bin(x, y, rb_intern("remainder"));
06223     }
06224     bigdivrem(x, y, 0, &z);
06225 
06226     return bignorm(z);
06227 }
06228 
06229 /*
06230  *  call-seq:
06231  *     big.divmod(numeric)   -> array
06232  *
06233  *  See <code>Numeric#divmod</code>.
06234  *
06235  */
06236 VALUE
06237 rb_big_divmod(VALUE x, VALUE y)
06238 {
06239     VALUE div, mod;
06240 
06241     if (FIXNUM_P(y)) {
06242         y = rb_int2big(FIX2LONG(y));
06243     }
06244     else if (!RB_BIGNUM_TYPE_P(y)) {
06245         return rb_num_coerce_bin(x, y, rb_intern("divmod"));
06246     }
06247     bigdivmod(x, y, &div, &mod);
06248 
06249     return rb_assoc_new(bignorm(div), bignorm(mod));
06250 }
06251 
06252 static VALUE
06253 big_shift(VALUE x, long n)
06254 {
06255     if (n < 0)
06256         return big_lshift(x, 1+(unsigned long)(-(n+1)));
06257     else if (n > 0)
06258         return big_rshift(x, (unsigned long)n);
06259     return x;
06260 }
06261 
06262 static VALUE
06263 big_fdiv(VALUE x, VALUE y, long ey)
06264 {
06265 #define DBL_BIGDIG ((DBL_MANT_DIG + BITSPERDIG) / BITSPERDIG)
06266     VALUE z;
06267     long l, ex;
06268 
06269     bigtrunc(x);
06270     l = RBIGNUM_LEN(x);
06271     ex = l * BITSPERDIG - nlz(BDIGITS(x)[l-1]);
06272     ex -= 2 * DBL_BIGDIG * BITSPERDIG;
06273     if (ex) x = big_shift(x, ex);
06274 
06275     bigdivrem(x, y, &z, 0);
06276     l = ex - ey;
06277 #if SIZEOF_LONG > SIZEOF_INT
06278     {
06279         /* Visual C++ can't be here */
06280         if (l > INT_MAX) return DBL2NUM(INFINITY);
06281         if (l < INT_MIN) return DBL2NUM(0.0);
06282     }
06283 #endif
06284     return DBL2NUM(ldexp(big2dbl(z), (int)l));
06285 }
06286 
06287 static VALUE
06288 big_fdiv_int(VALUE x, VALUE y)
06289 {
06290     long l, ey;
06291     bigtrunc(y);
06292     l = RBIGNUM_LEN(y);
06293     ey = l * BITSPERDIG - nlz(BDIGITS(y)[l-1]);
06294     ey -= DBL_BIGDIG * BITSPERDIG;
06295     if (ey) y = big_shift(y, ey);
06296     return big_fdiv(x, y, ey);
06297 }
06298 
06299 static VALUE
06300 big_fdiv_float(VALUE x, VALUE y)
06301 {
06302     int i;
06303     y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &i), DBL_MANT_DIG));
06304     return big_fdiv(x, y, i - DBL_MANT_DIG);
06305 }
06306 
06307 /*
06308  *  call-seq:
06309   *     big.fdiv(numeric) -> float
06310  *
06311  *  Returns the floating point result of dividing <i>big</i> by
06312  *  <i>numeric</i>.
06313  *
06314  *     -1234567890987654321.fdiv(13731)      #=> -89910996357705.5
06315  *     -1234567890987654321.fdiv(13731.24)   #=> -89909424858035.7
06316  *
06317  */
06318 
06319 
06320 VALUE
06321 rb_big_fdiv(VALUE x, VALUE y)
06322 {
06323     double dx, dy;
06324 
06325     dx = big2dbl(x);
06326     if (FIXNUM_P(y)) {
06327         dy = (double)FIX2LONG(y);
06328         if (isinf(dx))
06329             return big_fdiv_int(x, rb_int2big(FIX2LONG(y)));
06330     }
06331     else if (RB_BIGNUM_TYPE_P(y)) {
06332         dy = rb_big2dbl(y);
06333         if (isinf(dx) || isinf(dy))
06334             return big_fdiv_int(x, y);
06335     }
06336     else if (RB_FLOAT_TYPE_P(y)) {
06337         dy = RFLOAT_VALUE(y);
06338         if (isnan(dy))
06339             return y;
06340         if (isinf(dx))
06341             return big_fdiv_float(x, y);
06342     }
06343     else {
06344         return rb_num_coerce_bin(x, y, rb_intern("fdiv"));
06345     }
06346     return DBL2NUM(dx / dy);
06347 }
06348 
06349 /*
06350  *  call-seq:
06351  *     big ** exponent   -> numeric
06352  *
06353  *  Raises _big_ to the _exponent_ power (which may be an integer, float,
06354  *  or anything that will coerce to a number). The result may be
06355  *  a Fixnum, Bignum, or Float
06356  *
06357  *    123456789 ** 2      #=> 15241578750190521
06358  *    123456789 ** 1.2    #=> 5126464716.09932
06359  *    123456789 ** -2     #=> 6.5610001194102e-17
06360  */
06361 
06362 VALUE
06363 rb_big_pow(VALUE x, VALUE y)
06364 {
06365     double d;
06366     SIGNED_VALUE yy;
06367 
06368   again:
06369     if (y == INT2FIX(0)) return INT2FIX(1);
06370     if (RB_FLOAT_TYPE_P(y)) {
06371         d = RFLOAT_VALUE(y);
06372         if ((!RBIGNUM_SIGN(x) && !BIGZEROP(x)) && d != round(d))
06373             return rb_funcall(rb_complex_raw1(x), rb_intern("**"), 1, y);
06374     }
06375     else if (RB_BIGNUM_TYPE_P(y)) {
06376         y = bignorm(y);
06377         if (FIXNUM_P(y))
06378             goto again;
06379         rb_warn("in a**b, b may be too big");
06380         d = rb_big2dbl(y);
06381     }
06382     else if (FIXNUM_P(y)) {
06383         yy = FIX2LONG(y);
06384 
06385         if (yy < 0)
06386             return rb_funcall(rb_rational_raw1(x), rb_intern("**"), 1, y);
06387         else {
06388             VALUE z = 0;
06389             SIGNED_VALUE mask;
06390             const size_t xbits = rb_absint_numwords(x, 1, NULL);
06391             const size_t BIGLEN_LIMIT = 32*1024*1024;
06392 
06393             if (xbits == (size_t)-1 ||
06394                 (xbits > BIGLEN_LIMIT) ||
06395                 (xbits * yy > BIGLEN_LIMIT)) {
06396                 rb_warn("in a**b, b may be too big");
06397                 d = (double)yy;
06398             }
06399             else {
06400                 for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
06401                     if (z) z = bigsq(z);
06402                     if (yy & mask) {
06403                         z = z ? bigtrunc(bigmul0(z, x)) : x;
06404                     }
06405                 }
06406                 return bignorm(z);
06407             }
06408         }
06409     }
06410     else {
06411         return rb_num_coerce_bin(x, y, rb_intern("**"));
06412     }
06413     return DBL2NUM(pow(rb_big2dbl(x), d));
06414 }
06415 
06416 static VALUE
06417 bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
06418 {
06419     VALUE z;
06420     BDIGIT *xds, *zds;
06421     long zn;
06422     long i;
06423     BDIGIT hibitsy;
06424 
06425     if (y == 0) return INT2FIX(0);
06426     if (xn == 0) return hibitsx ? LONG2NUM(y) : 0;
06427     hibitsy = 0 <= y ? 0 : BDIGMAX;
06428     xds = BDIGITS(x);
06429 #if SIZEOF_BDIGITS >= SIZEOF_LONG
06430     if (!hibitsy) {
06431         y &= xds[0];
06432         return LONG2NUM(y);
06433     }
06434 #endif
06435 
06436     zn = xn;
06437 #if SIZEOF_BDIGITS < SIZEOF_LONG
06438     if (hibitsx && zn < bdigit_roomof(SIZEOF_LONG))
06439         zn = bdigit_roomof(SIZEOF_LONG);
06440 #endif
06441 
06442     z = bignew(zn, 0);
06443     zds = BDIGITS(z);
06444 
06445 #if SIZEOF_BDIGITS >= SIZEOF_LONG
06446     i = 1;
06447     zds[0] = xds[0] & BIGLO(y);
06448 #else
06449     for (i=0; i < xn; i++) {
06450         if (y == 0 || y == -1) break;
06451         zds[i] = xds[i] & BIGLO(y);
06452         y = BIGDN(y);
06453     }
06454     for (; i < zn; i++) {
06455         if (y == 0 || y == -1) break;
06456         zds[i] = hibitsx & BIGLO(y);
06457         y = BIGDN(y);
06458     }
06459 #endif
06460     for (;i < xn; i++) {
06461         zds[i] = xds[i] & hibitsy;
06462     }
06463     for (;i < zn; i++) {
06464         zds[i] = hibitsx & hibitsy;
06465     }
06466     twocomp2abs_bang(z, hibitsx && hibitsy);
06467     RB_GC_GUARD(x);
06468     return bignorm(z);
06469 }
06470 
06471 /*
06472  * call-seq:
06473  *     big & numeric   ->  integer
06474  *
06475  * Performs bitwise +and+ between _big_ and _numeric_.
06476  */
06477 
06478 VALUE
06479 rb_big_and(VALUE x, VALUE y)
06480 {
06481     VALUE z;
06482     BDIGIT *ds1, *ds2, *zds;
06483     long i, xn, yn, n1, n2;
06484     BDIGIT hibitsx, hibitsy;
06485     BDIGIT hibits1, hibits2;
06486     VALUE tmpv;
06487     BDIGIT tmph;
06488     long tmpn;
06489 
06490     if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
06491         return rb_num_coerce_bit(x, y, '&');
06492     }
06493 
06494     hibitsx = abs2twocomp(&x, &xn);
06495     if (FIXNUM_P(y)) {
06496         return bigand_int(x, xn, hibitsx, FIX2LONG(y));
06497     }
06498     hibitsy = abs2twocomp(&y, &yn);
06499     if (xn > yn) {
06500         tmpv = x; x = y; y = tmpv;
06501         tmpn = xn; xn = yn; yn = tmpn;
06502         tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
06503     }
06504     n1 = xn;
06505     n2 = yn;
06506     ds1 = BDIGITS(x);
06507     ds2 = BDIGITS(y);
06508     hibits1 = hibitsx;
06509     hibits2 = hibitsy;
06510 
06511     if (!hibits1)
06512         n2 = n1;
06513 
06514     z = bignew(n2, 0);
06515     zds = BDIGITS(z);
06516 
06517     for (i=0; i<n1; i++) {
06518         zds[i] = ds1[i] & ds2[i];
06519     }
06520     for (; i<n2; i++) {
06521         zds[i] = hibits1 & ds2[i];
06522     }
06523     twocomp2abs_bang(z, hibits1 && hibits2);
06524     RB_GC_GUARD(x);
06525     RB_GC_GUARD(y);
06526     return bignorm(z);
06527 }
06528 
06529 static VALUE
06530 bigor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
06531 {
06532     VALUE z;
06533     BDIGIT *xds, *zds;
06534     long zn;
06535     long i;
06536     BDIGIT hibitsy;
06537 
06538     if (y == -1) return INT2FIX(-1);
06539     if (xn == 0) return hibitsx ? INT2FIX(-1) : LONG2FIX(y);
06540     hibitsy = 0 <= y ? 0 : BDIGMAX;
06541     xds = BDIGITS(x);
06542 
06543     zn = RBIGNUM_LEN(x);
06544 #if SIZEOF_BDIGITS < SIZEOF_LONG
06545     if (zn < bdigit_roomof(SIZEOF_LONG))
06546         zn = bdigit_roomof(SIZEOF_LONG);
06547 #endif
06548     z = bignew(zn, 0);
06549     zds = BDIGITS(z);
06550 
06551 #if SIZEOF_BDIGITS >= SIZEOF_LONG
06552     i = 1;
06553     zds[0] = xds[0] | BIGLO(y);
06554     if (i < zn)
06555         goto y_is_fixed_point;
06556     goto finish;
06557 #else
06558     for (i=0; i < xn; i++) {
06559         if (y == 0 || y == -1) goto y_is_fixed_point;
06560         zds[i] = xds[i] | BIGLO(y);
06561         y = BIGDN(y);
06562     }
06563     if (hibitsx)
06564         goto fill_hibits;
06565     for (; i < zn; i++) {
06566         if (y == 0 || y == -1) goto y_is_fixed_point;
06567         zds[i] = BIGLO(y);
06568         y = BIGDN(y);
06569     }
06570   goto finish;
06571 #endif
06572 
06573   y_is_fixed_point:
06574     if (hibitsy)
06575         goto fill_hibits;
06576     for (; i < xn; i++) {
06577         zds[i] = xds[i];
06578     }
06579     if (hibitsx)
06580         goto fill_hibits;
06581     for (; i < zn; i++) {
06582         zds[i] = 0;
06583     }
06584   goto finish;
06585 
06586   fill_hibits:
06587     for (; i < zn; i++) {
06588         zds[i] = BDIGMAX;
06589     }
06590 
06591   finish:
06592     twocomp2abs_bang(z, hibitsx || hibitsy);
06593     RB_GC_GUARD(x);
06594     return bignorm(z);
06595 }
06596 
06597 /*
06598  * call-seq:
06599  *     big | numeric   ->  integer
06600  *
06601  * Performs bitwise +or+ between _big_ and _numeric_.
06602  */
06603 
06604 VALUE
06605 rb_big_or(VALUE x, VALUE y)
06606 {
06607     VALUE z;
06608     BDIGIT *ds1, *ds2, *zds;
06609     long i, xn, yn, n1, n2;
06610     BDIGIT hibitsx, hibitsy;
06611     BDIGIT hibits1, hibits2;
06612     VALUE tmpv;
06613     BDIGIT tmph;
06614     long tmpn;
06615 
06616     if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
06617         return rb_num_coerce_bit(x, y, '|');
06618     }
06619 
06620     hibitsx = abs2twocomp(&x, &xn);
06621     if (FIXNUM_P(y)) {
06622         return bigor_int(x, xn, hibitsx, FIX2LONG(y));
06623     }
06624     hibitsy = abs2twocomp(&y, &yn);
06625     if (xn > yn) {
06626         tmpv = x; x = y; y = tmpv;
06627         tmpn = xn; xn = yn; yn = tmpn;
06628         tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
06629     }
06630     n1 = xn;
06631     n2 = yn;
06632     ds1 = BDIGITS(x);
06633     ds2 = BDIGITS(y);
06634     hibits1 = hibitsx;
06635     hibits2 = hibitsy;
06636 
06637     if (hibits1)
06638         n2 = n1;
06639 
06640     z = bignew(n2, 0);
06641     zds = BDIGITS(z);
06642 
06643     for (i=0; i<n1; i++) {
06644         zds[i] = ds1[i] | ds2[i];
06645     }
06646     for (; i<n2; i++) {
06647         zds[i] = hibits1 | ds2[i];
06648     }
06649     twocomp2abs_bang(z, hibits1 || hibits2);
06650     RB_GC_GUARD(x);
06651     RB_GC_GUARD(y);
06652     return bignorm(z);
06653 }
06654 
06655 static VALUE
06656 bigxor_int(VALUE x, long xn, BDIGIT hibitsx, long y)
06657 {
06658     VALUE z;
06659     BDIGIT *xds, *zds;
06660     long zn;
06661     long i;
06662     BDIGIT hibitsy;
06663 
06664     hibitsy = 0 <= y ? 0 : BDIGMAX;
06665     xds = BDIGITS(x);
06666     zn = RBIGNUM_LEN(x);
06667 #if SIZEOF_BDIGITS < SIZEOF_LONG
06668     if (zn < bdigit_roomof(SIZEOF_LONG))
06669         zn = bdigit_roomof(SIZEOF_LONG);
06670 #endif
06671     z = bignew(zn, 0);
06672     zds = BDIGITS(z);
06673 
06674 #if SIZEOF_BDIGITS >= SIZEOF_LONG
06675     i = 1;
06676     zds[0] = xds[0] ^ BIGLO(y);
06677 #else
06678     for (i = 0; i < xn; i++) {
06679         zds[i] = xds[i] ^ BIGLO(y);
06680         y = BIGDN(y);
06681     }
06682     for (; i < zn; i++) {
06683         zds[i] = hibitsx ^ BIGLO(y);
06684         y = BIGDN(y);
06685     }
06686 #endif
06687     for (; i < xn; i++) {
06688         zds[i] = xds[i] ^ hibitsy;
06689     }
06690     for (; i < zn; i++) {
06691         zds[i] = hibitsx ^ hibitsy;
06692     }
06693     twocomp2abs_bang(z, (hibitsx ^ hibitsy) != 0);
06694     RB_GC_GUARD(x);
06695     return bignorm(z);
06696 }
06697 /*
06698  * call-seq:
06699  *     big ^ numeric   ->  integer
06700  *
06701  * Performs bitwise +exclusive or+ between _big_ and _numeric_.
06702  */
06703 
06704 VALUE
06705 rb_big_xor(VALUE x, VALUE y)
06706 {
06707     VALUE z;
06708     BDIGIT *ds1, *ds2, *zds;
06709     long i, xn, yn, n1, n2;
06710     BDIGIT hibitsx, hibitsy;
06711     BDIGIT hibits1, hibits2;
06712     VALUE tmpv;
06713     BDIGIT tmph;
06714     long tmpn;
06715 
06716     if (!FIXNUM_P(y) && !RB_BIGNUM_TYPE_P(y)) {
06717         return rb_num_coerce_bit(x, y, '^');
06718     }
06719 
06720     hibitsx = abs2twocomp(&x, &xn);
06721     if (FIXNUM_P(y)) {
06722         return bigxor_int(x, xn, hibitsx, FIX2LONG(y));
06723     }
06724     hibitsy = abs2twocomp(&y, &yn);
06725     if (xn > yn) {
06726         tmpv = x; x = y; y = tmpv;
06727         tmpn = xn; xn = yn; yn = tmpn;
06728         tmph = hibitsx; hibitsx = hibitsy; hibitsy = tmph;
06729     }
06730     n1 = xn;
06731     n2 = yn;
06732     ds1 = BDIGITS(x);
06733     ds2 = BDIGITS(y);
06734     hibits1 = hibitsx;
06735     hibits2 = hibitsy;
06736 
06737     z = bignew(n2, 0);
06738     zds = BDIGITS(z);
06739 
06740     for (i=0; i<n1; i++) {
06741         zds[i] = ds1[i] ^ ds2[i];
06742     }
06743     for (; i<n2; i++) {
06744         zds[i] = hibitsx ^ ds2[i];
06745     }
06746     twocomp2abs_bang(z, (hibits1 ^ hibits2) != 0);
06747     RB_GC_GUARD(x);
06748     RB_GC_GUARD(y);
06749     return bignorm(z);
06750 }
06751 
06752 /*
06753  * call-seq:
06754  *     big << numeric   ->  integer
06755  *
06756  * Shifts big left _numeric_ positions (right if _numeric_ is negative).
06757  */
06758 
06759 VALUE
06760 rb_big_lshift(VALUE x, VALUE y)
06761 {
06762     int lshift_p;
06763     size_t shift_numdigits;
06764     int shift_numbits;
06765 
06766     for (;;) {
06767         if (FIXNUM_P(y)) {
06768             long l = FIX2LONG(y);
06769             unsigned long shift;
06770             if (0 <= l) {
06771                 lshift_p = 1;
06772                 shift = l;
06773             }
06774             else {
06775                 lshift_p = 0;
06776                 shift = 1+(unsigned long)(-(l+1));
06777             }
06778             shift_numbits = (int)(shift & (BITSPERDIG-1));
06779             shift_numdigits = shift >> bit_length(BITSPERDIG-1);
06780             return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
06781         }
06782         else if (RB_BIGNUM_TYPE_P(y)) {
06783             return bignorm(big_shift2(x, 1, y));
06784         }
06785         y = rb_to_int(y);
06786     }
06787 }
06788 
06789 
06790 /*
06791  * call-seq:
06792  *     big >> numeric   ->  integer
06793  *
06794  * Shifts big right _numeric_ positions (left if _numeric_ is negative).
06795  */
06796 
06797 VALUE
06798 rb_big_rshift(VALUE x, VALUE y)
06799 {
06800     int lshift_p;
06801     size_t shift_numdigits;
06802     int shift_numbits;
06803 
06804     for (;;) {
06805         if (FIXNUM_P(y)) {
06806             long l = FIX2LONG(y);
06807             unsigned long shift;
06808             if (0 <= l) {
06809                 lshift_p = 0;
06810                 shift = l;
06811             }
06812             else {
06813                 lshift_p = 1;
06814                 shift = 1+(unsigned long)(-(l+1));
06815             }
06816             shift_numbits = (int)(shift & (BITSPERDIG-1));
06817             shift_numdigits = shift >> bit_length(BITSPERDIG-1);
06818             return bignorm(big_shift3(x, lshift_p, shift_numdigits, shift_numbits));
06819         }
06820         else if (RB_BIGNUM_TYPE_P(y)) {
06821             return bignorm(big_shift2(x, 0, y));
06822         }
06823         y = rb_to_int(y);
06824     }
06825 }
06826 
06827 /*
06828  *  call-seq:
06829  *     big[n] -> 0, 1
06830  *
06831  *  Bit Reference---Returns the <em>n</em>th bit in the (assumed) binary
06832  *  representation of <i>big</i>, where <i>big</i>[0] is the least
06833  *  significant bit.
06834  *
06835  *     a = 9**15
06836  *     50.downto(0) do |n|
06837  *       print a[n]
06838  *     end
06839  *
06840  *  <em>produces:</em>
06841  *
06842  *     000101110110100000111000011110010100111100010111001
06843  *
06844  */
06845 
06846 static VALUE
06847 rb_big_aref(VALUE x, VALUE y)
06848 {
06849     BDIGIT *xds;
06850     unsigned long shift;
06851     long i, s1, s2;
06852     BDIGIT bit;
06853 
06854     if (RB_BIGNUM_TYPE_P(y)) {
06855         if (!RBIGNUM_SIGN(y))
06856             return INT2FIX(0);
06857         bigtrunc(y);
06858         if (BIGSIZE(y) > sizeof(long)) {
06859           out_of_range:
06860             return RBIGNUM_SIGN(x) ? INT2FIX(0) : INT2FIX(1);
06861         }
06862         shift = big2ulong(y, "long");
06863     }
06864     else {
06865         i = NUM2LONG(y);
06866         if (i < 0) return INT2FIX(0);
06867         shift = i;
06868     }
06869     s1 = shift/BITSPERDIG;
06870     s2 = shift%BITSPERDIG;
06871     bit = (BDIGIT)1 << s2;
06872 
06873     if (s1 >= RBIGNUM_LEN(x)) goto out_of_range;
06874 
06875     xds = BDIGITS(x);
06876     if (RBIGNUM_POSITIVE_P(x))
06877         return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
06878     if (xds[s1] & (bit-1))
06879         return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
06880     for (i = 0; i < s1; i++)
06881         if (xds[i])
06882             return (xds[s1] & bit) ? INT2FIX(0) : INT2FIX(1);
06883     return (xds[s1] & bit) ? INT2FIX(1) : INT2FIX(0);
06884 }
06885 
06886 /*
06887  * call-seq:
06888  *   big.hash   -> fixnum
06889  *
06890  * Compute a hash based on the value of _big_.
06891  */
06892 
06893 static VALUE
06894 rb_big_hash(VALUE x)
06895 {
06896     st_index_t hash;
06897 
06898     hash = rb_memhash(BDIGITS(x), sizeof(BDIGIT)*RBIGNUM_LEN(x)) ^ RBIGNUM_SIGN(x);
06899     return INT2FIX(hash);
06900 }
06901 
06902 /*
06903  * call-seq:
06904  *   big.coerce(numeric)  ->  array
06905  *
06906  * Returns an array with both a +numeric+ and a +big+ represented as Bignum
06907  * objects.
06908  *
06909  * This is achieved by converting +numeric+ to a Bignum.
06910  *
06911  * A TypeError is raised if the +numeric+ is not a Fixnum or Bignum type.
06912  *
06913  *     (0x3FFFFFFFFFFFFFFF+1).coerce(42)   #=> [42, 4611686018427387904]
06914  */
06915 
06916 static VALUE
06917 rb_big_coerce(VALUE x, VALUE y)
06918 {
06919     if (FIXNUM_P(y)) {
06920         y = rb_int2big(FIX2LONG(y));
06921     }
06922     else if (!RB_BIGNUM_TYPE_P(y)) {
06923         rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
06924                  rb_obj_classname(y));
06925     }
06926     return rb_assoc_new(y, x);
06927 }
06928 
06929 /*
06930  *  call-seq:
06931  *     big.abs -> aBignum
06932  *     big.magnitude -> aBignum
06933  *
06934  *  Returns the absolute value of <i>big</i>.
06935  *
06936  *     -1234567890987654321.abs   #=> 1234567890987654321
06937  */
06938 
06939 static VALUE
06940 rb_big_abs(VALUE x)
06941 {
06942     if (!RBIGNUM_SIGN(x)) {
06943         x = rb_big_clone(x);
06944         RBIGNUM_SET_SIGN(x, 1);
06945     }
06946     return x;
06947 }
06948 
06949 /*
06950  *  call-seq:
06951  *     big.size -> integer
06952  *
06953  *  Returns the number of bytes in the machine representation of
06954  *  <i>big</i>.
06955  *
06956  *     (256**10 - 1).size   #=> 12
06957  *     (256**20 - 1).size   #=> 20
06958  *     (256**40 - 1).size   #=> 40
06959  */
06960 
06961 static VALUE
06962 rb_big_size(VALUE big)
06963 {
06964     return SIZET2NUM(BIGSIZE(big));
06965 }
06966 
06967 /*
06968  *  call-seq:
06969  *     int.bit_length -> integer
06970  *
06971  *  Returns the number of bits of the value of <i>int</i>.
06972  *
06973  *  "the number of bits" means that
06974  *  the bit position of the highest bit which is different to the sign bit.
06975  *  (The bit position of the bit 2**n is n+1.)
06976  *  If there is no such bit (zero or minus one), zero is returned.
06977  *
06978  *  I.e. This method returns ceil(log2(int < 0 ? -int : int+1)).
06979  *
06980  *     (-2**10000-1).bit_length  #=> 10001
06981  *     (-2**10000).bit_length    #=> 10000
06982  *     (-2**10000+1).bit_length  #=> 10000
06983  *
06984  *     (-2**1000-1).bit_length   #=> 1001
06985  *     (-2**1000).bit_length     #=> 1000
06986  *     (-2**1000+1).bit_length   #=> 1000
06987  *
06988  *     (2**1000-1).bit_length    #=> 1000
06989  *     (2**1000).bit_length      #=> 1001
06990  *     (2**1000+1).bit_length    #=> 1001
06991  *
06992  *     (2**10000-1).bit_length   #=> 10000
06993  *     (2**10000).bit_length     #=> 10001
06994  *     (2**10000+1).bit_length   #=> 10001
06995  *
06996  */
06997 
06998 static VALUE
06999 rb_big_bit_length(VALUE big)
07000 {
07001     int nlz_bits;
07002     size_t numbytes;
07003 
07004     static const BDIGIT char_bit[1] = { CHAR_BIT };
07005     BDIGIT numbytes_bary[bdigit_roomof(sizeof(size_t))];
07006     BDIGIT nlz_bary[1];
07007     BDIGIT result_bary[bdigit_roomof(sizeof(size_t)+1)];
07008 
07009     numbytes = rb_absint_size(big, &nlz_bits);
07010 
07011     if (numbytes == 0)
07012         return LONG2FIX(0);
07013 
07014     if (RBIGNUM_NEGATIVE_P(big) && rb_absint_singlebit_p(big)) {
07015         if (nlz_bits != CHAR_BIT-1) {
07016             nlz_bits++;
07017         }
07018         else {
07019             nlz_bits = 0;
07020             numbytes--;
07021         }
07022     }
07023 
07024     if (numbytes <= SIZE_MAX / CHAR_BIT) {
07025         return SIZET2NUM(numbytes * CHAR_BIT - nlz_bits);
07026     }
07027 
07028     nlz_bary[0] = nlz_bits;
07029 
07030     bary_unpack(BARY_ARGS(numbytes_bary), &numbytes, 1, sizeof(numbytes), 0,
07031             INTEGER_PACK_NATIVE_BYTE_ORDER);
07032     BARY_SHORT_MUL(result_bary, numbytes_bary, char_bit);
07033     BARY_SUB(result_bary, result_bary, nlz_bary);
07034 
07035     return rb_integer_unpack(result_bary, numberof(result_bary), sizeof(BDIGIT), 0,
07036             INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
07037 }
07038 
07039 /*
07040  *  call-seq:
07041  *     big.odd? -> true or false
07042  *
07043  *  Returns <code>true</code> if <i>big</i> is an odd number.
07044  */
07045 
07046 static VALUE
07047 rb_big_odd_p(VALUE num)
07048 {
07049     if (RBIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
07050         return Qtrue;
07051     }
07052     return Qfalse;
07053 }
07054 
07055 /*
07056  *  call-seq:
07057  *     big.even? -> true or false
07058  *
07059  *  Returns <code>true</code> if <i>big</i> is an even number.
07060  */
07061 
07062 static VALUE
07063 rb_big_even_p(VALUE num)
07064 {
07065     if (RBIGNUM_LEN(num) != 0 && BDIGITS(num)[0] & 1) {
07066         return Qfalse;
07067     }
07068     return Qtrue;
07069 }
07070 
07071 /*
07072  *  Bignum objects hold integers outside the range of
07073  *  Fixnum. Bignum objects are created
07074  *  automatically when integer calculations would otherwise overflow a
07075  *  Fixnum. When a calculation involving
07076  *  Bignum objects returns a result that will fit in a
07077  *  Fixnum, the result is automatically converted.
07078  *
07079  *  For the purposes of the bitwise operations and <code>[]</code>, a
07080  *  Bignum is treated as if it were an infinite-length
07081  *  bitstring with 2's complement representation.
07082  *
07083  *  While Fixnum values are immediate, Bignum
07084  *  objects are not---assignment and parameter passing work with
07085  *  references to objects, not the objects themselves.
07086  *
07087  */
07088 
07089 void
07090 Init_Bignum(void)
07091 {
07092     rb_cBignum = rb_define_class("Bignum", rb_cInteger);
07093 
07094     rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
07095     rb_define_alias(rb_cBignum, "inspect", "to_s");
07096     rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
07097     rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
07098     rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
07099     rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
07100     rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
07101     rb_define_method(rb_cBignum, "/", rb_big_div, 1);
07102     rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
07103     rb_define_method(rb_cBignum, "div", rb_big_idiv, 1);
07104     rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
07105     rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
07106     rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
07107     rb_define_method(rb_cBignum, "fdiv", rb_big_fdiv, 1);
07108     rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
07109     rb_define_method(rb_cBignum, "&", rb_big_and, 1);
07110     rb_define_method(rb_cBignum, "|", rb_big_or, 1);
07111     rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
07112     rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
07113     rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
07114     rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
07115     rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
07116 
07117     rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
07118     rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
07119     rb_define_method(rb_cBignum, ">", big_gt, 1);
07120     rb_define_method(rb_cBignum, ">=", big_ge, 1);
07121     rb_define_method(rb_cBignum, "<", big_lt, 1);
07122     rb_define_method(rb_cBignum, "<=", big_le, 1);
07123     rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
07124     rb_define_method(rb_cBignum, "eql?", rb_big_eql, 1);
07125     rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
07126     rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
07127     rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
07128     rb_define_method(rb_cBignum, "magnitude", rb_big_abs, 0);
07129     rb_define_method(rb_cBignum, "size", rb_big_size, 0);
07130     rb_define_method(rb_cBignum, "bit_length", rb_big_bit_length, 0);
07131     rb_define_method(rb_cBignum, "odd?", rb_big_odd_p, 0);
07132     rb_define_method(rb_cBignum, "even?", rb_big_even_p, 0);
07133 
07134 #ifdef USE_GMP
07135     rb_define_const(rb_cBignum, "GMP_VERSION", rb_sprintf("GMP %s", gmp_version));
07136 #endif
07137 
07138     power_cache_init();
07139 }
07140 

Generated on 19 Jul 2016 for Ruby by  doxygen 1.4.7