* numeric.c (rb_num2ulong_internal): New function similart to

rb_num2ulong but integer wrap around flag is also returned.
  (rb_num2ulong): Use rb_num2ulong_internal.
  (rb_num2uint): Use rb_num2ulong_internal and the wrap around flag is
  used instead of negative_int_p(val).
  (rb_num2ushort): ditto.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40017 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
akr 2013-03-31 04:51:29 +00:00
Родитель 18affefbe5
Коммит 59182ccf69
3 изменённых файлов: 52 добавлений и 11 удалений

Просмотреть файл

@ -1,3 +1,12 @@
Sun Mar 31 13:47:04 2013 Tanaka Akira <akr@fsij.org>
* numeric.c (rb_num2ulong_internal): New function similart to
rb_num2ulong but integer wrap around flag is also returned.
(rb_num2ulong): Use rb_num2ulong_internal.
(rb_num2uint): Use rb_num2ulong_internal and the wrap around flag is
used instead of negative_int_p(val).
(rb_num2ushort): ditto.
Sun Mar 31 06:27:17 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
* class.c (HAVE_METACLASS_P): should check FL_SINGLTON flag before get

Просмотреть файл

@ -1979,21 +1979,29 @@ rb_num2long(VALUE val)
}
}
VALUE
rb_num2ulong(VALUE val)
static unsigned long
rb_num2ulong_internal(VALUE val, int *wrap_p)
{
again:
if (NIL_P(val)) {
rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
}
if (FIXNUM_P(val)) return FIX2LONG(val); /* this is FIX2LONG, inteneded */
if (FIXNUM_P(val)) {
long l = FIX2LONG(val); /* this is FIX2LONG, inteneded */
if (wrap_p)
*wrap_p = l < 0;
return l;
}
switch (TYPE(val)) {
case T_FLOAT:
if (RFLOAT_VALUE(val) < ULONG_MAX_PLUS_ONE
&& LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
return (VALUE)RFLOAT_VALUE(val);
double d = RFLOAT_VALUE(val);
if (wrap_p)
*wrap_p = d <= -1.0; /* NUM2ULONG(v) uses v.to_int conceptually. */
return (unsigned long)d;
}
else {
char buf[24];
@ -2005,7 +2013,12 @@ rb_num2ulong(VALUE val)
}
case T_BIGNUM:
return rb_big2ulong(val);
{
unsigned long ul = rb_big2ulong(val);
if (wrap_p)
*wrap_p = RBIGNUM_NEGATIVE_P(val);
return ul;
}
default:
val = rb_to_int(val);
@ -2013,6 +2026,12 @@ rb_num2ulong(VALUE val)
}
}
VALUE
rb_num2ulong(VALUE val)
{
return rb_num2ulong_internal(val, NULL);
}
#if SIZEOF_INT < SIZEOF_VALUE
void
rb_out_of_int(SIGNED_VALUE num)
@ -2068,10 +2087,11 @@ rb_fix2int(VALUE val)
unsigned long
rb_num2uint(VALUE val)
{
VALUE num = rb_num2ulong(val);
int wrap;
unsigned long num = rb_num2ulong_internal(val, &wrap);
check_uint(num, negative_int_p(val));
return (unsigned long)num;
check_uint(num, wrap);
return num;
}
unsigned long
@ -2155,10 +2175,11 @@ rb_fix2short(VALUE val)
unsigned short
rb_num2ushort(VALUE val)
{
VALUE num = rb_num2ulong(val);
int wrap;
unsigned long num = rb_num2ulong_internal(val, &wrap);
check_ushort(num, negative_int_p(val));
return (unsigned long)num;
check_ushort(num, wrap);
return num;
}
unsigned short

Просмотреть файл

@ -48,6 +48,17 @@ class TestNum2int < Test::Unit::TestCase
if num.to_f.to_i == num
assert_num2i_success_internal(result.to_s, func, num.to_f)
end
if num == result
# The conversion functions such as NUM2INT uses to_int (conceptually).
arg = num.to_f + 0.5
if arg != num.to_f && arg.to_int == num
assert_num2i_success_internal(result.to_s, func, arg)
end
arg = num.to_f - 0.5
if arg != num.to_f && arg.to_int == num
assert_num2i_success_internal(result.to_s, func, arg)
end
end
end
def assert_num2i_error_internal(func, arg)