#[inline]
pub(crate) fn _ipow(mut base: i64, mut exp: i64) -> i64 {
if exp < 0 {
if base == 1 {
return 1;
}
if base == -1 {
return if exp % 2 == 0 { 1 } else { -1 };
}
return 0;
}
let mut result: i64 = 1;
loop {
if exp & 1 != 0 {
result = result.wrapping_mul(base);
}
exp >>= 1;
if exp == 0 {
break;
}
base = base.wrapping_mul(base);
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ipow() {
assert_eq!(_ipow(7, 0), 1, "7^0");
assert_eq!(_ipow(7, 1), 7, "7^1");
assert_eq!(_ipow(7, 2), 49, "7^2");
assert_eq!(_ipow(1, 20), 1, "1^20");
assert_eq!(_ipow(2, 5), 32, "2^5");
assert_eq!(_ipow(-2, 2), 4, "(-2)^2");
assert_eq!(_ipow(-2, 3), -8, "(-2)^3");
assert_eq!(_ipow(2, -1), 0, "2^-1");
assert_eq!(_ipow(1, -5), 1, "1^-5");
assert_eq!(_ipow(-1, -2), 1, "(-1)^-2");
assert_eq!(_ipow(-1, -3), -1, "(-1)^-3");
assert_eq!(_ipow(3, 39), 4052555153018976267_i64, "3^39 should fit");
assert_eq!(_ipow(3, 40), -6289078614652622815_i64, "3^40 should wrap");
}
}