diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-09-01 18:00:00 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-09-01 19:13:47 +0200 |
| commit | 335d361fc6b878f283423b74babab3f5e13b847c (patch) | |
| tree | 375b210838e366510e1a3d8b7263ccc39f8423d8 | |
| parent | df29d1021058624664ea8ec8fac0d01d9d45b97a (diff) | |
big: Add comparison helpers.
| -rw-r--r-- | core/math/big/internal.odin | 174 | ||||
| -rw-r--r-- | core/math/big/public.odin | 292 |
2 files changed, 466 insertions, 0 deletions
diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index ca113275c..aa62569e7 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -1098,6 +1098,7 @@ internal_is_power_of_two :: proc { internal_int_is_power_of_two, }; Expects `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare :: #force_inline proc(a, b: ^Int) -> (comparison: int) { + assert_if_nil(a, b); a_is_negative := #force_inline internal_is_negative(a); /* @@ -1121,6 +1122,7 @@ internal_cmp :: internal_compare; Expects: `a` and `b` both to be valid `Int`s, i.e. initialized and not `nil`. */ internal_int_compare_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (comparison: int) { + assert_if_nil(a); a_is_negative := #force_inline internal_is_negative(a); switch { @@ -1152,6 +1154,7 @@ internal_cmp_digit :: internal_compare_digit; Compare the magnitude of two `Int`s, unsigned. */ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: int) { + assert_if_nil(a, b); /* Compare based on used digits. */ @@ -1179,6 +1182,177 @@ internal_int_compare_magnitude :: #force_inline proc(a, b: ^Int) -> (comparison: internal_compare_magnitude :: proc { internal_int_compare_magnitude, }; internal_cmp_mag :: internal_compare_magnitude; + +/* + bool := a < b +*/ +internal_int_less_than :: #force_inline proc(a, b: ^Int) -> (less_than: bool) { + return internal_cmp(a, b) == -1; +} + +/* + bool := a < b +*/ +internal_int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (less_than: bool) { + return internal_cmp_digit(a, b) == -1; +} + +/* + bool := |a| < |b| + Compares the magnitudes only, ignores the sign. +*/ +internal_int_less_than_abs :: #force_inline proc(a, b: ^Int) -> (less_than: bool) { + return internal_cmp_mag(a, b) == -1; +} + +internal_less_than :: proc { + internal_int_less_than, + internal_int_less_than_digit, +} +internal_lt :: internal_less_than; + +internal_less_than_abs :: proc { + internal_int_less_than_abs, +} +internal_lt_abs :: internal_less_than_abs; + + +/* + bool := a <= b +*/ +internal_int_less_than_or_equal :: #force_inline proc(a, b: ^Int) -> (less_than_or_equal: bool) { + return internal_cmp(a, b) <= 0; +} + +/* + bool := a <= b +*/ +internal_int_less_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (less_than_or_equal: bool) { + return internal_cmp_digit(a, b) <= 0; +} + +/* + bool := |a| <= |b| + Compares the magnitudes only, ignores the sign. +*/ +internal_int_less_than_or_equal_abs :: #force_inline proc(a, b: ^Int) -> (less_than_or_equal: bool) { + return internal_cmp_mag(a, b) <= 0; +} + +internal_less_than_or_equal :: proc { + internal_int_less_than_or_equal, + internal_int_less_than_or_equal_digit, +} +internal_lteq :: internal_less_than_or_equal; + +internal_less_than_or_equal_abs :: proc { + internal_int_less_than_or_equal_abs, +} +internal_lteq_abs :: internal_less_than_or_equal_abs; + + +/* + bool := a == b +*/ +internal_int_equals :: #force_inline proc(a, b: ^Int) -> (equals: bool) { + return internal_cmp(a, b) == 0; +} + +/* + bool := a == b +*/ +internal_int_equals_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (equals: bool) { + return internal_cmp_digit(a, b) == 0; +} + +/* + bool := |a| == |b| + Compares the magnitudes only, ignores the sign. +*/ +internal_int_equals_abs :: #force_inline proc(a, b: ^Int) -> (equals: bool) { + return internal_cmp_mag(a, b) == 0; +} + +internal_equals :: proc { + internal_int_equals, + internal_int_equals_digit, +} +internal_eq :: internal_equals; + +internal_equals_abs :: proc { + internal_int_equals_abs, +} +internal_eq_abs :: internal_equals_abs; + + +/* + bool := a >= b +*/ +internal_int_greater_than_or_equal :: #force_inline proc(a, b: ^Int) -> (greater_than_or_equal: bool) { + return internal_cmp(a, b) >= 0; +} + +/* + bool := a >= b +*/ +internal_int_greater_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (greater_than_or_equal: bool) { + return internal_cmp_digit(a, b) >= 0; +} + +/* + bool := |a| >= |b| + Compares the magnitudes only, ignores the sign. +*/ +internal_int_greater_than_or_equal_abs :: #force_inline proc(a, b: ^Int) -> (greater_than_or_equal: bool) { + return internal_cmp_mag(a, b) >= 0; +} + +internal_greater_than_or_equal :: proc { + internal_int_greater_than_or_equal, + internal_int_greater_than_or_equal_digit, +} +internal_gteq :: internal_greater_than_or_equal; + +internal_greater_than_or_equal_abs :: proc { + internal_int_greater_than_or_equal_abs, +} +internal_gteq_abs :: internal_greater_than_or_equal_abs; + + +/* + bool := a > b +*/ +internal_int_greater_than :: #force_inline proc(a, b: ^Int) -> (greater_than: bool) { + return internal_cmp(a, b) == 1; +} + +/* + bool := a > b +*/ +internal_int_greater_than_digit :: #force_inline proc(a: ^Int, b: DIGIT) -> (greater_than: bool) { + return internal_cmp_digit(a, b) == 1; +} + +/* + bool := |a| > |b| + Compares the magnitudes only, ignores the sign. +*/ +internal_int_greater_than_abs :: #force_inline proc(a, b: ^Int) -> (greater_than: bool) { + return internal_cmp_mag(a, b) == 1; +} + +internal_greater_than :: proc { + internal_int_greater_than, + internal_int_greater_than_digit, +} +internal_gt :: internal_greater_than; + +internal_greater_than_abs :: proc { + internal_int_greater_than_abs, +} +internal_gt_abs :: internal_greater_than_abs; + + /* Check if remainders are possible squares - fast exclude non-squares. diff --git a/core/math/big/public.odin b/core/math/big/public.odin index 68c574905..f701663a7 100644 --- a/core/math/big/public.odin +++ b/core/math/big/public.odin @@ -561,6 +561,298 @@ int_compare_magnitude :: proc(a, b: ^Int, allocator := context.allocator) -> (re return #force_inline internal_cmp_mag(a, b), nil;
}
+int_cmp_mag :: int_compare_magnitude;
+
+
+/*
+ bool := a < b
+*/
+int_less_than :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c == -1, err;
+}
+
+/*
+ bool := a < b
+*/
+int_less_than_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (less_than: bool, err: Error) {
+ assert_if_nil(a);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c == -1, err;
+}
+
+/*
+ bool := |a| < |b|
+ Compares the magnitudes only, ignores the sign.
+*/
+int_less_than_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp_mag(a, b);
+
+ return c == -1, err;
+}
+
+less_than :: proc {
+ int_less_than,
+ int_less_than_digit,
+}
+lt :: less_than;
+
+less_than_abs :: proc {
+ int_less_than_abs,
+}
+lt_abs :: less_than_abs;
+
+
+/*
+ bool := a <= b
+*/
+int_less_than_or_equal :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c <= 0, err;
+}
+
+/*
+ bool := a <= b
+*/
+int_less_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
+ assert_if_nil(a);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c <= 0, err;
+}
+
+/*
+ bool := |a| <= |b|
+ Compares the magnitudes only, ignores the sign.
+*/
+int_less_than_or_equal_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (less_than_or_equal: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp_mag(a, b);
+
+ return c <= 0, err;
+}
+
+less_than_or_equal :: proc {
+ int_less_than_or_equal,
+ int_less_than_or_equal_digit,
+}
+lteq :: less_than_or_equal;
+
+less_than_or_equal_abs :: proc {
+ int_less_than_or_equal_abs,
+}
+lteq_abs :: less_than_or_equal_abs;
+
+
+/*
+ bool := a == b
+*/
+int_equals :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (equals: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c == 0, err;
+}
+
+/*
+ bool := a == b
+*/
+int_equals_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (equals: bool, err: Error) {
+ assert_if_nil(a);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c == 0, err;
+}
+
+/*
+ bool := |a| == |b|
+ Compares the magnitudes only, ignores the sign.
+*/
+int_equals_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (equals: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp_mag(a, b);
+
+ return c == 0, err;
+}
+
+equals :: proc {
+ int_equals,
+ int_equals_digit,
+}
+eq :: equals;
+
+equals_abs :: proc {
+ int_equals_abs,
+}
+eq_abs :: equals_abs;
+
+
+/*
+ bool := a >= b
+*/
+int_greater_than_or_equal :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c >= 0, err;
+}
+
+/*
+ bool := a >= b
+*/
+int_greater_than_or_equal_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
+ assert_if_nil(a);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c >= 0, err;
+}
+
+/*
+ bool := |a| >= |b|
+ Compares the magnitudes only, ignores the sign.
+*/
+int_greater_than_or_equal_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than_or_equal: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp_mag(a, b);
+
+ return c >= 0, err;
+}
+
+greater_than_or_equal :: proc {
+ int_greater_than_or_equal,
+ int_greater_than_or_equal_digit,
+}
+gteq :: greater_than_or_equal;
+
+greater_than_or_equal_abs :: proc {
+ int_greater_than_or_equal_abs,
+}
+gteq_abs :: greater_than_or_equal_abs;
+
+
+/*
+ bool := a > b
+*/
+int_greater_than :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c > 0, err;
+}
+
+/*
+ bool := a > b
+*/
+int_greater_than_digit :: #force_inline proc(a: ^Int, b: DIGIT, allocator := context.allocator) -> (greater_than: bool, err: Error) {
+ assert_if_nil(a);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a) or_return;
+
+ c: int;
+ c, err = cmp(a, b);
+
+ return c > 0, err;
+}
+
+/*
+ bool := |a| > |b|
+ Compares the magnitudes only, ignores the sign.
+*/
+int_greater_than_abs :: #force_inline proc(a, b: ^Int, allocator := context.allocator) -> (greater_than: bool, err: Error) {
+ assert_if_nil(a, b);
+ context.allocator = allocator;
+
+ internal_clear_if_uninitialized(a, b) or_return;
+
+ c: int;
+ c, err = cmp_mag(a, b);
+
+ return c > 0, err;
+}
+
+greater_than :: proc {
+ int_greater_than,
+ int_greater_than_digit,
+}
+gt :: greater_than;
+
+greater_than_abs :: proc {
+ int_greater_than_abs,
+}
+gt_abs :: greater_than_abs;
+
/*
Check if remainders are possible squares - fast exclude non-squares.
|