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