1 /*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2017 The Khronos Group Inc. 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 */ /*! 20 * \file glcMisc.cpp 21 * \brief Miscellaneous helper functions. 22 */ /*-------------------------------------------------------------------*/ 23 24 #include "glcMisc.hpp" 25 26 using namespace glw; 27 28 namespace glcts 29 { 30 31 /* utility functions from the book OpenGL ES 2.0 Programming Guide */ 32 /* -15 stored using a single precision bias of 127 */ 33 const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000; 34 /* max exponent value in single precision that will be converted */ 35 /* to Inf or Nan when stored as a half-float */ 36 const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000; 37 /* 255 is the max exponent biased value */ 38 const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23); 39 const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10); 40 floatToHalfFloat(float f)41GLhalf floatToHalfFloat(float f) 42 { 43 union 44 { 45 float v; 46 unsigned int x; 47 }; 48 v = f; 49 unsigned int sign = (GLhalf)(x >> 31); 50 unsigned int mantissa; 51 unsigned int exp; 52 GLhalf hf; 53 54 /* get mantissa */ 55 mantissa = x & ((1 << 23) - 1); 56 /* get exponent bits */ 57 exp = x & FLOAT_MAX_BIASED_EXP; 58 if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP) 59 { 60 /* check if the original single precision float number is a NaN */ 61 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 62 { 63 /* we have a single precision NaN */ 64 mantissa = (1 << 23) - 1; 65 } 66 else 67 { 68 /* 16-bit half-float representation stores number as Inf */ 69 mantissa = 0; 70 } 71 hf = (((GLhalf)sign) << 15) | (GLhalf)(HALF_FLOAT_MAX_BIASED_EXP) | (GLhalf)(mantissa >> 13); 72 } 73 /* check if exponent is <= -15 */ 74 else if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) 75 { 76 /* store a denorm half-float value or zero */ 77 exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23; 78 mantissa |= (1 << 23); 79 80 if (exp < 18) 81 mantissa >>= (14 + exp); 82 else 83 mantissa = 0; 84 85 hf = (((GLhalf)sign) << 15) | (GLhalf)(mantissa); 86 } 87 else 88 { 89 hf = (((GLhalf)sign) << 15) | (GLhalf)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) | 90 (GLhalf)(mantissa >> 13); 91 } 92 93 return hf; 94 } 95 96 /* -15 stored using a single precision bias of 127 */ 97 const unsigned int FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000; 98 /* max exponent value in single precision that will be converted */ 99 /* to Inf or Nan when stored as a half-float */ 100 const unsigned int FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000; 101 const unsigned int FLOAT11_MAX_BIASED_EXP = (0x1F << 6); 102 floatToUnisgnedF11(float f)103GLuint floatToUnisgnedF11(float f) 104 { 105 union 106 { 107 float v; 108 unsigned int x; 109 }; 110 v = f; 111 unsigned int sign = (GLhalf)(x >> 31); 112 unsigned int mantissa; 113 unsigned int exp; 114 GLuint f11; 115 116 /* get mantissa */ 117 mantissa = x & ((1 << 23) - 1); 118 /* get exponent bits */ 119 exp = x & FLOAT_MAX_BIASED_EXP; 120 121 /* minus f32 value */ 122 if (sign > 0) 123 { 124 /* f32 NaN -> f11 NaN */ 125 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 126 { 127 f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(0x0000003F); 128 } 129 /* Others round to 0.0 */ 130 else 131 { 132 f11 = 0x00000000; 133 } 134 135 return f11; 136 } 137 138 /* only check positive value below */ 139 if (exp >= FLOAT11_MAX_BIASED_EXP_AS_SINGLE_FP_EXP) 140 { 141 /* check if the original single precision float number is a NaN */ 142 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 143 { 144 /* we have a single precision NaN */ 145 mantissa = (1 << 23) - 1; 146 } 147 else 148 { 149 /* 11-bit float representation stores number as Inf */ 150 mantissa = 0; 151 } 152 f11 = (GLuint)(FLOAT11_MAX_BIASED_EXP) | (GLuint)(mantissa >> 17); 153 } 154 /* check if exponent is <= -15 */ 155 else if (exp <= FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) 156 { 157 /* store a denorm 11-bit float value or zero */ 158 exp = (FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23; 159 mantissa |= (1 << 23); 160 if (18 + exp >= sizeof(mantissa) * 8) 161 { 162 mantissa = 0; 163 } 164 else 165 { 166 mantissa >>= (18 + exp); 167 } 168 f11 = mantissa; 169 } 170 else 171 { 172 f11 = ((exp - FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 17) | (mantissa >> 17); 173 } 174 175 return f11; 176 } 177 178 /* -15 stored using a single precision bias of 127 */ 179 const unsigned int FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000; 180 /* max exponent value in single precision that will be converted */ 181 /* to Inf or Nan when stored as a half-float */ 182 const unsigned int FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000; 183 const unsigned int FLOAT10_MAX_BIASED_EXP = (0x1F << 5); 184 floatToUnisgnedF10(float f)185GLuint floatToUnisgnedF10(float f) 186 { 187 union 188 { 189 float v; 190 unsigned int x; 191 }; 192 v = f; 193 unsigned int sign = (GLhalf)(x >> 31); 194 unsigned int mantissa; 195 unsigned int exp; 196 GLuint f10; 197 198 /* get mantissa */ 199 mantissa = x & ((1 << 23) - 1); 200 /* get exponent bits */ 201 exp = x & FLOAT_MAX_BIASED_EXP; 202 203 /* minus f32 value */ 204 if (sign > 0) 205 { 206 /* f32 NaN -> f10 NaN */ 207 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 208 { 209 f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(0x0000001F); 210 } 211 /* Others round to 0.0 */ 212 else 213 { 214 f10 = 0x00000000; 215 } 216 217 return f10; 218 } 219 220 /* only check positive value below */ 221 if (exp >= FLOAT10_MAX_BIASED_EXP_AS_SINGLE_FP_EXP) 222 { 223 /* check if the original single precision float number is a NaN */ 224 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP)) 225 { 226 /* we have a single precision NaN */ 227 mantissa = (1 << 23) - 1; 228 } 229 else 230 { 231 /* 10-bit float representation stores number as Inf */ 232 mantissa = 0; 233 } 234 f10 = (GLuint)(FLOAT10_MAX_BIASED_EXP) | (GLuint)(mantissa >> 18); 235 } 236 /* check if exponent is <= -15 */ 237 else if (exp <= FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) 238 { 239 /* store a denorm 11-bit float value or zero */ 240 exp = (FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23; 241 mantissa |= (1 << 23); 242 if (19 + exp >= sizeof(mantissa) * 8) 243 { 244 mantissa = 0; 245 } 246 else 247 { 248 mantissa >>= (19 + exp); 249 } 250 f10 = mantissa; 251 } 252 else 253 { 254 f10 = ((exp - FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 18) | (mantissa >> 18); 255 } 256 257 return f10; 258 } 259 halfFloatToFloat(GLhalf hf)260float halfFloatToFloat(GLhalf hf) 261 { 262 unsigned int sign = (unsigned int)(hf >> 15); 263 unsigned int mantissa = (unsigned int)(hf & ((1 << 10) - 1)); 264 unsigned int exp = (unsigned int)(hf & HALF_FLOAT_MAX_BIASED_EXP); 265 union 266 { 267 float f; 268 unsigned int ui; 269 }; 270 271 if (exp == HALF_FLOAT_MAX_BIASED_EXP) 272 { 273 /* we have a half-float NaN or Inf */ 274 /* half-float NaNs will be converted to a single precision NaN */ 275 /* half-float Infs will be converted to a single precision Inf */ 276 exp = FLOAT_MAX_BIASED_EXP; 277 if (mantissa) 278 mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */ 279 } 280 else if (exp == 0x0) 281 { 282 /* convert half-float zero/denorm to single precision value */ 283 if (mantissa) 284 { 285 mantissa <<= 1; 286 exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 287 /* check for leading 1 in denorm mantissa */ 288 while ((mantissa & (1 << 10)) == 0) 289 { 290 /* for every leading 0, decrement single precision exponent by 1 */ 291 /* and shift half-float mantissa value to the left */ 292 mantissa <<= 1; 293 exp -= (1 << 23); 294 } 295 /* clamp the mantissa to 10-bits */ 296 mantissa &= ((1 << 10) - 1); 297 /* shift left to generate single-precision mantissa of 23-bits */ 298 mantissa <<= 13; 299 } 300 } 301 else 302 { 303 /* shift left to generate single-precision mantissa of 23-bits */ 304 mantissa <<= 13; 305 /* generate single precision biased exponent value */ 306 exp = (exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 307 } 308 ui = (sign << 31) | exp | mantissa; 309 return f; 310 } 311 unsignedF11ToFloat(GLuint f11)312float unsignedF11ToFloat(GLuint f11) 313 { 314 unsigned int mantissa = (unsigned int)(f11 & ((1 << 6) - 1)); 315 unsigned int exp = (unsigned int)(f11 & FLOAT11_MAX_BIASED_EXP); 316 union 317 { 318 float f; 319 unsigned int ui; 320 }; 321 322 if (exp == FLOAT11_MAX_BIASED_EXP) 323 { 324 /* we have a f11 NaN or Inf */ 325 /* f11 NaNs will be converted to a single precision NaN */ 326 /* f11 Infs will be converted to a single precision Inf */ 327 exp = FLOAT_MAX_BIASED_EXP; 328 if (mantissa) 329 mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */ 330 } 331 else if (exp == 0x0) 332 { 333 /* convert f11 zero/denorm to single precision value */ 334 if (mantissa) 335 { 336 mantissa <<= 1; 337 exp = FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 338 /* check for leading 1 in denorm mantissa */ 339 while ((mantissa & (1 << 10)) == 0) 340 { 341 /* for every leading 0, decrement single precision exponent by 1 */ 342 /* and shift half-float mantissa value to the left */ 343 mantissa <<= 1; 344 exp -= (1 << 23); 345 } 346 /* clamp the mantissa to 6-bits */ 347 mantissa &= ((1 << 6) - 1); 348 /* shift left to generate single-precision mantissa of 23-bits */ 349 mantissa <<= 17; 350 } 351 } 352 else 353 { 354 /* shift left to generate single-precision mantissa of 23-bits */ 355 mantissa <<= 17; 356 /* generate single precision biased exponent value */ 357 exp = (exp << 17) + FLOAT11_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 358 } 359 ui = exp | mantissa; 360 return f; 361 } 362 unsignedF10ToFloat(GLuint f10)363float unsignedF10ToFloat(GLuint f10) 364 { 365 unsigned int mantissa = (unsigned int)(f10 & ((1 << 5) - 1)); 366 unsigned int exp = (unsigned int)(f10 & FLOAT10_MAX_BIASED_EXP); 367 union 368 { 369 float f; 370 unsigned int ui; 371 }; 372 373 if (exp == FLOAT10_MAX_BIASED_EXP) 374 { 375 /* we have a f11 NaN or Inf */ 376 /* f11 NaNs will be converted to a single precision NaN */ 377 /* f11 Infs will be converted to a single precision Inf */ 378 exp = FLOAT_MAX_BIASED_EXP; 379 if (mantissa) 380 mantissa = (1 << 23) - 1; /* set all bits to indicate a NaN */ 381 } 382 else if (exp == 0x0) 383 { 384 /* convert f11 zero/denorm to single precision value */ 385 if (mantissa) 386 { 387 mantissa <<= 1; 388 exp = FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 389 /* check for leading 1 in denorm mantissa */ 390 while ((mantissa & (1 << 10)) == 0) 391 { 392 /* for every leading 0, decrement single precision exponent by 1 */ 393 /* and shift half-float mantissa value to the left */ 394 mantissa <<= 1; 395 exp -= (1 << 23); 396 } 397 /* clamp the mantissa to 5-bits */ 398 mantissa &= ((1 << 5) - 1); 399 /* shift left to generate single-precision mantissa of 23-bits */ 400 mantissa <<= 18; 401 } 402 } 403 else 404 { 405 /* shift left to generate single-precision mantissa of 23-bits */ 406 mantissa <<= 18; 407 /* generate single precision biased exponent value */ 408 exp = (exp << 18) + FLOAT10_MIN_BIASED_EXP_AS_SINGLE_FP_EXP; 409 } 410 ui = exp | mantissa; 411 return f; 412 } 413 414 } // namespace glcts 415