WIP - bignum2 -> string

This commit is contained in:
Justin Ethier 2022-06-06 22:44:46 -04:00
parent 141e9ed7b5
commit f8c6d43c4e
2 changed files with 58 additions and 26 deletions

View file

@ -851,6 +851,8 @@ typedef struct {
// TODO: digits (implicit, after object??) // TODO: digits (implicit, after object??)
} bignum2_type; } bignum2_type;
#define C_bignum_digits(n) ((((bignum2_type *)n)->sign) + 1)
// TODO: covert applicable definitions below - // TODO: covert applicable definitions below -
// #ifdef C_SIXTY_FOUR // #ifdef C_SIXTY_FOUR
// # define C_MOST_POSITIVE_FIXNUM 0x3fffffffffffffffL // # define C_MOST_POSITIVE_FIXNUM 0x3fffffffffffffffL
@ -887,11 +889,11 @@ typedef struct {
#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)
// #define C_BIGNUM_DIGIT_LO_HALF(d) (C_uhword)(d) #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_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_POSITIVE_32_BIT_FIXNUM 0x3fffffff
// #define C_MOST_NEGATIVE_FIXNUM (-C_MOST_POSITIVE_FIXNUM - 1) // #define C_MOST_NEGATIVE_FIXNUM (-C_MOST_POSITIVE_FIXNUM - 1)

View file

@ -1772,7 +1772,7 @@ void Cyc_int2bignum(int n, mp_int *bn)
object Cyc_bignum2(bignum2_type *bn, int sign, int n) object Cyc_bignum2(bignum2_type *bn, int sign, int n)
{ {
uint32_t *p = &(bn->sign); uint32_t *p = &(bn->num_digits);
*(p++) = 1; *(p++) = 1;
*(p++) = sign; *(p++) = sign;
*(p++) = n; *(p++) = n;
@ -2416,7 +2416,7 @@ inline static int nlz(uint32_t x)
return n + 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 /* 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 * 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 * we may need to do because we write strings back-to-front, and
* pointers must be aligned (even for byte blocks). * 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; int nbits = (size_t)len * 32; //C_BIGNUM_DIGIT_LENGTH;
nbits += nlz(C_bignum_digits(num)[len]); // TODO: ? nbits += nlz(C_bignum_digits(bn)+len); // TODO: ?
len = nlz(radix)-1; len = nlz(radix)-1;
len = (nbits + len - 1) / len; len = (nbits + len - 1) / len;
@ -2435,6 +2435,30 @@ int bignum2_num_digits(bignum2_type bn, int radix)
return len; 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 //TODO: static
void bignum2string(void *data, object cont, bignum2_type *bn, int radix) void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
{ {
@ -2452,10 +2476,12 @@ void bignum2string(void *data, object cont, bignum2_type *bn, int radix)
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 operations (??) // TODO: make a working copy of the bignum so we can perform destructive operation below
start = &(bn->sign); // TODO: C_bignum_digits
start += 1; // TODO: start = C_bignum_digits(working_copy);
start = &(bn->sign); // DEBUG ONLY
start += 1; // DEBUG ONLY
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:
@ -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 */ if (*(scan-1) == 0) scan--; /* Adjust if we exhausted the highest digit */
for(i = 0; i < steps && index >= buf; ++i) { //TODO: for(i = 0; i < steps && index >= buf; ++i) {
C_word tmp = big_digit / radix; for(i = 0; i < steps ; ++i) {
*index-- = characters[big_digit - (tmp*radix)]; /* big_digit % radix */ 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; big_digit = tmp;
} }
} }
assert(index >= buf-1); // TODO: assert(index >= buf-1);
free_tmp_bignum(working_copy); // TODO: 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. */
while(*++index == '0'); // TODO:
// while(*++index == '0');
if (negp) *--index = '-'; //
// if (negp) *--index = '-';
/* Shorten with distance between start and index. */ /* Shorten with distance between start and index. */
if (buf != index) { // TODO:
i = C_header_size(string) - (index - buf); // if (buf != index) {
C_memmove(buf, index, i); /* Move start of number to beginning. */ // i = C_header_size(string) - (index - buf);
C_block_header(string) = C_STRING_TYPE | i; /* Mutate strlength. */ // 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 // TODO: call into cont with string
} }