From 5f61a592e9f560a7de63ca072ef767c1e8495be1 Mon Sep 17 00:00:00 2001 From: akr Date: Mon, 2 Sep 2013 13:52:05 +0000 Subject: [PATCH] * bignum.c (str2big_poweroftwo): Extracted from rb_cstr_to_inum. (str2big_normal): Ditto. (str2big_karatsuba): Ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42776 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++ bignum.c | 295 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 184 insertions(+), 117 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5064be39f8..608935e212 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Mon Sep 2 22:49:15 2013 Tanaka Akira + + * 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 * parse.y (str_suffix_gen): String#b creates new string object, use diff --git a/bignum.c b/bignum.c index 9bebf7224a..472126f548 100644 --- a/bignum.c +++ b/bignum.c @@ -3567,6 +3567,176 @@ rb_quad_unpack(const char *buf, int signed_p) (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