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