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

ruby-changes:30697

From: akr <ko1@a...>
Date: Mon, 2 Sep 2013 22:52:10 +0900 (JST)
Subject: [ruby-changes:30697] akr:r42776 (trunk): * bignum.c (str2big_poweroftwo): Extracted from rb_cstr_to_inum.

akr	2013-09-02 22:52:05 +0900 (Mon, 02 Sep 2013)

  New Revision: 42776

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

  Log:
    * bignum.c (str2big_poweroftwo): Extracted from rb_cstr_to_inum.
      (str2big_normal): Ditto.
      (str2big_karatsuba): Ditto.

  Modified files:
    trunk/ChangeLog
    trunk/bignum.c
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 42775)
+++ ChangeLog	(revision 42776)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Mon Sep  2 22:49:15 2013  Tanaka Akira  <akr@f...>
+
+	* bignum.c (str2big_poweroftwo): Extracted from rb_cstr_to_inum.
+	  (str2big_normal): Ditto.
+	  (str2big_karatsuba): Ditto.
+
 Mon Sep  2 17:53:33 2013  Nobuyoshi Nakada  <nobu@r...>
 
 	* parse.y (str_suffix_gen): String#b creates new string object, use
Index: bignum.c
===================================================================
--- bignum.c	(revision 42775)
+++ bignum.c	(revision 42776)
@@ -3567,6 +3567,176 @@ rb_quad_unpack(const char *buf, int sign https://github.com/ruby/ruby/blob/trunk/bignum.c#L3567
             (signed_p ? INTEGER_PACK_2COMP : 0));
 }
 
+#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
+
+static VALUE
+str2big_poweroftwo(
+    int sign,
+    const char *digits_start,
+    const char *digits_end,
+    size_t num_digits,
+    int bits_per_digit)
+{
+    BDIGIT *dp;
+    BDIGIT_DBL dd;
+    int numbits;
+
+    size_t num_bdigits;
+    const char *p;
+    int c;
+    VALUE z;
+
+    num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
+    z = bignew(num_bdigits, sign);
+    dp = BDIGITS(z);
+    dd = 0;
+    numbits = 0;
+    for (p = digits_end; digits_start < p; p--) {
+        if ((c = conv_digit(p[-1])) < 0)
+            continue;
+        dd |= (BDIGIT_DBL)c << numbits;
+        numbits += bits_per_digit;
+        if (BITSPERDIG <= numbits) {
+            *dp++ = BIGLO(dd);
+            dd = BIGDN(dd);
+            numbits -= BITSPERDIG;
+        }
+    }
+    if (numbits) {
+        *dp++ = BIGLO(dd);
+    }
+    assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
+
+    return z;
+}
+
+static VALUE
+str2big_normal(
+    int sign,
+    const char *digits_start,
+    const char *digits_end,
+    size_t num_bdigits,
+    int base)
+{
+    size_t blen = 1;
+    BDIGIT *zds;
+    BDIGIT_DBL num;
+
+    size_t i;
+    const char *p;
+    int c;
+    VALUE z;
+
+    z = bignew(num_bdigits, sign);
+    zds = BDIGITS(z);
+    BDIGITS_ZERO(zds, num_bdigits);
+
+    for (p = digits_start; p < digits_end; p++) {
+        if ((c = conv_digit(*p)) < 0)
+            continue;
+        num = c;
+        i = 0;
+        for (;;) {
+            while (i<blen) {
+                num += (BDIGIT_DBL)zds[i]*base;
+                zds[i++] = BIGLO(num);
+                num = BIGDN(num);
+            }
+            if (num) {
+                blen++;
+                continue;
+            }
+            break;
+        }
+        assert(blen <= num_bdigits);
+    }
+
+    return z;
+}
+
+static VALUE
+str2big_karatsuba(
+    int sign,
+    const char *digits_start,
+    const char *digits_end,
+    size_t num_digits,
+    size_t num_bdigits,
+    int digits_per_bdigits_dbl,
+    int base)
+{
+    VALUE powerv;
+    size_t unit;
+    VALUE tmpuv = 0;
+    BDIGIT *uds, *vds, *tds;
+    BDIGIT_DBL dd;
+    BDIGIT_DBL current_base;
+    int m;
+    int power_level = 0;
+
+    size_t i;
+    const char *p;
+    int c;
+    VALUE z;
+
+    uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
+    vds = uds + num_bdigits;
+
+    powerv = power_cache_get_power(base, power_level, NULL);
+
+    i = 0;
+    dd = 0;
+    current_base = 1;
+    m = digits_per_bdigits_dbl;
+    if (num_digits < (size_t)m)
+        m = (int)num_digits;
+    for (p = digits_end; digits_start < p; p--) {
+        if ((c = conv_digit(p[-1])) < 0)
+            continue;
+        dd = dd + c * current_base;
+        current_base *= base;
+        num_digits--;
+        m--;
+        if (m == 0) {
+            uds[i++] = BIGLO(dd);
+            uds[i++] = (BDIGIT)BIGDN(dd);
+            dd = 0;
+            m = digits_per_bdigits_dbl;
+            if (num_digits < (size_t)m)
+                m = (int)num_digits;
+            current_base = 1;
+        }
+    }
+    assert(i == num_bdigits);
+    for (unit = 2; unit < num_bdigits; unit *= 2) {
+        for (i = 0; i < num_bdigits; i += unit*2) {
+            if (2*unit <= num_bdigits - i) {
+                bary_mul(vds+i, unit*2, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, unit);
+                bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
+            }
+            else if (unit <= num_bdigits - i) {
+                bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
+                bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
+            }
+            else {
+                MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
+            }
+        }
+        power_level++;
+        powerv = power_cache_get_power(base, power_level, NULL);
+        tds = vds;
+        vds = uds;
+        uds = tds;
+    }
+    BARY_TRUNC(uds, num_bdigits);
+    z = bignew(num_bdigits, sign);
+    MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
+
+    if (tmpuv)
+        ALLOCV_END(tmpuv);
+
+    return z;
+}
+
 VALUE
 rb_cstr_to_inum(const char *str, int base, int badcheck)
 {
@@ -3576,15 +3746,13 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L3746
     VALUE z;
 
     int bits_per_digit;
-    size_t i;
 
-    const char *digits_start, *digits_end, *p;
+    const char *digits_start, *digits_end;
     size_t num_digits;
     size_t num_bdigits;
 
 #undef ISDIGIT
 #define ISDIGIT(c) ('0' <= (c) && (c) <= '9')
-#define conv_digit(c) (ruby_digit36_to_number_table[(unsigned char)(c)])
 
     if (!str) {
 	if (badcheck) goto bad;
@@ -3699,6 +3867,7 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L3867
 	    return bignorm(big);
 	}
     }
+
   bigparse:
     if (badcheck && *str == '_') goto bad;
 
@@ -3732,29 +3901,8 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L3901
     }
 
     if (POW2_P(base)) {
-        BDIGIT *dp;
-        BDIGIT_DBL dd;
-        int numbits;
-        num_bdigits = (num_digits / BITSPERDIG) * bits_per_digit + roomof((num_digits % BITSPERDIG) * bits_per_digit, BITSPERDIG);
-        z = bignew(num_bdigits, sign);
-        dp = BDIGITS(z);
-        dd = 0;
-        numbits = 0;
-        for (p = digits_end; digits_start < p; p--) {
-            if ((c = conv_digit(p[-1])) < 0)
-                continue;
-            dd |= (BDIGIT_DBL)c << numbits;
-            numbits += bits_per_digit;
-            if (BITSPERDIG <= numbits) {
-                *dp++ = BIGLO(dd);
-                dd = BIGDN(dd);
-                numbits -= BITSPERDIG;
-            }
-        }
-        if (numbits) {
-            *dp++ = BIGLO(dd);
-        }
-        assert((size_t)(dp - BDIGITS(z)) == num_bdigits);
+        z = str2big_poweroftwo(sign, digits_start, digits_end, num_digits,
+                bits_per_digit);
     }
     else {
         int digits_per_bdigits_dbl;
@@ -3762,99 +3910,12 @@ rb_cstr_to_inum(const char *str, int bas https://github.com/ruby/ruby/blob/trunk/bignum.c#L3910
         num_bdigits = roomof(num_digits, digits_per_bdigits_dbl)*2;
 
         if (num_bdigits < KARATSUBA_MUL_DIGITS) {
-            size_t blen = 1;
-            BDIGIT *zds;
-            BDIGIT_DBL num;
-
-            z = bignew(num_bdigits, sign);
-            zds = BDIGITS(z);
-            BDIGITS_ZERO(zds, num_bdigits);
-
-            for (p = digits_start; p < digits_end; p++) {
-                if ((c = conv_digit(*p)) < 0)
-                    continue;
-                num = c;
-                i = 0;
-                for (;;) {
-                    while (i<blen) {
-                        num += (BDIGIT_DBL)zds[i]*base;
-                        zds[i++] = BIGLO(num);
-                        num = BIGDN(num);
-                    }
-                    if (num) {
-                        blen++;
-                        continue;
-                    }
-                    break;
-                }
-                assert(blen <= num_bdigits);
-            }
+            z = str2big_normal(sign, digits_start, digits_end,
+                    num_bdigits, base);
         }
         else {
-            VALUE powerv;
-            size_t unit;
-            VALUE tmpuv = 0;
-            BDIGIT *uds, *vds, *tds;
-            BDIGIT_DBL dd;
-            BDIGIT_DBL current_base;
-            int m;
-            int power_level = 0;
-
-            uds = ALLOCV_N(BDIGIT, tmpuv, 2*num_bdigits);
-            vds = uds + num_bdigits;
-
-            powerv = power_cache_get_power(base, power_level, NULL);
-
-            i = 0;
-            dd = 0;
-            current_base = 1;
-            m = digits_per_bdigits_dbl;
-            if (num_digits < (size_t)m)
-                m = (int)num_digits;
-            for (p = digits_end; digits_start < p; p--) {
-                if ((c = conv_digit(p[-1])) < 0)
-                    continue;
-                dd = dd + c * current_base;
-                current_base *= base;
-                num_digits--;
-                m--;
-                if (m == 0) {
-                    uds[i++] = BIGLO(dd);
-                    uds[i++] = (BDIGIT)BIGDN(dd);
-                    dd = 0;
-                    m = digits_per_bdigits_dbl;
-                    if (num_digits < (size_t)m)
-                        m = (int)num_digits;
-                    current_base = 1;
-                }
-            }
-            assert(i == num_bdigits);
-            for (unit = 2; unit < num_bdigits; unit *= 2) {
-                for (i = 0; i < num_bdigits; i += unit*2) {
-                    if (2*unit <= num_bdigits - i) {
-                        bary_mul(vds+i, unit*2, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, unit);
-                        bary_add(vds+i, unit*2, vds+i, unit*2, uds+i, unit);
-                    }
-                    else if (unit <= num_bdigits - i) {
-                        bary_mul(vds+i, num_bdigits-i, BDIGITS(powerv), RBIGNUM_LEN(powerv), uds+i+unit, num_bdigits-(i+unit));
-                        bary_add(vds+i, num_bdigits-i, vds+i, num_bdigits-i, uds+i, unit);
-                    }
-                    else {
-                        MEMCPY(vds+i, uds+i, BDIGIT, num_bdigits-i);
-                    }
-                }
-                power_level++;
-                powerv = power_cache_get_power(base, power_level, NULL);
-                tds = vds;
-                vds = uds;
-                uds = tds;
-            }
-            BARY_TRUNC(uds, num_bdigits);
-            z = bignew(num_bdigits, sign);
-            MEMCPY(BDIGITS(z), uds, BDIGIT, num_bdigits);
-
-            if (tmpuv)
-                ALLOCV_END(tmpuv);
+            z = str2big_karatsuba(sign, digits_start, digits_end, num_digits,
+                    num_bdigits, digits_per_bdigits_dbl, base);
         }
     }
 

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

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