正木です。

In [ruby-math:00966]

|近岡です。
|
|isqrtの組込みに関して意見を述べさせてください。
|組込みを前提とした場合、私の意見は、次の2点です。
|
|1.FIXNUM用とBIGNUM用の2つに分ける

これまで何度も書いたように、これは困ります。
(絶対反対というわけではありませんが。)

実際の C の code は原さんにお任せしますが、参考までに
現在私が使っている code を付記します。

------
#define Unity            INT2FIX(1)
#define rb_lshift(x,y)   rb_big_lshift(x, LONG2FIX(y))
#define rb_rshift(x,y)   rb_big_rshift(x, LONG2FIX(y))
#define rb_less(x,y)     (FIX2INT(rb_big_cmp(x, y)) == -1)

static long
int_sqrt(i)
    long i;
{
    long j, k;
    if (i < 0) rb_raise(rb_eRangeError,"argument is negative");
    if (i == 0) return 0;
    j = int_sqrt(i >> 2) << 1;
    k = j | 1;
    if (k * k > i) return j;
    return k;
}

static VALUE
rb_isqrt_ini(x)
    VALUE x;
{
    long j;
    VALUE y, z;
    if (FIXNUM_P(x)) return LONG2FIX(int_sqrt(FIX2LONG(x))); 
    j = (FIX2LONG(rb_ilog2(x)) + 2) >> 2;
    y = rb_isqrt_ini(rb_rshift(x, j << 1));
    return rb_rshift(rb_big_plus(rb_lshift(y, j), rb_big_div(rb_rshift(x, j),y)), 1);
}

static VALUE
rb_isqrt(x)
    VALUE x;
{
    VALUE y;
    if (FIXNUM_P(x)) return LONG2FIX(int_sqrt(FIX2LONG(x))); 
    if (!RBIGNUM(x)->sign)  rb_raise(rb_eRangeError,"argument is negative");
    y = rb_isqrt_ini(x);
    if (rb_less(x, rb_big_mul(y, y))) return rb_big_minus(y, Unity);
    return y;
}

-----
ただし
rb_big_plus,rb_big_minus,rb_big_lshift,rb_big_rshift,rb_big_div に

    if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));

の一行を追加しています。