big: fix itoa base PoT other than 16.

This commit is contained in:
Jeroen van Rijn
2021-08-11 20:59:51 +02:00
parent 2fbff25a18
commit 74258a170a
3 changed files with 52 additions and 33 deletions
+49 -29
View File
@@ -177,7 +177,7 @@ neg :: proc(dest, src: ^Int, allocator := context.allocator) -> (err: Error) {
/*
Helpers to extract values from the `Int`.
*/
int_extract_bit :: proc(a: ^Int, bit_offset: int) -> (bit: DIGIT, err: Error) {
extract_bit :: proc(a: ^Int, bit_offset: int) -> (bit: DIGIT, err: Error) {
/*
Check that `a`is usable.
*/
@@ -195,6 +195,9 @@ int_extract_bit :: proc(a: ^Int, bit_offset: int) -> (bit: DIGIT, err: Error) {
return 1 if ((a.digit[limb] & i) != 0) else 0, .None;
}
/*
TODO: Optimize.
*/
int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: Error) {
/*
Check that `a`is usable.
@@ -207,40 +210,57 @@ int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: E
return 0, .Invalid_Argument;
}
limb_lo := offset / _DIGIT_BITS;
bits_lo := offset % _DIGIT_BITS;
limb_hi := (offset + count) / _DIGIT_BITS;
bits_hi := (offset + count) % _DIGIT_BITS;
when true {
v: DIGIT;
e: Error;
if limb_lo < 0 || limb_lo >= a.used || limb_hi < 0 || limb_hi >= a.used {
return 0, .Invalid_Argument;
}
for i := limb_hi; i >= limb_lo; i -= 1 {
res <<= _DIGIT_BITS;
/*
Determine which bits to extract from each DIGIT. The whole DIGIT's worth by default.
*/
bit_count := _DIGIT_BITS;
bit_offset := 0;
if i == limb_lo {
bit_count -= bits_lo;
bit_offset = _DIGIT_BITS - bit_count;
} else if i == limb_hi {
bit_count = bits_hi;
bit_offset = 0;
for shift := 0; shift < count; shift += 1 {
o := offset + shift;
v, e = extract_bit(a, o);
if e != .None {
break;
}
res = res + _WORD(v) << uint(shift);
}
d := a.digit[i];
return res, e;
} else {
limb_lo := offset / _DIGIT_BITS;
bits_lo := offset % _DIGIT_BITS;
limb_hi := (offset + count) / _DIGIT_BITS;
bits_hi := (offset + count) % _DIGIT_BITS;
v := (d >> uint(bit_offset)) & DIGIT(1 << uint(bit_count - 1));
m := DIGIT(1 << uint(bit_count-1));
r := v & m;
if limb_lo < 0 || limb_lo >= a.used || limb_hi < 0 || limb_hi >= a.used {
return 0, .Invalid_Argument;
}
for i := limb_hi; i >= limb_lo; i -= 1 {
res <<= _DIGIT_BITS;
/*
Determine which bits to extract from each DIGIT. The whole DIGIT's worth by default.
*/
bit_count := _DIGIT_BITS;
bit_offset := 0;
if i == limb_lo {
bit_count -= bits_lo;
bit_offset = _DIGIT_BITS - bit_count;
} else if i == limb_hi {
bit_count = bits_hi;
bit_offset = 0;
}
d := a.digit[i];
v := (d >> uint(bit_offset)) & DIGIT(1 << uint(bit_count - 1));
m := DIGIT(1 << uint(bit_count-1));
r := v & m;
res |= _WORD(r);
}
return res, .None;
res |= _WORD(r);
}
return res, .None;
}
/*