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")]
65#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")]
66pub const fn _mm_cvtsi64_ss(a: __m128, b: i64) -> __m128 {
67 unsafe { simd_insert!(a, 0, b as f32) }
68}
69
70#[cfg(test)]
71mod tests {
72 use crate::core_arch::arch::x86_64::*;
73 use crate::core_arch::assert_eq_const as assert_eq;
74 use stdarch_test::simd_test;
75
76 #[simd_test(enable = "sse")]
77 fn test_mm_cvtss_si64() {
78 let inputs = &[
79 (42.0f32, 42i64),
80 (-31.4, -31),
81 (-33.5, -34),
82 (-34.5, -34),
83 (4.0e10, 40_000_000_000),
84 (4.0e-10, 0),
85 (f32::NAN, i64::MIN),
86 (2147483500.1, 2147483520),
87 (9.223371e18, 9223370937343148032),
88 ];
89 for (i, &(xi, e)) in inputs.iter().enumerate() {
90 let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
91 let r = _mm_cvtss_si64(x);
92 assert_eq!(
93 e, r,
94 "TestCase #{} _mm_cvtss_si64({:?}) = {}, expected: {}",
95 i, x, r, e
96 );
97 }
98 }
99
100 #[simd_test(enable = "sse")]
101 fn test_mm_cvttss_si64() {
102 let inputs = &[
103 (42.0f32, 42i64),
104 (-31.4, -31),
105 (-33.5, -33),
106 (-34.5, -34),
107 (10.999, 10),
108 (-5.99, -5),
109 (4.0e10, 40_000_000_000),
110 (4.0e-10, 0),
111 (f32::NAN, i64::MIN),
112 (2147483500.1, 2147483520),
113 (9.223371e18, 9223370937343148032),
114 (9.223372e18, i64::MIN),
115 ];
116 for (i, &(xi, e)) in inputs.iter().enumerate() {
117 let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
118 let r = _mm_cvttss_si64(x);
119 assert_eq!(
120 e, r,
121 "TestCase #{} _mm_cvttss_si64({:?}) = {}, expected: {}",
122 i, x, r, e
123 );
124 }
125 }
126
127 #[simd_test(enable = "sse")]
128 const fn test_mm_cvtsi64_ss() {
129 let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0);
130
131 let r = _mm_cvtsi64_ss(a, 4555);
132 let e = _mm_setr_ps(4555.0, 6.0, 7.0, 8.0);
133 assert_eq_m128(e, r);
134
135 let r = _mm_cvtsi64_ss(a, 322223333);
136 let e = _mm_setr_ps(322223333.0, 6.0, 7.0, 8.0);
137 assert_eq_m128(e, r);
138
139 let r = _mm_cvtsi64_ss(a, -432);
140 let e = _mm_setr_ps(-432.0, 6.0, 7.0, 8.0);
141 assert_eq_m128(e, r);
142
143 let r = _mm_cvtsi64_ss(a, -322223333);
144 let e = _mm_setr_ps(-322223333.0, 6.0, 7.0, 8.0);
145 assert_eq_m128(e, r);
146
147 let r = _mm_cvtsi64_ss(a, 9223372036854775807);
148 let e = _mm_setr_ps(9.223372e18, 6.0, 7.0, 8.0);
149 assert_eq_m128(e, r);
150
151 let r = _mm_cvtsi64_ss(a, -9223372036854775808);
152 let e = _mm_setr_ps(-9.223372e18, 6.0, 7.0, 8.0);
153 assert_eq_m128(e, r);
154 }
155}
156