• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1///////////////////////////////////////////////////////////////////////////////////
2/// OpenGL Mathematics (glm.g-truc.net)
3///
4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
5///
6/// This half implementation is based on OpenEXR which is Copyright (c) 2002,
7/// Industrial Light & Magic, a division of Lucas Digital Ltd. LLC
8///
9/// Permission is hereby granted, free of charge, to any person obtaining a copy
10/// of this software and associated documentation files (the "Software"), to deal
11/// in the Software without restriction, including without limitation the rights
12/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13/// copies of the Software, and to permit persons to whom the Software is
14/// furnished to do so, subject to the following conditions:
15///
16/// The above copyright notice and this permission notice shall be included in
17/// all copies or substantial portions of the Software.
18///
19/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25/// THE SOFTWARE.
26///
27/// @ref core
28/// @file glm/core/type_half.inl
29/// @date 2008-08-17 / 2011-06-15
30/// @author Christophe Riccio
31///////////////////////////////////////////////////////////////////////////////////
32
33namespace glm{
34namespace detail
35{
36	GLM_FUNC_QUALIFIER float overflow()
37	{
38		volatile float f = 1e10;
39
40		for(int i = 0; i < 10; ++i)
41			f *= f;             // this will overflow before
42								// the for�loop terminates
43		return f;
44	}
45
46	union uif32
47	{
48		GLM_FUNC_QUALIFIER uif32() :
49			i(0)
50		{}
51
52		GLM_FUNC_QUALIFIER uif32(float f) :
53			f(f)
54		{}
55
56		GLM_FUNC_QUALIFIER uif32(uint32 i) :
57			i(i)
58		{}
59
60		float f;
61		uint32 i;
62	};
63
64	GLM_FUNC_QUALIFIER float toFloat32(hdata value)
65	{
66		int s = (value >> 15) & 0x00000001;
67		int e = (value >> 10) & 0x0000001f;
68		int m =  value        & 0x000003ff;
69
70		if(e == 0)
71		{
72			if(m == 0)
73			{
74				//
75				// Plus or minus zero
76				//
77
78				detail::uif32 result;
79				result.i = (unsigned int)(s << 31);
80				return result.f;
81			}
82			else
83			{
84				//
85				// Denormalized number -- renormalize it
86				//
87
88				while(!(m & 0x00000400))
89				{
90					m <<= 1;
91					e -=  1;
92				}
93
94				e += 1;
95				m &= ~0x00000400;
96			}
97		}
98		else if(e == 31)
99		{
100			if(m == 0)
101			{
102				//
103				// Positive or negative infinity
104				//
105
106				uif32 result;
107				result.i = (unsigned int)((s << 31) | 0x7f800000);
108				return result.f;
109			}
110			else
111			{
112				//
113				// Nan -- preserve sign and significand bits
114				//
115
116				uif32 result;
117				result.i = (unsigned int)((s << 31) | 0x7f800000 | (m << 13));
118				return result.f;
119			}
120		}
121
122		//
123		// Normalized number
124		//
125
126		e = e + (127 - 15);
127		m = m << 13;
128
129		//
130		// Assemble s, e and m.
131		//
132
133		uif32 Result;
134		Result.i = (unsigned int)((s << 31) | (e << 23) | m);
135		return Result.f;
136	}
137
138	GLM_FUNC_QUALIFIER hdata toFloat16(float const & f)
139	{
140		uif32 Entry;
141		Entry.f = f;
142		int i = (int)Entry.i;
143
144		//
145		// Our floating point number, f, is represented by the bit
146		// pattern in integer i.  Disassemble that bit pattern into
147		// the sign, s, the exponent, e, and the significand, m.
148		// Shift s into the position where it will go in in the
149		// resulting half number.
150		// Adjust e, accounting for the different exponent bias
151		// of float and half (127 versus 15).
152		//
153
154		int s =  (i >> 16) & 0x00008000;
155		int e = ((i >> 23) & 0x000000ff) - (127 - 15);
156		int m =   i        & 0x007fffff;
157
158		//
159		// Now reassemble s, e and m into a half:
160		//
161
162		if(e <= 0)
163		{
164			if(e < -10)
165			{
166				//
167				// E is less than -10.  The absolute value of f is
168				// less than half_MIN (f may be a small normalized
169				// float, a denormalized float or a zero).
170				//
171				// We convert f to a half zero.
172				//
173
174				return hdata(s);
175			}
176
177			//
178			// E is between -10 and 0.  F is a normalized float,
179			// whose magnitude is less than __half_NRM_MIN.
180			//
181			// We convert f to a denormalized half.
182			//
183
184			m = (m | 0x00800000) >> (1 - e);
185
186			//
187			// Round to nearest, round "0.5" up.
188			//
189			// Rounding may cause the significand to overflow and make
190			// our number normalized.  Because of the way a half's bits
191			// are laid out, we don't have to treat this case separately;
192			// the code below will handle it correctly.
193			//
194
195			if(m & 0x00001000)
196				m += 0x00002000;
197
198			//
199			// Assemble the half from s, e (zero) and m.
200			//
201
202			return hdata(s | (m >> 13));
203		}
204		else if(e == 0xff - (127 - 15))
205		{
206			if(m == 0)
207			{
208				//
209				// F is an infinity; convert f to a half
210				// infinity with the same sign as f.
211				//
212
213				return hdata(s | 0x7c00);
214			}
215			else
216			{
217				//
218				// F is a NAN; we produce a half NAN that preserves
219				// the sign bit and the 10 leftmost bits of the
220				// significand of f, with one exception: If the 10
221				// leftmost bits are all zero, the NAN would turn
222				// into an infinity, so we have to set at least one
223				// bit in the significand.
224				//
225
226				m >>= 13;
227
228				return hdata(s | 0x7c00 | m | (m == 0));
229			}
230		}
231		else
232		{
233			//
234			// E is greater than zero.  F is a normalized float.
235			// We try to convert f to a normalized half.
236			//
237
238			//
239			// Round to nearest, round "0.5" up
240			//
241
242			if(m &  0x00001000)
243			{
244				m += 0x00002000;
245
246				if(m & 0x00800000)
247				{
248					m =  0;     // overflow in significand,
249					e += 1;     // adjust exponent
250				}
251			}
252
253			//
254			// Handle exponent overflow
255			//
256
257			if (e > 30)
258			{
259				overflow();        // Cause a hardware floating point overflow;
260
261				return hdata(s | 0x7c00);
262				// if this returns, the half becomes an
263			}   // infinity with the same sign as f.
264
265			//
266			// Assemble the half from s, e and m.
267			//
268
269			return hdata(s | (e << 10) | (m >> 13));
270		}
271	}
272
273}//namespace detail
274}//namespace glm
275