summaryrefslogtreecommitdiff
path: root/rational.c
diff options
context:
space:
mode:
authormrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-01 14:58:54 +0000
committermrkn <mrkn@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-01 14:58:54 +0000
commite06407cf7d8647a66c3d514014b71170d54ddca3 (patch)
treefdeeef19f123215a4a12a17ad957cd383193fa0b /rational.c
parent9ebd675c478a84ca1a7187eb2992e47ddd7a9e0d (diff)
* 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
Diffstat (limited to 'rational.c')
-rw-r--r--rational.c96
1 files changed, 58 insertions, 38 deletions
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 <ctype.h>