5757 self . 0
5858 }
5959
60- /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices.
61- /// If an index is out of bounds, that lane instead selects the value from the "or" vector.
60+ /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
61+ /// Lanes given an out-of-bounds index instead select values from the `or` vector.
62+ ///
63+ /// # Examples
6264 /// ```
6365 /// # #![feature(portable_simd)]
6466 /// # #[cfg(feature = "std")] use core_simd::Simd;
7678 Self :: gather_select ( slice, Mask :: splat ( true ) , idxs, or)
7779 }
7880
79- /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices.
80- /// Out-of-bounds indices instead use the default value for that lane (0).
81+ /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
82+ /// Lanes given an out-of-bounds index instead are set the default value for the type.
83+ ///
84+ /// # Examples
8185 /// ```
8286 /// # #![feature(portable_simd)]
8387 /// # #[cfg(feature = "std")] use core_simd::Simd;
@@ -97,69 +101,82 @@ where
97101 Self :: gather_or ( slice, idxs, Self :: splat ( T :: default ( ) ) )
98102 }
99103
100- /// SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices.
101- /// Out-of-bounds or masked indices instead select the value from the "or" vector.
104+ /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
105+ /// The mask `enable`s all `true` lanes and disables all `false` lanes.
106+ /// If an index is disabled or is out-of-bounds, the lane is selected from the `or` vector.
107+ ///
108+ /// # Examples
102109 /// ```
103110 /// # #![feature(portable_simd)]
104111 /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
105112 /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
106113 /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
107114 /// let idxs = Simd::from_array([9, 3, 0, 5]);
108115 /// let alt = Simd::from_array([-5, -4, -3, -2]);
109- /// let mask = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
116+ /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
110117 ///
111- /// let result = Simd::gather_select(&vec, mask , idxs, alt); // Note the lane that is out-of-bounds.
118+ /// let result = Simd::gather_select(&vec, enable , idxs, alt); // Note the lane that is out-of-bounds.
112119 /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2]));
113120 /// ```
114121 #[ must_use]
115122 #[ inline]
116123 pub fn gather_select (
117124 slice : & [ T ] ,
118- mask : Mask < isize , LANES > ,
125+ enable : Mask < isize , LANES > ,
119126 idxs : Simd < usize , LANES > ,
120127 or : Self ,
121128 ) -> Self {
122- let mask : Mask < isize , LANES > = mask & idxs. lanes_lt ( Simd :: splat ( slice. len ( ) ) ) ;
129+ let enable : Mask < isize , LANES > = enable & idxs. lanes_lt ( Simd :: splat ( slice. len ( ) ) ) ;
123130 // SAFETY: We have masked-off out-of-bounds lanes.
124- unsafe { Self :: gather_select_unchecked ( slice, mask , idxs, or) }
131+ unsafe { Self :: gather_select_unchecked ( slice, enable , idxs, or) }
125132 }
126133
127- /// Unsafe SIMD gather: construct a SIMD vector by reading from a slice, using potentially discontiguous indices.
128- /// Masked indices instead select the value from the "or" vector.
129- /// `gather_select_unchecked` is unsound if any unmasked index is out-of-bounds of the slice.
134+ /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
135+ /// The mask `enable`s all `true` lanes and disables all `false` lanes.
136+ /// If an index is disabled, the lane is selected from the `or` vector.
137+ ///
138+ /// # Safety
139+ ///
140+ /// Calling this function with an `enable`d out-of-bounds index is *[undefined behavior]*
141+ /// even if the resulting value is not used.
142+ ///
143+ /// # Examples
130144 /// ```
131145 /// # #![feature(portable_simd)]
132146 /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
133147 /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
134148 /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
135149 /// let idxs = Simd::from_array([9, 3, 0, 5]);
136150 /// let alt = Simd::from_array([-5, -4, -3, -2]);
137- /// let mask = Mask::from_array([true, true, true, false]); // Note the final mask lane.
151+ /// let enable = Mask::from_array([true, true, true, false]); // Note the final mask lane.
138152 /// // If this mask was used to gather, it would be unsound. Let's fix that.
139- /// let mask = mask & idxs.lanes_lt(Simd::splat(vec.len()));
153+ /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len()));
140154 ///
141155 /// // We have masked the OOB lane, so it's safe to gather now.
142- /// let result = unsafe { Simd::gather_select_unchecked(&vec, mask , idxs, alt) };
156+ /// let result = unsafe { Simd::gather_select_unchecked(&vec, enable , idxs, alt) };
143157 /// assert_eq!(result, Simd::from_array([-5, 13, 10, -2]));
144158 /// ```
159+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
145160 #[ must_use]
146161 #[ inline]
147162 pub unsafe fn gather_select_unchecked (
148163 slice : & [ T ] ,
149- mask : Mask < isize , LANES > ,
164+ enable : Mask < isize , LANES > ,
150165 idxs : Simd < usize , LANES > ,
151166 or : Self ,
152167 ) -> Self {
153168 let base_ptr = crate :: simd:: ptr:: SimdConstPtr :: splat ( slice. as_ptr ( ) ) ;
154169 // Ferris forgive me, I have done pointer arithmetic here.
155170 let ptrs = base_ptr. wrapping_add ( idxs) ;
156171 // SAFETY: The ptrs have been bounds-masked to prevent memory-unsafe reads insha'allah
157- unsafe { intrinsics:: simd_gather ( or, ptrs, mask . to_int ( ) ) }
172+ unsafe { intrinsics:: simd_gather ( or, ptrs, enable . to_int ( ) ) }
158173 }
159174
160- /// SIMD scatter: write a SIMD vector's values into a slice, using potentially discontiguous indices.
161- /// Out-of-bounds indices are not written.
162- /// `scatter` writes "in order", so if an index receives two writes, only the last is guaranteed.
175+ /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`.
176+ /// If two lanes in the scattered vector would write to the same index
177+ /// only the last lane is guaranteed to actually be written.
178+ ///
179+ /// # Examples
163180 /// ```
164181 /// # #![feature(portable_simd)]
165182 /// # #[cfg(feature = "std")] use core_simd::Simd;
@@ -176,58 +193,70 @@ where
176193 self . scatter_select ( slice, Mask :: splat ( true ) , idxs)
177194 }
178195
179- /// SIMD scatter: write a SIMD vector's values into a slice, using potentially discontiguous indices.
180- /// Out-of-bounds or masked indices are not written.
181- /// `scatter_select` writes "in order", so if an index receives two writes, only the last is guaranteed.
196+ /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`.
197+ /// The mask `enable`s all `true` lanes and disables all `false` lanes.
198+ /// If an enabled index is out-of-bounds, the lane is not written.
199+ /// If two enabled lanes in the scattered vector would write to the same index,
200+ /// only the last lane is guaranteed to actually be written.
201+ ///
202+ /// # Examples
182203 /// ```
183204 /// # #![feature(portable_simd)]
184205 /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
185206 /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
186207 /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
187208 /// let idxs = Simd::from_array([9, 3, 0, 0]);
188209 /// let vals = Simd::from_array([-27, 82, -41, 124]);
189- /// let mask = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
210+ /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
190211 ///
191- /// vals.scatter_select(&mut vec, mask , idxs); // index 0's second write is masked, thus omitted.
212+ /// vals.scatter_select(&mut vec, enable , idxs); // index 0's second write is masked, thus omitted.
192213 /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]);
193214 /// ```
194215 #[ inline]
195216 pub fn scatter_select (
196217 self ,
197218 slice : & mut [ T ] ,
198- mask : Mask < isize , LANES > ,
219+ enable : Mask < isize , LANES > ,
199220 idxs : Simd < usize , LANES > ,
200221 ) {
201- let mask : Mask < isize , LANES > = mask & idxs. lanes_lt ( Simd :: splat ( slice. len ( ) ) ) ;
222+ let enable : Mask < isize , LANES > = enable & idxs. lanes_lt ( Simd :: splat ( slice. len ( ) ) ) ;
202223 // SAFETY: We have masked-off out-of-bounds lanes.
203- unsafe { self . scatter_select_unchecked ( slice, mask , idxs) }
224+ unsafe { self . scatter_select_unchecked ( slice, enable , idxs) }
204225 }
205226
206- /// Unsafe SIMD scatter: write a SIMD vector's values into a slice, using potentially discontiguous indices.
207- /// Out-of-bounds or masked indices are not written.
208- /// `scatter_select_unchecked` is unsound if any unmasked index is out of bounds of the slice.
209- /// `scatter_select_unchecked` writes "in order", so if the same index receives two writes, only the last is guaranteed.
227+ /// Writes the values in a SIMD vector to multiple potentially discontiguous indices in `slice`.
228+ /// The mask `enable`s all `true` lanes and disables all `false` lanes.
229+ /// If two enabled lanes in the scattered vector would write to the same index,
230+ /// only the last lane is guaranteed to actually be written.
231+ ///
232+ /// # Safety
233+ ///
234+ /// Calling this function with an enabled out-of-bounds index is *[undefined behavior]*,
235+ /// and may lead to memory corruption.
236+ ///
237+ /// # Examples
210238 /// ```
211239 /// # #![feature(portable_simd)]
212240 /// # #[cfg(feature = "std")] use core_simd::{Simd, Mask};
213241 /// # #[cfg(not(feature = "std"))] use core::simd::{Simd, Mask};
214242 /// let mut vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
215243 /// let idxs = Simd::from_array([9, 3, 0, 0]);
216244 /// let vals = Simd::from_array([-27, 82, -41, 124]);
217- /// let mask = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
245+ /// let enable = Mask::from_array([true, true, true, false]); // Note the mask of the last lane.
218246 /// // If this mask was used to scatter, it would be unsound. Let's fix that.
219- /// let mask = mask & idxs.lanes_lt(Simd::splat(vec.len()));
247+ /// let enable = enable & idxs.lanes_lt(Simd::splat(vec.len()));
220248 ///
221249 /// // We have masked the OOB lane, so it's safe to scatter now.
222- /// unsafe { vals.scatter_select_unchecked(&mut vec, mask , idxs); }
250+ /// unsafe { vals.scatter_select_unchecked(&mut vec, enable , idxs); }
223251 /// // index 0's second write is masked, thus was omitted.
224252 /// assert_eq!(vec, vec![-41, 11, 12, 82, 14, 15, 16, 17, 18]);
225253 /// ```
254+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
226255 #[ inline]
227256 pub unsafe fn scatter_select_unchecked (
228257 self ,
229258 slice : & mut [ T ] ,
230- mask : Mask < isize , LANES > ,
259+ enable : Mask < isize , LANES > ,
231260 idxs : Simd < usize , LANES > ,
232261 ) {
233262 // SAFETY: This block works with *mut T derived from &mut 'a [T],
@@ -237,7 +266,7 @@ where
237266 // to prevent invalidating the raw ptrs while they're live.
238267 // Thus, entering this block requires all values to use being already ready:
239268 // 0. idxs we want to write to, which are used to construct the mask.
240- // 1. mask , which depends on an initial &'a [T] and the idxs.
269+ // 1. enable , which depends on an initial &'a [T] and the idxs.
241270 // 2. actual values to scatter (self).
242271 // 3. &mut [T] which will become our base ptr.
243272 unsafe {
@@ -246,7 +275,7 @@ where
246275 // Ferris forgive me, I have done pointer arithmetic here.
247276 let ptrs = base_ptr. wrapping_add ( idxs) ;
248277 // The ptrs have been bounds-masked to prevent memory-unsafe writes insha'allah
249- intrinsics:: simd_scatter ( self , ptrs, mask . to_int ( ) )
278+ intrinsics:: simd_scatter ( self , ptrs, enable . to_int ( ) )
250279 // Cleared ☢️ *mut T Zone
251280 }
252281 }
0 commit comments