• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
Vector4Vector427     Vector4() {}
Vector4Vector428     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 
isPow2(int x)36 inline bool isPow2(int x)
37 {
38     return (x & (x - 1)) == 0 && (x != 0);
39 }
40 
log2(int x)41 inline int log2(int x)
42 {
43     int r = 0;
44     while ((x >> r) > 1) r++;
45     return r;
46 }
47 
ceilPow2(unsigned int x)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 
clampToInt(unsigned int x)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>
clampCast(SrcT value)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>
clamp(T x,MIN min,MAX 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 
clamp01(float x)86 inline float clamp01(float x)
87 {
88     return clamp(x, 0.0f, 1.0f);
89 }
90 
91 template<const int n>
unorm(float x)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 
supportsSSE2()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>
bitCast(const sourceType & source)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 
float32ToFloat16(float fp32)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 
float32ToFloat11(float fp32)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 
float32ToFloat10(float fp32)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 
float11ToFloat32(unsigned short fp11)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 
float10ToFloat32(unsigned short fp11)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>
normalizedToFloat(T input)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>
normalizedToFloat(T input)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>
floatToNormalized(float input)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>
floatToNormalized(float input)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>
getShiftedData(T input)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>
shiftData(T input)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 
average(unsigned char a,unsigned char b)451 inline unsigned char average(unsigned char a, unsigned char b)
452 {
453     return ((a ^ b) >> 1) + (a & b);
454 }
455 
average(signed char a,signed char b)456 inline signed char average(signed char a, signed char b)
457 {
458     return ((short)a + (short)b) / 2;
459 }
460 
average(unsigned short a,unsigned short b)461 inline unsigned short average(unsigned short a, unsigned short b)
462 {
463     return ((a ^ b) >> 1) + (a & b);
464 }
465 
average(signed short a,signed short b)466 inline signed short average(signed short a, signed short b)
467 {
468     return ((int)a + (int)b) / 2;
469 }
470 
average(unsigned int a,unsigned int b)471 inline unsigned int average(unsigned int a, unsigned int b)
472 {
473     return ((a ^ b) >> 1) + (a & b);
474 }
475 
average(signed int a,signed int b)476 inline signed int average(signed int a, signed int b)
477 {
478     return ((long long)a + (long long)b) / 2;
479 }
480 
average(float a,float b)481 inline float average(float a, float b)
482 {
483     return (a + b) * 0.5f;
484 }
485 
averageHalfFloat(unsigned short a,unsigned short b)486 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
487 {
488     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
489 }
490 
averageFloat11(unsigned int a,unsigned int b)491 inline unsigned int averageFloat11(unsigned int a, unsigned int b)
492 {
493     return float32ToFloat11((float11ToFloat32(a) + float11ToFloat32(b)) * 0.5f);
494 }
495 
averageFloat10(unsigned int a,unsigned int b)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 {
RangeRange509     Range() {}
RangeRange510     Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); }
511 
512     T start;
513     T end;
514 
lengthRange515     T length() const { return end - start; }
516 };
517 
518 typedef Range<int> RangeI;
519 typedef Range<unsigned int> RangeUI;
520 
521 template <typename T>
roundUp(const T value,const T alignment)522 T roundUp(const T value, const T alignment)
523 {
524     return value + alignment - 1 - (value - 1) % alignment;
525 }
526 
UnsignedCeilDivide(unsigned int value,unsigned int divisor)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>
IsUnsignedAdditionSafe(T lhs,T rhs)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>
IsUnsignedMultiplicationSafe(T lhs,T rhs)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>
IsIntegerCastSafe(BigIntT bigValue)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