@@ -314,6 +314,142 @@ 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
+ <T as SimdElement >:: Mask : Default
335
+ + core:: convert:: From < i8 >
336
+ + core:: ops:: Add < <T as SimdElement >:: Mask , Output = <T as SimdElement >:: Mask > ,
337
+ Simd < <T as SimdElement >:: Mask , N > : SimdPartialOrd ,
338
+ Mask < <T as SimdElement >:: Mask , N > : core:: ops:: BitAnd < Output = Mask < <T as SimdElement >:: Mask , N > >
339
+ + core:: convert:: From < Mask < i8 , N > > ,
340
+ {
341
+ Self :: load_or ( slice, Default :: default ( ) )
342
+ }
343
+
344
+ /// Reads contiguous elements from `slice`. Elements are read so long as they're in-bounds for
345
+ /// the `slice`. Otherwise, the corresponding value from `or` is passed through.
346
+ ///
347
+ /// # Examples
348
+ /// ```
349
+ /// # #![feature(portable_simd)]
350
+ /// # use core::simd::{Simd, Mask};
351
+ /// let vec: Vec<i32> = vec![10, 11];
352
+ /// let or = Simd::from_array([-5, -4, -3, -2]);
353
+ ///
354
+ /// let result = Simd::load_or(&vec, or);
355
+ /// assert_eq!(result, Simd::from_array([10, 11, -3, -2]));
356
+ /// ```
357
+ #[ must_use]
358
+ #[ inline]
359
+ pub fn load_or ( slice : & [ T ] , or : Self ) -> Self
360
+ where
361
+ <T as SimdElement >:: Mask : Default
362
+ + core:: convert:: From < i8 >
363
+ + core:: ops:: Add < <T as SimdElement >:: Mask , Output = <T as SimdElement >:: Mask > ,
364
+ Simd < <T as SimdElement >:: Mask , N > : SimdPartialOrd ,
365
+ Mask < <T as SimdElement >:: Mask , N > : core:: ops:: BitAnd < Output = Mask < <T as SimdElement >:: Mask , N > >
366
+ + core:: convert:: From < Mask < i8 , N > > ,
367
+ {
368
+ Self :: load_select ( slice, Mask :: splat ( true ) , or)
369
+ }
370
+
371
+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
372
+ /// corresponding lane in `enable` is `true`.
373
+ ///
374
+ /// When the lane is disabled or out of bounds for the slice, that memory location
375
+ /// is not accessed and the corresponding value from `or` is passed through.
376
+ ///
377
+ /// # Examples
378
+ /// ```
379
+ /// # #![feature(portable_simd)]
380
+ /// # use core::simd::{Simd, Mask};
381
+ /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
382
+ /// let enable = Mask::from_array([true, true, false, true]);
383
+ /// let or = Simd::from_array([-5, -4, -3, -2]);
384
+ ///
385
+ /// let result = Simd::load_select(&vec, enable, or);
386
+ /// assert_eq!(result, Simd::from_array([10, 11, -3, 14]));
387
+ /// ```
388
+ #[ must_use]
389
+ #[ inline]
390
+ pub fn load_select_or_default ( slice : & [ T ] , enable : Mask < <T as SimdElement >:: Mask , N > ) -> Self
391
+ where
392
+ T : Default ,
393
+ {
394
+ Self :: load_select ( slice, enable, Default :: default ( ) )
395
+ }
396
+
397
+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
398
+ /// corresponding lane in `enable` is `true`.
399
+ ///
400
+ /// When the lane is disabled or out of bounds for the slice, that memory location
401
+ /// is not accessed and the corresponding value from `or` is passed through.
402
+ ///
403
+ /// # Examples
404
+ /// ```
405
+ /// # #![feature(portable_simd)]
406
+ /// # use core::simd::{Simd, Mask};
407
+ /// let vec: Vec<i32> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
408
+ /// let enable = Mask::from_array([true, true, false, true]);
409
+ /// let or = Simd::from_array([-5, -4, -3, -2]);
410
+ ///
411
+ /// let result = Simd::load_select(&vec, enable, or);
412
+ /// assert_eq!(result, Simd::from_array([10, 11, -3, 14]));
413
+ /// ```
414
+ #[ must_use]
415
+ #[ inline]
416
+ pub fn load_select ( slice : & [ T ] , mut enable : Mask < <T as SimdElement >:: Mask , N > , or : Self ) -> Self
417
+ {
418
+ enable &= mask_up_to ( enable, slice. len ( ) ) ;
419
+ unsafe { Self :: load_select_ptr ( slice. as_ptr ( ) , enable, or) }
420
+ }
421
+
422
+ /// Reads contiguous elements from `slice`. Each lane is read from memory if its
423
+ /// corresponding lane in `enable` is `true`.
424
+ ///
425
+ /// When the lane is disabled, that memory location is not accessed and the corresponding
426
+ /// value from `or` is passed through.
427
+ #[ must_use]
428
+ #[ inline]
429
+ pub unsafe fn load_select_unchecked (
430
+ slice : & [ T ] ,
431
+ enable : Mask < <T as SimdElement >:: Mask , N > ,
432
+ or : Self ,
433
+ ) -> Self {
434
+ let ptr = slice. as_ptr ( ) ;
435
+ unsafe { Self :: load_select_ptr ( ptr, enable, or) }
436
+ }
437
+
438
+ /// Reads contiguous elements starting at `ptr`. Each lane is read from memory if its
439
+ /// corresponding lane in `enable` is `true`.
440
+ ///
441
+ /// When the lane is disabled, that memory location is not accessed and the corresponding
442
+ /// value from `or` is passed through.
443
+ #[ must_use]
444
+ #[ inline]
445
+ pub unsafe fn load_select_ptr (
446
+ ptr : * const T ,
447
+ enable : Mask < <T as SimdElement >:: Mask , N > ,
448
+ or : Self ,
449
+ ) -> Self {
450
+ unsafe { core:: intrinsics:: simd:: simd_masked_load ( enable. to_int ( ) , ptr, or) }
451
+ }
452
+
317
453
/// Reads from potentially discontiguous indices in `slice` to construct a SIMD vector.
318
454
/// If an index is out-of-bounds, the element is instead selected from the `or` vector.
319
455
///
@@ -492,6 +628,28 @@ where
492
628
unsafe { core:: intrinsics:: simd:: simd_gather ( or, source, enable. to_int ( ) ) }
493
629
}
494
630
631
+ #[ inline]
632
+ pub fn masked_store ( self , slice : & mut [ T ] , mut enable : Mask < <T as SimdElement >:: Mask , N > )
633
+ {
634
+ enable &= mask_up_to ( enable, slice. len ( ) ) ;
635
+ unsafe { self . masked_store_ptr ( slice. as_mut_ptr ( ) , enable) }
636
+ }
637
+
638
+ #[ inline]
639
+ pub unsafe fn masked_store_unchecked (
640
+ self ,
641
+ slice : & mut [ T ] ,
642
+ enable : Mask < <T as SimdElement >:: Mask , N > ,
643
+ ) {
644
+ let ptr = slice. as_mut_ptr ( ) ;
645
+ unsafe { self . masked_store_ptr ( ptr, enable) }
646
+ }
647
+
648
+ #[ inline]
649
+ pub unsafe fn masked_store_ptr ( self , ptr : * mut T , enable : Mask < <T as SimdElement >:: Mask , N > ) {
650
+ unsafe { core:: intrinsics:: simd:: simd_masked_store ( enable. to_int ( ) , ptr, self ) }
651
+ }
652
+
495
653
/// Writes the values in a SIMD vector to potentially discontiguous indices in `slice`.
496
654
/// If an index is out-of-bounds, the write is suppressed without panicking.
497
655
/// If two elements in the scattered vector would write to the same index
@@ -979,3 +1137,27 @@ where
979
1137
{
980
1138
type Mask = isize ;
981
1139
}
1140
+
1141
+ #[ inline]
1142
+ fn lane_indices < T , const N : usize > ( ) -> Simd < T , N >
1143
+ where
1144
+ T : MaskElement + Default + core:: convert:: From < i8 > + core:: ops:: Add < T , Output = T > ,
1145
+ LaneCount < N > : SupportedLaneCount ,
1146
+ {
1147
+ let mut index = [ T :: default ( ) ; N ] ;
1148
+ for i in 1 ..N {
1149
+ index[ i] = index[ i - 1 ] + T :: from ( 1 ) ;
1150
+ }
1151
+ Simd :: from_array ( index)
1152
+ }
1153
+
1154
+ #[ inline]
1155
+ fn mask_up_to < M , const N : usize > ( enable : Mask < M , N > , len : usize ) -> Mask < M , N >
1156
+ where
1157
+ LaneCount < N > : SupportedLaneCount ,
1158
+ M : MaskElement ,
1159
+ {
1160
+ let index = lane_indices :: < i8 , N > ( ) ;
1161
+ let lt = index. simd_lt ( Simd :: splat ( i8:: try_from ( len) . unwrap_or ( i8:: MAX ) ) ) ;
1162
+ enable & Mask :: < M , N > :: from_bitmask_vector ( lt. to_bitmask_vector ( ) )
1163
+ }
0 commit comments