Przeglądaj źródła

big: More ZII refactoring.

Jeroen van Rijn 4 lat temu
rodzic
commit
d9efa6c8b5

+ 33 - 13
core/math/big/basic.odin

@@ -25,7 +25,11 @@ import "core:intrinsics"
 */
 int_add :: proc(dest, a, b: ^Int) -> (err: Error) {
 	dest := dest; x := a; y := b;
-	assert_initialized(dest); assert_initialized(a); assert_initialized(b);
+	if dest == nil || a == nil || b == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(a) || !is_initialized(b) {
+		return .Int_Not_Initialized;
+	}
 
 	/*
 		Handle both negative or both positive.
@@ -56,8 +60,11 @@ int_add :: proc(dest, a, b: ^Int) -> (err: Error) {
 */
 int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 	dest := dest; digit := digit;
-	assert_initialized(dest); assert_initialized(a);
-
+	if dest == nil || a == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(a) {
+		return .Int_Not_Initialized;
+	}
 	/*
 		Fast paths for destination and input Int being the same.
 	*/
@@ -81,8 +88,7 @@ int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 	/*
 		Grow destination as required.
 	*/
-	err = grow(dest, a.used + 1);
-	if err != .OK {
+	if err = grow(dest, a.used + 1); err != .OK {
 		return err;
 	}
 
@@ -170,7 +176,11 @@ int_add_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 */
 int_sub :: proc(dest, number, decrease: ^Int) -> (err: Error) {
 	dest := dest; x := number; y := decrease;
-	assert_initialized(number); assert_initialized(decrease); assert_initialized(dest);
+	if dest == nil || number == nil || decrease == nil {
+		return .Nil_Pointer_Passed;
+	} else if !(is_initialized(number) && is_initialized(decrease)) {
+		return .Int_Not_Initialized;
+	}
 
 	if x.sign != y.sign {
 		/*
@@ -210,7 +220,11 @@ int_sub :: proc(dest, number, decrease: ^Int) -> (err: Error) {
 */
 int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 	dest := dest; digit := digit;
-	assert_initialized(dest); assert_initialized(a);
+	if dest == nil || a == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(a) {
+		return .Int_Not_Initialized;
+	}
 
 	/*
 		Fast paths for destination and input Int being the same.
@@ -306,7 +320,11 @@ int_sub_digit :: proc(dest, a: ^Int, digit: DIGIT) -> (err: Error) {
 */
 _int_add :: proc(dest, a, b: ^Int) -> (err: Error) {
 	dest := dest; x := a; y := b;
-	assert_initialized(a); assert_initialized(b); assert_initialized(dest);
+	if dest == nil || a == nil || b == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(a) || !is_initialized(b) {
+		return .Int_Not_Initialized;
+	}
 
 	old_used, min_used, max_used, i: int;
 
@@ -318,8 +336,7 @@ _int_add :: proc(dest, a, b: ^Int) -> (err: Error) {
 	max_used = y.used;
 	old_used = dest.used;
 
-	err = grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT));
-	if err != .OK {
+	if err = grow(dest, max(max_used + 1, _DEFAULT_DIGIT_COUNT)); err != .OK {
 		return err;
 	}
 	dest.used = max_used + 1;
@@ -387,15 +404,18 @@ _int_add :: proc(dest, a, b: ^Int) -> (err: Error) {
 */
 _int_sub :: proc(dest, number, decrease: ^Int) -> (err: Error) {
 	dest := dest; x := number; y := decrease;
-	assert_initialized(number); assert_initialized(decrease); assert_initialized(dest);
+	if dest == nil || number == nil || decrease == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(number) || !is_initialized(decrease) {
+		return .Int_Not_Initialized;
+	}
 
 	old_used := dest.used;
 	min_used := y.used;
 	max_used := x.used;
 	i: int;
 
-	err = grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT));
-	if err != .OK {
+	if err = grow(dest, max(max_used, _DEFAULT_DIGIT_COUNT)); err != .OK {
 		return err;
 	}
 	dest.used = max_used;

+ 2 - 2
core/math/big/example.odin

@@ -44,9 +44,9 @@ _SQR_TOOM_CUTOFF,
 print :: proc(name: string, a: ^Int, base := i8(16)) {
 	as, err := itoa(a, base);
 	defer delete(as);
-
 	if err == .OK {
-		fmt.printf("%v (base: %v, bits used: %v): %v\n", name, base, count_bits(a), as);
+		cb, _ := count_bits(a);
+		fmt.printf("%v (base: %v, bits used: %v): %v\n", name, base, cb, as);
 	} else {
 		fmt.printf("%v (error: %v): %v\n", name, err, a);
 	}

+ 33 - 15
core/math/big/helpers.odin

@@ -328,7 +328,12 @@ minus_one :: proc { int_minus_one, };
 
 
 power_of_two :: proc(a: ^Int, power: int) -> (err: Error) {
-	assert_initialized(a);
+	/*
+		Check that `a` is usable.
+	*/
+	if a == nil {
+		return .Nil_Pointer_Passed;
+	}
 
 	if power < 0 || power > _MAX_BIT_COUNT {
 		return .Invalid_Input;
@@ -356,13 +361,17 @@ power_of_two :: proc(a: ^Int, power: int) -> (err: Error) {
 /*
 	Count bits in an `Int`.
 */
-count_bits :: proc(a: ^Int) -> (count: int) {
-	assert_initialized(a);
+count_bits :: proc(a: ^Int) -> (count: int, err: Error) {
+	if a == nil {
+		return 0, .Nil_Pointer_Passed;
+	} else if !is_initialized(a) {
+		return 0, .Int_Not_Initialized;
+	}
 	/*
 		Fast path for zero.
 	*/
 	if is_zero(a) {
-		return 0;
+		return 0, .OK;
 	}
 	/*
 		Get the number of DIGITs and use it.
@@ -384,7 +393,12 @@ assert_initialized :: proc(a: ^Int, loc := #caller_location) {
 }
 
 _zero_unused :: proc(a: ^Int) {
-	assert_initialized(a);
+	if a == nil {
+		return;
+	} else if !is_initialized(a) {
+		return;
+	}
+
 	if a.used < len(a.digit) {
 		mem.zero_slice(a.digit[a.used:]);
 	}
@@ -397,15 +411,18 @@ _grow_if_uninitialized :: proc(dest: ^Int, minimize := false) -> (err: Error) {
 	return .OK;
 }
 
-clamp :: proc(a: ^Int) {
-	assert_initialized(a);
-	/*
-		Trim unused digits
-		This is used to ensure that leading zero digits are
-		trimmed and the leading "used" digit will be non-zero.
-		Typically very fast.  Also fixes the sign if there
-		are no more leading digits.
-	*/
+/*
+	Trim unused digits.
+
+	This is used to ensure that leading zero digits are trimmed and the leading "used" digit will be non-zero.
+	Typically very fast.  Also fixes the sign if there are no more leading digits.
+*/
+clamp :: proc(a: ^Int) -> (err: Error) {
+	if a == nil {
+		return .Nil_Pointer_Passed;
+	} else if !is_initialized(a) {
+		return .Int_Not_Initialized;
+	}
 
 	for a.used > 0 && a.digit[a.used - 1] == 0 {
 		a.used -= 1;
@@ -414,5 +431,6 @@ clamp :: proc(a: ^Int) {
 	if is_zero(a) {
 		a.sign = .Zero_or_Positive;
 	}
-}
 
+	return .OK;
+}

+ 16 - 11
core/math/big/log.odin

@@ -10,7 +10,11 @@ package big
 */
 
 log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
-	assert_initialized(a);
+	if a == nil {
+		return 0, .Nil_Pointer_Passed;
+	} else if !is_initialized(a) {
+		return 0, .Int_Not_Initialized;
+	}
 	if is_neg(a) || is_zero(a) || base < 2 || DIGIT(base) > _DIGIT_MAX {
 		return -1, .Invalid_Input;
 	}
@@ -19,14 +23,14 @@ log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
 		Fast path for bases that are a power of two.
 	*/
 	if is_power_of_two(int(base)) {
-		return _log_power_of_two(a, base), .OK;
+		return _log_power_of_two(a, base);
 	}
 
 	/*
 		Fast path for `Int`s that fit within a single `DIGIT`.
 	*/
 	if a.used == 1 {
-		return log_n_digit(a.digit[0], DIGIT(base)), .OK;
+		return log_n_digit(a.digit[0], DIGIT(base));
 	}
 
     // if (MP_HAS(S_MP_LOG)) {
@@ -42,14 +46,15 @@ log_n :: proc{log_n_int, log_n_digit};
 	Returns the log2 of an `Int`, provided `base` is a power of two.
 	Don't call it if it isn't.
 */
-_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int) {
+_log_power_of_two :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
 	base := base;
 	y: int;
 	for y = 0; base & 1 == 0; {
 		y += 1;
 		base >>= 1;
 	}
-	return (count_bits(a) - 1) / y;
+	log, err = count_bits(a);
+	return (log - 1) / y, err;
 }
 
 /*
@@ -69,20 +74,20 @@ small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
    	return result;
 }
 
-log_n_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int) {
+log_n_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
 	/*
 		If the number is smaller than the base, it fits within a fraction.
 		Therefore, we return 0.
 	*/
 	if a < base {
-		return 0;
+		return 0, .OK;
 	}
 
 	/*
 		If a number equals the base, the log is 1.
 	*/
 	if a == base {
-		return 1;
+		return 1, .OK;
 	}
 
 	N := _WORD(a);
@@ -111,13 +116,13 @@ log_n_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int) {
 			bracket_low = bracket_mid;
 		}
 		if N == bracket_mid {
-			return mid;
+			return mid, .OK;
 		}
    	}
 
    	if bracket_high == N {
-   		return high;
+   		return high, .OK;
    	} else {
-   		return low;
+   		return low, .OK;
    	}
 }

+ 3 - 2
core/math/big/radix.odin

@@ -198,9 +198,10 @@ itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_termina
 			buffer[available] = 0;
 		}
 
+		shift, count: int;
 		// mask  := _WORD(radix - 1);
-		shift := int(log_n(DIGIT(radix), 2));
-		count := int(count_bits(a));
+		shift, err = log_n(DIGIT(radix), 2);
+		count, err = count_bits(a);
 		// digit: _WORD;
 
 		for offset := 0; offset < count; offset += 4 {