]> git.proxmox.com Git - rustc.git/blob - vendor/packed_simd_2/src/api/slice/from_slice.rs
New upstream version 1.68.2+dfsg1
[rustc.git] / vendor / packed_simd_2 / src / api / slice / from_slice.rs
1 //! Implements methods to read a vector type from a slice.
2
3 macro_rules! impl_slice_from_slice {
4 ([$elem_ty:ident; $elem_count:expr]: $id:ident | $test_tt:tt) => {
5 impl $id {
6 /// Instantiates a new vector with the values of the `slice`.
7 ///
8 /// # Panics
9 ///
10 /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
11 /// to an `align_of::<Self>()` boundary.
12 #[inline]
13 pub fn from_slice_aligned(slice: &[$elem_ty]) -> Self {
14 unsafe {
15 assert!(slice.len() >= $elem_count);
16 let target_ptr = slice.get_unchecked(0) as *const $elem_ty;
17 assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
18 Self::from_slice_aligned_unchecked(slice)
19 }
20 }
21
22 /// Instantiates a new vector with the values of the `slice`.
23 ///
24 /// # Panics
25 ///
26 /// If `slice.len() < Self::lanes()`.
27 #[inline]
28 pub fn from_slice_unaligned(slice: &[$elem_ty]) -> Self {
29 unsafe {
30 assert!(slice.len() >= $elem_count);
31 Self::from_slice_unaligned_unchecked(slice)
32 }
33 }
34
35 /// Instantiates a new vector with the values of the `slice`.
36 ///
37 /// # Safety
38 ///
39 /// If `slice.len() < Self::lanes()` or `&slice[0]` is not aligned
40 /// to an `align_of::<Self>()` boundary, the behavior is undefined.
41 #[inline]
42 pub unsafe fn from_slice_aligned_unchecked(slice: &[$elem_ty]) -> Self {
43 debug_assert!(slice.len() >= $elem_count);
44 let target_ptr = slice.get_unchecked(0) as *const $elem_ty;
45 debug_assert_eq!(target_ptr.align_offset(crate::mem::align_of::<Self>()), 0);
46
47 #[allow(clippy::cast_ptr_alignment)]
48 *(target_ptr as *const Self)
49 }
50
51 /// Instantiates a new vector with the values of the `slice`.
52 ///
53 /// # Safety
54 ///
55 /// If `slice.len() < Self::lanes()` the behavior is undefined.
56 #[inline]
57 pub unsafe fn from_slice_unaligned_unchecked(slice: &[$elem_ty]) -> Self {
58 use crate::mem::size_of;
59 debug_assert!(slice.len() >= $elem_count);
60 let target_ptr = slice.get_unchecked(0) as *const $elem_ty as *const u8;
61 let mut x = Self::splat(0 as $elem_ty);
62 let self_ptr = &mut x as *mut Self as *mut u8;
63 crate::ptr::copy_nonoverlapping(target_ptr, self_ptr, size_of::<Self>());
64 x
65 }
66 }
67
68 test_if! {
69 $test_tt:
70 paste::item! {
71 // Comparisons use integer casts within mantissa^1 range.
72 #[allow(clippy::float_cmp)]
73 pub mod [<$id _slice_from_slice>] {
74 use super::*;
75 use crate::iter::Iterator;
76
77 #[cfg_attr(not(target_arch = "wasm32"), test)]
78 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
79 fn from_slice_unaligned() {
80 let mut unaligned = [42 as $elem_ty; $id::lanes() + 1];
81 unaligned[0] = 0 as $elem_ty;
82 let vec = $id::from_slice_unaligned(&unaligned[1..]);
83 for (index, &b) in unaligned.iter().enumerate() {
84 if index == 0 {
85 assert_eq!(b, 0 as $elem_ty);
86 } else {
87 assert_eq!(b, 42 as $elem_ty);
88 assert_eq!(b, vec.extract(index - 1));
89 }
90 }
91 }
92
93 // FIXME: wasm-bindgen-test does not support #[should_panic]
94 // #[cfg_attr(not(target_arch = "wasm32"), test)]
95 // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
96 #[cfg(not(target_arch = "wasm32"))]
97 #[test]
98 #[should_panic]
99 fn from_slice_unaligned_fail() {
100 let mut unaligned = [42 as $elem_ty; $id::lanes() + 1];
101 unaligned[0] = 0 as $elem_ty;
102 // the slice is not large enough => panic
103 let _vec = $id::from_slice_unaligned(&unaligned[2..]);
104 }
105
106 union A {
107 data: [$elem_ty; 2 * $id::lanes()],
108 _vec: $id,
109 }
110
111 #[cfg_attr(not(target_arch = "wasm32"), test)]
112 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
113 fn from_slice_aligned() {
114 let mut aligned = A {
115 data: [0 as $elem_ty; 2 * $id::lanes()],
116 };
117 for i in $id::lanes()..(2 * $id::lanes()) {
118 unsafe {
119 aligned.data[i] = 42 as $elem_ty;
120 }
121 }
122
123 let vec = unsafe {
124 $id::from_slice_aligned(
125 &aligned.data[$id::lanes()..]
126 )
127 };
128 for (index, &b) in
129 unsafe { aligned.data.iter().enumerate() } {
130 if index < $id::lanes() {
131 assert_eq!(b, 0 as $elem_ty);
132 } else {
133 assert_eq!(b, 42 as $elem_ty);
134 assert_eq!(
135 b, vec.extract(index - $id::lanes())
136 );
137 }
138 }
139 }
140
141 // FIXME: wasm-bindgen-test does not support #[should_panic]
142 // #[cfg_attr(not(target_arch = "wasm32"), test)]
143 // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
144 #[cfg(not(target_arch = "wasm32"))]
145 #[test]
146 #[should_panic]
147 fn from_slice_aligned_fail_lanes() {
148 let aligned = A {
149 data: [0 as $elem_ty; 2 * $id::lanes()],
150 };
151 let _vec = unsafe {
152 $id::from_slice_aligned(
153 &aligned.data[2 * $id::lanes()..]
154 )
155 };
156 }
157
158 // FIXME: wasm-bindgen-test does not support #[should_panic]
159 // #[cfg_attr(not(target_arch = "wasm32"), test)]
160 // #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
161 #[cfg(not(target_arch = "wasm32"))]
162 #[test]
163 #[should_panic]
164 fn from_slice_aligned_fail_align() {
165 unsafe {
166 let aligned = A {
167 data: [0 as $elem_ty; 2 * $id::lanes()],
168 };
169
170 // get a pointer to the front of data
171 let ptr: *const $elem_ty = aligned.data.as_ptr()
172 as *const $elem_ty;
173 // offset pointer by one element
174 let ptr = ptr.wrapping_add(1);
175
176 if ptr.align_offset(
177 crate::mem::align_of::<$id>()
178 ) == 0 {
179 // the pointer is properly aligned, so
180 // from_slice_aligned won't fail here (e.g. this
181 // can happen for i128x1). So we panic to make
182 // the "should_fail" test pass:
183 panic!("ok");
184 }
185
186 // create a slice - this is safe, because the
187 // elements of the slice exist, are properly
188 // initialized, and properly aligned:
189 let s: &[$elem_ty] = slice::from_raw_parts(
190 ptr, $id::lanes()
191 );
192 // this should always panic because the slice
193 // alignment does not match the alignment
194 // requirements for the vector type:
195 let _vec = $id::from_slice_aligned(s);
196 }
197 }
198 }
199 }
200 }
201 };
202 }