Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/wide-1.7.0/src/simd_uint.rs
Line
Count
Source
1
/// Emits functionality shared by all SIMD unsigned-integer types.
2
///
3
/// Functions that need a separate implementation for each type (for
4
/// performance) use `$fn_{name}:item` syntax, and functions that have one
5
/// shared implementation for all uints are written out normally inside this
6
/// macro.
7
///
8
/// This macro also invokes `impl_simd`.
9
macro_rules! impl_simd_uint {
10
  (
11
    // SAFETY: The contents of this macro assume that:
12
    //
13
    // - `T` implements `Pod`
14
    // - `Pod` can be implemented for `Simd`
15
    // - `size_of::<Simd>()` is `size_of::<T>() * N`
16
    // - `align_of::<Simd>()` is `size_of::<Simd>()`
17
    // - `Pod` can be implemented for the optional native SIMD types
18
    unsafe {
19
      T = $T:ident,
20
      N = $N:literal,
21
      Simd = $Simd:ident,
22
      IntSimd = $IntSimd:ident,
23
      T_BITS = $T_BITS:literal,
24
      T_BITS_MUL_2 = $T_BITS_MUL_2:literal,
25
      [$($index:literal),* $(,)?],
26
      optional_type_x86_inner { $(X86Inner = $X86Inner:ident)? },
27
      optional_type_arm_inner { $(ArmInner = $ArmInner:ident)? },
28
      optional_type_wasm_inner { $(WasmInner = $WasmInner:ident)? },
29
    }
30
31
    // General SIMD functions
32
    $fn_not:item
33
    $fn_add:item
34
    $fn_sub:item
35
    $fn_mul:item
36
    $fn_bitand:item
37
    $fn_bitor:item
38
    $fn_bitxor:item
39
    $fn_simd_eq:item
40
    $fn_simd_ne:item
41
    $fn_simd_lt:item
42
    $fn_simd_gt:item
43
    $fn_simd_le:item
44
    $fn_simd_ge:item
45
    $fn_reduce_add:item
46
    $fn_reduce_mul:item
47
    $fn_bitselect:item
48
    $fn_select:item
49
    $fn_to_bitmask:item
50
    $fn_any:item
51
    $fn_all:item
52
    $fn_shuffle:item
53
    $fn_shuffle_zeroing:item
54
    $fn_shuffle_wrapping:item
55
    $fn_shuffle_2:item
56
    $fn_shuffle_zeroing_2:item
57
    $fn_shuffle_wrapping_2:item
58
    $fn_shuffle_3:item
59
    $fn_shuffle_zeroing_3:item
60
    $fn_shuffle_wrapping_3:item
61
    $fn_shuffle_4:item
62
    $fn_shuffle_zeroing_4:item
63
    $fn_shuffle_wrapping_4:item
64
    $fn_transpose:item
65
66
    // Uint-specific functions
67
    $fn_shl_unsigned_simd:item
68
    $fn_shl_u32:item
69
    $fn_shr_unsigned_simd:item
70
    $fn_shr_u32:item
71
    $fn_max:item
72
    $fn_min:item
73
    $fn_reduce_max:item
74
    $fn_reduce_min:item
75
    $fn_unbounded_shl:item
76
    $fn_unbounded_shl_scalar:item
77
    $fn_unbounded_shr:item
78
    $fn_unbounded_shr_scalar:item
79
    $fn_saturating_add:item
80
    $fn_saturating_sub:item
81
    $fn_overflowing_mul:item
82
    optional_fn_widening_mul { $($fn_widening_mul:item)? }
83
    $fn_mul_keep_low_high:item
84
    $fn_mul_keep_high:item
85
    optional_fn_deserialize { $($fn_deserialize:item)? }
86
  ) => {
87
    impl_simd!(
88
      unsafe {
89
        T = $T,
90
        N = $N,
91
        Simd = $Simd,
92
        UintSimd = $Simd,
93
        optional_type_x86_inner { $(X86Inner = $X86Inner)? },
94
        optional_type_arm_inner { $(ArmInner = $ArmInner)? },
95
        optional_type_wasm_inner { $(WasmInner = $WasmInner)? },
96
      }
97
98
      $fn_simd_eq
99
100
      $fn_simd_ne
101
102
      $fn_simd_lt
103
104
      $fn_simd_gt
105
106
      $fn_simd_le
107
108
      $fn_simd_ge
109
110
      $fn_reduce_add
111
112
      $fn_reduce_mul
113
114
      $fn_bitselect
115
116
      $fn_select
117
118
      $fn_to_bitmask
119
120
      $fn_any
121
122
      $fn_all
123
124
      $fn_shuffle
125
126
      $fn_shuffle_zeroing
127
128
      $fn_shuffle_wrapping
129
130
      $fn_shuffle_2
131
132
      $fn_shuffle_zeroing_2
133
134
      $fn_shuffle_wrapping_2
135
136
      $fn_shuffle_3
137
138
      $fn_shuffle_zeroing_3
139
140
      $fn_shuffle_wrapping_3
141
142
      $fn_shuffle_4
143
144
      $fn_shuffle_zeroing_4
145
146
      $fn_shuffle_wrapping_4
147
148
      $fn_transpose
149
150
      optional_fn_deserialize { $($fn_deserialize)? }
151
    );
152
153
    impl_unary_operator!(
154
      $Simd,
155
      Neg,
156
      neg,
157
      #[inline]
158
      fn neg(self) -> Self::Output {
159
        Self::default() - self
160
      }
161
    );
162
    impl_unary_operator!($Simd, Not, not, $fn_not);
163
164
    impl_binary_operator!($T, $Simd, Add, add, AddAssign, add_assign, $fn_add);
165
    impl_binary_operator!($T, $Simd, Sub, sub, SubAssign, sub_assign, $fn_sub);
166
    impl_binary_operator!($T, $Simd, Mul, mul, MulAssign, mul_assign, $fn_mul);
167
    impl_binary_operator!(
168
        $T,
169
        $Simd,
170
        Div,
171
        div,
172
        DivAssign,
173
        div_assign,
174
        #[inline]
175
        fn div(self, rhs: Self) -> Self::Output {
176
            let self_array = self.to_array();
177
            let rhs_array = rhs.to_array();
178
179
            Self::new([$(self_array[$index].wrapping_div(rhs_array[$index])),*])
180
        },
181
        /// Divides each element of `left` by the corresponding element `right`.
182
        ///
183
        /// Note that because division has no hardware support, this operation
184
        /// is very slow and should be avoided if possible.
185
        ///
186
        /// # Panics
187
        ///
188
        /// Panics if any element of `right` is zero.
189
        ,
190
        /// Divides each element of `left` by the scalar `right`.
191
        ///
192
        /// Note that because division has no hardware support, this operation
193
        /// is very slow and should be avoided if possible.
194
        ///
195
        /// # Panics
196
        ///
197
        /// Panics if `right` is zero.
198
        ,
199
        /// Divides the scalar `left` by each element of `right`.
200
        ///
201
        /// Note that because division has no hardware support, this operation
202
        /// is very slow and should be avoided if possible.
203
        ///
204
        /// # Panics
205
        ///
206
        /// Panics if any element of `right` is zero.
207
    );
208
    impl_binary_operator!(
209
        $T,
210
        $Simd,
211
        Rem,
212
        rem,
213
        RemAssign,
214
        rem_assign,
215
        #[inline]
216
        fn rem(self, rhs: Self) -> Self::Output {
217
            let self_array = self.to_array();
218
            let rhs_array = rhs.to_array();
219
220
            Self::new([$(self_array[$index].wrapping_rem(rhs_array[$index])),*])
221
        },
222
        /// Returns the remainder of each element of `left` divided by the
223
        /// corresponding element `right`.
224
        ///
225
        /// Note that because division has no hardware support, this operation
226
        /// is very slow and should be avoided if possible.
227
        ///
228
        /// # Panics
229
        ///
230
        /// Panics if any element of `right` is zero.
231
        ,
232
        /// Returns the remainder of each element of `left` divided by the
233
        /// scalar `right`.
234
        ///
235
        /// Note that because division has no hardware support, this operation
236
        /// is very slow and should be avoided if possible.
237
        ///
238
        /// # Panics
239
        ///
240
        /// Panics if `right` is zero.
241
        ,
242
        /// Returns the remainder of the scalar `left` divided by each element
243
        /// of `right`.
244
        ///
245
        /// Note that because division has no hardware support, this operation
246
        /// is very slow and should be avoided if possible.
247
        ///
248
        /// # Panics
249
        ///
250
        /// Panics if any element of `right` is zero.
251
    );
252
    impl_shift_operator!(
253
      $T,
254
      $Simd,
255
      $Simd,
256
      $IntSimd,
257
      Shl,
258
      shl,
259
      ShlAssign,
260
      shl_assign,
261
      $fn_shl_unsigned_simd,
262
      $fn_shl_u32,
263
      /// Shifts left each element of `self` by the corresponding element of
264
      /// `rhs`.
265
      ///
266
      /// This operator behaves like [`wrapping_shl`].
267
      ///
268
      /// Note that for most targets, this operator is slower than
269
      /// [`unbounded_shl`], so consider using that instead.
270
      ///
271
      #[doc = concat!("[`wrapping_shl`]: ", stringify!($T), "::wrapping_shl")]
272
      #[doc = concat!("[`unbounded_shl`]: ", stringify!($Simd), "::unbounded_shl")]
273
      ,
274
      /// Shifts left each element of `self` by the uniform scalar `rhs`.
275
      ///
276
      /// This operator behaves like [`wrapping_shl`].
277
      ///
278
      /// Note that for most targets, this operator is slower than
279
      /// [`unbounded_shl_scalar`], so consider using that instead.
280
      ///
281
      #[doc = concat!("[`wrapping_shl`]: ", stringify!($T), "::wrapping_shl")]
282
      #[doc = concat!("[`unbounded_shl_scalar`]: ", stringify!($Simd), "::unbounded_shl_scalar")]
283
      ,
284
      /// Shifts left the scalar `self` by each element of `rhs`.
285
      ///
286
      /// This operator behaves like [`wrapping_shl`].
287
      ///
288
      /// Note that for most targets, this operator is slower than
289
      /// [`unbounded_shl`], so consider using that instead.
290
      ///
291
      #[doc = concat!("[`wrapping_shl`]: ", stringify!($T), "::wrapping_shl")]
292
      #[doc = concat!("[`unbounded_shl`]: ", stringify!($Simd), "::unbounded_shl")]
293
    );
294
    impl_shift_operator!(
295
      $T,
296
      $Simd,
297
      $Simd,
298
      $IntSimd,
299
      Shr,
300
      shr,
301
      ShrAssign,
302
      shr_assign,
303
      $fn_shr_unsigned_simd,
304
      $fn_shr_u32,
305
      /// Shifts right each element of `self` by the corresponding element of
306
      /// `rhs`.
307
      ///
308
      /// This operator behaves like [`wrapping_shr`].
309
      ///
310
      /// Note that for most targets, this operator is slower than
311
      /// [`unbounded_shr`], so consider using that instead.
312
      ///
313
      #[doc = concat!("[`wrapping_shr`]: ", stringify!($T), "::wrapping_shr")]
314
      #[doc = concat!("[`unbounded_shr`]: ", stringify!($Simd), "::unbounded_shr")]
315
      ,
316
      /// Shifts right each element of `self` by the uniform scalar `rhs`.
317
      ///
318
      /// This operator behaves like [`wrapping_shr`].
319
      ///
320
      /// Note that for most targets, this operator is slower than
321
      /// [`unbounded_shr_scalar`], so consider using that instead.
322
      ///
323
      #[doc = concat!("[`wrapping_shr`]: ", stringify!($T), "::wrapping_shr")]
324
      #[doc = concat!("[`unbounded_shr_scalar`]: ", stringify!($Simd), "::unbounded_shr_scalar")]
325
      ,
326
      /// Shifts right the scalar `self` by each element of `rhs`.
327
      ///
328
      /// This operator behaves like [`wrapping_shr`].
329
      ///
330
      /// Note that for most targets, this operator is slower than
331
      /// [`unbounded_shr`], so consider using that instead.
332
      ///
333
      #[doc = concat!("[`wrapping_shr`]: ", stringify!($T), "::wrapping_shr")]
334
      #[doc = concat!("[`unbounded_shr`]: ", stringify!($Simd), "::unbounded_shr")]
335
    );
336
    impl_binary_operator!(
337
      $T,
338
      $Simd,
339
      BitAnd,
340
      bitand,
341
      BitAndAssign,
342
      bitand_assign,
343
      $fn_bitand
344
    );
345
    impl_binary_operator!(
346
      $T,
347
      $Simd,
348
      BitOr,
349
      bitor,
350
      BitOrAssign,
351
      bitor_assign,
352
      $fn_bitor
353
    );
354
    impl_binary_operator!(
355
      $T,
356
      $Simd,
357
      BitXor,
358
      bitxor,
359
      BitXorAssign,
360
      bitxor_assign,
361
      $fn_bitxor
362
    );
363
364
    impl<Rhs> core::iter::Sum<Rhs> for $Simd
365
    where
366
      $Simd: AddAssign<Rhs>,
367
    {
368
      #[inline]
369
      fn sum<I: Iterator<Item = Rhs>>(iter: I) -> Self {
370
        let mut total = Self::zeroed();
371
        for val in iter {
372
          total += val;
373
        }
374
        total
375
      }
376
    }
377
378
    impl<Rhs> core::iter::Product<Rhs> for $Simd
379
    where
380
      $Simd: MulAssign<Rhs>,
381
    {
382
      #[inline]
383
      fn product<I: Iterator<Item = Rhs>>(iter: I) -> Self {
384
        let mut total = Self::from(1);
385
        for val in iter {
386
          total *= val;
387
        }
388
        total
389
      }
390
    }
391
392
    macro_rules! impl_formatting_trait {
393
      ($Trait:path) => {
394
        impl $Trait for $Simd {
395
          #[allow(clippy::missing_inline_in_public_items)]
396
0
          fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
397
0
            write!(f, "(")?;
398
0
            for (i, x) in self.to_array().iter().enumerate() {
399
0
              if i > 0 {
400
0
                write!(f, ", ")?;
401
0
              }
402
0
              <$T as $Trait>::fmt(x, f)?;
403
            }
404
0
            write!(f, ")")
405
0
          }
Unexecuted instantiation: <wide::u8x64_::u8x64 as core::fmt::Binary>::fmt
Unexecuted instantiation: <wide::u64x8_::u64x8 as core::fmt::Binary>::fmt
Unexecuted instantiation: <wide::u8x64_::u8x64 as core::fmt::LowerHex>::fmt
Unexecuted instantiation: <wide::u64x8_::u64x8 as core::fmt::LowerHex>::fmt
Unexecuted instantiation: <wide::u8x64_::u8x64 as core::fmt::Octal>::fmt
Unexecuted instantiation: <wide::u64x8_::u64x8 as core::fmt::Octal>::fmt
Unexecuted instantiation: <wide::u8x64_::u8x64 as core::fmt::UpperHex>::fmt
Unexecuted instantiation: <wide::u64x8_::u64x8 as core::fmt::UpperHex>::fmt
Unexecuted instantiation: <wide::u32x8_::u32x8 as core::fmt::Binary>::fmt
Unexecuted instantiation: <wide::u32x8_::u32x8 as core::fmt::LowerHex>::fmt
Unexecuted instantiation: <wide::u32x8_::u32x8 as core::fmt::Octal>::fmt
Unexecuted instantiation: <wide::u32x8_::u32x8 as core::fmt::UpperHex>::fmt
406
        }
407
      }
408
    }
409
    impl_formatting_trait!(core::fmt::Binary);
410
    impl_formatting_trait!(core::fmt::LowerHex);
411
    impl_formatting_trait!(core::fmt::Octal);
412
    impl_formatting_trait!(core::fmt::UpperHex);
413
414
    /// The following functionality exists for all SIMD vectors of unsigned
415
    /// integers.
416
    impl $Simd {
417
      /// A SIMD vector with all elements set to `1`.
418
      pub const ONE: Self = Self::splat(1);
419
420
      /// A SIMD vector with all elements set to `0`.
421
      pub const ZERO: Self = Self::splat(0);
422
423
      #[doc = concat!("A SIMD vector with all elements set to [`", stringify!($T) ,"::MAX`].")]
424
      pub const MAX: Self = Self::splat($T::MAX);
425
426
      #[doc = concat!("A SIMD vector with all elements set to [`", stringify!($T) ,"::MIN`].")]
427
      pub const MIN: Self = Self::splat($T::MIN);
428
429
      /// The number of elements in this SIMD vector.
430
      pub const LANES: u16 = $N;
431
432
      /// The size of this SIMD vector in bits.
433
      pub const BITS: u16 = (size_of::<Self>() * 8) as u16;
434
435
      /// Returns the maximum between each element of `self` and the
436
      /// corresponding element of `other`.
437
      #[must_use]
438
      $fn_max
439
440
      /// Returns the minimum between each element of `self` and the
441
      /// corresponding element of `other`.
442
      #[must_use]
443
      $fn_min
444
445
      /// Clamps each element of `self` between the corresponding elements of
446
      /// `min` and `max`.
447
      ///
448
      /// If `min > max`, the result is unspecified. Consider manually checking
449
      /// for that case.
450
      #[inline]
451
      #[must_use]
452
      pub fn clamp(self, min: Self, max: Self) -> Self {
453
        self.max(min).min(max)
454
      }
455
456
      /// Reducing maximum. Returns the maximum of the vector's elements.
457
      ///
458
      /// Equivalent to `self[0].max(self[1].max(...))`.
459
      #[must_use]
460
      $fn_reduce_max
461
462
      /// Reducing minimum. Returns the minimum of the vector's elements.
463
      ///
464
      /// Equivalent to `self[0].min(self[1].min(...))`.
465
      #[must_use]
466
      $fn_reduce_min
467
468
      /// Returns the bit patterns of `self` reinterpreted as signed integers of
469
      /// the same size.
470
      #[inline]
471
      #[must_use]
472
      pub const fn cast_signed(self) -> $IntSimd {
473
        // SAFETY: Both types accept all bit-patterns and only contain
474
        // initialized memory.
475
        unsafe { core::mem::transmute::<$Simd, $IntSimd>(self) }
476
      }
477
478
      /// Shifts left each element of `self` by the corresponding element of
479
      /// `rhs`, without bounding `rhs`.
480
      ///
481
      #[doc = concat!("If `rhs` is larger than or equal to the number of bits in [`", stringify!($T), "`],")]
482
      /// the entire value is shifted out, and `0` is returned.
483
      ///
484
      /// This is different from the standard operator, which behaves like
485
      /// [`wrapping_shl`]. For most targets, `unbounded_shl` is faster than the
486
      /// standard operator.
487
      ///
488
      /// If you intend to shift all elements by the same value, consider using
489
      /// [`unbounded_shl_scalar`] which is faster.
490
      ///
491
      #[doc = concat!("[`wrapping_shl`]: ", stringify!($T), "::wrapping_shl")]
492
      /// [`unbounded_shl_scalar`]: Self::unbounded_shl_scalar
493
      #[must_use]
494
      $fn_unbounded_shl
495
496
      /// Shifts left each element of `self` by the uniform scalar `rhs`,
497
      /// without bounding `rhs`.
498
      ///
499
      #[doc = concat!("If `rhs` is larger than or equal to the number of bits in [`", stringify!($T), "`],")]
500
      /// the entire value is shifted out, and `0` is returned.
501
      ///
502
      /// This is different from the standard operator, which behaves like
503
      /// [`wrapping_shl`]. For most targets, `unbounded_shl_scalar` is faster
504
      /// than the standard operator.
505
      ///
506
      /// This function is faster than `self.unbounded_shl(splat(rhs))` because
507
      /// it has special hardware support.
508
      ///
509
      #[doc = concat!("[`wrapping_shl`]: ", stringify!($T), "::wrapping_shl")]
510
      #[must_use]
511
      $fn_unbounded_shl_scalar
512
513
      /// Shifts right each element of `self` by the corresponding element of
514
      /// `rhs`, without bounding `rhs`.
515
      ///
516
      #[doc = concat!("If `rhs` is larger than or equal to the number of bits in [`", stringify!($T), "`],")]
517
      /// the entire value is shifted out, and `0` is returned.
518
      ///
519
      /// This is different from the standard operator, which behaves like
520
      /// [`wrapping_shr`]. For most targets, `unbounded_shr` is faster than the
521
      /// standard operator.
522
      ///
523
      /// If you intend to shift all elements by the same value, consider using
524
      /// [`unbounded_shr_scalar`] which is faster.
525
      ///
526
      #[doc = concat!("[`wrapping_shr`]: ", stringify!($T), "::wrapping_shr")]
527
      /// [`unbounded_shr_scalar`]: Self::unbounded_shr_scalar
528
      #[must_use]
529
      $fn_unbounded_shr
530
531
      /// Shifts right each element of `self` by the uniform scalar `rhs`,
532
      /// without bounding `rhs`.
533
      ///
534
      #[doc = concat!("If `rhs` is larger than or equal to the number of bits in [`", stringify!($T), "`],")]
535
      /// the entire value is shifted out, and `0` is returned.
536
      ///
537
      /// This is different from the standard operator, which behaves like
538
      /// [`wrapping_shr`]. For most targets, `unbounded_shr_scalar` is faster
539
      /// than the standard operator.
540
      ///
541
      /// This function is faster than `self.unbounded_shr(splat(rhs))` because
542
      /// it has special hardware support.
543
      ///
544
      #[doc = concat!("[`wrapping_shr`]: ", stringify!($T), "::wrapping_shr")]
545
      #[must_use]
546
      $fn_unbounded_shr_scalar
547
548
      /// Saturating integer addition. Computes `self + rhs`, saturating at the
549
      /// numeric bounds instead of overflowing.
550
      #[must_use]
551
      $fn_saturating_add
552
553
      /// Saturating integer subtraction. Computes `self - rhs`, saturating at
554
      /// the numeric bounds instead of overflowing.
555
      #[must_use]
556
      $fn_saturating_sub
557
558
      /// Saturating integer multiplication. Computes `self * rhs`, saturating
559
      /// at the numeric bounds instead of overflowing.
560
      #[inline]
561
      #[must_use]
562
      pub fn saturating_mul(self, rhs: Self) -> Self {
563
        let (low, high) = self.mul_keep_low_high(rhs);
564
        low | high.simd_ne(Self::ZERO)
565
      }
566
567
      /// Saturating integer division. Computes `self / rhs`, saturating at the
568
      /// numeric bounds instead of overflowing.
569
      ///
570
      /// Note that for unsigned integers overflow never occurs, so this is
571
      /// identical to regular division. This function only exists for
572
      /// consistency with signed integers.
573
      ///
574
      /// Note that because division has no hardware support, this operation is
575
      /// very slow and should be avoided if possible.
576
      ///
577
      /// # Panics
578
      ///
579
      /// Panics if any element of `rhs` is zero.
580
      #[inline]
581
      #[must_use]
582
      pub fn saturating_div(self, rhs: Self) -> Self {
583
        let self_array = self.to_array();
584
        let rhs_array = rhs.to_array();
585
586
        Self::new([$(self_array[$index].saturating_div(rhs_array[$index])),*])
587
      }
588
589
      /// Returns `self + rhs` and whether an overflow occured.
590
      ///
591
      /// Returns a tuple with:
592
      ///
593
      /// - The addition (returns the wrapped value if an overflow occured)
594
      /// - A mask indicating whether an overflow occured
595
      #[inline]
596
      #[must_use]
597
      pub fn overflowing_add(self, rhs: Self) -> (Self, Self) {
598
        let result = self + rhs;
599
        let overflow = result.simd_lt(self);
600
601
        (result, overflow)
602
      }
603
604
      /// Returns `self - rhs` and whether an overflow occured.
605
      ///
606
      /// Returns a tuple with:
607
      ///
608
      /// - The subtraction (returns the wrapped value if an overflow occured)
609
      /// - A mask indicating whether an overflow occured
610
      #[inline]
611
      #[must_use]
612
      pub fn overflowing_sub(self, rhs: Self) -> (Self, Self) {
613
        let result = self - rhs;
614
        let overflow = result.simd_gt(self);
615
616
        (result, overflow)
617
      }
618
619
      /// Returns `self * rhs` and whether an overflow occured.
620
      ///
621
      /// Returns a tuple with:
622
      ///
623
      /// - The multiplication (returns the wrapped value if an overflow occured)
624
      /// - A mask indicating whether an overflow occured
625
      #[must_use]
626
      $fn_overflowing_mul
627
628
      /// Returns `self / rhs` and whether an overflow occured.
629
      ///
630
      /// Note that for unsigned integers overflow never occurs, so the second
631
      /// value is always `false`. This function only exists for consistency
632
      /// with signed integers.
633
      ///
634
      /// Returns a tuple with:
635
      ///
636
      /// - The division (returns `self` if an overflow occured)
637
      /// - A mask indicating whether an overflow occured (always false)
638
      ///
639
      /// Note that because division has no hardware support, this operation is
640
      /// very slow and should be avoided if possible.
641
      #[inline]
642
      #[must_use]
643
      pub fn overflowing_div(self, rhs: Self) -> (Self, Self) {
644
        (self / rhs, Self::ZERO)
645
      }
646
647
      /// Returns `self % rhs` and whether an overflow occured.
648
      ///
649
      /// Note that for unsigned integers overflow never occurs, so the second
650
      /// value is always `false`. This function only exists for consistency
651
      /// with signed integers.
652
      ///
653
      /// Returns a tuple with:
654
      ///
655
      /// - The remainder (returns zero if an overflow occured)
656
      /// - A mask indicating whether an overflow occured (always false)
657
      ///
658
      /// Note that because division has no hardware support, this operation is
659
      /// very slow and should be avoided if possible.
660
      #[inline]
661
      #[must_use]
662
      pub fn overflowing_rem(self, rhs: Self) -> (Self, Self) {
663
        (self % rhs, Self::ZERO)
664
      }
665
666
      $(
667
        /// Widening multiplication. Computes `self * rhs`, widening to a SIMD
668
        /// vector of a larger integer type.
669
        ///
670
        /// The returned value is always exact and can never overflow.
671
        ///
672
        /// This function is different from [`mul_keep_low_high`], which returns
673
        /// two seperate SIMD vectors for low and high parts, instead of a
674
        /// single SIMD vector of a larger integer type. Also note that while
675
        /// [`mul_keep_low_high`] exists for all types, `widening_mul` does not
676
        /// exist for types with no wider variant (e.g., for `i32x16` because
677
        /// there is no `i64x16`).
678
        ///
679
        /// [`mul_keep_low_high`]: Self::mul_keep_low_high
680
        #[must_use]
681
        $fn_widening_mul
682
      )?
683
684
      #[doc = concat!(
685
        "Computes `self * rhs`, producing intermediate ",
686
        $T_BITS_MUL_2,
687
        "-bit integers, then returns their low ",
688
        $T_BITS,
689
        "-bit parts and high ",
690
        $T_BITS,
691
        "-bit parts in two seperate SIMD vectors."
692
      )]
693
      ///
694
      /// This function is different from `widening_mul`, which returns a single
695
      /// SIMD vector of a larger integer type, instead of two seperate SIMD
696
      /// vectors for low and high parts. Also note that while
697
      /// `mul_keep_low_high` exists for all types, `widening_mul` does not
698
      /// exist for types with no wider variant (e.g., for `i32x16` because
699
      /// there is no `i64x16`).
700
      #[must_use]
701
      $fn_mul_keep_low_high
702
703
      #[doc = concat!(
704
        "Computes `self * rhs`, producing intermediate ",
705
        $T_BITS_MUL_2,
706
        "-bit integers, then returns their high ",
707
        $T_BITS,
708
        "-bit parts."
709
      )]
710
      #[must_use]
711
      $fn_mul_keep_high
712
    }
713
  };
714
}