Project

General

Profile

Bug #12337 ยป int-coerce.patch

akr (Akira Tanaka), 05/03/2016 09:06 AM

View differences:

bignum.c (working copy)
/*
* call-seq:
* big.coerce(numeric) -> array
* int.coerce(numeric) -> array
*
* Returns an array with both a +numeric+ and a +big+ represented as Bignum
* objects.
* Returns an array with both a +numeric+ with same class.
* The result can be
* <code>[<i>fixnum</i>, <i>fixnum</i>]</code>,
* <code>[<i>bignum</i>, <i>bignum</i>]</code> or
* <code>[<i>float</i>, <i>float</i>]</code>.
*
* The values are preserved except that the floats loses preceision.
*
* 2.coerce(3) #=> [3, 2] # [fixnum, fixnum]
* (2**70).coerce(3) #=> [3, 1180591620717411303424] # [bignum, bignum]
* (2**70).coerce(3.0) #=> [3.0, 1.1805916207174113e+21] # [float, float]
*
* This is achieved by converting +numeric+ to a Bignum.
*
* A TypeError is raised if the +numeric+ is not a Fixnum or Bignum type.
*
* (0x3FFFFFFFFFFFFFFF+1).coerce(42) #=> [42, 4611686018427387904]
*/
static VALUE
rb_big_coerce(VALUE x, VALUE y)
rb_int_coerce(VALUE x, VALUE y)
{
if (FIXNUM_P(y)) {
y = rb_int2big(FIX2LONG(y));
}
else if (!RB_BIGNUM_TYPE_P(y)) {
rb_raise(rb_eTypeError, "can't coerce %"PRIsVALUE" to Bignum",
rb_obj_class(y));
if (FIXNUM_P(x)) {
if (FIXNUM_P(y))
return rb_assoc_new(y, x);
else if (RB_BIGNUM_TYPE_P(y))
return rb_assoc_new(y, rb_int2big(FIX2LONG(x)));
else if (RB_TYPE_P(y, T_FLOAT))
return rb_assoc_new(y, rb_Float(x));
}
else if (RB_BIGNUM_TYPE_P(x)) {
if (FIXNUM_P(y))
return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
else if (RB_BIGNUM_TYPE_P(y))
return rb_assoc_new(y, x);
else if (RB_TYPE_P(y, T_FLOAT))
return rb_assoc_new(y, rb_Float(x));
}
return rb_assoc_new(y, x);
return rb_assoc_new(rb_Float(y), rb_Float(x));
}
VALUE
......
{
rb_cBignum = rb_define_class("Bignum", rb_cInteger);
rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
rb_define_method(rb_cInteger, "coerce", rb_int_coerce, 1);
rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
    (1-1/1)