+/// 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 }
};
}
+/// 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")]
}
}
-macro_rules! define_type {
- { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
- define_type! { @impl $(#[$attr])* | $name [$type; $lanes] }
+/// 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! 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 {
Self::splat(value)
}
}
- };
- { @impl $(#[$attr:meta])* | $name:ident [$type:ty; 1] } => {
- define_type! { @def $(#[$attr])* | $name | $type | $type, | v0, }
- };
- { @impl $(#[$attr:meta])* | $name:ident [$type:ty; 2] } => {
- define_type! { @def $(#[$attr])* | $name | $type | $type, $type, | v0, v1, }
- };
- { @impl $(#[$attr:meta])* | $name:ident [$type:ty; 4] } => {
- define_type! { @def $(#[$attr])* | $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 $(#[$attr:meta])* | $name:ident [$type:ty; 8] } => {
- define_type! { @def $(#[$attr])* | $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 $(#[$attr:meta])* | $name:ident [$type:ty; 16] } => {
- define_type! { @def $(#[$attr])* | $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 $(#[$attr:meta])* | $name:ident [$type:ty; 32] } => {
- define_type! { @def $(#[$attr])* | $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 $(#[$attr:meta])* | $name:ident [$type:ty; 64] } => {
- define_type! { @def $(#[$attr])* | $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] }
};
- { @def $(#[$attr:meta])* | $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 {
- /// Construct a vector by setting all lanes to the given value.
- #[inline]
- pub const fn splat(value: $type) -> Self {
- Self($(value as $itype),*)
- }
-
- /// Construct a vector by setting each lane to the given values.
- #[allow(clippy::too_many_arguments)]
- #[inline]
- pub const 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),*)
}
}
}