1 /// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
2 macro_rules! from_transmute {
3 { unsafe $a:ty => $b:ty } => {
4 from_transmute!{ @impl $a => $b }
5 from_transmute!{ @impl $b => $a }
7 { @impl $from:ty => $to:ty } => {
8 impl core::convert::From<$from> for $to {
10 fn from(value: $from) -> $to {
11 unsafe { core::mem::transmute(value) }
17 /// Provides implementations of `From<$generic> for core::arch::{x86, x86_64}::$intel` and
18 /// vice-versa that transmutes the value.
19 macro_rules! from_transmute_x86 {
20 { unsafe $generic:ty => $intel:ident } => {
21 #[cfg(target_arch = "x86")]
22 from_transmute! { unsafe $generic => core::arch::x86::$intel }
24 #[cfg(target_arch = "x86_64")]
25 from_transmute! { unsafe $generic => core::arch::x86_64::$intel }
29 /// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified
31 macro_rules! call_repeat {
32 { 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
38 { 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
41 $($repeat)* $($repeat)*
44 { 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
47 $($repeat)* $($repeat)* $($repeat)* $($repeat)*
50 { 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
53 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
56 { 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
59 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
60 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
63 { 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
66 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
67 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
68 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
69 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
72 { 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
75 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
76 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
77 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
78 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
79 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
80 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
81 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
82 $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
87 /// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique
89 macro_rules! call_counting_args {
90 { 1 => $mac:path => $($args:tt)* } => {
96 { 2 => $mac:path => $($args:tt)* } => {
102 { 4 => $mac:path => $($args:tt)* } => {
108 { 8 => $mac:path => $($args:tt)* } => {
111 v0 v1 v2 v3 v4 v5 v6 v7
114 { 16 => $mac:path => $($args:tt)* } => {
117 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
120 { 32 => $mac:path => $($args:tt)* } => {
123 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
124 v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
127 { 64 => $mac:path => $($args:tt)* } => {
130 v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
131 v16 v17 v18 v19 v20 v21 v22 v23 v24 v25 v26 v27 v28 v29 v30 v31
132 v32 v33 v34 v35 v36 v37 v38 v39 v40 v41 v42 v43 v44 v45 v46 v47
133 v48 v49 v50 v51 v52 v53 v54 v55 v56 v57 v58 v59 v60 v61 v62 v63
138 /// Implements common traits on the specified vector `$name`, holding multiple `$lanes` of `$type`.
139 macro_rules! base_vector_traits {
140 { $name:path => [$type:ty; $lanes:literal] } => {
141 impl Copy for $name {}
143 impl Clone for $name {
145 fn clone(&self) -> Self {
150 impl Default for $name {
152 fn default() -> Self {
153 Self::splat(<$type>::default())
157 impl PartialEq for $name {
159 fn eq(&self, other: &Self) -> bool {
160 AsRef::<[$type]>::as_ref(self) == AsRef::<[$type]>::as_ref(other)
164 impl PartialOrd for $name {
166 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
167 AsRef::<[$type]>::as_ref(self).partial_cmp(AsRef::<[$type]>::as_ref(other))
172 impl AsRef<[$type; $lanes]> for $name {
174 fn as_ref(&self) -> &[$type; $lanes] {
175 unsafe { &*(self as *const _ as *const _) }
179 impl AsMut<[$type; $lanes]> for $name {
181 fn as_mut(&mut self) -> &mut [$type; $lanes] {
182 unsafe { &mut *(self as *mut _ as *mut _) }
187 impl AsRef<[$type]> for $name {
189 fn as_ref(&self) -> &[$type] {
190 AsRef::<[$type; $lanes]>::as_ref(self)
194 impl AsMut<[$type]> for $name {
196 fn as_mut(&mut self) -> &mut [$type] {
197 AsMut::<[$type; $lanes]>::as_mut(self)
201 // vector/array conversion
202 from_transmute! { unsafe $name => [$type; $lanes] }
205 impl From<$type> for $name {
207 fn from(value: $type) -> Self {
214 /// Implements additional integer traits (Eq, Ord, Hash) on the specified vector `$name`, holding multiple `$lanes` of `$type`.
215 macro_rules! integer_vector_traits {
216 { $name:path => [$type:ty; $lanes:literal] } => {
221 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
222 AsRef::<[$type]>::as_ref(self).cmp(AsRef::<[$type]>::as_ref(other))
226 impl core::hash::Hash for $name {
228 fn hash<H>(&self, state: &mut H)
230 H: core::hash::Hasher
232 AsRef::<[$type]>::as_ref(self).hash(state)
238 /// Defines a vector `$name` containing multiple `$lanes` of `$type`.
239 macro_rules! define_vector {
240 { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
241 call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | }
244 call_repeat! { $lanes => define_vector [$type] splat $type | }
245 call_counting_args! { $lanes => define_vector => new $type | }
248 base_vector_traits! { $name => [$type; $lanes] }
250 { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
252 #[allow(non_camel_case_types)]
254 pub struct $name($($itype),*);
256 { splat $type:ty | $($itype:ty)* } => {
257 /// Construct a vector by setting all lanes to the given value.
259 pub const fn splat(value: $type) -> Self {
260 Self($(value as $itype),*)
263 { new $type:ty | $($var:ident)* } => {
264 /// Construct a vector by setting each lane to the given values.
265 #[allow(clippy::too_many_arguments)]
267 pub const fn new($($var: $type),*) -> Self {
273 /// Implements inherent methods for a float vector `$name` containing multiple
274 /// `$lanes` of float `$type`, which uses `$bits_ty` as its binary
275 /// representation. Called from `define_float_vector!`.
276 macro_rules! impl_float_vector {
277 { $name:path => [$type:ty; $lanes:literal]; bits $bits_ty:ty; } => {
279 /// Raw transmutation to an unsigned integer vector type with the
280 /// same size and number of lanes.
282 pub fn to_bits(self) -> $bits_ty {
283 unsafe { core::mem::transmute(self) }
286 /// Raw transmutation from an unsigned integer vector type with the
287 /// same size and number of lanes.
289 pub fn from_bits(bits: $bits_ty) -> Self {
290 unsafe { core::mem::transmute(bits) }
293 /// Produces a vector where every lane has the absolute value of the
294 /// equivalently-indexed lane in `self`.
296 pub fn abs(self) -> Self {
297 let no_sign = <$bits_ty>::splat(!0 >> 1);
298 Self::from_bits(self.to_bits() & no_sign)
304 /// Defines a float vector `$name` containing multiple `$lanes` of float
305 /// `$type`, which uses `$bits_ty` as its binary representation.
306 macro_rules! define_float_vector {
307 { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); bits $bits_ty:ty; } => {
310 struct $name([$type; $lanes]);
313 impl_float_vector! { $name => [$type; $lanes]; bits $bits_ty; }
317 /// Defines an integer vector `$name` containing multiple `$lanes` of integer `$type`.
318 macro_rules! define_integer_vector {
319 { $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
322 struct $name([$type; $lanes]);
325 integer_vector_traits! { $name => [$type; $lanes] }
329 /// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the
330 /// underlying type `$impl_type`.
331 macro_rules! define_mask_vector {
332 { $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => {
333 call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | }
336 call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | }
337 call_counting_args! { $lanes => define_mask_vector => new $type | }
338 call_counting_args! { $lanes => define_mask_vector => new_from_bool $type | }
341 base_vector_traits! { $name => [$type; $lanes] }
342 integer_vector_traits! { $name => [$type; $lanes] }
344 { def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
346 #[allow(non_camel_case_types)]
348 pub struct $name($($itype),*);
350 { splat $type:ty | $($itype:ty)* } => {
351 /// Construct a vector by setting all lanes to the given value.
353 pub const fn splat(value: $type) -> Self {
354 Self($(value.0 as $itype),*)
357 { new $type:ty | $($var:ident)* } => {
358 /// Construct a vector by setting each lane to the given values.
359 #[allow(clippy::too_many_arguments)]
361 pub const fn new($($var: $type),*) -> Self {
365 { new_from_bool $type:ty | $($var:ident)* } => {
366 /// Used internally (since we can't use the Into trait in `const fn`s)
367 #[allow(clippy::too_many_arguments)]
370 pub(crate) const fn new_from_bool($($var: bool),*) -> Self {
371 Self($(<$type>::new($var).0),*)