summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-03-17 10:06:57 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>1998-03-17 10:06:57 +0000
commit4c3d81d323f2876d5528fc9601cff55c88c6f566 (patch)
tree92eb620a2238c53401118b9ca5c920dbb1ca7d91 /bignum.c
parenta94679135080615136be4d83a66b3f964b8d66a4 (diff)
modulo, frexp, ldexp
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c44
1 files changed, 35 insertions, 9 deletions
diff --git a/bignum.c b/bignum.c
index 8a6e54a9da..8ca00fcd6f 100644
--- a/bignum.c
+++ b/bignum.c
@@ -662,12 +662,13 @@ big_mul(x, y)
}
static void
-bigdivmod(x, y, div, mod)
+bigdivmod(x, y, div, mod, modulo)
VALUE x, y;
VALUE *div, *mod;
+ int modulo;
{
UINT nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len, i, j;
- VALUE z;
+ VALUE yy, z;
USHORT *xds, *yds, *zds, *tds;
unsigned long t2;
long num;
@@ -703,8 +704,8 @@ bigdivmod(x, y, div, mod)
if (nx==ny) zds[nx+1] = 0;
while (!yds[ny-1]) ny--;
if ((dd = BIGRAD/(int)(yds[ny-1]+1)) != 1) {
- y = big_clone(y);
- tds = BDIGITS(y);
+ yy = big_clone(y);
+ tds = BDIGITS(yy);
j = 0;
num = 0;
while (j<ny) {
@@ -776,7 +777,16 @@ bigdivmod(x, y, div, mod)
}
}
RBIGNUM(*mod)->len = ny;
- RBIGNUM(*mod)->sign = RBIGNUM(y)->sign;
+ RBIGNUM(*mod)->sign = RBIGNUM(x)->sign;
+ if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) {
+ int len = ny;
+ zds = BDIGITS(*mod);
+ while (len-- && !zds[len]);
+ if (len > 0) {
+ *mod = bigadd(*mod, y, 1);
+ return;
+ }
+ }
*mod = bignorm(*mod);
}
}
@@ -801,14 +811,16 @@ big_div(x, y)
default:
return num_coerce_bin(x, y);
}
- bigdivmod(x, y, &z, 0);
+ bigdivmod(x, y, &z, 0, 0);
return z;
}
+
static VALUE
-big_mod(x, y)
+big_modulo(x, y, modulo)
VALUE x, y;
+ int modulo;
{
VALUE z;
@@ -827,12 +839,26 @@ big_mod(x, y)
default:
return num_coerce_bin(x, y);
}
- bigdivmod(x, y, 0, &z);
+ bigdivmod(x, y, 0, &z, modulo);
return z;
}
static VALUE
+big_mod(x, y)
+ VALUE x, y;
+{
+ return big_modulo(x, y, 1);
+}
+
+static VALUE
+big_remainder(x, y)
+ VALUE x, y;
+{
+ return big_modulo(x, y, 0);
+}
+
+static VALUE
big_divmod(x, y)
VALUE x, y;
{
@@ -853,7 +879,7 @@ big_divmod(x, y)
default:
return num_coerce_bin(x, y);
}
- bigdivmod(x, y, &div, &mod);
+ bigdivmod(x, y, &div, &mod, 1);
return assoc_new(div, mod);;
}