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