1use super::*;
2
3simd_type!({
5 #[allow(missing_docs)]
7 pub struct V1 {
8 pub sse: f!("sse"),
9 pub sse2: f!("sse2"),
10 pub fxsr: f!("fxsr"),
11 }
12});
13
14impl Seal for V1 {}
15
16impl V1 {
17 binop_128_nosign!(sse: add, "Computes `a + b` for each lane of `a` and `b`.", f32 x 4);
18
19 binop_128_nosign!(sse2: add, "Adds the elements of each lane of `a` and `b`.", f64 x 2);
20
21 binop_128_nosign!(sse2: add, "Adds the elements of each lane of `a` and `b`, with wrapping on overflow.", wrapping_add, u8 x 16, i8 x 16, u16 x 8, i16 x 8, u32 x 4, i32 x 4, u64 x 2, i64 x 2);
22
23 binop_128!(sse: and, "Returns `a & b` for each bit in `a` and `b`.", f32 x 4);
24
25 binop_128!(sse2: and, "Returns `a & b` for each bit in `a` and `b`.", f64 x 2);
26
27 binop_128_full!(sse2: and, "Returns `a & b` for each bit in `a` and `b`.", m8 x 16, u8 x 16, i8 x 16, m16 x 8, u16 x 8, i16 x 8, m32 x 4, u32 x 4, i32 x 4, m64 x 2, u64 x 2, i64 x 2);
28
29 binop_128!(sse: andnot, "Returns `!a & b` for each bit in `a` and `b`.", f32 x 4);
30
31 binop_128!(sse2: andnot, "Returns `!a & b` for each bit in `a` and `b`.", f64 x 2);
32
33 binop_128_full!(sse2: andnot, "Returns `!a & b` for each bit in `a` and `b`.", m8 x 16, u8 x 16, i8 x 16, m16 x 8, u16 x 8, i16 x 8, m32 x 4, u32 x 4, i32 x 4, m64 x 2, u64 x 2, i64 x 2);
34
35 binop_128!(sse2: avg, "Computes `average(a, b)` for each lane of `a` and `b`.", average, u8 x 16, u16 x 8);
36
37 binop_128_nosign!(sse: cmpeq, "Compares the elements in each lane of `a` and `b` for equality.", cmp_eq, f32 x 4 => m32);
38
39 binop_128_nosign!(sse2: cmpeq, "Compares the elements in each lane of `a` and `b` for equality.", cmp_eq, m8 x 16 => m8, u8 x 16 => m8, i8 x 16 => m8, m16 x 8 => m16, u16 x 8 => m16, i16 x 8 => m16, m32 x 4 => m32, u32 x 4 => m32, i32 x 4 => m32, f64 x 2 => m64);
40
41 binop_128!(sse: cmpge, "Compares the elements in each lane of `a` and `b` for greater-than-or-equal-to.", cmp_ge, f32 x 4 => m32);
42
43 binop_128!(sse2: cmpge, "Compares the elements in each lane of `a` and `b` for greater-than-or-equal-to.", cmp_ge, f64 x 2 => m64);
44
45 binop_128!(sse: cmpgt, "Compares the elements in each lane of `a` and `b` for greater-than.", cmp_gt, f32 x 4 => m32);
46
47 binop_128!(sse2: cmpgt, "Compares the elements in each lane of `a` and `b` for equality.", cmp_gt, i8 x 16 => m8, i16 x 8 => m16, i32 x 4 => m32, f64 x 2 => m64);
48
49 binop_128!(sse: cmplt, "Compares the elements in each lane of `a` and `b` for greater-than.", cmp_lt, f32 x 4 => m32);
50
51 binop_128!(sse2: cmplt, "Compares the elements in each lane of `a` and `b` for less-than.", cmp_lt, i8 x 16 => m8, i16 x 8 => m16, i32 x 4 => m32, f64 x 2 => m64);
52
53 binop_128!(sse: cmple, "Compares the elements in each lane of `a` and `b` for less-than-or-equal-to.", cmp_le, f32 x 4 => m32);
54
55 binop_128!(sse2: cmple, "Compares the elements in each lane of `a` and `b` for less-than-or-equal-to.", cmp_le, f64 x 2 => m64);
56
57 binop_128!(sse: cmpneq, "Compares the elements in each lane of `a` and `b` for inequality.", cmp_not_eq, f32 x 4 => m32);
58
59 binop_128!(sse2: cmpneq, "Compares the elements in each lane of `a` and `b` for inequality.", cmp_not_eq, f64 x 2 => m64);
60
61 binop_128!(sse: cmpnge, "Compares the elements in each lane of `a` and `b` for not-greater-than-or-equal.", cmp_not_ge, f32 x 4 => m32);
62
63 binop_128!(sse2: cmpnge, "Compares the elements in each lane of `a` and `b` for not-greater-than-or-equal.", cmp_not_ge, f64 x 2 => m64);
64
65 binop_128!(sse: cmpngt, "Compares the elements in each lane of `a` and `b` for not-greater-than.", cmp_not_gt, f32 x 4 => m32);
66
67 binop_128!(sse2: cmpngt, "Compares the elements in each lane of `a` and `b` for not-greater-than.", cmp_not_gt, f64 x 2 => m64);
68
69 binop_128!(sse: cmpnle, "Compares the elements in each lane of `a` and `b` for not-less-than-or-equal.", cmp_not_le, f32 x 4 => m32);
70
71 binop_128!(sse2: cmpnle, "Compares the elements in each lane of `a` and `b` for not-less-than-or-equal.", cmp_not_le, f64 x 2 => m64);
72
73 binop_128!(sse: cmpnlt, "Compares the elements in each lane of `a` and `b` for not-less-than.", cmp_not_lt, f32 x 4 => m32);
74
75 binop_128!(sse2: cmpnlt, "Compares the elements in each lane of `a` and `b` for not-less-than.", cmp_not_lt, f64 x 2 => m64);
76
77 binop_128!(sse: div, "Divides the elements of each lane of `a` and `b`.", f32 x 4);
78
79 binop_128!(sse2: div, "Divides the elements of each lane of `a` and `b`.", f64 x 2);
80
81 binop_128!(sse: max, "Computes `max(a, b)`. for each lane in `a` and `b`.", f32 x 4);
82
83 binop_128!(sse2: max, "Computes `max(a, b)`. for each lane in `a` and `b`.", u8 x 16, i16 x 8, f64 x 2);
84
85 binop_128!(sse: min, "Computes `max(a, b)`. for each lane in `a` and `b`.", f32 x 4);
86
87 binop_128!(sse2: min, "Computes `max(a, b)`. for each lane in `a` and `b`.", u8 x 16, i16 x 8, f64 x 2);
88
89 binop_128!(sse: mul, "Computes `a * b` for each lane in `a` and `b`.", f32 x 4);
90
91 binop_128!(sse2: mul, "Computes `a * b` for each lane in `a` and `b`.", f64 x 2);
92
93 binop_128_nosign!(sse2: mullo, "Computes `a * b` for each lane in `a` and `b`, with wrapping overflow.", wrapping_mul, u16 x 8, i16 x 8);
94
95 binop_128!(sse: or, "Returns `a | b` for each bit in `a` and `b`.", f32 x 4);
96
97 binop_128!(sse2: or, "Returns `a | b` for each bit in `a` and `b`.", f64 x 2);
98
99 binop_128_full!(sse2: or, "Returns `a | b` for each bit in `a` and `b`.", m8 x 16, u8 x 16, i8 x 16, m16 x 8, u16 x 8, i16 x 8, m32 x 4, u32 x 4, i32 x 4, m64 x 2, u64 x 2, i64 x 2);
100
101 binop_128!(sse2: adds, "Adds the elements of each lane of `a` and `b`, with saturation.", saturating_add, u8 x 16, i8 x 16, u16 x 8, i16 x 8);
102
103 binop_128!(sse2: subs, "Subtracts the elements of each lane of `a` and `b`, with saturation.", saturating_sub, u8 x 16, i8 x 16, u16 x 8, i16 x 8);
104
105 binop_128_nosign!(sse: sub, "Subtracts the elements of each lane of `a` and `b`.", f32 x 4);
106
107 binop_128_nosign!(sse2: sub, "Subtracts the elements of each lane of `a` and `b`.", f64 x 2);
108
109 binop_128_nosign!(sse2: sub, "Subtracts the elements of each lane of `a` and `b`, with wrapping overflow.", wrapping_sub, u8 x 16, i8 x 16, u16 x 8, i16 x 8, u32 x 4, i32 x 4, u64 x 2, i64 x 2);
110
111 binop_128!(sse: xor, "Returns `a ^ b` for each bit in `a` and `b`.", f32 x 4);
112
113 binop_128!(sse2: xor, "Returns `a ^ b` for each bit in `a` and `b`.", f64 x 2);
114
115 binop_128_full!(sse2: xor, "Returns `a ^ b` for each bit in `a` and `b`.", m8 x 16, u8 x 16, i8 x 16, m16 x 8, u16 x 8, i16 x 8, m32 x 4, u32 x 4, i32 x 4, m64 x 2, u64 x 2, i64 x 2);
116
117 #[inline(always)]
119 pub fn abs_f32x4(self, a: f32x4) -> f32x4 {
120 self.and_f32x4(a, cast!(self.splat_u32x4((1 << 31) - 1)))
121 }
122
123 #[inline(always)]
125 pub fn abs_f64x2(self, a: f64x2) -> f64x2 {
126 self.and_f64x2(a, cast!(self.splat_u64x2((1 << 63) - 1)))
127 }
128
129 #[inline(always)]
131 pub fn approx_reciprocal_f32x4(self, a: f32x4) -> f32x4 {
132 cast!(self.sse._mm_rcp_ps(cast!(a)))
133 }
134
135 #[inline(always)]
137 pub fn approx_reciprocal_sqrt_f32x4(self, a: f32x4) -> f32x4 {
138 cast!(self.sse._mm_rsqrt_ps(cast!(a)))
139 }
140
141 #[inline(always)]
143 pub fn cmp_ge_i16x8(self, a: i16x8, b: i16x8) -> m16x8 {
144 self.not_m16x8(self.cmp_lt_i16x8(a, b))
145 }
146
147 #[inline(always)]
149 pub fn cmp_ge_i32x4(self, a: i32x4, b: i32x4) -> m32x4 {
150 self.not_m32x4(self.cmp_lt_i32x4(a, b))
151 }
152
153 #[inline(always)]
155 pub fn cmp_ge_i8x16(self, a: i8x16, b: i8x16) -> m8x16 {
156 self.not_m8x16(self.cmp_lt_i8x16(a, b))
157 }
158
159 #[inline(always)]
161 pub fn cmp_ge_u16x8(self, a: u16x8, b: u16x8) -> m16x8 {
162 self.not_m16x8(self.cmp_lt_u16x8(a, b))
163 }
164
165 #[inline(always)]
167 pub fn cmp_ge_u32x4(self, a: u32x4, b: u32x4) -> m32x4 {
168 self.not_m32x4(self.cmp_lt_u32x4(a, b))
169 }
170
171 #[inline(always)]
173 pub fn cmp_ge_u8x16(self, a: u8x16, b: u8x16) -> m8x16 {
174 self.not_m8x16(self.cmp_lt_u8x16(a, b))
175 }
176
177 #[inline(always)]
179 pub fn cmp_gt_u16x8(self, a: u16x8, b: u16x8) -> m16x8 {
180 let k = self.splat_u16x8(0x8000);
181 self.cmp_gt_i16x8(cast!(self.xor_u16x8(a, k)), cast!(self.xor_u16x8(b, k)))
182 }
183
184 #[inline(always)]
186 pub fn cmp_gt_u32x4(self, a: u32x4, b: u32x4) -> m32x4 {
187 let k = self.splat_u32x4(0x80000000);
188 self.cmp_gt_i32x4(cast!(self.xor_u32x4(a, k)), cast!(self.xor_u32x4(b, k)))
189 }
190
191 #[inline(always)]
193 pub fn cmp_gt_u8x16(self, a: u8x16, b: u8x16) -> m8x16 {
194 let k = self.splat_u8x16(0x80);
195 self.cmp_gt_i8x16(cast!(self.xor_u8x16(a, k)), cast!(self.xor_u8x16(b, k)))
196 }
197
198 #[inline(always)]
200 pub fn cmp_le_i16x8(self, a: i16x8, b: i16x8) -> m16x8 {
201 self.not_m16x8(self.cmp_gt_i16x8(a, b))
202 }
203
204 #[inline(always)]
206 pub fn cmp_le_i32x4(self, a: i32x4, b: i32x4) -> m32x4 {
207 self.not_m32x4(self.cmp_gt_i32x4(a, b))
208 }
209
210 #[inline(always)]
212 pub fn cmp_le_i8x16(self, a: i8x16, b: i8x16) -> m8x16 {
213 self.not_m8x16(self.cmp_gt_i8x16(a, b))
214 }
215
216 #[inline(always)]
218 pub fn cmp_le_u16x8(self, a: u16x8, b: u16x8) -> m16x8 {
219 self.not_m16x8(self.cmp_gt_u16x8(a, b))
220 }
221
222 #[inline(always)]
224 pub fn cmp_le_u32x4(self, a: u32x4, b: u32x4) -> m32x4 {
225 self.not_m32x4(self.cmp_gt_u32x4(a, b))
226 }
227
228 #[inline(always)]
230 pub fn cmp_le_u8x16(self, a: u8x16, b: u8x16) -> m8x16 {
231 self.not_m8x16(self.cmp_gt_u8x16(a, b))
232 }
233
234 #[inline(always)]
236 pub fn cmp_lt_u16x8(self, a: u16x8, b: u16x8) -> m16x8 {
237 let k = self.splat_u16x8(0x8000);
238 self.cmp_lt_i16x8(cast!(self.xor_u16x8(a, k)), cast!(self.xor_u16x8(b, k)))
239 }
240
241 #[inline(always)]
243 pub fn cmp_lt_u32x4(self, a: u32x4, b: u32x4) -> m32x4 {
244 let k = self.splat_u32x4(0x80000000);
245 self.cmp_lt_i32x4(cast!(self.xor_u32x4(a, k)), cast!(self.xor_u32x4(b, k)))
246 }
247
248 #[inline(always)]
250 pub fn cmp_lt_u8x16(self, a: u8x16, b: u8x16) -> m8x16 {
251 let k = self.splat_u8x16(0x80);
252 self.cmp_lt_i8x16(cast!(self.xor_u8x16(a, k)), cast!(self.xor_u8x16(b, k)))
253 }
254
255 #[inline(always)]
257 pub fn convert_f32x4_to_f64x2(self, a: f32x4) -> f64x2 {
258 cast!(self.sse2._mm_cvtps_pd(cast!(a)))
259 }
260
261 #[inline(always)]
263 pub fn convert_f32x4_to_i32x4(self, a: f32x4) -> i32x4 {
264 cast!(self.sse2._mm_cvttps_epi32(cast!(a)))
265 }
266
267 #[inline(always)]
269 pub fn convert_f64x2_to_f32x4(self, a: f64x2) -> f32x4 {
270 cast!(self.sse2._mm_cvtpd_ps(cast!(a)))
271 }
272
273 #[inline(always)]
275 pub fn convert_f64x2_to_i32x4(self, a: f64x2) -> i32x4 {
276 cast!(self.sse2._mm_cvttpd_epi32(cast!(a)))
277 }
278
279 #[inline(always)]
281 pub fn convert_i16x8_to_u16x8(self, a: i16x8) -> u16x8 {
282 cast!(a)
283 }
284
285 #[inline(always)]
287 pub fn convert_i32x4_to_f32x4(self, a: i32x4) -> f32x4 {
288 cast!(self.sse2._mm_cvtepi32_ps(cast!(a)))
289 }
290
291 #[inline(always)]
293 pub fn convert_i32x4_to_f64x2(self, a: i32x4) -> f64x2 {
294 cast!(self.sse2._mm_cvtepi32_pd(cast!(a)))
295 }
296
297 #[inline(always)]
299 pub fn convert_i32x4_to_u32x4(self, a: i32x4) -> u32x4 {
300 cast!(a)
301 }
302
303 #[inline(always)]
305 pub fn convert_i8x16_to_u8x16(self, a: i8x16) -> u8x16 {
306 cast!(a)
307 }
308
309 #[inline(always)]
311 pub fn convert_u16x8_to_i16x8(self, a: u16x8) -> i16x8 {
312 cast!(a)
313 }
314
315 #[inline(always)]
317 pub fn convert_u32x4_to_i32x4(self, a: u32x4) -> i32x4 {
318 cast!(a)
319 }
320
321 #[inline(always)]
323 pub fn convert_u8x16_to_i8x16(self, a: u8x16) -> i8x16 {
324 cast!(a)
325 }
326
327 #[inline(always)]
329 pub fn is_nan_f32x4(self, a: f32x4) -> m32x4 {
330 cast!(self.sse._mm_cmpunord_ps(cast!(a), cast!(a)))
331 }
332
333 #[inline(always)]
335 pub fn is_nan_f64x2(self, a: f64x2) -> m64x2 {
336 cast!(self.sse2._mm_cmpunord_pd(cast!(a), cast!(a)))
337 }
338
339 #[inline(always)]
341 pub fn is_not_nan_f32x4(self, a: f32x4) -> m32x4 {
342 cast!(self.sse._mm_cmpord_ps(cast!(a), cast!(a)))
343 }
344
345 #[inline(always)]
347 pub fn is_not_nan_f64x2(self, a: f64x2) -> m64x2 {
348 cast!(self.sse2._mm_cmpord_pd(cast!(a), cast!(a)))
349 }
350
351 #[inline(always)]
355 pub fn multiply_wrapping_add_adjacent_i16x8(self, a: i16x8, b: i16x8) -> i32x4 {
356 cast!(self.sse2._mm_madd_epi16(cast!(a), cast!(b)))
357 }
358
359 #[inline(always)]
361 pub fn not_i16x8(self, a: i16x8) -> i16x8 {
362 self.xor_i16x8(a, self.splat_i16x8(!0))
363 }
364
365 #[inline(always)]
367 pub fn not_i32x4(self, a: i32x4) -> i32x4 {
368 self.xor_i32x4(a, self.splat_i32x4(!0))
369 }
370
371 #[inline(always)]
373 pub fn not_i64x2(self, a: i64x2) -> i64x2 {
374 self.xor_i64x2(a, self.splat_i64x2(!0))
375 }
376
377 #[inline(always)]
379 pub fn not_i8x16(self, a: i8x16) -> i8x16 {
380 self.xor_i8x16(a, self.splat_i8x16(!0))
381 }
382
383 #[inline(always)]
385 pub fn not_m16x8(self, a: m16x8) -> m16x8 {
386 self.xor_m16x8(a, self.splat_m16x8(m16::new(true)))
387 }
388
389 #[inline(always)]
391 pub fn not_m32x4(self, a: m32x4) -> m32x4 {
392 self.xor_m32x4(a, self.splat_m32x4(m32::new(true)))
393 }
394
395 #[inline(always)]
397 pub fn not_m64x2(self, a: m64x2) -> m64x2 {
398 self.xor_m64x2(a, self.splat_m64x2(m64::new(true)))
399 }
400
401 #[inline(always)]
403 pub fn not_m8x16(self, a: m8x16) -> m8x16 {
404 self.xor_m8x16(a, self.splat_m8x16(m8::new(true)))
405 }
406
407 #[inline(always)]
409 pub fn not_u16x8(self, a: u16x8) -> u16x8 {
410 self.xor_u16x8(a, self.splat_u16x8(!0))
411 }
412
413 #[inline(always)]
415 pub fn not_u32x4(self, a: u32x4) -> u32x4 {
416 self.xor_u32x4(a, self.splat_u32x4(!0))
417 }
418
419 #[inline(always)]
421 pub fn not_u64x2(self, a: u64x2) -> u64x2 {
422 self.xor_u64x2(a, self.splat_u64x2(!0))
423 }
424
425 #[inline(always)]
427 pub fn not_u8x16(self, a: u8x16) -> u8x16 {
428 self.xor_u8x16(a, self.splat_u8x16(!0))
429 }
430
431 #[inline(always)]
435 pub fn pack_with_signed_saturation_i16x8(self, a: i16x8, b: i16x8) -> i8x16 {
436 cast!(self.sse2._mm_packs_epi16(cast!(a), cast!(b)))
437 }
438
439 #[inline(always)]
443 pub fn pack_with_signed_saturation_i32x4(self, a: i32x4, b: i32x4) -> i16x8 {
444 cast!(self.sse2._mm_packs_epi32(cast!(a), cast!(b)))
445 }
446
447 #[inline(always)]
451 pub fn pack_with_unsigned_saturation_i16x8(self, a: i16x8, b: i16x8) -> u8x16 {
452 cast!(self.sse2._mm_packus_epi16(cast!(a), cast!(b)))
453 }
454
455 #[inline(always)]
456 pub fn reduce_max_c32x2(self, a: f32x4) -> c32 {
457 let a: __m128 = cast!(a);
459 let hi = self.sse._mm_movehl_ps(a, a);
461
462 let r0 = self.sse._mm_max_ps(a, hi);
464
465 cast!(self.sse2._mm_cvtsd_f64(cast!(r0)))
466 }
467
468 #[inline(always)]
469 pub fn reduce_max_c64x1(self, a: f64x2) -> c64 {
470 cast!(a)
471 }
472
473 #[inline(always)]
474 pub fn reduce_max_f32x4(self, a: f32x4) -> f32 {
475 let a: __m128 = cast!(a);
476 let hi = self.sse._mm_movehl_ps(a, a);
477 let r0 = self.sse._mm_max_ps(a, hi);
478 let r0_shuffled = self.sse._mm_shuffle_ps::<0b0001>(r0, r0);
479 let r = self.sse._mm_max_ss(r0, r0_shuffled);
480 self.sse._mm_cvtss_f32(r)
481 }
482
483 #[inline(always)]
484 pub fn reduce_max_f64x2(self, a: f64x2) -> f64 {
485 let a: __m128d = cast!(a);
486 let hi = cast!(self.sse._mm_movehl_ps(cast!(a), cast!(a)));
487 let r = self.sse2._mm_max_sd(a, hi);
488 self.sse2._mm_cvtsd_f64(r)
489 }
490
491 #[inline(always)]
492 pub fn reduce_min_c32x2(self, a: f32x4) -> c32 {
493 let a: __m128 = cast!(a);
495 let hi = self.sse._mm_movehl_ps(a, a);
497
498 let r0 = self.sse._mm_min_ps(a, hi);
500
501 cast!(self.sse2._mm_cvtsd_f64(cast!(r0)))
502 }
503
504 #[inline(always)]
505 pub fn reduce_min_c64x1(self, a: f64x2) -> c64 {
506 cast!(a)
507 }
508
509 #[inline(always)]
510 pub fn reduce_min_f32x4(self, a: f32x4) -> f32 {
511 let a: __m128 = cast!(a);
512 let hi = self.sse._mm_movehl_ps(a, a);
513 let r0 = self.sse._mm_min_ps(a, hi);
514 let r0_shuffled = self.sse._mm_shuffle_ps::<0b0001>(r0, r0);
515 let r = self.sse._mm_min_ss(r0, r0_shuffled);
516 self.sse._mm_cvtss_f32(r)
517 }
518
519 #[inline(always)]
520 pub fn reduce_min_f64x2(self, a: f64x2) -> f64 {
521 let a: __m128d = cast!(a);
522 let hi = cast!(self.sse._mm_movehl_ps(cast!(a), cast!(a)));
523 let r = self.sse2._mm_min_sd(a, hi);
524 self.sse2._mm_cvtsd_f64(r)
525 }
526
527 #[inline(always)]
528 pub fn reduce_product_f32x4(self, a: f32x4) -> f32 {
529 let a: __m128 = cast!(a);
530 let hi = self.sse._mm_movehl_ps(a, a);
531 let r0 = self.sse._mm_mul_ps(a, hi);
532 let r0_shuffled = self.sse._mm_shuffle_ps::<0b0001>(r0, r0);
533 let r = self.sse._mm_mul_ss(r0, r0_shuffled);
534 self.sse._mm_cvtss_f32(r)
535 }
536
537 #[inline(always)]
538 pub fn reduce_product_f64x2(self, a: f64x2) -> f64 {
539 let a: __m128d = cast!(a);
540 let hi = cast!(self.sse._mm_movehl_ps(cast!(a), cast!(a)));
541 let r = self.sse2._mm_mul_sd(a, hi);
542 self.sse2._mm_cvtsd_f64(r)
543 }
544
545 #[inline(always)]
546 pub fn reduce_sum_c32x2(self, a: f32x4) -> c32 {
547 let a: __m128 = cast!(a);
549 let hi = self.sse._mm_movehl_ps(a, a);
551
552 let r0 = self.sse._mm_add_ps(a, hi);
554
555 cast!(self.sse2._mm_cvtsd_f64(cast!(r0)))
556 }
557
558 #[inline(always)]
559 pub fn reduce_sum_c64x1(self, a: f64x2) -> c64 {
560 cast!(a)
561 }
562
563 #[inline(always)]
564 pub fn reduce_sum_f32x4(self, a: f32x4) -> f32 {
565 let a: __m128 = cast!(a);
567 let hi = self.sse._mm_movehl_ps(a, a);
569
570 let r0 = self.sse._mm_add_ps(a, hi);
572 let r0_shuffled = self.sse._mm_shuffle_ps::<0b0001>(r0, r0);
574
575 let r = self.sse._mm_add_ss(r0, r0_shuffled);
576
577 self.sse._mm_cvtss_f32(r)
578 }
579
580 #[inline(always)]
581 pub fn reduce_sum_f64x2(self, a: f64x2) -> f64 {
582 let a: __m128d = cast!(a);
583 let hi = cast!(self.sse._mm_movehl_ps(cast!(a), cast!(a)));
584 let r = self.sse2._mm_add_sd(a, hi);
585 self.sse2._mm_cvtsd_f64(r)
586 }
587
588 #[inline(always)]
591 pub fn shl_const_i16x8<const AMOUNT: i32>(self, a: i16x8) -> i16x8 {
592 cast!(self.sse2._mm_slli_epi16::<AMOUNT>(cast!(a)))
593 }
594
595 #[inline(always)]
598 pub fn shl_const_i32x4<const AMOUNT: i32>(self, a: i32x4) -> i32x4 {
599 cast!(self.sse2._mm_slli_epi32::<AMOUNT>(cast!(a)))
600 }
601
602 #[inline(always)]
605 pub fn shl_const_i64x2<const AMOUNT: i32>(self, a: i64x2) -> i64x2 {
606 cast!(self.sse2._mm_slli_epi64::<AMOUNT>(cast!(a)))
607 }
608
609 #[inline(always)]
612 pub fn shl_const_u16x8<const AMOUNT: i32>(self, a: u16x8) -> u16x8 {
613 cast!(self.sse2._mm_slli_epi16::<AMOUNT>(cast!(a)))
614 }
615
616 #[inline(always)]
619 pub fn shl_const_u32x4<const AMOUNT: i32>(self, a: u32x4) -> u32x4 {
620 cast!(self.sse2._mm_slli_epi32::<AMOUNT>(cast!(a)))
621 }
622
623 #[inline(always)]
626 pub fn shl_const_u64x2<const AMOUNT: i32>(self, a: u64x2) -> u64x2 {
627 cast!(self.sse2._mm_slli_epi64::<AMOUNT>(cast!(a)))
628 }
629
630 #[inline(always)]
634 pub fn shl_i16x8(self, a: i16x8, amount: u64x2) -> i16x8 {
635 cast!(self.sse2._mm_sll_epi16(cast!(a), cast!(amount)))
636 }
637
638 #[inline(always)]
642 pub fn shl_i32x4(self, a: i32x4, amount: u64x2) -> i32x4 {
643 cast!(self.sse2._mm_sll_epi32(cast!(a), cast!(amount)))
644 }
645
646 #[inline(always)]
650 pub fn shl_i64x2(self, a: i64x2, amount: u64x2) -> u64x2 {
651 cast!(self.sse2._mm_sll_epi64(cast!(a), cast!(amount)))
652 }
653
654 #[inline(always)]
658 pub fn shl_u16x8(self, a: u16x8, amount: u64x2) -> u16x8 {
659 cast!(self.sse2._mm_sll_epi16(cast!(a), cast!(amount)))
660 }
661
662 #[inline(always)]
666 pub fn shl_u32x4(self, a: u32x4, amount: u64x2) -> u32x4 {
667 cast!(self.sse2._mm_sll_epi32(cast!(a), cast!(amount)))
668 }
669
670 #[inline(always)]
674 pub fn shl_u64x2(self, a: u64x2, amount: u64x2) -> u64x2 {
675 cast!(self.sse2._mm_sll_epi64(cast!(a), cast!(amount)))
676 }
677
678 #[inline(always)]
682 pub fn shr_const_i16x8<const AMOUNT: i32>(self, a: i16x8) -> i16x8 {
683 cast!(self.sse2._mm_srai_epi16::<AMOUNT>(cast!(a)))
684 }
685
686 #[inline(always)]
690 pub fn shr_const_i32x4<const AMOUNT: i32>(self, a: i32x4) -> i32x4 {
691 cast!(self.sse2._mm_srai_epi32::<AMOUNT>(cast!(a)))
692 }
693
694 #[inline(always)]
697 pub fn shr_const_u16x8<const AMOUNT: i32>(self, a: u16x8) -> u16x8 {
698 cast!(self.sse2._mm_srli_epi16::<AMOUNT>(cast!(a)))
699 }
700
701 #[inline(always)]
704 pub fn shr_const_u32x4<const AMOUNT: i32>(self, a: u32x4) -> u32x4 {
705 cast!(self.sse2._mm_srli_epi32::<AMOUNT>(cast!(a)))
706 }
707
708 #[inline(always)]
711 pub fn shr_const_u64x2<const AMOUNT: i32>(self, a: u64x2) -> u64x2 {
712 cast!(self.sse2._mm_srli_epi64::<AMOUNT>(cast!(a)))
713 }
714
715 #[inline(always)]
720 pub fn shr_i16x8(self, a: i16x8, amount: u64x2) -> i16x8 {
721 cast!(self.sse2._mm_sra_epi16(cast!(a), cast!(amount)))
722 }
723
724 #[inline(always)]
729 pub fn shr_i32x4(self, a: i32x4, amount: u64x2) -> i32x4 {
730 cast!(self.sse2._mm_sra_epi32(cast!(a), cast!(amount)))
731 }
732
733 #[inline(always)]
737 pub fn shr_u16x8(self, a: u16x8, amount: u64x2) -> u16x8 {
738 cast!(self.sse2._mm_srl_epi16(cast!(a), cast!(amount)))
739 }
740
741 #[inline(always)]
745 pub fn shr_u32x4(self, a: u32x4, amount: u64x2) -> u32x4 {
746 cast!(self.sse2._mm_srl_epi32(cast!(a), cast!(amount)))
747 }
748
749 #[inline(always)]
753 pub fn shr_u64x2(self, a: u64x2, amount: u64x2) -> u64x2 {
754 cast!(self.sse2._mm_srl_epi64(cast!(a), cast!(amount)))
755 }
756
757 #[inline(always)]
759 pub fn splat_f32x4(self, value: f32) -> f32x4 {
760 cast!(self.sse._mm_set1_ps(value))
761 }
762
763 #[inline(always)]
765 pub fn splat_f64x2(self, value: f64) -> f64x2 {
766 cast!(self.sse2._mm_set1_pd(value))
767 }
768
769 #[inline(always)]
771 pub fn splat_i16x8(self, value: i16) -> i16x8 {
772 cast!(self.sse2._mm_set1_epi16(value))
773 }
774
775 #[inline(always)]
777 pub fn splat_i32x4(self, value: i32) -> i32x4 {
778 cast!(self.sse2._mm_set1_epi32(value))
779 }
780
781 #[inline(always)]
783 pub fn splat_i64x2(self, value: i64) -> i64x2 {
784 cast!(self.sse2._mm_set1_epi64x(value))
785 }
786
787 #[inline(always)]
789 pub fn splat_i8x16(self, value: i8) -> i8x16 {
790 cast!(self.sse2._mm_set1_epi8(value))
791 }
792
793 #[inline(always)]
795 pub fn splat_m16x8(self, value: m16) -> m16x8 {
796 cast!(self.sse2._mm_set1_epi16(value.0 as i16))
797 }
798
799 #[inline(always)]
801 pub fn splat_m32x4(self, value: m32) -> m32x4 {
802 cast!(self.sse2._mm_set1_epi32(value.0 as i32))
803 }
804
805 #[inline(always)]
807 pub fn splat_m64x2(self, value: m64) -> m64x2 {
808 cast!(self.sse2._mm_set1_epi64x(value.0 as i64))
809 }
810
811 #[inline(always)]
813 pub fn splat_m8x16(self, value: m8) -> m8x16 {
814 cast!(self.sse2._mm_set1_epi8(value.0 as i8))
815 }
816
817 #[inline(always)]
819 pub fn splat_u16x8(self, value: u16) -> u16x8 {
820 cast!(self.sse2._mm_set1_epi16(value as i16))
821 }
822
823 #[inline(always)]
825 pub fn splat_u32x4(self, value: u32) -> u32x4 {
826 cast!(self.sse2._mm_set1_epi32(value as i32))
827 }
828
829 #[inline(always)]
831 pub fn splat_u64x2(self, value: u64) -> u64x2 {
832 cast!(self.sse2._mm_set1_epi64x(value as i64))
833 }
834
835 #[inline(always)]
837 pub fn splat_u8x16(self, value: u8) -> u8x16 {
838 cast!(self.sse2._mm_set1_epi8(value as i8))
839 }
840
841 #[inline(always)]
843 pub fn sqrt_f32x4(self, a: f32x4) -> f32x4 {
844 cast!(self.sse._mm_sqrt_ps(cast!(a)))
845 }
846
847 #[inline(always)]
849 pub fn sqrt_f64x2(self, a: f64x2) -> f64x2 {
850 cast!(self.sse2._mm_sqrt_pd(cast!(a)))
851 }
852
853 #[inline(always)]
857 pub fn sum_of_absolute_differences_u8x16(self, a: u8x16, b: u8x16) -> u64x2 {
858 cast!(self.sse2._mm_sad_epu8(cast!(a), cast!(b)))
859 }
860
861 #[inline(always)]
864 pub fn widening_mul_i16x8(self, a: i16x8, b: i16x8) -> (u16x8, i16x8) {
865 (
866 cast!(self.sse2._mm_mullo_epi16(cast!(a), cast!(b))),
867 cast!(self.sse2._mm_mulhi_epi16(cast!(a), cast!(b))),
868 )
869 }
870
871 #[inline(always)]
874 pub fn widening_mul_u16x8(self, a: u16x8, b: u16x8) -> (u16x8, u16x8) {
875 (
876 cast!(self.sse2._mm_mullo_epi16(cast!(a), cast!(b))),
877 cast!(self.sse2._mm_mulhi_epu16(cast!(a), cast!(b))),
878 )
879 }
880}