aboutsummaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-07-19 14:16:44 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-08-11 20:59:50 +0200
commitcccd29083440ae7f93b58d085e70f368293d92bc (patch)
treecfdb74ea2bbd6a307c0c63019159c45ce1582257 /core/math
parent5af85aed3dcbcead9e8a436e0795b77fcda93a7f (diff)
bigint: Add `is_power_of_two` helper.
Diffstat (limited to 'core/math')
-rw-r--r--core/math/bigint/compare.odin38
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.
*/