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 unsafefn cvtss2si64(a: __m128) -> i64;
12 #[link_name = "llvm.x86.sse.cvttss2si64"]
13 unsafefn 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}
144