1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! `x86_64` 流式 SIMD 扩展 (SSE)

use crate::core_arch::x86::*;

#[cfg(test)]
use stdarch_test::assert_instr;

#[allow(improper_ctypes)]
extern "C" {
    #[link_name = "llvm.x86.sse.cvtss2si64"]
    fn cvtss2si64(a: __m128) -> i64;
    #[link_name = "llvm.x86.sse.cvttss2si64"]
    fn cvttss2si64(a: __m128) -> i64;
    #[link_name = "llvm.x86.sse.cvtsi642ss"]
    fn cvtsi642ss(a: __m128, b: i64) -> __m128;
}

/// 将输入 vector 中的最低 32 位浮点型转换为 64 位整数。
///
/// 根据当前舍入模式对结果进行舍入。
/// 如果结果不能表示为 64 位整数,则结果将为 `0x8000_0000_0000_0000` (`i64::MIN`) 或在未屏蔽的情况下触发无效的操作浮点异常 (请参见 [`_mm_setcsr`](fn._mm_setcsr.html))。)
///
///
/// 这对应于 `CVTSS2SI` 指令 (具有 64 位输出)。
///
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtss_si64)
///
///
#[inline]
#[target_feature(enable = "sse")]
#[cfg_attr(test, assert_instr(cvtss2si))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_cvtss_si64(a: __m128) -> i64 {
    cvtss2si64(a)
}

/// 将输入 vector 中的最低 32 位浮点型转换为带截断的 64 位整数。
///
/// 始终使用截断将结果四舍五入 (趋向于零)。
/// 如果结果不能表示为 64 位整数,则结果将为 `0x8000_0000_0000_0000` (`i64::MIN`) 或无效的操作浮点异常 (如果未屏蔽) (请参见 [`_mm_setcsr`](fn._mm_setcsr.html)))。
///
///
/// 这对应于 `CVTTSS2SI` 指令 (具有 64 位输出)。
///
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvttss_si64)
///
///
#[inline]
#[target_feature(enable = "sse")]
#[cfg_attr(test, assert_instr(cvttss2si))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_cvttss_si64(a: __m128) -> i64 {
    cvttss2si64(a)
}

/// 将 64 位整数转换为 32 位浮点型。
/// 结果 vector 是输入 vector `a`,其最低 32 位浮点数已由转换后的整数替换。
///
/// 此内部函数对应于 `CVTSI2SS` 指令 (具有 64 位输入)。
///
/// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm_cvtsi64_ss)
///
#[inline]
#[target_feature(enable = "sse")]
#[cfg_attr(test, assert_instr(cvtsi2ss))]
#[stable(feature = "simd_x86", since = "1.27.0")]
pub unsafe fn _mm_cvtsi64_ss(a: __m128, b: i64) -> __m128 {
    cvtsi642ss(a, b)
}

#[cfg(test)]
mod tests {
    use crate::core_arch::arch::x86_64::*;
    use stdarch_test::simd_test;

    #[simd_test(enable = "sse")]
    unsafe fn test_mm_cvtss_si64() {
        let inputs = &[
            (42.0f32, 42i64),
            (-31.4, -31),
            (-33.5, -34),
            (-34.5, -34),
            (4.0e10, 40_000_000_000),
            (4.0e-10, 0),
            (f32::NAN, i64::MIN),
            (2147483500.1, 2147483520),
            (9.223371e18, 9223370937343148032),
        ];
        for i in 0..inputs.len() {
            let (xi, e) = inputs[i];
            let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
            let r = _mm_cvtss_si64(x);
            assert_eq!(
                e, r,
                "TestCase #{} _mm_cvtss_si64({:?}) = {}, expected: {}",
                i, x, r, e
            );
        }
    }

    #[simd_test(enable = "sse")]
    unsafe fn test_mm_cvttss_si64() {
        let inputs = &[
            (42.0f32, 42i64),
            (-31.4, -31),
            (-33.5, -33),
            (-34.5, -34),
            (10.999, 10),
            (-5.99, -5),
            (4.0e10, 40_000_000_000),
            (4.0e-10, 0),
            (f32::NAN, i64::MIN),
            (2147483500.1, 2147483520),
            (9.223371e18, 9223370937343148032),
            (9.223372e18, i64::MIN),
        ];
        for i in 0..inputs.len() {
            let (xi, e) = inputs[i];
            let x = _mm_setr_ps(xi, 1.0, 3.0, 4.0);
            let r = _mm_cvttss_si64(x);
            assert_eq!(
                e, r,
                "TestCase #{} _mm_cvttss_si64({:?}) = {}, expected: {}",
                i, x, r, e
            );
        }
    }

    #[simd_test(enable = "sse")]
    unsafe fn test_mm_cvtsi64_ss() {
        let inputs = &[
            (4555i64, 4555.0f32),
            (322223333, 322223330.0),
            (-432, -432.0),
            (-322223333, -322223330.0),
            (9223372036854775807, 9.223372e18),
            (-9223372036854775808, -9.223372e18),
        ];

        for i in 0..inputs.len() {
            let (x, f) = inputs[i];
            let a = _mm_setr_ps(5.0, 6.0, 7.0, 8.0);
            let r = _mm_cvtsi64_ss(a, x);
            let e = _mm_setr_ps(f, 6.0, 7.0, 8.0);
            assert_eq_m128(e, r);
        }
    }
}