@@ -314,6 +314,131 @@ where
314
314
unsafe { self . store ( slice. as_mut_ptr ( ) . cast ( ) ) }
315
315
}
316
316
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
+
317
442
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
318
443
/// If an index is out-of-bounds, the element is instead selected from the `or` vector.
319
444
///
@@ -492,6 +617,27 @@ where
492
617
unsafe { core:: intrinsics:: simd:: simd_gather ( or, source, enable. to_int ( ) ) }
493
618
}
494
619
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
+
495
641
/// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`.
496
642
/// If an index is out-of-bounds, the write is suppressed without panicking.
497
643
/// If two elements in the scattered vector would write to the same index
@@ -979,3 +1125,27 @@ where
979
1125
{
980
1126
type Mask = isize ;
981
1127
}
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