mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 23:28:48 +00:00
big: Continuing to refactor.
This commit is contained in:
+36
-39
@@ -4,32 +4,32 @@ package big
|
||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||
Made available under Odin's BSD-2 license.
|
||||
|
||||
A BigInt implementation in Odin.
|
||||
An arbitrary precision mathematics implementation in Odin.
|
||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
||||
|
||||
This file contains various comparison routines.
|
||||
*/
|
||||
|
||||
import "core:intrinsics"
|
||||
|
||||
is_initialized :: proc(a: ^Int) -> bool {
|
||||
int_is_initialized :: proc(a: ^Int) -> bool {
|
||||
return a != rawptr(uintptr(0));
|
||||
}
|
||||
|
||||
is_zero :: proc(a: ^Int) -> bool {
|
||||
int_is_zero :: proc(a: ^Int) -> bool {
|
||||
return is_initialized(a) && a.used == 0;
|
||||
}
|
||||
|
||||
is_positive :: proc(a: ^Int) -> bool {
|
||||
int_is_positive :: proc(a: ^Int) -> bool {
|
||||
return is_initialized(a) && a.sign == .Zero_or_Positive;
|
||||
}
|
||||
is_pos :: is_positive;;
|
||||
|
||||
is_negative :: proc(a: ^Int) -> bool {
|
||||
int_is_negative :: proc(a: ^Int) -> bool {
|
||||
return is_initialized(a) && a.sign == .Negative;
|
||||
}
|
||||
is_neg :: is_negative;
|
||||
|
||||
is_even :: proc(a: ^Int) -> bool {
|
||||
int_is_even :: proc(a: ^Int) -> bool {
|
||||
if is_initialized(a) {
|
||||
if is_zero(a) {
|
||||
return true;
|
||||
@@ -41,18 +41,18 @@ is_even :: proc(a: ^Int) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
is_odd :: proc(a: ^Int) -> bool {
|
||||
int_is_odd :: proc(a: ^Int) -> bool {
|
||||
if is_initialized(a) {
|
||||
return !is_even(a);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
is_power_of_two_small :: proc(a: int) -> bool {
|
||||
platform_int_is_power_of_two :: proc(a: int) -> bool {
|
||||
return ((a) != 0) && (((a) & ((a) - 1)) == 0);
|
||||
}
|
||||
|
||||
is_power_of_two_large :: proc(a: ^Int) -> (res: bool) {
|
||||
int_is_power_of_two :: proc(a: ^Int) -> (res: bool) {
|
||||
/*
|
||||
Early out for Int == 0.
|
||||
*/
|
||||
@@ -63,7 +63,7 @@ is_power_of_two_large :: proc(a: ^Int) -> (res: bool) {
|
||||
/*
|
||||
For an `Int` to be a power of two, its top limb has to be a power of two.
|
||||
*/
|
||||
if !is_power_of_two_small(int(a.digit[a.used - 1])) {
|
||||
if !platform_int_is_power_of_two(int(a.digit[a.used - 1])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -84,12 +84,11 @@ is_power_of_two_large :: proc(a: ^Int) -> (res: bool) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
is_power_of_two :: proc{is_power_of_two_small, is_power_of_two_large};
|
||||
|
||||
/*
|
||||
Compare two `Int`s, signed.
|
||||
*/
|
||||
compare :: proc(a, b: ^Int) -> Comparison_Flag {
|
||||
int_compare :: proc(a, b: ^Int) -> Comparison_Flag {
|
||||
if !is_initialized(a) { return .Uninitialized; }
|
||||
if !is_initialized(b) { return .Uninitialized; }
|
||||
|
||||
@@ -105,35 +104,11 @@ compare :: proc(a, b: ^Int) -> Comparison_Flag {
|
||||
}
|
||||
return cmp_mag(x, y);
|
||||
}
|
||||
cmp :: compare;
|
||||
|
||||
/*
|
||||
Compare the magnitude of two `Int`s, unsigned.
|
||||
*/
|
||||
compare_magnitude :: proc(a, b: ^Int) -> Comparison_Flag {
|
||||
if !is_initialized(a) { return .Uninitialized; }
|
||||
if !is_initialized(b) { return .Uninitialized; }
|
||||
|
||||
/* Compare based on used digits */
|
||||
if a.used != b.used {
|
||||
return .Greater_Than if a.used > b.used else .Less_Than;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return .Equal;
|
||||
}
|
||||
cmp_mag :: compare_magnitude;
|
||||
|
||||
/*
|
||||
Compare an `Int` to an unsigned number upto the size of the backing type.
|
||||
*/
|
||||
compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag {
|
||||
int_compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag {
|
||||
if !is_initialized(a) { return .Uninitialized; }
|
||||
|
||||
/* Compare based on sign */
|
||||
@@ -152,4 +127,26 @@ compare_digit :: proc(a: ^Int, u: DIGIT) -> Comparison_Flag {
|
||||
}
|
||||
|
||||
return .Equal;
|
||||
}
|
||||
|
||||
/*
|
||||
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; }
|
||||
|
||||
/* Compare based on used digits */
|
||||
if a.used != b.used {
|
||||
return .Greater_Than if a.used > b.used else .Less_Than;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
return .Equal;
|
||||
}
|
||||
Reference in New Issue
Block a user