commit 1d3cc6969b0644dccf778fb7f44eedcc914d9b63
parent df4f614e602ce528c0de4c0829c1418c6d99b64d
Author: Andres Navarro <canavarro82@gmail.com>
Date: Sun, 10 Apr 2011 20:53:47 -0300
Added support for bigints to =? applicative.
Diffstat:
3 files changed, 81 insertions(+), 27 deletions(-)
diff --git a/src/kgnumbers.c b/src/kgnumbers.c
@@ -53,8 +53,37 @@ inline int32_t max_ttype(TValue obj1, TValue obj2)
return (t1 > t2? t1 : t2);
}
-/* TEMP: for now only fixints and exact infinities */
-bool knum_eqp(TValue n1, TValue n2) { return tv_equal(n1, n2); }
+inline int32_t min_ttype(TValue obj1, TValue obj2)
+{
+ int32_t t1 = ttype(obj1);
+ int32_t t2 = ttype(obj2);
+
+ return (t1 < t2? t1 : t2);
+}
+
+/* TEMP: for now only fixints, bigints and exact infinities */
+bool knum_eqp(TValue n1, TValue n2)
+{
+ switch(max_ttype(n1, n2)) {
+ case K_TFIXINT:
+ return ivalue(n1) == ivalue(n2);
+ case K_TBIGINT:
+ if (min_ttype(n1, n2) != K_TBIGINT) {
+ /* NOTE: no fixint is =? to a bigint */
+ return false;
+ } else {
+ /* both are bigints */
+ return kbigint_eqp(n1, n2);
+ }
+ case K_TEINF:
+ return (tv_equal(n1, n2));
+ default:
+ /* shouldn't happen */
+ assert(0);
+ return false;
+ }
+}
+
bool knum_ltp(TValue n1, TValue n2)
{
switch(max_ttype(n1, n2)) {
diff --git a/src/kinteger.c b/src/kinteger.c
@@ -154,6 +154,54 @@ bool kbigint_has_digits(klisp_State *K, TValue tv_bigint)
return kbigint_size(tv2bigint(tv_bigint)) != 0;
}
+/* Mutate the bigint to have the opposite sign, used in read,
+ write and abs */
+void kbigint_invert_sign(TValue tv_bigint)
+{
+ Bigint *bigint = tv2bigint(tv_bigint);
+ bigint->sign_size = -bigint->sign_size;
+}
+
+/* this is used by write to estimate the number of chars necessary to
+ print the number */
+int32_t kbigint_print_size(TValue tv_bigint, int32_t base)
+{
+ /* count the number of bits and estimate using the log of
+ the base */
+ Bigint *bigint = tv2bigint(tv_bigint);
+
+ int32_t num_bits = 0;
+ uint32_t first_digit = bigint->first->digit;
+ while(first_digit != 0) {
+ ++num_bits;
+ first_digit >>= 1;
+ }
+ num_bits += 32 * (kbigint_size(bigint)) - 2 ;
+ /* add 1.5 for safety */
+ return (int32_t)(LOG_BASE(base) * num_bits + 1.0);
+}
+
+bool kbigint_eqp(TValue tv_bigint1, TValue tv_bigint2)
+{
+ Bigint *bigint1 = tv2bigint(tv_bigint1);
+ Bigint *bigint2 = tv2bigint(tv_bigint2);
+
+ if (bigint1->sign_size != bigint2->sign_size)
+ return false;
+
+ /* iterate in big endian mode */
+ bind_iter(iter1, bigint1, true);
+ bind_iter(iter2, bigint2, true);
+
+ while(iter_has_next(iter1)) {
+ uint32_t digit1 = iter_next(iter1);
+ uint32_t digit2 = iter_next(iter2);
+ if (digit1 != digit2)
+ return false;
+ }
+ return true;
+}
+
bool kbigint_negativep(TValue tv_bigint)
{
return kbigint_negp(tv2bigint(tv_bigint));
@@ -189,28 +237,3 @@ TValue kbigint_abs(klisp_State *K, TValue tv_bigint)
}
}
-/* Mutate the bigint to have the opposite sign, used in read */
-void kbigint_invert_sign(TValue tv_bigint)
-{
- Bigint *bigint = tv2bigint(tv_bigint);
- bigint->sign_size = -bigint->sign_size;
-}
-
-/* this is used by write to estimate the number of chars necessary to
- print the number */
-int32_t kbigint_print_size(TValue tv_bigint, int32_t base)
-{
- /* count the number of bits and estimate using the log of
- the base */
- Bigint *bigint = tv2bigint(tv_bigint);
-
- int32_t num_bits = 0;
- uint32_t first_digit = bigint->first->digit;
- while(first_digit != 0) {
- ++num_bits;
- first_digit >>= 1;
- }
- num_bits += 32 * (kbigint_size(bigint)) - 2 ;
- /* add 1.5 for safety */
- return (int32_t)(LOG_BASE(base) * num_bits + 1.0);
-}
diff --git a/src/kinteger.h b/src/kinteger.h
@@ -48,6 +48,8 @@ int32_t kbigint_remove_digit(klisp_State *K, TValue tv_bigint, int32_t base);
/* This is used by write to test if there is any digit left to print */
bool kbigint_has_digits(klisp_State *K, TValue tv_bigint);
+bool kbigint_eqp(TValue bigint1, TValue bigint2);
+
bool kbigint_negativep(TValue tv_bigint);
bool kbigint_positivep(TValue tv_bigint);