use f8::f8;
use std::{hint::black_box, time::Instant};
fn measure(name: &str, len: usize, mut run: impl FnMut()) {
for _ in 0..100 {
run();
}
let iterations = (8_000_000 / len).max(16);
let mut samples = [0.0; 7];
for sample in &mut samples {
let start = Instant::now();
for _ in 0..iterations {
run();
}
*sample = start.elapsed().as_secs_f64() * 1e9 / (iterations * len) as f64;
}
samples.sort_by(f64::total_cmp);
println!("{name:24} {len:8} values: {:8.3} ns/value", samples[3]);
}
fn main() {
println!("Median of seven samples; black-boxed input and output; lower is better.");
println!("simd feature: {}", cfg!(feature = "simd"));
for len in [16, 256, 4096, 1_048_576] {
let mut seed = 0x1234_5678u32;
let input: Vec<f32> = (0..len)
.map(|_| {
seed ^= seed << 13;
seed ^= seed >> 17;
seed ^= seed << 5;
(seed >> 8) as f32 / 16_777_215.0
})
.collect();
let mut packed = vec![f8::ZERO; len];
let mut decoded = vec![0.0f32; len];
measure("encode portable loop", len, || {
for (&x, out) in black_box(&input).iter().zip(&mut packed) {
*out = f8::from_f32(x);
}
black_box(&packed);
});
measure("encode bulk dispatch", len, || {
f8::from_f32_slice(black_box(&input), &mut packed);
black_box(&packed);
});
measure("encode f64 reference", len, || {
for (&x, out) in black_box(&input).iter().zip(&mut packed) {
*out = f8::from_bits((f64::from(x) * 255.0).round_ties_even() as u8);
}
black_box(&packed);
});
measure("decode integer loop", len, || {
for (&x, out) in black_box(&packed).iter().zip(&mut decoded) {
*out = x.to_f32();
}
black_box(&decoded);
});
measure("decode bulk", len, || {
f8::to_f32_slice(black_box(&packed), &mut decoded);
black_box(&decoded);
});
measure("decode division loop", len, || {
for (&x, out) in black_box(&packed).iter().zip(&mut decoded) {
*out = f32::from(x.to_bits()) / 255.0;
}
black_box(&decoded);
});
let rhs: Vec<_> = packed.iter().rev().copied().collect();
let mut product = vec![f8::ZERO; len];
measure("multiply integer loop", len, || {
for ((&a, &b), out) in black_box(&packed)
.iter()
.zip(black_box(&rhs))
.zip(&mut product)
{
*out = a * b;
}
black_box(&product);
});
measure("multiply f64 reference", len, || {
for ((&a, &b), out) in black_box(&packed)
.iter()
.zip(black_box(&rhs))
.zip(&mut product)
{
*out = f8::from_bits(
(f64::from(a.to_bits()) * f64::from(b.to_bits()) / 255.0).round_ties_even()
as u8,
);
}
black_box(&product);
});
}
}