klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

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:
Msrc/kgnumbers.c | 33+++++++++++++++++++++++++++++++--
Msrc/kinteger.c | 73++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/kinteger.h | 2++
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);