bignum-mul-gmp.patch

Akira Tanaka, 08/17/2013 04:10 AM

Download (5.04 KB)

View differences:

configure.in (working copy)
1048 1048
  setjmpex.h
1049 1049
)
1050 1050

  
1051
AC_ARG_WITH([gmp],
1052
  [AS_HELP_STRING([--without-gmp],
1053
    [disable GNU GMP to accelerate Bignum operations])],
1054
  [],
1055
  [with_gmp=yes])
1056
AS_IF([test "x$with_gmp" != xno],
1057
  [AC_CHECK_HEADERS(gmp.h)
1058
   AS_IF([test "x$ac_cv_header_gmp_h" != xno],
1059
     AC_CHECK_LIB([gmp], [__gmpz_init]))])
1060

  
1051 1061
dnl check for large file stuff
1052 1062
mv confdefs.h confdefs1.h
1053 1063
: > confdefs.h
bignum.c (working copy)
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, zn-count);
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;
ext/-test-/bignum/mul.c (working copy)
42 42
    return rb_big_norm(rb_big_mul_toom3(big(x), big(y)));
43 43
}
44 44

  
45
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
46
static VALUE
47
mul_gmp(VALUE x, VALUE y)
48
{
49
    return rb_big_norm(rb_big_mul_gmp(big(x), big(y)));
50
}
51
#else
52
#define mul_gmp rb_f_notimplement
53
#endif
54

  
45 55
void
46 56
Init_mul(VALUE klass)
47 57
{
......
52 62
    rb_define_method(rb_cInteger, "big_mul_balance", mul_balance, 1);
53 63
    rb_define_method(rb_cInteger, "big_mul_karatsuba", mul_karatsuba, 1);
54 64
    rb_define_method(rb_cInteger, "big_mul_toom3", mul_toom3, 1);
65
    rb_define_method(rb_cInteger, "big_mul_gmp", mul_gmp, 1);
55 66
}
internal.h (working copy)
512 512
VALUE rb_big_mul_balance(VALUE x, VALUE y);
513 513
VALUE rb_big_mul_karatsuba(VALUE x, VALUE y);
514 514
VALUE rb_big_mul_toom3(VALUE x, VALUE y);
515
#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
516
VALUE rb_big_mul_gmp(VALUE x, VALUE y);
517
#endif
515 518
VALUE rb_big_sq_fast(VALUE x);
516 519

  
517 520
/* file.c */