diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-03 03:50:15 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2013-09-03 03:50:15 +0000 |
commit | 0b2413b471e5a23c619078f75b191c38619b35df (patch) | |
tree | 191b9cd91cabad6d75834ec5a4b4f767fcebf3dd | |
parent | 1df73dd9adb3c11af6a5a3dc5839b8f87e8070a0 (diff) |
* bignum.c (rb_str2big_poweroftwo): New function.
(rb_str2big_normal): Ditto.
(rb_str2big_karatsuba): Ditto.
* internal.h (rb_str2big_poweroftwo): Declared.
(rb_str2big_normal): Ditto.
(rb_str2big_karatsuba): Ditto.
* ext/-test-/bignum/str2big.c: New file.
* test/-ext-/bignum/test_str2big.rb: New file.
* ext/-test-/bignum/depend: Add the dependency for str2big.c.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42797 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | bignum.c | 111 | ||||
-rw-r--r-- | ext/-test-/bignum/depend | 1 | ||||
-rw-r--r-- | ext/-test-/bignum/str2big.c | 28 | ||||
-rw-r--r-- | internal.h | 3 | ||||
-rw-r--r-- | test/-ext-/bignum/test_str2big.rb | 30 |
6 files changed, 189 insertions, 0 deletions
@@ -1,3 +1,19 @@ +Tue Sep 3 12:45:23 2013 Tanaka Akira <akr@fsij.org> + + * bignum.c (rb_str2big_poweroftwo): New function. + (rb_str2big_normal): Ditto. + (rb_str2big_karatsuba): Ditto. + + * internal.h (rb_str2big_poweroftwo): Declared. + (rb_str2big_normal): Ditto. + (rb_str2big_karatsuba): Ditto. + + * ext/-test-/bignum/str2big.c: New file. + + * test/-ext-/bignum/test_str2big.rb: New file. + + * ext/-test-/bignum/depend: Add the dependency for str2big.c. + Tue Sep 3 12:09:08 2013 Tanaka Akira <akr@fsij.org> * process.c (rb_clock_gettime): Support times() based monotonic clock. @@ -3972,6 +3972,117 @@ rb_str_to_inum(VALUE str, int base, int badcheck) return ret; } +VALUE +rb_str2big_poweroftwo(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; + + if (base < 2 || 36 < base || !POW2_P(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; + + z = str2big_poweroftwo(positive_p, digits_start, digits_end, num_digits, + bit_length(base-1)); + + RB_GC_GUARD(arg); + + return bignorm(z); +} + +VALUE +rb_str2big_normal(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_normal(positive_p, digits_start, digits_end, + num_bdigits, base); + + RB_GC_GUARD(arg); + + return bignorm(z); +} + +VALUE +rb_str2big_karatsuba(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_karatsuba(positive_p, digits_start, digits_end, num_digits, + num_bdigits, digits_per_bdigits_dbl, base); + + RB_GC_GUARD(arg); + + return bignorm(z); +} + #if HAVE_LONG_LONG static VALUE diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend index cac4d52a12..4634ecf627 100644 --- a/ext/-test-/bignum/depend +++ b/ext/-test-/bignum/depend @@ -3,3 +3,4 @@ $(OBJS): $(HDRS) $(ruby_headers) intpack.o: intpack.c $(top_srcdir)/internal.h mul.o: mul.c $(top_srcdir)/internal.h big2str.o: big2str.c $(top_srcdir)/internal.h +str2big.o: big2str.c $(top_srcdir)/internal.h diff --git a/ext/-test-/bignum/str2big.c b/ext/-test-/bignum/str2big.c new file mode 100644 index 0000000000..b6492fa73f --- /dev/null +++ b/ext/-test-/bignum/str2big.c @@ -0,0 +1,28 @@ +#include "ruby.h" +#include "internal.h" + +static VALUE +str2big_poweroftwo(VALUE str, VALUE vbase, VALUE badcheck) +{ + return rb_str2big_poweroftwo(str, NUM2INT(vbase), RTEST(badcheck)); +} + +static VALUE +str2big_normal(VALUE str, VALUE vbase, VALUE badcheck) +{ + return rb_str2big_normal(str, NUM2INT(vbase), RTEST(badcheck)); +} + +static VALUE +str2big_karatsuba(VALUE str, VALUE vbase, VALUE badcheck) +{ + return rb_str2big_karatsuba(str, NUM2INT(vbase), RTEST(badcheck)); +} + +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); +} diff --git a/internal.h b/internal.h index 9d7ce97b4c..bf5446bf8b 100644 --- a/internal.h +++ b/internal.h @@ -647,6 +647,9 @@ VALUE rb_big_mul_toom3(VALUE x, VALUE y); VALUE rb_big_sq_fast(VALUE x); VALUE rb_big2str_poweroftwo(VALUE x, int base); VALUE rb_big2str_generic(VALUE x, int base); +VALUE rb_str2big_poweroftwo(VALUE arg, int base, int badcheck); +VALUE rb_str2big_normal(VALUE arg, int base, int badcheck); +VALUE rb_str2big_karatsuba(VALUE arg, int base, int badcheck); #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); diff --git a/test/-ext-/bignum/test_str2big.rb b/test/-ext-/bignum/test_str2big.rb new file mode 100644 index 0000000000..ac55c78082 --- /dev/null +++ b/test/-ext-/bignum/test_str2big.rb @@ -0,0 +1,30 @@ +require 'test/unit' +require "-test-/bignum" + +class TestBignum < Test::Unit::TestCase + class TestStr2big < Test::Unit::TestCase + + SIZEOF_BDIGITS = Bignum::SIZEOF_BDIGITS + BITSPERDIG = Bignum::BITSPERDIG + BDIGMAX = (1 << BITSPERDIG) - 1 + + def test_str2big_poweroftwo + s = "1" + "0" * 1000 + n = 16 ** 1000 + assert_equal(n, s.str2big_poweroftwo(16, true)) + end + + def test_str2big_normal + s = "1" + "0" * 1000 + n = 10 ** 1000 + assert_equal(n, s.str2big_normal(10, true)) + end + + def test_str2big_karatsuba + s = "1" + "0" * 1000 + n = 10 ** 1000 + assert_equal(n, s.str2big_karatsuba(10, true)) + end + + end +end |