klisp

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

commit c3e06d98bde932ba603d499c63fb1b593ac91320
parent 0b42ae61dc42512bddaadd57bd67d4539090aabc
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Sat,  9 Apr 2011 14:52:33 -0300

Added object definitions for bigints.

Diffstat:
Msrc/kobject.h | 50++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)

diff --git a/src/kobject.h b/src/kobject.h @@ -141,9 +141,10 @@ typedef struct __attribute__ ((__packed__)) GCheader { ** ** - decide if inexact infinities and reals with no ** primary values are included in K_TDOUBLE -** - For now we will only use fixints and exact infinities +** - For now we will only use fixints, bigints and exact infinities */ #define K_TAG_FIXINT K_MAKE_VTAG(K_TFIXINT) +#define K_TAG_BIGINT K_MAKE_VTAG(K_TBIGINT) #define K_TAG_EINF K_MAKE_VTAG(K_TEINF) #define K_TAG_IINF K_MAKE_VTAG(K_TIINF) @@ -181,11 +182,15 @@ typedef struct __attribute__ ((__packed__)) GCheader { /* This is intended for internal use below. DON'T USE OUTSIDE THIS FILE */ #define ttag(o) ((o).tv.t) #define ttype_(o) (K_TAG_TYPE(ttag(o))) +/* NOTE: not used for now */ #define tflag_(o) (K_TAG_FLAG(ttag(o))) #define tbasetype_(o) (K_TAG_BASE_TYPE(ttag(o))) /* Simple types (value in TValue struct) */ #define ttisfixint(o) (tbasetype_(o) == K_TAG_FIXINT) +#define ttisbigint(o) (tbasetype_(o) == K_TAG_FIXINT) +#define ttisinteger(o_) ({ int32_t t_ = tbasetype_(o_); \ + t_ == K_TAG_FIXINT || t_ == K_TAG_BIGINT;}) #define ttiseinf(o) (tbasetype_(o) == K_TAG_EINF) #define ttisiinf(o) (tbasetype_(o) == K_TAG_IINF) #define ttisnil(o) (tbasetype_(o) == K_TAG_NIL) @@ -194,7 +199,7 @@ typedef struct __attribute__ ((__packed__)) GCheader { #define ttiseof(o) (tbasetype_(o) == K_TAG_EOF) #define ttisboolean(o) (tbasetype_(o) == K_TAG_BOOLEAN) #define ttischar(o) (tbasetype_(o) == K_TAG_CHAR) -#define ttisdouble(o) ((ttag(o) & K_TAG_BASE_MASK) != K_TAG_TAGGED) +#define ttisdouble(o) ((ttag(o) & K_TAG_BASE_MASK) != K_TAG_TAGGED) /* Complex types (value in heap) */ #define ttisstring(o) (tbasetype_(o) == K_TAG_STRING) @@ -248,6 +253,41 @@ typedef __attribute__((aligned (8))) union { /* ** Individual heap-allocated values */ + +/* +** Node Structure for the list of 'digits' in bignums. +** The node list is a xor encoded doubly linked list of big endian 'digits' +** in base 2^32. +** It is a linked list instead of say, an array because it is immutable and +** there is no need to index the list. +** It is doubly linked because some operations (like + and *) work from least +** significant to most significant and some others (like <? and >?) work the +** other way around. +** It is xor encoded because, well... I never had a chance to actually use +** this and this is a perfect example of where it is actually useful: Lists +** are to be traversed in both directions, the node is small so the space +** gain is real (2/3 the space in 32 bits, 3/5 in 64 bits) and all the code +** using the pointers is encapsulated in a (relatively) small module. +*/ + +typedef struct __attribute__ ((__packed__)) { + uint32_t digit; + uintptr_t next_xor_prev; +} BigintNode; + +/* some useful macros to traverse the list */ +#define kxor_next(cur, prev) \ + ((BigintNode *) ((cur)->next_xor_prev ^ (uintptr_t) (prev))) + +#define kxor_prev(cur, next) \ + ((BigintNode *) ((cur)->next_xor_prev ^ (uintptr_t) (next))) + +typedef struct __attribute__ ((__packed__)) { + CommonHeader; /* here there is a flag for the sign */ + BigintNode *first; + BigintNode *last; +} Bigint; + typedef struct __attribute__ ((__packed__)) { CommonHeader; TValue mark; /* for cycle/sharing aware algorithms */ @@ -500,6 +540,12 @@ int32_t kmark_count; #define gch_get_flags(o_) (obj2gch(o_)->flags) #define tv_get_flags(o_) (gch_get_flags(tv2gch(o_))) +/* Flags for bigints */ +/* is negative */ +#define K_FLAG_NEG 0x01 +#define kbigint_is_pos(s_) ((tv_get_flags(s_) & K_FLAG_NEG) == 0) +#define kbigint_is_neg(s_) ((tv_get_flags(s_) & K_FLAG_NEG) != 0) + /* Flags for symbols */ /* has external representation (identifiers) */ #define K_FLAG_EXT_REP 0x01