master
ブランチ master
VulkanExample / dep / include / glm / detail / type_half.inl
5.1 KB、258行 生 Blame 履歴
1namespace glm{
2namespace detail
3{
4#if (GLM_COMPILER & GLM_COMPILER_VC)
5# pragma warning(push)
6# pragma warning(disable: 4746) // volatile access of 'f' is subject to /volatile:<iso|ms> setting; consider using __iso_volatile_load/store intrinsic functions
7#endif
8
9// This function cause a build error on Github C.I.
10#if (!(GLM_COMPILER & GLM_COMPILER_VC) && (GLM_ARCH & GLM_ARCH_ARM_BIT))
11 GLM_FUNC_QUALIFIER float overflow()
12 {
13 volatile float f = 1e10;
14
15 for(int i = 0; i < 10; ++i)
16 f = f * f; // this will overflow before the for loop terminates
17 return f;
18 }
19#else
20 GLM_FUNC_QUALIFIER float overflow()
21 {
22 return 0.0f;
23 }
24#endif//
25
26#if (GLM_COMPILER & GLM_COMPILER_VC)
27# pragma warning(pop)
28#endif
29
30 union uif32
31 {
32 GLM_FUNC_QUALIFIER uif32() :
33 i(0)
34 {}
35
36 GLM_FUNC_QUALIFIER uif32(float f_) :
37 f(f_)
38 {}
39
40 GLM_FUNC_QUALIFIER uif32(unsigned int i_) :
41 i(i_)
42 {}
43
44 float f;
45 unsigned int i;
46 };
47
48 GLM_FUNC_QUALIFIER float toFloat32(hdata value)
49 {
50 int s = (value >> 15) & 0x00000001;
51 int e = (value >> 10) & 0x0000001f;
52 int m = value & 0x000003ff;
53
54 if(e == 0)
55 {
56 if(m == 0)
57 {
58 //
59 // Plus or minus zero
60 //
61
62 detail::uif32 result;
63 result.i = static_cast<unsigned int>(s << 31);
64 return result.f;
65 }
66 else
67 {
68 //
69 // Denormalized number -- renormalize it
70 //
71
72 while(!(m & 0x00000400))
73 {
74 m <<= 1;
75 e -= 1;
76 }
77
78 e += 1;
79 m &= ~0x00000400;
80 }
81 }
82 else if(e == 31)
83 {
84 if(m == 0)
85 {
86 //
87 // Positive or negative infinity
88 //
89
90 uif32 result;
91 result.i = static_cast<unsigned int>((s << 31) | 0x7f800000);
92 return result.f;
93 }
94 else
95 {
96 //
97 // Nan -- preserve sign and significand bits
98 //
99
100 uif32 result;
101 result.i = static_cast<unsigned int>((s << 31) | 0x7f800000 | (m << 13));
102 return result.f;
103 }
104 }
105
106 //
107 // Normalized number
108 //
109
110 e = e + (127 - 15);
111 m = m << 13;
112
113 //
114 // Assemble s, e and m.
115 //
116
117 uif32 Result;
118 Result.i = static_cast<unsigned int>((s << 31) | (e << 23) | m);
119 return Result.f;
120 }
121
122 GLM_FUNC_QUALIFIER hdata toFloat16(float const& f)
123 {
124 uif32 Entry;
125 Entry.f = f;
126 int i = static_cast<int>(Entry.i);
127
128 //
129 // Our floating point number, f, is represented by the bit
130 // pattern in integer i. Disassemble that bit pattern into
131 // the sign, s, the exponent, e, and the significand, m.
132 // Shift s into the position where it will go in the
133 // resulting half number.
134 // Adjust e, accounting for the different exponent bias
135 // of float and half (127 versus 15).
136 //
137
138 int s = (i >> 16) & 0x00008000;
139 int e = ((i >> 23) & 0x000000ff) - (127 - 15);
140 int m = i & 0x007fffff;
141
142 //
143 // Now reassemble s, e and m into a half:
144 //
145
146 if(e <= 0)
147 {
148 if(e < -10)
149 {
150 //
151 // E is less than -10. The absolute value of f is
152 // less than half_MIN (f may be a small normalized
153 // float, a denormalized float or a zero).
154 //
155 // We convert f to a half zero.
156 //
157
158 return hdata(s);
159 }
160
161 //
162 // E is between -10 and 0. F is a normalized float,
163 // whose magnitude is less than __half_NRM_MIN.
164 //
165 // We convert f to a denormalized half.
166 //
167
168 m = (m | 0x00800000) >> (1 - e);
169
170 //
171 // Round to nearest, round "0.5" up.
172 //
173 // Rounding may cause the significand to overflow and make
174 // our number normalized. Because of the way a half's bits
175 // are laid out, we don't have to treat this case separately;
176 // the code below will handle it correctly.
177 //
178
179 if(m & 0x00001000)
180 m += 0x00002000;
181
182 //
183 // Assemble the half from s, e (zero) and m.
184 //
185
186 return hdata(s | (m >> 13));
187 }
188 else if(e == 0xff - (127 - 15))
189 {
190 if(m == 0)
191 {
192 //
193 // F is an infinity; convert f to a half
194 // infinity with the same sign as f.
195 //
196
197 return hdata(s | 0x7c00);
198 }
199 else
200 {
201 //
202 // F is a NAN; we produce a half NAN that preserves
203 // the sign bit and the 10 leftmost bits of the
204 // significand of f, with one exception: If the 10
205 // leftmost bits are all zero, the NAN would turn
206 // into an infinity, so we have to set at least one
207 // bit in the significand.
208 //
209
210 m >>= 13;
211
212 return hdata(s | 0x7c00 | m | (m == 0));
213 }
214 }
215 else
216 {
217 //
218 // E is greater than zero. F is a normalized float.
219 // We try to convert f to a normalized half.
220 //
221
222 //
223 // Round to nearest, round "0.5" up
224 //
225
226 if(m & 0x00001000)
227 {
228 m += 0x00002000;
229
230 if(m & 0x00800000)
231 {
232 m = 0; // overflow in significand,
233 e += 1; // adjust exponent
234 }
235 }
236
237 //
238 // Handle exponent overflow
239 //
240
241 if (e > 30)
242 {
243 overflow(); // Cause a hardware floating point overflow;
244
245 return hdata(s | 0x7c00);
246 // if this returns, the half becomes an
247 } // infinity with the same sign as f.
248
249 //
250 // Assemble the half from s, e and m.
251 //
252
253 return hdata(s | (e << 10) | (m >> 13));
254 }
255 }
256
257}//namespace detail
258}//namespace glm