From e06407cf7d8647a66c3d514014b71170d54ddca3 Mon Sep 17 00:00:00 2001 From: mrkn Date: Thu, 1 Aug 2013 14:58:54 +0000 Subject: * rational.c (rb_flt_rationalize_with_prec): new public C function to rationalize a Float instance with a precision. * rational.c (rb_flt_rationalize): new public C function to rationalize a Float instance. A precision is calculated from the given float number. * include/ruby/intern.h: Add rb_flt_rationalize_with_prec and rb_flt_rationalize. * parse.y: implement number literal suffixes, 'r' and 'i'. [ruby-core:55096] [Feature #8430] * bootstraptest/test_literal_suffix.rb: add tests for parser to scan number literals with the above tsuffixes. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42311 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- rational.c | 96 +++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 38 deletions(-) (limited to 'rational.c') diff --git a/rational.c b/rational.c index 6cd31e119a..ee0e1689e9 100644 --- a/rational.c +++ b/rational.c @@ -2004,6 +2004,60 @@ float_to_r(VALUE self) #endif } +VALUE +rb_flt_rationalize_with_prec(VALUE flt, VALUE prec) +{ + VALUE e, a, b, p, q; + + e = f_abs(prec); + a = f_sub(flt, e); + b = f_add(flt, e); + + if (f_eqeq_p(a, b)) + return f_to_r(flt); + + nurat_rationalize_internal(a, b, &p, &q); + return rb_rational_new2(p, q); +} + +VALUE +rb_flt_rationalize(VALUE flt) +{ + VALUE a, b, f, n, p, q; + + float_decode_internal(flt, &f, &n); + if (f_zero_p(f) || f_positive_p(n)) + return rb_rational_new1(f_lshift(f, n)); + +#if FLT_RADIX == 2 + { + VALUE two_times_f, den; + + two_times_f = f_mul(TWO, f); + den = f_lshift(ONE, f_sub(ONE, n)); + + a = rb_rational_new2(f_sub(two_times_f, ONE), den); + b = rb_rational_new2(f_add(two_times_f, ONE), den); + } +#else + { + VALUE radix_times_f, den; + + radix_times_f = f_mul(INT2FIX(FLT_RADIX), f); + den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)); + + a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); + b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); + } +#endif + + if (f_eqeq_p(a, b)) + return f_to_r(flt); + + nurat_rationalize_internal(a, b, &p, &q); + return rb_rational_new2(p, q); +} + /* * call-seq: * flt.rationalize([eps]) -> rational @@ -2021,53 +2075,19 @@ float_to_r(VALUE self) static VALUE float_rationalize(int argc, VALUE *argv, VALUE self) { - VALUE e, a, b, p, q; + VALUE e; if (f_negative_p(self)) - return f_negate(float_rationalize(argc, argv, f_abs(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); + return rb_flt_rationalize_with_prec(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 - { - VALUE two_times_f, den; - - two_times_f = f_mul(TWO, f); - den = f_lshift(ONE, f_sub(ONE, n)); - - a = rb_rational_new2(f_sub(two_times_f, ONE), den); - b = rb_rational_new2(f_add(two_times_f, ONE), den); - } -#else - { - VALUE radix_times_f, den; - - radix_times_f = f_mul(INT2FIX(FLT_RADIX), f); - den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n)); - - a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); - b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den); - } -#endif + return rb_flt_rationalize(self); } - - if (f_eqeq_p(a, b)) - return f_to_r(self); - - nurat_rationalize_internal(a, b, &p, &q); - return rb_rational_new2(p, q); } #include -- cgit v1.2.3