}
}
-/// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified
-/// number of times.
-macro_rules! call_repeat {
- { 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)*
- }
- };
- { 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)*
- }
- };
- { 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- }
- };
- { 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- }
- };
- { 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- }
- };
- { 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- }
- };
- { 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
- $mac! {
- $($args)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
- }
- };
-}
-
-/// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique
-/// identifiers.
-macro_rules! call_counting_args {
- { 1 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- value
- }
- };
- { 2 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1
- }
- };
- { 4 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1 v2 v3
- }
- };
- { 8 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1 v2 v3 v4 v5 v6 v7
- }
- };
- { 16 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
- }
- };
- { 32 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
- v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
- }
- };
- { 64 => $mac:path => $($args:tt)* } => {
- $mac! {
- $($args)*
- v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
- v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
- v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 v42 v43 v44 v45 v46 v47
- v48 v49 v50 v51 v52 v53 v54 v55 v56 v57 v58 v59 v60 v61 v62 v63
- }
- };
-}
-
/// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! impl_vector {
{ $name:ident, $type:ty } => {
- impl<const LANES: usize> $name<LANES> {
- /// Construct a vector by setting all lanes to the given value.
+ impl<const LANES: usize> $name<LANES> where Self: crate::LanesAtMost64 {
+ /// Construct a SIMD vector by setting all lanes to the given value.
pub const fn splat(value: $type) -> Self {
Self([value; LANES])
}
+ /// Returns a slice containing the entire SIMD vector.
pub const fn as_slice(&self) -> &[$type] {
&self.0
}
+ /// Returns a mutable slice containing the entire SIMD vector.
pub fn as_mut_slice(&mut self) -> &mut [$type] {
&mut self.0
}
- pub const fn as_ptr(&self) -> *const $type {
- self.0.as_ptr()
- }
-
- pub fn as_mut_ptr(&mut self) -> *mut $type {
- self.0.as_mut_ptr()
- }
-
+ /// Converts an array to a SIMD vector.
pub const fn from_array(array: [$type; LANES]) -> Self {
Self(array)
}
+ /// Converts a SIMD vector to an array.
pub const fn to_array(self) -> [$type; LANES] {
- self.0
+ // workaround for rust-lang/rust#80108
+ // TODO fix this
+ #[cfg(target_arch = "wasm32")]
+ {
+ let mut arr = [self.0[0]; LANES];
+ let mut i = 0;
+ while i < LANES {
+ arr[i] = self.0[i];
+ i += 1;
+ }
+ arr
+ }
+
+ #[cfg(not(target_arch = "wasm32"))]
+ {
+ self.0
+ }
}
}
- impl<const LANES: usize> Copy for $name<LANES> {}
+ impl<const LANES: usize> Copy for $name<LANES> where Self: crate::LanesAtMost64 {}
- impl<const LANES: usize> Clone for $name<LANES> {
+ impl<const LANES: usize> Clone for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn clone(&self) -> Self {
*self
}
}
- impl<const LANES: usize> Default for $name<LANES> {
+ impl<const LANES: usize> Default for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn default() -> Self {
Self::splat(<$type>::default())
}
}
- impl<const LANES: usize> PartialEq for $name<LANES> {
+ impl<const LANES: usize> PartialEq for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn eq(&self, other: &Self) -> bool {
// TODO use SIMD equality
}
}
- impl<const LANES: usize> PartialOrd for $name<LANES> {
+ impl<const LANES: usize> PartialOrd for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
// TODO use SIMD equalitya
}
// array references
- impl<const LANES: usize> AsRef<[$type; LANES]> for $name<LANES> {
+ impl<const LANES: usize> AsRef<[$type; LANES]> for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn as_ref(&self) -> &[$type; LANES] {
&self.0
}
}
- impl<const LANES: usize> AsMut<[$type; LANES]> for $name<LANES> {
+ impl<const LANES: usize> AsMut<[$type; LANES]> for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn as_mut(&mut self) -> &mut [$type; LANES] {
&mut self.0
}
// slice references
- impl<const LANES: usize> AsRef<[$type]> for $name<LANES> {
+ impl<const LANES: usize> AsRef<[$type]> for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn as_ref(&self) -> &[$type] {
&self.0
}
}
- impl<const LANES: usize> AsMut<[$type]> for $name<LANES> {
+ impl<const LANES: usize> AsMut<[$type]> for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn as_mut(&mut self) -> &mut [$type] {
&mut self.0
}
// vector/array conversion
- impl<const LANES: usize> From<[$type; LANES]> for $name<LANES> {
+ impl<const LANES: usize> From<[$type; LANES]> for $name<LANES> where Self: crate::LanesAtMost64 {
fn from(array: [$type; LANES]) -> Self {
Self(array)
}
}
// splat
- impl<const LANES: usize> From<$type> for $name<LANES> {
+ impl<const LANES: usize> From<$type> for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn from(value: $type) -> Self {
Self::splat(value)
}
}
+
+ impl_shuffle_2pow_lanes!{ $name }
}
}
/// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`.
macro_rules! impl_integer_vector {
- { $name:path, $type:ty } => {
+ { $name:ident, $type:ty } => {
impl_vector! { $name, $type }
- impl<const LANES: usize> Eq for $name<LANES> {}
+ impl<const LANES: usize> Eq for $name<LANES> where Self: crate::LanesAtMost64 {}
- impl<const LANES: usize> Ord for $name<LANES> {
+ impl<const LANES: usize> Ord for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
// TODO use SIMD cmp
}
}
- impl<const LANES: usize> core::hash::Hash for $name<LANES> {
+ impl<const LANES: usize> core::hash::Hash for $name<LANES> where Self: crate::LanesAtMost64 {
#[inline]
fn hash<H>(&self, state: &mut H)
where
/// `$lanes` of float `$type`, which uses `$bits_ty` as its binary
/// representation. Called from `define_float_vector!`.
macro_rules! impl_float_vector {
- { $name:path => [$type:ty; $lanes:literal]; bits $bits_ty:ty; } => {
- impl $name {
-// /// Raw transmutation to an unsigned integer vector type with the
-// /// same size and number of lanes.
-// #[inline]
-// pub fn to_bits(self) -> $bits_ty {
-// unsafe { core::mem::transmute(self) }
-// }
-//
-// /// Raw transmutation from an unsigned integer vector type with the
-// /// same size and number of lanes.
-// #[inline]
-// pub fn from_bits(bits: $bits_ty) -> Self {
-// unsafe { core::mem::transmute(bits) }
-// }
-//
-// /// Produces a vector where every lane has the absolute value of the
-// /// equivalently-indexed lane in `self`.
-// #[inline]
-// pub fn abs(self) -> Self {
-// let no_sign = <$bits_ty>::splat(!0 >> 1);
-// Self::from_bits(self.to_bits() & no_sign)
-// }
+ { $name:ident, $type:ty, $bits_ty:ident } => {
+ impl_vector! { $name, $type }
+
+ impl<const LANES: usize> $name<LANES>
+ where
+ Self: crate::LanesAtMost64,
+ crate::$bits_ty<LANES>: crate::LanesAtMost64,
+ {
+ /// Raw transmutation to an unsigned integer vector type with the
+ /// same size and number of lanes.
+ #[inline]
+ pub fn to_bits(self) -> crate::$bits_ty<LANES> {
+ assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<crate::$bits_ty<LANES>>());
+ unsafe { core::mem::transmute_copy(&self) }
+ }
+
+ /// Raw transmutation from an unsigned integer vector type with the
+ /// same size and number of lanes.
+ #[inline]
+ pub fn from_bits(bits: crate::$bits_ty<LANES>) -> Self {
+ assert_eq!(core::mem::size_of::<Self>(), core::mem::size_of::<crate::$bits_ty<LANES>>());
+ unsafe { core::mem::transmute_copy(&bits) }
+ }
+
+ /// Produces a vector where every lane has the absolute value of the
+ /// equivalently-indexed lane in `self`.
+ #[inline]
+ pub fn abs(self) -> Self {
+ let no_sign = crate::$bits_ty::splat(!0 >> 1);
+ Self::from_bits(self.to_bits() & no_sign)
+ }
}
};
}