diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-08-13 05:36:33 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-08-13 05:36:33 +0000 |
commit | f830ace8a831a954db7a6aae280a530651a5b58a (patch) | |
tree | fb2112fdd586672358bcf53f45b8532fde3297b7 /object.c | |
parent | 235e7738d6371c1e3ca638e873acf663e7b90850 (diff) | |
download | ruby-f830ace8a831a954db7a6aae280a530651a5b58a.tar.gz |
object.c: rb_num_to_dbl
* object.c (rb_num_to_dbl): move from num2dbl_with_to_f in math.c.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@51563 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'object.c')
-rw-r--r-- | object.c | 197 |
1 files changed, 155 insertions, 42 deletions
@@ -2903,33 +2903,84 @@ rb_str_to_dbl(VALUE str, int badcheck) return ret; } +#define fix2dbl_without_to_f(x) (double)FIX2LONG(x) +#define big2dbl_without_to_f(x) rb_big2dbl(x) +#define int2dbl_without_to_f(x) \ + (FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x)) +#define rat2dbl_without_to_f(x) \ + (int2dbl_without_to_f(rb_rational_num(x)) / \ + int2dbl_without_to_f(rb_rational_den(x))) + +#define special_const_to_float(val, pre, post) \ + switch (val) { \ + case Qnil: \ + rb_raise(rb_eTypeError, pre "nil" post); \ + case Qtrue: \ + rb_raise(rb_eTypeError, pre "true" post); \ + case Qfalse: \ + rb_raise(rb_eTypeError, pre "false" post); \ + } + +static inline void +conversion_to_float(VALUE val) +{ + special_const_to_float(val, "can't convert ", " into Float"); +} + +static inline void +implicit_conversion_to_float(VALUE val) +{ + special_const_to_float(val, "no implicit conversion to float from ", ""); +} + +static int +to_float(VALUE *valp) +{ + VALUE val = *valp; + if (SPECIAL_CONST_P(val)) { + if (FIXNUM_P(val)) { + *valp = DBL2NUM(fix2dbl_without_to_f(val)); + return T_FLOAT; + } + else if (FLONUM_P(val)) { + return T_FLOAT; + } + else { + conversion_to_float(val); + } + } + else { + int type = BUILTIN_TYPE(val); + switch (type) { + case T_FLOAT: + return T_FLOAT; + case T_BIGNUM: + *valp = DBL2NUM(big2dbl_without_to_f(val)); + return T_FLOAT; + case T_RATIONAL: + *valp = DBL2NUM(rat2dbl_without_to_f(val)); + return T_FLOAT; + case T_STRING: + return T_STRING; + } + } + return T_NONE; +} + VALUE rb_Float(VALUE val) { - switch (TYPE(val)) { - case T_FIXNUM: - return DBL2NUM((double)FIX2LONG(val)); - + switch (to_float(&val)) { case T_FLOAT: return val; - - case T_BIGNUM: - return DBL2NUM(rb_big2dbl(val)); - case T_STRING: return DBL2NUM(rb_str_to_dbl(val, TRUE)); - - case T_NIL: - rb_raise(rb_eTypeError, "can't convert nil into Float"); - break; - - default: - return rb_convert_type(val, T_FLOAT, "Float", "to_f"); } - - UNREACHABLE; + return rb_convert_type(val, T_FLOAT, "Float", "to_f"); } +FUNC_MINIMIZED(static VALUE rb_f_float(VALUE obj, VALUE arg)); + /* * call-seq: * Float(arg) -> float @@ -2948,21 +2999,27 @@ rb_f_float(VALUE obj, VALUE arg) return rb_Float(arg); } -VALUE -rb_to_float(VALUE val) +static VALUE +numeric_to_float(VALUE val) { - if (RB_TYPE_P(val, T_FLOAT)) return val; if (!rb_obj_is_kind_of(val, rb_cNumeric)) { - rb_raise(rb_eTypeError, "can't convert %s into Float", - NIL_P(val) ? "nil" : - val == Qtrue ? "true" : - val == Qfalse ? "false" : - rb_obj_classname(val)); + rb_raise(rb_eTypeError, "can't convert %"PRIsVALUE" into Float", + rb_obj_class(val)); } return rb_convert_type(val, T_FLOAT, "Float", "to_f"); } VALUE +rb_to_float(VALUE val) +{ + switch (to_float(&val)) { + case T_FLOAT: + return val; + } + return numeric_to_float(val); +} + +VALUE rb_check_to_float(VALUE val) { if (RB_TYPE_P(val, T_FLOAT)) return val; @@ -2972,26 +3029,75 @@ rb_check_to_float(VALUE val) return rb_check_convert_type(val, T_FLOAT, "Float", "to_f"); } -double -rb_num2dbl(VALUE val) -{ - switch (TYPE(val)) { - case T_FLOAT: - return RFLOAT_VALUE(val); - - case T_STRING: - rb_raise(rb_eTypeError, "no implicit conversion to float from string"); - break; +static ID id_to_f; - case T_NIL: - rb_raise(rb_eTypeError, "no implicit conversion to float from nil"); - break; +static inline int +basic_to_f_p(VALUE klass) +{ + return rb_method_basic_definition_p(klass, id_to_f); +} - default: - break; +double +rb_num_to_dbl(VALUE val) +{ + if (SPECIAL_CONST_P(val)) { + if (FIXNUM_P(val)) { + if (basic_to_f_p(rb_cFixnum)) + return fix2dbl_without_to_f(val); + } + else if (FLONUM_P(val)) { + return rb_float_flonum_value(val); + } + else { + conversion_to_float(val); + } } + else { + switch (BUILTIN_TYPE(val)) { + case T_FLOAT: + return rb_float_noflonum_value(val); + case T_BIGNUM: + if (basic_to_f_p(rb_cBignum)) + return big2dbl_without_to_f(val); + break; + case T_RATIONAL: + if (basic_to_f_p(rb_cRational)) + return rat2dbl_without_to_f(val); + break; + } + } + val = numeric_to_float(val); + return RFLOAT_VALUE(val); +} - return RFLOAT_VALUE(rb_Float(val)); +double +rb_num2dbl(VALUE val) +{ + if (SPECIAL_CONST_P(val)) { + if (FIXNUM_P(val)) { + return fix2dbl_without_to_f(val); + } + else if (FLONUM_P(val)) { + return rb_float_flonum_value(val); + } + else { + implicit_conversion_to_float(val); + } + } + else { + switch (BUILTIN_TYPE(val)) { + case T_FLOAT: + return rb_float_noflonum_value(val); + case T_BIGNUM: + return big2dbl_without_to_f(val); + case T_RATIONAL: + return rat2dbl_without_to_f(val); + case T_STRING: + rb_raise(rb_eTypeError, "no implicit conversion to float from string"); + } + } + val = rb_convert_type(val, T_FLOAT, "Float", "to_f"); + return RFLOAT_VALUE(val); } VALUE @@ -3243,7 +3349,7 @@ rb_f_hash(VALUE obj, VALUE arg) */ void -Init_Object(void) +InitVM_Object(void) { Init_class_hierarchy(); @@ -3461,3 +3567,10 @@ Init_Object(void) */ rb_define_global_const("FALSE", Qfalse); } + +void +Init_Object(void) +{ + id_to_f = rb_intern_const("to_f"); + InitVM(Object); +} |