1use super::*;
2
3pick! {
4 if #[cfg(target_feature="avx512bw")] {
5 #[derive(Default, Clone, Copy, PartialEq, Eq)]
12 #[repr(C, align(64))]
13 pub struct u8x64 { pub(crate) avx512: m512i }
14 } else {
15 #[derive(Default, Clone, Copy, PartialEq, Eq)]
22 #[repr(C, align(64))]
23 pub struct u8x64 { pub(crate) a : u8x32, pub(crate) b : u8x32 }
24 }
25}
26
27impl_simd_uint! {
28 unsafe {
29 T = u8,
30 N = 64,
31 Simd = u8x64,
32 IntSimd = i8x64,
33 T_BITS = 8,
34 T_BITS_MUL_2 = 16,
35 [
36 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
37 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
38 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
39 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
40 ],
41 optional_type_x86_inner { X86Inner = __m512i },
42 optional_type_arm_inner {},
43 optional_type_wasm_inner {},
44 }
45
46 #[inline]
47 fn not(self) -> Self {
48 pick! {
49 if #[cfg(target_feature="avx512bw")] {
50 Self { avx512: bitxor_m512i(self.avx512, set_splat_i8_m512i(-1)) }
51 } else {
52 Self {
53 a : self.a.not(),
54 b : self.b.not(),
55 }
56 }
57 }
58 }
59
60 #[inline]
61 fn add(self, rhs: Self) -> Self::Output {
62 pick! {
63 if #[cfg(target_feature="avx512bw")] {
64 Self { avx512: add_i8_m512i(self.avx512, rhs.avx512) }
65 } else {
66 Self {
67 a : self.a.add(rhs.a),
68 b : self.b.add(rhs.b),
69 }
70 }
71 }
72 }
73
74 #[inline]
75 fn sub(self, rhs: Self) -> Self::Output {
76 pick! {
77 if #[cfg(target_feature="avx512bw")] {
78 Self { avx512: sub_i8_m512i(self.avx512, rhs.avx512) }
79 } else {
80 Self {
81 a : self.a.sub(rhs.a),
82 b : self.b.sub(rhs.b),
83 }
84 }
85 }
86 }
87
88 #[inline]
89 fn mul(self, rhs: Self) -> Self::Output {
90 let [self_a, self_b]: [u8x32; 2] = cast(self);
95 let [rhs_a, rhs_b]: [u8x32; 2] = cast(rhs);
96 cast([self_a * rhs_a, self_b * rhs_b])
97 }
98
99 #[inline]
100 fn bitand(self, rhs: Self) -> Self::Output {
101 pick! {
102 if #[cfg(target_feature="avx512bw")] {
103 Self { avx512: bitand_m512i(self.avx512, rhs.avx512) }
104 } else {
105 Self {
106 a : self.a.bitand(rhs.a),
107 b : self.b.bitand(rhs.b),
108 }
109 }
110 }
111 }
112
113 #[inline]
114 fn bitor(self, rhs: Self) -> Self::Output {
115 pick! {
116 if #[cfg(target_feature="avx512bw")] {
117 Self { avx512: bitor_m512i(self.avx512, rhs.avx512) }
118 } else {
119 Self {
120 a : self.a.bitor(rhs.a),
121 b : self.b.bitor(rhs.b),
122 }
123 }
124 }
125 }
126
127 #[inline]
128 fn bitxor(self, rhs: Self) -> Self::Output {
129 pick! {
130 if #[cfg(target_feature="avx512bw")] {
131 Self { avx512: bitxor_m512i(self.avx512, rhs.avx512) }
132 } else {
133 Self {
134 a : self.a.bitxor(rhs.a),
135 b : self.b.bitxor(rhs.b),
136 }
137 }
138 }
139 }
140
141 #[inline]
142 fn simd_eq(self, rhs: Self) -> Self::Output {
143 pick! {
144 if #[cfg(target_feature="avx512bw")] {
145 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Eq)}>(self.avx512, rhs.avx512) }
146 } else {
147 Self {
148 a : self.a.simd_eq(rhs.a),
149 b : self.b.simd_eq(rhs.b),
150 }
151 }
152 }
153 }
154
155 #[inline]
156 fn simd_ne(self, rhs: Self) -> Self::Output {
157 pick! {
158 if #[cfg(target_feature="avx512bw")] {
159 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Ne)}>(self.avx512, rhs.avx512) }
160 } else {
161 Self {
162 a : self.a.simd_ne(rhs.a),
163 b : self.b.simd_ne(rhs.b),
164 }
165 }
166 }
167 }
168
169 #[inline]
170 fn simd_lt(self, rhs: Self) -> Self::Output {
171 pick! {
172 if #[cfg(target_feature="avx512bw")] {
173 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Lt)}>(self.avx512, rhs.avx512) }
174 } else {
175 Self { a: self.a.simd_lt(rhs.a), b: self.b.simd_lt(rhs.b) }
176 }
177 }
178 }
179
180 #[inline]
181 fn simd_gt(self, rhs: Self) -> Self::Output {
182 pick! {
183 if #[cfg(target_feature="avx512bw")] {
184 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Nle)}>(self.avx512, rhs.avx512) }
185 } else {
186 Self { a: self.a.simd_gt(rhs.a), b: self.b.simd_gt(rhs.b) }
187 }
188 }
189 }
190
191 #[inline]
192 fn simd_le(self, rhs: Self) -> Self::Output {
193 pick! {
194 if #[cfg(target_feature="avx512bw")] {
195 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Le)}>(self.avx512, rhs.avx512) }
196 } else {
197 Self { a: self.a.simd_le(rhs.a), b: self.b.simd_le(rhs.b) }
198 }
199 }
200 }
201
202 #[inline]
203 fn simd_ge(self, rhs: Self) -> Self::Output {
204 pick! {
205 if #[cfg(target_feature="avx512bw")] {
206 Self { avx512: cmp_op_mask_u8_m512i::<{cmp_int_op!(Nlt)}>(self.avx512, rhs.avx512) }
207 } else {
208 Self { a: self.a.simd_ge(rhs.a), b: self.b.simd_ge(rhs.b) }
209 }
210 }
211 }
212
213 #[inline]
214 pub fn reduce_add(self) -> u8 {
215 let array: [u8x32; 2] = cast(self);
217 (array[0] + array[1]).reduce_add()
218 }
219
220 #[inline]
221 pub fn reduce_mul(self) -> u8 {
222 let array: [u8x32; 2] = cast(self);
224 (array[0] * array[1]).reduce_mul()
225 }
226
227 #[inline]
228 pub fn bitselect(self, if_one: Self, if_zero: Self) -> Self {
229 pick! {
230 if #[cfg(target_feature="avx512bw")] {
231 Self {
232 avx512: bitor_m512i(
233 bitand_m512i(if_one.avx512, self.avx512),
234 bitandnot_m512i(self.avx512, if_zero.avx512),
235 ),
236 }
237 } else {
238 Self {
239 a: self.a.bitselect(if_one.a, if_zero.a),
240 b: self.b.bitselect(if_one.b, if_zero.b),
241 }
242 }
243 }
244 }
245
246 #[inline]
247 fn select(self, if_true: Self, if_false: Self) -> Self {
248 pick! {
249 if #[cfg(target_feature="avx512bw")] {
250 Self { avx512: blend_varying_i8_m512i(if_false.avx512, if_true.avx512, movepi8_mask_m512i(self.avx512)) }
251 } else {
252 Self {
253 a : self.a.select(if_true.a, if_false.a),
254 b : self.b.select(if_true.b, if_false.b),
255 }
256 }
257 }
258 }
259
260 #[inline]
261 pub fn to_bitmask(self) -> u64 {
262 pick! {
263 if #[cfg(target_feature="avx512bw")] {
264 movepi8_mask_m512i(self.avx512) as u64
265 } else {
266 self.a.to_bitmask() as u64 | ((self.b.to_bitmask() as u64) << 32)
267 }
268 }
269 }
270
271 #[inline]
272 pub fn any(self) -> bool {
273 pick! {
274 if #[cfg(target_feature="avx512bw")] {
275 movepi8_mask_m512i(self.avx512) != 0
276 } else {
277 (self.a | self.b).any()
278 }
279 }
280 }
281
282 #[inline]
283 pub fn all(self) -> bool {
284 pick! {
285 if #[cfg(target_feature="avx512bw")] {
286 movepi8_mask_m512i(self.avx512) == u64::MAX
287 } else {
288 (self.a & self.b).all()
289 }
290 }
291 }
292
293 #[inline]
294 pub fn shuffle(self, indices: u8x64) -> Self {
295 pick! {
296 if #[cfg(target_feature = "avx512vbmi")] {
297 Self { avx512: permute_i8_m512i(indices.avx512, self.avx512) }
298 } else {
299 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
300 let [indices_a, indices_b] = cast::<u8x64, [u8x32; 2]>(indices);
301
302 cast([[self_a, self_b].shuffle(indices_a), [self_a, self_b].shuffle(indices_b)])
303 }
304 }
305 }
306
307 #[inline]
308 pub fn shuffle_zeroing(self, indices: u8x64) -> Self {
309 pick! {
310 if #[cfg(target_feature = "avx512vbmi")] {
311 self.shuffle(indices) & indices.simd_lt(64)
312 } else {
313 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
314 let [indices_a, indices_b] = cast::<u8x64, [u8x32; 2]>(indices);
315
316 cast([
317 [self_a, self_b].shuffle_zeroing(indices_a),
318 [self_a, self_b].shuffle_zeroing(indices_b),
319 ])
320 }
321 }
322 }
323
324 #[inline]
325 pub fn shuffle_wrapping(self, indices: u8x64) -> Self {
326 pick! {
327 if #[cfg(target_feature = "avx512vbmi")] {
328 self.shuffle(indices)
330 } else {
331 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
332 let [indices_a, indices_b] = cast::<u8x64, [u8x32; 2]>(indices);
333
334 cast([
335 [self_a, self_b].shuffle_wrapping(indices_a),
336 [self_a, self_b].shuffle_wrapping(indices_b),
337 ])
338 }
339 }
340 }
341
342 #[inline]
343 fn shuffle(self: [u8x64; 2], indices: u8x64) -> u8x64 {
344 pick! {
345 if #[cfg(target_feature = "avx512vbmi")] {
346 #[cfg(target_arch = "x86")]
347 use core::arch::x86::_mm512_permutex2var_epi8;
348 #[cfg(target_arch = "x86_64")]
349 use core::arch::x86_64::_mm512_permutex2var_epi8;
350 u8x64 {
352 avx512: unsafe {
353 m512i(_mm512_permutex2var_epi8(self[0].avx512.0, indices.avx512.0, self[1].avx512.0))
354 },
355 }
356 } else {
357 self[0].shuffle_zeroing(indices) | self[1].shuffle_zeroing(indices - 64)
358 }
359 }
360 }
361
362 #[inline]
363 fn shuffle_zeroing(self: [u8x64; 2], indices: u8x64) -> u8x64 {
364 pick! {
365 if #[cfg(target_feature = "avx512vbmi")] {
366 self.shuffle(indices) & indices.simd_lt(128)
367 } else {
368 self.shuffle(indices)
369 }
370 }
371 }
372
373 #[inline]
374 fn shuffle_wrapping(self: [u8x64; 2], indices: u8x64) -> u8x64 {
375 pick! {
376 if #[cfg(target_feature = "avx512vbmi")] {
377 self.shuffle(indices)
379 } else {
380 self.shuffle(indices & 127)
381 }
382 }
383 }
384
385 #[inline]
386 fn shuffle(self: [u8x64; 3], indices: u8x64) -> u8x64 {
387 [self[0], self[1]].shuffle_zeroing(indices) | self[2].shuffle_zeroing(indices - 128)
388 }
389
390 #[inline]
391 fn shuffle_zeroing(self: [u8x64; 3], indices: u8x64) -> u8x64 {
392 self.shuffle(indices)
393 }
394
395 #[inline]
396 fn shuffle_wrapping(self: [u8x64; 3], indices: u8x64) -> u8x64 {
397 self.shuffle(indices % 192)
398 }
399
400 #[inline]
401 fn shuffle(self: [u8x64; 4], indices: u8x64) -> u8x64 {
402 [self[0], self[1]].shuffle_zeroing(indices) | [self[2], self[3]].shuffle_zeroing(indices - 128)
403 }
404
405 #[inline]
406 fn shuffle_zeroing(self: [u8x64; 4], indices: u8x64) -> u8x64 {
407 self.shuffle(indices)
408 }
409
410 #[inline]
411 fn shuffle_wrapping(self: [u8x64; 4], indices: u8x64) -> u8x64 {
412 self.shuffle(indices)
415 }
416
417 #[inline]
420 pub fn transpose(data: [Self; 64]) -> [Self; 64] {
421 #[inline(always)]
424 fn transpose_column(data: &[u8x64; 64], index: usize) -> u8x64 {
425 u8x64::new([
426 data[0].as_array()[index],
427 data[1].as_array()[index],
428 data[2].as_array()[index],
429 data[3].as_array()[index],
430 data[4].as_array()[index],
431 data[5].as_array()[index],
432 data[6].as_array()[index],
433 data[7].as_array()[index],
434 data[8].as_array()[index],
435 data[9].as_array()[index],
436 data[10].as_array()[index],
437 data[11].as_array()[index],
438 data[12].as_array()[index],
439 data[13].as_array()[index],
440 data[14].as_array()[index],
441 data[15].as_array()[index],
442 data[16].as_array()[index],
443 data[17].as_array()[index],
444 data[18].as_array()[index],
445 data[19].as_array()[index],
446 data[20].as_array()[index],
447 data[21].as_array()[index],
448 data[22].as_array()[index],
449 data[23].as_array()[index],
450 data[24].as_array()[index],
451 data[25].as_array()[index],
452 data[26].as_array()[index],
453 data[27].as_array()[index],
454 data[28].as_array()[index],
455 data[29].as_array()[index],
456 data[30].as_array()[index],
457 data[31].as_array()[index],
458 data[32].as_array()[index],
459 data[33].as_array()[index],
460 data[34].as_array()[index],
461 data[35].as_array()[index],
462 data[36].as_array()[index],
463 data[37].as_array()[index],
464 data[38].as_array()[index],
465 data[39].as_array()[index],
466 data[40].as_array()[index],
467 data[41].as_array()[index],
468 data[42].as_array()[index],
469 data[43].as_array()[index],
470 data[44].as_array()[index],
471 data[45].as_array()[index],
472 data[46].as_array()[index],
473 data[47].as_array()[index],
474 data[48].as_array()[index],
475 data[49].as_array()[index],
476 data[50].as_array()[index],
477 data[51].as_array()[index],
478 data[52].as_array()[index],
479 data[53].as_array()[index],
480 data[54].as_array()[index],
481 data[55].as_array()[index],
482 data[56].as_array()[index],
483 data[57].as_array()[index],
484 data[58].as_array()[index],
485 data[59].as_array()[index],
486 data[60].as_array()[index],
487 data[61].as_array()[index],
488 data[62].as_array()[index],
489 data[63].as_array()[index],
490 ])
491 }
492
493 [
494 transpose_column(&data, 0),
495 transpose_column(&data, 1),
496 transpose_column(&data, 2),
497 transpose_column(&data, 3),
498 transpose_column(&data, 4),
499 transpose_column(&data, 5),
500 transpose_column(&data, 6),
501 transpose_column(&data, 7),
502 transpose_column(&data, 8),
503 transpose_column(&data, 9),
504 transpose_column(&data, 10),
505 transpose_column(&data, 11),
506 transpose_column(&data, 12),
507 transpose_column(&data, 13),
508 transpose_column(&data, 14),
509 transpose_column(&data, 15),
510 transpose_column(&data, 16),
511 transpose_column(&data, 17),
512 transpose_column(&data, 18),
513 transpose_column(&data, 19),
514 transpose_column(&data, 20),
515 transpose_column(&data, 21),
516 transpose_column(&data, 22),
517 transpose_column(&data, 23),
518 transpose_column(&data, 24),
519 transpose_column(&data, 25),
520 transpose_column(&data, 26),
521 transpose_column(&data, 27),
522 transpose_column(&data, 28),
523 transpose_column(&data, 29),
524 transpose_column(&data, 30),
525 transpose_column(&data, 31),
526 transpose_column(&data, 32),
527 transpose_column(&data, 33),
528 transpose_column(&data, 34),
529 transpose_column(&data, 35),
530 transpose_column(&data, 36),
531 transpose_column(&data, 37),
532 transpose_column(&data, 38),
533 transpose_column(&data, 39),
534 transpose_column(&data, 40),
535 transpose_column(&data, 41),
536 transpose_column(&data, 42),
537 transpose_column(&data, 43),
538 transpose_column(&data, 44),
539 transpose_column(&data, 45),
540 transpose_column(&data, 46),
541 transpose_column(&data, 47),
542 transpose_column(&data, 48),
543 transpose_column(&data, 49),
544 transpose_column(&data, 50),
545 transpose_column(&data, 51),
546 transpose_column(&data, 52),
547 transpose_column(&data, 53),
548 transpose_column(&data, 54),
549 transpose_column(&data, 55),
550 transpose_column(&data, 56),
551 transpose_column(&data, 57),
552 transpose_column(&data, 58),
553 transpose_column(&data, 59),
554 transpose_column(&data, 60),
555 transpose_column(&data, 61),
556 transpose_column(&data, 62),
557 transpose_column(&data, 63),
558 ]
559 }
560
561 #[inline]
562 fn shl(self, rhs: Self) -> Self::Output {
563 let [self_a, self_b]: [u8x32; 2] = cast(self);
567 let [rhs_a, rhs_b]: [u8x32; 2] = cast(rhs);
568 cast([self_a << rhs_a, self_b << rhs_b])
569 }
570
571 #[inline]
572 fn shl(self, rhs: u32) -> Self::Output {
573 pick! {
574 if #[cfg(target_feature="avx512bw")] {
575 let values: u16x32 = cast(self);
576 let shift = rhs & 7;
577 let shifted = values << shift;
578 let crossed = u16x32::splat(!((0x00FFu16 << shift) & 0xFF00));
579 cast(shifted & crossed)
580 } else {
581 let [self_a, self_b]: [u8x32; 2] = cast(self);
582 cast([self_a << rhs, self_b << rhs])
583 }
584 }
585 }
586
587 #[inline]
588 fn shr(self, rhs: Self) -> Self::Output {
589 let [self_a, self_b]: [u8x32; 2] = cast(self);
590 let [rhs_a, rhs_b]: [u8x32; 2] = cast(rhs);
591 cast([self_a >> rhs_a, self_b >> rhs_b])
592 }
593
594 #[inline]
595 fn shr(self, rhs: u32) -> Self::Output {
596 pick! {
597 if #[cfg(target_feature="avx512bw")] {
598 let values: u16x32 = cast(self);
599 let shift = rhs & 7;
600 let shifted = values >> shift;
601 let crossed = u16x32::splat(!((0xFF00u16 >> shift) & 0x00FF));
602 cast(shifted & crossed)
603 } else {
604 let [self_a, self_b]: [u8x32; 2] = cast(self);
605 cast([self_a >> rhs, self_b >> rhs])
606 }
607 }
608 }
609
610 #[inline]
611 pub fn max(self, rhs: Self) -> Self {
612 pick! {
613 if #[cfg(target_feature="avx512bw")] {
614 Self { avx512: max_u8_m512i(self.avx512, rhs.avx512) }
615 } else {
616 Self {
617 a : self.a.max(rhs.a),
618 b : self.b.max(rhs.b),
619 }
620 }
621 }
622 }
623
624 #[inline]
625 pub fn min(self, rhs: Self) -> Self {
626 pick! {
627 if #[cfg(target_feature="avx512bw")] {
628 Self { avx512: min_u8_m512i(self.avx512, rhs.avx512) }
629 } else {
630 Self {
631 a : self.a.min(rhs.a),
632 b : self.b.min(rhs.b),
633 }
634 }
635 }
636 }
637
638 #[inline]
639 pub fn reduce_max(self) -> u8 {
640 let array: [u8x32; 2] = cast(self);
641 array[0].max(array[1]).reduce_max()
642 }
643
644 #[inline]
645 pub fn reduce_min(self) -> u8 {
646 let array: [u8x32; 2] = cast(self);
647 array[0].min(array[1]).reduce_min()
648 }
649
650 #[inline]
651 pub fn unbounded_shl(self, rhs: Self) -> Self {
652 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
653 let [rhs_a, rhs_b] = cast::<u8x64, [u8x32; 2]>(rhs);
654 cast([self_a.unbounded_shl(rhs_a), self_b.unbounded_shl(rhs_b)])
655 }
656
657 #[inline]
658 pub fn unbounded_shl_scalar(self, rhs: u32) -> Self {
659 pick! {
660 if #[cfg(target_feature="avx512bw")] {
661 let values: u16x32 = cast(self);
662 let shifted = values.unbounded_shl_scalar(rhs);
663 let crossed = u16x32::splat(!(0x00FFu16.wrapping_shl(rhs) & 0xFF00));
664 cast(shifted & crossed)
665 } else {
666 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
667 cast([self_a.unbounded_shl_scalar(rhs), self_b.unbounded_shl_scalar(rhs)])
668 }
669 }
670 }
671
672 #[inline]
673 pub fn unbounded_shr(self, rhs: Self) -> Self {
674 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
675 let [rhs_a, rhs_b] = cast::<u8x64, [u8x32; 2]>(rhs);
676 cast([self_a.unbounded_shr(rhs_a), self_b.unbounded_shr(rhs_b)])
677 }
678
679 #[inline]
680 pub fn unbounded_shr_scalar(self, rhs: u32) -> Self {
681 pick! {
682 if #[cfg(target_feature="avx512bw")] {
683 let values: u16x32 = cast(self);
684 let shifted = values.unbounded_shr_scalar(rhs);
685 let crossed = u16x32::splat(!(0xFF00u16.wrapping_shr(rhs) & 0x00FF));
686 cast(shifted & crossed)
687 } else {
688 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
689 cast([self_a.unbounded_shr_scalar(rhs), self_b.unbounded_shr_scalar(rhs)])
690 }
691 }
692 }
693
694 #[inline]
695 pub fn saturating_add(self, rhs: Self) -> Self {
696 pick! {
697 if #[cfg(target_feature="avx512bw")] {
698 Self { avx512: add_saturating_u8_m512i(self.avx512, rhs.avx512) }
699 } else {
700 Self {
701 a : self.a.saturating_add(rhs.a),
702 b : self.b.saturating_add(rhs.b),
703 }
704 }
705 }
706 }
707
708 #[inline]
709 pub fn saturating_sub(self, rhs: Self) -> Self {
710 pick! {
711 if #[cfg(target_feature="avx512bw")] {
712 Self { avx512: sub_saturating_u8_m512i(self.avx512, rhs.avx512) }
713 } else {
714 Self {
715 a : self.a.saturating_sub(rhs.a),
716 b : self.b.saturating_sub(rhs.b),
717 }
718 }
719 }
720 }
721
722 #[inline]
723 pub fn overflowing_mul(self, rhs: Self) -> (Self, Self) {
724 let (low, high) = self.mul_keep_low_high(rhs);
725 let overflow = high.simd_ne(Self::ZERO);
726 (low, overflow)
727 }
728
729 optional_fn_widening_mul {
730 }
732
733 #[inline]
734 pub fn mul_keep_low_high(self, rhs: Self) -> (Self, Self) {
735 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
739 let [rhs_a, rhs_b] = cast::<u8x64, [u8x32; 2]>(rhs);
740
741 let result_a = self_a.mul_keep_low_high(rhs_a);
742 let result_b = self_b.mul_keep_low_high(rhs_b);
743 (cast([result_a.0, result_b.0]), cast([result_a.1, result_b.1]))
744 }
745
746 #[inline]
747 pub fn mul_keep_high(self, rhs: Self) -> Self {
748 let [self_a, self_b] = cast::<u8x64, [u8x32; 2]>(self);
752 let [rhs_a, rhs_b] = cast::<u8x64, [u8x32; 2]>(rhs);
753
754 cast([self_a.mul_keep_high(rhs_a), self_b.mul_keep_high(rhs_b)])
755 }
756
757 optional_fn_deserialize {
758 #[inline]
759 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
760 where
761 D: serde_core::Deserializer<'de>,
762 {
763 crate::simd::deserialize_array(deserializer)
764 }
765 }
766}