1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* 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.

* util.c (ruby_strtod): fixed wrong conversion.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@10123 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2006-05-01 03:46:47 +00:00
parent a6fdf0bbcd
commit 9466848db3
4 changed files with 81 additions and 71 deletions

View file

@ -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

View file

@ -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);
}

View file

@ -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

84
util.c
View file

@ -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) {