summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog14
-rw-r--r--numeric.c16
-rw-r--r--test/-ext-/num2int/test_num2int.rb10
3 files changed, 36 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ef87e2bc9e..eca0373171 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+Wed Mar 27 22:09:14 2013 Tanaka Akira <akr@fsij.org>
+
+ * numeric.c (LONG_MIN_MINUS_ONE_IS_LESS_THAN): New macro.
+ (LLONG_MIN_MINUS_ONE_IS_LESS_THAN): Ditto.
+ (rb_num2long): Use LONG_MIN_MINUS_ONE_IS_LESS_THAN.
+ (rb_num2ulong): Ditto.
+ (rb_num2ll): Use LLONG_MIN_MINUS_ONE_IS_LESS_THAN.
+ (rb_num2ull): Ditto.
+
+ * test/-ext-/num2int/test_num2int.rb (asert_num2i_success): Test the
+ value converted into a Float if Float can represent the value
+ exactly.
+ (asert_num2i_error): Ditto.
+
Wed Mar 27 20:59:47 2013 Tanaka Akira <akr@fsij.org>
* test/-ext-/num2int/test_num2int.rb (asert_num2i_success): New
diff --git a/numeric.c b/numeric.c
index c735e5437d..c9302fb0e8 100644
--- a/numeric.c
+++ b/numeric.c
@@ -1940,6 +1940,10 @@ num_step(int argc, VALUE *argv, VALUE from)
#define LONG_MIN_MINUS_ONE ((double)LONG_MIN-1)
#define LONG_MAX_PLUS_ONE (2*(double)(LONG_MAX/2+1))
#define ULONG_MAX_PLUS_ONE (2*(double)(ULONG_MAX/2+1))
+#define LONG_MIN_MINUS_ONE_IS_LESS_THAN(n) \
+ (LONG_MIN_MINUS_ONE == (double)LONG_MIN ? \
+ LONG_MIN <= (n): \
+ LONG_MIN_MINUS_ONE < (n))
SIGNED_VALUE
rb_num2long(VALUE val)
@@ -1954,7 +1958,7 @@ rb_num2long(VALUE val)
switch (TYPE(val)) {
case T_FLOAT:
if (RFLOAT_VALUE(val) < LONG_MAX_PLUS_ONE
- && RFLOAT_VALUE(val) > LONG_MIN_MINUS_ONE) {
+ && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
return (SIGNED_VALUE)(RFLOAT_VALUE(val));
}
else {
@@ -1988,7 +1992,7 @@ rb_num2ulong(VALUE val)
switch (TYPE(val)) {
case T_FLOAT:
if (RFLOAT_VALUE(val) < ULONG_MAX_PLUS_ONE
- && RFLOAT_VALUE(val) > LONG_MIN_MINUS_ONE) {
+ && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
return (VALUE)RFLOAT_VALUE(val);
}
else {
@@ -2192,6 +2196,10 @@ rb_num2fix(VALUE val)
#ifndef ULLONG_MAX
#define ULLONG_MAX ((unsigned LONG_LONG)LLONG_MAX*2+1)
#endif
+#define LLONG_MIN_MINUS_ONE_IS_LESS_THAN(n) \
+ (LLONG_MIN_MINUS_ONE == (double)LLONG_MIN ? \
+ LLONG_MIN <= (n): \
+ LLONG_MIN_MINUS_ONE < (n))
LONG_LONG
rb_num2ll(VALUE val)
@@ -2205,7 +2213,7 @@ rb_num2ll(VALUE val)
switch (TYPE(val)) {
case T_FLOAT:
if (RFLOAT_VALUE(val) < LLONG_MAX_PLUS_ONE
- && RFLOAT_VALUE(val) > LLONG_MIN_MINUS_ONE) {
+ && (LLONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val)))) {
return (LONG_LONG)(RFLOAT_VALUE(val));
}
else {
@@ -2249,7 +2257,7 @@ rb_num2ull(VALUE val)
case T_FLOAT:
if (RFLOAT_VALUE(val) < ULLONG_MAX_PLUS_ONE
- && RFLOAT_VALUE(val) > 0) {
+ && LLONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
return (unsigned LONG_LONG)(RFLOAT_VALUE(val));
}
else {
diff --git a/test/-ext-/num2int/test_num2int.rb b/test/-ext-/num2int/test_num2int.rb
index 90827fdc1f..47e57fffc6 100644
--- a/test/-ext-/num2int/test_num2int.rb
+++ b/test/-ext-/num2int/test_num2int.rb
@@ -36,6 +36,11 @@ class TestNum2int < Test::Unit::TestCase
assert_output(result.to_s) do
Num2int.send(method, num)
end
+ if num.to_f.to_i == num
+ assert_output(result.to_s) do
+ Num2int.send(method, num.to_f)
+ end
+ end
end
def asert_num2i_error(type, num)
@@ -43,6 +48,11 @@ class TestNum2int < Test::Unit::TestCase
assert_raise(RangeError) do
Num2int.send(method, num)
end
+ if num.to_f.to_i == num
+ assert_raise(RangeError) do
+ Num2int.send(method, num)
+ end
+ end
end
def test_num2short