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