mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-01 04:10:07 +00:00
big: Add pow.
This commit is contained in:
@@ -516,7 +516,7 @@ int_mul_digit :: proc(dest, src: ^Int, multiplier: DIGIT) -> (err: Error) {
|
|||||||
}
|
}
|
||||||
if is_power_of_two(int(multiplier)) {
|
if is_power_of_two(int(multiplier)) {
|
||||||
ix: int;
|
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);
|
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, };
|
mul :: proc { int_mul, int_mul_digit, };
|
||||||
|
|
||||||
|
sqr :: proc(dest, src: ^Int) -> (err: Error) {
|
||||||
|
return mul(dest, src, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
==========================
|
==========================
|
||||||
Low-level routines
|
Low-level routines
|
||||||
|
|||||||
+46
-4
@@ -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.
|
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 {
|
if base < 2 || DIGIT(base) > _DIGIT_MAX {
|
||||||
return -1, .Invalid_Argument;
|
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`.
|
Fast path for `Int`s that fit within a single `DIGIT`.
|
||||||
*/
|
*/
|
||||||
if a.used == 1 {
|
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)) {
|
// 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;
|
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.
|
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;
|
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.
|
If the number is smaller than the base, it fits within a fraction.
|
||||||
Therefore, we return 0.
|
Therefore, we return 0.
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ itoa_raw :: proc(a: ^Int, radix: i8, buffer: []u8, size := int(-1), zero_termina
|
|||||||
|
|
||||||
shift, count: int;
|
shift, count: int;
|
||||||
// mask := _WORD(radix - 1);
|
// mask := _WORD(radix - 1);
|
||||||
shift, err = log_n(DIGIT(radix), 2);
|
shift, err = log(DIGIT(radix), 2);
|
||||||
count, err = count_bits(a);
|
count, err = count_bits(a);
|
||||||
digit: _WORD;
|
digit: _WORD;
|
||||||
|
|
||||||
@@ -263,7 +263,7 @@ radix_size :: proc(a: ^Int, radix: i8, zero_terminate := false) -> (size: int, e
|
|||||||
digit = a.digit,
|
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;
|
return 0, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user