[前][次][番号順一覧][スレッド一覧]

ruby-changes:30727

From: akr <ko1@a...>
Date: Tue, 3 Sep 2013 20:20:16 +0900 (JST)
Subject: [ruby-changes:30727] akr:r42806 (trunk): * bignum.c (GMP_STR2BIG_DIGITS): New macro.

akr	2013-09-03 20:20:02 +0900 (Tue, 03 Sep 2013)

  New Revision: 42806

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42806

  Log:
    * bignum.c (GMP_STR2BIG_DIGITS): New macro.
      (str2big_gmp): New function.
      (rb_cstr_to_inum): Use str2big_gmp for big bignums.
      (rb_str2big_gmp): New function.
    
    * internal.h (rb_str2big_gmp): Declared.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
    trunk/ext/-test-/bignum/str2big.c
    trunk/internal.h
    trunk/test/-ext-/bignum/test_str2big.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42805)
+++ ChangeLog	(revision 42806)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Tue Sep  3 20:12:46 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (GMP_STR2BIG_DIGITS): New macro.
+	  (str2big_gmp): New function.
+	  (rb_cstr_to_inum): Use str2big_gmp for big bignums.
+	  (rb_str2big_gmp): New function.
+
+	* internal.h (rb_str2big_gmp): Declared.
+
 Tue Sep  3 19:44:40 2013  NAKAMURA Usaku  <usa@r...>
 
 	* ext/win32/lib/win32/registry.rb (Win32::Registry#values): added.
Index: ext/-test-/bignum/str2big.c
===================================================================
--- ext/-test-/bignum/str2big.c	(revision 42805)
+++ ext/-test-/bignum/str2big.c	(revision 42806)
@@ -19,10 +19,21 @@ str2big_karatsuba(VALUE str, VALUE vbase https://github.com/ruby/ruby/blob/trunk/ext/-test-/bignum/str2big.c#L19
     return rb_str2big_karatsuba(str, NUM2INT(vbase), RTEST(badcheck));
 }
 
+#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
+static VALUE
+str2big_gmp(VALUE str, VALUE vbase, VALUE badcheck)
+{
+    return rb_str2big_gmp(str, NUM2INT(vbase), RTEST(badcheck));
+}
+#else
+#define str2big_gmp rb_f_notimplement
+#endif
+
 void
 Init_str2big(VALUE klass)
 {
     rb_define_method(rb_cString, "str2big_poweroftwo", str2big_poweroftwo, 2);
     rb_define_method(rb_cString, "str2big_normal", str2big_normal, 2);
     rb_define_method(rb_cString, "str2big_karatsuba", str2big_karatsuba, 2);
+    rb_define_method(rb_cString, "str2big_gmp", str2big_gmp, 2);
 }
Index: internal.h
===================================================================
--- internal.h	(revision 42805)
+++ internal.h	(revision 42806)
@@ -653,6 +653,7 @@ VALUE rb_str2big_karatsuba(VALUE arg, in https://github.com/ruby/ruby/blob/trunk/internal.h#L653
 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
 VALUE rb_big_mul_gmp(VALUE x, VALUE y);
 VALUE rb_big2str_gmp(VALUE x, int base);
+VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
 #endif
 
 /* file.c */
Index: bignum.c
===================================================================
--- bignum.c	(revision 42805)
+++ bignum.c	(revision 42806)
@@ -136,6 +136,7 @@ STATIC_ASSERT(sizeof_long_and_sizeof_bdi https://github.com/ruby/ruby/blob/trunk/bignum.c#L136
 #define TOOM3_MUL_DIGITS 150
 
 #define GMP_BIG2STR_DIGITS 20
+#define GMP_STR2BIG_DIGITS 20
 
 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);
 
@@ -3781,6 +3782,50 @@ str2big_karatsuba( https://github.com/ruby/ruby/blob/trunk/bignum.c#L3782
     return z;
 }
 
+#ifdef USE_GMP
+static VALUE
+str2big_gmp(
+    int sign,
+    const char *digits_start,
+    const char *digits_end,
+    size_t num_digits,
+    size_t num_bdigits,
+    int base)
+{
+    const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGITS)*CHAR_BIT;
+    char *buf, *p;
+    const char *q;
+    VALUE tmps;
+    mpz_t mz;
+    VALUE z;
+    BDIGIT *zds;
+    size_t zn, count;
+
+    buf = ALLOCV_N(char, tmps, num_digits+1);
+    p = buf;
+    for (q = digits_start; q < digits_end; q++) {
+        if (conv_digit(*q) < 0)
+            continue;
+        *p++ = *q;
+    }
+    *p = '\0';
+
+    mpz_init(mz);
+    mpz_set_str(mz, buf, base);
+    zn = num_bdigits;
+    z = bignew(zn, sign);
+    zds = BDIGITS(z);
+    mpz_export(BDIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
+    BDIGITS_ZERO(zds+count, zn-count);
+    mpz_clear(mz);
+
+    if (tmps)
+        ALLOCV_END(tmps);
+
+    return z;
+}
+#endif
+
 VALUE
 rb_cstr_to_inum(const char *str, int base, int badcheck)
 {
@@ -3927,6 +3972,13 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L3972
         maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
         num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
 
+#ifdef USE_GMP
+        if (GMP_STR2BIG_DIGITS < num_bdigits) {
+            z = str2big_gmp(sign, digits_start, digits_end, num_digits,
+                    num_bdigits, base);
+        }
+        else
+#endif
         if (num_bdigits < KARATSUBA_MUL_DIGITS) {
             z = str2big_normal(sign, digits_start, digits_end,
                     num_bdigits, base);
@@ -4083,6 +4135,46 @@ rb_str2big_karatsuba(VALUE arg, int base https://github.com/ruby/ruby/blob/trunk/bignum.c#L4135
     return bignorm(z);
 }
 
+#ifdef USE_GMP
+VALUE
+rb_str2big_gmp(VALUE arg, int base, int badcheck)
+{
+    int positive_p = 1;
+    const char *s, *str;
+    const char *digits_start, *digits_end;
+    size_t num_digits;
+    size_t len;
+    VALUE z;
+
+    int digits_per_bdigits_dbl;
+    size_t num_bdigits;
+
+    if (base < 2 || 36 < base) {
+        rb_raise(rb_eArgError, "invalid radix %d", base);
+    }
+
+    rb_must_asciicompat(arg);
+    s = str = StringValueCStr(arg);
+    if (*str == '-') {
+        str++;
+        positive_p = 0;
+    }
+
+    digits_start = str;
+    str2big_scan_digits(s, str, base, badcheck, &num_digits, &len);
+    digits_end = digits_start + len;
+
+    maxpow_in_bdigit_dbl(base, &digits_per_bdigits_dbl);
+    num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
+
+    z = str2big_gmp(positive_p, digits_start, digits_end, num_digits, num_bdigits, base);
+
+    RB_GC_GUARD(arg);
+
+    return bignorm(z);
+}
+#endif
+
 #if HAVE_LONG_LONG
 
 static VALUE
Index: test/-ext-/bignum/test_str2big.rb
===================================================================
--- test/-ext-/bignum/test_str2big.rb	(revision 42805)
+++ test/-ext-/bignum/test_str2big.rb	(revision 42806)
@@ -26,5 +26,12 @@ class TestBignum < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/bignum/test_str2big.rb#L26
       assert_equal(n, s.str2big_karatsuba(10, true))
     end
 
+    def test_str2big_gmp
+      s = "1" + "0" * 1000
+      n = 10 ** 1000
+      assert_equal(n, s.str2big_gmp(10, true))
+    rescue NotImplementedError
+    end
+
   end
 end

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]