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