Skip to content

Instantly share code, notes, and snippets.

@goertzenator
Created January 28, 2022 17:15
Show Gist options
  • Save goertzenator/9a47f2d1636a4724bf7d8038b5883a34 to your computer and use it in GitHub Desktop.
Save goertzenator/9a47f2d1636a4724bf7d8038b5883a34 to your computer and use it in GitHub Desktop.
use case for simd horizontal traits
use conv::{ValueFrom, ValueInto};
use core_simd::*;
use std::iter::Sum;
use std::ops::{Div, Mul, Sub};
/// Trait wrapper for Simd horizontal_sum()
pub trait HorizontalSum {
type Output;
fn hsum(&self) -> Self::Output;
}
macro_rules! hsum_impl {
($($t:ty)*) => ($(
impl<const LANES: usize> HorizontalSum for Simd<$t, LANES>
where
LaneCount<LANES>: SupportedLaneCount,
{
type Output = $t;
fn hsum(&self) -> Self::Output {
self.horizontal_sum()
}
}
)*)
}
hsum_impl! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize f32 f64 }
/// Compute variance of a slice of Simd types
pub fn var<T, const LANES: usize>(xs: &[Simd<T, LANES>]) -> T
where
T: SimdElement + Div<Output = T> + ValueFrom<usize>,
LaneCount<LANES>: SupportedLaneCount,
Simd<T, LANES>: Sum
+ Sub<Output = Simd<T, LANES>>
+ Mul<Output = Simd<T, LANES>>
+ HorizontalSum<Output = T>,
{
let count: T = (LANES * xs.len()).value_into().unwrap();
let mean = {
let s: Simd<T, LANES> = xs.iter().cloned().sum();
s.hsum() / count
};
let vmean = Simd::<T, LANES>::splat(mean);
let vs: Simd<T, LANES> = xs
.iter()
.map(|x| {
let d: Simd<T, LANES> = *x - vmean;
d * d
})
.sum();
vs.hsum() / count
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment