ruby-changes:30755
From: akr <ko1@a...>
Date: Thu, 5 Sep 2013 01:10:15 +0900 (JST)
Subject: [ruby-changes:30755] akr:r42834 (trunk): * bignum.c (rb_big_divrem_normal): New function.
akr 2013-09-05 01:10:06 +0900 (Thu, 05 Sep 2013) New Revision: 42834 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=42834 Log: * bignum.c (rb_big_divrem_normal): New function. * internal.h (rb_big_divrem_normal): Declared. * ext/-test-/bignum/div.c: New file. * test/-ext-/bignum/test_div.rb: New file. Added files: trunk/ext/-test-/bignum/div.c trunk/test/-ext-/bignum/test_div.rb Modified files: trunk/ChangeLog trunk/bignum.c trunk/ext/-test-/bignum/depend trunk/internal.h Index: ChangeLog =================================================================== --- ChangeLog (revision 42833) +++ ChangeLog (revision 42834) @@ -1,3 +1,13 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Sep 5 00:38:32 2013 Tanaka Akira <akr@f...> + + * bignum.c (rb_big_divrem_normal): New function. + + * internal.h (rb_big_divrem_normal): Declared. + + * ext/-test-/bignum/div.c: New file. + + * test/-ext-/bignum/test_div.rb: New file. + Thu Sep 5 00:08:44 2013 Tanaka Akira <akr@f...> * bignum.c (bigdivrem_normal): Removed. Index: ext/-test-/bignum/depend =================================================================== --- ext/-test-/bignum/depend (revision 42833) +++ ext/-test-/bignum/depend (revision 42834) @@ -2,5 +2,6 @@ $(OBJS): $(HDRS) $(ruby_headers) https://github.com/ruby/ruby/blob/trunk/ext/-test-/bignum/depend#L2 intpack.o: intpack.c $(top_srcdir)/internal.h mul.o: mul.c $(top_srcdir)/internal.h +div.o: div.c $(top_srcdir)/internal.h big2str.o: big2str.c $(top_srcdir)/internal.h str2big.o: big2str.c $(top_srcdir)/internal.h Index: ext/-test-/bignum/div.c =================================================================== --- ext/-test-/bignum/div.c (revision 0) +++ ext/-test-/bignum/div.c (revision 42834) @@ -0,0 +1,25 @@ https://github.com/ruby/ruby/blob/trunk/ext/-test-/bignum/div.c#L1 +#include "ruby.h" +#include "internal.h" + +static VALUE +big(VALUE x) +{ + if (FIXNUM_P(x)) + return rb_int2big(FIX2LONG(x)); + if (RB_TYPE_P(x, T_BIGNUM)) + return x; + rb_raise(rb_eTypeError, "can't convert %s to Bignum", + rb_obj_classname(x)); +} + +static VALUE +divrem_normal(VALUE x, VALUE y) +{ + return rb_big_norm(rb_big_divrem_normal(big(x), big(y))); +} + +void +Init_div(VALUE klass) +{ + rb_define_method(rb_cInteger, "big_divrem_normal", divrem_normal, 1); +} Index: internal.h =================================================================== --- internal.h (revision 42833) +++ internal.h (revision 42834) @@ -696,6 +696,7 @@ VALUE rb_big_mul_balance(VALUE x, VALUE https://github.com/ruby/ruby/blob/trunk/internal.h#L696 VALUE rb_big_mul_karatsuba(VALUE x, VALUE y); VALUE rb_big_mul_toom3(VALUE x, VALUE y); VALUE rb_big_sq_fast(VALUE x); +VALUE rb_big_divrem_normal(VALUE x, VALUE y); 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); Index: bignum.c =================================================================== --- bignum.c (revision 42833) +++ bignum.c (revision 42834) @@ -2644,6 +2644,7 @@ bary_divmod_normal(BDIGIT *qds, size_t q https://github.com/ruby/ruby/blob/trunk/bignum.c#L2644 VALUE tmpz = 0; VALUE tmpyy = 0; + assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); assert(qds ? (xn - yn + 1) <= qn : 1); assert(rds ? yn <= rn : 1); @@ -2696,6 +2697,37 @@ bary_divmod_normal(BDIGIT *qds, size_t q https://github.com/ruby/ruby/blob/trunk/bignum.c#L2697 ALLOCV_END(tmpz); } +VALUE +rb_big_divrem_normal(VALUE x, VALUE y) +{ + size_t xn = RBIGNUM_LEN(x), yn = RBIGNUM_LEN(y), qn, rn; + BDIGIT *xds = BDIGITS(x), *yds = BDIGITS(y), *qds, *rds; + VALUE q, r; + + BARY_TRUNC(yds, yn); + if (yn == 0) + rb_num_zerodiv(); + BARY_TRUNC(xds, xn); + + if (xn < yn || (xn == yn && xds[xn - 1] < yds[yn - 1])) + return rb_assoc_new(LONG2FIX(0), x); + + qn = xn + BIGDIVREM_EXTRA_WORDS; + q = bignew(qn, RBIGNUM_SIGN(x)==RBIGNUM_SIGN(y)); + qds = BDIGITS(q); + + rn = yn; + r = bignew(rn, RBIGNUM_SIGN(x)); + rds = BDIGITS(r); + + bary_divmod_normal(qds, qn, rds, rn, xds, xn, yds, yn); + + bigtrunc(q); + bigtrunc(r); + + return rb_assoc_new(q, r); +} + static void bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn) { Index: test/-ext-/bignum/test_div.rb =================================================================== --- test/-ext-/bignum/test_div.rb (revision 0) +++ test/-ext-/bignum/test_div.rb (revision 42834) @@ -0,0 +1,19 @@ https://github.com/ruby/ruby/blob/trunk/test/-ext-/bignum/test_div.rb#L1 +require 'test/unit' +require "-test-/bignum" + +class TestBignum < Test::Unit::TestCase + class TestDiv < Test::Unit::TestCase + + SIZEOF_BDIGITS = Bignum::SIZEOF_BDIGITS + BITSPERDIG = Bignum::BITSPERDIG + BDIGMAX = (1 << BITSPERDIG) - 1 + + def test_divrem_normal + x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3 + y = (1 << BITSPERDIG) | 1 + q = (1 << BITSPERDIG) | 1 + r = 2 + assert_equal([q, r], x.big_divrem_normal(y)) + end + end +end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/