00001
00002
00003
00004
00005
00006
00007
00008
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
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
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
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
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 {
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
00810 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
00811 sign *= 2;
00812 else {
00813 if (de - dp == 1 && dp[0] == 1)
00814 sign = -1;
00815 else
00816 sign = -2;
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
00878 if (dp != de || 1 < dd) {
00879
00880 sign *= 2;
00881 }
00882 else if (dd == 1) {
00883
00884 if (!(flags & INTEGER_PACK_2COMP) || 0 <= sign)
00885 sign *= 2;
00886 else {
00887
00888 dp = ds;
00889 while (dp < de && *dp == 0)
00890 dp++;
00891 if (de - dp == 1 &&
00892 POW2_P(*dp))
00893 sign = -1;
00894 else
00895 sign = -2;
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
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
00971
00972
00973
00974
00975 size_t num_bytes1 = wordsize * numwords;
00976
00977
00978 size_t q1 = numwords / CHAR_BIT;
00979 size_t r1 = numwords % CHAR_BIT;
00980
00981
00982 size_t num_bytes2 = num_bytes1 - nails * q1;
00983
00984
00985 size_t q2 = nails / CHAR_BIT;
00986 size_t r2 = nails % CHAR_BIT;
00987
00988
00989 size_t num_bytes3 = num_bytes2 - q2 * r1;
00990
00991
00992 size_t q3 = num_bytes3 / BITSPERDIG;
00993 size_t r3 = num_bytes3 % BITSPERDIG;
00994
00995
00996 size_t num_digits1 = CHAR_BIT * q3;
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
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;
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
01551
01552
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
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
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
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
01715
01716
01717
01718
01719
01720 wn = 2*n;
01721 wds = ALLOCV_N(BDIGIT, work, wn);
01722 }
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
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
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
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
01766
01767 bary_mul_karatsuba_start(zds1, 2*n, zds0, n, wds, n, wds+n, wn-n);
01768 }
01769
01770
01771
01772 borrow = 0;
01773 if (sub_p) {
01774 borrow = !bary_2comp(zds1, 2*n);
01775 }
01776
01777
01778 MEMCPY(wds, zds1, BDIGIT, n);
01779
01780
01781
01782 bary_mul_karatsuba_start(zds0, 2*n, xds0, n, yds0, n, wds+n, wn-n);
01783
01784
01785
01786 carry1 = bary_add(wds, n, wds, n, zds0, n);
01787 carry1 = bary_addc(zds2, n, zds2, n, zds1, n, carry1);
01788
01789
01790
01791 carry2 = bary_add(zds1, n, zds1, n, wds, n);
01792
01793
01794
01795 MEMCPY(wds, zds2, BDIGIT, n);
01796
01797
01798
01799 bary_mul_karatsuba_start(zds2, zn-2*n, xds1, xn-n, yds1, n, wds+n, wn-n);
01800
01801
01802
01803 carry3 = bary_add(zds1, n, zds1, n, zds2, n);
01804
01805
01806
01807 carry3 = bary_addc(zds2, n, zds2, n, zds3, (4*n < zn ? n : zn-3*n), carry3);
01808
01809
01810
01811 bary_add(zds2, zn-2*n, zds2, zn-2*n, wds, n);
01812
01813
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
01827
01828
01829
01830
01831
01832
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
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);
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);
01909 wnc += (u2n = n+1);
01910 wnc += (u3n = n+1);
01911 wnc += (v1n = n+1);
01912 wnc += (v2n = n+1);
01913 wnc += (v3n = n+1);
01914
01915 wnc += (t0n = 2*n);
01916 wnc += (t1n = 2*n+2);
01917 wnc += (t2n = 2*n+2);
01918 wnc += (t3n = 2*n+2);
01919 wnc += (t4n = 2*n);
01920
01921 wnc += (z1n = 2*n+1);
01922 wnc += (z2n = 2*n+1);
01923 wnc += (z3n = 2*n+1);
01924
01925 if (wn < wnc) {
01926 wn = wnc * 3 / 2;
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
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012 bary_add(u1ds, u1n, x0ds, x0n, x2ds, x2n);
02013 u1p = 1;
02014
02015
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
02025 bary_add(u1ds, u1n, u1ds, u1n, x1ds, x1n);
02026
02027
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
02052 bary_add(v1ds, v1n, y0ds, y0n, y2ds, y2n);
02053 v1p = 1;
02054
02055
02056 v2p = 1;
02057 if (bary_sub(v2ds, v2n, v1ds, v1n, y1ds, y1n)) {
02058 bary_2comp(v2ds, v2n);
02059 v2p = 0;
02060 }
02061
02062
02063 bary_add(v1ds, v1n, v1ds, v1n, y1ds, y1n);
02064
02065
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
02085 bary_mul_toom3_start(t0ds, t0n, x0ds, x0n, y0ds, y0n, wds, wn);
02086 t0p = 1;
02087
02088
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
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
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
02107 bary_mul_toom3_start(t4ds, t4n, x2ds, x2n, y2ds, y2n, wds, wn);
02108 t4p = 1;
02109
02110
02111
02112
02113
02114
02115 z0n = t0n; z0ds = t0ds;
02116
02117
02118 z4n = t4n; z4ds = t4ds;
02119
02120
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
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
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
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
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
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
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
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;
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
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
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
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
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
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) {
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
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
02673
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
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)
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
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));
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
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225
03226
03227
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
03311
03312
03313
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
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357
03358
03359
03360
03361
03362
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
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
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)
03467 return 0;
03468 if (dp != de-1)
03469 return 0;
03470 d = *dp;
03471 return POW2_P(d);
03472 }
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525
03526
03527
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
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590
03591
03592
03593
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
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') {
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;
04076 while (*end && ISSPACE(*end)) end++;
04077 if (*end) goto bad;
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]) {
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));
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
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
04503
04504
04505
04506
04507
04508
04509
04510
04511
04512
04513
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
04544
04545
04546
04547
04548
04549
04550
04551
04552
04553
04554
04555
04556
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
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));
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
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685 if (xn == 0 || bary_zero_p(xds, xn)) {
04686 if (b2s->ptr) {
04687
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
04744
04745 tds = (BDIGIT *)bds;
04746 xds[xn] = 0;
04747 }
04748 else {
04749
04750
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
04850
04851
04852
04853
04854
04855
04856
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
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
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
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
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];
05068 }
05069 #endif
05070 return num;
05071 }
05072
05073
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
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
05285
05286
05287
05288
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
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
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
05382
05383
05384
05385
05386
05387
05388
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
05463
05464
05465
05466
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
05477
05478
05479
05480
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
05491
05492
05493
05494
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
05505
05506
05507
05508
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
05519
05520
05521
05522
05523
05524
05525
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
05551
05552
05553
05554
05555
05556
05557
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
05572
05573
05574
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
05589
05590
05591
05592
05593
05594
05595
05596
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
05861
05862
05863
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
05897
05898
05899
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
05991
05992
05993
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
06153
06154
06155
06156
06157
06158
06159
06160 VALUE
06161 rb_big_div(VALUE x, VALUE y)
06162 {
06163 return rb_big_divide(x, y, '/');
06164 }
06165
06166
06167
06168
06169
06170
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
06181
06182
06183
06184
06185
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
06206
06207
06208
06209
06210
06211
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
06231
06232
06233
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
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
06309
06310
06311
06312
06313
06314
06315
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
06351
06352
06353
06354
06355
06356
06357
06358
06359
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
06473
06474
06475
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
06599
06600
06601
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
06699
06700
06701
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
06754
06755
06756
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
06792
06793
06794
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
06829
06830
06831
06832
06833
06834
06835
06836
06837
06838
06839
06840
06841
06842
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
06888
06889
06890
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
06904
06905
06906
06907
06908
06909
06910
06911
06912
06913
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
06931
06932
06933
06934
06935
06936
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
06951
06952
06953
06954
06955
06956
06957
06958
06959
06960
06961 static VALUE
06962 rb_big_size(VALUE big)
06963 {
06964 return SIZET2NUM(BIGSIZE(big));
06965 }
06966
06967
06968
06969
06970
06971
06972
06973
06974
06975
06976
06977
06978
06979
06980
06981
06982
06983
06984
06985
06986
06987
06988
06989
06990
06991
06992
06993
06994
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
07041
07042
07043
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
07057
07058
07059
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
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
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