-macro_rules! from_aligned {
- { unsafe $from:ty => $to:ty } => {
+/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
+macro_rules! from_transmute {
+ { unsafe $a:ty => $b:ty } => {
+ from_transmute!{ @impl $a => $b }
+ from_transmute!{ @impl $b => $a }
+ };
+ { @impl $from:ty => $to:ty } => {
impl core::convert::From<$from> for $to {
#[inline]
fn from(value: $from) -> $to {
- assert_eq!(core::mem::size_of::<$from>(), core::mem::size_of::<$to>());
- assert!(core::mem::align_of::<$from>() >= core::mem::align_of::<$to>());
unsafe { core::mem::transmute(value) }
}
}
};
- { unsafe $a:ty |bidirectional| $b:ty } => {
- from_aligned!{ unsafe $a => $b }
- from_aligned!{ unsafe $b => $a }
+}
+
+/// Provides implementations of `From<$generic> for core::arch::{x86, x86_64}::$intel` and
+/// vice-versa that transmutes the value.
+macro_rules! from_transmute_x86 {
+ { unsafe $generic:ty => $intel:ident } => {
+ #[cfg(target_arch = "x86")]
+ from_transmute! { unsafe $generic => core::arch::x86::$intel }
+
+ #[cfg(target_arch = "x86_64")]
+ from_transmute! { unsafe $generic => core::arch::x86_64::$intel }
}
}
-macro_rules! from_unaligned {
- { unsafe $from:ty => $to:ty } => {
- impl core::convert::From<$from> for $to {
- #[inline]
- fn from(value: $from) -> $to {
- assert_eq!(core::mem::size_of::<$from>(), core::mem::size_of::<$to>());
- unsafe { (&value as *const $from as *const $to).read_unaligned() }
- }
+/// 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
+ }
+ };
}
-macro_rules! define_type {
- { struct $name:ident([$type:ty; $lanes:tt]); } => {
- define_type! { @impl $name [$type; $lanes] }
+/// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`.
+macro_rules! base_vector_traits {
+ { $name:path => [$type:ty; $lanes:literal] } => {
+ impl Copy for $name {}
+
+ impl Clone for $name {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
+
+ impl Default for $name {
+ fn default() -> Self {
+ Self::splat(<$type>::default())
+ }
+ }
+
+ impl PartialEq for $name {
+ fn eq(&self, other: &Self) -> bool {
+ AsRef::<[$type]>::as_ref(self) == AsRef::<[$type]>::as_ref(other)
+ }
+ }
+
+ impl PartialOrd for $name {
+ fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
+ AsRef::<[$type]>::as_ref(self).partial_cmp(AsRef::<[$type]>::as_ref(other))
+ }
+ }
// array references
impl AsRef<[$type; $lanes]> for $name {
}
}
- // vector to array
- from_aligned! { unsafe $name => [$type; $lanes] }
-
- // array to vector
- from_unaligned! { unsafe [$type; $lanes] => $name }
+ // vector/array conversion
+ from_transmute! { unsafe $name => [$type; $lanes] }
// splat
impl From<$type> for $name {
+ #[inline]
fn from(value: $type) -> Self {
Self::splat(value)
}
}
- };
- { @impl $name:ident [$type:ty; 1] } => {
- define_type! { @impl $name | $type | $type, | v0, }
- };
- { @impl $name:ident [$type:ty; 2] } => {
- define_type! { @impl $name | $type | $type, $type, | v0, v1, }
- };
- { @impl $name:ident [$type:ty; 4] } => {
- define_type! { @impl $name | $type |
- $type, $type, $type, $type, |
- v0, v1, v2, v3,
+ }
+}
+
+/// Defines a vector `$name` containing multiple `$lanes` of `$type`.
+macro_rules! define_vector {
+ { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
+ call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | }
+
+ impl $name {
+ call_repeat! { $lanes => define_vector [$type] splat $type | }
+ call_counting_args! { $lanes => define_vector => new $type | }
}
+
+ base_vector_traits! { $name => [$type; $lanes] }
};
- { @impl $name:ident [$type:ty; 8] } => {
- define_type! { @impl $name | $type |
- $type, $type, $type, $type, $type, $type, $type, $type, |
- v0, v1, v2, v3, v4, v5, v6, v7,
- }
+ { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
+ $(#[$attr])*
+ #[allow(non_camel_case_types)]
+ #[repr(simd)]
+ pub struct $name($($itype),*);
};
- { @impl $name:ident [$type:ty; 16] } => {
- define_type! { @impl $name | $type |
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
- v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
+ { splat $type:ty | $($itype:ty)* } => {
+ /// Construct a vector by setting all lanes to the given value.
+ #[inline]
+ pub const fn splat(value: $type) -> Self {
+ Self($(value as $itype),*)
}
};
- { @impl $name:ident [$type:ty; 32] } => {
- define_type! { @impl $name | $type |
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
- 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,
+ { new $type:ty | $($var:ident)* } => {
+ /// Construct a vector by setting each lane to the given values.
+ #[allow(clippy::too_many_arguments)]
+ #[inline]
+ pub const fn new($($var: $type),*) -> Self {
+ Self($($var),*)
}
- };
- { @impl $name:ident [$type:ty; 64] } => {
- define_type! { @impl $name | $type |
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
- $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
- 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,
+ }
+}
+
+/// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the
+/// underlying type `$impl_type`.
+macro_rules! define_mask_vector {
+ { $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => {
+ call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | }
+
+ impl $name {
+ call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | }
+ call_counting_args! { $lanes => define_mask_vector => new $type | }
}
+
+ base_vector_traits! { $name => [$type; $lanes] }
};
- { @impl $name:ident | $type:ty | $($itype:ty,)* | $($ivar:ident,)* } => {
+ { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
+ $(#[$attr])*
#[allow(non_camel_case_types)]
- #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
+ #[derive(Eq, Ord)]
#[repr(simd)]
pub struct $name($($itype),*);
-
- impl $name {
- #[inline]
- pub fn splat(value: $type) -> Self {
- Self($(value as $itype),*)
- }
-
- #[allow(clippy::too_many_arguments)]
- #[inline]
- pub fn new($($ivar: $itype),*) -> Self {
- Self($($ivar),*)
- }
+ };
+ { splat $type:ty | $($itype:ty)* } => {
+ /// Construct a vector by setting all lanes to the given value.
+ #[inline]
+ pub const fn splat(value: $type) -> Self {
+ Self($(value.0 as $itype),*)
+ }
+ };
+ { new $type:ty | $($var:ident)* } => {
+ /// Construct a vector by setting each lane to the given values.
+ #[allow(clippy::too_many_arguments)]
+ #[inline]
+ pub const fn new($($var: $type),*) -> Self {
+ Self($($var.0),*)
}
}
}