High-performance `fast-powi` crate

Following Fast powi function topic, I made a fast-powi crate. I only implemented 8-bit exponents; i.e, i8 and u8. I don't know of any practical use of exponents greater than 127. This allowed me to hard-code all the shortest "addition-chains" (or multiplication-chains in this case) for all u8 exponents. I decided to implement the num crate numerical types. It is about 10X faster than the standard library powi for floats on my computer. It is about 20% faster than most ints, bigints, and ratios. It is about 50% faster for complex ratio types.

Here is a summary of the benchmarks from my laptop.

f64_fast                time:   [765.08 ns 772.03 ns 778.96 ns]
f64_std                 time:   [8.1878 µs 8.2823 µs 8.3878 µs]

bigint_fast             time:   [70.852 µs 71.336 µs 71.814 µs]
bigint_num              time:   [89.324 µs 89.779 µs 90.293 µs]

big_ratio_fast          time:   [303.19 µs 304.39 µs 305.70 µs]
big_ratio_num           time:   [355.01 µs 357.22 µs 359.59 µs]

u64_fast                time:   [105.52 ns 107.19 ns 108.99 ns]
u64_num                 time:   [210.32 ns 213.48 ns 218.01 ns]

big_complex_ratio_fast  time:   [23.048 ms 23.522 ms 24.193 ms]
big_complex_ratio_num   time:   [32.578 ms 32.965 ms 33.449 ms]

You can find the benchmark code here

I probably should have ask for a review before publishing on crate.io, but I got "go fever" to publish my first crate. I would appreciate any input.

Precision tests? (Extra points if it's more precise according to IEEE754 than standard :grinning:)

Good question. It is comparable, but not quite as accurate.

fn main() {
    let tenth: f64 = 0.1;
    let exp: i8 = 20;
    println!("std:  {tenth}^{exp} = {:e}", tenth.powi(exp as i32));
    println!("fast: {tenth}^{exp} = {:e}", tenth.powi8(exp));
}
std:  0.1^20 = 1.0000000000000011e-20
fast: 0.1^20 = 1.0000000000000024e-20

This could be useful for speeding up some graphics stuff like Phong–Blinn style specular highlights which use an exponent somewhere from 20 to 100 depending on the "shininess" desired.

Your right. I forgot about Phong–Blinn style specular highlights. I wrote one a few year ago while playing with WebGL, WebGL Demo 7: Normal Map. In my example I use a power of 256! The power is just beyond what my fast-powi crate can handle. The highlight intensity usually get written into the shader, so I am not sure it is applicable to for use with Rust (unless you can compile Rust into shaders, ¯_(ツ)_/¯ ).