正木です。


|原です。
|round も self の正負で場合分けが必要なんじゃないかな。

こちらの方はすっかり忘れていました。


static VALUE
rb_rational_round(VALUE self)
{
  struct RRational *rrational;
  VALUE num, den;
  if(is_negative(self)) return rb_uminus(rb_rational_round(rb_uminus(self)));

  Data_Get_Struct(self,struct RRational,rrational);
  num = rrational->num;
  den = rrational->den;
  return rb_div(rb_plus(rb_mul(num,Two),den),rb_mul(den,Two));
}

に訂正します。

|#やっぱり Integer を返す sqrt と log2 は、欲しいですね。

同感です。ちなみに私は次のようにしています。

-----
/* integer.c */

static int
int_sqrt(int i)
{
  int j;
  if(i == 0) return 0;
  j=2*int_sqrt(i >> 2);
  if((j + 1) * (j + 1) > i) return j;
  return j + 1;
}

static VALUE
rb_int_sqrt(VALUE self)
{
  VALUE j,k,k1;
  if(is_negative(self))
    rb_raise(rb_eTypeError,"argument is negative");
  switch (TYPE(self)) {
  case T_FIXNUM:
    return INT2FIX(int_sqrt(FIX2INT(self)));
    break;
  case T_BIGNUM:
    j=rb_rshift(self,Two);
    k=rb_mul(rb_int_sqrt(j),Two);
    k1=rb_plus(k,Unity);
    if(rb_greater(rb_mul(k1,k1),self)) return k;
    return k1;
    break;
  default:
    rb_raise(rb_eTypeError,"argument is not integer");
  }
}

static VALUE
rb_int_root(VALUE self,VALUE m)
{
  VALUE j,k,k1;
  if(is_zero(self)) return Zero;
  j=rb_rshift(self,m);
  k=rb_mul(rb_int_root(j,m),Two);
  k1=rb_plus(k,Unity);
  if(rb_greater(rb_power(k1,m),self)) return k;
  return k1;
}

void
Init_integer(void)
{
  rb_define_method(rb_cInteger,"int_sqrt",rb_int_sqrt,0);
  rb_define_method(rb_cInteger,"int_root",rb_int_root,1);
}
-----