Working conversion of bignum2 -> string

This commit is contained in:
Justin Ethier 2022-06-08 11:56:29 -04:00
parent 4e013b726a
commit eb78f50c66
3 changed files with 59 additions and 66 deletions

View file

@ -887,7 +887,7 @@ typedef struct {
// //
// /* These might fit better in runtime.c? */ // /* These might fit better in runtime.c? */
#define Cyc_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_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) \ #define C_BIGNUM_BITS_TO_DIGITS(n) \
(((n) + (C_BIGNUM_DIGIT_LENGTH - 1)) / C_BIGNUM_DIGIT_LENGTH) (((n) + (C_BIGNUM_DIGIT_LENGTH - 1)) / C_BIGNUM_DIGIT_LENGTH)

119
runtime.c
View file

@ -2461,16 +2461,17 @@ static uint32_t bignum_digits_destructive_scale_down(uint32_t *start, uint32_t *
return k; return k;
} }
// TODO:
/* Copy all the digits from source to target, obliterating what was /* Copy all the digits from source to target, obliterating what was
* there. If target is larger than source, the most significant * there. If target is larger than source, the most significant
* digits will remain untouched. * digits will remain untouched.
*/ */
//inline static void bignum_digits_destructive_copy(C_word target, C_word source) inline static void bignum_digits_destructive_copy(bignum2_type *target, bignum2_type *source)
//{ {
// C_memcpy(C_bignum_digits(target), C_bignum_digits(source), memcpy(C_bignum_digits(target),
// C_wordstobytes(C_bignum_size(source))); C_bignum_digits(source),
//} source->num_digits * sizeof(uint32_t));
//C_wordstobytes(C_bignum_size(source)));
}
//TODO: static //TODO: static
void bignum2string(void *data, object cont, bignum2_type *bn, int radix) void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
@ -2480,9 +2481,6 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
int str_length = bignum2_num_digits(bn, radix); int str_length = bignum2_num_digits(bn, radix);
int heap_grown; int heap_grown;
//printf("DEBUG string length %d\n", bignum2_num_digits(bn, radix));
//printf("DEBUG radix=%d, nlz = %d\n", radix, radix_shift);
string_type *s = gc_alloc(((gc_thread_data *)data)->heap, string_type *s = gc_alloc(((gc_thread_data *)data)->heap,
sizeof(string_type) + str_length + 1, sizeof(string_type) + str_length + 1,
boolean_f, // OK to populate manually over here boolean_f, // OK to populate manually over here
@ -2499,66 +2497,57 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
*index = buf + str_length - 1; *index = buf + str_length - 1;
if (((uint32_t)1 << radix_shift) == radix) { /* Power of two? */ if (((uint32_t)1 << radix_shift) == radix) { /* Power of two? */
uint32_t *scan, *end; uint32_t *scan, *end, big_digit = 0;
printf("TODO: radix is a power of two\n"); int radix_mask = radix - 1, big_digit_len = 0, radix_digit;
// TODO:
// int radix_mask = radix - 1, big_digit_len = 0, radix_digit; scan = C_bignum_digits(bn);
// C_uword *scan, *end, big_digit = 0; end = scan + bn->num_digits;
//
// scan = C_bignum_digits(bignum); while (scan < end) {
// end = scan + C_bignum_size(bignum); /* If radix isn't an exact divisor of digit length, handle overlap */
// if (big_digit_len == 0) {
// while (scan < end) { big_digit = *scan++;
// /* If radix isn't an exact divisor of digit length, handle overlap */ big_digit_len = C_BIGNUM_DIGIT_LENGTH;
// if (big_digit_len == 0) { } else {
// big_digit = *scan++; assert(index >= buf);
// big_digit_len = C_BIGNUM_DIGIT_LENGTH; radix_digit = big_digit;
// } else { big_digit = *scan++;
// assert(index >= buf); radix_digit |= ((unsigned int)big_digit << big_digit_len) & radix_mask;
// radix_digit = big_digit; *index-- = characters[radix_digit];
// big_digit = *scan++; big_digit >>= (radix_shift - big_digit_len);
// radix_digit |= ((unsigned int)big_digit << big_digit_len) & radix_mask; big_digit_len = C_BIGNUM_DIGIT_LENGTH - (radix_shift - big_digit_len);
// *index-- = characters[radix_digit]; }
// big_digit >>= (radix_shift - big_digit_len);
// big_digit_len = C_BIGNUM_DIGIT_LENGTH - (radix_shift - big_digit_len); while(big_digit_len >= radix_shift && index >= buf) {
// } radix_digit = big_digit & radix_mask;
// *index-- = characters[radix_digit];
// while(big_digit_len >= radix_shift && index >= buf) { big_digit >>= radix_shift;
// radix_digit = big_digit & radix_mask; big_digit_len -= radix_shift;
// *index-- = characters[radix_digit]; }
// big_digit >>= radix_shift; }
// big_digit_len -= radix_shift;
// } assert(big_digit < radix);
// }
// /* Final digit (like overlap at start of while loop) */
// assert(big_digit < radix); if (big_digit) *index-- = characters[big_digit];
//
// /* Final digit (like overlap at start of while loop) */ if (negp) {
// if (big_digit) *index-- = characters[big_digit]; /* Loop above might've overwritten sign position with a zero */
// if (*(index+1) == '0') *(index+1) = '-';
// if (negp) { else *index-- = '-';
// /* Loop above might've overwritten sign position with a zero */ }
// if (*(index+1) == '0') *(index+1) = '-';
// else *index-- = '-'; /* Length calculation is always precise for radix powers of two. */
// } assert(index == buf-1);
//
// /* Length calculation is always precise for radix powers of two. */
// assert(index == buf-1);
} else { } else {
uint32_t base, *start, *scan, big_digit; uint32_t base, *start, *scan, big_digit;
int steps, i; int steps, i;
// TODO: make a working copy of the bignum so we can perform destructive operation below bignum2_type *working_copy = gc_alloc_bignum2(data, bn->num_digits);
// working_copy = allocate_tmp_bignum(C_fix(C_bignum_size(bignum)), working_copy->sign = bn->sign;
// C_mk_bool(negp), C_SCHEME_FALSE); bignum_digits_destructive_copy(working_copy, bn);
// bignum_digits_destructive_copy(working_copy, bignum);
//
//TODO: replace below two lines with this: start = C_bignum_digits(working_copy);
start = &(bn->sign); // DEBUG ONLY
start += 1; // DEBUG ONLY
start = C_bignum_digits(working_copy);
scan = start + bn->num_digits; scan = start + bn->num_digits;
/* Calculate the largest power of radix that fits a halfdigit: /* Calculate the largest power of radix that fits a halfdigit:
@ -2582,7 +2571,7 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
} }
} }
assert(index >= buf-1); assert(index >= buf-1);
// TODO: free_tmp_bignum(working_copy); // FUTURE (?): free_tmp_bignum(working_copy);
/* Move index onto first nonzero digit. We're writing a bignum /* Move index onto first nonzero digit. We're writing a bignum
here: it can't consist of only zeroes. */ here: it can't consist of only zeroes. */

View file

@ -31,6 +31,10 @@
(test-bn -16326000 10) (test-bn -16326000 10)
(test-bn #x0FFFffff 10) (test-bn #x0FFFffff 10)
(test-bn #x0FFFffff 16) (test-bn #x0FFFffff 16)
(test-bn #x0eadbeef 16)
(test-bn #x0eadbeef 12)
(test-bn #x0eadbeef 8)
(test-bn #x0eadbeef 2)
(test-bn #x3FFFffff 10) (test-bn #x3FFFffff 10)
(test-larger-bn #x3FFF0000 #x0FFF0001 10) (test-larger-bn #x3FFF0000 #x0FFF0001 10)
)) ))