static VALUE
float_rationalize(int argc, VALUE *argv, VALUE self)
{
VALUE e, a, b, p, q;
if (f_negative_p(self))
return f_negate(float_rationalize(argc, argv, f_abs(self)));
rb_scan_args(argc, argv, "01", &e);
if (argc != 0) {
e = f_abs(e);
a = f_sub(self, e);
b = f_add(self, e);
}
else {
VALUE f, n;
float_decode_internal(self, &f, &n);
if (f_zero_p(f) || f_positive_p(n))
return rb_rational_new1(f_lshift(f, n));
#if FLT_RADIX == 2
a = rb_rational_new2(f_sub(f_mul(TWO, f), ONE),
f_lshift(ONE, f_sub(ONE, n)));
b = rb_rational_new2(f_add(f_mul(TWO, f), ONE),
f_lshift(ONE, f_sub(ONE, n)));
#else
a = rb_rational_new2(f_sub(f_mul(INT2FIX(FLT_RADIX), f),
INT2FIX(FLT_RADIX - 1)),
f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)));
b = rb_rational_new2(f_add(f_mul(INT2FIX(FLT_RADIX), f),
INT2FIX(FLT_RADIX - 1)),
f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)));
#endif
}
if (f_eqeq_p(a, b))
return f_to_r(self);
nurat_rationalize_internal(a, b, &p, &q);
return rb_rational_new2(p, q);
}