@@ -314,6 +314,131 @@ where
314314 unsafe { self . store ( slice. as_mut_ptr ( ) . cast ( ) ) }
315315 }
316316
317+ /// Reads contiguous elements from `slice`. Elements are read so long as they're in-bounds for
318+ /// the `slice`. Otherwise, the default value for the element type is returned.
319+ ///
320+ /// # Examples
321+ /// ```
322+ /// # #![feature(portable_simd)]
323+ /// # use core::simd::{Simd, Mask};
324+ /// let vec: Vec<i32> = vec![10, 11];
325+ ///
326+ /// let result = Simd::<i32, 4>::load_or_default(&vec);
327+ /// assert_eq!(result, Simd::from_array([10, 11, 0, 0]));
328+ /// ```
329+ #[ must_use]
330+ #[ inline]
331+ pub fn load_or_default ( slice : & [ T ] ) -> Self
332+ where
333+ T : Default ,
334+ {
335+ Self :: load_or ( slice, Default :: default ( ) )
336+ }
337+
338+ /// Reads contiguous elements from `slice`. Elements are read so long as they're in-bounds for
339+ /// the `slice`. Otherwise, the corresponding value from `or` is passed through.
340+ ///
341+ /// # Examples
342+ /// ```
343+ /// # #![feature(portable_simd)]
344+ /// # use core::simd::{Simd, Mask};
345+ /// let vec: Vec<i32> = vec![10, 11];
346+ /// let or = Simd::from_array([-5, -4, -3, -2]);
347+ ///
348+ /// let result = Simd::load_or(&vec, or);
349+ /// assert_eq!(result, Simd::from_array([10, 11, -3, -2]));
350+ /// ```
351+ #[ must_use]
352+ #[ inline]
353+ pub fn load_or ( slice : & [ T ] , or : Self ) -> Self {
354+ Self :: load_select ( slice, Mask :: splat ( true ) , or)
355+ }
356+
357+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
358+ /// corresponding lane in `enable` is `true`.
359+ ///
360+ /// When the lane is disabled or out of bounds for the slice, that memory location
361+ /// is not accessed and the corresponding value from `or` is passed through.
362+ ///
363+ /// # Examples
364+ /// ```
365+ /// # #![feature(portable_simd)]
366+ /// # use core::simd::{Simd, Mask};
367+ /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
368+ /// let enable = Mask::from_array([true, true, false, true]);
369+ /// let or = Simd::from_array([-5, -4, -3, -2]);
370+ ///
371+ /// let result = Simd::load_select(&vec, enable, or);
372+ /// assert_eq!(result, Simd::from_array([10, 11, -3, 14]));
373+ /// ```
374+ #[ must_use]
375+ #[ inline]
376+ pub fn load_select_or_default ( slice : & [ T ] , enable : Mask < <T as SimdElement >:: Mask , N > ) -> Self
377+ where
378+ T : Default ,
379+ {
380+ Self :: load_select ( slice, enable, Default :: default ( ) )
381+ }
382+
383+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
384+ /// corresponding lane in `enable` is `true`.
385+ ///
386+ /// When the lane is disabled or out of bounds for the slice, that memory location
387+ /// is not accessed and the corresponding value from `or` is passed through.
388+ ///
389+ /// # Examples
390+ /// ```
391+ /// # #![feature(portable_simd)]
392+ /// # use core::simd::{Simd, Mask};
393+ /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
394+ /// let enable = Mask::from_array([true, true, false, true]);
395+ /// let or = Simd::from_array([-5, -4, -3, -2]);
396+ ///
397+ /// let result = Simd::load_select(&vec, enable, or);
398+ /// assert_eq!(result, Simd::from_array([10, 11, -3, 14]));
399+ /// ```
400+ #[ must_use]
401+ #[ inline]
402+ pub fn load_select (
403+ slice : & [ T ] ,
404+ mut enable : Mask < <T as SimdElement >:: Mask , N > ,
405+ or : Self ,
406+ ) -> Self {
407+ enable &= mask_up_to ( enable, slice. len ( ) ) ;
408+ unsafe { Self :: load_select_ptr ( slice. as_ptr ( ) , enable, or) }
409+ }
410+
411+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
412+ /// corresponding lane in `enable` is `true`.
413+ ///
414+ /// When the lane is disabled, that memory location is not accessed and the corresponding
415+ /// value from `or` is passed through.
416+ #[ must_use]
417+ #[ inline]
418+ pub unsafe fn load_select_unchecked (
419+ slice : & [ T ] ,
420+ enable : Mask < <T as SimdElement >:: Mask , N > ,
421+ or : Self ,
422+ ) -> Self {
423+ let ptr = slice. as_ptr ( ) ;
424+ unsafe { Self :: load_select_ptr ( ptr, enable, or) }
425+ }
426+
427+ /// Reads contiguous elements starting at `ptr`. Each lane is read from memory if its
428+ /// corresponding lane in `enable` is `true`.
429+ ///
430+ /// When the lane is disabled, that memory location is not accessed and the corresponding
431+ /// value from `or` is passed through.
432+ #[ must_use]
433+ #[ inline]
434+ pub unsafe fn load_select_ptr (
435+ ptr : * const T ,
436+ enable : Mask < <T as SimdElement >:: Mask , N > ,
437+ or : Self ,
438+ ) -> Self {
439+ unsafe { core:: intrinsics:: simd:: simd_masked_load ( enable. to_int ( ) , ptr, or) }
440+ }
441+
317442 /// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
318443 /// If an index is out-of-bounds, the element is instead selected from the `or` vector.
319444 ///
@@ -492,6 +617,27 @@ where
492617 unsafe { core:: intrinsics:: simd:: simd_gather ( or, source, enable. to_int ( ) ) }
493618 }
494619
620+ #[ inline]
621+ pub fn masked_store ( self , slice : & mut [ T ] , mut enable : Mask < <T as SimdElement >:: Mask , N > ) {
622+ enable &= mask_up_to ( enable, slice. len ( ) ) ;
623+ unsafe { self . masked_store_ptr ( slice. as_mut_ptr ( ) , enable) }
624+ }
625+
626+ #[ inline]
627+ pub unsafe fn masked_store_unchecked (
628+ self ,
629+ slice : & mut [ T ] ,
630+ enable : Mask < <T as SimdElement >:: Mask , N > ,
631+ ) {
632+ let ptr = slice. as_mut_ptr ( ) ;
633+ unsafe { self . masked_store_ptr ( ptr, enable) }
634+ }
635+
636+ #[ inline]
637+ pub unsafe fn masked_store_ptr ( self , ptr : * mut T , enable : Mask < <T as SimdElement >:: Mask , N > ) {
638+ unsafe { core:: intrinsics:: simd:: simd_masked_store ( enable. to_int ( ) , ptr, self ) }
639+ }
640+
495641 /// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`.
496642 /// If an index is out-of-bounds, the write is suppressed without panicking.
497643 /// If two elements in the scattered vector would write to the same index
@@ -979,3 +1125,27 @@ where
9791125{
9801126 type Mask = isize ;
9811127}
1128+
1129+ #[ inline]
1130+ fn lane_indices < T , const N : usize > ( ) -> Simd < T , N >
1131+ where
1132+ T : MaskElement + Default + core:: convert:: From < i8 > + core:: ops:: Add < T , Output = T > ,
1133+ LaneCount < N > : SupportedLaneCount ,
1134+ {
1135+ let mut index = [ T :: default ( ) ; N ] ;
1136+ for i in 1 ..N {
1137+ index[ i] = index[ i - 1 ] + T :: from ( 1 ) ;
1138+ }
1139+ Simd :: from_array ( index)
1140+ }
1141+
1142+ #[ inline]
1143+ fn mask_up_to < M , const N : usize > ( enable : Mask < M , N > , len : usize ) -> Mask < M , N >
1144+ where
1145+ LaneCount < N > : SupportedLaneCount ,
1146+ M : MaskElement ,
1147+ {
1148+ let index = lane_indices :: < i8 , N > ( ) ;
1149+ let lt = index. simd_lt ( Simd :: splat ( i8:: try_from ( len) . unwrap_or ( i8:: MAX ) ) ) ;
1150+ enable & Mask :: < M , N > :: from_bitmask_vector ( lt. to_bitmask_vector ( ) )
1151+ }
0 commit comments