Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef HalfFloat_INCLUDE_ONCE
00033 #define HalfFloat_INCLUDE_ONCE
00034
00035 #include <vlCore/Matrix4.hpp>
00036
00037 namespace vl
00038 {
00040 class half
00041 {
00042 public:
00043 half(): bits(0) {}
00044 half(const half& hf): bits(hf.bits) {}
00045 half(int i): bits(convertFloatToHalf((float)i).bits) {}
00046 half(long long i): bits(convertFloatToHalf((float)i).bits) {}
00047 half(float f): bits(convertFloatToHalf(f).bits) {}
00048 half(double d): bits(convertFloatToHalf((float)d).bits) {}
00049
00050 operator float() const
00051 {
00052 return convertHalfToFloat(*this);
00053 }
00054
00055 operator double() const
00056 {
00057 return (double)convertHalfToFloat(*this);
00058 }
00059
00060 operator int() const
00061 {
00062 return (int)convertHalfToFloat(*this);
00063 }
00064
00065 operator long long() const
00066 {
00067 return (long long)convertHalfToFloat(*this);
00068 }
00069
00070 half& operator=(const half& other)
00071 {
00072 bits = other.bits;
00073 return *this;
00074 }
00075
00076 half operator+(const half& other) const
00077 {
00078 return convertFloatToHalf( convertHalfToFloat(*this) + convertHalfToFloat(other) );
00079 }
00080
00081 half& operator+=(const half& other)
00082 {
00083 return *this = convertFloatToHalf( convertHalfToFloat(*this) + convertHalfToFloat(other) );
00084 }
00085
00086 half operator-(const half& other) const
00087 {
00088 return convertFloatToHalf( convertHalfToFloat(*this) - convertHalfToFloat(other) );
00089 }
00090
00091 half& operator-=(const half& other)
00092 {
00093 return *this = convertFloatToHalf( convertHalfToFloat(*this) - convertHalfToFloat(other) );
00094 }
00095
00096 half operator*(const half& other) const
00097 {
00098 return convertFloatToHalf( convertHalfToFloat(*this) * convertHalfToFloat(other) );
00099 }
00100
00101 half& operator*=(const half& other)
00102 {
00103 return *this = convertFloatToHalf( convertHalfToFloat(*this) * convertHalfToFloat(other) );
00104 }
00105
00106 half operator/(const half& other) const
00107 {
00108 return convertFloatToHalf( convertHalfToFloat(*this) / convertHalfToFloat(other) );
00109 }
00110
00111 half& operator/=(const half& other)
00112 {
00113 return *this = convertFloatToHalf( convertHalfToFloat(*this) / convertHalfToFloat(other) );
00114 }
00115
00116 bool isZero() const
00117 {
00118 return (bits & ((1 << 15)-1)) == 0;
00119 }
00120
00121 operator bool() const
00122 {
00123 return !isZero();
00124 }
00125
00126 bool operator==(const half& other) const
00127 {
00128 if (isNaN() && other.isNaN())
00129 return false;
00130 else
00131 if (isZero() && other.isZero())
00132 return true;
00133 else
00134 return bits == other.bits;
00135 }
00136
00137 bool operator==(const float& other) const
00138 {
00139 return operator==( convertFloatToHalf(other) );
00140 }
00141
00142 bool operator==(const double& other) const
00143 {
00144 return operator==( convertFloatToHalf((float)other) );
00145 }
00146
00147 bool operator==(const int& other) const
00148 {
00149 return operator==( convertFloatToHalf((float)other) );
00150 }
00151
00152 bool operator==(const long long& other) const
00153 {
00154 return operator==( convertFloatToHalf((float)other) );
00155 }
00156
00157 bool operator!=(const half& other) const
00158 {
00159 if (isNaN() && other.isNaN())
00160 return false;
00161 else
00162 if (isZero() && other.isZero())
00163 return false;
00164 else
00165 return bits != other.bits;
00166 }
00167
00168 bool operator!=(const float& other) const
00169 {
00170 return operator!=( convertFloatToHalf(other) );
00171 }
00172
00173 bool operator!=(const double& other) const
00174 {
00175 return operator!=( convertFloatToHalf((float)other) );
00176 }
00177
00178 bool operator!=(const int& other) const
00179 {
00180 return operator!=( convertFloatToHalf((float)other) );
00181 }
00182
00183 bool operator!=(const long long& other) const
00184 {
00185 return operator!=( convertFloatToHalf((float)other) );
00186 }
00187
00188 bool operator<(const half& other) const
00189 {
00190 return convertHalfToFloat(*this) < convertHalfToFloat(other);
00191 }
00192
00193 bool operator>(const half& other) const
00194 {
00195 return convertHalfToFloat(*this) < convertHalfToFloat(other);
00196 }
00197
00198 bool isNaN() const
00199 {
00200 unsigned int mantissa = (unsigned int) (bits & (( 1 << 10) - 1) );
00201 unsigned int exp = (unsigned int) (bits & HALF_FLOAT_MAX_BIASED_EXP);
00202 return exp == HALF_FLOAT_MAX_BIASED_EXP && mantissa != 0;
00203 }
00204
00205 bool isinf() const
00206 {
00207 unsigned int mantissa = (unsigned int) (bits & (( 1 << 10) - 1) );
00208 unsigned int exp = (unsigned int) (bits & HALF_FLOAT_MAX_BIASED_EXP);
00209 return exp == HALF_FLOAT_MAX_BIASED_EXP && mantissa == 0;
00210 }
00211
00212 bool isinf_pos() const
00213 {
00214 unsigned int sign = (unsigned int) ( bits >> 15);
00215 unsigned int mantissa = (unsigned int) (bits & (( 1 << 10) - 1) );
00216 unsigned int exp = (unsigned int) (bits & HALF_FLOAT_MAX_BIASED_EXP);
00217 return exp == HALF_FLOAT_MAX_BIASED_EXP && mantissa == 0 && sign == 0;
00218 }
00219
00220 bool isinf_neg() const
00221 {
00222 unsigned int sign = (unsigned int) ( bits >> 15);
00223 unsigned int mantissa = (unsigned int) (bits & (( 1 << 10) - 1) );
00224 unsigned int exp = (unsigned int) (bits & HALF_FLOAT_MAX_BIASED_EXP);
00225 return exp == HALF_FLOAT_MAX_BIASED_EXP && mantissa == 0 && sign == 1;
00226 }
00227
00228 bool isdenorm() const
00229 {
00230 unsigned int mantissa = (unsigned int) (bits & (( 1 << 10) - 1) );
00231 unsigned int exp = (unsigned int) (bits & HALF_FLOAT_MAX_BIASED_EXP);
00232 return exp == 0 && mantissa != 0;
00233 }
00234
00235 half operator-() const
00236 {
00237 half h = *this;
00238 h.bits ^= 1 << 15;
00239 return h;
00240 }
00241
00242
00243 static half infinity()
00244 {
00245 half h;
00246 h.bits = HALF_FLOAT_MAX_BIASED_EXP;
00247 return h;
00248 }
00249
00250 static half NaN()
00251 {
00252 half h;
00253 h.bits = HALF_FLOAT_MAX_BIASED_EXP | (( 1 << 10) - 1);
00254 return h;
00255 }
00256
00257 static void convertDoubleToHalf(const double* d, half* h, int count)
00258 {
00259 for(int i=0; i<count; ++i)
00260 h[i] = convertFloatToHalf((float)d[i]);
00261 }
00262
00263 static void convertHalfToDouble(const half* h, double* d, int count)
00264 {
00265 for(int i=0; i<count; ++i)
00266 d[i] = (double)convertHalfToFloat(h[i]);
00267 }
00268
00269 static half convertFloatToHalf(float f)
00270 {
00271 union { float f; unsigned int x; } val;
00272 val.f = f;
00273 unsigned int sign = (unsigned short)(val.x>>31);
00274 unsigned int mantissa = val.x & ((1 << 23)-1);
00275 unsigned int exp = val.x & FLOAT_MAX_BIASED_EXP;
00276 typedef unsigned short hfloat;
00277 half hf;
00278
00279 if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
00280 {
00281
00282 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
00283 {
00284
00285 mantissa = (1<<23) - 1;
00286 }
00287 else
00288 {
00289
00290 mantissa = 0;
00291 }
00292 hf.bits = (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) | (hfloat)(mantissa >> 13);
00293 }
00294
00295 else
00296 if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
00297 {
00298
00299 exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
00300 mantissa >>= (14 + exp);
00301 hf.bits = (((hfloat)sign) << 15) | (hfloat)(mantissa);
00302 }
00303 else
00304 {
00305 hf.bits = (((hfloat)sign)<<15) |
00306 (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
00307 (hfloat)(mantissa >> 13);
00308 }
00309 return hf;
00310 }
00311
00312 static float convertHalfToFloat(const half& h)
00313 {
00314 unsigned short hf = h.bits;
00315 unsigned int sign = (unsigned int) ( hf >> 15);
00316 unsigned int mantissa = (unsigned int) (hf & (( 1 << 10) - 1) );
00317 unsigned int exp = (unsigned int) (hf & HALF_FLOAT_MAX_BIASED_EXP);
00318
00319 if (exp == HALF_FLOAT_MAX_BIASED_EXP)
00320 {
00321
00322
00323
00324 exp = FLOAT_MAX_BIASED_EXP;
00325 if ( mantissa)
00326 mantissa = (1 << 23 ) - 1;
00327 }
00328 else if (exp == 0x0)
00329 {
00330
00331 if ( mantissa)
00332 {
00333 mantissa <<= 1;
00334 exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
00335
00336 while ((mantissa & (1 << 10) ) == 0)
00337 {
00338
00339
00340 mantissa <<= 1;
00341 exp -= (1 << 23 );
00342 }
00343
00344 mantissa &= (( 1 << 10) - 1);
00345
00346 mantissa <<= 13;
00347 }
00348 }
00349 else
00350 {
00351
00352 mantissa <<= 13;
00353
00354 exp = ( exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
00355 }
00356 union { float f; unsigned int x; } val;
00357 val.x = ( sign << 31) | exp | mantissa;
00358 return val.f;
00359 }
00360
00361 static void convertFloatToHalf(const float* f, half* h, int count)
00362 {
00363 for(int i=0; i<count; ++i)
00364 {
00365 union { float f; unsigned int x; } val;
00366 val.f = f[i];
00367 unsigned int sign = (unsigned short)(val.x>>31);
00368 unsigned int mantissa = val.x & ((1 << 23)-1);
00369 unsigned int exp = val.x & FLOAT_MAX_BIASED_EXP;
00370 typedef unsigned short hfloat;
00371 hfloat& hf = h[i].bits;
00372
00373 if (exp >= HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP)
00374 {
00375
00376 if (mantissa && (exp == FLOAT_MAX_BIASED_EXP))
00377 {
00378
00379 mantissa = (1<<23) - 1;
00380 }
00381 else
00382 {
00383
00384 mantissa = 0;
00385 }
00386 hf = (((hfloat)sign) << 15) | (hfloat)(HALF_FLOAT_MAX_BIASED_EXP) | (hfloat)(mantissa >> 13);
00387 }
00388
00389 else
00390 if (exp <= HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP)
00391 {
00392
00393 exp = (HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP - exp) >> 23;
00394 mantissa >>= (14 + exp);
00395 hf = (((hfloat)sign) << 15) | (hfloat)(mantissa);
00396 }
00397 else
00398 {
00399 hf = (((hfloat)sign)<<15) |
00400 (hfloat)((exp - HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP) >> 13) |
00401 (hfloat)(mantissa >> 13);
00402 }
00403 }
00404 }
00405
00406 static void convertHalfToFloat(const half* h, float *f, int count)
00407 {
00408 for(int i=0; i<count; ++i)
00409 {
00410 const unsigned short& hf = h[i].bits;
00411 unsigned int sign = (unsigned int) ( hf >> 15);
00412 unsigned int mantissa = (unsigned int) (hf & (( 1 << 10) - 1) );
00413 unsigned int exp = (unsigned int) (hf & HALF_FLOAT_MAX_BIASED_EXP);
00414
00415 if (exp == HALF_FLOAT_MAX_BIASED_EXP)
00416 {
00417
00418
00419
00420 exp = FLOAT_MAX_BIASED_EXP;
00421 if ( mantissa)
00422 mantissa = (1 << 23 ) - 1;
00423 }
00424 else if (exp == 0x0)
00425 {
00426
00427 if ( mantissa)
00428 {
00429 mantissa <<= 1;
00430 exp = HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
00431
00432 while ((mantissa & (1 << 10) ) == 0)
00433 {
00434
00435
00436 mantissa <<= 1;
00437 exp -= (1 << 23 );
00438 }
00439
00440 mantissa &= (( 1 << 10) - 1);
00441
00442 mantissa <<= 13;
00443 }
00444 }
00445 else
00446 {
00447
00448 mantissa <<= 13;
00449
00450 exp = ( exp << 13) + HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP;
00451 }
00452 union { float f; unsigned int x; } val;
00453 val.x = ( sign << 31) | exp | mantissa;
00454 f[i] = val.f;
00455 }
00456 }
00457
00458 public:
00459 unsigned short bits;
00460
00461 private:
00462
00463 static const unsigned int HALF_FLOAT_MIN_BIASED_EXP_AS_SINGLE_FP_EXP = 0x38000000;
00464
00465
00466
00467 static const unsigned int HALF_FLOAT_MAX_BIASED_EXP_AS_SINGLE_FP_EXP = 0x47800000;
00468
00469
00470 static const unsigned int FLOAT_MAX_BIASED_EXP = (0xFF << 23);
00471 static const unsigned int HALF_FLOAT_MAX_BIASED_EXP = (0x1F << 10);
00472
00473 };
00474
00475 inline float operator/(float a, const half& b)
00476 {
00477 return (float)a / half::convertHalfToFloat(b);
00478 }
00479
00480 inline float operator/(double a, const half& b)
00481 {
00482 return (float)a / half::convertHalfToFloat(b);
00483 }
00484
00485 inline float operator/(int a, const half& b)
00486 {
00487 return (float)a / half::convertHalfToFloat(b);
00488 }
00489
00490 inline float operator*(float a, const half& b)
00491 {
00492 return (float)a * half::convertHalfToFloat(b);
00493 }
00494
00495 inline float operator*(double a, const half& b)
00496 {
00497 return (float)a * half::convertHalfToFloat(b);
00498 }
00499
00500 inline float operator*(int a, const half& b)
00501 {
00502 return (float)a * half::convertHalfToFloat(b);
00503 }
00504
00505 inline float operator+(float a, const half& b)
00506 {
00507 return (float)a + half::convertHalfToFloat(b);
00508 }
00509
00510 inline float operator+(double a, const half& b)
00511 {
00512 return (float)a + half::convertHalfToFloat(b);
00513 }
00514
00515 inline float operator+(int a, const half& b)
00516 {
00517 return (float)a + half::convertHalfToFloat(b);
00518 }
00519
00520 inline float operator-(float a, const half& b)
00521 {
00522 return (float)a - half::convertHalfToFloat(b);
00523 }
00524
00525 inline float operator-(double a, const half& b)
00526 {
00527 return (float)a - half::convertHalfToFloat(b);
00528 }
00529
00530 inline float operator-(int a, const half& b)
00531 {
00532 return (float)a - half::convertHalfToFloat(b);
00533 }
00534
00535
00536
00537 inline float operator/(const half& a, float b)
00538 {
00539 return half::convertHalfToFloat(a) / (float)b ;
00540 }
00541
00542 inline float operator/(const half& a, double b)
00543 {
00544 return half::convertHalfToFloat(a) / (float)b ;
00545 }
00546
00547 inline float operator/(const half& a, int b)
00548 {
00549 return half::convertHalfToFloat(a) / (float)b ;
00550 }
00551
00552 inline float operator*(const half& a, float b)
00553 {
00554 return half::convertHalfToFloat(a) * (float)b ;
00555 }
00556
00557 inline float operator*(const half& a, double b)
00558 {
00559 return half::convertHalfToFloat(a) * (float)b ;
00560 }
00561
00562 inline float operator*(const half& a, int b)
00563 {
00564 return half::convertHalfToFloat(a) * (float)b ;
00565 }
00566
00567 inline float operator+(const half& a, float b)
00568 {
00569 return half::convertHalfToFloat(a) + (float)b ;
00570 }
00571
00572 inline float operator+(const half& a, double b)
00573 {
00574 return half::convertHalfToFloat(a) + (float)b ;
00575 }
00576
00577 inline float operator+(const half& a, int b)
00578 {
00579 return half::convertHalfToFloat(a) + (float)b ;
00580 }
00581
00582 inline float operator-(const half& a, float b)
00583 {
00584 return half::convertHalfToFloat(a) - (float)b ;
00585 }
00586
00587 inline float operator-(const half& a, double b)
00588 {
00589 return half::convertHalfToFloat(a) - (float)b ;
00590 }
00591
00592 inline float operator-(const half& a, int b)
00593 {
00594 return half::convertHalfToFloat(a) - (float)b ;
00595 }
00596
00597 template<> inline half Vector4<half>::length() const { return (half)::sqrt( (float)x()*(float)x()+(float)y()*(float)y()+(float)z()*(float)z()+(float)w()*(float)w()); }
00598 template<> inline half Vector4<half>::lengthSquared() const { return (half)((float)x()*(float)x()+(float)y()*(float)y()+(float)z()*(float)z()+(float)w()*(float)w()); }
00599
00600 template<> inline half Vector3<half>::length() const { return (half)::sqrt( (float)x()*(float)x()+(float)y()*(float)y()+(float)z()*(float)z()); }
00601 template<> inline half Vector3<half>::lengthSquared() const { return (half)((float)x()*(float)x()+(float)y()*(float)y()+(float)z()*(float)z()); }
00602
00603 template<> inline half Vector2<half>::length() const { return (half)::sqrt( (float)x()*(float)x()+(float)y()*(float)y()); }
00604 template<> inline half Vector2<half>::lengthSquared() const { return (half)((float)x()*(float)x()+(float)y()*(float)y()); }
00605
00606 typedef Vector4<half> hvec4;
00607 typedef Vector3<half> hvec3;
00608 typedef Vector2<half> hvec2;
00609
00610 typedef Matrix4<half> hmat4;
00611 typedef Matrix3<half> hmat3;
00612 typedef Matrix2<half> hmat2;
00613
00614 }
00615
00616 #endif