diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-08-04 13:43:16 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-08-11 20:59:53 +0200 |
| commit | 85a2a8815e2ae06d23ec23224e00084e143363e2 (patch) | |
| tree | 8da0f411671e2e222154e812c2a16411cce80d7c /core/math/big/helpers.odin | |
| parent | 47397a6a488ad9cae625e531e5236513b81660a0 (diff) | |
big: Some more work on constants.
Diffstat (limited to 'core/math/big/helpers.odin')
| -rw-r--r-- | core/math/big/helpers.odin | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index f0eeea96b..9217589db 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -14,6 +14,10 @@ import "core:intrinsics" import rnd "core:math/rand" /* + TODO: Int.flags and Constants like ONE, NAN, etc, are not yet properly handled everywhere. +*/ + +/* Deallocates the backing memory of one or more `Int`s. */ int_destroy :: proc(integers: ..^Int) { @@ -35,10 +39,13 @@ int_destroy :: proc(integers: ..^Int) { int_set_from_integer :: proc(dest: ^Int, src: $T, minimize := false, allocator := context.allocator) -> (err: Error) where intrinsics.type_is_integer(T) { src := src; - if err = clear_if_uninitialized(dest); err != nil { - return err; - } - dest.used = 0; + + if err = error_if_immutable(dest); err != nil { return err; } + if err = clear_if_uninitialized(dest); err != nil { return err; } + + dest.flags = {}; // We're not -Inf, Inf, NaN or Immutable. + + dest.used = 0; dest.sign = .Zero_or_Positive if src >= 0 else .Negative; src = abs(src); @@ -57,19 +64,21 @@ set :: proc { int_set_from_integer, int_copy }; Copy one `Int` to another. */ int_copy :: proc(dest, src: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - if err = error_if_immutable(dest); err != nil { return err; } - if err = clear_if_uninitialized(src); err != nil { return err; } /* If dest == src, do nothing */ - if (dest == src) { - return nil; - } + if (dest == src) { return nil; } + + if err = error_if_immutable(dest); err != nil { return err; } + if err = clear_if_uninitialized(src); err != nil { return err; } + /* Grow `dest` to fit `src`. If `dest` is not yet initialized, it will be using `allocator`. */ - if err = grow(dest, src.used, minimize, allocator); err != nil { + needed := src.used if minimize else max(src.used, _DEFAULT_DIGIT_COUNT); + + if err = grow(dest, needed, minimize, allocator); err != nil { return err; } @@ -340,7 +349,7 @@ zero :: clear; Set the `Int` to 1 and optionally shrink it to the minimum backing size. */ int_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return set(a, 1); + return set(a, 1, minimize, allocator); } one :: proc { int_one, }; @@ -348,7 +357,7 @@ one :: proc { int_one, }; Set the `Int` to -1 and optionally shrink it to the minimum backing size. */ int_minus_one :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return set(a, -1); + return set(a, -1, minimize, allocator); } minus_one :: proc { int_minus_one, }; @@ -356,7 +365,9 @@ minus_one :: proc { int_minus_one, }; Set the `Int` to Inf and optionally shrink it to the minimum backing size. */ int_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return copy(a, INF, minimize, allocator); + err = set(a, 1, minimize, allocator); + a.flags |= { .Inf, }; + return err; } inf :: proc { int_inf, }; @@ -364,7 +375,9 @@ inf :: proc { int_inf, }; Set the `Int` to -Inf and optionally shrink it to the minimum backing size. */ int_minus_inf :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return copy(a, MINUS_INF, minimize, allocator); + err = set(a, -1, minimize, allocator); + a.flags |= { .Inf, }; + return err; } minus_inf :: proc { int_inf, }; @@ -372,7 +385,9 @@ minus_inf :: proc { int_inf, }; Set the `Int` to NaN and optionally shrink it to the minimum backing size. */ int_nan :: proc(a: ^Int, minimize := false, allocator := context.allocator) -> (err: Error) { - return copy(a, NAN, minimize, allocator); + err = set(a, 1, minimize, allocator); + a.flags |= { .NaN, }; + return err; } nan :: proc { int_nan, }; @@ -691,9 +706,14 @@ initialize_constants :: proc() -> (res: int) { set( ZERO, 0); ZERO.flags = {.Immutable}; set( ONE, 1); ONE.flags = {.Immutable}; set(MINUS_ONE, -1); MINUS_ONE.flags = {.Immutable}; - set( INF, 0); INF.flags = {.Immutable, .Inf}; - set( INF, 0); MINUS_INF.flags = {.Immutable, .Inf}; MINUS_INF.sign = .Negative; - set( NAN, 0); NAN.flags = {.Immutable, .NaN}; + + /* + We set these special values to -1 or 1 so they don't get mistake for zero accidentally. + This allows for shortcut tests of is_zero as .used == 0. + */ + set( INF, 1); INF.flags = {.Immutable, .Inf}; + set( INF, -1); MINUS_INF.flags = {.Immutable, .Inf}; + set( NAN, 1); NAN.flags = {.Immutable, .NaN}; return #config(MUL_KARATSUBA_CUTOFF, _DEFAULT_MUL_KARATSUBA_CUTOFF); } |