aboutsummaryrefslogtreecommitdiff
path: root/core/math
diff options
context:
space:
mode:
authorJeroen van Rijn <Kelimion@users.noreply.github.com>2021-07-23 22:47:44 +0200
committerJeroen van Rijn <Kelimion@users.noreply.github.com>2021-08-11 20:59:51 +0200
commitd953e40fb30daecb4571e600d64a19a9dd2baac4 (patch)
tree874ac6c69be90fea8f930f4673feaa6a3a8cec69 /core/math
parentc3a4d7dda258d092fab7a101d63f7ffe6009db8e (diff)
big: Add `pow`.
Diffstat (limited to 'core/math')
-rw-r--r--core/math/big/basic.odin7
-rw-r--r--core/math/big/log.odin50
-rw-r--r--core/math/big/radix.odin4
3 files changed, 54 insertions, 7 deletions
diff --git a/core/math/big/basic.odin b/core/math/big/basic.odin
index fbb533ddf..18186b38c 100644
--- a/core/math/big/basic.odin
+++ b/core/math/big/basic.odin
@@ -516,7 +516,7 @@ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT) -> (err: Error) {
}
if is_power_of_two(int(multiplier)) {
ix: int;
- if ix, err = log_n(multiplier, 2); err != .None { return err; }
+ if ix, err = log(multiplier, 2); err != .None { return err; }
return shl(dest, src, ix);
}
@@ -648,6 +648,11 @@ int_mul :: proc(dest, src, multiplier: ^Int) -> (err: Error) {
mul :: proc { int_mul, int_mul_digit, };
+sqr :: proc(dest, src: ^Int) -> (err: Error) {
+ return mul(dest, src, src);
+}
+
+
/*
==========================
Low-level routines
diff --git a/core/math/big/log.odin b/core/math/big/log.odin
index bb918f690..14b4c593b 100644
--- a/core/math/big/log.odin
+++ b/core/math/big/log.odin
@@ -9,7 +9,7 @@ package big
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
*/
-log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
+int_log :: proc(a: ^Int, base: DIGIT) -> (res: int, err: Error) {
if base < 2 || DIGIT(base) > _DIGIT_MAX {
return -1, .Invalid_Argument;
}
@@ -35,7 +35,7 @@ log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
Fast path for `Int`s that fit within a single `DIGIT`.
*/
if a.used == 1 {
- return log_n_digit(a.digit[0], DIGIT(base));
+ return log(a.digit[0], DIGIT(base));
}
// if (MP_HAS(S_MP_LOG)) {
@@ -45,7 +45,49 @@ log_n_int :: proc(a: ^Int, base: DIGIT) -> (log: int, err: Error) {
return -1, .Unimplemented;
}
-log_n :: proc{log_n_int, log_n_digit};
+log :: proc { int_log, int_log_digit, };
+
+/*
+ Calculate c = a**b using a square-multiply algorithm.
+*/
+int_pow :: proc(dest, base: ^Int, power: int) -> (err: Error) {
+ if err = clear_if_uninitialized(dest); err != .None { return err; }
+ if err = clear_if_uninitialized(base); err != .None { return err; }
+
+// if ((err = mp_init_copy(&g, a)) != MP_OKAY) {
+// return err;
+// }
+
+// /* set initial result */
+// mp_set(c, 1uL);
+
+// while (b > 0) {
+// /* if the bit is set multiply */
+// if ((b & 1) != 0) {
+// if ((err = mp_mul(c, &g, c)) != MP_OKAY) {
+// goto LBL_ERR;
+// }
+// }
+
+// /* square */
+// if (b > 1) {
+// if ((err = mp_sqr(&g, &g)) != MP_OKAY) {
+// goto LBL_ERR;
+// }
+// }
+
+// /* shift to next bit */
+// b >>= 1;
+// }
+
+// LBL_ERR:
+// mp_clear(&g);
+// return err;
+ return err;
+}
+
+
+pow :: proc { int_pow, };
/*
Returns the log2 of an `Int`, provided `base` is a power of two.
@@ -79,7 +121,7 @@ small_pow :: proc(base: _WORD, exponent: _WORD) -> (result: _WORD) {
return result;
}
-log_n_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
+int_log_digit :: proc(a: DIGIT, base: DIGIT) -> (log: int, err: Error) {
/*
If the number is smaller than the base, it fits within a fraction.
Therefore, we return 0.
diff --git a/core/math/big/radix.odin b/core/math/big/radix.odin
index 8b4abc76d..2dba5d8b4 100644
--- a/core/math/big/radix.odin
+++ b/core/math/big/radix.odin
@@ -207,7 +207,7 @@ itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_termina
shift, count: int;
// mask := _WORD(radix - 1);
- shift, err = log_n(DIGIT(radix), 2);
+ shift, err = log(DIGIT(radix), 2);
count, err = count_bits(a);
digit: _WORD;
@@ -263,7 +263,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false) -> (size: int, e
digit = a.digit,
};
- if size, err = log_n(t, DIGIT(radix)); err != .None {
+ if size, err = log(t, DIGIT(radix)); err != .None {
return 0, err;
}