From bbc345cc9b67b724915533b03022802a03dadd93 Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Thu, 2 Jun 2022 20:05:08 -0700 Subject: [PATCH] WIP --- include/cyclone/types.h | 2 ++ runtime.c | 73 +++++++++++++++++++++++++++++++++++++++++ test-bn.scm | 8 +++-- 3 files changed, 81 insertions(+), 2 deletions(-) diff --git a/include/cyclone/types.h b/include/cyclone/types.h index bc76b46a..017622ac 100644 --- a/include/cyclone/types.h +++ b/include/cyclone/types.h @@ -1556,6 +1556,8 @@ void vpbuffer_free(void **buf); int Cyc_bignum_cmp(bn_cmp_type type, object x, int tx, object y, int ty); void Cyc_int2bignum(int n, mp_int *bn); object Cyc_int2bignum2(gc_thread_data *data, int n); +// TODO: debug only, remove this function from here! +void bignum2string(void *data, object cont, bignum2_type *bn, int base); /* Remaining GC prototypes that require objects to be defined */ void *gc_alloc_from_bignum(gc_thread_data *data, bignum_type *src); diff --git a/runtime.c b/runtime.c index f9270894..1ffb8787 100644 --- a/runtime.c +++ b/runtime.c @@ -2395,6 +2395,79 @@ object Cyc_number2string2(void *data, object cont, int argc, object n, ...) _return_closcall1(data, cont, &str); } +/* + * Number of leading zero's + * From Hacker's Delight by Henry S. Warren + * based on a modified nlz() from section 5-3 (fig. 5-7) + */ +inline static int nlz(uint32_t x) +{ + uint32_t y; + int n = 0; + +//#ifdef C_SIXTY_FOUR +// y = x >> 32; if (y != 0) { n += 32; x = y; } +//#endif + y = x >> 16; if (y != 0) { n += 16; x = y; } + y = x >> 8; if (y != 0) { n += 8; x = y; } + y = x >> 4; if (y != 0) { n += 4; x = y; } + y = x >> 2; if (y != 0) { n += 2; x = y; } + y = x >> 1; if (y != 0) return n + 2; + return n + x; +} + +int bignum2_num_digits(bignum2_type bn, int radix) +{ + /* Approximation of the number of radix digits we'll need. We try + * to be as precise as possible to avoid memmove overhead at the end + * of the non-powers of two part of the conversion procedure, which + * we may need to do because we write strings back-to-front, and + * pointers must be aligned (even for byte blocks). + */ + len = bn->num_digits - 1; //C_bignum_size(num)-1; + + nbits = (size_t)len * 32; //C_BIGNUM_DIGIT_LENGTH; + nbits += nlz(C_bignum_digits(num)[len]); // TODO: ? + + len = nlz(radix)-1; + len = (nbits + len - 1) / len; + len += bn->sign; // Space for sign + return len; +} + +//TODO: static +void bignum2string(void *data, object cont, bignum2_type *bn, int radix) +{ + static char *characters = "0123456789abcdef"; + // buf + int negp = bn->sign, radix_shift = nlz(radix) - 1; + printf("DEBUG string length %d\n", bignum2_num_digits(bn, radix)); + printf("DEBUG radix=%d, nlz = %d\n", radix, radix_shift); + printf("DEBUG power of 2 %d\n", ((uint32_t)1 << radix_shift)); + if (((uint32_t)1 << radix_shift) == radix) { /* Power of two? */ + uint32_t *scan, *end; + printf("radix power of two\n"); + // TODO: + } else { + uint32_t base, *start, *scan, *end; + int steps, i; + + // working copy?? + + start = &(bn->sign); + start += 1; + scan = start + bn->num_digits; + + /* Calculate the largest power of radix that fits a halfdigit: + * steps = log10(2^halfdigit_bits), base = 10^steps + */ + for(steps = 0, base = radix; C_fitsinbignumhalfdigitp(base); base *= radix) + steps++; + + base /= radix; /* Back down: we overshot in the loop */ + } +} + object Cyc_symbol2string(void *data, object cont, object sym) { Cyc_check_sym(data, sym); diff --git a/test-bn.scm b/test-bn.scm index 1638c91f..96387bbc 100644 --- a/test-bn.scm +++ b/test-bn.scm @@ -1,8 +1,12 @@ +; /sync.sh runtime.c gc.c include/cyclone/*.h test-bn.scm && cd ../cyclone-bootstrap && rm -f cyclone libcyclone.a ; make cyclone && ./cyclone -L. -I. test-bn.scm && ./test-bn && cd ../cyclone (import (scheme base) (scheme write) (scheme repl)) - (define-c bn-test + (define-c test-bn "(void *data, int argc, closure _, object k, object fx)" " object bn = Cyc_int2bignum2(data, obj_obj2int(fx)); + bignum2string(data, k, bn, 10); return_closcall1(data, k, bn); ") - (repl) +(test-bn 10) +(test-bn 16) + ;(repl)