Skip to content

Commit 3df72fd

Browse files
committed
Add masks
1 parent 872e8f6 commit 3df72fd

23 files changed

+433
-108
lines changed

crates/core_simd/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
#![no_std]
22
#![feature(repr_simd)]
33
#![warn(missing_docs)]
4+
//! Portable SIMD module.
45
56
#[macro_use]
67
mod macros;
78

9+
mod masks;
10+
pub use masks::*;
11+
812
mod vectors_u8;
913
pub use vectors_u8::*;
1014
mod vectors_u16;
@@ -17,6 +21,7 @@ mod vectors_u128;
1721
pub use vectors_u128::*;
1822
mod vectors_usize;
1923
pub use vectors_usize::*;
24+
2025
mod vectors_i8;
2126
pub use vectors_i8::*;
2227
mod vectors_i16;
@@ -29,7 +34,21 @@ mod vectors_i128;
2934
pub use vectors_i128::*;
3035
mod vectors_isize;
3136
pub use vectors_isize::*;
37+
3238
mod vectors_f32;
3339
pub use vectors_f32::*;
3440
mod vectors_f64;
3541
pub use vectors_f64::*;
42+
43+
mod vectors_mask8;
44+
pub use vectors_mask8::*;
45+
mod vectors_mask16;
46+
pub use vectors_mask16::*;
47+
mod vectors_mask32;
48+
pub use vectors_mask32::*;
49+
mod vectors_mask64;
50+
pub use vectors_mask64::*;
51+
mod vectors_mask128;
52+
pub use vectors_mask128::*;
53+
mod vectors_masksize;
54+
pub use vectors_masksize::*;

crates/core_simd/src/macros.rs

Lines changed: 173 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/// Provides implementations of `From<$a> for $b` and `From<$b> for $a` that transmutes the value.
12
macro_rules! from_transmute {
23
{ unsafe $a:ty => $b:ty } => {
34
from_transmute!{ @impl $a => $b }
@@ -13,6 +14,8 @@ macro_rules! from_transmute {
1314
};
1415
}
1516

17+
/// Provides implementations of `From<$generic> for core::arch::{x86, x86_64}::$intel` and
18+
/// vice-versa that transmutes the value.
1619
macro_rules! from_transmute_x86 {
1720
{ unsafe $generic:ty => $intel:ident } => {
1821
#[cfg(target_arch = "x86")]
@@ -23,10 +26,118 @@ macro_rules! from_transmute_x86 {
2326
}
2427
}
2528

26-
macro_rules! define_type {
27-
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
28-
define_type! { @impl $(#[$attr])* | $name [$type; $lanes] }
29+
/// Calls a the macro `$mac` with the provided `$args` followed by `$repeat` repeated the specified
30+
/// number of times.
31+
macro_rules! call_repeat {
32+
{ 1 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
33+
$mac! {
34+
$($args)*
35+
$($repeat)*
36+
}
37+
};
38+
{ 2 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
39+
$mac! {
40+
$($args)*
41+
$($repeat)* $($repeat)*
42+
}
43+
};
44+
{ 4 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
45+
$mac! {
46+
$($args)*
47+
$($repeat)* $($repeat)* $($repeat)* $($repeat)*
48+
}
49+
};
50+
{ 8 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
51+
$mac! {
52+
$($args)*
53+
$($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
54+
}
55+
};
56+
{ 16 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
57+
$mac! {
58+
$($args)*
59+
$($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
60+
$($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)* $($repeat)*
61+
}
62+
};
63+
{ 32 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
64+
$mac! {
65+
$($args)*
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)*
70+
}
71+
};
72+
{ 64 => $mac:path [$($repeat:tt)*] $($args:tt)* } => {
73+
$mac! {
74+
$($args)*
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)*
83+
}
84+
};
85+
}
2986

87+
/// Calls the macro `$mac` with the specified `$args` followed by the specified number of unique
88+
/// identifiers.
89+
macro_rules! call_counting_args {
90+
{ 1 => $mac:path => $($args:tt)* } => {
91+
$mac! {
92+
$($args)*
93+
value
94+
}
95+
};
96+
{ 2 => $mac:path => $($args:tt)* } => {
97+
$mac! {
98+
$($args)*
99+
v1 v2
100+
}
101+
};
102+
{ 4 => $mac:path => $($args:tt)* } => {
103+
$mac! {
104+
$($args)*
105+
v0 v1 v2 v3
106+
}
107+
};
108+
{ 8 => $mac:path => $($args:tt)* } => {
109+
$mac! {
110+
$($args)*
111+
v0 v1 v2 v3 v4 v5 v6 v7
112+
}
113+
};
114+
{ 16 => $mac:path => $($args:tt)* } => {
115+
$mac! {
116+
$($args)*
117+
v0 v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12 v13 v14 v15
118+
}
119+
};
120+
{ 32 => $mac:path => $($args:tt)* } => {
121+
$mac! {
122+
$($args)*
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
125+
}
126+
};
127+
{ 64 => $mac:path => $($args:tt)* } => {
128+
$mac! {
129+
$($args)*
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
134+
}
135+
};
136+
}
137+
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] } => {
30141
// array references
31142
impl AsRef<[$type; $lanes]> for $name {
32143
#[inline]
@@ -67,71 +178,78 @@ macro_rules! define_type {
67178
Self::splat(value)
68179
}
69180
}
70-
};
71-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 1] } => {
72-
define_type! { @def $(#[$attr])* | $name | $type | $type, | v0, }
73-
};
74-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 2] } => {
75-
define_type! { @def $(#[$attr])* | $name | $type | $type, $type, | v0, v1, }
76-
};
77-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 4] } => {
78-
define_type! { @def $(#[$attr])* | $name | $type |
79-
$type, $type, $type, $type, |
80-
v0, v1, v2, v3,
181+
}
182+
}
183+
184+
/// Defines a vector `$name` containing multiple `$lanes` of `$type`.
185+
macro_rules! define_vector {
186+
{ $(#[$attr:meta])* struct $name:ident([$type:ty; $lanes:tt]); } => {
187+
call_repeat! { $lanes => define_vector [$type] def $(#[$attr])* | $name | }
188+
189+
impl $name {
190+
call_repeat! { $lanes => define_vector [$type] splat $type | }
191+
call_counting_args! { $lanes => define_vector => new $type | }
81192
}
193+
194+
base_vector_traits! { $name => [$type; $lanes] }
82195
};
83-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 8] } => {
84-
define_type! { @def $(#[$attr])* | $name | $type |
85-
$type, $type, $type, $type, $type, $type, $type, $type, |
86-
v0, v1, v2, v3, v4, v5, v6, v7,
87-
}
196+
{ def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
197+
$(#[$attr])*
198+
#[allow(non_camel_case_types)]
199+
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
200+
#[repr(simd)]
201+
pub struct $name($($itype),*);
88202
};
89-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 16] } => {
90-
define_type! { @def $(#[$attr])* | $name | $type |
91-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
92-
v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
203+
{ splat $type:ty | $($itype:ty)* } => {
204+
/// Construct a vector by setting all lanes to the given value.
205+
#[inline]
206+
pub const fn splat(value: $type) -> Self {
207+
Self($(value as $itype),*)
93208
}
94209
};
95-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 32] } => {
96-
define_type! { @def $(#[$attr])* | $name | $type |
97-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
98-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
99-
v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
100-
v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
210+
{ new $type:ty | $($var:ident)* } => {
211+
/// Construct a vector by setting each lane to the given values.
212+
#[allow(clippy::too_many_arguments)]
213+
#[inline]
214+
pub const fn new($($var: $type),*) -> Self {
215+
Self($($var),*)
101216
}
102-
};
103-
{ @impl $(#[$attr:meta])* | $name:ident [$type:ty; 64] } => {
104-
define_type! { @def $(#[$attr])* | $name | $type |
105-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
106-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
107-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type,
108-
$type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, $type, |
109-
v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15,
110-
v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31,
111-
v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47,
112-
v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63,
217+
}
218+
}
219+
220+
/// Defines a mask vector `$name` containing multiple `$lanes` of `$type`, represented by the
221+
/// underlying type `$impl_type`.
222+
macro_rules! define_mask_vector {
223+
{ $(#[$attr:meta])* struct $name:ident([$impl_type:ty as $type:ty; $lanes:tt]); } => {
224+
call_repeat! { $lanes => define_mask_vector [$impl_type] def $(#[$attr])* | $name | }
225+
226+
impl $name {
227+
call_repeat! { $lanes => define_mask_vector [$impl_type] splat $type | }
228+
call_counting_args! { $lanes => define_mask_vector => new $type | }
113229
}
230+
231+
base_vector_traits! { $name => [$type; $lanes] }
114232
};
115-
{ @def $(#[$attr:meta])* | $name:ident | $type:ty | $($itype:ty,)* | $($ivar:ident,)* } => {
233+
{ def $(#[$attr:meta])* | $name:ident | $($itype:ty)* } => {
116234
$(#[$attr])*
117235
#[allow(non_camel_case_types)]
118236
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd)]
119237
#[repr(simd)]
120238
pub struct $name($($itype),*);
121-
122-
impl $name {
123-
/// Construct a vector by setting all lanes to the given value.
124-
#[inline]
125-
pub const fn splat(value: $type) -> Self {
126-
Self($(value as $itype),*)
127-
}
128-
129-
/// Construct a vector by setting each lane to the given values.
130-
#[allow(clippy::too_many_arguments)]
131-
#[inline]
132-
pub const fn new($($ivar: $itype),*) -> Self {
133-
Self($($ivar),*)
134-
}
239+
};
240+
{ splat $type:ty | $($itype:ty)* } => {
241+
/// Construct a vector by setting all lanes to the given value.
242+
#[inline]
243+
pub const fn splat(value: $type) -> Self {
244+
Self($(value.0 as $itype),*)
245+
}
246+
};
247+
{ new $type:ty | $($var:ident)* } => {
248+
/// Construct a vector by setting each lane to the given values.
249+
#[allow(clippy::too_many_arguments)]
250+
#[inline]
251+
pub const fn new($($var: $type),*) -> Self {
252+
Self($($var.0),*)
135253
}
136254
}
137255
}

crates/core_simd/src/masks.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
macro_rules! define_mask {
2+
{ $(#[$attr:meta])* struct $name:ident($type:ty); } => {
3+
$(#[$attr])*
4+
#[allow(non_camel_case_types)]
5+
#[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Eq, Ord, Hash)]
6+
#[repr(transparent)]
7+
pub struct $name(pub(crate) $type);
8+
9+
impl $name {
10+
/// Construct a mask from the given value.
11+
pub const fn new(value: bool) -> Self {
12+
if value {
13+
Self(!0)
14+
} else {
15+
Self(0)
16+
}
17+
}
18+
19+
/// Test if the mask is set.
20+
pub const fn test(&self) -> bool {
21+
self.0 != 0
22+
}
23+
}
24+
25+
impl core::convert::From<bool> for $name {
26+
fn from(value: bool) -> Self {
27+
Self::new(value)
28+
}
29+
}
30+
31+
impl core::convert::From<$name> for bool {
32+
fn from(mask: $name) -> Self {
33+
mask.test()
34+
}
35+
}
36+
}
37+
}
38+
39+
define_mask! {
40+
#[doc = "8-bit mask"]
41+
struct mask8(i8);
42+
}
43+
44+
define_mask! {
45+
#[doc = "16-bit mask"]
46+
struct mask16(i16);
47+
}
48+
49+
define_mask! {
50+
#[doc = "32-bit mask"]
51+
struct mask32(i32);
52+
}
53+
54+
define_mask! {
55+
#[doc = "64-bit mask"]
56+
struct mask64(i64);
57+
}
58+
59+
define_mask! {
60+
#[doc = "128-bit mask"]
61+
struct mask128(i128);
62+
}
63+
64+
define_mask! {
65+
#[doc = "`isize`-wide mask"]
66+
struct masksize(isize);
67+
}

0 commit comments

Comments
 (0)