kinteger.h (5274B)
1 /* 2 ** kinteger.h 3 ** Kernel Integers (fixints and bigints) 4 ** See Copyright Notice in klisp.h 5 */ 6 7 #ifndef kinteger_h 8 #define kinteger_h 9 10 #include <stdbool.h> 11 #include <stdint.h> 12 #include <inttypes.h> 13 14 #include "kobject.h" 15 #include "kstate.h" 16 #include "imath.h" 17 18 /* Check to see if an int64_t fits in a int32_t */ 19 static inline bool kfit_int32_t(int64_t n) { 20 return (n >= (int64_t) INT32_MIN && n <= (int64_t) INT32_MAX); 21 } 22 23 /* This tries to convert a bigint to a fixint */ 24 /* XXX this doesn't need K really */ 25 static inline TValue kbigint_try_fixint(klisp_State *K, TValue n) 26 { 27 UNUSED(K); 28 Bigint *b = tv2bigint(n); 29 if (MP_USED(b) != 1) 30 return n; 31 32 int64_t digit = (int64_t) *(MP_DIGITS(b)); 33 if (MP_SIGN(b) == MP_NEG) digit = -digit; 34 if (kfit_int32_t(digit)) { 35 /* n shouln't be reachable but the let the gc do its job */ 36 return i2tv((int32_t) digit); 37 } else { 38 return n; 39 } 40 } 41 42 /* NOTE: is uint and has flag to allow INT32_MIN as positive argument */ 43 TValue kbigint_new(klisp_State *K, bool sign, uint32_t digit); 44 45 TValue kbigint_copy(klisp_State *K, TValue src); 46 47 /* macro to create the simplest bigint */ 48 #define kbigint_make_simple(K_) kbigint_new(K_, false, 0) 49 50 /* Create a stack allocated bigints from a fixint, 51 useful for mixed operations, relatively light weight compared 52 to creating it in the heap and burdening the gc */ 53 #define kbind_bigint(name, fixint) \ 54 int32_t (KUNIQUE_NAME(i)) = ivalue(fixint); \ 55 Bigint KUNIQUE_NAME(bigint); \ 56 (KUNIQUE_NAME(bigint)).single = ({ \ 57 int64_t temp = (KUNIQUE_NAME(i)); \ 58 (uint32_t) ((temp < 0)? -temp : temp); \ 59 }); \ 60 (KUNIQUE_NAME(bigint)).digits = &((KUNIQUE_NAME(bigint)).single); \ 61 (KUNIQUE_NAME(bigint)).alloc = 1; \ 62 (KUNIQUE_NAME(bigint)).used = 1; \ 63 (KUNIQUE_NAME(bigint)).sign = (KUNIQUE_NAME(i)) < 0? \ 64 MP_NEG : MP_ZPOS; \ 65 Bigint *name = &(KUNIQUE_NAME(bigint)) 66 67 /* This can be used prior to calling a bigint functions 68 to automatically convert fixints to bigints. 69 NOTE: calls to this macro should go in different lines! */ 70 #define kensure_bigint(n) \ 71 /* must use goto, no block should be entered before calling \ 72 kbind_bigint */ \ 73 if (!ttisfixint(n)) \ 74 goto KUNIQUE_NAME(exit_lbl); \ 75 kbind_bigint(KUNIQUE_NAME(bint), (n)); \ 76 (n) = gc2bigint(KUNIQUE_NAME(bint)); \ 77 KUNIQUE_NAME(exit_lbl): 78 79 /* This is used by the reader to destructively add digits to a number 80 tv_bigint must be positive */ 81 void kbigint_add_digit(klisp_State *K, TValue tv_bigint, int32_t base, 82 int32_t digit); 83 84 /* This is used by the writer to get the digits of a number 85 tv_bigint must be positive */ 86 int32_t kbigint_remove_digit(klisp_State *K, TValue tv_bigint, int32_t base); 87 88 /* This is used by write to test if there is any digit left to print */ 89 bool kbigint_has_digits(klisp_State *K, TValue tv_bigint); 90 91 /* Mutate the bigint to have the opposite sign, used in read & write */ 92 void kbigint_invert_sign(klisp_State *K, TValue tv_bigint); 93 94 /* read/write interface */ 95 96 /* this works for bigints & fixints, returns true if ok */ 97 /* only positive numbers? */ 98 bool kinteger_read(klisp_State *K, char *buf, int32_t base, TValue *out, 99 char **end); 100 101 /* this is used by write to estimate the number of chars necessary to 102 print the number */ 103 int32_t kbigint_print_size(TValue tv_bigint, int32_t base); 104 105 /* this is used by write */ 106 void kbigint_print_string(klisp_State *K, TValue tv_bigint, int32_t base, 107 char *buf, int32_t limit); 108 109 /* Interface for kgnumbers */ 110 bool kbigint_eqp(TValue bigint1, TValue bigint2); 111 112 bool kbigint_ltp(TValue bigint1, TValue bigint2); 113 bool kbigint_lep(TValue bigint1, TValue bigint2); 114 bool kbigint_gtp(TValue bigint1, TValue bigint2); 115 bool kbigint_gep(TValue bigint1, TValue bigint2); 116 117 TValue kbigint_plus(klisp_State *K, TValue n1, TValue n2); 118 TValue kbigint_times(klisp_State *K, TValue n1, TValue n2); 119 TValue kbigint_minus(klisp_State *K, TValue n1, TValue n2); 120 121 TValue kbigint_div_mod(klisp_State *K, TValue n1, TValue n2, TValue *res_r); 122 TValue kbigint_div0_mod0(klisp_State *K, TValue n1, TValue n2, TValue *res_r); 123 124 bool kbigint_negativep(TValue tv_bigint); 125 bool kbigint_positivep(TValue tv_bigint); 126 127 bool kbigint_oddp(TValue tv_bigint); 128 bool kbigint_evenp(TValue tv_bigint); 129 130 /* needs the state to create a copy if negative */ 131 TValue kbigint_abs(klisp_State *K, TValue tv_bigint); 132 133 TValue kbigint_gcd(klisp_State *K, TValue n1, TValue n2); 134 TValue kbigint_lcm(klisp_State *K, TValue n1, TValue n2); 135 136 /* conversion from uint64_t */ 137 TValue kinteger_new_uint64(klisp_State *K, uint64_t x); 138 139 #endif