summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--internal.h47
-rw-r--r--math.c47
-rw-r--r--object.c197
4 files changed, 189 insertions, 106 deletions
diff --git a/ChangeLog b/ChangeLog
index 0a6fcffa06..332821c81b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Aug 13 14:36:31 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * object.c (rb_num_to_dbl): move from num2dbl_with_to_f in math.c.
+
Thu Aug 13 09:01:25 2015 Eric Wong <e@80x24.org>
* load.c (features_index_add): avoid repeat calculation
diff --git a/internal.h b/internal.h
index 59526c8ec7..a1eadfa074 100644
--- a/internal.h
+++ b/internal.h
@@ -903,31 +903,41 @@ VALUE rb_dbl_hash(double d);
#endif
static inline double
-rb_float_value_inline(VALUE v)
+rb_float_flonum_value(VALUE v)
{
#if USE_FLONUM
- if (FLONUM_P(v)) {
- if (v != (VALUE)0x8000000000000002) { /* LIKELY */
- union {
- double d;
- VALUE v;
- } t;
-
- VALUE b63 = (v >> 63);
- /* e: xx1... -> 011... */
- /* xx0... -> 100... */
- /* ^b63 */
- t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~0x03), 3);
- return t.d;
- }
- else {
- return 0.0;
- }
+ if (v != (VALUE)0x8000000000000002) { /* LIKELY */
+ union {
+ double d;
+ VALUE v;
+ } t;
+
+ VALUE b63 = (v >> 63);
+ /* e: xx1... -> 011... */
+ /* xx0... -> 100... */
+ /* ^b63 */
+ t.v = RUBY_BIT_ROTR((2 - b63) | (v & ~0x03), 3);
+ return t.d;
}
#endif
+ return 0.0;
+}
+
+static inline double
+rb_float_noflonum_value(VALUE v)
+{
return ((struct RFloat *)v)->float_value;
}
+static inline double
+rb_float_value_inline(VALUE v)
+{
+ if (FLONUM_P(v)) {
+ return rb_float_flonum_value(v);
+ }
+ return rb_float_noflonum_value(v);
+}
+
static inline VALUE
rb_float_new_inline(double d)
{
@@ -965,6 +975,7 @@ rb_float_new_inline(double d)
void rb_obj_copy_ivar(VALUE dest, VALUE obj);
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
+double rb_num_to_dbl(VALUE val);
struct RBasicRaw {
VALUE flags;
diff --git a/math.c b/math.c
index 134d937358..591d6ae2f2 100644
--- a/math.c
+++ b/math.c
@@ -21,54 +21,10 @@
#define RB_BIGNUM_TYPE_P(x) RB_TYPE_P((x), T_BIGNUM)
-static ID id_to_f;
-
VALUE rb_mMath;
VALUE rb_eMathDomainError;
-static inline int
-basic_to_f_p(VALUE klass)
-{
- return rb_method_basic_definition_p(klass, id_to_f);
-}
-
-#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)))
-
-static inline double
-num2dbl_with_to_f(VALUE num)
-{
- if (SPECIAL_CONST_P(num)) {
- if (FIXNUM_P(num)) {
- if (basic_to_f_p(rb_cFixnum))
- return fix2dbl_without_to_f(num);
- }
- else if (FLONUM_P(num)) {
- return RFLOAT_VALUE(num);
- }
- }
- else {
- switch (BUILTIN_TYPE(num)) {
- case T_FLOAT:
- return RFLOAT_VALUE(num);
- case T_BIGNUM:
- if (basic_to_f_p(rb_cBignum))
- return big2dbl_without_to_f(num);
- break;
- case T_RATIONAL:
- if (basic_to_f_p(rb_cRational))
- return rat2dbl_without_to_f(num);
- break;
- }
- }
- return RFLOAT_VALUE(rb_to_float(num));
-}
-
-#define Get_Double(x) num2dbl_with_to_f(x)
+#define Get_Double(x) rb_num_to_dbl(x)
#define domain_error(msg) \
rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " #msg)
@@ -1024,6 +980,5 @@ InitVM_Math(void)
void
Init_Math(void)
{
- id_to_f = rb_intern_const("to_f");
InitVM(Math);
}
diff --git a/object.c b/object.c
index 51355e1354..910fb4e5d1 100644
--- a/object.c
+++ b/object.c
@@ -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);
+}