From 9acef5d4bee38f548f178729b91a58a42b31b7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sat, 22 Jun 2024 16:03:53 +0200 Subject: [PATCH] feat: replace the SimdValue::lanes() function by an associated const SimdValue::LANES --- CHANGELOG | 1 + src/scalar/fixed_impl.rs | 6 +----- src/simd/auto_simd_impl.rs | 12 +++++------- src/simd/portable_simd_impl.rs | 30 +++++++++++------------------- src/simd/simd_value.rs | 28 ++++++++++------------------ src/simd/wide_simd_impl.rs | 14 +++----------- 6 files changed, 31 insertions(+), 60 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5656327..c43349d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -7,6 +7,7 @@ traits named `ClosedAddAssign, ClosedMulAssign, etc.` - The `ComplexField` and `SimdComplexField` (and, by extension, `RealField` and `SimdRealField`) traits now depend on the `SupersetOf` trait in addition to `SupersetOf`. +- Replace the `SimdValue::lanes()` function by an associated constant `SimdValue::LANES`. ## Release v0.8.1 (04 Apr. 2023) - Add implementation of `rkyv` serialization/deserialization to the `Wide*` wrapper types. diff --git a/src/scalar/fixed_impl.rs b/src/scalar/fixed_impl.rs index 9f84c82..93734fd 100644 --- a/src/scalar/fixed_impl.rs +++ b/src/scalar/fixed_impl.rs @@ -95,14 +95,10 @@ macro_rules! impl_fixed_type ( impl PrimitiveSimdValue for $FixedI {} impl SimdValue for $FixedI { + const LANES: usize = 1; type Element = Self; type SimdBool = bool; - #[inline(always)] - fn lanes() -> usize { - 1 - } - #[inline(always)] fn splat(val: Self::Element) -> Self { val diff --git a/src/simd/auto_simd_impl.rs b/src/simd/auto_simd_impl.rs index 659530b..1da962f 100644 --- a/src/simd/auto_simd_impl.rs +++ b/src/simd/auto_simd_impl.rs @@ -219,7 +219,7 @@ macro_rules! impl_scalar_subset_of_simd ( fn is_in_subset(c: &AutoSimd) -> bool { let elt0 = c.extract(0); elt0.is_in_subset() && - (1..AutoSimd::::lanes()).all(|i| c.extract(i) == elt0) + (1..AutoSimd::::LANES).all(|i| c.extract(i) == elt0) } } )*} @@ -265,13 +265,14 @@ macro_rules! impl_simd_value ( impl fmt::Display for AutoSimd<$t> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if Self::lanes() == 1 { + if Self::LANES == 1 { return self.extract(0).fmt(f); } write!(f, "({}", self.extract(0))?; - for i in 1..Self::lanes() { + #[allow(clippy::reversed_empty_ranges)] // Needed for LANES == 1 that’s in a different code path. + for i in 1..Self::LANES { write!(f, ", {}", self.extract(i))?; } @@ -288,13 +289,10 @@ macro_rules! impl_simd_value ( impl PrimitiveSimdValue for AutoSimd<$t> {} impl SimdValue for AutoSimd<$t> { + const LANES: usize = $lanes; type Element = $elt; type SimdBool = $bool; - #[inline(always)] - fn lanes() -> usize { - $lanes - } #[inline(always)] fn splat(val: Self::Element) -> Self { diff --git a/src/simd/portable_simd_impl.rs b/src/simd/portable_simd_impl.rs index e529cc6..8e73da7 100644 --- a/src/simd/portable_simd_impl.rs +++ b/src/simd/portable_simd_impl.rs @@ -52,13 +52,13 @@ macro_rules! impl_bool_simd ( ($($t: ty, $lanes: literal, $($i: ident),*;)*) => {$( impl fmt::Display for Simd<$t> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if Self::lanes() == 1 { + if Self::LANES == 1 { return self.extract(0).fmt(f); } write!(f, "({}", self.extract(0))?; - for i in 1..Self::lanes() { + for i in 1..Self::LANES { write!(f, ", {}", self.extract(i))?; } @@ -76,14 +76,10 @@ macro_rules! impl_bool_simd ( impl PrimitiveSimdValue for Simd<$t> {} impl SimdValue for Simd<$t> { + const LANES: usize = $lanes; type Element = bool; type SimdBool = Simd<$t>; - #[inline(always)] - fn lanes() -> usize { - $lanes - } - #[inline(always)] fn splat(val: Self::Element) -> Self { Simd(<$t>::splat(val)) @@ -263,7 +259,7 @@ macro_rules! impl_scalar_subset_of_simd ( fn is_in_subset(c: &Simd) -> bool { let elt0 = c.extract(0); elt0.is_in_subset() && - (1..Simd::::lanes()).all(|i| c.extract(i) == elt0) + (1..Simd::::LANES).all(|i| c.extract(i) == elt0) } } )*} @@ -277,13 +273,13 @@ macro_rules! impl_simd_value ( ($($t: ty, $elt: ty, $bool: ty, $($i: ident),*;)*) => ($( impl fmt::Display for Simd<$t> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if Self::lanes() == 1 { + if Self::LANES == 1 { return self.extract(0).fmt(f); } write!(f, "({}", self.extract(0))?; - for i in 1..Self::lanes() { + for i in 1..Self::LANES { write!(f, ", {}", self.extract(i))?; } @@ -301,14 +297,10 @@ macro_rules! impl_simd_value ( impl PrimitiveSimdValue for Simd<$t> {} impl SimdValue for Simd<$t> { + const LANES: usize = <$t>::LEN; type Element = $elt; type SimdBool = $bool; - #[inline(always)] - fn lanes() -> usize { - <$t>::LEN - } - #[inline(always)] fn splat(val: Self::Element) -> Self { Simd(<$t>::splat(val)) @@ -351,7 +343,7 @@ macro_rules! impl_uint_simd ( /// /// # Panics /// - /// If `slice.len() < Self::lanes()`. + /// If `slice.len() < Self::LANES`. #[inline] pub fn from_slice_unaligned(slice: &[$elt]) -> Self { Simd(<$t>::from_slice(slice)) @@ -1075,7 +1067,7 @@ macro_rules! impl_float_simd ( #[inline(always)] fn simd_horizontal_product(self) -> Self::Element { let mut prod = self.extract(0); - for ii in 1..Self::lanes() { + for ii in 1..Self::LANES { prod *= self.extract(ii) } prod @@ -1589,9 +1581,9 @@ impl_bool_simd!( // //macro_rules! impl_simd_complex_from( // ($($t: ty, $elt: ty $(, $i: expr)*;)*) => ($( -// impl From<[num_complex::Complex<$elt>; <$t>::lanes()]> for num_complex::Complex> { +// impl From<[num_complex::Complex<$elt>; <$t>::LANES]> for num_complex::Complex> { // #[inline(always)] -// fn from(vals: [num_complex::Complex<$elt>; <$t>::lanes()]) -> Self { +// fn from(vals: [num_complex::Complex<$elt>; <$t>::LANES]) -> Self { // num_complex::Complex { // re: <$t>::from([$(vals[$i].re),*]), // im: <$t>::from([$(vals[$i].im),*]), diff --git a/src/simd/simd_value.rs b/src/simd/simd_value.rs index dd29ec8..f74c00f 100644 --- a/src/simd/simd_value.rs +++ b/src/simd/simd_value.rs @@ -2,32 +2,32 @@ use crate::simd::SimdBool; /// Base trait for every SIMD types. pub trait SimdValue: Sized { + /// The number of lanes of this SIMD value. + const LANES: usize; /// The type of the elements of each lane of this SIMD value. type Element: SimdValue; /// Type of the result of comparing two SIMD values like `self`. type SimdBool: SimdBool; - /// The number of lanes of this SIMD value. - fn lanes() -> usize; /// Initializes an SIMD value with each lanes set to `val`. fn splat(val: Self::Element) -> Self; /// Extracts the i-th lane of `self`. /// - /// Panics if `i >= Self::lanes()`. + /// Panics if `i >= Self::LANES`. fn extract(&self, i: usize) -> Self::Element; /// Extracts the i-th lane of `self` without bound-checking. /// /// # Safety - /// Undefined behavior if `i >= Self::lanes()`. + /// Undefined behavior if `i >= Self::LANES`. unsafe fn extract_unchecked(&self, i: usize) -> Self::Element; /// Replaces the i-th lane of `self` by `val`. /// - /// Panics if `i >= Self::lanes()`. + /// Panics if `i >= Self::LANES`. fn replace(&mut self, i: usize, val: Self::Element); /// Replaces the i-th lane of `self` by `val` without bound-checking. /// /// # Safety - /// Undefined behavior if `i >= Self::lanes()`. + /// Undefined behavior if `i >= Self::LANES`. unsafe fn replace_unchecked(&mut self, i: usize, val: Self::Element); /// Merges `self` and `other` depending on the lanes of `cond`. @@ -48,7 +48,7 @@ pub trait SimdValue: Sized { { let mut result = self.clone(); - for i in 0..Self::lanes() { + for i in 0..Self::LANES { unsafe { result.replace_unchecked(i, f(self.extract_unchecked(i))) } } @@ -71,7 +71,7 @@ pub trait SimdValue: Sized { { let mut result = self.clone(); - for i in 0..Self::lanes() { + for i in 0..Self::LANES { unsafe { let a = self.extract_unchecked(i); let b = b.extract_unchecked(i); @@ -92,14 +92,10 @@ pub trait SimdValue: Sized { pub trait PrimitiveSimdValue: Copy + SimdValue {} impl SimdValue for num_complex::Complex { + const LANES: usize = N::LANES; type Element = num_complex::Complex; type SimdBool = N::SimdBool; - #[inline(always)] - fn lanes() -> usize { - N::lanes() - } - #[inline(always)] fn splat(val: Self::Element) -> Self { num_complex::Complex { @@ -151,14 +147,10 @@ macro_rules! impl_primitive_simd_value_for_scalar ( ($($t: ty),*) => {$( impl PrimitiveSimdValue for $t {} impl SimdValue for $t { + const LANES: usize = 1; type Element = $t; type SimdBool = bool; - #[inline(always)] - fn lanes() -> usize { - 1 - } - #[inline(always)] fn splat(val: Self::Element) -> Self { val diff --git a/src/simd/wide_simd_impl.rs b/src/simd/wide_simd_impl.rs index 7c201a6..427a0c4 100644 --- a/src/simd/wide_simd_impl.rs +++ b/src/simd/wide_simd_impl.rs @@ -153,14 +153,10 @@ macro_rules! impl_wide_f32 ( } impl SimdValue for $WideF32xX { + const LANES: usize = $lanes; type Element = $f32; type SimdBool = $WideBoolF32xX; - #[inline(always)] - fn lanes() -> usize { - $lanes - } - #[inline(always)] fn splat(val: Self::Element) -> Self { $WideF32xX(wide::$f32xX::from(val)) @@ -197,14 +193,10 @@ macro_rules! impl_wide_f32 ( } impl SimdValue for $WideBoolF32xX { + const LANES: usize = $lanes; type Element = bool; type SimdBool = Self; - #[inline(always)] - fn lanes() -> usize { - $lanes - } - #[inline(always)] fn splat(val: bool) -> Self { let results = [ @@ -1090,7 +1082,7 @@ macro_rules! impl_wide_f32 ( #[inline(always)] fn simd_horizontal_product(self) -> Self::Element { let mut prod = self.extract(0); - for ii in 1..Self::lanes() { + for ii in 1..Self::LANES { prod *= self.extract(ii) } prod