summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--numeric.c28
-rw-r--r--test/ruby/test_float.rb28
-rw-r--r--util.c84
4 files changed, 81 insertions, 71 deletions
diff --git a/ChangeLog b/ChangeLog
index 8f11859f3c..95962c77c5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+Mon May 1 12:23:19 2006 <sinara@blade.nagaokaut.ac.jp>
+
+ * numeric.c (num_div): use floor rather than rb_Integer().
+ [ruby-dev:28589]
+
+ * numeric.c (flo_divmod): the first element of Float#divmod should
+ be an integer. [ruby-dev:28589]
+
+ * test/ruby/test_float.rb: add tests for divmod, div, modulo and remainder.
+
Sat Apr 29 22:42:08 2006 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_asn1.c (ossl_asn1_decode0): should initialize
@@ -8,6 +18,8 @@ Fri Apr 28 10:53:16 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* util.c (ruby_strtod): should not cut off 18 digits for no
reason. [ruby-core:07796]
+ * util.c (ruby_strtod): fixed wrong conversion.
+
Thu Apr 27 01:38:10 2006 Yukihiro Matsumoto <matz@ruby-lang.org>
* array.c (rb_ary_fill): internalize local variable "beg" to
diff --git a/numeric.c b/numeric.c
index 4c8bacdaf6..a937868ce4 100644
--- a/numeric.c
+++ b/numeric.c
@@ -256,6 +256,8 @@ num_quo(x, y)
}
+static VALUE num_floor(VALUE num);
+
/*
* call-seq:
* num.div(numeric) => integer
@@ -269,7 +271,7 @@ static VALUE
num_div(x, y)
VALUE x, y;
{
- return rb_Integer(rb_funcall(x, '/', 1, y));
+ return num_floor(rb_funcall(x, '/', 1, y));
}
@@ -297,21 +299,21 @@ num_div(x, y)
* ------+-----+---------------+---------+-------------+---------------
* -13 | -4 | 3, -1 | 3 | -1 | -1
* ------+-----+---------------+---------+-------------+---------------
- * 11.5 | 4 | 2.0, 3.5 | 2.875 | 3.5 | 3.5
+ * 11.5 | 4 | 2, 3.5 | 2.875 | 3.5 | 3.5
* ------+-----+---------------+---------+-------------+---------------
- * 11.5 | -4 | -3.0, -0.5 | -2.875 | -0.5 | 3.5
+ * 11.5 | -4 | -3, -0.5 | -2.875 | -0.5 | 3.5
* ------+-----+---------------+---------+-------------+---------------
- * -11.5 | 4 | -3.0 0.5 | -2.875 | 0.5 | -3.5
+ * -11.5 | 4 | -3, 0.5 | -2.875 | 0.5 | -3.5
* ------+-----+---------------+---------+-------------+---------------
- * -11.5 | -4 | 2.0 -3.5 | 2.875 | -3.5 | -3.5
+ * -11.5 | -4 | 2 -3.5 | 2.875 | -3.5 | -3.5
*
*
* Examples
* 11.divmod(3) #=> [3, 2]
* 11.divmod(-3) #=> [-4, -1]
- * 11.divmod(3.5) #=> [3.0, 0.5]
- * (-11).divmod(3.5) #=> [-4.0, 3.0]
- * (11.5).divmod(3.5) #=> [3.0, 1.0]
+ * 11.divmod(3.5) #=> [3, 0.5]
+ * (-11).divmod(3.5) #=> [-4, 3.0]
+ * (11.5).divmod(3.5) #=> [3, 1.0]
*/
static VALUE
@@ -715,7 +717,7 @@ static VALUE
flo_divmod(x, y)
VALUE x, y;
{
- double fy, div, mod;
+ double fy, div, mod, val;
volatile VALUE a, b;
switch (TYPE(y)) {
@@ -732,7 +734,13 @@ flo_divmod(x, y)
return rb_num_coerce_bin(x, y);
}
flodivmod(RFLOAT(x)->value, fy, &div, &mod);
- a = rb_float_new(div);
+ if (FIXABLE(div)) {
+ val = div;
+ a = LONG2FIX(val);
+ }
+ else {
+ a = rb_dbl2big(div);
+ }
b = rb_float_new(mod);
return rb_assoc_new(a, b);
}
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 63979b5be0..c2e5041a21 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -87,4 +87,32 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError){Float("1e")}
# add expected behaviour here.
end
+
+ def test_divmod
+ assert_equal([2, 3.5], 11.5.divmod(4))
+ assert_equal([-3, -0.5], 11.5.divmod(-4))
+ assert_equal([-3, 0.5], (-11.5).divmod(4))
+ assert_equal([2, -3.5], (-11.5).divmod(-4))
+ end
+
+ def test_div
+ assert_equal(2, 11.5.div(4))
+ assert_equal(-3, 11.5.div(-4))
+ assert_equal(-3, (-11.5).div(4))
+ assert_equal(2, (-11.5).div(-4))
+ end
+
+ def test_modulo
+ assert_equal(3.5, 11.5.modulo(4))
+ assert_equal(-0.5, 11.5.modulo(-4))
+ assert_equal(0.5, (-11.5).modulo(4))
+ assert_equal(-3.5, (-11.5).modulo(-4))
+ end
+
+ def test_remainder
+ assert_equal(3.5, 11.5.remainder(4))
+ assert_equal(3.5, 11.5.remainder(-4))
+ assert_equal(-3.5, (-11.5).remainder(4))
+ assert_equal(-3.5, (-11.5).remainder(-4))
+ end
end
diff --git a/util.c b/util.c
index c4fd2fd2fa..42ab81039b 100644
--- a/util.c
+++ b/util.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <errno.h>
#include <math.h>
+#include <float.h>
#ifdef _WIN32
#include "missing/file.h"
@@ -750,26 +751,25 @@ ruby_strtod(string, endPtr)
errno = 0;
p = string;
- while (ISSPACE(*p)) {
- p += 1;
- }
+ while (ISSPACE(*p)) p++;
if (*p == '-') {
sign = Qtrue;
- p += 1;
+ p++;
}
else {
- if (*p == '+') {
- p += 1;
- }
+ if (*p == '+') p++;
sign = Qfalse;
}
+ fraction = 0.;
+ exp = 0;
+
/*
* Count the number of digits in the mantissa
* and also locate the decimal point.
*/
- for ( ; c = *p; p += 1) {
+ for ( ; c = *p; p++) {
if (!ISDIGIT(c)) {
if (c != '.' || hasPoint) {
break;
@@ -778,13 +778,13 @@ ruby_strtod(string, endPtr)
}
else {
if (hasPoint) { /* already in fractional part */
- fracExp -= 1;
+ fracExp--;
}
if (mantSize) { /* already in mantissa */
- mantSize += 1;
+ mantSize++;
}
else if (c != '0') { /* have entered mantissa */
- mantSize += 1;
+ mantSize++;
pMant = p;
}
hasDigit = Qtrue;
@@ -807,30 +807,17 @@ ruby_strtod(string, endPtr)
mantSize = 18;
}
if (!hasDigit) {
+ errno = ERANGE;
fraction = 0.0;
p = string;
}
else {
- double frac1, frac2;
- frac1 = 0;
- for ( ; mantSize > 9; mantSize -= 1) {
- c = *p;
- p += 1;
+ for (; mantSize > 0; mantSize--) {
+ c = *p++;
if (c == '.') {
- c = *p;
- p += 1;
+ c = *p++;
}
- frac1 = 10*frac1 + (c - '0');
- }
- frac2 = 0;
- for (; mantSize > 0; mantSize -= 1) {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac2 = 10*frac2 + (c - '0');
+ fraction = 10*fraction + (c - '0');
}
/*
@@ -839,21 +826,20 @@ ruby_strtod(string, endPtr)
p = pExp;
if ((*p == 'E') || (*p == 'e')) {
- p += 1;
+ p++;
if (*p == '-') {
expSign = Qtrue;
- p += 1;
+ p++;
}
else {
if (*p == '+') {
- p += 1;
+ p++;
}
expSign = Qfalse;
}
if (ISDIGIT(*p)) {
do {
- exp = exp * 10 + (*p - '0');
- p += 1;
+ exp = exp * 10 + (*p++ - '0');
}
while (ISDIGIT(*p));
}
@@ -883,29 +869,6 @@ ruby_strtod(string, endPtr)
errno = ERANGE;
return 0.0 * (sign ? -1.0 : 1.0);
}
- if (frac1 > 0) {
- fracExp = exp;
- exp += 9;
- if (exp < 0) {
- expSign = Qtrue;
- exp = -exp;
- }
- else {
- expSign = Qfalse;
- }
- dblExp = 10.0;
- while (exp) {
- if (exp & 1) {
- if (expSign)
- frac1 /= dblExp;
- else
- frac1 *= dblExp;
- }
- exp >>= 1;
- dblExp *= dblExp;
- }
- fraction = frac1;
- }
if (exp < 0) {
expSign = Qtrue;
exp = -exp;
@@ -918,18 +881,17 @@ ruby_strtod(string, endPtr)
{
if (exp & 1) {
if (expSign)
- frac2 /= dblExp;
+ fraction /= dblExp;
else
- frac2 *= dblExp;
+ fraction *= dblExp;
}
exp >>= 1;
dblExp *= dblExp;
}
- fraction += frac2;
}
if (endPtr != NULL) {
- *endPtr = (char *) p;
+ *endPtr = (char *)p;
}
if (sign) {