commit 51b19792042a7cc65292698f0a4c947f426ffcc6
parent 4ef1dabaea247b73f87767e529e87b5bb865b5b7
Author: Andres Navarro <canavarro82@gmail.com>
Date: Sun, 1 May 2011 01:23:21 -0300
Added rational->real conversion.
Diffstat:
M | src/kreal.c | | | 59 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/src/kreal.c b/src/kreal.c
@@ -28,8 +28,6 @@
else res = d2tv(d__); \
res;})
-
-
double kbigint_to_double(Bigint *bigint)
{
double radix = (double) UINT32_MAX + 1.0;
@@ -45,6 +43,58 @@ double kbigint_to_double(Bigint *bigint)
return mp_int_compare_zero(bigint) < 0? -accum : accum;
}
+/* bigrat is rooted */
+double kbigrat_to_double(klisp_State *K, Bigrat *bigrat)
+{
+ TValue tv_rem = kbigrat_copy(K, gc2bigrat(bigrat));
+ krooted_tvs_push(K, tv_rem);
+ Bigrat *rem = tv2bigrat(tv_rem);
+ UNUSED(mp_rat_abs(K, rem, rem));
+
+ TValue int_radix = kbigint_make_simple(K);
+ krooted_tvs_push(K, int_radix);
+ /* cant do UINT32_MAX and then +1 because _value functions take
+ int32_t arguments */
+ UNUSED(mp_int_set_value(K, tv2bigint(int_radix), INT32_MAX));
+ UNUSED(mp_int_add_value(K, tv2bigint(int_radix), 1,
+ tv2bigint(int_radix)));
+ UNUSED(mp_int_add(K, tv2bigint(int_radix), tv2bigint(int_radix),
+ tv2bigint(int_radix)));
+
+ TValue int_part = kbigint_make_simple(K);
+ krooted_tvs_push(K, int_part);
+
+ double accum = 0.0;
+ double radix = (double) UINT32_MAX + 1.0;
+ uint32_t digit = 0;
+ /* inside there is a check to avoid problem with continuing fractions */
+ while(mp_rat_compare_zero(rem) > 0) {
+ UNUSED(mp_int_div(K, MP_NUMER_P(rem), MP_DENOM_P(rem),
+ tv2bigint(int_part), NULL));
+
+ double di = kbigint_to_double(tv2bigint(int_part));
+ bool was_zero = di == 0.0;
+ for (uint32_t i = 0; i < digit; i++) {
+ di /= radix;
+ }
+ /* if last di became 0.0 we will exit next loop,
+ this is to avoid problem with continuing fractions */
+ if (!was_zero && di == 0.0)
+ break;
+
+ ++digit;
+ accum += di;
+
+ UNUSED(mp_rat_sub_int(K, rem, tv2bigint(int_part), rem));
+ UNUSED(mp_rat_mul_int(K, rem, tv2bigint(int_radix), rem));
+ }
+ krooted_tvs_pop(K); /* int_part */
+ krooted_tvs_pop(K); /* int_radix */
+ krooted_tvs_pop(K); /* rem */
+
+ return mp_rat_compare_zero(bigrat) < 0? -accum : accum;
+}
+
TValue kexact_to_inexact(klisp_State *K, TValue n)
{
switch(ttype(n)) {
@@ -58,8 +108,9 @@ TValue kexact_to_inexact(klisp_State *K, TValue n)
return ktag_double(d);
}
case K_TBIGRAT: {
- klisp_assert(0);
- return KUNDEF;
+ Bigrat *bigrat = tv2bigrat(n);
+ double d = kbigrat_to_double(K, bigrat);
+ return ktag_double(d);
}
case K_TEINF:
return tv_equal(n, KEPINF)? KIPINF : KIMINF;