core\stdarch\crates\core_arch\src\x86_64/
sse.rs

1//! `x86_64` Streaming SIMD Extensions (SSE)
2
3use crate::core_arch::x86::*;
4
5#[cfg(test)]
6use stdarch_test::assert_instr;
7
8#[allow(improper_ctypes)]
9unsafe extern "C" {
10    #[link_name = "llvm.x86.sse.cvtss2si64"]
11    fn cvtss2si64(a: __m128) -> i64;
12    #[link_name = "llvm.x86.sse.cvttss2si64"]
13    fn cvttss2si64(a: __m128) -> i64;
14}
15
16/// Converts the lowest 32 bit float in the input vector to a 64 bit integer.
17///
18/// The result is rounded according to the current rounding mode. If the result
19/// cannot be represented as a 64 bit integer the result will be
20/// `0x8000_0000_0000_0000` (`i64::MIN`) or trigger an invalid operation
21/// floating point exception if unmasked (see
22/// [`_mm_setcsr`](fn._mm_setcsr.html)).
23///
24/// This corresponds to the `CVTSS2SI` instruction (with 64 bit output).
25///
26/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_si64)
27#[inline]
28#[target_feature(enable = "sse")]
29#[cfg_attr(test, assert_instr(cvtss2si))]
30#[stable(feature = "simd_x86", since = "1.27.0")]
31pub fn _mm_cvtss_si64(a: __m128) -> i64 {
32    unsafe { cvtss2si64(a) }
33}
34
35/// Converts the lowest 32 bit float in the input vector to a 64 bit integer
36/// with truncation.
37///
38/// The result is rounded always using truncation (round towards zero). If the
39/// result cannot be represented as a 64 bit integer the result will be
40/// `0x8000_0000_0000_0000` (`i64::MIN`) or an invalid operation floating
41/// point exception if unmasked (see [`_mm_setcsr`](fn._mm_setcsr.html)).
42///
43/// This corresponds to the `CVTTSS2SI` instruction (with 64 bit output).
44///
45/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttss_si64)
46#[inline]
47#[target_feature(enable = "sse")]
48#[cfg_attr(test, assert_instr(cvttss2si))]
49#[stable(feature = "simd_x86", since = "1.27.0")]
50pub fn _mm_cvttss_si64(a: __m128) -> i64 {
51    unsafe { cvttss2si64(a) }
52}
53
54/// Converts a 64 bit integer to a 32 bit float. The result vector is the input
55/// vector `a` with the lowest 32 bit float replaced by the converted integer.
56///
57/// This intrinsic corresponds to the `CVTSI2SS` instruction (with 64 bit
58/// input).
59///
60/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_ss)
61#[inline]
62#[target_feature(enable = "sse")]
63#[cfg_attr(test, assert_instr(cvtsi2ss))]
64#[stable(feature = "simd_x86", since = "1.27.0")]
65pub fn _mm_cvtsi64_ss(a: __m128, b: i64) -> __m128 {
66    unsafe { simd_insert!(a, 0, b as f32) }
67}
68
69#[cfg(test)]
70mod tests {
71    use crate::core_arch::arch::x86_64::*;
72    use stdarch_test::simd_test;
73
74    #[simd_test(enable = "sse")]
75    unsafe fn test_mm_cvtss_si64() {
76        let inputs = &[
77            (42.0f32, 42i64),
78            (-31.4, -31),
79            (-33.5, -34),
80            (-34.5, -34),
81            (4.0e10, 40_000_000_000),
82            (4.0e-10, 0),
83            (f32::NAN, i64::MIN),
84            (2147483500.1, 2147483520),
85            (9.223371e18, 9223370937343148032),
86        ];
87        for (i, &(xi, e)) in inputs.iter().enumerate() {
88            let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
89            let r = _mm_cvtss_si64(x);
90            assert_eq!(
91                e, r,
92                "TestCase #{} _mm_cvtss_si64({:?}) = {}, expected: {}",
93                i, x, r, e
94            );
95        }
96    }
97
98    #[simd_test(enable = "sse")]
99    unsafe fn test_mm_cvttss_si64() {
100        let inputs = &[
101            (42.0f32, 42i64),
102            (-31.4, -31),
103            (-33.5, -33),
104            (-34.5, -34),
105            (10.999, 10),
106            (-5.99, -5),
107            (4.0e10, 40_000_000_000),
108            (4.0e-10, 0),
109            (f32::NAN, i64::MIN),
110            (2147483500.1, 2147483520),
111            (9.223371e18, 9223370937343148032),
112            (9.223372e18, i64::MIN),
113        ];
114        for (i, &(xi, e)) in inputs.iter().enumerate() {
115            let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
116            let r = _mm_cvttss_si64(x);
117            assert_eq!(
118                e, r,
119                "TestCase #{} _mm_cvttss_si64({:?}) = {}, expected: {}",
120                i, x, r, e
121            );
122        }
123    }
124
125    #[simd_test(enable = "sse")]
126    unsafe fn test_mm_cvtsi64_ss() {
127        let inputs = &[
128            (4555i64, 4555.0f32),
129            (322223333, 322223330.0),
130            (-432, -432.0),
131            (-322223333, -322223330.0),
132            (9223372036854775807, 9.223372e18),
133            (-9223372036854775808, -9.223372e18),
134        ];
135
136        for &(x, f) in inputs {
137            let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0);
138            let r = _mm_cvtsi64_ss(a, x);
139            let e = _mm_setr_ps(f, 6.0, 7.0, 8.0);
140            assert_eq_m128(e, r);
141        }
142    }
143}