summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-09-04 16:10:06 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-09-04 16:10:06 +0000
commit8f8bf8243d810d49a98dcb2713b14de3bf3716e0 (patch)
treec6abe5461a6b3c784d613a9284ca9a583170d8fd /bignum.c
parentff5a4c998340eff7c3d6867836d387d7a5159dec (diff)
* 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. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42834 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/bignum.c b/bignum.c
index ec1411e7f4..6092376061 100644
--- a/bignum.c
+++ b/bignum.c
@@ -2644,6 +2644,7 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT
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 qn, BDIGIT *rds, size_t rn, const BDIGIT
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)
{