From: Charles Mills Date: 2005-05-19T00:50:14+09:00 Subject: Re: Strange behaviour of class Fixnum in exponentation Wolfgang N�dasi-Donner wrote: > The german Ruby forum recognized a strange behaviour of the Fixnum class. > > In exponentation Fixnum is much slower than Bignum, which lets us assume, that some kind of a problem occurs > in the implementation. Example: > > >>>>> Code (Ruby) >>>>> > > require 'benchmark' > > N = 10**6 > B = 65891264863465298234965902602612457060348499377 > F = 4628 > > Benchmark.bmbm(10) do |bm| > bm.report('Bignum') do N.times do > B ** 0.5 > end end > > bm.report('Fixnum') do N.times do > F ** 0.5 > end end > end > > >>>>> Result >>>>> > user system total real > > Bignum 3.856000 0.000000 3.856000 ( 3.946000) > Fixnum 7.861000 0.020000 7.881000 ( 8.081000) > > >>>>> End of Example >>>>> > > Further investigations leads to the responsible C code: > > >>>>> Code (C) >>>>> > > static VALUE > fix_pow(x, y) > VALUE x, y; > { > if (FIXNUM_P(y)) { > long a, b; > > b = FIX2LONG(y); > if (b == 0) return INT2FIX(1); > if (b == 1) return x; > a = FIX2LONG(x); > if (b > 0) { > return rb_big_pow(rb_int2big(a), y); > } > return rb_float_new(pow((double)a, (double)b)); > } > return rb_num_coerce_bin(x, y); // <-- das dauert > } You chould change the above code to and it should solve the speed problem. untested code: static VALUE fix_pow(x, y) VALUE x, y; { if (FIXNUM_P(y)) { long a, b; b = FIX2LONG(y); if (b == 0) return INT2FIX(1); if (b == 1) return x; a = FIX2LONG(x); if (b > 0) { return rb_big_pow(rb_int2big(a), y); } return rb_float_new(pow((double)a, (double)b)); } else if (TYPE(y) == T_FLOAT) { long a = FIX2LONG(x); return rb_float_new(pow((double)a, RFLOAT(y)->value)); } return rb_num_coerce_bin(x, y); // <-- das dauert } -Charlie