commit 7ac6a08241675b63e9f413917c89eba5e701f0f5
parent 57390ed864b9d860353ecf100974f211f2343b89
Author: Andres Navarro <canavarro82@gmail.com>
Date: Sat, 23 Apr 2011 12:57:53 -0300
Added a krational.h header file. TODO: add krational.c.
Diffstat:
3 files changed, 174 insertions(+), 7 deletions(-)
diff --git a/src/Makefile b/src/Makefile
@@ -10,12 +10,13 @@ MYLIBS=
CORE_O= kobject.o ktoken.o kpair.o kstring.o ksymbol.o kread.o \
kwrite.o kstate.o kmem.o kerror.o kauxlib.o kenvironment.o \
kcontinuation.o koperative.o kapplicative.o keval.o krepl.o \
- kencapsulation.o kpromise.o kport.o kinteger.o ktable.o \
+ kencapsulation.o kpromise.o kport.o kinteger.o krational.o \
+ ktable.o kgc.o imath.o imrat.o \
kground.o kghelpers.o kgbooleans.o kgeqp.o kgequalp.o \
kgsymbols.o kgcontrol.o kgpairs_lists.o kgpair_mut.o kgenvironments.o \
kgenv_mut.o kgcombiners.o kgcontinuations.o kgencapsulations.o \
kgpromises.o kgkd_vars.o kgks_vars.o kgports.o kgchars.o kgnumbers.o \
- kgstrings.o imath.o imrat.o kgc.o
+ kgstrings.o
KRN_T= klisp
KRN_O= klisp.o
@@ -44,9 +45,11 @@ klisp.o: klisp.c klisp.h kobject.h kread.h kwrite.h klimits.h kstate.h kmem.h \
kapplicative.h koperative.h keval.h krepl.h kground.h
kobject.o: kobject.c kobject.h klimits.h klispconf.h
ktoken.o: ktoken.c ktoken.h kobject.h kstate.h kpair.h kstring.h ksymbol.h \
- kerror.h klisp.h kinteger.h kport.h
+ kerror.h klisp.h kinteger.h krational.h kport.h
kinteger.o: kinteger.c kinteger.h kobject.h kstate.h kmem.h klisp.h imath.h \
kgc.h
+krational.o: krational.c krational.h kinteger.h kobject.h kstate.h kmem.h klisp.h
+ imrat.h kgc.h
kpair.o: kpair.c kpair.h kobject.h kstate.h kmem.h klisp.h kgc.h
kstring.o: kstring.c kstring.h kobject.h kstate.h kmem.h klisp.h kgc.h
# XXX: kpair.h because of use of list as symbol table
@@ -55,11 +58,12 @@ ksymbol.o: ksymbol.c ksymbol.h kobject.h kpair.h kstring.h kstate.h kmem.h \
kread.o: kread.c kread.h kobject.h ktoken.h kpair.h kstate.h kerror.h klisp.h \
kport.h ktable.h klispconf.h
kwrite.o: kwrite.c kwrite.h kobject.h kpair.h kstring.h kstate.h kerror.h \
- klisp.h kport.h kinteger.h ktable.h klispconf.h
+ klisp.h kport.h kinteger.h krational.h ktable.h klispconf.h
+# XXX: now that all dealloc code is in gc, many of these are unnecessary
kstate.o: kstate.c kstate.h klisp.h kobject.h kmem.h kstring.h klisp.h \
kenvironment.h kpair.h keval.h koperative.h kground.h \
krepl.h kcontinuation.h kapplicative.h kport.h ksymbol.h kport.h \
- kstring.h kinteger.h kgc.h klimits.h ktable.h klispconf.h
+ kstring.h kinteger.h krational.h kgc.h klimits.h ktable.h klispconf.h
kmem.o: kmem.c kmem.h klisp.h kerror.h klisp.h kstate.h kgc.h klispconf.h
kerror.o: kerror.c kerror.h klisp.h kstate.h klisp.h kmem.h kstring.h kpair.h
kauxlib.o: kauxlib.c kauxlib.h klisp.h kstate.h klisp.h
@@ -97,7 +101,7 @@ kgbooleans.o: kgbooleans.c kgbooleans.c kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kpair.h kcontinuation.h ksymbol.h
kgeqp.o: kgeqp.c kgeqp.c kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kpair.h kcontinuation.h kapplicative.h \
- kinteger.h
+ kinteger.h krational.h
kgequalp.o: kgequalp.c kgequalp.c kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kpair.h kcontinuation.h kgeqp.h kstring.h
kgsymbols.o: kgsymbols.c kgsymbols.c kghelpers.h kstate.h klisp.h \
@@ -141,7 +145,7 @@ kgchars.o: kgchars.c kgchars.h kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h
kgnumbers.o: kgnumbers.c kgnumbers.h kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
- ksymbol.h kinteger.h imrat.h
+ ksymbol.h kinteger.h krational.h
kgstrings.o: kgstrings.c kgstrings.h kghelpers.h kstate.h klisp.h \
kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \
kstring.h ksymbol.h kgnumbers.h
diff --git a/src/kobject.h b/src/kobject.h
@@ -566,6 +566,7 @@ const TValue kfree;
#define gc2tv(t_, o_) ((TValue) {.tv = {.t = (t_), \
.v = { .gc = obj2gco(o_)}}})
#define gc2bigint(o_) (gc2tv(K_TAG_BIGINT, o_))
+#define gc2bigrat(o_) (gc2tv(K_TAG_BIGRAT, o_))
#define gc2pair(o_) (gc2tv(K_TAG_PAIR, o_))
#define gc2str(o_) (gc2tv(K_TAG_STRING, o_))
#define gc2sym(o_) (gc2tv(K_TAG_SYMBOL, o_))
@@ -581,6 +582,7 @@ const TValue kfree;
/* Macro to convert a TValue into a specific heap allocated object */
#define tv2bigint(v_) ((Bigint *) gcvalue(v_))
+#define tv2bigrat(v_) ((Bigrat *) gcvalue(v_))
#define tv2pair(v_) ((Pair *) gcvalue(v_))
#define tv2str(v_) ((String *) gcvalue(v_))
#define tv2sym(v_) ((Symbol *) gcvalue(v_))
diff --git a/src/krational.h b/src/krational.h
@@ -0,0 +1,161 @@
+/*
+** krational.h
+** Kernel Rationals (fixrats and bigrats)
+** See Copyright Notice in klisp.h
+*/
+
+#ifndef krational_h
+#define krational_h
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#include "kobject.h"
+#include "kstate.h"
+#include "kinteger.h"
+#include "imrat.h"
+
+/* TEMP: for now we only implement bigrats (memory allocated) */
+
+/* TODO: how to alloc?? */
+/* TEMP: we'll see about these */
+/* for now used only for reading */
+TValue kbigrat_new(klisp_State *K, bool sign, uint32_t num,
+ uint32_t den);
+
+/* used in write to destructively get the digits */
+TValue kbigrat_copy(klisp_State *K, TValue src);
+
+/* Create a stack allocated bigrat from a bigint,
+ useful for mixed operations, relatively light weight compared
+ to creating it in the heap and burdening the gc */
+#define kbind_bigrat_fixint(name, fixint) \
+ int32_t (KUNIQUE_NAME(i)) = ivalue(fixint); \
+ Bigrat KUNIQUE_NAME(bigrat_i); \
+ /* can't use unique_name bigrat because it conflicts */ \
+ /* numer is 1 */ \
+ (KUNIQUE_NAME(bigrat_i)).num.single = ({ \
+ int64_t temp = (KUNIQUE_NAME(i)); \
+ (uint32_t) ((temp < 0)? -temp : temp); \
+ }); \
+ (KUNIQUE_NAME(bigrat_i)).num.digits = \
+ &((KUNIQUE_NAME(bigrat_i)).single); \
+ (KUNIQUE_NAME(bigrat_i)).num.alloc = 1; \
+ (KUNIQUE_NAME(bigrat_i)).num.used = 1; \
+ (KUNIQUE_NAME(bigrat_i)).num.sign = (KUNIQUE_NAME(i)) < 0? \
+ MP_NEG : MP_ZPOS; \
+ /* denom is 1 */ \
+ (KUNIQUE_NAME(bigrat_i)).num.single = 1; \
+ (KUNIQUE_NAME(bigrat_i)).num.digits = \
+ &((KUNIQUE_NAME(bigrat_i)).num.single); \
+ (KUNIQUE_NAME(bigrat_i)).num.alloc = 1; \
+ (KUNIQUE_NAME(bigrat_i)).num.used = 1; \
+ (KUNIQUE_NAME(bigrat_i)).num.sign = MP_ZPOS; \
+ \
+ Bigrat *name = &(KUNIQUE_NAME(bigrat_i));
+
+#define kbind_bigrat_bigint(name, bigint) \
+ Bigrat KUNIQUE_NAME(bigrat); \
+ /* numer is bigint */ \
+ (KUNIQUE_NAME(bigrat)).num.single = bigint.single; \
+ (KUNIQUE_NAME(bigrat)).num.digits = bigint.digits; \
+ (KUNIQUE_NAME(bigrat)).num.alloc = bigint.alloc; \
+ (KUNIQUE_NAME(bigrat)).num.used = bigint.used; \
+ (KUNIQUE_NAME(bigrat)).num.sign = bigint.sign; \
+ /* denom is 1 */ \
+ (KUNIQUE_NAME(bigrat)).num.single = 1; \
+ (KUNIQUE_NAME(bigrat)).num.digits = \
+ &((KUNIQUE_NAME(bigrat)).num.single); \
+ (KUNIQUE_NAME(bigrat)).num.alloc = 1; \
+ (KUNIQUE_NAME(bigrat)).num.used = 1; \
+ (KUNIQUE_NAME(bigrat)).num.sign = MP_ZPOS; \
+ \
+ Bigrat *name = &(KUNIQUE_NAME(bigrat));
+
+/* XXX: Now that I think about it this (and kensure_bigint) could be more
+ cleanly implemented as a function that takes a pointer... (derp derp) */
+
+/* This can be used prior to calling a bigrat functions
+ to automatically convert fixints & bigints to bigrats.
+ NOTE: calls to this macro should go in different lines!
+ and on different lines to calls to kensure_bigint */
+#define kensure_bigrat(n) \
+ /* must use goto, no block should be entered before calling \
+ kbind_bigrat */ \
+ if (ttisbigrat(n)) \
+ goto KUNIQUE_NAME(bigrat_exit_lbl); \
+ if (ttisbigint(n)) \
+ goto KUNIQUE_NAME(bigrat_bigint_lbl); \
+ /* else ttisfixint(n) */ \
+ kbind_bigrat_fixint(KUNIQUE_NAME(brat_i), (n)); \
+ (n) = gc2bigrat(KUNIQUE_NAME(brat_i)); \
+ goto KUNIQUE_NAME(bigrat_exit_lbl); \
+KUNIQUE_NAME(bigrat_bigint_lbl): \
+ kbind_bigrat_bigint(KUNIQUE_NAME(brat), (n)); \
+ (n) = gc2bigrat(KUNIQUE_NAME(brat)); \
+KUNIQUE_NAME(bigrat_exit_lbl):
+
+#if 0
+/* This is used by the reader to destructively add digits to a number
+ tv_bigrat must be positive */
+void kbigrat_add_digit(klisp_State *K, TValue tv_bigrat, int32_t base,
+ int32_t digit);
+
+/* This is used by the writer to get the digits of a number
+ tv_bigrat must be positive */
+int32_t kbigrat_remove_digit(klisp_State *K, TValue tv_bigrat, int32_t base);
+
+/* This is used by write to test if there is any digit left to print */
+bool kbigrat_has_digits(klisp_State *K, TValue tv_bigrat);
+
+/* Mutate the bigrat to have the opposite sign, used in read & write */
+void kbigrat_invert_sign(klisp_State *K, TValue tv_bigrat);
+
+/* this is used by write to estimate the number of chars necessary to
+ print the number */
+int32_t kbigrat_print_size(TValue tv_bigrat, int32_t base);
+
+#endif /* #if 0 */
+
+
+/* Interface for kgnumbers */
+bool kbigrat_eqp(klisp_State *K, TValue bigrat1, TValue bigrat2);
+
+bool kbigrat_ltp(klisp_State *K, TValue bigrat1, TValue bigrat2);
+bool kbigrat_lep(klisp_State *K, TValue bigrat1, TValue bigrat2);
+bool kbigrat_gtp(klisp_State *K, TValue bigrat1, TValue bigrat2);
+bool kbigrat_gep(klisp_State *K, TValue bigrat1, TValue bigrat2);
+
+TValue kbigrat_plus(klisp_State *K, klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_times(klisp_State *K, klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_minus(klisp_State *K, klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_divide(klisp_State *K, klisp_State *K, TValue n1, TValue n2);
+
+/* TODO: Kernel allows arbitrary reals for these... will have to define */
+#if 0
+TValue kbigrat_div_mod(klisp_State *K, TValue n1, TValue n2, TValue *res_r);
+TValue kbigrat_div0_mod0(klisp_State *K, TValue n1, TValue n2, TValue *res_r);
+#endif
+
+bool kbigrat_negativep(TValue tv_bigrat);
+bool kbigrat_positivep(TValue tv_bigrat);
+
+/* needs the state to create a copy if negative */
+TValue kbigrat_abs(klisp_State *K, TValue tv_bigrat);
+
+bool kbigrat_numerator(TValue tv_bigrat);
+bool kbigrat_denominator(TValue tv_bigrat);
+
+/* TODO implement these */
+#if 0
+TValue kbigrat_floor(klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_ceiling(klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_truncate(klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_round(klisp_State *K, TValue n1, TValue n2);
+
+TValue kbigrat_simplest_rational(klisp_State *K, TValue n1, TValue n2);
+TValue kbigrat_rationalize(klisp_State *K, TValue n1, TValue n2);
+#endif
+
+#endif