25 
25 
#endif

26 
26 
#include <assert.h>

27 
27 


28 
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)


29 
#define USE_GMP


30 
#include <gmp.h>


31 
#endif


32 

28 
33 
VALUE rb_cBignum;

29 
34 
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";

30 
35 

...  ...  
129 
134 
#define KARATSUBA_BALANCED(xn, yn) ((yn)/2 < (xn))

130 
135 
#define TOOM3_BALANCED(xn, yn) (((yn)+2)/3 * 2 < (xn))

131 
136 


137 
#define GMP_MUL_DIGITS 20

132 
138 
#define KARATSUBA_MUL_DIGITS 70

133 
139 
#define TOOM3_MUL_DIGITS 150

134 
140 

...  ...  
2409 
2415 
return z;

2410 
2416 
}

2411 
2417 


2418 
#ifdef USE_GMP


2419 
static void


2420 
bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)


2421 
{


2422 
const size_t nails = (sizeof(BDIGIT)SIZEOF_BDIGITS)*CHAR_BIT;


2423 
mpz_t x, y, z;


2424 
size_t count;


2425 


2426 
assert(xn + yn <= zn);


2427 


2428 
mpz_inits(x, y, z, 0);


2429 
mpz_import(x, xn, 1, sizeof(BDIGIT), 0, nails, xds);


2430 
if (xds == yds && xn == yn) {


2431 
mpz_mul(z, x, x);


2432 
}


2433 
else {


2434 
mpz_import(y, yn, 1, sizeof(BDIGIT), 0, nails, yds);


2435 
mpz_mul(z, x, y);


2436 
}


2437 
mpz_export (zds, &count, 1, sizeof(BDIGIT), 0, nails, z);


2438 
BDIGITS_ZERO(zds+count, zncount);


2439 
mpz_clears(x, y, z, 0);


2440 
}


2441 


2442 
VALUE


2443 
rb_big_mul_gmp(VALUE x, VALUE y)


2444 
{


2445 
size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), zn = xn + yn;


2446 
VALUE z = bignew(zn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y));


2447 
bary_mul_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn);


2448 
RB_GC_GUARD(x);


2449 
RB_GC_GUARD(y);


2450 
return z;


2451 
}


2452 
#endif


2453 

2412 
2454 
static void

2413 
2455 
bary_mul1(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)

2414 
2456 
{

...  ...  
2601 
2643 
static void

2602 
2644 
bary_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn)

2603 
2645 
{


2646 
#ifdef USE_GMP


2647 
const size_t naive_threshold = GMP_MUL_DIGITS;


2648 
#else


2649 
const size_t naive_threshold = KARATSUBA_MUL_DIGITS;


2650 
#endif

2604 
2651 
if (xn <= yn) {

2605 

if (xn < KARATSUBA_MUL_DIGITS) {


2652 
if (xn < naive_threshold) {

2606 
2653 
if (xds == yds && xn == yn)

2607 
2654 
bary_sq_fast(zds, zn, xds, xn);

2608 
2655 
else

...  ...  
2611 
2658 
}

2612 
2659 
}

2613 
2660 
else {

2614 

if (yn < KARATSUBA_MUL_DIGITS) {


2661 
if (yn < naive_threshold) {

2615 
2662 
bary_mul1(zds, zn, yds, yn, xds, xn);

2616 
2663 
return;

2617 
2664 
}

2618 
2665 
}

2619 
2666 


2667 
#ifdef USE_GMP


2668 
bary_mul_gmp(zds, zn, xds, xn, yds, yn);


2669 
#else

2620 
2670 
bary_mul_toom3_start(zds, zn, xds, xn, yds, yn, NULL, 0);


2671 
#endif

2621 
2672 
}

2622 
2673 

2623 
2674 
struct big_div_struct {

...  ...  
5580 
5631 
xds = BDIGITS(x);

5581 
5632 
zds = BDIGITS(z);

5582 
5633 


5634 
#ifdef USE_GMP


5635 
if (xn < GMP_MUL_DIGITS)


5636 
bary_sq_fast(zds, zn, xds, xn);


5637 
else


5638 
bary_mul(zds, zn, xds, xn, xds, xn);


5639 
#else

5583 
5640 
if (xn < KARATSUBA_MUL_DIGITS)

5584 
5641 
bary_sq_fast(zds, zn, xds, xn);

5585 
5642 
else

5586 
5643 
bary_mul(zds, zn, xds, xn, xds, xn);


5644 
#endif

5587 
5645 

5588 
5646 
RB_GC_GUARD(x);

5589 
5647 
return z;
