diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-07-19 14:16:44 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2021-08-11 20:59:50 +0200 |
| commit | cccd29083440ae7f93b58d085e70f368293d92bc (patch) | |
| tree | cfdb74ea2bbd6a307c0c63019159c45ce1582257 /core/math | |
| parent | 5af85aed3dcbcead9e8a436e0795b77fcda93a7f (diff) | |
bigint: Add `is_power_of_two` helper.
Diffstat (limited to 'core/math')
| -rw-r--r-- | core/math/bigint/compare.odin | 38 |
1 files changed, 36 insertions, 2 deletions
diff --git a/core/math/bigint/compare.odin b/core/math/bigint/compare.odin index 9d48c4706..97cb64197 100644 --- a/core/math/bigint/compare.odin +++ b/core/math/bigint/compare.odin @@ -48,10 +48,44 @@ is_odd :: proc(a: ^Int) -> bool { return false; } -is_power_of_two :: proc(x: int) -> bool { - return ((x) != 0) && (((x) & ((x) - 1)) == 0); +is_power_of_two_small :: proc(a: int) -> bool { + return ((a) != 0) && (((a) & ((a) - 1)) == 0); } +is_power_of_two_large :: proc(a: ^Int) -> (res: bool) { + /* + Early out for Int == 0. + */ + if a.used == 0 { + return false; + } + + /* + 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])) { + return false; + } + + /* + That was the only limb, so it's a power of two. + */ + if a.used == 1 { + return true; + } + + /* + For an Int to be a power of two, all limbs except the top one have to be zero. + */ + for i := 1; i < a.used; i += 1 { + if a.digit[i - 1] != 0 { + return false; + } + } + return true; +} +is_power_of_two :: proc{is_power_of_two_small, is_power_of_two_large}; + /* Compare two `Int`s, signed. */ |