Closed ritchie46 closed 1 year ago
Are you using the git repo, instead of std::simd
?
The cast functions are now part of the element traits, e.g. SimdInt::cast
.
Are you using the git repo, instead of std::simd?
No, I pulled in version nightly-2023-07-27
.
So we have this function that is generic over T
and is called with f32
, f64
and all integer types. Is there a trait that combines cast for all those types?
fn nonnull_sum_as_f64<T>(values: &[T]) -> f64
where
T: NativeType + SimdElement + ToPrimitive + SimdCast,
{
// we choose 8 as that the maximum size of f64x8 -> 512bit wide
const LANES: usize = 8;
let (head, simd_vals, tail) = unsafe { values.align_to::<Simd<T, LANES>>() };
let mut reduced: Simd<f64, LANES> = Simd::splat(0.0);
for chunk in simd_vals {
reduced += chunk.cast::<f64>();
}
unsafe {
reduced.reduce_sum()
+ head
.iter()
.map(|v| v.to_f64().unwrap_unchecked())
.sum::<f64>()
+ tail
.iter()
.map(|v| v.to_f64().unwrap_unchecked())
.sum::<f64>()
}
}
Ah, now I understand. There is no longer any generic cast that works for any element type--it's tied to the element. This is because some elements have their own cast semantics (e.g. pointers) and in the future, some element types may not support casts at all.
You may want to implement your own trait to handle this. In the future I expect a community crate to help (I am working on one, but it is not yet published)
You may want to implement your own trait to handle this.
Right, that's what I did in the meantime:
pub trait SimdCastPl<const N: usize>
where
LaneCount<N>: SupportedLaneCount,
{
fn cast_custom<U: SimdCast>(self) -> Simd<U, N>;
}
macro_rules! impl_cast_custom {
($_type:ty) => {
impl<const N: usize> SimdCastPl<N> for Simd<$_type, N>
where
LaneCount<N>: SupportedLaneCount,
{
fn cast_custom<U: SimdCast>(self) -> Simd<U, N> {
self.cast::<U>()
}
}
};
}
impl_cast_custom!(u8);
impl_cast_custom!(u16);
impl_cast_custom!(u32);
impl_cast_custom!(u64);
impl_cast_custom!(i8);
impl_cast_custom!(i16);
impl_cast_custom!(i32);
impl_cast_custom!(i64);
impl_cast_custom!(f32);
impl_cast_custom!(f64);
some element types may not support casts at all.
primitives to primitives remain supported? Or is it all in the open?
That's pretty much how I would do it.
some element types may not support casts at all.
primitives to primitives remain supported? Or is it all in the open?
The existing casts will continue to exist, I meant if we add new supported element types that are more exotic than primitives.
Check. Thanks for the help! :slightly_smiling_face:
350 removed
Simd::cast<U>
.This broke our code upstream and I fail to understand how I now can coerce a
Simd<T, N>
toSimd<f64, N>
?Is there a
cast
function/trait I missed?