正木です。
拡張ライブラリ版 Rational 拝見しました。
大変参考になります。ただ二三問題があります。

以前にも書きましたが、rb_rat_to_f はこのままでは numerator 
もしくは denominator が Float の範囲外で、その値自身は範囲
内のときに、正しい値を返しません。

それから floor,ceil,round の定義が抜けているようです。

rb_rat_to_i ですが、これだと
(-3/2).to_i #=> -2
(-1.5).to_i #=> -1
となって整合性がとれません。
Float と仕様を合わした方が良くありませんか?


私の rational.c では次のようにしています。
to_f は intel x86 以外でも正しく動くかどうか分かりませんが、
その点も含めて検討していただけませんか。

ついでなので Bignum#to_f も付けておきます。

------
/* rational.c */

#include "ruby.h"
#include <math.h>

#define Zero  INT2FIX(0)
#define Unity INT2FIX(1)
#define Two   INT2FIX(2)
#define rb_uminus(x)    rb_funcall(x,rb_intern("-@"),0)
#define rb_abs(x)       rb_funcall(x,rb_intern("abs"),0)
#define rb_inverse(x)   rb_funcall(x,rb_intern("inverse"),0)
#define rb_hash(x)      rb_funcall(x,rb_intern("hash"),0)
#define rb_to_f(x)      rb_funcall(x,rb_intern("to_f"),0)
#define rb_plus(x,y)    rb_funcall(x,'+',1,y)
#define rb_minus(x,y)   rb_funcall(x,'-',1,y)
#define rb_mul(x,y)     rb_funcall(x,'*',1,y)
#define rb_quot(x,y)    rb_funcall(x,'/',1,y)
#define rb_div(x,y)     rb_funcall(x,rb_intern("div"),1,y)
#define rb_mod(x,y)     rb_funcall(x,'%',1,y)
#define rb_xor(x,y)     rb_funcall(x,'^',1,y)
#define rb_cmp(x,y)     rb_funcall(x,rb_intern("<=>"),1,y)
#define rb_eq(x,y)      rb_funcall(x,rb_intern("=="),1,y)
#define rb_rshift(x,y)  rb_funcall(x,rb_intern(">>"),1,y)
#define rb_lshift(x,y)  rb_funcall(x,rb_intern("<<"),1,y)
#define rb_power(x,y)   rb_funcall(x,rb_intern("**"),1,y)
#define rb_less(x,y)    rb_funcall(x,'<',1,y)
#define rb_greater(x,y) rb_funcall(x,'>',1,y)
#define is_negative(x)  rb_funcall(x,'<',1,Zero)
#define is_integer(x)  (TYPE(x) == T_FIXNUM || TYPE(x) == T_BIGNUM)
#define is_float(x)    (TYPE(x) == T_FLOAT)
#define is_rational(x) (CLASS_OF(x) == rb_cRational)
#define is_zero(x)     (FIXNUM_P(x) && FIX2INT(x)==0)
#define is_unity(x)    (FIXNUM_P(x) && FIX2INT(x)==1)
#define is_two(x)      (FIXNUM_P(x) && FIX2INT(x)==2)

(以下直接関係無いところは省略)

static VALUE
rb_rational_floor(VALUE self)
{
  struct RRational *rrational;
  VALUE num, den;

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

static VALUE
rb_rational_ceil(VALUE self)
{
  struct RRational *rrational;
  VALUE num, den;

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

static VALUE
rb_rational_round(VALUE self)
{
  struct RRational *rrational;
  VALUE num, den;

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

static VALUE
rb_rational_to_i(VALUE self)
{
  struct RRational *rrational;
  VALUE num, den;

  Data_Get_Struct(self,struct RRational,rrational);
  num = rrational->num;
  den = rrational->den;
  if(is_negative(num)) return rb_uminus(rb_div(rb_uminus(num),den));
  return rb_div(num,den);
}

static VALUE
rb_rational_log2floor(VALUE self)
{
  VALUE inv,n,m;
  if(is_negative(self)) rb_raise(rb_eTypeError,"argument is not positive");
  if(rb_greater(self,Unity))
    return rb_funcall((rb_rational_floor(self)),rb_intern("int_log2"),0);
  inv=rb_rational_inverse(self);
  n=rb_funcall(inv,rb_intern("int_log2"),0);
  m=rb_uminus(n);
  if(is_integer(inv) && rb_eq(rb_lshift(Unity,n),inv)) return m;
  return rb_minus(m,Unity);
}

static VALUE
rb_rational_lshift(VALUE self, VALUE m)
{
  struct RRational *rrational;
  VALUE num,den;

  Data_Get_Struct(self,struct RRational,rrational);
  num = rrational->num;
  den = rrational->den;
  if (is_negative(m))
    return rb_rational(self,num,rb_lshift(den,rb_uminus(m)));
  return rb_rational(self,rb_lshift(num,m),den);
}

static VALUE
rb_rational_to_f(VALUE self)
{
  VALUE m,n,e,a;
  m=rb_minus(rb_const_get(rb_cFloat,rb_intern("MANT_DIG")),Unity);
  n=rb_funcall(rb_rational_abs(self),rb_intern("int_log2"),0);
  e=rb_minus(m,n);
  a=rb_funcall(rb_rational_lshift(self,e),rb_intern("round"),0);
  return rb_funcall(rb_intern("Math"),rb_intern("ldexp"),2,a,rb_uminus(e));
}

static VALUE
rb_rational_hash(VALUE self)
{
  VALUE num_hash,den_hash,rational_hash;
  rational_hash = rb_hash(rb_cRational);
  num_hash = rb_hash(rb_rational_num(self));
  den_hash = rb_hash(rb_rational_den(self));
  return rb_hash(rb_plus(rb_mul(rational_hash,num_hash),den_hash));
}

void
Init_rational(void)
{
  rb_define_method(rb_cRational,"floor",rb_rational_floor,0);
  rb_define_method(rb_cRational,"ceil",rb_rational_ceil,0);
  rb_define_method(rb_cRational,"round",rb_rational_round,0);
  rb_define_method(rb_cRational,"to_i",rb_rational_to_i,0);
  rb_define_method(rb_cRational,"int_log2",rb_rational_log2floor,0);
  rb_define_method(rb_cRational,"lshift",rb_rational_lshift,1);
  rb_define_method(rb_cRational,"to_f",rb_rational_to_f,0);
  rb_define_method(rb_cRational,"hash",rb_rational_hash,0);
}

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

static VALUE
int_log2floor(VALUE self)
{
  int i,byte,s,size;
  VALUE d;
  if(!is_positive(self)) rb_raise(rb_eTypeError,"argument is not positive");
  byte=8;
  s=FIX2INT(rb_size(Unity));
  size=FIX2INT(rb_size(self));
  d=INT2FIX(byte*(size-s));
  if(size>s) return rb_plus(int_log2floor(rb_rshift(self,d)),d);
  i=byte*s-1;
  while(is_zero(rb_funcall(self,rb_intern("[]"),1,INT2FIX(i)))) i -= 1;
  return INT2FIX(i);
}

static VALUE
rb_int_to_f(VALUE self)
{
  VALUE m,l,n,a,d;
  m=rb_minus(rb_const_get(rb_cFloat,rb_intern("MANT_DIG")),Unity);
  l=int_log2floor(rb_abs(self));
  n=rb_minus(l,m);
  if (is_negative(n)){
    return rb_funcall(rb_intern("Math"),rb_intern("ldexp"),2,self,Zero);
  }
  else{
    a=rb_rshift(rb_plus(rb_rshift(self,rb_minus(n,Unity)),Unity),Unity);
    return rb_funcall(rb_intern("Math"),rb_intern("ldexp"),2,a,n);
  }
}

void
Init_integer(void)
{
  rb_define_method(rb_cInteger,"int_log2",int_log2floor,0);
  rb_define_method(rb_cBignum,"to_f",rb_int_to_f,0);
}