diff --git a/include/cyclone/types.h b/include/cyclone/types.h index 6bf4180c..bf60683b 100644 --- a/include/cyclone/types.h +++ b/include/cyclone/types.h @@ -858,8 +858,8 @@ typedef struct { // # define C_HALF_WORD_SIZE 32 // #else // # define C_MOST_POSITIVE_FIXNUM 0x3fffffff -// # define C_WORD_SIZE 32 -// # define C_HALF_WORD_SIZE 16 +#define C_WORD_SIZE 32 +#define C_HALF_WORD_SIZE 16 // #endif // // /* Tunable performance-related constants */ @@ -884,13 +884,13 @@ typedef struct { // #endif // // /* These might fit better in runtime.c? */ -// #define C_fitsinbignumhalfdigitp(n) (C_BIGNUM_DIGIT_HI_HALF(n) == 0) +#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_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_DIGIT_HI_HALF(d) (C_uhword)((d) >> C_BIGNUM_HALF_DIGIT_LENGTH) +#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_MOST_POSITIVE_32_BIT_FIXNUM 0x3fffffff diff --git a/runtime.c b/runtime.c index 1ffb8787..8140f386 100644 --- a/runtime.c +++ b/runtime.c @@ -2449,10 +2449,10 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix) printf("radix power of two\n"); // TODO: } else { - uint32_t base, *start, *scan, *end; + uint32_t base, *start, *scan, big_digit; int steps, i; - // working copy?? + // TODO: make a working copy of the bignum so we can perform destructive operations (??) start = &(bn->sign); start += 1; @@ -2461,11 +2461,39 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix) /* 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) + for(steps = 0, base = radix; Cyc_fitsinbignumhalfdigitp(base); base *= radix) steps++; base /= radix; /* Back down: we overshot in the loop */ + + while (scan > start) { + big_digit = bignum_digits_destructive_scale_down(start, scan, base); + + 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 */ + big_digit = tmp; + } + } + assert(index >= buf-1); + 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 = '-'; + + /* 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: call into cont with string } object Cyc_symbol2string(void *data, object cont, object sym)