Home | History | Annotate | Download | only in common
      1 //
      2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // mathutil.h: Math and bit manipulation functions.
      8 
      9 #ifndef LIBGLESV2_MATHUTIL_H_
     10 #define LIBGLESV2_MATHUTIL_H_
     11 
     12 #include "common/debug.h"
     13 #include "common/platform.h"
     14 
     15 #include <limits>
     16 #include <algorithm>
     17 #include <string.h>
     18 
     19 namespace gl
     20 {
     21 
     22 const unsigned int Float32One = 0x3F800000;
     23 const unsigned short Float16One = 0x3C00;
     24 
     25 struct Vector4
     26 {
     27     Vector4() {}
     28     Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {}
     29 
     30     float x;
     31     float y;
     32     float z;
     33     float w;
     34 };
     35 
     36 inline bool isPow2(int x)
     37 {
     38     return (x & (x - 1)) == 0 && (x != 0);
     39 }
     40 
     41 inline int log2(int x)
     42 {
     43     int r = 0;
     44     while ((x >> r) > 1) r++;
     45     return r;
     46 }
     47 
     48 inline unsigned int ceilPow2(unsigned int x)
     49 {
     50     if (x != 0) x--;
     51     x |= x >> 1;
     52     x |= x >> 2;
     53     x |= x >> 4;
     54     x |= x >> 8;
     55     x |= x >> 16;
     56     x++;
     57 
     58     return x;
     59 }
     60 
     61 inline int clampToInt(unsigned int x)
     62 {
     63     return static_cast<int>(std::min(x, static_cast<unsigned int>(std::numeric_limits<int>::max())));
     64 }
     65 
     66 template <typename DestT, typename SrcT>
     67 inline DestT clampCast(SrcT value)
     68 {
     69     // This assumes SrcT can properly represent DestT::min/max
     70     // Unfortunately we can't use META_ASSERT without C++11 constexpr support
     71     ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::min())) == std::numeric_limits<DestT>::min());
     72     ASSERT(static_cast<DestT>(static_cast<SrcT>(std::numeric_limits<DestT>::max())) == std::numeric_limits<DestT>::max());
     73 
     74     SrcT lo = static_cast<SrcT>(std::numeric_limits<DestT>::min());
     75     SrcT hi = static_cast<SrcT>(std::numeric_limits<DestT>::max());
     76     return static_cast<DestT>(value > lo ? (value > hi ? hi : value) : lo);
     77 }
     78 
     79 template<typename T, typename MIN, typename MAX>
     80 inline T clamp(T x, MIN min, MAX max)
     81 {
     82     // Since NaNs fail all comparison tests, a NaN value will default to min
     83     return x > min ? (x > max ? max : x) : min;
     84 }
     85 
     86 inline float clamp01(float x)
     87 {
     88     return clamp(x, 0.0f, 1.0f);
     89 }
     90 
     91 template<const int n>
     92 inline unsigned int unorm(float x)
     93 {
     94     const unsigned int max = 0xFFFFFFFF >> (32 - n);
     95 
     96     if (x > 1)
     97     {
     98         return max;
     99     }
    100     else if (x < 0)
    101     {
    102         return 0;
    103     }
    104     else
    105     {
    106         return (unsigned int)(max * x + 0.5f);
    107     }
    108 }
    109 
    110 inline bool supportsSSE2()
    111 {
    112 #ifdef ANGLE_PLATFORM_WINDOWS
    113     static bool checked = false;
    114     static bool supports = false;
    115 
    116     if (checked)
    117     {
    118         return supports;
    119     }
    120 
    121     int info[4];
    122     __cpuid(info, 0);
    123 
    124     if (info[0] >= 1)
    125     {
    126         __cpuid(info, 1);
    127 
    128         supports = (info[3] >> 26) & 1;
    129     }
    130 
    131     checked = true;
    132 
    133     return supports;
    134 #else
    135     UNIMPLEMENTED();
    136     return false;
    137 #endif
    138 }
    139 
    140 template <typename destType, typename sourceType>
    141 destType bitCast(const sourceType &source)
    142 {
    143     size_t copySize = std::min(sizeof(destType), sizeof(sourceType));
    144     destType output;
    145     memcpy(&output, &source, copySize);
    146     return output;
    147 }
    148 
    149 inline unsigned short float32ToFloat16(float fp32)
    150 {
    151     unsigned int fp32i = (unsigned int&)fp32;
    152     unsigned int sign = (fp32i & 0x80000000) >> 16;
    153     unsigned int abs = fp32i & 0x7FFFFFFF;
    154 
    155     if(abs > 0x47FFEFFF)   // Infinity
    156     {
    157         return sign | 0x7FFF;
    158     }
    159     else if(abs < 0x38800000)   // Denormal
    160     {
    161         unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
    162         int e = 113 - (abs >> 23);
    163 
    164         if(e < 24)
    165         {
    166             abs = mantissa >> e;
    167         }
    168         else
    169         {
    170             abs = 0;
    171         }
    172 
    173         return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
    174     }
    175     else
    176     {
    177         return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13;
    178     }
    179 }
    180 
    181 float float16ToFloat32(unsigned short h);
    182 
    183 unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
    184 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
    185 
    186 inline unsigned short float32ToFloat11(float fp32)
    187 {
    188     const unsigned int float32MantissaMask = 0x7FFFFF;
    189     const unsigned int float32ExponentMask = 0x7F800000;
    190     const unsigned int float32SignMask = 0x80000000;
    191     const unsigned int float32ValueMask = ~float32SignMask;
    192     const unsigned int float32ExponentFirstBit = 23;
    193     const unsigned int float32ExponentBias = 127;
    194 
    195     const unsigned short float11Max = 0x7BF;
    196     const unsigned short float11MantissaMask = 0x3F;
    197     const unsigned short float11ExponentMask = 0x7C0;
    198     const unsigned short float11BitMask = 0x7FF;
    199     const unsigned int float11ExponentBias = 14;
    200 
    201     const unsigned int float32Maxfloat11 = 0x477E0000;
    202     const unsigned int float32Minfloat11 = 0x38800000;
    203 
    204     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
    205     const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
    206 
    207     unsigned int float32Val = float32Bits & float32ValueMask;
    208 
    209     if ((float32Val & float32ExponentMask) == float32ExponentMask)
    210     {
    211         // INF or NAN
    212         if ((float32Val & float32MantissaMask) != 0)
    213         {
    214             return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
    215         }
    216         else if (float32Sign)
    217         {
    218             // -INF is clamped to 0 since float11 is positive only
    219             return 0;
    220         }
    221         else
    222         {
    223             return float11ExponentMask;
    224         }
    225     }
    226     else if (float32Sign)
    227     {
    228         // float11 is positive only, so clamp to zero
    229         return 0;
    230     }
    231     else if (float32Val > float32Maxfloat11)
    232     {
    233         // The number is too large to be represented as a float11, set to max
    234         return float11Max;
    235     }
    236     else
    237     {
    238         if (float32Val < float32Minfloat11)
    239         {
    240             // The number is too small to be represented as a normalized float11
    241             // Convert it to a denormalized value.
    242             const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
    243             float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
    244         }
    245         else
    246         {
    247             // Rebias the exponent to represent the value as a normalized float11
    248             float32Val += 0xC8000000;
    249         }
    250 
    251         return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
    252     }
    253 }
    254 
    255 inline unsigned short float32ToFloat10(float fp32)
    256 {
    257     const unsigned int float32MantissaMask = 0x7FFFFF;
    258     const unsigned int float32ExponentMask = 0x7F800000;
    259     const unsigned int float32SignMask = 0x80000000;
    260     const unsigned int float32ValueMask = ~float32SignMask;
    261     const unsigned int float32ExponentFirstBit = 23;
    262     const unsigned int float32ExponentBias = 127;
    263 
    264     const unsigned short float10Max = 0x3DF;
    265     const unsigned short float10MantissaMask = 0x1F;
    266     const unsigned short float10ExponentMask = 0x3E0;
    267     const unsigned short float10BitMask = 0x3FF;
    268     const unsigned int float10ExponentBias = 14;
    269 
    270     const unsigned int float32Maxfloat10 = 0x477C0000;
    271     const unsigned int float32Minfloat10 = 0x38800000;
    272 
    273     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
    274     const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
    275 
    276     unsigned int float32Val = float32Bits & float32ValueMask;
    277 
    278     if ((float32Val & float32ExponentMask) == float32ExponentMask)
    279     {
    280         // INF or NAN
    281         if ((float32Val & float32MantissaMask) != 0)
    282         {
    283             return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
    284         }
    285         else if (float32Sign)
    286         {
    287             // -INF is clamped to 0 since float11 is positive only
    288             return 0;
    289         }
    290         else
    291         {
    292             return float10ExponentMask;
    293         }
    294     }
    295     else if (float32Sign)
    296     {
    297         // float10 is positive only, so clamp to zero
    298         return 0;
    299     }
    300     else if (float32Val > float32Maxfloat10)
    301     {
    302         // The number is too large to be represented as a float11, set to max
    303         return float10Max;
    304     }
    305     else
    306     {
    307         if (float32Val < float32Minfloat10)
    308         {
    309             // The number is too small to be represented as a normalized float11
    310             // Convert it to a denormalized value.
    311             const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
    312             float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
    313         }
    314         else
    315         {
    316             // Rebias the exponent to represent the value as a normalized float11
    317             float32Val += 0xC8000000;
    318         }
    319 
    320         return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
    321     }
    322 }
    323 
    324 inline float float11ToFloat32(unsigned short fp11)
    325 {
    326     unsigned short exponent = (fp11 >> 6) & 0x1F;
    327     unsigned short mantissa = fp11 & 0x3F;
    328 
    329     if (exponent == 0x1F)
    330     {
    331         // INF or NAN
    332         return bitCast<float>(0x7f800000 | (mantissa << 17));
    333     }
    334     else
    335     {
    336         if (exponent != 0)
    337         {
    338             // normalized
    339         }
    340         else if (mantissa != 0)
    341         {
    342             // The value is denormalized
    343             exponent = 1;
    344 
    345             do
    346             {
    347                 exponent--;
    348                 mantissa <<= 1;
    349             }
    350             while ((mantissa & 0x40) == 0);
    351 
    352             mantissa = mantissa & 0x3F;
    353         }
    354         else // The value is zero
    355         {
    356             exponent = -112;
    357         }
    358 
    359         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
    360     }
    361 }
    362 
    363 inline float float10ToFloat32(unsigned short fp11)
    364 {
    365     unsigned short exponent = (fp11 >> 5) & 0x1F;
    366     unsigned short mantissa = fp11 & 0x1F;
    367 
    368     if (exponent == 0x1F)
    369     {
    370         // INF or NAN
    371         return bitCast<float>(0x7f800000 | (mantissa << 17));
    372     }
    373     else
    374     {
    375         if (exponent != 0)
    376         {
    377             // normalized
    378         }
    379         else if (mantissa != 0)
    380         {
    381             // The value is denormalized
    382             exponent = 1;
    383 
    384             do
    385             {
    386                 exponent--;
    387                 mantissa <<= 1;
    388             }
    389             while ((mantissa & 0x20) == 0);
    390 
    391             mantissa = mantissa & 0x1F;
    392         }
    393         else // The value is zero
    394         {
    395             exponent = -112;
    396         }
    397 
    398         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
    399     }
    400 }
    401 
    402 template <typename T>
    403 inline float normalizedToFloat(T input)
    404 {
    405     META_ASSERT(std::numeric_limits<T>::is_integer);
    406 
    407     const float inverseMax = 1.0f / std::numeric_limits<T>::max();
    408     return input * inverseMax;
    409 }
    410 
    411 template <unsigned int inputBitCount, typename T>
    412 inline float normalizedToFloat(T input)
    413 {
    414     META_ASSERT(std::numeric_limits<T>::is_integer);
    415     META_ASSERT(inputBitCount < (sizeof(T) * 8));
    416 
    417     const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
    418     return input * inverseMax;
    419 }
    420 
    421 template <typename T>
    422 inline T floatToNormalized(float input)
    423 {
    424     return std::numeric_limits<T>::max() * input + 0.5f;
    425 }
    426 
    427 template <unsigned int outputBitCount, typename T>
    428 inline T floatToNormalized(float input)
    429 {
    430     META_ASSERT(outputBitCount < (sizeof(T) * 8));
    431     return ((1 << outputBitCount) - 1) * input + 0.5f;
    432 }
    433 
    434 template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
    435 inline T getShiftedData(T input)
    436 {
    437     META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
    438     const T mask = (1 << inputBitCount) - 1;
    439     return (input >> inputBitStart) & mask;
    440 }
    441 
    442 template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
    443 inline T shiftData(T input)
    444 {
    445     META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
    446     const T mask = (1 << inputBitCount) - 1;
    447     return (input & mask) << inputBitStart;
    448 }
    449 
    450 
    451 inline unsigned char average(unsigned char a, unsigned char b)
    452 {
    453     return ((a ^ b) >> 1) + (a & b);
    454 }
    455 
    456 inline signed char average(signed char a, signed char b)
    457 {
    458     return ((short)a + (short)b) / 2;
    459 }
    460 
    461 inline unsigned short average(unsigned short a, unsigned short b)
    462 {
    463     return ((a ^ b) >> 1) + (a & b);
    464 }
    465 
    466 inline signed short average(signed short a, signed short b)
    467 {
    468     return ((int)a + (int)b) / 2;
    469 }
    470 
    471 inline unsigned int average(unsigned int a, unsigned int b)
    472 {
    473     return ((a ^ b) >> 1) + (a & b);
    474 }
    475 
    476 inline signed int average(signed int a, signed int b)
    477 {
    478     return ((long long)a + (long long)b) / 2;
    479 }
    480 
    481 inline float average(float a, float b)
    482 {
    483     return (a + b) * 0.5f;
    484 }
    485 
    486 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
    487 {
    488     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
    489 }
    490 
    491 inline unsigned int averageFloat11(unsigned int a, unsigned int b)
    492 {
    493     return float32ToFloat11((float11ToFloat32(a) + float11ToFloat32(b)) * 0.5f);
    494 }
    495 
    496 inline unsigned int averageFloat10(unsigned int a, unsigned int b)
    497 {
    498     return float32ToFloat10((float10ToFloat32(a) + float10ToFloat32(b)) * 0.5f);
    499 }
    500 
    501 }
    502 
    503 namespace rx
    504 {
    505 
    506 template <typename T>
    507 struct Range
    508 {
    509     Range() {}
    510     Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
    511 
    512     T start;
    513     T end;
    514 
    515     T length() const { return end - start; }
    516 };
    517 
    518 typedef Range<int> RangeI;
    519 typedef Range<unsigned int> RangeUI;
    520 
    521 template <typename T>
    522 T roundUp(const T value, const T alignment)
    523 {
    524     return value + alignment - 1 - (value - 1) % alignment;
    525 }
    526 
    527 inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
    528 {
    529     unsigned int divided = value / divisor;
    530     return (divided + ((value % divisor == 0) ? 0 : 1));
    531 }
    532 
    533 template <class T>
    534 inline bool IsUnsignedAdditionSafe(T lhs, T rhs)
    535 {
    536     META_ASSERT(!std::numeric_limits<T>::is_signed);
    537     return (rhs <= std::numeric_limits<T>::max() - lhs);
    538 }
    539 
    540 template <class T>
    541 inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs)
    542 {
    543     META_ASSERT(!std::numeric_limits<T>::is_signed);
    544     return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs));
    545 }
    546 
    547 template <class SmallIntT, class BigIntT>
    548 inline bool IsIntegerCastSafe(BigIntT bigValue)
    549 {
    550     return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue);
    551 }
    552 
    553 }
    554 
    555 #endif   // LIBGLESV2_MATHUTIL_H_
    556