commit ba3e6bebfcb7f348fb380665a25ee68ed38a44d3
parent 723f1354e3c8a81f16b01fd69f05ad52518039e6
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sat, 23 Apr 2011 18:00:03 -0300
Added support for rationals to abs, negative? & positive?.
Diffstat:
2 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/src/kgnumbers.c b/src/kgnumbers.c
@@ -258,6 +258,10 @@ TValue knum_abs(klisp_State *K, TValue n)
 	kensure_bigint(n); 
 	return kbigint_abs(K, n);
     }
+    case K_TBIGRAT: {
+	kensure_bigrat(n); 
+	return kbigrat_abs(K, n);
+    }
     case K_TEINF:
 	return KEPINF;
     default:
@@ -720,6 +724,8 @@ bool kpositivep(TValue n)
 	return ivalue(n) > 0;
     case K_TBIGINT:
 	return kbigint_positivep(n);
+    case K_TBIGRAT:
+	return kbigrat_positivep(n);
     default:
 	/* shouldn't happen */
 	assert(0);
@@ -735,6 +741,8 @@ bool knegativep(TValue n)
 	return ivalue(n) < 0;
     case K_TBIGINT:
 	return kbigint_negativep(n);
+    case K_TBIGRAT:
+	return kbigrat_negativep(n);
     default:
 	/* shouldn't happen */
 	assert(0);
diff --git a/src/krational.c b/src/krational.c
@@ -71,10 +71,13 @@ TValue kbigrat_new(klisp_State *K, bool sign, uint32_t num,
     return gc2bigrat(new_bigrat);
 }
 
+/* macro to create the simplest rational */
+#define kbigrat_make_simple(K_) kbigrat_new(K_, false, 0, 1)
+
 /* assumes src is rooted */
 TValue kbigrat_copy(klisp_State *K, TValue src)
 {
-    TValue copy = kbigrat_new(K, false, 0, 1);
+    TValue copy = kbigrat_make_simple(K);
     /* arguments are in reverse order with respect to mp_rat_copy */
     UNUSED(mp_rat_init_copy(K, tv2bigrat(copy), tv2bigrat(src)));
     return copy;
@@ -87,7 +90,7 @@ TValue kbigrat_copy(klisp_State *K, TValue src)
 bool krational_read(klisp_State *K, char *buf, int32_t base, TValue *out, 
 		   char **end)
 {
-    TValue res = kbigrat_new(K, false, 0, 1);
+    TValue res = kbigrat_make_simple(K);
     krooted_tvs_push(K, res);
     bool ret_val = (mp_rat_read_cstring(K, tv2bigrat(res), base, 
 					buf, end) == MP_OK);
@@ -109,7 +112,7 @@ bool krational_read(klisp_State *K, char *buf, int32_t base, TValue *out,
 bool krational_read_decimal(klisp_State *K, char *buf, int32_t base, TValue *out, 
 			    char **end)
 {
-    TValue res = kbigrat_new(K, false, 0, 1);
+    TValue res = kbigrat_make_simple(K);
     krooted_tvs_push(K, res);
     bool ret_val = (mp_rat_read_ustring(K, tv2bigrat(res), base, 
 					buf, end) == MP_OK);
@@ -183,3 +186,28 @@ bool kbigrat_gep(klisp_State *K, TValue tv_bigrat1, TValue tv_bigrat2)
     return (mp_rat_compare(K, tv2bigrat(tv_bigrat1), 
 			   tv2bigrat(tv_bigrat2)) >= 0);
 }
+
+bool kbigrat_negativep(TValue tv_bigrat)
+{
+    return (mp_rat_compare_zero(tv2bigrat(tv_bigrat)) < 0);
+}
+
+bool kbigrat_positivep(TValue tv_bigrat)
+{
+    return (mp_rat_compare_zero(tv2bigrat(tv_bigrat)) > 0);
+}
+
+/* needs the state to create a copy if negative */
+TValue kbigrat_abs(klisp_State *K, TValue tv_bigrat)
+{
+    if (kbigrat_negativep(tv_bigrat)) {
+	TValue copy = kbigrat_make_simple(K);
+	krooted_tvs_push(K, copy);
+	UNUSED(mp_rat_abs(K, tv2bigrat(tv_bigrat), tv2bigrat(copy)));
+	krooted_tvs_pop(K);
+	/* NOTE: this can never be an integer if the parameter was a bigrat */
+	return copy;
+    } else {
+	return tv_bigrat;
+    }
+}