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