blob: 7f920055477d483c39f19a2674f2d5c3d4e72cd0 [file]
// Copyright 2025 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! A number of SIMD extension traits.
use fearless_simd::*;
/// Splatting every 4th element in the vector, used for splatting the alpha value of
/// a color to all lanes.
pub trait Splat4thExt<S> {
/// Splat every 4th element of the vector.
fn splat_4th(self) -> Self;
}
impl<S: Simd> Splat4thExt<S> for f32x4<S> {
#[inline(always)]
fn splat_4th(self) -> Self {
// TODO: Explore whether it's just faster to manually access the 4th element and splat it.
let zip1 = self.zip_high(self);
zip1.zip_high(zip1)
}
}
impl<S: Simd> Splat4thExt<S> for f32x8<S> {
#[inline(always)]
fn splat_4th(self) -> Self {
let (mut p1, mut p2) = self.simd.split_f32x8(self);
p1 = p1.splat_4th();
p2 = p2.splat_4th();
self.simd.combine_f32x4(p1, p2)
}
}
impl<S: Simd> Splat4thExt<S> for f32x16<S> {
#[inline(always)]
fn splat_4th(self) -> Self {
let (mut p1, mut p2) = self.simd.split_f32x16(self);
p1 = p1.splat_4th();
p2 = p2.splat_4th();
self.simd.combine_f32x8(p1, p2)
}
}
impl<S: Simd> Splat4thExt<S> for u8x16<S> {
#[inline(always)]
fn splat_4th(self) -> Self {
// TODO: SIMDify
Self {
val: [
self.val[3],
self.val[3],
self.val[3],
self.val[3],
self.val[7],
self.val[7],
self.val[7],
self.val[7],
self.val[11],
self.val[11],
self.val[11],
self.val[11],
self.val[15],
self.val[15],
self.val[15],
self.val[15],
],
simd: self.simd,
}
}
}
impl<S: Simd> Splat4thExt<S> for u8x32<S> {
#[inline(always)]
fn splat_4th(self) -> Self {
let (mut p1, mut p2) = self.simd.split_u8x32(self);
p1 = p1.splat_4th();
p2 = p2.splat_4th();
self.simd.combine_u8x16(p1, p2)
}
}
/// Splat each single element in the vector to 4 lanes.
#[inline(always)]
pub fn element_wise_splat<S: Simd>(simd: S, input: f32x4<S>) -> f32x16<S> {
simd.combine_f32x8(
simd.combine_f32x4(
f32x4::splat(simd, input.val[0]),
f32x4::splat(simd, input.val[1]),
),
simd.combine_f32x4(
f32x4::splat(simd, input.val[2]),
f32x4::splat(simd, input.val[3]),
),
)
}