big: Finish big ZII refactor.

This commit is contained in:
Jeroen van Rijn
2021-08-11 20:59:50 +02:00
parent d9efa6c8b5
commit 7648f2e655
8 changed files with 404 additions and 323 deletions
+102 -52
View File
@@ -22,61 +22,83 @@ int_is_initialized :: proc(a: ^Int) -> bool {
return raw.cap >= _MIN_DIGIT_COUNT;
}
int_is_zero :: proc(a: ^Int) -> bool {
return is_initialized(a) && a.used == 0;
}
int_is_positive :: proc(a: ^Int) -> bool {
return is_initialized(a) && a.sign == .Zero_or_Positive;
}
int_is_negative :: proc(a: ^Int) -> bool {
return is_initialized(a) && a.sign == .Negative;
}
int_is_even :: proc(a: ^Int) -> bool {
if is_initialized(a) {
if is_zero(a) {
return true;
}
if a.used > 0 && a.digit[0] & 1 == 0 {
return true;
}
int_is_zero :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
return false;
return a.used == 0, .None;
}
int_is_odd :: proc(a: ^Int) -> bool {
if is_initialized(a) {
return !is_even(a);
int_is_positive :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
return false;
return a.sign == .Zero_or_Positive, .None;
}
int_is_negative :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
return a.sign == .Negative, .None;
}
int_is_even :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
res, err = is_zero(a);
if err != .None {
return false, err;
} else if res == true {
return true, .None;
}
res = false;
if a.used > 0 && a.digit[0] & 1 == 0 {
res = true;
}
return res, .None;
}
int_is_odd :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
res, err = is_even(a);
return !res, err;
}
platform_int_is_power_of_two :: proc(a: int) -> bool {
return ((a) != 0) && (((a) & ((a) - 1)) == 0);
}
int_is_power_of_two :: proc(a: ^Int) -> (res: bool) {
int_is_power_of_two :: proc(a: ^Int) -> (res: bool, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return false, err;
}
/*
Early out for Int == 0.
*/
if a.used == 0 {
return false;
return false, .None;
}
/*
For an `Int` to be a power of two, its top limb has to be a power of two.
*/
if !platform_int_is_power_of_two(int(a.digit[a.used - 1])) {
return false;
return false, .None;
}
/*
That was the only limb, so it's a power of two.
*/
if a.used == 1 {
return true;
return true, .None;
}
/*
@@ -84,74 +106,102 @@ int_is_power_of_two :: proc(a: ^Int) -> (res: bool) {
*/
for i := 1; i < a.used; i += 1 {
if a.digit[i - 1] != 0 {
return false;
return false, .None;
}
}
return true;
return true, .None;
}
/*
Compare two `Int`s, signed.
*/
int_compare :: proc(a, b: ^Int) -> Comparison_Flag {
if !is_initialized(a) { return .Uninitialized; }
if !is_initialized(b) { return .Uninitialized; }
int_compare :: proc(a, b: ^Int) -> (res: int, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return 0, err;
}
if err = clear_if_uninitialized(b); err != .None {
return 0, err;
}
neg: bool;
if neg, err = is_negative(a); err != .None {
return 0, err;
}
/* Compare based on sign */
if a.sign != b.sign {
return .Less_Than if is_negative(a) else .Greater_Than;
res = -1 if neg else +1;
return res, .None;
}
x, y := a, b;
/* If negative, compare in the opposite direction */
if is_neg(a) {
x, y = b, a;
if neg {
return cmp_mag(b, a);
}
return cmp_mag(x, y);
return cmp_mag(a, b);
}
/*
Compare an `Int` to an unsigned number upto the size of the backing type.
*/
int_compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag {
if !is_initialized(a) { return .Uninitialized; }
int_compare_digit :: proc(a: ^Int, u: DIGIT) -> (res: int, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return 0, err;
}
/* Compare based on sign */
if is_neg(a) {
return .Less_Than;
neg: bool;
if neg, err = is_neg(a); err != .None {
return 0, err;
}
if neg {
return -1, .None;
}
/* Compare based on magnitude */
if a.used > 1 {
return .Greater_Than;
return +1, .None;
}
/* Compare the only digit in `a` to `u`. */
if a.digit[0] != u {
return .Greater_Than if a.digit[0] > u else .Less_Than;
if a.digit[0] > u {
return +1, .None;
}
return -1, .None;
}
return .Equal;
return 0, .None;
}
/*
Compare the magnitude of two `Int`s, unsigned.
*/
int_compare_magnitude :: proc(a, b: ^Int) -> Comparison_Flag {
if !is_initialized(a) { return .Uninitialized; }
if !is_initialized(b) { return .Uninitialized; }
int_compare_magnitude :: proc(a, b: ^Int) -> (res: int, err: Error) {
if err = clear_if_uninitialized(a); err != .None {
return 0, err;
}
if err = clear_if_uninitialized(b); err != .None {
return 0, err;
}
/* Compare based on used digits */
if a.used != b.used {
return .Greater_Than if a.used > b.used else .Less_Than;
if a.used > b.used {
return +1, .None;
}
return -1, .None;
}
/* Same number of used digits, compare based on their value */
for n := a.used - 1; n >= 0; n -= 1 {
if a.digit[n] != b.digit[n] {
return .Greater_Than if a.digit[n] > b.digit[n] else .Less_Than;
if a.digit[n] > b.digit[n] {
return +1, .None;
}
return -1, .None;
}
}
return .Equal;
return 0, .None;
}