1
///////////////////////////////////////////////////////////////////////////////////
2
/// OpenGL Mathematics (glm.g-truc.net)
4
/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net)
5
/// Permission is hereby granted, free of charge, to any person obtaining a copy
6
/// of this software and associated documentation files (the "Software"), to deal
7
/// in the Software without restriction, including without limitation the rights
8
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
/// copies of the Software, and to permit persons to whom the Software is
10
/// furnished to do so, subject to the following conditions:
12
/// The above copyright notice and this permission notice shall be included in
13
/// all copies or substantial portions of the Software.
15
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
/// @file glm/core/type_half.inl
25
/// @date 2008-08-17 / 2011-06-15
26
/// @author Christophe Riccio
29
/// This half implementation is based on OpenEXR which is Copyright (c) 2002,
30
/// Industrial Light & Magic, a division of Lucas Digital Ltd. LLC
31
///////////////////////////////////////////////////////////////////////////////////
33
#include "_detail.hpp"
38
GLM_FUNC_QUALIFIER float overflow()
40
volatile float f = 1e10;
42
for(int i = 0; i < 10; ++i)
43
f *= f; // this will overflow before
44
// the for�loop terminates
48
GLM_FUNC_QUALIFIER float toFloat32(hdata value)
50
int s = (value >> 15) & 0x00000001;
51
int e = (value >> 10) & 0x0000001f;
52
int m = value & 0x000003ff;
63
result.i = (unsigned int)(s << 31);
69
// Denormalized number -- renormalize it
72
while(!(m & 0x00000400))
87
// Positive or negative infinity
91
result.i = (unsigned int)((s << 31) | 0x7f800000);
97
// Nan -- preserve sign and significand bits
101
result.i = (unsigned int)((s << 31) | 0x7f800000 | (m << 13));
114
// Assemble s, e and m.
118
Result.i = (unsigned int)((s << 31) | (e << 23) | m);
122
GLM_FUNC_QUALIFIER hdata toFloat16(float const & f)
126
int i = (int)Entry.i;
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 in the
133
// resulting half number.
134
// Adjust e, accounting for the different exponent bias
135
// of float and half (127 versus 15).
138
register int s = (i >> 16) & 0x00008000;
139
register int e = ((i >> 23) & 0x000000ff) - (127 - 15);
140
register int m = i & 0x007fffff;
143
// Now reassemble s, e and m into a half:
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).
155
// We convert f to a _halfGTX zero.
162
// E is between -10 and 0. F is a normalized float,
163
// whose magnitude is less than __half_NRM_MIN.
165
// We convert f to a denormalized _halfGTX.
168
m = (m | 0x00800000) >> (1 - e);
171
// Round to nearest, round "0.5" up.
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.
183
// Assemble the _halfGTX from s, e (zero) and m.
186
return hdata(s | (m >> 13));
188
else if(e == 0xff - (127 - 15))
193
// F is an infinity; convert f to a half
194
// infinity with the same sign as f.
197
return hdata(s | 0x7c00);
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.
212
return hdata(s | 0x7c00 | m | (m == 0));
218
// E is greater than zero. F is a normalized float.
219
// We try to convert f to a normalized half.
223
// Round to nearest, round "0.5" up
232
m = 0; // overflow in significand,
233
e += 1; // adjust exponent
238
// Handle exponent overflow
243
overflow(); // Cause a hardware floating point overflow;
245
return hdata(s | 0x7c00);
246
// if this returns, the half becomes an
247
} // infinity with the same sign as f.
250
// Assemble the half from s, e and m.
253
return hdata(s | (e << 10) | (m >> 13));
257
GLM_FUNC_QUALIFIER half::half() :
261
GLM_FUNC_QUALIFIER half::half(half const & s) :
265
template <typename U>
266
GLM_FUNC_QUALIFIER half::half(U const & s) :
267
data(toFloat16(float(s)))
270
template <typename U>
271
GLM_FUNC_QUALIFIER half::operator U() const
273
return static_cast<U>(toFloat32(this->data));
276
// Unary updatable operators
277
GLM_FUNC_QUALIFIER half& half::operator= (half const & s)
283
GLM_FUNC_QUALIFIER half& half::operator+=(half const & s)
285
data = toFloat16(toFloat32(data) + toFloat32(s.data));
289
GLM_FUNC_QUALIFIER half& half::operator-=(half const & s)
291
data = toFloat16(toFloat32(data) - toFloat32(s.data));
295
GLM_FUNC_QUALIFIER half& half::operator*=(half const & s)
297
data = toFloat16(toFloat32(data) * toFloat32(s.data));
301
GLM_FUNC_QUALIFIER half& half::operator/=(half const & s)
303
data = toFloat16(toFloat32(data) / toFloat32(s.data));
307
GLM_FUNC_QUALIFIER half& half::operator++()
309
float Casted = toFloat32(data);
310
this->data = toFloat16(++Casted);
314
GLM_FUNC_QUALIFIER half& half::operator--()
316
float Casted = toFloat32(data);
317
this->data = toFloat16(--Casted);
321
//////////////////////////////////////
322
// Binary arithmetic operators
324
GLM_FUNC_QUALIFIER detail::half operator+ (detail::half const & s1, detail::half const & s2)
326
return detail::half(float(s1) + float(s2));
329
GLM_FUNC_QUALIFIER detail::half operator- (detail::half const & s1, detail::half const & s2)
331
return detail::half(float(s1) - float(s2));
334
GLM_FUNC_QUALIFIER detail::half operator* (detail::half const & s1, detail::half const & s2)
336
return detail::half(float(s1) * float(s2));
339
GLM_FUNC_QUALIFIER detail::half operator/ (detail::half const & s1, detail::half const & s2)
341
return detail::half(float(s1) / float(s2));
344
// Unary constant operators
345
GLM_FUNC_QUALIFIER detail::half operator- (detail::half const & s)
347
return detail::half(-float(s));
350
GLM_FUNC_QUALIFIER detail::half operator-- (detail::half const & s, int)
352
return detail::half(float(s) - 1.0f);
355
GLM_FUNC_QUALIFIER detail::half operator++ (detail::half const & s, int)
357
return detail::half(float(s) + 1.0f);
360
GLM_FUNC_QUALIFIER bool operator==
362
detail::half const & x,
363
detail::half const & y
366
return x._data() == y._data();
369
GLM_FUNC_QUALIFIER bool operator!=
371
detail::half const & x,
372
detail::half const & y
375
return x._data() != y._data();
378
GLM_FUNC_QUALIFIER bool operator<
380
detail::half const & x,
381
detail::half const & y
384
return float(x) < float(y);
387
GLM_FUNC_QUALIFIER bool operator<=
389
detail::half const & x,
390
detail::half const & y
393
return float(x) <= float(y);
396
GLM_FUNC_QUALIFIER bool operator>
398
detail::half const & x,
399
detail::half const & y
402
return float(x) > float(y);
405
GLM_FUNC_QUALIFIER bool operator>=
407
detail::half const & x,
408
detail::half const & y
411
return float(x) >= float(y);