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
#[allow(unused_imports)]
use std::mem;
use crate::*;
#[inline]
pub fn XMConvertHalfToFloat(Value: HALF) -> f32 {
#[cfg(any(_XM_NO_INTRINSICS_, not(_XM_F16C_INTRINSICS_)))]
unsafe {
let mut Mantissa = (Value as u32 & 0x03FF);
let mut Exponent: u32 = (Value as u32 & 0x7C00);
if (Exponent == 0x7C00)
{
Exponent = 0x8f;
}
else if (Exponent != 0)
{
Exponent = (((Value as i32) >> 10) & 0x1F) as u32;
}
else if (Mantissa != 0)
{
Exponent = 1;
loop
{
Exponent = Exponent.wrapping_sub(1);
Mantissa <<= 1;
if ((Mantissa & 0x0400) == 0) {
break;
}
}
Mantissa &= 0x03FF;
}
else
{
Exponent = ((-112_i32) as u32);
}
let Result: u32 =
((Value as u32 & 0x8000) << 16)
| ((Exponent.wrapping_add(112)) << 23)
| (Mantissa << 13);
return mem::transmute::<u32, f32>(Result);
}
#[cfg(_XM_ARM_NEON_INTRINSICS_)]
{
unimplemented!()
}
#[cfg(_XM_F16C_INTRINSICS_)]
unsafe {
let V1: __m128i = _mm_cvtsi32_si128(Value as i32);
let V2: __m128 = _mm_cvtph_ps(V1);
return _mm_cvtss_f32(V2);
}
}
#[inline]
pub fn XMConvertFloatToHalf(Value: f32) -> HALF {
#[cfg(any(_XM_NO_INTRINSICS_, not(_XM_F16C_INTRINSICS_)))]
unsafe {
let mut Result: u32;
let mut IValue = *mem::transmute::<_, *const u32>(&Value);
let Sign: u32 = (IValue & 0x80000000u32) >> 16u32;
IValue = IValue & 0x7FFFFFFFu32;
if (IValue >= 0x47800000 )
{
Result = 0x7C00u32 | (if (IValue > 0x7F800000) { (0x200 | ((IValue >> 13u32) & 0x3FFu32)) } else { 0u32 });
}
else if (IValue <= 0x33000000u32 )
{
Result = 0;
}
else if (IValue < 0x38800000u32 )
{
let Shift: u32 = 125u32 - (IValue >> 23u32);
IValue = 0x800000u32 | (IValue & 0x7FFFFFu32);
Result = IValue >> (Shift.wrapping_add(1));
let s: u32 = if (IValue & ((1u32 << Shift).wrapping_sub(1))) != 0 { 1 } else { 0 };
Result += (Result | s) & ((IValue >> Shift) & 1u32);
}
else
{
IValue = IValue.wrapping_add(0xC8000000u32);
Result = ((IValue + 0x0FFFu32 + ((IValue >> 13u32) & 1u32)) >> 13u32) & 0x7FFFu32;
}
return (Result | Sign) as u16;
}
#[cfg(_XM_ARM_NEON_INTRINSICS_)]
{
unimplemented!()
}
#[cfg(_XM_F16C_INTRINSICS_)]
unsafe {
let V1: __m128 = _mm_set_ss(Value);
let V2: __m128i = _mm_cvtps_ph(V1, _MM_FROUND_TO_NEAREST_INT);
return _mm_extract_epi16(V2, 0) as u16
}
}
#[test]
fn test_half_conversion() {
for v in [-1.0, 0.0, 1.0].iter().cloned() {
let h = XMConvertFloatToHalf(v);
assert_eq!(v, XMConvertHalfToFloat(h));
}
}