From: Tadashi Saito Date: 2005-08-11T20:48:44+09:00 Subject: [ruby-dev:26789] Re: Fixnum演算メソッド中のcoerceの削減 斎藤と申します。 以前言及した、Fixnum比較演算についてのcoerce削減パッチです。 速度の向上は、平均で2倍速ちょっとという所です。 $ ruby cmp.rb before.cmp after.cmp [method & arg]: [n times faster] Fixnum == Bignum: 1.26264643227275 Fixnum == Float: 1.55535110739741 Fixnum <=> Bignum: 2.05209809644487 Fixnum <=> Float: 3.02643105919018 Fixnum > Bignum: 2.3287825740834 Fixnum > Float: 3.06581075412439 よろしければお使い下さい。よろしくおねがいします。 Index: bignum.c =================================================================== RCS file: /src/ruby/bignum.c,v retrieving revision 1.119 diff -u -p -r1.119 bignum.c --- bignum.c 10 Aug 2005 01:39:24 -0000 1.119 +++ bignum.c 11 Aug 2005 01:48:39 -0000 @@ -922,7 +922,7 @@ rb_big_to_f(x) * */ -static VALUE +VALUE rb_big_cmp(x, y) VALUE x, y; { @@ -968,7 +968,7 @@ rb_big_cmp(x, y) * 68719476736 == 68719476736.0 #=> true */ -static VALUE +VALUE rb_big_eq(x, y) VALUE x, y; { Index: intern.h =================================================================== RCS file: /src/ruby/intern.h,v retrieving revision 1.175 diff -u -p -r1.175 intern.h --- intern.h 3 Aug 2005 07:09:47 -0000 1.175 +++ intern.h 11 Aug 2005 01:48:39 -0000 @@ -95,6 +95,8 @@ void rb_quad_pack _((char*,VALUE)); VALUE rb_quad_unpack _((const char*,int)); VALUE rb_dbl2big _((double)); double rb_big2dbl _((VALUE)); +VALUE rb_big_cmp _((VALUE, VALUE)); +VALUE rb_big_eq _((VALUE, VALUE)); VALUE rb_big_plus _((VALUE, VALUE)); VALUE rb_big_minus _((VALUE, VALUE)); VALUE rb_big_mul _((VALUE, VALUE)); Index: numeric.c =================================================================== RCS file: /src/ruby/numeric.c,v retrieving revision 1.124 diff -u -p -r1.124 numeric.c --- numeric.c 4 Aug 2005 11:29:51 -0000 1.124 +++ numeric.c 11 Aug 2005 01:48:40 -0000 @@ -2289,7 +2289,12 @@ fix_equal(x, y) if (FIXNUM_P(y)) { return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse; } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return rb_big_eq(y, x); + case T_FLOAT: + return (double)FIX2LONG(x) == RFLOAT(y)->value ? Qtrue : Qfalse; + default: return num_equal(x, y); } } @@ -2314,7 +2319,12 @@ fix_cmp(x, y) if (a > b) return INT2FIX(1); return INT2FIX(-1); } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return rb_big_cmp(rb_int2big(FIX2LONG(x)), y); + case T_FLOAT: + return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT(y)->value); + default: return rb_num_coerce_cmp(x, y); } } @@ -2337,7 +2347,12 @@ fix_gt(x, y) if (a > b) return Qtrue; return Qfalse; } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse; + case T_FLOAT: + return (double)FIX2LONG(x) > RFLOAT(y)->value ? Qtrue : Qfalse; + default: return rb_num_coerce_relop(x, y); } } @@ -2360,7 +2375,12 @@ fix_ge(x, y) if (a >= b) return Qtrue; return Qfalse; } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse; + case T_FLOAT: + return (double)FIX2LONG(x) >= RFLOAT(y)->value ? Qtrue : Qfalse; + default: return rb_num_coerce_relop(x, y); } } @@ -2383,7 +2403,12 @@ fix_lt(x, y) if (a < b) return Qtrue; return Qfalse; } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse; + case T_FLOAT: + return (double)FIX2LONG(x) < RFLOAT(y)->value ? Qtrue : Qfalse; + default: return rb_num_coerce_relop(x, y); } } @@ -2406,7 +2431,12 @@ fix_le(x, y) if (a <= b) return Qtrue; return Qfalse; } - else { + switch (TYPE(y)) { + case T_BIGNUM: + return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse; + case T_FLOAT: + return (double)FIX2LONG(x) <= RFLOAT(y)->value ? Qtrue : Qfalse; + default: return rb_num_coerce_relop(x, y); } } -- 斎藤ただし # 今度こそ間違いがないといいんですが…