poor man's rubyのパッチ
まだ、一杯バグがありますけど、パッチを晒します。
ライセンスはruby's でお願いします。
変更情報
バグがあったので直しました。 2007/12/9
直したのは、
- 条件比較が思い切りバグっていたので直しました。Floatの数値をポインタのまま比較していました。
- EPSILONやMAXをdoubleのものから、floatのものに変更しました。実現方法が汚いです。
Index: time.c =================================================================== --- time.c (revision 14077) +++ time.c (working copy) @@ -193,6 +193,7 @@ t.tv_nsec = 0; break; + case T_FIXFLOAT: case T_FLOAT: if (interval && RFLOAT_VALUE(num) < 0.0) rb_raise(rb_eArgError, "%s must be positive", tstr); Index: include/ruby/intern.h =================================================================== --- include/ruby/intern.h (revision 14077) +++ include/ruby/intern.h (working copy) @@ -83,6 +83,7 @@ VALUE rb_int2big(SIGNED_VALUE); VALUE rb_uint2inum(VALUE); VALUE rb_int2inum(SIGNED_VALUE); +VALUE rb_int2id(SIGNED_VALUE); VALUE rb_cstr_to_inum(const char*, int, int); VALUE rb_str_to_inum(VALUE, int, int); VALUE rb_cstr2inum(const char*, int); @@ -367,7 +368,8 @@ VALUE rb_num_coerce_bin(VALUE, VALUE); VALUE rb_num_coerce_cmp(VALUE, VALUE); VALUE rb_num_coerce_relop(VALUE, VALUE); -VALUE rb_float_new(double); +float rb_value2float(VALUE); +VALUE rb_float_new(float); VALUE rb_num2fix(VALUE); VALUE rb_fix2str(VALUE, int); VALUE rb_dbl_cmp(double, double); Index: include/ruby/ruby.h =================================================================== --- include/ruby/ruby.h (revision 14077) +++ include/ruby/ruby.h (working copy) @@ -151,16 +151,18 @@ # endif #endif -#define FIXNUM_MAX (LONG_MAX>>1) -#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1) +#define FIXNUM_MAX (LONG_MAX>>2) +#define FIXNUM_MIN RSHIFT((long)LONG_MIN,2) -#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | FIXNUM_FLAG)) +#define INT2FIX(i) ((VALUE)(((SIGNED_VALUE)(i))<<2 | FIXNUM_FLAG)) +#define INT2ID(i) ((VALUE)(((SIGNED_VALUE)(i))<<1 | 1)) #define LONG2FIX(i) INT2FIX(i) #define rb_fix_new(v) INT2FIX(v) VALUE rb_int2inum(SIGNED_VALUE); #define INT2NUM(v) rb_int2inum(v) #define LONG2NUM(v) INT2NUM(v) #define rb_int_new(v) rb_int2inum(v) +#define LONG2ID(v) rb_int2id(v) VALUE rb_uint2inum(VALUE); #define UINT2NUM(v) rb_uint2inum(v) #define ULONG2NUM(v) UINT2NUM(v) @@ -200,9 +202,10 @@ #define NUM2GIDT(v) NUM2LONG(v) #endif -#define FIX2LONG(x) RSHIFT((SIGNED_VALUE)x,1) -#define FIX2ULONG(x) ((((VALUE)(x))>>1)&LONG_MAX) -#define FIXNUM_P(f) (((SIGNED_VALUE)(f))&FIXNUM_FLAG) +#define FIX2LONG(x) RSHIFT((SIGNED_VALUE)x,2) +#define FIX2ULONG(x) ((((VALUE)(x))>>2)&LONG_MAX) +#define FIXNUM_P(f) ((((SIGNED_VALUE)(f))&FIXNUM_FLAG) == 3) +#define FIXFLOAT_P(f) ((((SIGNED_VALUE)(f))&FIXNUM_FLAG) == 1) #define POSFIXABLE(f) ((f) <= FIXNUM_MAX) #define NEGFIXABLE(f) ((f) >= FIXNUM_MIN) #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) @@ -221,7 +224,7 @@ RUBY_Qundef = 6, RUBY_IMMEDIATE_MASK = 0x03, - RUBY_FIXNUM_FLAG = 0x01, + RUBY_FIXNUM_FLAG = 0x03, RUBY_SYMBOL_FLAG = 0x0e, RUBY_SPECIAL_SHIFT = 8, }; @@ -289,6 +292,8 @@ #define T_BLOCK RUBY_T_BLOCK RUBY_T_UNDEF = 0x1c, #define T_UNDEF RUBY_T_UNDEF + RUBY_T_FIXFLOAT = 0x1d, +#define T_FIXFLOAT RUBY_T_FIXFLOAT RUBY_T_NODE = 0x1f, #define T_NODE RUBY_T_NODE @@ -339,6 +344,7 @@ VALUE rb_num2ulong(VALUE); #define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x)) #define NUM2ULONG(x) rb_num2ulong((VALUE)x) +#define ID2ULONG(x) rb_id2ulong((VALUE)x) #if SIZEOF_INT < SIZEOF_LONG long rb_num2int(VALUE); #define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2int((VALUE)x)) @@ -451,9 +457,9 @@ struct RFloat { struct RBasic basic; - double float_value; + float float_value; }; -#define RFLOAT_VALUE(v) (RFLOAT(v)->float_value) +/* #define RFLOAT_VALUE(v) (RFLOAT(v)->float_value)*/ #define DOUBLE2NUM(dbl) rb_float_new(dbl) #define ELTS_SHARED FL_USER2 @@ -616,6 +622,7 @@ #define RCLASS(obj) (R_CAST(RClass)(obj)) #define RMODULE(obj) RCLASS(obj) #define RFLOAT(obj) (R_CAST(RFloat)(obj)) +#define RFLOAT_VALUE(obj) ((FIXFLOAT_P(obj)) ? rb_value2float(obj) : (RFLOAT(obj)->float_value)) #define RSTRING(obj) (R_CAST(RString)(obj)) #define RREGEXP(obj) (R_CAST(RRegexp)(obj)) #define RARRAY(obj) (R_CAST(RArray)(obj)) @@ -886,6 +893,7 @@ rb_class_of(VALUE obj) { if (IMMEDIATE_P(obj)) { + if (FIXFLOAT_P(obj)) return rb_cFloat; if (FIXNUM_P(obj)) return rb_cFixnum; if (obj == Qtrue) return rb_cTrueClass; if (SYMBOL_P(obj)) return rb_cSymbol; @@ -901,6 +909,7 @@ rb_type(VALUE obj) { if (IMMEDIATE_P(obj)) { + if (FIXFLOAT_P(obj)) return T_FIXFLOAT; if (FIXNUM_P(obj)) return T_FIXNUM; if (obj == Qtrue) return T_TRUE; if (SYMBOL_P(obj)) return T_SYMBOL; Index: insns.def =================================================================== --- insns.def (revision 14077) +++ insns.def (working copy) @@ -1361,7 +1361,7 @@ BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { /* fixnum + fixnum */ #ifndef LONG_LONG_VALUE - val = (recv + (obj & (~1))); + val = (recv + (obj & (~3))); if ((~(recv ^ obj) & (recv ^ val)) & ((VALUE)0x01 << ((sizeof(VALUE) * CHAR_BIT) - 1))) { val = rb_big_plus(rb_int2big(FIX2LONG(recv)), @@ -1382,6 +1382,12 @@ } #endif + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat + fixfloat */ + val = rb_float_new(rb_value2float(recv) + rb_value2float(obj)); + } + else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (0) { } @@ -1444,6 +1450,11 @@ val = rb_big_minus(rb_int2big(a), rb_int2big(b)); } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat - fixfloat */ + val = rb_float_new(rb_value2float(recv) - rb_value2float(obj)); + } else { /* other */ PUSH(recv); @@ -1483,6 +1494,11 @@ } } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat * fixfloat */ + val = rb_float_new(rb_value2float(recv) * rb_value2float(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (0) { } @@ -1547,6 +1563,11 @@ } val = LONG2NUM(div); } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat / fixfloat */ + val = rb_float_new(rb_value2float(recv) / rb_value2float(obj)); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (0) { } @@ -1612,6 +1633,26 @@ } val = LONG2FIX(mod); } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat + fixfloat */ + double x = RFLOAT_VALUE(recv); + double y = RFLOAT_VALUE(obj); + double div, mod; + { + double z; + + modf(x / y, &z); + mod = x - z * y; + } + + div = (x - mod) / y; + if (y * mod < 0) { + mod += y; + div -= 1.0; + } + val = rb_float_new(mod); + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (0) { } @@ -1670,6 +1711,11 @@ val = Qfalse; } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat == fixfloat */ + val = (RFLOAT_VALUE(recv) == RFLOAT_VALUE(obj)) ? Qtrue : Qfalse; + } else if (!SPECIAL_CONST_P(recv) && !SPECIAL_CONST_P(obj)) { if (0) { } @@ -1730,6 +1776,11 @@ val = Qfalse; } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat <= fixfloat */ + val = (RFLOAT_VALUE(recv) < RFLOAT_VALUE(obj)) ? Qtrue : Qfalse; + } else { PUSH(recv); PUSH(obj); @@ -1759,6 +1810,11 @@ val = Qfalse; } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat <= fixfloat */ + val = (RFLOAT_VALUE(recv) <= RFLOAT_VALUE(obj)) ? Qtrue : Qfalse; + } else { /* other */ PUSH(recv); @@ -1789,6 +1845,11 @@ val = Qfalse; } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat > fixfloat */ + val = (RFLOAT_VALUE(recv) > RFLOAT_VALUE(obj)) ? Qtrue : Qfalse; + } else { PUSH(recv); PUSH(obj); @@ -1818,6 +1879,11 @@ val = Qfalse; } } + else if (FIXFLOAT_P(recv) && FIXFLOAT_P(obj) && + BASIC_OP_UNREDEFINED_P(BOP_PLUS)) { + /* fixfloat >= fixfloat */ + val = (RFLOAT_VALUE(recv) >= RFLOAT_VALUE(obj)) ? Qtrue : Qfalse; + } else { PUSH(recv); PUSH(obj); Index: object.c =================================================================== --- object.c (revision 14077) +++ object.c (working copy) @@ -1919,6 +1919,7 @@ VALUE tmp; switch (TYPE(val)) { + case T_FIXFLOAT: case T_FLOAT: if (RFLOAT_VALUE(val) <= (double)FIXNUM_MAX && RFLOAT_VALUE(val) >= (double)FIXNUM_MIN) { @@ -2066,6 +2067,7 @@ case T_FIXNUM: return DOUBLE2NUM((double)FIX2LONG(val)); + case T_FIXFLOAT: case T_FLOAT: return val; @@ -2112,6 +2114,7 @@ rb_num2dbl(VALUE val) { switch (TYPE(val)) { + case T_FIXFLOAT: case T_FLOAT: return RFLOAT_VALUE(val); Index: insnhelper.h =================================================================== --- insnhelper.h (revision 14077) +++ insnhelper.h (working copy) @@ -137,7 +137,7 @@ /**********************************************************/ /* optimize insn */ -#define FIXNUM_2_P(a, b) ((a) & (b) & 1) +#define FIXNUM_2_P(a, b) (((a) & (b) & 3) == 3) #define BASIC_OP_UNREDEFINED_P(op) ((ruby_vm_redefined_flag & (op)) == 0) #define HEAP_CLASS_OF(obj) RBASIC(obj)->klass Index: sprintf.c =================================================================== --- sprintf.c (revision 14077) +++ sprintf.c (working copy) @@ -551,6 +551,7 @@ bin_retry: switch (TYPE(val)) { + case T_FIXFLOAT: case T_FLOAT: if (FIXABLE((long)RFLOAT_VALUE(val))) { val = LONG2FIX((long)RFLOAT_VALUE(val)); Index: gc.c =================================================================== --- gc.c (revision 14077) +++ gc.c (working copy) @@ -2053,7 +2053,7 @@ id2ref(VALUE obj, VALUE objid) { #if SIZEOF_LONG == SIZEOF_VOIDP -#define NUM2PTR(x) NUM2ULONG(x) +#define NUM2PTR(x) ID2ULONG(x) #elif SIZEOF_LONG_LONG == SIZEOF_VOIDP #define NUM2PTR(x) NUM2ULL(x) #endif @@ -2067,8 +2067,9 @@ if (ptr == Qtrue) return Qtrue; if (ptr == Qfalse) return Qfalse; if (ptr == Qnil) return Qnil; + if (FIXFLOAT_P(ptr)) return (VALUE)ptr; if (FIXNUM_P(ptr)) return (VALUE)ptr; - ptr = objid ^ FIXNUM_FLAG; /* unset FIXNUM_FLAG */ + ptr = objid ^ 1; /* unset FIXNUM_FLAG */ if ((ptr % sizeof(RVALUE)) == (4 << 2)) { ID symid = ptr / sizeof(RVALUE); @@ -2146,12 +2147,12 @@ * 40 if 64-bit */ if (TYPE(obj) == T_SYMBOL) { - return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG; + return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | 1; } if (SPECIAL_CONST_P(obj)) { - return LONG2NUM((SIGNED_VALUE)obj); + return LONG2ID((SIGNED_VALUE)obj); } - return (VALUE)((SIGNED_VALUE)obj|FIXNUM_FLAG); + return (VALUE)((SIGNED_VALUE)obj|1); } /* @@ -2225,6 +2226,7 @@ case T_REGEXP: type = ID2SYM(rb_intern("T_REGEXP")); break; case T_ARRAY: type = ID2SYM(rb_intern("T_ARRAY")); break; case T_FIXNUM: type = ID2SYM(rb_intern("T_FIXNUM")); break; + case T_FIXFLOAT: type = ID2SYM(rb_intern("T_FIXFLOAT")); break; case T_HASH: type = ID2SYM(rb_intern("T_HASH")); break; case T_STRUCT: type = ID2SYM(rb_intern("T_STRUCT")); break; case T_BIGNUM: type = ID2SYM(rb_intern("T_BIGNUM")); break; Index: parse.y =================================================================== --- parse.y (revision 14077) +++ parse.y (working copy) @@ -8255,6 +8255,9 @@ case T_FLOAT: RFLOAT(node->nd_lit)->float_value = -RFLOAT_VALUE(node->nd_lit); break; + case T_FIXFLOAT: + node->nd_lit = DOUBLE2NUM(-RFLOAT_VALUE(node->nd_lit)); + break; default: break; } @@ -9294,6 +9297,7 @@ if (x == Qundef) rb_raise(rb_eArgError, "Qundef given"); if (FIXNUM_P(x)) return x; + if (FIXFLOAT_P(x)) return x; if (SYMBOL_P(x)) return x; if (!rb_is_pointer_to_heap(x)) rb_raise(rb_eArgError, "invalid pointer: %p", x); Index: util.c =================================================================== --- util.c (revision 14077) +++ util.c (working copy) @@ -751,8 +751,8 @@ * Llong, #define #ULLong to be the corresponding unsigned type. * #define KR_headers for old-style C function headers. * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * define some or all of FLT_DIG, FLT_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and FLT_MAX. * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) * if memory is available and otherwise does something you deem * appropriate. If MALLOC is undefined, malloc will be invoked Index: numeric.c =================================================================== --- numeric.c (revision 14077) +++ numeric.c (working copy) @@ -29,39 +29,23 @@ #endif /* use IEEE 64bit values if not defined */ +/* poor man's ruby use 32bit value, so rewrite parameter */ +/* For GCC */ #ifndef FLT_RADIX #define FLT_RADIX 2 #endif #ifndef FLT_ROUNDS #define FLT_ROUNDS 1 #endif -#ifndef DBL_MIN -#define DBL_MIN 2.2250738585072014e-308 -#endif -#ifndef DBL_MAX -#define DBL_MAX 1.7976931348623157e+308 -#endif -#ifndef DBL_MIN_EXP -#define DBL_MIN_EXP (-1021) -#endif -#ifndef DBL_MAX_EXP -#define DBL_MAX_EXP 1024 -#endif -#ifndef DBL_MIN_10_EXP -#define DBL_MIN_10_EXP (-307) -#endif -#ifndef DBL_MAX_10_EXP -#define DBL_MAX_10_EXP 308 -#endif -#ifndef DBL_DIG -#define DBL_DIG 15 -#endif -#ifndef DBL_MANT_DIG -#define DBL_MANT_DIG 53 -#endif -#ifndef DBL_EPSILON -#define DBL_EPSILON 2.2204460492503131e-16 -#endif +#define DBL_MIN __FLT_MIN__ +#define DBL_MAX __FLT_MAX__ +#define DBL_MIN_EXP __FLT_MIN_EXP__ +#define DBL_MAX_EXP __FLT_MAX_EXP__ +#define DBL_MIN_10_EXP __FLT_MIN_10_EXP__ +#define DBL_MAX_10_EXP __FLT_MAX_10_EXP__ +#define DBL_DIG __FLT_DIG__ +#define DBL_MANT_DIG __FLT_MANT_DIG__ +#define DBL_EPSILON __FLT_EPSILON__ #ifndef HAVE_ROUND double @@ -469,6 +453,38 @@ } +static VALUE +d2v(float d) +{ + union { +float d; +VALUE v; + } u; + u.d = d; + return u.v; +} + +static float +v2d(VALUE v) +{ + union { +float d; +VALUE v; + } u; + u.v = v; + return u.d; +} + +#define ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n))) +#define ROTR(v, n) (((v) >> (n)) | ((v) << ((sizeof(v) * 8) - n))) + +float +rb_value2float(VALUE v) +{ + VALUE v1 = (v & 0x4) ? v & (~0x3) : v | 0x3; + VALUE v2 = ROTR(v1, 4); + return v2d(v2); +} /******************************************************************** * * Document-class: Float @@ -478,13 +494,22 @@ */ VALUE -rb_float_new(double d) +rb_float_new(float d) { - NEWOBJ(flt, struct RFloat); - OBJSETUP(flt, rb_cFloat, T_FLOAT); + VALUE v1 = d2v(d); + VALUE v2 = ROTL(v1, 4); - flt->float_value = d; - return (VALUE)flt; + if ((v2 & 0x7) == 4 || (v2 & 0x7) == 3) { + // printf("(float2value)%f ", d); + return ((v2 | 0x3) ^ 2); + } + else { + NEWOBJ(flt, struct RFloat); + OBJSETUP(flt, rb_cFloat, T_FLOAT); + + flt->float_value = d; + return (VALUE)flt; + } } /* @@ -546,7 +571,7 @@ static VALUE flo_uminus(VALUE flt) { - return DOUBLE2NUM(-RFLOAT_VALUE(flt)); + return DOUBLE2NUM(-RFLOAT_VALUE(flt)); } /* @@ -565,6 +590,7 @@ return DOUBLE2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y)); case T_BIGNUM: return DOUBLE2NUM(RFLOAT_VALUE(x) + rb_big2dbl(y)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y)); default: @@ -588,6 +614,7 @@ return DOUBLE2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y)); case T_BIGNUM: return DOUBLE2NUM(RFLOAT_VALUE(x) - rb_big2dbl(y)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y)); default: @@ -611,6 +638,7 @@ return DOUBLE2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y)); case T_BIGNUM: return DOUBLE2NUM(RFLOAT_VALUE(x) * rb_big2dbl(y)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y)); default: @@ -639,6 +667,7 @@ case T_BIGNUM: d = rb_big2dbl(y); return DOUBLE2NUM(RFLOAT_VALUE(x) / d); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y)); default: @@ -698,6 +727,7 @@ case T_BIGNUM: fy = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: fy = RFLOAT_VALUE(y); break; @@ -728,6 +758,7 @@ case T_BIGNUM: fy = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: fy = RFLOAT_VALUE(y); break; @@ -765,6 +796,7 @@ return DOUBLE2NUM(pow(RFLOAT_VALUE(x), (double)FIX2LONG(y))); case T_BIGNUM: return DOUBLE2NUM(pow(RFLOAT_VALUE(x), rb_big2dbl(y))); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(pow(RFLOAT_VALUE(x), RFLOAT_VALUE(y))); default: @@ -838,6 +870,7 @@ case T_BIGNUM: b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); if (isnan(b)) return Qfalse; @@ -902,6 +935,7 @@ b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); break; @@ -934,6 +968,7 @@ b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); if (isnan(b)) return Qfalse; @@ -969,6 +1004,7 @@ b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); if (isnan(b)) return Qfalse; @@ -1003,6 +1039,7 @@ b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); if (isnan(b)) return Qfalse; @@ -1038,6 +1075,7 @@ b = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: b = RFLOAT_VALUE(y); if (isnan(b)) return Qfalse; @@ -1064,7 +1102,8 @@ static VALUE flo_eql(VALUE x, VALUE y) { - if (TYPE(y) == T_FLOAT) { + if (TYPE(y) == T_FLOAT || + TYPE(y) == T_FIXFLOAT) { double a = RFLOAT_VALUE(x); double b = RFLOAT_VALUE(y); @@ -1456,7 +1495,9 @@ } } } - else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) { + else if ((TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) || + (TYPE(from) == T_FIXFLOAT || TYPE(to) == T_FIXFLOAT || TYPE(step) == T_FIXFLOAT)) + { const double epsilon = DBL_EPSILON; double beg = NUM2DBL(from); double end = NUM2DBL(to); @@ -1501,6 +1542,7 @@ switch (TYPE(val)) { case T_FLOAT: + case T_FIXFLOAT: if (RFLOAT_VALUE(val) <= (double)LONG_MAX && RFLOAT_VALUE(val) >= (double)LONG_MIN) { return (SIGNED_VALUE)(RFLOAT_VALUE(val)); @@ -1532,6 +1574,15 @@ return (VALUE)rb_num2long(val); } +VALUE +rb_id2ulong(VALUE val) +{ + if (TYPE(val) == T_BIGNUM) { + return rb_big2ulong(val); + } + return (VALUE)(((SIGNED_VALUE)val) >> 1); +} + #if SIZEOF_INT < SIZEOF_VALUE static void check_int(SIGNED_VALUE num) @@ -1648,6 +1699,7 @@ if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val); switch (TYPE(val)) { + case T_FIXFLOAT: case T_FLOAT: if (RFLOAT_VALUE(val) <= (double)LLONG_MAX && RFLOAT_VALUE(val) >= (double)LLONG_MIN) { @@ -1913,6 +1965,7 @@ case T_FIXNUM: case T_BIGNUM: return x; + case T_FIXFLOAT: case T_FLOAT: return rb_funcall(x, id_to_i, 0); default: @@ -1935,6 +1988,7 @@ case T_FIXNUM: case T_BIGNUM: return rb_funcall(x, rb_intern("to_f"), 0); + case T_FIXFLOAT: case T_FLOAT: return x; default: @@ -2039,6 +2093,7 @@ switch (TYPE(y)) { case T_BIGNUM: return rb_big_plus(y, x); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM((double)FIX2LONG(x) + RFLOAT_VALUE(y)); default: @@ -2073,6 +2128,7 @@ case T_BIGNUM: x = rb_int2big(FIX2LONG(x)); return rb_big_minus(x, y); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM((double)FIX2LONG(x) - RFLOAT_VALUE(y)); default: @@ -2132,6 +2188,7 @@ switch (TYPE(y)) { case T_BIGNUM: return rb_big_mul(y, x); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM((double)FIX2LONG(x) * RFLOAT_VALUE(y)); default: @@ -2188,6 +2245,7 @@ switch (TYPE(y)) { case T_BIGNUM: return DOUBLE2NUM((double)FIX2LONG(y) / rb_big2dbl(y)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y)); default: @@ -2208,6 +2266,7 @@ case T_BIGNUM: x = rb_int2big(FIX2LONG(x)); return rb_big_div(x, y); + case T_FIXFLOAT: case T_FLOAT: if (flo) { return DOUBLE2NUM((double)FIX2LONG(x) / RFLOAT_VALUE(y)); @@ -2271,6 +2330,7 @@ case T_BIGNUM: x = rb_int2big(FIX2LONG(x)); return rb_big_modulo(x, y); + case T_FIXFLOAT: case T_FLOAT: { double mod; @@ -2303,6 +2363,7 @@ case T_BIGNUM: x = rb_int2big(FIX2LONG(x)); return rb_big_divmod(x, y); + case T_FIXFLOAT: case T_FLOAT: { double div, mod; @@ -2403,6 +2464,7 @@ } x = rb_int2big(FIX2LONG(x)); return rb_big_pow(x, y); + case T_FIXFLOAT: case T_FLOAT: if (RFLOAT_VALUE(y) == 0.0) return DOUBLE2NUM(1.0); if (a == 0) { @@ -2434,6 +2496,7 @@ switch (TYPE(y)) { case T_BIGNUM: return rb_big_eq(y, x); + case T_FIXFLOAT: case T_FLOAT: return (double)FIX2LONG(x) == RFLOAT_VALUE(y) ? Qtrue : Qfalse; default: @@ -2461,6 +2524,7 @@ switch (TYPE(y)) { case T_BIGNUM: return rb_big_cmp(rb_int2big(FIX2LONG(x)), y); + case T_FIXFLOAT: case T_FLOAT: return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT_VALUE(y)); default: @@ -2486,6 +2550,7 @@ switch (TYPE(y)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse; + case T_FIXFLOAT: case T_FLOAT: return (double)FIX2LONG(x) > RFLOAT_VALUE(y) ? Qtrue : Qfalse; default: @@ -2511,6 +2576,7 @@ switch (TYPE(y)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse; + case T_FIXFLOAT: case T_FLOAT: return (double)FIX2LONG(x) >= RFLOAT_VALUE(y) ? Qtrue : Qfalse; default: @@ -2536,6 +2602,7 @@ switch (TYPE(y)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse; + case T_FIXFLOAT: case T_FLOAT: return (double)FIX2LONG(x) < RFLOAT_VALUE(y) ? Qtrue : Qfalse; default: @@ -2561,6 +2628,7 @@ switch (TYPE(y)) { case T_BIGNUM: return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse; + case T_FIXFLOAT: case T_FLOAT: return (double)FIX2LONG(x) <= RFLOAT_VALUE(y) ? Qtrue : Qfalse; default: Index: bignum.c =================================================================== --- bignum.c (revision 14077) +++ bignum.c (working copy) @@ -245,6 +245,13 @@ return rb_int2big(n); } +VALUE +rb_int2id(SIGNED_VALUE n) +{ + if (FIXABLE(n)) return INT2ID(n); + return rb_int2big(n); +} + #ifdef HAVE_LONG_LONG void @@ -1174,6 +1181,7 @@ case T_BIGNUM: break; + case T_FIXFLOAT: case T_FLOAT: return rb_dbl_cmp(rb_big2dbl(x), RFLOAT_VALUE(y)); @@ -1215,6 +1223,7 @@ break; case T_BIGNUM: break; + case T_FIXFLOAT: case T_FLOAT: { volatile double a, b; @@ -1409,6 +1418,7 @@ case T_BIGNUM: return bignorm(bigadd(x, y, 1)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(rb_big2dbl(x) + RFLOAT_VALUE(y)); @@ -1434,6 +1444,7 @@ case T_BIGNUM: return bignorm(bigadd(x, y, 0)); + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(rb_big2dbl(x) - RFLOAT_VALUE(y)); @@ -1458,6 +1469,7 @@ case T_BIGNUM: break; + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(rb_big2dbl(x) * RFLOAT_VALUE(y)); @@ -1664,6 +1676,7 @@ case T_BIGNUM: break; + case T_FIXFLOAT: case T_FLOAT: return DOUBLE2NUM(rb_big2dbl(x) / RFLOAT_VALUE(y)); @@ -1837,6 +1850,7 @@ bigdivrem(x, y, &z, 0); return DOUBLE2NUM(ldexp(big2dbl(z), ex - ey)); } + case T_FIXFLOAT: case T_FLOAT: y = dbl2big(ldexp(frexp(RFLOAT_VALUE(y), &ey), DBL_MANT_DIG)); ey -= DBL_MANT_DIG; @@ -1852,6 +1866,7 @@ dy = rb_big2dbl(y); break; + case T_FIXFLOAT: case T_FLOAT: dy = RFLOAT_VALUE(y); break; @@ -1930,6 +1945,7 @@ if (y == INT2FIX(0)) return INT2FIX(1); switch (TYPE(y)) { + case T_FIXFLOAT: case T_FLOAT: d = RFLOAT_VALUE(y); break; Index: random.c =================================================================== --- random.c (revision 14077) +++ random.c (working copy) @@ -436,6 +436,7 @@ rb_scan_args(argc, argv, "01", &vmax); switch (TYPE(vmax)) { + case T_FIXFLOAT: case T_FLOAT: if (RFLOAT_VALUE(vmax) <= LONG_MAX && RFLOAT_VALUE(vmax) >= LONG_MIN) { max = (long)RFLOAT_VALUE(vmax);