Fast `powi` function
⚓ Rust 📅 2025-11-06 👤 surdeus 👁️ 7I think there is a lot of room to make the powi function a lot quicker, at least for exponents that are u8 and i8. When I benchmark the code below it is significantly faster than powi. I know powi takes an i32, but honestly who is raising a number to a power greater than 127 or less than -128?
trait ExtendedMath {
fn powu8(self, n: u8) -> Self;
}
impl ExtendedMath for f64 {
fn powu8(mut self, n: u8) -> Self {
let mut prod = if n & 1 == 0 { 1.0 } else { self };
for bit in [2, 4, 8, 16, 32, 64, 128] {
self *= self;
if n & bit != 0 {
prod *= self
}
}
prod
}
}
I think there is room to improve this function. It is not too crazy to exhaustively match all the u8 exponents with their optimal solution, see the sample below. There is also a good example of this here, fast_ipow.rs. It would be long, but I think it should execute quickly. The only thing I am not sure of is how quick a match statement would be in this case. Does the exponent need to compare to each match branch, or can it do some memory address magic to jump right to the matching u8? Alternately, I think I could put all the optimal solutions in a static array of closures and index into the needed solution. If this is a better way, then I think the array should be static or maybe const. I hear you should go with const if you can, but I also hear const get inlined everywhere and I am a little scared of accidentally inlining a big array in a bunch of places I didn't mean to.
fn powu8(self, n: u8) -> Self {
match n {
...
3 => self * self * self,
4 => {
let n_2 = n * n;
n_2 * n_2
}
...
}
}
Thoughts?
3 posts - 2 participants
🏷️ Rust_feed