]>
Commit | Line | Data |
---|---|---|
83c7162d XL |
1 | //! Minimal portable vector types API. |
2 | #![allow(unused)] | |
0531ce1d XL |
3 | |
4 | /// Minimal interface: all packed SIMD vector types implement this. | |
5 | macro_rules! impl_minimal { | |
6 | ($id:ident, $elem_ty:ident, $elem_count:expr, $($elem_name:ident),+) => { | |
83c7162d | 7 | impl super::api::Lanes<[u32; $elem_count]> for $id {} |
0531ce1d XL |
8 | |
9 | impl $id { | |
10 | /// Creates a new instance with each vector elements initialized | |
11 | /// with the provided values. | |
12 | #[inline] | |
13 | pub const fn new($($elem_name: $elem_ty),*) -> Self { | |
14 | $id($($elem_name),*) | |
15 | } | |
16 | ||
17 | /// Returns the number of vector lanes. | |
18 | #[inline] | |
19 | pub const fn lanes() -> usize { | |
20 | $elem_count | |
21 | } | |
22 | ||
23 | /// Constructs a new instance with each element initialized to | |
24 | /// `value`. | |
25 | #[inline] | |
26 | pub const fn splat(value: $elem_ty) -> Self { | |
27 | $id($({ | |
28 | #[allow(non_camel_case_types, dead_code)] | |
29 | struct $elem_name; | |
30 | value | |
31 | }),*) | |
32 | } | |
33 | ||
34 | /// Extracts the value at `index`. | |
35 | /// | |
36 | /// # Panics | |
37 | /// | |
38 | /// If `index >= Self::lanes()`. | |
39 | #[inline] | |
40 | pub fn extract(self, index: usize) -> $elem_ty { | |
41 | assert!(index < $elem_count); | |
42 | unsafe { self.extract_unchecked(index) } | |
43 | } | |
44 | ||
45 | /// Extracts the value at `index`. | |
46 | /// | |
83c7162d XL |
47 | /// # Precondition |
48 | /// | |
0531ce1d XL |
49 | /// If `index >= Self::lanes()` the behavior is undefined. |
50 | #[inline] | |
51 | pub unsafe fn extract_unchecked(self, index: usize) -> $elem_ty { | |
83c7162d | 52 | use coresimd::simd_llvm::simd_extract; |
0531ce1d XL |
53 | simd_extract(self, index as u32) |
54 | } | |
55 | ||
56 | /// Returns a new vector where the value at `index` is replaced by `new_value`. | |
57 | /// | |
58 | /// # Panics | |
59 | /// | |
60 | /// If `index >= Self::lanes()`. | |
61 | #[inline] | |
62 | #[must_use = "replace does not modify the original value - it returns a new vector with the value at `index` replaced by `new_value`d"] | |
63 | pub fn replace(self, index: usize, new_value: $elem_ty) -> Self { | |
64 | assert!(index < $elem_count); | |
65 | unsafe { self.replace_unchecked(index, new_value) } | |
66 | } | |
67 | ||
68 | /// Returns a new vector where the value at `index` is replaced by `new_value`. | |
69 | /// | |
83c7162d | 70 | /// # Precondition |
0531ce1d | 71 | /// |
83c7162d | 72 | /// If `index >= Self::lanes()` the behavior is undefined. |
0531ce1d XL |
73 | #[inline] |
74 | #[must_use = "replace_unchecked does not modify the original value - it returns a new vector with the value at `index` replaced by `new_value`d"] | |
75 | pub unsafe fn replace_unchecked( | |
76 | self, | |
77 | index: usize, | |
78 | new_value: $elem_ty, | |
79 | ) -> Self { | |
83c7162d | 80 | use coresimd::simd_llvm::simd_insert; |
0531ce1d XL |
81 | simd_insert(self, index as u32, new_value) |
82 | } | |
83 | } | |
84 | } | |
85 | } | |
86 | ||
87 | #[cfg(test)] | |
88 | macro_rules! test_minimal { | |
89 | ($id:ident, $elem_ty:ident, $elem_count:expr) => { | |
90 | #[test] | |
91 | fn minimal() { | |
83c7162d | 92 | use coresimd::simd::$id; |
0531ce1d XL |
93 | // TODO: test new |
94 | ||
95 | // lanes: | |
96 | assert_eq!($elem_count, $id::lanes()); | |
97 | ||
98 | // splat and extract / extract_unchecked: | |
99 | const VAL: $elem_ty = 7 as $elem_ty; | |
100 | const VEC: $id = $id::splat(VAL); | |
101 | for i in 0..$id::lanes() { | |
102 | assert_eq!(VAL, VEC.extract(i)); | |
103 | assert_eq!(VAL, unsafe { VEC.extract_unchecked(i) }); | |
104 | } | |
105 | ||
106 | // replace / replace_unchecked | |
107 | let new_vec = VEC.replace(1, 42 as $elem_ty); | |
108 | for i in 0..$id::lanes() { | |
109 | if i == 1 { | |
110 | assert_eq!(42 as $elem_ty, new_vec.extract(i)); | |
111 | } else { | |
112 | assert_eq!(VAL, new_vec.extract(i)); | |
113 | } | |
114 | } | |
115 | let new_vec = unsafe { VEC.replace_unchecked(1, 42 as $elem_ty) }; | |
116 | for i in 0..$id::lanes() { | |
117 | if i == 1 { | |
118 | assert_eq!(42 as $elem_ty, new_vec.extract(i)); | |
119 | } else { | |
120 | assert_eq!(VAL, new_vec.extract(i)); | |
121 | } | |
122 | } | |
123 | } | |
124 | #[test] | |
125 | #[should_panic] | |
126 | fn minimal_extract_panic_on_out_of_bounds() { | |
83c7162d | 127 | use coresimd::simd::$id; |
0531ce1d XL |
128 | const VAL: $elem_ty = 7 as $elem_ty; |
129 | const VEC: $id = $id::splat(VAL); | |
130 | let _ = VEC.extract($id::lanes()); | |
131 | } | |
132 | #[test] | |
133 | #[should_panic] | |
134 | fn minimal_replace_panic_on_out_of_bounds() { | |
83c7162d | 135 | use coresimd::simd::$id; |
0531ce1d XL |
136 | const VAL: $elem_ty = 7 as $elem_ty; |
137 | const VEC: $id = $id::splat(VAL); | |
138 | let _ = VEC.replace($id::lanes(), 42 as $elem_ty); | |
139 | } | |
83c7162d | 140 | }; |
0531ce1d | 141 | } |