From f8c6d43c4ee4965de332e0ae77a6f2a5369b7ceb Mon Sep 17 00:00:00 2001 From: Justin Ethier Date: Mon, 6 Jun 2022 22:44:46 -0400 Subject: [PATCH] WIP - bignum2 -> string --- include/cyclone/types.h | 10 +++--- runtime.c | 74 +++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 26 deletions(-) diff --git a/include/cyclone/types.h b/include/cyclone/types.h index bf60683b..f2c7a814 100644 --- a/include/cyclone/types.h +++ b/include/cyclone/types.h @@ -851,6 +851,8 @@ typedef struct { // TODO: digits (implicit, after object??) } bignum2_type; +#define C_bignum_digits(n) ((((bignum2_type *)n)->sign) + 1) + // TODO: covert applicable definitions below - // #ifdef C_SIXTY_FOUR // # define C_MOST_POSITIVE_FIXNUM 0x3fffffffffffffffL @@ -887,11 +889,11 @@ typedef struct { #define Cyc_fitsinbignumhalfdigitp(n) (C_BIGNUM_DIGIT_HI_HALF(n) == 0) // #define C_BIGNUM_DIGIT_LENGTH C_WORD_SIZE #define C_BIGNUM_HALF_DIGIT_LENGTH C_HALF_WORD_SIZE -// #define C_BIGNUM_BITS_TO_DIGITS(n) \ -// (((n) + (C_BIGNUM_DIGIT_LENGTH - 1)) / C_BIGNUM_DIGIT_LENGTH) -// #define C_BIGNUM_DIGIT_LO_HALF(d) (C_uhword)(d) +#define C_BIGNUM_BITS_TO_DIGITS(n) \ + (((n) + (C_BIGNUM_DIGIT_LENGTH - 1)) / C_BIGNUM_DIGIT_LENGTH) +#define C_BIGNUM_DIGIT_LO_HALF(d) (uint16_t)(d) #define C_BIGNUM_DIGIT_HI_HALF(d) (uint16_t)((d) >> C_BIGNUM_HALF_DIGIT_LENGTH) -// #define C_BIGNUM_DIGIT_COMBINE(h,l) ((C_uword)(h) << C_BIGNUM_HALF_DIGIT_LENGTH|(C_uhword)(l)) +#define C_BIGNUM_DIGIT_COMBINE(h,l) ((uint16_t)(h) << C_BIGNUM_HALF_DIGIT_LENGTH|(uint16_t)(l)) // // #define C_MOST_POSITIVE_32_BIT_FIXNUM 0x3fffffff // #define C_MOST_NEGATIVE_FIXNUM (-C_MOST_POSITIVE_FIXNUM - 1) diff --git a/runtime.c b/runtime.c index 8140f386..4b61360e 100644 --- a/runtime.c +++ b/runtime.c @@ -1772,7 +1772,7 @@ void Cyc_int2bignum(int n, mp_int *bn) object Cyc_bignum2(bignum2_type *bn, int sign, int n) { - uint32_t *p = &(bn->sign); + uint32_t *p = &(bn->num_digits); *(p++) = 1; *(p++) = sign; *(p++) = n; @@ -2416,7 +2416,7 @@ inline static int nlz(uint32_t x) return n + x; } -int bignum2_num_digits(bignum2_type bn, int radix) +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 @@ -2424,10 +2424,10 @@ int bignum2_num_digits(bignum2_type bn, int radix) * 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; + int 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: ? + int nbits = (size_t)len * 32; //C_BIGNUM_DIGIT_LENGTH; + nbits += nlz(C_bignum_digits(bn)+len); // TODO: ? len = nlz(radix)-1; len = (nbits + len - 1) / len; @@ -2435,6 +2435,30 @@ int bignum2_num_digits(bignum2_type bn, int radix) return len; } +static uint32_t bignum_digits_destructive_scale_down(uint32_t *start, uint32_t *end, uint32_t denominator) +{ + uint32_t digit, k = 0; + uint16_t q_j_hi, q_j_lo; + + /* Single digit divisor case from Hacker's Delight, Figure 9-1, + * adapted to modify u[] in-place instead of writing to q[]. + */ + while (start < end) { + digit = (*--end); + + k = C_BIGNUM_DIGIT_COMBINE(k, C_BIGNUM_DIGIT_HI_HALF(digit)); /* j */ + q_j_hi = k / denominator; + k -= q_j_hi * denominator; + + k = C_BIGNUM_DIGIT_COMBINE(k, C_BIGNUM_DIGIT_LO_HALF(digit)); /* j-1 */ + q_j_lo = k / denominator; + k -= q_j_lo * denominator; + + *end = C_BIGNUM_DIGIT_COMBINE(q_j_hi, q_j_lo); + } + return k; +} + //TODO: static void bignum2string(void *data, object cont, bignum2_type *bn, int radix) { @@ -2443,7 +2467,7 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix) 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)); + 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"); @@ -2452,10 +2476,12 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix) uint32_t base, *start, *scan, big_digit; int steps, i; - // TODO: make a working copy of the bignum so we can perform destructive operations (??) + // TODO: make a working copy of the bignum so we can perform destructive operation below - start = &(bn->sign); - start += 1; + // TODO: C_bignum_digits + // TODO: start = C_bignum_digits(working_copy); + start = &(bn->sign); // DEBUG ONLY + start += 1; // DEBUG ONLY scan = start + bn->num_digits; /* Calculate the largest power of radix that fits a halfdigit: @@ -2471,27 +2497,31 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix) if (*(scan-1) == 0) scan--; /* Adjust if we exhausted the highest digit */ - for(i = 0; i < steps && index >= buf; ++i) { - C_word tmp = big_digit / radix; - *index-- = characters[big_digit - (tmp*radix)]; /* big_digit % radix */ + //TODO: for(i = 0; i < steps && index >= buf; ++i) { + for(i = 0; i < steps ; ++i) { + uint32_t tmp = big_digit / radix; + printf("%c", characters[big_digit - (tmp*radix)]); + //TODO: *index-- = characters[big_digit - (tmp*radix)]; /* big_digit % radix */ big_digit = tmp; } } - assert(index >= buf-1); - free_tmp_bignum(working_copy); + // TODO: assert(index >= buf-1); + // TODO: free_tmp_bignum(working_copy); /* Move index onto first nonzero digit. We're writing a bignum here: it can't consist of only zeroes. */ - while(*++index == '0'); - - if (negp) *--index = '-'; +// TODO: +// while(*++index == '0'); +// +// if (negp) *--index = '-'; /* Shorten with distance between start and index. */ - if (buf != index) { - i = C_header_size(string) - (index - buf); - C_memmove(buf, index, i); /* Move start of number to beginning. */ - C_block_header(string) = C_STRING_TYPE | i; /* Mutate strlength. */ - } +// TODO: +// if (buf != index) { +// i = C_header_size(string) - (index - buf); +// C_memmove(buf, index, i); /* Move start of number to beginning. */ +// C_block_header(string) = C_STRING_TYPE | i; /* Mutate strlength. */ +// } } // TODO: call into cont with string }