diskann_wide/arch/x86_64/v3/
conversion.rs1use std::arch::x86_64::*;
8
9use super::{f16x8, f16x16, f32x8, f32x16, i8x16, i16x8, i16x16, i32x8, u8x16, u32x8};
10use crate::{LoHi, SIMDCast, SIMDReinterpret, SplitJoin, helpers};
11
12cfg_if::cfg_if! {
18 if #[cfg(not(miri))] {
22 helpers::unsafe_map_conversion!(f16x8, f32x8, _mm256_cvtph_ps, "f16c");
23 helpers::unsafe_map_cast!(
24 f32x8 => (half::f16, f16x8),
25 _mm256_cvtps_ph::<_MM_FROUND_TO_NEAREST_INT>,
26 "f16c"
27 );
28 helpers::unsafe_map_cast!(f16x8 => (f32, f32x8), _mm256_cvtph_ps, "f16c");
29 } else {
30 use crate::{SIMDVector, reference::ReferenceCast};
31
32 impl From<f16x8> for f32x8 {
33 fn from(value: f16x8) -> f32x8 {
34 let array = value.to_array();
35 let converted = array.map(|i| i.reference_cast());
36 f32x8::from_array(value.arch(), converted)
37 }
38 }
39
40 impl SIMDCast<f32> for f16x8 {
41 type Cast = f32x8;
42
43 fn simd_cast(self) -> f32x8 {
44 self.into()
45 }
46 }
47
48 impl SIMDCast<half::f16> for f32x8 {
49 type Cast = f16x8;
50
51 fn simd_cast(self) -> f16x8 {
52 let array = self.to_array();
53 let converted = array.map(|i| i.reference_cast());
54 f16x8::from_array(self.arch(), converted)
55 }
56 }
57 }
58}
59
60impl From<f16x16> for f32x16 {
61 #[inline(always)]
62 fn from(value: f16x16) -> f32x16 {
63 let LoHi { lo, hi } = value.split();
64 f32x16::new(lo.into(), hi.into())
65 }
66}
67
68impl SIMDCast<f32> for f16x16 {
69 type Cast = f32x16;
70 #[inline(always)]
71 fn simd_cast(self) -> f32x16 {
72 self.into()
73 }
74}
75
76impl SIMDCast<half::f16> for f32x16 {
77 type Cast = f16x16;
78 #[inline(always)]
79 fn simd_cast(self) -> f16x16 {
80 self.split().map(|x| -> f16x8 { x.simd_cast() }).join()
81 }
82}
83
84helpers::unsafe_map_conversion!(i8x16, i16x16, _mm256_cvtepi8_epi16, "avx2");
86
87helpers::unsafe_map_conversion!(u8x16, i16x16, _mm256_cvtepu8_epi16, "avx2");
89
90helpers::unsafe_map_cast!(i32x8 => (f32, f32x8), _mm256_cvtepi32_ps, "avx");
92
93impl SIMDReinterpret<i16x16> for u32x8 {
98 fn reinterpret_simd(self) -> i16x16 {
99 i16x16(self.0)
100 }
101}
102
103impl SIMDReinterpret<u8x16> for i16x8 {
104 fn reinterpret_simd(self) -> u8x16 {
105 u8x16(self.0)
106 }
107}
108
109impl SIMDReinterpret<i16x8> for u8x16 {
110 fn reinterpret_simd(self) -> i16x8 {
111 i16x8(self.0)
112 }
113}
114
115#[cfg(test)]
120mod test_x86_conversions {
121 use super::*;
122 use crate::{arch::x86_64::V3, test_utils};
123
124 #[cfg(not(miri))]
126 test_utils::ops::test_lossless_convert!(
127 f16x8 => f32x8, 0xa998182f02ff4d0d, V3::new_checked_uncached()
128 );
129
130 #[cfg(not(miri))]
131 test_utils::ops::test_lossless_convert!(
132 f16x16 => f32x16, 0xf63b356d1dfc1d52, V3::new_checked_uncached()
133 );
134
135 test_utils::ops::test_lossless_convert!(
136 i8x16 => i16x16, 0x84602159fb122584, V3::new_checked_uncached()
137 );
138 test_utils::ops::test_lossless_convert!(
139 u8x16 => i16x16, 0x5ba4b69df84ca568, V3::new_checked_uncached()
140 );
141
142 test_utils::ops::test_cast!(f16x8 => f32x8, 0x37314659b022466a, V3::new_checked_uncached());
144 test_utils::ops::test_cast!(f16x16 => f32x16, 0xba8fe343fc9dbeff, V3::new_checked_uncached());
145
146 test_utils::ops::test_cast!(f32x8 => f16x8, 0x8386cb0a7091cc3b, V3::new_checked_uncached());
147 test_utils::ops::test_cast!(f32x16 => f16x16, 0x7b9c9afee7e6ac63, V3::new_checked_uncached());
148
149 test_utils::ops::test_cast!(i32x8 => f32x8, 0xde4fbf25c554b29e, V3::new_checked_uncached());
150}