safe_arch/x86_x64/sse2.rs
1#![cfg(target_feature = "sse2")]
2
3use super::*;
4
5/// Lanewise `a + b` with lanes as `i8`.
6/// ```
7/// # use safe_arch::*;
8/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
9/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
10/// let c: [i8; 16] = add_i8_m128i(a, b).into();
11/// assert_eq!(c, [0, 12, 4, 16, 8, 20, 12, 24, 16, 28, -10, 32, 34, -10, 38, -114]);
12/// ```
13#[must_use]
14#[inline(always)]
15#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
16pub fn add_i8_m128i(a: m128i, b: m128i) -> m128i {
17 m128i(unsafe { _mm_add_epi8(a.0, b.0) })
18}
19
20/// Lanewise `a + b` with lanes as `i16`.
21/// ```
22/// # use safe_arch::*;
23/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
24/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
25/// let c: [i16; 8] = add_i16_m128i(a, b).into();
26/// assert_eq!(c, [6, 8, 10, 12, -16, -28, -40, 44]);
27/// ```
28#[must_use]
29#[inline(always)]
30#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
31pub fn add_i16_m128i(a: m128i, b: m128i) -> m128i {
32 m128i(unsafe { _mm_add_epi16(a.0, b.0) })
33}
34
35/// Lanewise `a + b` with lanes as `i32`.
36/// ```
37/// # use safe_arch::*;
38/// let a = m128i::from([1, 2, 3, 4]);
39/// let b = m128i::from([5, 6, 7, 8]);
40/// let c: [i32; 4] = add_i32_m128i(a, b).into();
41/// assert_eq!(c, [6, 8, 10, 12]);
42/// ```
43#[must_use]
44#[inline(always)]
45#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
46pub fn add_i32_m128i(a: m128i, b: m128i) -> m128i {
47 m128i(unsafe { _mm_add_epi32(a.0, b.0) })
48}
49
50/// Lanewise `a + b` with lanes as `i64`.
51/// ```
52/// # use safe_arch::*;
53/// let a = m128i::from([92_i64, 87]);
54/// let b = m128i::from([-9001_i64, 1]);
55/// let c: [i64; 2] = add_i64_m128i(a, b).into();
56/// assert_eq!(c, [-8909, 88]);
57/// ```
58#[must_use]
59#[inline(always)]
60#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
61pub fn add_i64_m128i(a: m128i, b: m128i) -> m128i {
62 m128i(unsafe { _mm_add_epi64(a.0, b.0) })
63}
64
65/// Lanewise `a + b`.
66/// ```
67/// # use safe_arch::*;
68/// let a = m128d::from_array([92.0, 87.5]);
69/// let b = m128d::from_array([100.0, -6.0]);
70/// let c = add_m128d(a, b).to_array();
71/// assert_eq!(c, [192.0, 81.5]);
72/// ```
73#[must_use]
74#[inline(always)]
75#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
76pub fn add_m128d(a: m128d, b: m128d) -> m128d {
77 m128d(unsafe { _mm_add_pd(a.0, b.0) })
78}
79
80/// Lowest lane `a + b`, high lane unchanged.
81/// ```
82/// # use safe_arch::*;
83/// let a = m128d::from_array([92.0, 87.5]);
84/// let b = m128d::from_array([100.0, -600.0]);
85/// let c = add_m128d_s(a, b).to_array();
86/// assert_eq!(c, [192.0, 87.5]);
87/// ```
88#[must_use]
89#[inline(always)]
90#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
91pub fn add_m128d_s(a: m128d, b: m128d) -> m128d {
92 m128d(unsafe { _mm_add_sd(a.0, b.0) })
93}
94
95/// Lanewise saturating `a + b` with lanes as `i8`.
96/// ```
97/// # use safe_arch::*;
98/// let a = m128i::from([
99/// i8::MAX, i8::MIN, 3, 4, -1, -2, -3, -4,
100/// 3, 4, -1, -2, -1, -2, -3, -4,
101/// ]);
102/// let b = m128i::from([
103/// i8::MAX, i8::MIN, 7, 8, -15, -26, -37, 48,
104/// 7, 8, -15, -26, -15, -26, -37, 48,
105/// ]);
106/// let c: [i8; 16] = add_saturating_i8_m128i(a, b).into();
107/// assert_eq!(
108/// c,
109/// [
110/// i8::MAX, i8::MIN, 10, 12, -16, -28, -40, 44,
111/// 10, 12, -16, -28, -16, -28, -40, 44
112/// ]
113/// );
114/// ```
115#[must_use]
116#[inline(always)]
117#[rustfmt::skip]
118#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
119pub fn add_saturating_i8_m128i(a: m128i, b: m128i) -> m128i {
120 m128i(unsafe { _mm_adds_epi8(a.0, b.0) })
121}
122
123/// Lanewise saturating `a + b` with lanes as `i16`.
124/// ```
125/// # use safe_arch::*;
126/// let a = m128i::from([i16::MAX, i16::MIN, 3, 4, -1, -2, -3, -4]);
127/// let b = m128i::from([i16::MAX, i16::MIN, 7, 8, -15, -26, -37, 48]);
128/// let c: [i16; 8] = add_saturating_i16_m128i(a, b).into();
129/// assert_eq!(c, [i16::MAX, i16::MIN, 10, 12, -16, -28, -40, 44]);
130/// ```
131#[must_use]
132#[inline(always)]
133#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
134pub fn add_saturating_i16_m128i(a: m128i, b: m128i) -> m128i {
135 m128i(unsafe { _mm_adds_epi16(a.0, b.0) })
136}
137
138/// Lanewise saturating `a + b` with lanes as `u8`.
139/// ```
140/// # use safe_arch::*;
141/// let a = m128i::from([
142/// u8::MAX, 0, 3, 4, 254, 2, 3, 4,
143/// 3, 4, 1, 2, 1, 2, 128, 4,
144/// ]);
145/// let b = m128i::from([
146/// u8::MAX, 0, 7, 8, 15, 26, 37, 48,
147/// 7, 8, 15, 26, 15, 26, 37, 48,
148/// ]);
149/// let c: [u8; 16] = add_saturating_u8_m128i(a, b).into();
150/// assert_eq!(
151/// c,
152/// [
153/// u8::MAX, 0, 10, 12, 255, 28, 40, 52,
154/// 10, 12, 16, 28, 16, 28, 165, 52
155/// ]
156/// );
157/// ```
158#[must_use]
159#[inline(always)]
160#[rustfmt::skip]
161#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
162pub fn add_saturating_u8_m128i(a: m128i, b: m128i) -> m128i {
163 m128i(unsafe { _mm_adds_epu8(a.0, b.0) })
164}
165
166/// Lanewise saturating `a + b` with lanes as `u16`.
167/// ```
168/// # use safe_arch::*;
169/// let a = m128i::from([u16::MAX, 0, 3, 4, 1, 2, 3, 4]);
170/// let b = m128i::from([u16::MAX, 0, 7, 8, 15, 26, 37, 48]);
171/// let c: [u16; 8] = add_saturating_u16_m128i(a, b).into();
172/// assert_eq!(c, [u16::MAX, 0, 10, 12, 16, 28, 40, 52]);
173/// ```
174#[must_use]
175#[inline(always)]
176#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
177pub fn add_saturating_u16_m128i(a: m128i, b: m128i) -> m128i {
178 m128i(unsafe { _mm_adds_epu16(a.0, b.0) })
179}
180
181/// Bitwise `a & b`.
182/// ```
183/// # use safe_arch::*;
184/// let a = m128d::from_array([1.0, 0.0]);
185/// let b = m128d::from_array([1.0, 1.0]);
186/// let c = bitand_m128d(a, b).to_array();
187/// assert_eq!(c, [1.0, 0.0]);
188/// ```
189#[must_use]
190#[inline(always)]
191#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
192pub fn bitand_m128d(a: m128d, b: m128d) -> m128d {
193 m128d(unsafe { _mm_and_pd(a.0, b.0) })
194}
195
196/// Bitwise `a & b`.
197/// ```
198/// # use safe_arch::*;
199/// let a = m128i::from([1, 0, 1, 0]);
200/// let b = m128i::from([1, 1, 0, 0]);
201/// let c: [i32; 4] = bitand_m128i(a, b).into();
202/// assert_eq!(c, [1, 0, 0, 0]);
203/// ```
204#[must_use]
205#[inline(always)]
206#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
207pub fn bitand_m128i(a: m128i, b: m128i) -> m128i {
208 m128i(unsafe { _mm_and_si128(a.0, b.0) })
209}
210
211/// Bitwise `(!a) & b`.
212/// ```
213/// # use safe_arch::*;
214/// let a = m128d::from_array([1.0, 0.0]);
215/// let b = m128d::from_array([1.0, 1.0]);
216/// let c = bitandnot_m128d(a, b).to_array();
217/// assert_eq!(c, [0.0, 1.0]);
218/// ```
219#[must_use]
220#[inline(always)]
221#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
222pub fn bitandnot_m128d(a: m128d, b: m128d) -> m128d {
223 m128d(unsafe { _mm_andnot_pd(a.0, b.0) })
224}
225
226/// Bitwise `(!a) & b`.
227/// ```
228/// # use safe_arch::*;
229/// let a = m128i::from([1, 0, 1, 0]);
230/// let b = m128i::from([1, 1, 0, 0]);
231/// let c: [i32; 4] = bitandnot_m128i(a, b).into();
232/// assert_eq!(c, [0, 1, 0, 0]);
233/// ```
234#[must_use]
235#[inline(always)]
236#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
237pub fn bitandnot_m128i(a: m128i, b: m128i) -> m128i {
238 m128i(unsafe { _mm_andnot_si128(a.0, b.0) })
239}
240
241/// Lanewise average of the `u8` values.
242/// ```
243/// # use safe_arch::*;
244/// let a = m128i::from([
245/// u8::MAX, 0, 3, 4, 254, 2, 3, 4,
246/// 3, 4, 1, 2, 1, 2, 128, 4,
247/// ]);
248/// let b = m128i::from([
249/// u8::MAX, 0, 7, 8, 15, 26, 37, 48,
250/// 7, 8, 15, 26, 15, 26, 37, 48,
251/// ]);
252/// let c: [u8; 16] = average_u8_m128i(a, b).into();
253/// assert_eq!(
254/// c,
255/// [
256/// u8::MAX, 0, 5, 6, 135, 14, 20, 26,
257/// 5, 6, 8, 14, 8, 14, 83, 26
258/// ]
259/// );
260/// ```
261#[must_use]
262#[inline(always)]
263#[rustfmt::skip]
264#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
265pub fn average_u8_m128i(a: m128i, b: m128i) -> m128i {
266 m128i(unsafe { _mm_avg_epu8(a.0, b.0) })
267}
268
269/// Lanewise average of the `u16` values.
270/// ```
271/// # use safe_arch::*;
272/// let a = m128i::from([u16::MAX, 0, 3, 4, 1, 2, 3, 4]);
273/// let b = m128i::from([u16::MAX, 0, 7, 8, 15, 26, 37, 48]);
274/// let c: [u16; 8] = average_u16_m128i(a, b).into();
275/// assert_eq!(c, [u16::MAX, 0, 5, 6, 8, 14, 20, 26]);
276/// ```
277#[must_use]
278#[inline(always)]
279#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
280pub fn average_u16_m128i(a: m128i, b: m128i) -> m128i {
281 m128i(unsafe { _mm_avg_epu16(a.0, b.0) })
282}
283
284/// Shifts all bits in the entire register left by a number of **bytes**.
285///
286/// ```
287/// # use safe_arch::*;
288/// let a = m128i::from(0x0000000B_0000000A_0000000F_11111111_u128);
289/// //
290/// let b: u128 = byte_shl_imm_u128_m128i::<1>(a).into();
291/// assert_eq!(b, 0x00000B00_00000A00_00000F11_11111100);
292/// ```
293#[must_use]
294#[inline(always)]
295#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
296pub fn byte_shl_imm_u128_m128i<const IMM: i32>(a: m128i) -> m128i {
297 m128i(unsafe { _mm_bslli_si128(a.0, IMM) })
298}
299
300/// Shifts all bits in the entire register right by a number of **bytes**.
301///
302/// ```
303/// # use safe_arch::*;
304/// let a = m128i::from(0x0000000B_0000000A_0000000F_11111111_u128);
305/// //
306/// let c: u128 = byte_shr_imm_u128_m128i::<1>(a).into();
307/// assert_eq!(c, 0x00000000_0B000000_0A000000_0F111111);
308/// ```
309#[must_use]
310#[inline(always)]
311#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
312pub fn byte_shr_imm_u128_m128i<const IMM: i32>(a: m128i) -> m128i {
313 m128i(unsafe { _mm_bsrli_si128(a.0, IMM) })
314}
315
316/// Bit-preserving cast to `m128` from `m128d`
317/// ```
318/// # use safe_arch::*;
319/// let a = m128d::from_array([1.0, 2.0]);
320/// let c: [u32; 4] = cast_to_m128_from_m128d(a).to_bits();
321/// assert_eq!(c, [0, 0x3FF00000, 0, 0x40000000]);
322/// ```
323#[must_use]
324#[inline(always)]
325#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
326pub fn cast_to_m128_from_m128d(a: m128d) -> m128 {
327 m128(unsafe { _mm_castpd_ps(a.0) })
328}
329
330/// Bit-preserving cast to `m128i` from `m128d`
331/// ```
332/// # use safe_arch::*;
333/// let a = m128d::from_array([1.0, 2.0]);
334/// let c: [u32; 4] = cast_to_m128i_from_m128d(a).into();
335/// assert_eq!(c, [0, 0x3FF00000, 0, 0x40000000]);
336/// ```
337#[must_use]
338#[inline(always)]
339#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
340pub fn cast_to_m128i_from_m128d(a: m128d) -> m128i {
341 m128i(unsafe { _mm_castpd_si128(a.0) })
342}
343
344/// Bit-preserving cast to `m128d` from `m128`
345/// ```
346/// # use safe_arch::*;
347/// let a = m128::from_array([1.0, 2.0, 3.0, 4.0]);
348/// let c: [u64; 2] = cast_to_m128d_from_m128(a).to_bits();
349/// assert_eq!(c, [0x400000003F800000, 0x4080000040400000]);
350/// ```
351#[must_use]
352#[inline(always)]
353#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
354pub fn cast_to_m128d_from_m128(a: m128) -> m128d {
355 m128d(unsafe { _mm_castps_pd(a.0) })
356}
357
358/// Bit-preserving cast to `m128i` from `m128`
359/// ```
360/// # use safe_arch::*;
361/// let a = m128::from_array([1.0, 2.0, 3.0, 4.0]);
362/// let c: [u32; 4] = cast_to_m128i_from_m128(a).into();
363/// assert_eq!(c, [0x3F800000, 0x40000000, 0x40400000, 0x40800000]);
364/// ```
365#[must_use]
366#[inline(always)]
367#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
368pub fn cast_to_m128i_from_m128(a: m128) -> m128i {
369 m128i(unsafe { _mm_castps_si128(a.0) })
370}
371
372/// Bit-preserving cast to `m128d` from `m128i`
373/// ```
374/// # use safe_arch::*;
375/// let a = m128i::from([1, 2, 3, 4]);
376/// let c: [u64; 2] = cast_to_m128d_from_m128i(a).to_bits();
377/// assert_eq!(c, [0x200000001, 0x400000003]);
378/// ```
379#[must_use]
380#[inline(always)]
381#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
382pub fn cast_to_m128d_from_m128i(a: m128i) -> m128d {
383 m128d(unsafe { _mm_castsi128_pd(a.0) })
384}
385
386/// Bit-preserving cast to `m128` from `m128i`
387/// ```
388/// # use safe_arch::*;
389/// let a = m128i::from([1, 2, 3, 4]);
390/// let c: [u32; 4] = cast_to_m128_from_m128i(a).to_bits();
391/// assert_eq!(c, [1, 2, 3, 4]);
392/// ```
393#[must_use]
394#[inline(always)]
395#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
396pub fn cast_to_m128_from_m128i(a: m128i) -> m128 {
397 m128(unsafe { _mm_castsi128_ps(a.0) })
398}
399
400/// Lanewise `a == b` with lanes as `i8`.
401///
402/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
403/// ```
404/// # use safe_arch::*;
405/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 127]);
406/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
407/// let c: [i8; 16] = cmp_eq_mask_i8_m128i(a, b).into();
408/// assert_eq!(c, [-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, 0, 0, 0, 0, -1]);
409/// ```
410#[must_use]
411#[inline(always)]
412#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
413pub fn cmp_eq_mask_i8_m128i(a: m128i, b: m128i) -> m128i {
414 m128i(unsafe { _mm_cmpeq_epi8(a.0, b.0) })
415}
416
417/// Lanewise `a == b` with lanes as `i16`.
418///
419/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
420/// ```
421/// # use safe_arch::*;
422/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
423/// let b = m128i::from([5_i16, 2, 7, 4, -15, -26, -37, -4]);
424/// let c: [i16; 8] = cmp_eq_mask_i16_m128i(a, b).into();
425/// assert_eq!(c, [0, -1, 0, -1, 0, 0, 0, -1]);
426/// ```
427#[must_use]
428#[inline(always)]
429#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
430pub fn cmp_eq_mask_i16_m128i(a: m128i, b: m128i) -> m128i {
431 m128i(unsafe { _mm_cmpeq_epi16(a.0, b.0) })
432}
433
434/// Lanewise `a == b` with lanes as `i32`.
435///
436/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
437/// ```
438/// # use safe_arch::*;
439/// let a = m128i::from([1, 2, 3, 4]);
440/// let b = m128i::from([5, 2, 7, 4]);
441/// let c: [i32; 4] = cmp_eq_mask_i32_m128i(a, b).into();
442/// assert_eq!(c, [0, -1, 0, -1]);
443/// ```
444#[must_use]
445#[inline(always)]
446#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
447pub fn cmp_eq_mask_i32_m128i(a: m128i, b: m128i) -> m128i {
448 m128i(unsafe { _mm_cmpeq_epi32(a.0, b.0) })
449}
450
451/// Lanewise `a == b`, mask output.
452///
453/// Mask output.
454/// ```
455/// # use safe_arch::*;
456/// let a = m128d::from_array([1.0, 0.0]);
457/// let b = m128d::from_array([1.0, 1.0]);
458/// let c = cmp_eq_mask_m128d(a, b).to_bits();
459/// assert_eq!(c, [u64::MAX, 0]);
460/// ```
461#[must_use]
462#[inline(always)]
463#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
464pub fn cmp_eq_mask_m128d(a: m128d, b: m128d) -> m128d {
465 m128d(unsafe { _mm_cmpeq_pd(a.0, b.0) })
466}
467
468/// Low lane `a == b`, other lanes unchanged.
469///
470/// Mask output.
471/// ```
472/// # use safe_arch::*;
473/// let a = m128d::from_array([1.0, 5.0]);
474/// let b = m128d::from_array([1.0, 1.0]);
475/// let c = cmp_eq_mask_m128d_s(a, b).to_bits();
476/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
477/// ```
478#[must_use]
479#[inline(always)]
480#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
481pub fn cmp_eq_mask_m128d_s(a: m128d, b: m128d) -> m128d {
482 m128d(unsafe { _mm_cmpeq_sd(a.0, b.0) })
483}
484
485/// Lanewise `a >= b`.
486///
487/// Mask output.
488/// ```
489/// # use safe_arch::*;
490/// let a = m128d::from_array([3.0, 1.0]);
491/// let b = m128d::from_array([1.0, 1.0]);
492/// let c = cmp_ge_mask_m128d(a, b).to_bits();
493/// assert_eq!(c, [u64::MAX, u64::MAX]);
494/// ```
495#[must_use]
496#[inline(always)]
497#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
498pub fn cmp_ge_mask_m128d(a: m128d, b: m128d) -> m128d {
499 m128d(unsafe { _mm_cmpge_pd(a.0, b.0) })
500}
501
502/// Low lane `a >= b`, other lanes unchanged.
503///
504/// Mask output.
505/// ```
506/// # use safe_arch::*;
507/// let a = m128d::from_array([1.0, 5.0]);
508/// let b = m128d::from_array([1.0, 1.0]);
509/// let c = cmp_ge_mask_m128d_s(a, b).to_bits();
510/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
511/// ```
512#[must_use]
513#[inline(always)]
514#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
515pub fn cmp_ge_mask_m128d_s(a: m128d, b: m128d) -> m128d {
516 m128d(unsafe { _mm_cmpge_sd(a.0, b.0) })
517}
518
519/// Lanewise `a > b` with lanes as `i8`.
520///
521/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
522/// ```
523/// # use safe_arch::*;
524/// let a = m128i::from([1_i8, 1, 20, 3, 40, 5, 60, 7, 80, 9, 10, 11, 12, 13, 14, 127]);
525/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 120]);
526/// let c: [i8; 16] = cmp_gt_mask_i8_m128i(a, b).into();
527/// assert_eq!(c, [-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 0, -1, 0, -1]);
528/// ```
529#[must_use]
530#[inline(always)]
531#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
532pub fn cmp_gt_mask_i8_m128i(a: m128i, b: m128i) -> m128i {
533 m128i(unsafe { _mm_cmpgt_epi8(a.0, b.0) })
534}
535
536/// Lanewise `a > b` with lanes as `i16`.
537///
538/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
539/// ```
540/// # use safe_arch::*;
541/// let a = m128i::from([1_i16, 20, 3, 40, -1, -2, -3, 0]);
542/// let b = m128i::from([5_i16, 2, 7, 4, -15, -26, -37, -4]);
543/// let c: [i16; 8] = cmp_gt_mask_i16_m128i(a, b).into();
544/// assert_eq!(c, [0, -1, 0, -1, -1, -1, -1, -1]);
545/// ```
546#[must_use]
547#[inline(always)]
548#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
549pub fn cmp_gt_mask_i16_m128i(a: m128i, b: m128i) -> m128i {
550 m128i(unsafe { _mm_cmpgt_epi16(a.0, b.0) })
551}
552
553/// Lanewise `a > b` with lanes as `i32`.
554///
555/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
556/// ```
557/// # use safe_arch::*;
558/// let a = m128i::from([1, 20, 7, 40]);
559/// let b = m128i::from([5, 2, 7, 4]);
560/// let c: [i32; 4] = cmp_gt_mask_i32_m128i(a, b).into();
561/// assert_eq!(c, [0, -1, 0, -1]);
562/// ```
563#[must_use]
564#[inline(always)]
565#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
566pub fn cmp_gt_mask_i32_m128i(a: m128i, b: m128i) -> m128i {
567 m128i(unsafe { _mm_cmpgt_epi32(a.0, b.0) })
568}
569
570/// Lanewise `a > b`.
571///
572/// Mask output.
573/// ```
574/// # use safe_arch::*;
575/// let a = m128d::from_array([2.0, 0.0]);
576/// let b = m128d::from_array([1.0, 1.0]);
577/// let c = cmp_gt_mask_m128d(a, b).to_bits();
578/// assert_eq!(c, [u64::MAX, 0]);
579/// ```
580#[must_use]
581#[inline(always)]
582#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
583pub fn cmp_gt_mask_m128d(a: m128d, b: m128d) -> m128d {
584 m128d(unsafe { _mm_cmpgt_pd(a.0, b.0) })
585}
586
587/// Low lane `a > b`, other lanes unchanged.
588///
589/// Mask output.
590/// ```
591/// # use safe_arch::*;
592/// let a = m128d::from_array([2.0, 5.0]);
593/// let b = m128d::from_array([1.0, 1.0]);
594/// let c = cmp_gt_mask_m128d_s(a, b).to_bits();
595/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
596/// ```
597#[must_use]
598#[inline(always)]
599#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
600pub fn cmp_gt_mask_m128d_s(a: m128d, b: m128d) -> m128d {
601 m128d(unsafe { _mm_cmpgt_sd(a.0, b.0) })
602}
603
604/// Lanewise `a <= b`.
605///
606/// Mask output.
607/// ```
608/// # use safe_arch::*;
609/// let a = m128d::from_array([0.0, 1.0]);
610/// let b = m128d::from_array([1.0, 1.0]);
611/// let c = cmp_le_mask_m128d(a, b).to_bits();
612/// assert_eq!(c, [u64::MAX, u64::MAX]);
613/// ```
614#[must_use]
615#[inline(always)]
616#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
617pub fn cmp_le_mask_m128d(a: m128d, b: m128d) -> m128d {
618 m128d(unsafe { _mm_cmple_pd(a.0, b.0) })
619}
620
621/// Low lane `a <= b`, other lanes unchanged.
622///
623/// Mask output.
624/// ```
625/// # use safe_arch::*;
626/// let a = m128d::from_array([0.0, 5.0]);
627/// let b = m128d::from_array([1.0, 1.0]);
628/// let c = cmp_le_mask_m128d_s(a, b).to_bits();
629/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
630/// ```
631#[must_use]
632#[inline(always)]
633#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
634pub fn cmp_le_mask_m128d_s(a: m128d, b: m128d) -> m128d {
635 m128d(unsafe { _mm_cmple_sd(a.0, b.0) })
636}
637
638/// Lanewise `a < b` with lanes as `i8`.
639///
640/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
641/// ```
642/// # use safe_arch::*;
643/// let a = m128i::from([1_i8, 1, 20, 3, 40, 5, 60, 7, 80, 9, 10, 11, 12, 13, 14, 127]);
644/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 120]);
645/// let c: [i8; 16] = cmp_lt_mask_i8_m128i(a, b).into();
646/// assert_eq!(c, [0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, -1, 0, -1, 0]);
647/// ```
648#[must_use]
649#[inline(always)]
650#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
651pub fn cmp_lt_mask_i8_m128i(a: m128i, b: m128i) -> m128i {
652 m128i(unsafe { _mm_cmplt_epi8(a.0, b.0) })
653}
654
655/// Lanewise `a < b` with lanes as `i16`.
656///
657/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
658/// ```
659/// # use safe_arch::*;
660/// let a = m128i::from([1_i16, 20, 3, 40, -1, -2, -3, 0]);
661/// let b = m128i::from([5_i16, 2, 7, 4, -15, -26, -37, -4]);
662/// let c: [i16; 8] = cmp_lt_mask_i16_m128i(a, b).into();
663/// assert_eq!(c, [-1, 0, -1, 0, 0, 0, 0, 0]);
664/// ```
665#[must_use]
666#[inline(always)]
667#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
668pub fn cmp_lt_mask_i16_m128i(a: m128i, b: m128i) -> m128i {
669 m128i(unsafe { _mm_cmplt_epi16(a.0, b.0) })
670}
671
672/// Lanewise `a < b` with lanes as `i32`.
673///
674/// All bits 1 for true (`-1`), all bit 0 for false (`0`).
675/// ```
676/// # use safe_arch::*;
677/// let a = m128i::from([1, 20, 7, 40]);
678/// let b = m128i::from([5, 2, 7, 4]);
679/// let c: [i32; 4] = cmp_lt_mask_i32_m128i(a, b).into();
680/// assert_eq!(c, [-1, 0, 0, 0]);
681/// ```
682#[must_use]
683#[inline(always)]
684#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
685pub fn cmp_lt_mask_i32_m128i(a: m128i, b: m128i) -> m128i {
686 m128i(unsafe { _mm_cmplt_epi32(a.0, b.0) })
687}
688
689/// Lanewise `a < b`.
690///
691/// Mask output.
692/// ```
693/// # use safe_arch::*;
694/// let a = m128d::from_array([0.0, 7.0]);
695/// let b = m128d::from_array([1.0, 1.0]);
696/// let c = cmp_lt_mask_m128d(a, b).to_bits();
697/// assert_eq!(c, [u64::MAX, 0]);
698/// ```
699#[must_use]
700#[inline(always)]
701#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
702pub fn cmp_lt_mask_m128d(a: m128d, b: m128d) -> m128d {
703 m128d(unsafe { _mm_cmplt_pd(a.0, b.0) })
704}
705
706/// Low lane `a < b`, other lane unchanged.
707///
708/// Mask output.
709/// ```
710/// # use safe_arch::*;
711/// let a = m128d::from_array([0.0, 5.0]);
712/// let b = m128d::from_array([1.0, 1.0]);
713/// let c = cmp_lt_mask_m128d_s(a, b).to_bits();
714/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
715/// ```
716#[must_use]
717#[inline(always)]
718#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
719pub fn cmp_lt_mask_m128d_s(a: m128d, b: m128d) -> m128d {
720 m128d(unsafe { _mm_cmplt_sd(a.0, b.0) })
721}
722
723/// Lanewise `a != b`.
724///
725/// Mask output.
726/// ```
727/// # use safe_arch::*;
728/// let a = m128d::from_array([3.0, 1.0]);
729/// let b = m128d::from_array([1.0, 1.0]);
730/// let c = cmp_neq_mask_m128d(a, b).to_bits();
731/// assert_eq!(c, [u64::MAX, 0]);
732/// ```
733#[must_use]
734#[inline(always)]
735#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
736pub fn cmp_neq_mask_m128d(a: m128d, b: m128d) -> m128d {
737 m128d(unsafe { _mm_cmpneq_pd(a.0, b.0) })
738}
739
740/// Low lane `a != b`, other lane unchanged.
741///
742/// Mask output.
743/// ```
744/// # use safe_arch::*;
745/// let a = m128d::from_array([2.0, 5.0]);
746/// let b = m128d::from_array([1.0, 1.0]);
747/// let c = cmp_neq_mask_m128d_s(a, b).to_bits();
748/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
749/// ```
750#[must_use]
751#[inline(always)]
752#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
753pub fn cmp_neq_mask_m128d_s(a: m128d, b: m128d) -> m128d {
754 m128d(unsafe { _mm_cmpneq_sd(a.0, b.0) })
755}
756
757/// Lanewise `!(a >= b)`.
758///
759/// Mask output.
760/// ```
761/// # use safe_arch::*;
762/// let a = m128d::from_array([3.0, 0.0]);
763/// let b = m128d::from_array([1.0, 1.0]);
764/// let c = cmp_nge_mask_m128d(a, b).to_bits();
765/// assert_eq!(c, [0, u64::MAX]);
766/// ```
767#[must_use]
768#[inline(always)]
769#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
770pub fn cmp_nge_mask_m128d(a: m128d, b: m128d) -> m128d {
771 m128d(unsafe { _mm_cmpnge_pd(a.0, b.0) })
772}
773
774/// Low lane `!(a >= b)`, other lane unchanged.
775///
776/// Mask output.
777/// ```
778/// # use safe_arch::*;
779/// let a = m128d::from_array([2.0, 5.0]);
780/// let b = m128d::from_array([1.0, 1.0]);
781/// let c = cmp_nge_mask_m128d_s(a, b).to_bits();
782/// assert_eq!(c, [0, 5_f64.to_bits()]);
783/// ```
784#[must_use]
785#[inline(always)]
786#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
787pub fn cmp_nge_mask_m128d_s(a: m128d, b: m128d) -> m128d {
788 m128d(unsafe { _mm_cmpnge_sd(a.0, b.0) })
789}
790
791/// Lanewise `!(a > b)`.
792///
793/// Mask output.
794/// ```
795/// # use safe_arch::*;
796/// let a = m128d::from_array([3.0, 0.0]);
797/// let b = m128d::from_array([1.0, 1.0]);
798/// let c = cmp_ngt_mask_m128d(a, b).to_bits();
799/// assert_eq!(c, [0, u64::MAX]);
800/// ```
801#[must_use]
802#[inline(always)]
803#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
804pub fn cmp_ngt_mask_m128d(a: m128d, b: m128d) -> m128d {
805 m128d(unsafe { _mm_cmpngt_pd(a.0, b.0) })
806}
807
808/// Low lane `!(a > b)`, other lane unchanged.
809///
810/// Mask output.
811/// ```
812/// # use safe_arch::*;
813/// let a = m128d::from_array([2.0, 5.0]);
814/// let b = m128d::from_array([1.0, 1.0]);
815/// let c = cmp_ngt_mask_m128d_s(a, b).to_bits();
816/// assert_eq!(c, [0, 5_f64.to_bits()]);
817/// ```
818#[must_use]
819#[inline(always)]
820#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
821pub fn cmp_ngt_mask_m128d_s(a: m128d, b: m128d) -> m128d {
822 m128d(unsafe { _mm_cmpngt_sd(a.0, b.0) })
823}
824
825/// Lanewise `!(a <= b)`.
826///
827/// Mask output.
828/// ```
829/// # use safe_arch::*;
830/// let a = m128d::from_array([3.0, 0.0]);
831/// let b = m128d::from_array([1.0, 1.0]);
832/// let c = cmp_nle_mask_m128d(a, b).to_bits();
833/// assert_eq!(c, [u64::MAX, 0]);
834/// ```
835#[must_use]
836#[inline(always)]
837#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
838pub fn cmp_nle_mask_m128d(a: m128d, b: m128d) -> m128d {
839 m128d(unsafe { _mm_cmpnle_pd(a.0, b.0) })
840}
841
842/// Low lane `!(a <= b)`, other lane unchanged.
843///
844/// Mask output.
845/// ```
846/// # use safe_arch::*;
847/// let a = m128d::from_array([2.0, 5.0]);
848/// let b = m128d::from_array([1.0, 1.0]);
849/// let c = cmp_nle_mask_m128d_s(a, b).to_bits();
850/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
851/// ```
852#[must_use]
853#[inline(always)]
854#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
855pub fn cmp_nle_mask_m128d_s(a: m128d, b: m128d) -> m128d {
856 m128d(unsafe { _mm_cmpnle_sd(a.0, b.0) })
857}
858
859/// Lanewise `!(a < b)`.
860///
861/// Mask output.
862/// ```
863/// # use safe_arch::*;
864/// let a = m128d::from_array([3.0, 0.0]);
865/// let b = m128d::from_array([1.0, 1.0]);
866/// let c = cmp_nlt_mask_m128d(a, b).to_bits();
867/// assert_eq!(c, [u64::MAX, 0]);
868/// ```
869#[must_use]
870#[inline(always)]
871#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
872pub fn cmp_nlt_mask_m128d(a: m128d, b: m128d) -> m128d {
873 m128d(unsafe { _mm_cmpnlt_pd(a.0, b.0) })
874}
875
876/// Low lane `!(a < b)`, other lane unchanged.
877///
878/// Mask output.
879/// ```
880/// # use safe_arch::*;
881/// let a = m128d::from_array([2.0, 5.0]);
882/// let b = m128d::from_array([1.0, 1.0]);
883/// let c = cmp_nlt_mask_m128d_s(a, b).to_bits();
884/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
885/// ```
886#[must_use]
887#[inline(always)]
888#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
889pub fn cmp_nlt_mask_m128d_s(a: m128d, b: m128d) -> m128d {
890 m128d(unsafe { _mm_cmpnlt_sd(a.0, b.0) })
891}
892
893/// Lanewise `(!a.is_nan()) & (!b.is_nan())`.
894///
895/// Mask output.
896/// ```
897/// # use safe_arch::*;
898/// let a = m128d::from_array([3.0, f64::NAN]);
899/// let b = m128d::from_array([1.0, 1.0]);
900/// let c = cmp_ordered_mask_m128d(a, b).to_bits();
901/// assert_eq!(c, [u64::MAX, 0]);
902/// ```
903#[must_use]
904#[inline(always)]
905#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
906pub fn cmp_ordered_mask_m128d(a: m128d, b: m128d) -> m128d {
907 m128d(unsafe { _mm_cmpord_pd(a.0, b.0) })
908}
909
910/// Low lane `(!a.is_nan()) & (!b.is_nan())`, other lane unchanged.
911///
912/// Mask output.
913/// ```
914/// # use safe_arch::*;
915/// let a = m128d::from_array([2.0, 5.0]);
916/// let b = m128d::from_array([1.0, 1.0]);
917/// let c = cmp_ordered_mask_m128d_s(a, b).to_bits();
918/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
919/// ```
920#[must_use]
921#[inline(always)]
922#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
923pub fn cmp_ordered_mask_m128d_s(a: m128d, b: m128d) -> m128d {
924 m128d(unsafe { _mm_cmpord_sd(a.0, b.0) })
925}
926
927/// Lanewise `a.is_nan() | b.is_nan()`.
928///
929/// Mask output.
930/// ```
931/// # use safe_arch::*;
932/// let a = m128d::from_array([f64::NAN, 0.0]);
933/// let b = m128d::from_array([1.0, 1.0]);
934/// let c = cmp_unord_mask_m128d(a, b).to_bits();
935/// assert_eq!(c, [u64::MAX, 0]);
936/// ```
937#[must_use]
938#[inline(always)]
939#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
940pub fn cmp_unord_mask_m128d(a: m128d, b: m128d) -> m128d {
941 m128d(unsafe { _mm_cmpunord_pd(a.0, b.0) })
942}
943
944/// Low lane `a.is_nan() | b.is_nan()`, other lane unchanged.
945///
946/// Mask output.
947/// ```
948/// # use safe_arch::*;
949/// let a = m128d::from_array([f64::NAN, 5.0]);
950/// let b = m128d::from_array([1.0, 1.0]);
951/// let c = cmp_unord_mask_m128d_s(a, b).to_bits();
952/// assert_eq!(c, [u64::MAX, 5_f64.to_bits()]);
953/// ```
954#[must_use]
955#[inline(always)]
956#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
957pub fn cmp_unord_mask_m128d_s(a: m128d, b: m128d) -> m128d {
958 m128d(unsafe { _mm_cmpunord_sd(a.0, b.0) })
959}
960
961/// Low lane `f64` equal to.
962///
963/// `i32` output.
964/// ```
965/// # use safe_arch::*;
966/// let a = m128d::from_array([1.0, 5.0]);
967/// let b = m128d::from_array([1.0, 1.0]);
968/// assert_eq!(1_i32, cmp_eq_i32_m128d_s(a, b));
969/// ```
970#[must_use]
971#[inline(always)]
972#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
973pub fn cmp_eq_i32_m128d_s(a: m128d, b: m128d) -> i32 {
974 unsafe { _mm_comieq_sd(a.0, b.0) }
975}
976
977/// Low lane `f64` greater than or equal to.
978///
979/// `i32` output.
980/// ```
981/// # use safe_arch::*;
982/// let a = m128d::from_array([1.0, 5.0]);
983/// let b = m128d::from_array([1.0, 1.0]);
984/// assert_eq!(1_i32, cmp_ge_i32_m128d_s(a, b));
985/// ```
986#[must_use]
987#[inline(always)]
988#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
989pub fn cmp_ge_i32_m128d_s(a: m128d, b: m128d) -> i32 {
990 unsafe { _mm_comige_sd(a.0, b.0) }
991}
992
993/// Low lane `f64` greater than.
994///
995/// `i32` output.
996/// ```
997/// # use safe_arch::*;
998/// let a = m128d::from_array([1.0, 5.0]);
999/// let b = m128d::from_array([1.0, 1.0]);
1000/// assert_eq!(1_i32, cmp_ge_i32_m128d_s(a, b));
1001/// ```
1002#[must_use]
1003#[inline(always)]
1004#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1005pub fn cmp_gt_i32_m128d_s(a: m128d, b: m128d) -> i32 {
1006 unsafe { _mm_comigt_sd(a.0, b.0) }
1007}
1008
1009/// Low lane `f64` less than or equal to.
1010///
1011/// `i32` output.
1012/// ```
1013/// # use safe_arch::*;
1014/// let a = m128d::from_array([1.0, 5.0]);
1015/// let b = m128d::from_array([1.0, 1.0]);
1016/// assert_eq!(1_i32, cmp_le_i32_m128d_s(a, b));
1017/// ```
1018#[must_use]
1019#[inline(always)]
1020#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1021pub fn cmp_le_i32_m128d_s(a: m128d, b: m128d) -> i32 {
1022 unsafe { _mm_comile_sd(a.0, b.0) }
1023}
1024
1025/// Low lane `f64` less than.
1026///
1027/// `i32` output.
1028/// ```
1029/// # use safe_arch::*;
1030/// let a = m128d::from_array([0.0, 5.0]);
1031/// let b = m128d::from_array([1.0, 1.0]);
1032/// assert_eq!(1_i32, cmp_lt_i32_m128d_s(a, b));
1033/// ```
1034#[must_use]
1035#[inline(always)]
1036#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1037pub fn cmp_lt_i32_m128d_s(a: m128d, b: m128d) -> i32 {
1038 unsafe { _mm_comilt_sd(a.0, b.0) }
1039}
1040
1041/// Low lane `f64` less than.
1042///
1043/// `i32` output.
1044/// ```
1045/// # use safe_arch::*;
1046/// let a = m128d::from_array([0.0, 5.0]);
1047/// let b = m128d::from_array([1.0, 1.0]);
1048/// assert_eq!(1_i32, cmp_neq_i32_m128d_s(a, b));
1049/// ```
1050#[must_use]
1051#[inline(always)]
1052#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1053pub fn cmp_neq_i32_m128d_s(a: m128d, b: m128d) -> i32 {
1054 unsafe { _mm_comineq_sd(a.0, b.0) }
1055}
1056
1057/// Rounds the lower two `i32` lanes to two `f64` lanes.
1058/// ```
1059/// # use safe_arch::*;
1060/// let a = m128i::from([1, 2, 3, 4]);
1061/// let b = convert_to_m128d_from_lower2_i32_m128i(a);
1062/// let c = m128d::from_array([1.0, 2.0]);
1063/// assert_eq!(b.to_bits(), c.to_bits());
1064/// ```
1065/// * **Intrinsic:** [`_mm_cvtepi32_pd`]
1066/// * **Assembly:** `cvtdq2pd xmm, xmm`
1067#[must_use]
1068#[inline(always)]
1069#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1070pub fn convert_to_m128d_from_lower2_i32_m128i(a: m128i) -> m128d {
1071 m128d(unsafe { _mm_cvtepi32_pd(a.0) })
1072}
1073
1074/// Rounds the four `i32` lanes to four `f32` lanes.
1075/// ```
1076/// # use safe_arch::*;
1077/// let a = m128i::from([1, 2, 3, 4]);
1078/// let b = convert_to_m128_from_i32_m128i(a);
1079/// let c = m128::from_array([1.0, 2.0, 3.0, 4.0]);
1080/// assert_eq!(b.to_bits(), c.to_bits());
1081/// ```
1082/// * **Intrinsic:** [`_mm_cvtepi32_ps`]
1083/// * **Assembly:** `cvtdq2ps xmm, xmm`
1084#[must_use]
1085#[inline(always)]
1086#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1087pub fn convert_to_m128_from_i32_m128i(a: m128i) -> m128 {
1088 m128(unsafe { _mm_cvtepi32_ps(a.0) })
1089}
1090
1091/// Rounds the two `f64` lanes to the low two `i32` lanes.
1092/// ```
1093/// # use safe_arch::*;
1094/// let a = m128d::from_array([1.0, 2.5]);
1095/// let b = convert_to_i32_m128i_from_m128d(a);
1096/// let c: [i32; 4] = b.into();
1097/// assert_eq!(c, [1, 2, 0, 0]);
1098/// ```
1099/// * **Intrinsic:** [`_mm_cvtpd_epi32`]
1100/// * **Assembly:** `cvtpd2dq xmm, xmm`
1101#[must_use]
1102#[inline(always)]
1103#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1104pub fn convert_to_i32_m128i_from_m128d(a: m128d) -> m128i {
1105 m128i(unsafe { _mm_cvtpd_epi32(a.0) })
1106}
1107
1108/// Rounds the two `f64` lanes to the low two `f32` lanes.
1109/// ```
1110/// # use safe_arch::*;
1111/// let a = m128d::from_array([1.0, 2.5]);
1112/// let b = convert_to_m128_from_m128d(a);
1113/// assert_eq!(b.to_bits(), [1_f32.to_bits(), 2.5_f32.to_bits(), 0, 0]);
1114/// ```
1115/// * **Intrinsic:** [`_mm_cvtpd_ps`]
1116/// * **Assembly:** `cvtpd2ps xmm, xmm`
1117#[must_use]
1118#[inline(always)]
1119#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1120pub fn convert_to_m128_from_m128d(a: m128d) -> m128 {
1121 m128(unsafe { _mm_cvtpd_ps(a.0) })
1122}
1123
1124/// Rounds the `f32` lanes to `i32` lanes.
1125/// ```
1126/// # use safe_arch::*;
1127/// let a = m128::from_array([1.0, 2.5, 3.0, 4.0]);
1128/// let b = convert_to_i32_m128i_from_m128(a);
1129/// let c: [i32; 4] = b.into();
1130/// assert_eq!(c, [1, 2, 3, 4]);
1131/// ```
1132/// * **Intrinsic:** [`_mm_cvtps_epi32`]
1133/// * **Assembly:** `cvtps2dq xmm, xmm`
1134#[must_use]
1135#[inline(always)]
1136#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1137pub fn convert_to_i32_m128i_from_m128(a: m128) -> m128i {
1138 m128i(unsafe { _mm_cvtps_epi32(a.0) })
1139}
1140
1141/// Rounds the two `f64` lanes to the low two `f32` lanes.
1142/// ```
1143/// # use safe_arch::*;
1144/// let a = m128::from_array([1.0, 2.5, 3.6, 4.7]);
1145/// let b = convert_to_m128d_from_lower2_m128(a);
1146/// assert_eq!(b.to_bits(), [1_f64.to_bits(), 2.5_f64.to_bits()]);
1147/// ```
1148/// * **Intrinsic:** [`_mm_cvtps_pd`]
1149/// * **Assembly:** `cvtps2pd xmm, xmm`
1150#[must_use]
1151#[inline(always)]
1152#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1153pub fn convert_to_m128d_from_lower2_m128(a: m128) -> m128d {
1154 m128d(unsafe { _mm_cvtps_pd(a.0) })
1155}
1156
1157/// Gets the lower lane as an `f64` value.
1158/// ```
1159/// # use safe_arch::*;
1160/// let a = m128d::from_array([1.0, 2.5]);
1161/// let b = get_f64_from_m128d_s(a);
1162/// assert_eq!(b, 1.0_f64);
1163/// ```
1164#[must_use]
1165#[inline(always)]
1166#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1167pub fn get_f64_from_m128d_s(a: m128d) -> f64 {
1168 unsafe { _mm_cvtsd_f64(a.0) }
1169}
1170
1171/// Converts the lower lane to an `i32` value.
1172/// ```
1173/// # use safe_arch::*;
1174/// let a = m128d::from_array([1.0, 2.5]);
1175/// let b = get_i32_from_m128d_s(a);
1176/// assert_eq!(b, 1_i32);
1177/// ```
1178#[must_use]
1179#[inline(always)]
1180#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1181pub fn get_i32_from_m128d_s(a: m128d) -> i32 {
1182 unsafe { _mm_cvtsd_si32(a.0) }
1183}
1184
1185/// Converts the lower lane to an `i64` value.
1186/// ```
1187/// # use safe_arch::*;
1188/// let a = m128d::from_array([1.0, 2.5]);
1189/// let b = get_i64_from_m128d_s(a);
1190/// assert_eq!(b, 1_i64);
1191/// ```
1192#[must_use]
1193#[inline(always)]
1194#[cfg(target_arch = "x86_64")]
1195#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1196pub fn get_i64_from_m128d_s(a: m128d) -> i64 {
1197 unsafe { _mm_cvtsd_si64(a.0) }
1198}
1199
1200/// Converts the low `f64` to `f32` and replaces the low lane of the input.
1201/// ```
1202/// # use safe_arch::*;
1203/// let a = m128::from_array([3.0, 4.0, 5.0, 6.0]);
1204/// let b = m128d::from_array([1.0, 2.5]);
1205/// let c = convert_m128d_s_replace_m128_s(a, b);
1206/// assert_eq!(c.to_array(), [1.0, 4.0, 5.0, 6.0]);
1207/// ```
1208/// * **Intrinsic:** [`_mm_cvtsd_ss`]
1209/// * **Assembly:** `cvtsd2ss xmm, xmm`
1210#[must_use]
1211#[inline(always)]
1212#[cfg(target_arch = "x86_64")]
1213#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1214pub fn convert_m128d_s_replace_m128_s(a: m128, b: m128d) -> m128 {
1215 m128(unsafe { _mm_cvtsd_ss(a.0, b.0) })
1216}
1217
1218/// Converts the lower lane to an `i32` value.
1219/// ```
1220/// # use safe_arch::*;
1221/// let a = m128i::from([1, 3, 5, 7]);
1222/// let b = get_i32_from_m128i_s(a);
1223/// assert_eq!(b, 1_i32);
1224/// ```
1225#[must_use]
1226#[inline(always)]
1227#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1228pub fn get_i32_from_m128i_s(a: m128i) -> i32 {
1229 unsafe { _mm_cvtsi128_si32(a.0) }
1230}
1231
1232/// Converts the lower lane to an `i64` value.
1233/// ```
1234/// # use safe_arch::*;
1235/// let a = m128i::from([1_i64, 3]);
1236/// let b = get_i64_from_m128i_s(a);
1237/// assert_eq!(b, 1_i64);
1238/// ```
1239#[must_use]
1240#[inline(always)]
1241#[cfg(target_arch = "x86_64")]
1242#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1243pub fn get_i64_from_m128i_s(a: m128i) -> i64 {
1244 unsafe { _mm_cvtsi128_si64(a.0) }
1245}
1246
1247/// Convert `i32` to `f64` and replace the low lane of the input.
1248/// ```
1249/// # use safe_arch::*;
1250/// let a = m128d::from_array([1.0, 2.0]);
1251/// let b = convert_i32_replace_m128d_s(a, 5_i32);
1252/// assert_eq!(b.to_array(), [5.0, 2.0]);
1253/// ```
1254/// * **Intrinsic:** [`_mm_cvtsi32_sd`]
1255/// * **Assembly:** `cvtsi2sd xmm, r32`
1256#[must_use]
1257#[inline(always)]
1258#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1259pub fn convert_i32_replace_m128d_s(a: m128d, i: i32) -> m128d {
1260 m128d(unsafe { _mm_cvtsi32_sd(a.0, i) })
1261}
1262
1263/// Set an `i32` as the low 32-bit lane of an `m128i`, other lanes blank.
1264/// ```
1265/// # use safe_arch::*;
1266/// let a: [i32; 4] = set_i32_m128i_s(1_i32).into();
1267/// let b: [i32; 4] = m128i::from([1, 0, 0, 0]).into();
1268/// assert_eq!(a, b);
1269/// ```
1270#[must_use]
1271#[inline(always)]
1272#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1273pub fn set_i32_m128i_s(i: i32) -> m128i {
1274 m128i(unsafe { _mm_cvtsi32_si128(i) })
1275}
1276
1277/// Convert `i64` to `f64` and replace the low lane of the input.
1278/// ```
1279/// # use safe_arch::*;
1280/// let a = m128d::from_array([1.0, 2.0]);
1281/// let b = convert_i64_replace_m128d_s(a, 5_i64);
1282/// assert_eq!(b.to_array(), [5.0, 2.0]);
1283/// ```
1284/// * **Intrinsic:** [`_mm_cvtsi64_sd`]
1285/// * **Assembly:** `cvtsi2sd xmm, r64`
1286#[must_use]
1287#[inline(always)]
1288#[cfg(target_arch = "x86_64")]
1289#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1290pub fn convert_i64_replace_m128d_s(a: m128d, i: i64) -> m128d {
1291 m128d(unsafe { _mm_cvtsi64_sd(a.0, i) })
1292}
1293
1294/// Set an `i64` as the low 64-bit lane of an `m128i`, other lanes blank.
1295/// ```
1296/// # use safe_arch::*;
1297/// let a: [i64; 2] = set_i64_m128i_s(1_i64).into();
1298/// let b: [i64; 2] = m128i::from([1_i64, 0]).into();
1299/// assert_eq!(a, b);
1300/// ```
1301#[must_use]
1302#[inline(always)]
1303#[cfg(target_arch = "x86_64")]
1304#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1305pub fn set_i64_m128i_s(i: i64) -> m128i {
1306 m128i(unsafe { _mm_cvtsi64_si128(i) })
1307}
1308
1309/// Converts the lower `f32` to `f64` and replace the low lane of the input
1310/// ```
1311/// # use safe_arch::*;
1312/// let a = m128d::from_array([1.0, 2.5]);
1313/// let b = m128::from_array([3.0, 4.0, 5.0, 6.0]);
1314/// let c = convert_m128_s_replace_m128d_s(a, b);
1315/// assert_eq!(c.to_array(), [3.0, 2.5]);
1316/// ```
1317/// * **Intrinsic:** [`_mm_cvtss_sd`]
1318/// * **Assembly:** `cvtss2sd xmm, xmm`
1319#[must_use]
1320#[inline(always)]
1321#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1322pub fn convert_m128_s_replace_m128d_s(a: m128d, b: m128) -> m128d {
1323 m128d(unsafe { _mm_cvtss_sd(a.0, b.0) })
1324}
1325
1326/// Truncate the `f64` lanes to the lower `i32` lanes (upper `i32` lanes 0).
1327/// ```
1328/// # use safe_arch::*;
1329/// let a = m128d::from_array([1.1, 2.6]);
1330/// let b = truncate_m128d_to_m128i(a);
1331/// assert_eq!(<[i32; 4]>::from(b), [1, 2, 0, 0]);
1332/// ```
1333#[must_use]
1334#[inline(always)]
1335#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1336pub fn truncate_m128d_to_m128i(a: m128d) -> m128i {
1337 m128i(unsafe { _mm_cvttpd_epi32(a.0) })
1338}
1339
1340/// Truncate the `f32` lanes to `i32` lanes.
1341/// ```
1342/// # use safe_arch::*;
1343/// let a = m128::from_array([1.1, 2.6, 3.5, 4.0]);
1344/// let b = truncate_m128_to_m128i(a);
1345/// assert_eq!(<[i32; 4]>::from(b), [1, 2, 3, 4]);
1346/// ```
1347#[must_use]
1348#[inline(always)]
1349#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1350pub fn truncate_m128_to_m128i(a: m128) -> m128i {
1351 m128i(unsafe { _mm_cvttps_epi32(a.0) })
1352}
1353
1354/// Truncate the lower lane into an `i32`.
1355/// ```
1356/// # use safe_arch::*;
1357/// let a = m128d::from_array([1.7, 2.6]);
1358/// assert_eq!(truncate_to_i32_m128d_s(a), 1_i32);
1359/// ```
1360#[must_use]
1361#[inline(always)]
1362#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1363pub fn truncate_to_i32_m128d_s(a: m128d) -> i32 {
1364 unsafe { _mm_cvttsd_si32(a.0) }
1365}
1366
1367/// Truncate the lower lane into an `i64`.
1368/// ```
1369/// # use safe_arch::*;
1370/// let a = m128d::from_array([1.7, 2.6]);
1371/// assert_eq!(truncate_to_i64_m128d_s(a), 1_i64);
1372/// ```
1373#[must_use]
1374#[inline(always)]
1375#[cfg(target_arch = "x86_64")]
1376#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1377pub fn truncate_to_i64_m128d_s(a: m128d) -> i64 {
1378 unsafe { _mm_cvttsd_si64(a.0) }
1379}
1380
1381/// Lanewise `a / b`.
1382/// ```
1383/// # use safe_arch::*;
1384/// let a = m128d::from_array([92.0, 42.0]);
1385/// let b = m128d::from_array([100.0, -6.0]);
1386/// let c = div_m128d(a, b).to_array();
1387/// assert_eq!(c, [0.92, -7.0]);
1388/// ```
1389#[must_use]
1390#[inline(always)]
1391#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1392pub fn div_m128d(a: m128d, b: m128d) -> m128d {
1393 m128d(unsafe { _mm_div_pd(a.0, b.0) })
1394}
1395
1396/// Lowest lane `a / b`, high lane unchanged.
1397/// ```
1398/// # use safe_arch::*;
1399/// let a = m128d::from_array([92.0, 87.5]);
1400/// let b = m128d::from_array([100.0, -600.0]);
1401/// let c = div_m128d_s(a, b).to_array();
1402/// assert_eq!(c, [0.92, 87.5]);
1403/// ```
1404#[must_use]
1405#[inline(always)]
1406#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1407pub fn div_m128d_s(a: m128d, b: m128d) -> m128d {
1408 m128d(unsafe { _mm_div_sd(a.0, b.0) })
1409}
1410
1411/// Gets an `i16` value out of an `m128i`, returns as `i32`.
1412///
1413/// The lane to get must be a constant in `0..8`.
1414///
1415/// ```
1416/// # use safe_arch::*;
1417/// let a = m128i::from([0xA_i16, 0xB, 0xC, 0xD, 0, 0, 0, 0]);
1418/// //
1419/// assert_eq!(extract_i16_as_i32_m128i::<0>(a), 0xA);
1420/// assert_eq!(extract_i16_as_i32_m128i::<1>(a), 0xB);
1421/// ```
1422#[must_use]
1423#[inline(always)]
1424#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1425pub fn extract_i16_as_i32_m128i<const LANE: i32>(a: m128i) -> i32 {
1426 unsafe { _mm_extract_epi16(a.0, LANE) }
1427}
1428
1429/// Inserts the low 16 bits of an `i32` value into an `m128i`.
1430///
1431/// The lane to get must be a constant in `0..8`.
1432///
1433/// ```
1434/// # use safe_arch::*;
1435/// let a = m128i::from([0xA_i16, 0xB, 0xC, 0xD, 0, 0, 0, 0]);
1436/// //
1437/// let b = insert_i16_from_i32_m128i::<0>(a, -1);
1438/// assert_eq!(<[i16; 8]>::from(b), [-1, 0xB, 0xC, 0xD, 0, 0, 0, 0]);
1439/// ```
1440#[must_use]
1441#[inline(always)]
1442#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1443pub fn insert_i16_from_i32_m128i<const LANE: i32>(a: m128i, i: i32) -> m128i {
1444 m128i(unsafe { _mm_insert_epi16(a.0, i, LANE) })
1445}
1446
1447/// Loads the reference into a register.
1448/// ```
1449/// # use safe_arch::*;
1450/// let a = m128d::from_array([10.0, 12.0]);
1451/// let b = load_m128d(&a);
1452/// assert_eq!(a.to_bits(), b.to_bits());
1453/// ```
1454#[must_use]
1455#[inline(always)]
1456#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1457pub fn load_m128d(a: &m128d) -> m128d {
1458 m128d(unsafe { _mm_load_pd(a as *const m128d as *const f64) })
1459}
1460
1461/// Loads the `f64` reference into all lanes of a register.
1462/// ```
1463/// # use safe_arch::*;
1464/// let a = 1.0;
1465/// let b = load_f64_splat_m128d(&a);
1466/// assert_eq!(m128d::from_array([1.0, 1.0]).to_bits(), b.to_bits());
1467/// ```
1468#[must_use]
1469#[inline(always)]
1470#[allow(clippy::trivially_copy_pass_by_ref)]
1471#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1472pub fn load_f64_splat_m128d(a: &f64) -> m128d {
1473 m128d(unsafe { _mm_load1_pd(a) })
1474}
1475
1476/// Loads the reference into the low lane of the register.
1477/// ```
1478/// # use safe_arch::*;
1479/// let a = 1.0;
1480/// let b = load_f64_m128d_s(&a);
1481/// assert_eq!(m128d::from_array([1.0, 0.0]).to_bits(), b.to_bits());
1482/// ```
1483#[must_use]
1484#[inline(always)]
1485#[allow(clippy::trivially_copy_pass_by_ref)]
1486#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1487pub fn load_f64_m128d_s(a: &f64) -> m128d {
1488 m128d(unsafe { _mm_load_sd(a) })
1489}
1490
1491/// Loads the reference into a register.
1492/// ```
1493/// # use safe_arch::*;
1494/// let a = m128i::from([1, 2, 3, 4]);
1495/// let b = load_m128i(&a);
1496/// assert_eq!(<[i32; 4]>::from(a), <[i32; 4]>::from(b));
1497/// ```
1498#[must_use]
1499#[inline(always)]
1500#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1501pub fn load_m128i(a: &m128i) -> m128i {
1502 m128i(unsafe { _mm_load_si128(a as *const m128i as *const __m128i) })
1503}
1504
1505/// Loads the reference into a register, replacing the high lane.
1506/// ```
1507/// # use safe_arch::*;
1508/// let a = m128d::from([1.0, 2.0]);
1509/// let double = 7.0;
1510/// let b = load_replace_high_m128d(a, &double);
1511/// assert_eq!(b.to_array(), [1.0, 7.0]);
1512/// ```
1513#[must_use]
1514#[inline(always)]
1515#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1516pub fn load_replace_high_m128d(a: m128d, b: &f64) -> m128d {
1517 m128d(unsafe { _mm_loadh_pd(a.0, b) })
1518}
1519
1520/// Loads the low `i64` into a register.
1521/// ```
1522/// # use safe_arch::*;
1523/// let a = m128i::from([1_i64, 2]);
1524/// let b = load_i64_m128i_s(&a);
1525/// assert_eq!([1_i64, 0], <[i64; 2]>::from(b));
1526/// ```
1527#[must_use]
1528#[inline(always)]
1529#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1530pub fn load_i64_m128i_s(a: &m128i) -> m128i {
1531 m128i(unsafe { _mm_loadl_epi64(a as *const m128i as *const __m128i) })
1532}
1533
1534/// Loads the reference into a register, replacing the low lane.
1535/// ```
1536/// # use safe_arch::*;
1537/// let a = m128d::from([1.0, 2.0]);
1538/// let double = 7.0;
1539/// let b = load_replace_low_m128d(a, &double);
1540/// assert_eq!(b.to_array(), [7.0, 2.0]);
1541/// ```
1542#[must_use]
1543#[inline(always)]
1544#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1545pub fn load_replace_low_m128d(a: m128d, b: &f64) -> m128d {
1546 m128d(unsafe { _mm_loadl_pd(a.0, b) })
1547}
1548
1549/// Loads the reference into a register with reversed order.
1550/// ```
1551/// # use safe_arch::*;
1552/// let a = m128d::from_array([10.0, 12.0]);
1553/// let b = load_reverse_m128d(&a);
1554/// assert_eq!(m128d::from_array([12.0, 10.0]).to_bits(), b.to_bits());
1555/// ```
1556#[must_use]
1557#[inline(always)]
1558#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1559pub fn load_reverse_m128d(a: &m128d) -> m128d {
1560 m128d(unsafe { _mm_loadr_pd(a as *const m128d as *const f64) })
1561}
1562
1563/// Loads the reference into a register.
1564///
1565/// This generally has no speed penalty if the reference happens to be 16-byte
1566/// aligned, but there is a slight speed penalty if the reference is only 8-byte
1567/// aligned.
1568/// ```
1569/// # use safe_arch::*;
1570/// let a = [10.0, 12.0];
1571/// let b = load_unaligned_m128d(&a);
1572/// assert_eq!(m128d::from_array(a).to_bits(), b.to_bits());
1573/// ```
1574#[must_use]
1575#[inline(always)]
1576#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1577pub fn load_unaligned_m128d(a: &[f64; 2]) -> m128d {
1578 m128d(unsafe { _mm_loadu_pd(a as *const [f64; 2] as *const f64) })
1579}
1580
1581/// Loads the reference into a register.
1582///
1583/// This generally has no speed penalty if the reference happens to be 16-byte
1584/// aligned, but there is a slight speed penalty if the reference is less
1585/// aligned.
1586/// ```
1587/// # use safe_arch::*;
1588/// let a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
1589/// let b = load_unaligned_m128i(&a);
1590/// assert_eq!(a, <[u8; 16]>::from(b));
1591/// ```
1592#[must_use]
1593#[inline(always)]
1594#[allow(clippy::cast_ptr_alignment)]
1595#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1596pub fn load_unaligned_m128i(a: &[u8; 16]) -> m128i {
1597 m128i(unsafe { _mm_loadu_si128(a as *const [u8; 16] as *const __m128i) })
1598}
1599
1600/// Multiply `i16` lanes producing `i32` values, horizontal add pairs of `i32`
1601/// values to produce the final output.
1602/// ```
1603/// # use safe_arch::*;
1604/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
1605/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
1606/// let c: [i32; 4] = mul_i16_horizontal_add_m128i(a, b).into();
1607/// assert_eq!(c, [17, 53, 67, -81]);
1608/// ```
1609#[must_use]
1610#[inline(always)]
1611#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1612pub fn mul_i16_horizontal_add_m128i(a: m128i, b: m128i) -> m128i {
1613 m128i(unsafe { _mm_madd_epi16(a.0, b.0) })
1614}
1615
1616/// Lanewise `max(a, b)` with lanes as `u8`.
1617/// ```
1618/// # use safe_arch::*;
1619/// let a = m128i::from([0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
1620/// let b = m128i::from([0_u8, 11, 2, 13, 4, 15, 6, 17, 8, 19, 20, 21, 22, 23, 24, 127]);
1621/// let c: [u8; 16] = max_u8_m128i(a, b).into();
1622/// assert_eq!(c, [0, 11, 2, 13, 4, 15, 6, 17, 8, 19, 20, 21, 22, 23, 24, 127]);
1623/// ```
1624#[must_use]
1625#[inline(always)]
1626#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1627pub fn max_u8_m128i(a: m128i, b: m128i) -> m128i {
1628 m128i(unsafe { _mm_max_epu8(a.0, b.0) })
1629}
1630
1631/// Lanewise `max(a, b)` with lanes as `i16`.
1632/// ```
1633/// # use safe_arch::*;
1634/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
1635/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
1636/// let c: [i16; 8] = max_i16_m128i(a, b).into();
1637/// assert_eq!(c, [5_i16, 6, 7, 8, -1, -2, -3, 48]);
1638/// ```
1639#[must_use]
1640#[inline(always)]
1641#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1642pub fn max_i16_m128i(a: m128i, b: m128i) -> m128i {
1643 m128i(unsafe { _mm_max_epi16(a.0, b.0) })
1644}
1645
1646/// Lanewise `max(a, b)`.
1647/// ```
1648/// # use safe_arch::*;
1649/// let a = m128d::from_array([5.0, 2.0]);
1650/// let b = m128d::from_array([1.0, 6.0]);
1651/// let c = max_m128d(a, b).to_array();
1652/// assert_eq!(c, [5.0, 6.0]);
1653/// ```
1654#[must_use]
1655#[inline(always)]
1656#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1657pub fn max_m128d(a: m128d, b: m128d) -> m128d {
1658 m128d(unsafe { _mm_max_pd(a.0, b.0) })
1659}
1660
1661/// Low lane `max(a, b)`, other lanes unchanged.
1662/// ```
1663/// # use safe_arch::*;
1664/// let a = m128d::from_array([1.0, 12.0]);
1665/// let b = m128d::from_array([5.0, 6.0]);
1666/// let c = max_m128d_s(a, b).to_array();
1667/// assert_eq!(c, [5.0, 12.0]);
1668/// ```
1669#[must_use]
1670#[inline(always)]
1671#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1672pub fn max_m128d_s(a: m128d, b: m128d) -> m128d {
1673 m128d(unsafe { _mm_max_sd(a.0, b.0) })
1674}
1675
1676/// Lanewise `min(a, b)` with lanes as `u8`.
1677/// ```
1678/// # use safe_arch::*;
1679/// let a = m128i::from([0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
1680/// let b = m128i::from([0_u8, 11, 2, 13, 4, 15, 6, 17, 8, 0, 20, 0, 22, 0, 24, 0]);
1681/// let c: [u8; 16] = min_u8_m128i(a, b).into();
1682/// assert_eq!(c, [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 0, 10, 0, 12, 0, 14, 0]);
1683/// ```
1684#[must_use]
1685#[inline(always)]
1686#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1687pub fn min_u8_m128i(a: m128i, b: m128i) -> m128i {
1688 m128i(unsafe { _mm_min_epu8(a.0, b.0) })
1689}
1690
1691/// Lanewise `min(a, b)` with lanes as `i16`.
1692/// ```
1693/// # use safe_arch::*;
1694/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
1695/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
1696/// let c: [i16; 8] = min_i16_m128i(a, b).into();
1697/// assert_eq!(c, [1_i16, 2, 3, 4, -15, -26, -37, -4]);
1698/// ```
1699#[must_use]
1700#[inline(always)]
1701#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1702pub fn min_i16_m128i(a: m128i, b: m128i) -> m128i {
1703 m128i(unsafe { _mm_min_epi16(a.0, b.0) })
1704}
1705
1706/// Lanewise `min(a, b)`.
1707/// ```
1708/// # use safe_arch::*;
1709/// let a = m128d::from_array([1.0, 12.0]);
1710/// let b = m128d::from_array([5.0, 6.0]);
1711/// let c = min_m128d(a, b).to_array();
1712/// assert_eq!(c, [1.0, 6.0]);
1713/// ```
1714#[must_use]
1715#[inline(always)]
1716#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1717pub fn min_m128d(a: m128d, b: m128d) -> m128d {
1718 m128d(unsafe { _mm_min_pd(a.0, b.0) })
1719}
1720
1721/// Low lane `min(a, b)`, other lanes unchanged.
1722/// ```
1723/// # use safe_arch::*;
1724/// let a = m128d::from_array([1.0, 12.0]);
1725/// let b = m128d::from_array([0.0, 6.0]);
1726/// let c = min_m128d_s(a, b).to_array();
1727/// assert_eq!(c, [0.0, 12.0]);
1728/// ```
1729#[must_use]
1730#[inline(always)]
1731#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1732pub fn min_m128d_s(a: m128d, b: m128d) -> m128d {
1733 m128d(unsafe { _mm_min_sd(a.0, b.0) })
1734}
1735
1736/// Copy the low `i64` lane to a new register, upper bits 0.
1737/// ```
1738/// # use safe_arch::*;
1739/// let a = m128i::from([1_i64, 2]);
1740/// let b = copy_i64_m128i_s(a);
1741/// assert_eq!(<[i64; 2]>::from(b), [1, 0]);
1742/// ```
1743#[must_use]
1744#[inline(always)]
1745#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1746pub fn copy_i64_m128i_s(a: m128i) -> m128i {
1747 m128i(unsafe { _mm_move_epi64(a.0) })
1748}
1749
1750/// Copies the `a` value and replaces the low lane with the low `b` value.
1751/// ```
1752/// # use safe_arch::*;
1753/// let a = m128d::from([1.0, 2.0]);
1754/// let b = m128d::from([3.0, 4.0]);
1755/// let c = copy_replace_low_f64_m128d(a, b);
1756/// assert_eq!(c.to_array(), [3.0, 2.0]);
1757/// ```
1758#[must_use]
1759#[inline(always)]
1760#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1761pub fn copy_replace_low_f64_m128d(a: m128d, b: m128d) -> m128d {
1762 m128d(unsafe { _mm_move_sd(a.0, b.0) })
1763}
1764
1765/// Gathers the `i8` sign bit of each lane.
1766///
1767/// The output has lane 0 as bit 0, lane 1 as bit 1, and so on.
1768/// ```
1769/// # use safe_arch::*;
1770/// let a = m128i::from([0_i8, -11, -2, 13, 4, 15, -6, 17, 8, 19, -20, 21, 22, 23, -24, 127]);
1771/// let i = move_mask_i8_m128i(a);
1772/// assert_eq!(i, 0b0100010001000110);
1773/// ```
1774#[must_use]
1775#[inline(always)]
1776#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1777pub fn move_mask_i8_m128i(a: m128i) -> i32 {
1778 unsafe { _mm_movemask_epi8(a.0) }
1779}
1780
1781/// Gathers the sign bit of each lane.
1782///
1783/// The output has lane 0 as bit 0, lane 1 as bit 1.
1784/// ```
1785/// # use safe_arch::*;
1786/// let a = m128d::from_array([-1.0, 12.0]);
1787/// let i = move_mask_m128d(a);
1788/// assert_eq!(i, 0b01);
1789/// ```
1790#[must_use]
1791#[inline(always)]
1792#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1793pub fn move_mask_m128d(a: m128d) -> i32 {
1794 unsafe { _mm_movemask_pd(a.0) }
1795}
1796
1797/// Multiplies the odd `u32` lanes and gives the widened (`u64`) results.
1798///
1799/// ```
1800/// # use safe_arch::*;
1801/// let a = m128i::from([1, 7, u32::MAX, 7]);
1802/// let b = m128i::from([5, 7, u32::MAX, 7]);
1803/// let c: [u64; 2] = mul_widen_u32_odd_m128i(a, b).into();
1804/// assert_eq!(c, [(1 * 5), (u32::MAX as u64 * u32::MAX as u64)]);
1805/// ```
1806#[must_use]
1807#[inline(always)]
1808#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1809pub fn mul_widen_u32_odd_m128i(a: m128i, b: m128i) -> m128i {
1810 m128i(unsafe { _mm_mul_epu32(a.0, b.0) })
1811}
1812
1813/// Lanewise `a * b`.
1814/// ```
1815/// # use safe_arch::*;
1816/// let a = m128d::from_array([92.0, 87.5]);
1817/// let b = m128d::from_array([100.0, -6.0]);
1818/// let c = mul_m128d(a, b).to_array();
1819/// assert_eq!(c, [9200.0, -525.0]);
1820/// ```
1821#[must_use]
1822#[inline(always)]
1823#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1824pub fn mul_m128d(a: m128d, b: m128d) -> m128d {
1825 m128d(unsafe { _mm_mul_pd(a.0, b.0) })
1826}
1827
1828/// Lowest lane `a * b`, high lane unchanged.
1829/// ```
1830/// # use safe_arch::*;
1831/// let a = m128d::from_array([92.0, 87.5]);
1832/// let b = m128d::from_array([100.0, -600.0]);
1833/// let c = mul_m128d_s(a, b).to_array();
1834/// assert_eq!(c, [9200.0, 87.5]);
1835/// ```
1836#[must_use]
1837#[inline(always)]
1838#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1839pub fn mul_m128d_s(a: m128d, b: m128d) -> m128d {
1840 m128d(unsafe { _mm_mul_sd(a.0, b.0) })
1841}
1842
1843/// Lanewise `a * b` with lanes as `i16`, keep the high bits of the `i32`
1844/// intermediates.
1845/// ```
1846/// # use safe_arch::*;
1847/// let a = m128i::from([1_i16, 200, 300, 4568, -1, -2, -3, -4]);
1848/// let b = m128i::from([5_i16, 600, 700, 8910, -15, -26, -37, 48]);
1849/// let c: [i16; 8] = mul_i16_keep_high_m128i(a, b).into();
1850/// assert_eq!(c, [0, 1, 3, 621, 0, 0, 0, -1]);
1851/// ```
1852#[must_use]
1853#[inline(always)]
1854#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1855pub fn mul_i16_keep_high_m128i(a: m128i, b: m128i) -> m128i {
1856 m128i(unsafe { _mm_mulhi_epi16(a.0, b.0) })
1857}
1858
1859/// Lanewise `a * b` with lanes as `u16`, keep the high bits of the `u32`
1860/// intermediates.
1861/// ```
1862/// # use safe_arch::*;
1863/// let a = m128i::from([1_u16, 2003, 3005, 45687, 1, 2, 3, 4]);
1864/// let b = m128i::from([5_u16, 6004, 7006, 8910, 15, 26, 37, 48]);
1865/// let c: [u16; 8] = mul_u16_keep_high_m128i(a, b).into();
1866/// assert_eq!(c, [0, 183, 321, 6211, 0, 0, 0, 0]);
1867/// ```
1868#[must_use]
1869#[inline(always)]
1870#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1871pub fn mul_u16_keep_high_m128i(a: m128i, b: m128i) -> m128i {
1872 m128i(unsafe { _mm_mulhi_epu16(a.0, b.0) })
1873}
1874
1875/// Lanewise `a * b` with lanes as `i16`, keep the low bits of the `i32`
1876/// intermediates.
1877/// ```
1878/// # use safe_arch::*;
1879/// let a = m128i::from([1_i16, 200, 300, 4568, -1, -2, -3, -4]);
1880/// let b = m128i::from([5_i16, 600, 700, 8910, -15, -26, -37, 48]);
1881/// let c: [i16; 8] = mul_i16_keep_low_m128i(a, b).into();
1882/// assert_eq!(c, [5, -11072, 13392, 3024, 15, 52, 111, -192]);
1883/// ```
1884#[must_use]
1885#[inline(always)]
1886#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1887pub fn mul_i16_keep_low_m128i(a: m128i, b: m128i) -> m128i {
1888 m128i(unsafe { _mm_mullo_epi16(a.0, b.0) })
1889}
1890
1891/// Bitwise `a | b`.
1892/// ```
1893/// # use safe_arch::*;
1894/// let a = m128d::from_array([1.0, 0.0]);
1895/// let b = m128d::from_array([1.0, 1.0]);
1896/// let c = bitor_m128d(a, b).to_array();
1897/// assert_eq!(c, [1.0, 1.0]);
1898/// ```
1899#[must_use]
1900#[inline(always)]
1901#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1902pub fn bitor_m128d(a: m128d, b: m128d) -> m128d {
1903 m128d(unsafe { _mm_or_pd(a.0, b.0) })
1904}
1905
1906/// Bitwise `a | b`.
1907/// ```
1908/// # use safe_arch::*;
1909/// let a = m128i::from([1, 0, 1, 0]);
1910/// let b = m128i::from([1, 1, 0, 0]);
1911/// let c: [i32; 4] = bitor_m128i(a, b).into();
1912/// assert_eq!(c, [1, 1, 1, 0]);
1913/// ```
1914#[must_use]
1915#[inline(always)]
1916#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1917pub fn bitor_m128i(a: m128i, b: m128i) -> m128i {
1918 m128i(unsafe { _mm_or_si128(a.0, b.0) })
1919}
1920
1921/// Saturating convert `i16` to `i8`, and pack the values.
1922/// ```
1923/// # use safe_arch::*;
1924/// let a = m128i::from([1_i16, 2, 3, 4, 5, 6, 7, 8]);
1925/// let b = m128i::from([9_i16, 10, 11, 12, 13, 14, 15, 16]);
1926/// let c: [i8; 16] = pack_i16_to_i8_m128i(a, b).into();
1927/// assert_eq!(c, [1_i8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
1928/// ```
1929#[must_use]
1930#[inline(always)]
1931#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1932pub fn pack_i16_to_i8_m128i(a: m128i, b: m128i) -> m128i {
1933 m128i(unsafe { _mm_packs_epi16(a.0, b.0) })
1934}
1935
1936/// Saturating convert `i32` to `i16`, and pack the values.
1937/// ```
1938/// # use safe_arch::*;
1939/// let a = m128i::from([1_i32, 2, 3, 4]);
1940/// let b = m128i::from([5_i32, 6, 7, 8]);
1941/// let c: [i16; 8] = pack_i32_to_i16_m128i(a, b).into();
1942/// assert_eq!(c, [1_i16, 2, 3, 4, 5, 6, 7, 8]);
1943/// ```
1944#[must_use]
1945#[inline(always)]
1946#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1947pub fn pack_i32_to_i16_m128i(a: m128i, b: m128i) -> m128i {
1948 m128i(unsafe { _mm_packs_epi32(a.0, b.0) })
1949}
1950
1951/// Saturating convert `i16` to `u8`, and pack the values.
1952/// ```
1953/// # use safe_arch::*;
1954/// let a = m128i::from([-1_i16, 2, -3, 4, -5, 6, -7, 8]);
1955/// let b = m128i::from([9_i16, 10, 11, 12, 13, -14, 15, -16]);
1956/// let c: [u8; 16] = pack_i16_to_u8_m128i(a, b).into();
1957/// assert_eq!(c, [0, 2, 0, 4, 0, 6, 0, 8, 9, 10, 11, 12, 13, 0, 15, 0]);
1958/// ```
1959#[must_use]
1960#[inline(always)]
1961#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1962pub fn pack_i16_to_u8_m128i(a: m128i, b: m128i) -> m128i {
1963 m128i(unsafe { _mm_packus_epi16(a.0, b.0) })
1964}
1965
1966/// Compute "sum of `u8` absolute differences".
1967///
1968/// * `u8` lanewise `abs(a - b)`, producing `u8` intermediate values.
1969/// * Sum the first eight and second eight values.
1970/// * Place into the low 16 bits of two `u64` lanes.
1971/// ```
1972/// # use safe_arch::*;
1973/// let a = m128i::from([0_u8, 11, 2, 13, 4, 15, 6, 17, 8, 19, 20, 21, 22, 23, 24, 127]);
1974/// let b =
1975/// m128i::from([20_u8, 110, 250, 103, 34, 105, 60, 217, 8, 19, 210, 201, 202, 203, 204, 127]);
1976/// let c: [u64; 2] = sum_of_u8_abs_diff_m128i(a, b).into();
1977/// assert_eq!(c, [831_u64, 910]);
1978/// ```
1979#[must_use]
1980#[inline(always)]
1981#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1982pub fn sum_of_u8_abs_diff_m128i(a: m128i, b: m128i) -> m128i {
1983 m128i(unsafe { _mm_sad_epu8(a.0, b.0) })
1984}
1985
1986/// Sets the args into an `m128i`, first arg is the high lane.
1987/// ```
1988/// # use safe_arch::*;
1989/// let a = m128i::from([15_i8, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
1990/// let b = set_i8_m128i(0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
1991/// assert_eq!(<[i8; 16]>::from(a), <[i8; 16]>::from(b));
1992/// ```
1993#[must_use]
1994#[inline(always)]
1995#[allow(clippy::too_many_arguments)]
1996#[allow(clippy::many_single_char_names)]
1997#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
1998pub fn set_i8_m128i(a: i8, b: i8, c: i8, d: i8, e: i8, f: i8, g: i8, h: i8, i: i8, j: i8, k: i8, l: i8, m: i8, n: i8, o: i8, p: i8) -> m128i {
1999 m128i(unsafe { _mm_set_epi8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) })
2000}
2001
2002/// Sets the args into an `m128i`, first arg is the high lane.
2003/// ```
2004/// # use safe_arch::*;
2005/// let a = m128i::from([7_i16, 6, 5, 4, 3, 2, 1, 0]);
2006/// let b = set_i16_m128i(0_i16, 1, 2, 3, 4, 5, 6, 7);
2007/// assert_eq!(<[i16; 8]>::from(a), <[i16; 8]>::from(b));
2008/// ```
2009#[must_use]
2010#[inline(always)]
2011#[allow(clippy::too_many_arguments)]
2012#[allow(clippy::many_single_char_names)]
2013#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2014pub fn set_i16_m128i(a: i16, b: i16, c: i16, d: i16, e: i16, f: i16, g: i16, h: i16) -> m128i {
2015 m128i(unsafe { _mm_set_epi16(a, b, c, d, e, f, g, h) })
2016}
2017
2018/// Sets the args into an `m128i`, first arg is the high lane.
2019/// ```
2020/// # use safe_arch::*;
2021/// let a = m128i::from([3, 2, 1, 0]);
2022/// let b = set_i32_m128i(0, 1, 2, 3);
2023/// assert_eq!(<[i32; 4]>::from(a), <[i32; 4]>::from(b));
2024/// ```
2025#[must_use]
2026#[inline(always)]
2027#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2028pub fn set_i32_m128i(a: i32, b: i32, c: i32, d: i32) -> m128i {
2029 m128i(unsafe { _mm_set_epi32(a, b, c, d) })
2030}
2031
2032/// Sets the args into an `m128i`, first arg is the high lane.
2033/// ```
2034/// # use safe_arch::*;
2035/// let a = m128i::from([1_i64, 0]);
2036/// let b = set_i64_m128i(0, 1);
2037/// assert_eq!(<[i64; 2]>::from(a), <[i64; 2]>::from(b));
2038/// ```
2039#[must_use]
2040#[inline(always)]
2041#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2042pub fn set_i64_m128i(a: i64, b: i64) -> m128i {
2043 m128i(unsafe { _mm_set_epi64x(a, b) })
2044}
2045
2046/// Sets the args into an `m128d`, first arg is the high lane.
2047/// ```
2048/// # use safe_arch::*;
2049/// let a = m128d::from_array([1.0, 0.0]);
2050/// let b = set_m128d(0.0, 1.0);
2051/// assert_eq!(a.to_array(), b.to_array());
2052/// ```
2053#[must_use]
2054#[inline(always)]
2055#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2056pub fn set_m128d(a: f64, b: f64) -> m128d {
2057 m128d(unsafe { _mm_set_pd(a, b) })
2058}
2059
2060/// Sets the args into the low lane of a `m128d`.
2061/// ```
2062/// # use safe_arch::*;
2063/// let a = m128d::from_array([1.0, 0.0]);
2064/// let b = set_m128d_s(1.0);
2065/// assert_eq!(a.to_array(), b.to_array());
2066/// ```
2067#[must_use]
2068#[inline(always)]
2069#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2070pub fn set_m128d_s(a: f64) -> m128d {
2071 m128d(unsafe { _mm_set_sd(a) })
2072}
2073
2074/// Splats the args into both lanes of the `m128d`.
2075/// ```
2076/// # use safe_arch::*;
2077/// let a = m128d::from_array([1.0, 1.0]);
2078/// let b = set_splat_m128d(1.0);
2079/// assert_eq!(a.to_array(), b.to_array());
2080/// ```
2081#[must_use]
2082#[inline(always)]
2083#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2084pub fn set_splat_m128d(a: f64) -> m128d {
2085 m128d(unsafe { _mm_set1_pd(a) })
2086}
2087
2088/// Splats the `i8` to all lanes of the `m128i`.
2089/// ```
2090/// # use safe_arch::*;
2091/// let a = m128i::from([1_i8, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
2092/// let b = set_splat_i8_m128i(1);
2093/// assert_eq!(<[i8; 16]>::from(a), <[i8; 16]>::from(a));
2094/// ```
2095#[must_use]
2096#[inline(always)]
2097#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2098pub fn set_splat_i8_m128i(i: i8) -> m128i {
2099 m128i(unsafe { _mm_set1_epi8(i) })
2100}
2101
2102/// Splats the `i16` to all lanes of the `m128i`.
2103/// ```
2104/// # use safe_arch::*;
2105/// let a = m128i::from([1_i16, 1, 1, 1, 1, 1, 1, 1]);
2106/// let b = set_splat_i16_m128i(1);
2107/// assert_eq!(<[i16; 8]>::from(a), <[i16; 8]>::from(a));
2108/// ```
2109#[must_use]
2110#[inline(always)]
2111#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2112pub fn set_splat_i16_m128i(i: i16) -> m128i {
2113 m128i(unsafe { _mm_set1_epi16(i) })
2114}
2115
2116/// Splats the `i32` to all lanes of the `m128i`.
2117/// ```
2118/// # use safe_arch::*;
2119/// let a = m128i::from([1, 1, 1, 1]);
2120/// let b = set_splat_i32_m128i(1);
2121/// assert_eq!(<[i32; 4]>::from(a), <[i32; 4]>::from(a));
2122/// ```
2123#[must_use]
2124#[inline(always)]
2125#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2126pub fn set_splat_i32_m128i(i: i32) -> m128i {
2127 m128i(unsafe { _mm_set1_epi32(i) })
2128}
2129
2130/// Splats the `i64` to both lanes of the `m128i`.
2131/// ```
2132/// # use safe_arch::*;
2133/// let a = m128i::from([1_i64, 1]);
2134/// let b = set_splat_i64_m128i(1);
2135/// assert_eq!(<[i64; 2]>::from(a), <[i64; 2]>::from(a));
2136/// ```
2137#[must_use]
2138#[inline(always)]
2139#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2140pub fn set_splat_i64_m128i(i: i64) -> m128i {
2141 m128i(unsafe { _mm_set1_epi64x(i) })
2142}
2143
2144/// Sets the args into an `m128i`, first arg is the low lane.
2145/// ```
2146/// # use safe_arch::*;
2147/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2148/// let b = set_reversed_i8_m128i(0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
2149/// assert_eq!(<[i8; 16]>::from(a), <[i8; 16]>::from(b));
2150/// ```
2151#[must_use]
2152#[inline(always)]
2153#[allow(clippy::too_many_arguments)]
2154#[allow(clippy::many_single_char_names)]
2155#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2156pub fn set_reversed_i8_m128i(a: i8, b: i8, c: i8, d: i8, e: i8, f: i8, g: i8, h: i8, i: i8, j: i8, k: i8, l: i8, m: i8, n: i8, o: i8, p: i8) -> m128i {
2157 m128i(unsafe { _mm_setr_epi8(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) })
2158}
2159
2160/// Sets the args into an `m128i`, first arg is the low lane.
2161/// ```
2162/// # use safe_arch::*;
2163/// let a = m128i::from([0_i16, 1, 2, 3, 4, 5, 6, 7]);
2164/// let b = set_reversed_i16_m128i(0_i16, 1, 2, 3, 4, 5, 6, 7);
2165/// assert_eq!(<[i16; 8]>::from(a), <[i16; 8]>::from(b));
2166/// ```
2167#[must_use]
2168#[inline(always)]
2169#[allow(clippy::too_many_arguments)]
2170#[allow(clippy::many_single_char_names)]
2171#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2172pub fn set_reversed_i16_m128i(a: i16, b: i16, c: i16, d: i16, e: i16, f: i16, g: i16, h: i16) -> m128i {
2173 m128i(unsafe { _mm_setr_epi16(a, b, c, d, e, f, g, h) })
2174}
2175
2176/// Sets the args into an `m128i`, first arg is the low lane.
2177/// ```
2178/// # use safe_arch::*;
2179/// let a = m128i::from([0, 1, 2, 3]);
2180/// let b = set_reversed_i32_m128i(0, 1, 2, 3);
2181/// assert_eq!(<[i32; 4]>::from(a), <[i32; 4]>::from(b));
2182/// ```
2183#[must_use]
2184#[inline(always)]
2185#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2186pub fn set_reversed_i32_m128i(a: i32, b: i32, c: i32, d: i32) -> m128i {
2187 m128i(unsafe { _mm_setr_epi32(a, b, c, d) })
2188}
2189
2190/// Sets the args into an `m128d`, first arg is the low lane.
2191/// ```
2192/// # use safe_arch::*;
2193/// let a = m128d::from_array([0.0, 1.0]);
2194/// let b = set_reversed_m128d(0.0, 1.0);
2195/// assert_eq!(a.to_array(), b.to_array());
2196/// ```
2197#[must_use]
2198#[inline(always)]
2199#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2200pub fn set_reversed_m128d(a: f64, b: f64) -> m128d {
2201 m128d(unsafe { _mm_setr_pd(a, b) })
2202}
2203
2204/// All lanes zero.
2205/// ```
2206/// # use safe_arch::*;
2207/// let a = zeroed_m128i();
2208/// assert_eq!(u128::from(a), 0);
2209/// ```
2210#[must_use]
2211#[inline(always)]
2212#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2213pub fn zeroed_m128i() -> m128i {
2214 m128i(unsafe { _mm_setzero_si128() })
2215}
2216
2217/// Both lanes zero.
2218/// ```
2219/// # use safe_arch::*;
2220/// let a = zeroed_m128d();
2221/// assert_eq!(a.to_array(), [0.0, 0.0]);
2222/// ```
2223#[must_use]
2224#[inline(always)]
2225#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2226pub fn zeroed_m128d() -> m128d {
2227 m128d(unsafe { _mm_setzero_pd() })
2228}
2229
2230/// Shuffle the `i32` lanes in `$a` using an immediate
2231/// control value.
2232///
2233/// ```
2234/// # use safe_arch::*;
2235/// let a = m128i::from([6, 7, 8, 9]);
2236/// //
2237/// let c = shuffle_ai_f32_all_m128i::<0b01_10_10_00>(a);
2238/// assert_eq!(<[i32; 4]>::from(c), [6, 8, 8, 7]);
2239/// ```
2240/// * **Intrinsic:** [`_mm_shuffle_epi32`]
2241/// * **Assembly:** `pshufd xmm, xmm, imm8`
2242#[must_use]
2243#[inline(always)]
2244#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2245pub fn shuffle_ai_f32_all_m128i<const MASK: i32>(a: m128i) -> m128i {
2246 m128i(unsafe { _mm_shuffle_epi32(a.0, MASK) })
2247}
2248
2249/// Shuffle the `f64` lanes from `$a` and `$b` together using an immediate
2250/// control value.
2251///
2252/// The `a:` and `b:` prefixes on the index selection values are literal tokens
2253/// that you type. It helps keep clear what value comes from where. The first
2254/// two output lanes come from `$a`, the second two output lanes come from `$b`.
2255///
2256/// You can pass the same value as both arguments, but if you want to swizzle
2257/// within only a single register and you have `avx` available consider using
2258/// [`shuffle_ai_f64_all_m128d`] instead. You'll get much better performance.
2259/// ```
2260/// # use safe_arch::*;
2261/// let a = m128d::from_array([1.0, 2.0]);
2262/// let b = m128d::from_array([3.0, 4.0]);
2263/// //
2264/// let c = shuffle_abi_f64_all_m128d::<0b00>(a, b).to_array();
2265/// assert_eq!(c, [1.0, 3.0]);
2266/// //
2267/// let c = shuffle_abi_f64_all_m128d::<0b10>(a, b).to_array();
2268/// assert_eq!(c, [1.0, 4.0]);
2269/// ```
2270#[must_use]
2271#[inline(always)]
2272#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2273pub fn shuffle_abi_f64_all_m128d<const MASK: i32>(a: m128d, b: m128d) -> m128d {
2274 m128d(unsafe { _mm_shuffle_pd(a.0, b.0, MASK) })
2275}
2276
2277/// Shuffle the high `i16` lanes in `$a` using an immediate control value.
2278/// ```
2279/// # use safe_arch::*;
2280/// let a = m128i::from([1_i16, 2, 3, 4, 5, 6, 7, 8]);
2281/// let c = shuffle_ai_i16_h64all_m128i::<0b01_00_10_11>(a);
2282/// assert_eq!(<[i16; 8]>::from(c), [1_i16, 2, 3, 4, 8, 7, 5, 6]);
2283/// ```
2284/// * **Intrinsic:** [`_mm_shufflehi_epi16`]
2285/// * **Assembly:** `pshufhw xmm, xmm, imm8`
2286#[must_use]
2287#[inline(always)]
2288#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2289pub fn shuffle_ai_i16_h64all_m128i<const MASK: i32>(a: m128i) -> m128i {
2290 m128i(unsafe { _mm_shufflehi_epi16(a.0, MASK) })
2291}
2292
2293/// Shuffle the low `i16` lanes in `$a` using an immediate control value.
2294/// ```
2295/// # use safe_arch::*;
2296/// let a = m128i::from([1_i16, 2, 3, 4, 5, 6, 7, 8]);
2297/// //
2298/// let c = shuffle_ai_i16_l64all_m128i::<0b01_11_10_00>(a);
2299/// assert_eq!(<[i16; 8]>::from(c), [1_i16, 3, 4, 2, 5, 6, 7, 8]);
2300/// ```
2301/// * **Intrinsic:** [`_mm_shufflelo_epi16`]
2302/// * **Assembly:** `pshuflw xmm, xmm, imm8`
2303#[must_use]
2304#[inline(always)]
2305#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2306pub fn shuffle_ai_i16_l64all_m128i<const MASK: i32>(a: m128i) -> m128i {
2307 m128i(unsafe { _mm_shufflelo_epi16(a.0, MASK) })
2308}
2309
2310/// Shift all `u16` lanes to the left by the `count` in the lower `u64` lane.
2311///
2312/// New bits are 0s.
2313/// ```
2314/// # use safe_arch::*;
2315/// let a = m128i::from([1_u16, 2, 3, 4, 1, 2, 3, 4]);
2316/// let b = m128i::from([3_u64, 0]);
2317/// let c: [u16; 8] = shl_all_u16_m128i(a, b).into();
2318/// assert_eq!(c, [1_u16 << 3, 2 << 3, 3 << 3, 4 << 3, 1 << 3, 2 << 3, 3 << 3, 4 << 3]);
2319/// ```
2320#[must_use]
2321#[inline(always)]
2322#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2323pub fn shl_all_u16_m128i(a: m128i, count: m128i) -> m128i {
2324 m128i(unsafe { _mm_sll_epi16(a.0, count.0) })
2325}
2326
2327/// Shift all `u32` lanes to the left by the `count` in the lower `u64` lane.
2328///
2329/// New bits are 0s.
2330/// ```
2331/// # use safe_arch::*;
2332/// let a = m128i::from([1_u32, 2, 3, 4]);
2333/// let b = m128i::from([3_u64, 0]);
2334/// let c: [u32; 4] = shl_all_u32_m128i(a, b).into();
2335/// assert_eq!(c, [1 << 3, 2 << 3, 3 << 3, 4 << 3]);
2336/// ```
2337#[must_use]
2338#[inline(always)]
2339#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2340pub fn shl_all_u32_m128i(a: m128i, count: m128i) -> m128i {
2341 m128i(unsafe { _mm_sll_epi32(a.0, count.0) })
2342}
2343
2344/// Shift all `u64` lanes to the left by the `count` in the lower `u64` lane.
2345///
2346/// New bits are 0s.
2347/// ```
2348/// # use safe_arch::*;
2349/// let a = m128i::from([1_u64, 2]);
2350/// let b = m128i::from([3_u64, 0]);
2351/// let c: [u64; 2] = shl_all_u64_m128i(a, b).into();
2352/// assert_eq!(c, [1 << 3, 2 << 3]);
2353/// ```
2354#[must_use]
2355#[inline(always)]
2356#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2357pub fn shl_all_u64_m128i(a: m128i, count: m128i) -> m128i {
2358 m128i(unsafe { _mm_sll_epi64(a.0, count.0) })
2359}
2360
2361/// Shifts all `u16` lanes left by an immediate.
2362///
2363/// ```
2364/// # use safe_arch::*;
2365/// let a = m128i::from([1_u16, 2, 3, 4, 1, 2, 3, 4]);
2366/// let c: [u16; 8] = shl_imm_u16_m128i::<3>(a).into();
2367/// assert_eq!(c, [1_u16 << 3, 2 << 3, 3 << 3, 4 << 3, 1 << 3, 2 << 3, 3 << 3, 4 << 3]);
2368/// ```
2369#[must_use]
2370#[inline(always)]
2371#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2372pub fn shl_imm_u16_m128i<const IMM: i32>(a: m128i) -> m128i {
2373 m128i(unsafe { _mm_slli_epi16(a.0, IMM) })
2374}
2375
2376/// Shifts all `u32` lanes left by an immediate.
2377///
2378/// ```
2379/// # use safe_arch::*;
2380/// let a = m128i::from([1, 2, 3, 4]);
2381/// let c: [u32; 4] = shl_imm_u32_m128i::<3>(a).into();
2382/// assert_eq!(c, [1 << 3, 2 << 3, 3 << 3, 4 << 3]);
2383/// ```
2384#[must_use]
2385#[inline(always)]
2386#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2387pub fn shl_imm_u32_m128i<const IMM: i32>(a: m128i) -> m128i {
2388 m128i(unsafe { _mm_slli_epi32(a.0, IMM) })
2389}
2390
2391/// Shifts both `u64` lanes left by an immediate.
2392///
2393/// ```
2394/// # use safe_arch::*;
2395/// let a = m128i::from([1_u64, 2]);
2396/// let c: [u64; 2] = shl_imm_u64_m128i::<3>(a).into();
2397/// assert_eq!(c, [1_u64 << 3, 2 << 3]);
2398/// ```
2399#[must_use]
2400#[inline(always)]
2401#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2402pub fn shl_imm_u64_m128i<const IMM: i32>(a: m128i) -> m128i {
2403 m128i(unsafe { _mm_slli_epi64(a.0, IMM) })
2404}
2405
2406/// Lanewise `sqrt(a)`.
2407/// ```
2408/// # use safe_arch::*;
2409/// let a = m128d::from_array([25.0, 16.0]);
2410/// let b = sqrt_m128d(a).to_array();
2411/// assert_eq!(b, [5.0, 4.0]);
2412/// ```
2413#[must_use]
2414#[inline(always)]
2415#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2416pub fn sqrt_m128d(a: m128d) -> m128d {
2417 m128d(unsafe { _mm_sqrt_pd(a.0) })
2418}
2419
2420/// Low lane `sqrt(b)`, upper lane is unchanged from `a`.
2421/// ```
2422/// # use safe_arch::*;
2423/// let a = m128d::from_array([1.0, 2.0]);
2424/// let b = m128d::from_array([25.0, 4.0]);
2425/// let c = sqrt_m128d_s(a, b);
2426/// assert_eq!(c.to_array(), [5.0, 2.0]);
2427/// ```
2428#[must_use]
2429#[inline(always)]
2430#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2431pub fn sqrt_m128d_s(a: m128d, b: m128d) -> m128d {
2432 m128d(unsafe { _mm_sqrt_sd(a.0, b.0) })
2433}
2434
2435/// Shift each `i16` lane to the right by the `count` in the lower `i64` lane.
2436///
2437/// New bits are the sign bit.
2438/// ```
2439/// # use safe_arch::*;
2440/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2441/// let b = m128i::from([3_i64, 0]);
2442/// let c: [i16; 8] = shr_all_i16_m128i(a, b).into();
2443/// assert_eq!(c, [1_i16 >> 3, 2 >> 3, 3 >> 3, 4 >> 3, -1 >> 3, -2 >> 3, -3 >> 3, -4 >> 3]);
2444/// ```
2445#[must_use]
2446#[inline(always)]
2447#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2448pub fn shr_all_i16_m128i(a: m128i, count: m128i) -> m128i {
2449 m128i(unsafe { _mm_sra_epi16(a.0, count.0) })
2450}
2451
2452/// Shift each `i32` lane to the right by the `count` in the lower `i64` lane.
2453///
2454/// New bits are the sign bit.
2455/// ```
2456/// # use safe_arch::*;
2457/// let a = m128i::from([1_i32, 2, -3, -4]);
2458/// let b = m128i::from([3_i64, 0]);
2459/// let c: [i32; 4] = shr_all_i32_m128i(a, b).into();
2460/// assert_eq!(c, [1 >> 3, 2 >> 3, -3 >> 3, -4 >> 3]);
2461/// ```
2462#[must_use]
2463#[inline(always)]
2464#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2465pub fn shr_all_i32_m128i(a: m128i, count: m128i) -> m128i {
2466 m128i(unsafe { _mm_sra_epi32(a.0, count.0) })
2467}
2468
2469/// Shifts all `i16` lanes right by an immediate.
2470///
2471/// New bits are the sign bit.
2472///
2473/// ```
2474/// # use safe_arch::*;
2475/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2476/// let c: [i16; 8] = shr_imm_i16_m128i::<3>(a).into();
2477/// assert_eq!(c, [1_i16 >> 3, 2 >> 3, 3 >> 3, 4 >> 3, -1 >> 3, -2 >> 3, -3 >> 3, -4 >> 3]);
2478/// ```
2479#[must_use]
2480#[inline(always)]
2481#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2482pub fn shr_imm_i16_m128i<const IMM: i32>(a: m128i) -> m128i {
2483 m128i(unsafe { _mm_srai_epi16(a.0, IMM) })
2484}
2485
2486/// Shifts all `i32` lanes right by an immediate.
2487///
2488/// New bits are the sign bit.
2489///
2490/// ```
2491/// # use safe_arch::*;
2492/// let a = m128i::from([1, 2, -3, -4]);
2493/// let c: [i32; 4] = shr_imm_i32_m128i::<3>(a).into();
2494/// assert_eq!(c, [1 >> 3, 2 >> 3, -3 >> 3, -4 >> 3]);
2495/// ```
2496#[must_use]
2497#[inline(always)]
2498#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2499pub fn shr_imm_i32_m128i<const IMM: i32>(a: m128i) -> m128i {
2500 m128i(unsafe { _mm_srai_epi32(a.0, IMM) })
2501}
2502
2503/// Shift each `u16` lane to the right by the `count` in the lower `u64` lane.
2504///
2505/// ```
2506/// # use safe_arch::*;
2507/// let a = m128i::from([1_u16, 2, 3, 4, 100, 200, 300, 400]);
2508/// let b = m128i::from([3_u64, 0]);
2509/// let c: [u16; 8] = shr_all_u16_m128i(a, b).into();
2510/// assert_eq!(c, [1_u16 >> 3, 2 >> 3, 3 >> 3, 4 >> 3, 100 >> 3, 200 >> 3, 300 >> 3, 400 >> 3,]);
2511/// ```
2512#[must_use]
2513#[inline(always)]
2514#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2515pub fn shr_all_u16_m128i(a: m128i, count: m128i) -> m128i {
2516 m128i(unsafe { _mm_srl_epi16(a.0, count.0) })
2517}
2518
2519/// Shift each `u32` lane to the right by the `count` in the lower `u64` lane.
2520///
2521/// ```
2522/// # use safe_arch::*;
2523/// let a = m128i::from([1_u32, 2, 300, 400]);
2524/// let b = m128i::from([3_u64, 0]);
2525/// let c: [u32; 4] = shr_all_u32_m128i(a, b).into();
2526/// assert_eq!(c, [1 >> 3, 2 >> 3, 300 >> 3, 400 >> 3,]);
2527/// ```
2528#[must_use]
2529#[inline(always)]
2530#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2531pub fn shr_all_u32_m128i(a: m128i, count: m128i) -> m128i {
2532 m128i(unsafe { _mm_srl_epi32(a.0, count.0) })
2533}
2534
2535/// Shift each `u64` lane to the right by the `count` in the lower `u64` lane.
2536///
2537/// New bits are 0s.
2538/// ```
2539/// # use safe_arch::*;
2540/// let a = m128i::from([1_u64, 56]);
2541/// let b = m128i::from([3_u64, 0]);
2542/// let c: [u64; 2] = shr_all_u64_m128i(a, b).into();
2543/// assert_eq!(c, [1 >> 3, 56 >> 3]);
2544/// ```
2545#[must_use]
2546#[inline(always)]
2547#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2548pub fn shr_all_u64_m128i(a: m128i, count: m128i) -> m128i {
2549 m128i(unsafe { _mm_srl_epi64(a.0, count.0) })
2550}
2551
2552/// Shifts all `u16` lanes right by an immediate.
2553///
2554/// New bits are 0s.
2555///
2556/// ```
2557/// # use safe_arch::*;
2558/// let a = m128i::from([1_u16, 2, 3, 4, 100, 200, 300, 400]);
2559/// let c: [u16; 8] = shr_imm_u16_m128i::<3>(a).into();
2560/// assert_eq!(c, [1_u16 >> 3, 2 >> 3, 3 >> 3, 4 >> 3, 100 >> 3, 200 >> 3, 300 >> 3, 400 >> 3,]);
2561/// ```
2562/// * **Intrinsic:** [`_mm_srli_epi16`]
2563/// * **Assembly:** `psrlw xmm, imm8`
2564#[must_use]
2565#[inline(always)]
2566#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2567pub fn shr_imm_u16_m128i<const IMM: i32>(a: m128i) -> m128i {
2568 m128i(unsafe { _mm_srli_epi16(a.0, IMM) })
2569}
2570
2571/// Shifts all `u32` lanes right by an immediate.
2572///
2573/// ```
2574/// # use safe_arch::*;
2575/// let a = m128i::from([1, 2, 300, 400]);
2576/// let c: [u32; 4] = shr_imm_u32_m128i::<3>(a).into();
2577/// assert_eq!(c, [1 >> 3, 2 >> 3, 300 >> 3, 400 >> 3]);
2578/// ```
2579/// * **Intrinsic:** [`_mm_srli_epi32`]
2580/// * **Assembly:** `psrld xmm, imm8`
2581#[must_use]
2582#[inline(always)]
2583#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2584pub fn shr_imm_u32_m128i<const IMM: i32>(a: m128i) -> m128i {
2585 m128i(unsafe { _mm_srli_epi32(a.0, IMM) })
2586}
2587
2588/// Shifts both `u64` lanes right by an immediate.
2589///
2590/// ```
2591/// # use safe_arch::*;
2592/// let a = m128i::from([1_u64, 200]);
2593/// let c: [u64; 2] = shr_imm_u64_m128i::<3>(a).into();
2594/// assert_eq!(c, [1_u64 >> 3, 200 >> 3]);
2595/// ```
2596/// * **Intrinsic:** [`_mm_srli_epi64`]
2597/// * **Assembly:** `psrlq xmm, imm8`
2598#[must_use]
2599#[inline(always)]
2600#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2601pub fn shr_imm_u64_m128i<const IMM: i32>(a: m128i) -> m128i {
2602 m128i(unsafe { _mm_srli_epi64(a.0, IMM) })
2603}
2604
2605/// Stores the value to the reference given.
2606/// ```
2607/// # use safe_arch::*;
2608/// let a = m128d::from_array([10.0, 12.0]);
2609/// let mut b = zeroed_m128d();
2610/// store_m128d(&mut b, a);
2611/// let c = b.to_array();
2612/// assert_eq!(c, [10.0, 12.0]);
2613/// ```
2614#[inline(always)]
2615#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2616pub fn store_m128d(r: &mut m128d, a: m128d) {
2617 unsafe { _mm_store_pd(r as *mut m128d as *mut f64, a.0) }
2618}
2619
2620/// Stores the low lane value to the reference given.
2621/// ```
2622/// # use safe_arch::*;
2623/// let a = m128d::from_array([10.0, 12.0]);
2624/// let mut f = 0.0;
2625/// store_m128d_s(&mut f, a);
2626/// assert_eq!(f, 10.0);
2627/// ```
2628#[inline(always)]
2629#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2630pub fn store_m128d_s(r: &mut f64, a: m128d) {
2631 unsafe { _mm_store_sd(r as *mut f64, a.0) }
2632}
2633
2634/// Stores the low lane value to all lanes of the reference given.
2635/// ```
2636/// # use safe_arch::*;
2637/// let a = m128d::from_array([10.0, 12.0]);
2638/// let mut b = zeroed_m128d();
2639/// store_splat_m128d(&mut b, a);
2640/// let c = b.to_array();
2641/// assert_eq!(c, [10.0, 10.0]);
2642/// ```
2643#[inline(always)]
2644#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2645pub fn store_splat_m128d(r: &mut m128d, a: m128d) {
2646 unsafe { _mm_store1_pd(r as *mut m128d as *mut f64, a.0) }
2647}
2648
2649/// Stores the value to the reference given.
2650/// ```
2651/// # use safe_arch::*;
2652/// let a = m128i::from([1, 2, 3, 4]);
2653/// let mut b = zeroed_m128i();
2654/// store_m128i(&mut b, a);
2655/// let c: [i32; 4] = b.into();
2656/// assert_eq!(c, [1, 2, 3, 4]);
2657/// ```
2658#[inline(always)]
2659#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2660pub fn store_m128i(r: &mut m128i, a: m128i) {
2661 unsafe { _mm_store_si128(&mut r.0, a.0) }
2662}
2663
2664/// Stores the high lane value to the reference given.
2665/// ```
2666/// # use safe_arch::*;
2667/// let a = m128d::from_array([10.0, 12.0]);
2668/// let mut f = 0.0;
2669/// store_high_m128d_s(&mut f, a);
2670/// assert_eq!(f, 12.0);
2671/// ```
2672#[inline(always)]
2673#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2674pub fn store_high_m128d_s(r: &mut f64, a: m128d) {
2675 unsafe { _mm_storeh_pd(r as *mut f64, a.0) }
2676}
2677
2678/// Stores the value to the reference given.
2679/// ```
2680/// # use safe_arch::*;
2681/// let a = m128i::from([1_i64, 2]);
2682/// let mut b = 0_i64;
2683/// store_i64_m128i_s(&mut b, a);
2684/// assert_eq!(b, 1_i64);
2685/// ```
2686#[inline(always)]
2687#[allow(clippy::cast_ptr_alignment)]
2688#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2689pub fn store_i64_m128i_s(r: &mut i64, a: m128i) {
2690 unsafe { _mm_storel_epi64(r as *mut i64 as *mut __m128i, a.0) }
2691}
2692
2693/// Stores the value to the reference given.
2694/// ```
2695/// # use safe_arch::*;
2696/// let a = m128d::from_array([10.0, 12.0]);
2697/// let mut b = zeroed_m128d();
2698/// store_reversed_m128d(&mut b, a);
2699/// let c = b.to_array();
2700/// assert_eq!(c, [12.0, 10.0]);
2701/// ```
2702#[inline(always)]
2703#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2704pub fn store_reversed_m128d(r: &mut m128d, a: m128d) {
2705 unsafe { _mm_storer_pd(r as *mut m128d as *mut f64, a.0) }
2706}
2707
2708/// Stores the value to the reference given.
2709/// ```
2710/// # use safe_arch::*;
2711/// let a = m128d::from_array([10.0, 12.0]);
2712/// let mut b = [0.0, 0.0];
2713/// store_unaligned_m128d(&mut b, a);
2714/// assert_eq!(b, [10.0, 12.0]);
2715/// ```
2716#[inline(always)]
2717#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2718pub fn store_unaligned_m128d(r: &mut [f64; 2], a: m128d) {
2719 unsafe { _mm_storeu_pd(r.as_mut_ptr(), a.0) }
2720}
2721
2722/// Stores the value to the reference given.
2723/// ```
2724/// # use safe_arch::*;
2725/// let a = m128i::from([0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2726/// let mut b = [0_u8; 16];
2727/// store_unaligned_m128i(&mut b, a);
2728/// assert_eq!(b, [0_u8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2729/// ```
2730#[inline(always)]
2731#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2732pub fn store_unaligned_m128i(r: &mut [u8; 16], a: m128i) {
2733 unsafe { _mm_storeu_si128(r.as_mut_ptr().cast(), a.0) }
2734}
2735
2736/// Lanewise `a - b` with lanes as `i8`.
2737/// ```
2738/// # use safe_arch::*;
2739/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2740/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
2741/// let c: [i8; 16] = sub_i8_m128i(a, b).into();
2742/// assert_eq!(c, [0, -10, 0, -10, 0, -10, 0, -10, 0, -10, 30, -10, -10, 36, -10, -112]);
2743/// ```
2744#[must_use]
2745#[inline(always)]
2746#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2747pub fn sub_i8_m128i(a: m128i, b: m128i) -> m128i {
2748 m128i(unsafe { _mm_sub_epi8(a.0, b.0) })
2749}
2750
2751/// Lanewise `a - b` with lanes as `i16`.
2752/// ```
2753/// # use safe_arch::*;
2754/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2755/// let b = m128i::from([51_i16, 61, 71, 81, -15, -26, -37, 48]);
2756/// let c: [i16; 8] = sub_i16_m128i(a, b).into();
2757/// assert_eq!(c, [-50, -59, -68, -77, 14, 24, 34, -52]);
2758/// ```
2759#[must_use]
2760#[inline(always)]
2761#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2762pub fn sub_i16_m128i(a: m128i, b: m128i) -> m128i {
2763 m128i(unsafe { _mm_sub_epi16(a.0, b.0) })
2764}
2765
2766/// Lanewise `a - b` with lanes as `i32`.
2767/// ```
2768/// # use safe_arch::*;
2769/// let a = m128i::from([1, 2, 3, 4]);
2770/// let b = m128i::from([50, 60, 70, 87]);
2771/// let c: [i32; 4] = sub_i32_m128i(a, b).into();
2772/// assert_eq!(c, [-49, -58, -67, -83]);
2773/// ```
2774#[must_use]
2775#[inline(always)]
2776#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2777pub fn sub_i32_m128i(a: m128i, b: m128i) -> m128i {
2778 m128i(unsafe { _mm_sub_epi32(a.0, b.0) })
2779}
2780
2781/// Lanewise `a - b` with lanes as `i64`.
2782/// ```
2783/// # use safe_arch::*;
2784/// let a = m128i::from([92_i64, 87]);
2785/// let b = m128i::from([-9001_i64, 1]);
2786/// let c: [i64; 2] = sub_i64_m128i(a, b).into();
2787/// assert_eq!(c, [9093, 86]);
2788/// ```
2789#[must_use]
2790#[inline(always)]
2791#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2792pub fn sub_i64_m128i(a: m128i, b: m128i) -> m128i {
2793 m128i(unsafe { _mm_sub_epi64(a.0, b.0) })
2794}
2795
2796/// Lanewise `a - b`.
2797/// ```
2798/// # use safe_arch::*;
2799/// let a = m128d::from_array([92.0, 87.5]);
2800/// let b = m128d::from_array([100.0, -6.0]);
2801/// let c = sub_m128d(a, b).to_array();
2802/// assert_eq!(c, [-8.0, 93.5]);
2803/// ```
2804#[must_use]
2805#[inline(always)]
2806#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2807pub fn sub_m128d(a: m128d, b: m128d) -> m128d {
2808 m128d(unsafe { _mm_sub_pd(a.0, b.0) })
2809}
2810
2811/// Lowest lane `a - b`, high lane unchanged.
2812/// ```
2813/// # use safe_arch::*;
2814/// let a = m128d::from_array([92.0, 87.5]);
2815/// let b = m128d::from_array([100.0, -600.0]);
2816/// let c = sub_m128d_s(a, b).to_array();
2817/// assert_eq!(c, [-8.0, 87.5]);
2818/// ```
2819#[must_use]
2820#[inline(always)]
2821#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2822pub fn sub_m128d_s(a: m128d, b: m128d) -> m128d {
2823 m128d(unsafe { _mm_sub_sd(a.0, b.0) })
2824}
2825
2826/// Lanewise saturating `a - b` with lanes as `i8`.
2827/// ```
2828/// # use safe_arch::*;
2829/// let a = m128i::from([0_i8, -128, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, -127]);
2830/// let b = m128i::from([0_i8, 1, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
2831/// let c: [i8; 16] = sub_saturating_i8_m128i(a, b).into();
2832/// assert_eq!(c, [0, -128, 0, -10, 0, -10, 0, -10, 0, -10, 30, -10, -10, 36, -10, -128]);
2833/// ```
2834#[must_use]
2835#[inline(always)]
2836#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2837pub fn sub_saturating_i8_m128i(a: m128i, b: m128i) -> m128i {
2838 m128i(unsafe { _mm_subs_epi8(a.0, b.0) })
2839}
2840
2841/// Lanewise saturating `a - b` with lanes as `i16`.
2842/// ```
2843/// # use safe_arch::*;
2844/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2845/// let b = m128i::from([51_i16, 61, 71, 81, i16::MAX, -26, -37, 48]);
2846/// let c: [i16; 8] = sub_saturating_i16_m128i(a, b).into();
2847/// assert_eq!(c, [-50, -59, -68, -77, -32768, 24, 34, -52]);
2848/// ```
2849#[must_use]
2850#[inline(always)]
2851#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2852pub fn sub_saturating_i16_m128i(a: m128i, b: m128i) -> m128i {
2853 m128i(unsafe { _mm_subs_epi16(a.0, b.0) })
2854}
2855
2856/// Lanewise saturating `a - b` with lanes as `u8`.
2857/// ```
2858/// # use safe_arch::*;
2859/// let a = m128i::from([10_u8, 255, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 255]);
2860/// let b = m128i::from([1_u8, 1, 2, 13, 4, 15, 6, 17, 8, 19, 20, 21, 22, 23, 24, 127]);
2861/// let c: [u8; 16] = sub_saturating_u8_m128i(a, b).into();
2862/// assert_eq!(c, [9_u8, 254, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128]);
2863/// ```
2864#[must_use]
2865#[inline(always)]
2866#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2867pub fn sub_saturating_u8_m128i(a: m128i, b: m128i) -> m128i {
2868 m128i(unsafe { _mm_subs_epu8(a.0, b.0) })
2869}
2870
2871/// Lanewise saturating `a - b` with lanes as `u16`.
2872/// ```
2873/// # use safe_arch::*;
2874/// let a = m128i::from([51_u16, 61, 3, 4, u16::MAX, 2, 3, u16::MAX]);
2875/// let b = m128i::from([5_u16, 2, 71, 81, u16::MAX, 26, 37, u16::MIN]);
2876/// let c: [u16; 8] = sub_saturating_u16_m128i(a, b).into();
2877/// assert_eq!(c, [46, 59, 0, 0, 0, 0, 0, u16::MAX]);
2878/// ```
2879#[must_use]
2880#[inline(always)]
2881#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2882pub fn sub_saturating_u16_m128i(a: m128i, b: m128i) -> m128i {
2883 m128i(unsafe { _mm_subs_epu16(a.0, b.0) })
2884}
2885
2886/// Unpack and interleave high `i8` lanes of `a` and `b`.
2887/// ```
2888/// # use safe_arch::*;
2889/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2890/// let b = m128i::from([0_i8, 11, 2, 13, 4, 15, 6, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
2891/// let c: [i8; 16] = unpack_high_i8_m128i(a, b).into();
2892/// assert_eq!(c, [8, 8, 9, 19, 10, -20, 11, 21, 12, 22, 13, -23, 14, 24, 15, 127]);
2893/// ```
2894#[must_use]
2895#[inline(always)]
2896#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2897pub fn unpack_high_i8_m128i(a: m128i, b: m128i) -> m128i {
2898 m128i(unsafe { _mm_unpackhi_epi8(a.0, b.0) })
2899}
2900
2901/// Unpack and interleave high `i16` lanes of `a` and `b`.
2902/// ```
2903/// # use safe_arch::*;
2904/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2905/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
2906/// let c: [i16; 8] = unpack_high_i16_m128i(a, b).into();
2907/// assert_eq!(c, [-1, -15, -2, -26, -3, -37, -4, 48]);
2908/// ```
2909#[must_use]
2910#[inline(always)]
2911#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2912pub fn unpack_high_i16_m128i(a: m128i, b: m128i) -> m128i {
2913 m128i(unsafe { _mm_unpackhi_epi16(a.0, b.0) })
2914}
2915
2916/// Unpack and interleave high `i32` lanes of `a` and `b`.
2917/// ```
2918/// # use safe_arch::*;
2919/// let a = m128i::from([1, 2, 3, 4]);
2920/// let b = m128i::from([5, 6, 7, 8]);
2921/// let c: [i32; 4] = unpack_high_i32_m128i(a, b).into();
2922/// assert_eq!(c, [3, 7, 4, 8]);
2923/// ```
2924#[must_use]
2925#[inline(always)]
2926#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2927pub fn unpack_high_i32_m128i(a: m128i, b: m128i) -> m128i {
2928 m128i(unsafe { _mm_unpackhi_epi32(a.0, b.0) })
2929}
2930
2931/// Unpack and interleave high `i64` lanes of `a` and `b`.
2932/// ```
2933/// # use safe_arch::*;
2934/// let a = m128i::from([92_i64, 87]);
2935/// let b = m128i::from([-9001_i64, 1]);
2936/// let c: [i64; 2] = unpack_high_i64_m128i(a, b).into();
2937/// assert_eq!(c, [87, 1]);
2938/// ```
2939#[must_use]
2940#[inline(always)]
2941#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2942pub fn unpack_high_i64_m128i(a: m128i, b: m128i) -> m128i {
2943 m128i(unsafe { _mm_unpackhi_epi64(a.0, b.0) })
2944}
2945
2946/// Unpack and interleave high lanes of `a` and `b`.
2947/// ```
2948/// # use safe_arch::*;
2949/// let a = m128d::from_array([92.0, 87.5]);
2950/// let b = m128d::from_array([100.0, -6.0]);
2951/// let c = unpack_high_m128d(a, b).to_array();
2952/// assert_eq!(c, [87.5, -6.0]);
2953/// ```
2954#[must_use]
2955#[inline(always)]
2956#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2957pub fn unpack_high_m128d(a: m128d, b: m128d) -> m128d {
2958 m128d(unsafe { _mm_unpackhi_pd(a.0, b.0) })
2959}
2960
2961/// Unpack and interleave low `i8` lanes of `a` and `b`.
2962/// ```
2963/// # use safe_arch::*;
2964/// let a = m128i::from([0_i8, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
2965/// let b = m128i::from([12_i8, 11, 22, 13, 99, 15, 16, 17, 8, 19, -20, 21, 22, -23, 24, 127]);
2966/// let c: [i8; 16] = unpack_low_i8_m128i(a, b).into();
2967/// assert_eq!(c, [0, 12, 1, 11, 2, 22, 3, 13, 4, 99, 5, 15, 6, 16, 7, 17]);
2968/// ```
2969#[must_use]
2970#[inline(always)]
2971#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2972pub fn unpack_low_i8_m128i(a: m128i, b: m128i) -> m128i {
2973 m128i(unsafe { _mm_unpacklo_epi8(a.0, b.0) })
2974}
2975
2976/// Unpack and interleave low `i16` lanes of `a` and `b`.
2977/// ```
2978/// # use safe_arch::*;
2979/// let a = m128i::from([1_i16, 2, 3, 4, -1, -2, -3, -4]);
2980/// let b = m128i::from([5_i16, 6, 7, 8, -15, -26, -37, 48]);
2981/// let c: [i16; 8] = unpack_low_i16_m128i(a, b).into();
2982/// assert_eq!(c, [1, 5, 2, 6, 3, 7, 4, 8]);
2983/// ```
2984#[must_use]
2985#[inline(always)]
2986#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
2987pub fn unpack_low_i16_m128i(a: m128i, b: m128i) -> m128i {
2988 m128i(unsafe { _mm_unpacklo_epi16(a.0, b.0) })
2989}
2990
2991/// Unpack and interleave low `i32` lanes of `a` and `b`.
2992/// ```
2993/// # use safe_arch::*;
2994/// let a = m128i::from([1, 2, 3, 4]);
2995/// let b = m128i::from([5, 6, 7, 8]);
2996/// let c: [i32; 4] = unpack_low_i32_m128i(a, b).into();
2997/// assert_eq!(c, [1, 5, 2, 6]);
2998/// ```
2999#[must_use]
3000#[inline(always)]
3001#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
3002pub fn unpack_low_i32_m128i(a: m128i, b: m128i) -> m128i {
3003 m128i(unsafe { _mm_unpacklo_epi32(a.0, b.0) })
3004}
3005
3006/// Unpack and interleave low `i64` lanes of `a` and `b`.
3007/// ```
3008/// # use safe_arch::*;
3009/// let a = m128i::from([92_i64, 87]);
3010/// let b = m128i::from([-9001_i64, 1]);
3011/// let c: [i64; 2] = unpack_low_i64_m128i(a, b).into();
3012/// assert_eq!(c, [92, -9001]);
3013/// ```
3014#[must_use]
3015#[inline(always)]
3016#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
3017pub fn unpack_low_i64_m128i(a: m128i, b: m128i) -> m128i {
3018 m128i(unsafe { _mm_unpacklo_epi64(a.0, b.0) })
3019}
3020
3021/// Unpack and interleave low lanes of `a` and `b`.
3022/// ```
3023/// # use safe_arch::*;
3024/// let a = m128d::from_array([92.0, 87.5]);
3025/// let b = m128d::from_array([100.0, -6.0]);
3026/// let c = unpack_low_m128d(a, b).to_array();
3027/// assert_eq!(c, [92.0, 100.0]);
3028/// ```
3029#[must_use]
3030#[inline(always)]
3031#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
3032pub fn unpack_low_m128d(a: m128d, b: m128d) -> m128d {
3033 m128d(unsafe { _mm_unpacklo_pd(a.0, b.0) })
3034}
3035
3036/// Bitwise `a ^ b`.
3037/// ```
3038/// # use safe_arch::*;
3039/// let a = m128d::from_array([1.0, 0.0]);
3040/// let b = m128d::from_array([1.0, 1.0]);
3041/// let c = bitxor_m128d(a, b).to_array();
3042/// assert_eq!(c, [0.0, 1.0]);
3043/// ```
3044#[must_use]
3045#[inline(always)]
3046#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
3047pub fn bitxor_m128d(a: m128d, b: m128d) -> m128d {
3048 m128d(unsafe { _mm_xor_pd(a.0, b.0) })
3049}
3050
3051/// Bitwise `a ^ b`.
3052/// ```
3053/// # use safe_arch::*;
3054/// let a = m128i::from([1, 0, 1, 0]);
3055/// let b = m128i::from([1, 1, 0, 0]);
3056/// let c: [i32; 4] = bitxor_m128i(a, b).into();
3057/// assert_eq!(c, [0, 1, 1, 0]);
3058/// ```
3059#[must_use]
3060#[inline(always)]
3061#[cfg_attr(docsrs, doc(cfg(target_feature = "sse2")))]
3062pub fn bitxor_m128i(a: m128i, b: m128i) -> m128i {
3063 m128i(unsafe { _mm_xor_si128(a.0, b.0) })
3064}
3065
3066//
3067// Here we define the Operator Overloads for `m128`. Each one just calls the
3068// correct function from above. By putting the impls here and not with the
3069// `m128` type we theoretically would be able to build the crate safely even if
3070// there's no `sse` feature enabled. You'd just have a `m128` type without the
3071// operator overloads is all. Not that the standard Rust distribution can build
3072// properly without `sse` enabled, but maybe you're using a custom target or
3073// something. It doesn't really put us out of our way, so it doesn't hurt to try
3074// and accommodate the potential use case.
3075//
3076
3077// First we provide all `m128d` impls.
3078
3079impl Add for m128d {
3080 type Output = Self;
3081 #[inline(always)]
3082 fn add(self, rhs: Self) -> Self {
3083 add_m128d(self, rhs)
3084 }
3085}
3086impl AddAssign for m128d {
3087 #[inline(always)]
3088 fn add_assign(&mut self, rhs: Self) {
3089 *self = *self + rhs;
3090 }
3091}
3092
3093impl BitAnd for m128d {
3094 type Output = Self;
3095 #[inline(always)]
3096 fn bitand(self, rhs: Self) -> Self {
3097 bitand_m128d(self, rhs)
3098 }
3099}
3100impl BitAndAssign for m128d {
3101 #[inline(always)]
3102 fn bitand_assign(&mut self, rhs: Self) {
3103 *self = *self & rhs;
3104 }
3105}
3106
3107impl BitOr for m128d {
3108 type Output = Self;
3109 #[inline(always)]
3110 fn bitor(self, rhs: Self) -> Self {
3111 bitor_m128d(self, rhs)
3112 }
3113}
3114impl BitOrAssign for m128d {
3115 #[inline(always)]
3116 fn bitor_assign(&mut self, rhs: Self) {
3117 *self = *self | rhs;
3118 }
3119}
3120
3121impl BitXor for m128d {
3122 type Output = Self;
3123 #[inline(always)]
3124 fn bitxor(self, rhs: Self) -> Self {
3125 bitxor_m128d(self, rhs)
3126 }
3127}
3128impl BitXorAssign for m128d {
3129 #[inline(always)]
3130 fn bitxor_assign(&mut self, rhs: Self) {
3131 *self = *self ^ rhs;
3132 }
3133}
3134
3135impl Div for m128d {
3136 type Output = Self;
3137 #[inline(always)]
3138 fn div(self, rhs: Self) -> Self {
3139 div_m128d(self, rhs)
3140 }
3141}
3142impl DivAssign for m128d {
3143 #[inline(always)]
3144 fn div_assign(&mut self, rhs: Self) {
3145 *self = *self / rhs;
3146 }
3147}
3148
3149impl Mul for m128d {
3150 type Output = Self;
3151 #[inline(always)]
3152 fn mul(self, rhs: Self) -> Self {
3153 mul_m128d(self, rhs)
3154 }
3155}
3156impl MulAssign for m128d {
3157 #[inline(always)]
3158 fn mul_assign(&mut self, rhs: Self) {
3159 *self = *self * rhs;
3160 }
3161}
3162
3163impl Neg for m128d {
3164 type Output = Self;
3165 #[inline(always)]
3166 fn neg(self) -> Self {
3167 sub_m128d(zeroed_m128d(), self)
3168 }
3169}
3170
3171impl Not for m128d {
3172 type Output = Self;
3173 /// Not a direct intrinsic, but it's very useful and the implementation is
3174 /// simple enough.
3175 ///
3176 /// Negates the bits by performing an `xor` with an all-1s bit pattern.
3177 #[inline(always)]
3178 fn not(self) -> Self {
3179 let all_bits = set_splat_m128d(f64::from_bits(u64::MAX));
3180 self ^ all_bits
3181 }
3182}
3183
3184impl Sub for m128d {
3185 type Output = Self;
3186 #[inline(always)]
3187 fn sub(self, rhs: Self) -> Self {
3188 sub_m128d(self, rhs)
3189 }
3190}
3191impl SubAssign for m128d {
3192 #[inline(always)]
3193 fn sub_assign(&mut self, rhs: Self) {
3194 *self = *self - rhs;
3195 }
3196}
3197
3198impl PartialEq for m128d {
3199 /// Not a direct intrinsic, this is a `cmp_eq_mask` and then a `move_mask`.
3200 #[inline(always)]
3201 fn eq(&self, other: &Self) -> bool {
3202 move_mask_m128d(cmp_eq_mask_m128d(*self, *other)) == 0b11
3203 }
3204}
3205
3206// Next we provide all `m128i` impls. Since the interpretation of the lanes
3207// depends on the operation used, we only provide the bit ops (which are "lane
3208// agnostic").
3209
3210impl BitAnd for m128i {
3211 type Output = Self;
3212 #[inline(always)]
3213 fn bitand(self, rhs: Self) -> Self {
3214 bitand_m128i(self, rhs)
3215 }
3216}
3217impl BitAndAssign for m128i {
3218 #[inline(always)]
3219 fn bitand_assign(&mut self, rhs: Self) {
3220 *self = *self & rhs;
3221 }
3222}
3223
3224impl BitOr for m128i {
3225 type Output = Self;
3226 #[inline(always)]
3227 fn bitor(self, rhs: Self) -> Self {
3228 bitor_m128i(self, rhs)
3229 }
3230}
3231impl BitOrAssign for m128i {
3232 #[inline(always)]
3233 fn bitor_assign(&mut self, rhs: Self) {
3234 *self = *self | rhs;
3235 }
3236}
3237
3238impl BitXor for m128i {
3239 type Output = Self;
3240 #[inline(always)]
3241 fn bitxor(self, rhs: Self) -> Self {
3242 bitxor_m128i(self, rhs)
3243 }
3244}
3245impl BitXorAssign for m128i {
3246 #[inline(always)]
3247 fn bitxor_assign(&mut self, rhs: Self) {
3248 *self = *self ^ rhs;
3249 }
3250}
3251
3252impl Not for m128i {
3253 type Output = Self;
3254 /// Not a direct intrinsic, but it's very useful and the implementation is
3255 /// simple enough.
3256 ///
3257 /// Negates the bits by performing an `xor` with an all-1s bit pattern.
3258 #[inline(always)]
3259 fn not(self) -> Self {
3260 let all_bits = set_splat_i32_m128i(-1);
3261 self ^ all_bits
3262 }
3263}
3264
3265impl PartialEq for m128i {
3266 /// Not a direct intrinsic, this is a `cmp_eq_mask_i8_m128i` and then a
3267 /// `move_mask_i8_m128i`.
3268 #[inline(always)]
3269 fn eq(&self, other: &Self) -> bool {
3270 move_mask_i8_m128i(cmp_eq_mask_i8_m128i(*self, *other)) == 0b11111111_11111111
3271 }
3272}
3273/// Unlike with the floating types, ints have absolute equality.
3274impl Eq for m128i {}