xref: /aosp_15_r20/external/angle/src/common/mathutil.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // mathutil.h: Math and bit manipulation functions.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #ifndef COMMON_MATHUTIL_H_
10*8975f5c5SAndroid Build Coastguard Worker #define COMMON_MATHUTIL_H_
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include <math.h>
13*8975f5c5SAndroid Build Coastguard Worker #include <stdint.h>
14*8975f5c5SAndroid Build Coastguard Worker #include <stdlib.h>
15*8975f5c5SAndroid Build Coastguard Worker #include <string.h>
16*8975f5c5SAndroid Build Coastguard Worker #include <algorithm>
17*8975f5c5SAndroid Build Coastguard Worker #include <limits>
18*8975f5c5SAndroid Build Coastguard Worker 
19*8975f5c5SAndroid Build Coastguard Worker #include <anglebase/numerics/safe_math.h>
20*8975f5c5SAndroid Build Coastguard Worker 
21*8975f5c5SAndroid Build Coastguard Worker #include "common/debug.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "common/platform.h"
23*8975f5c5SAndroid Build Coastguard Worker 
24*8975f5c5SAndroid Build Coastguard Worker namespace angle
25*8975f5c5SAndroid Build Coastguard Worker {
26*8975f5c5SAndroid Build Coastguard Worker using base::CheckedNumeric;
27*8975f5c5SAndroid Build Coastguard Worker using base::IsValueInRangeForNumericType;
28*8975f5c5SAndroid Build Coastguard Worker }  // namespace angle
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker namespace gl
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker 
33*8975f5c5SAndroid Build Coastguard Worker const unsigned int Float32One   = 0x3F800000;
34*8975f5c5SAndroid Build Coastguard Worker const unsigned short Float16One = 0x3C00;
35*8975f5c5SAndroid Build Coastguard Worker 
36*8975f5c5SAndroid Build Coastguard Worker template <typename T>
isPow2(T x)37*8975f5c5SAndroid Build Coastguard Worker inline constexpr bool isPow2(T x)
38*8975f5c5SAndroid Build Coastguard Worker {
39*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
40*8975f5c5SAndroid Build Coastguard Worker     return (x & (x - 1)) == 0 && (x != 0);
41*8975f5c5SAndroid Build Coastguard Worker }
42*8975f5c5SAndroid Build Coastguard Worker 
43*8975f5c5SAndroid Build Coastguard Worker template <typename T>
log2(T x)44*8975f5c5SAndroid Build Coastguard Worker inline int log2(T x)
45*8975f5c5SAndroid Build Coastguard Worker {
46*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_integral<T>::value, "log2 must be called on an integer type.");
47*8975f5c5SAndroid Build Coastguard Worker     int r = 0;
48*8975f5c5SAndroid Build Coastguard Worker     while ((x >> r) > 1)
49*8975f5c5SAndroid Build Coastguard Worker         r++;
50*8975f5c5SAndroid Build Coastguard Worker     return r;
51*8975f5c5SAndroid Build Coastguard Worker }
52*8975f5c5SAndroid Build Coastguard Worker 
ceilPow2(unsigned int x)53*8975f5c5SAndroid Build Coastguard Worker inline unsigned int ceilPow2(unsigned int x)
54*8975f5c5SAndroid Build Coastguard Worker {
55*8975f5c5SAndroid Build Coastguard Worker     if (x != 0)
56*8975f5c5SAndroid Build Coastguard Worker         x--;
57*8975f5c5SAndroid Build Coastguard Worker     x |= x >> 1;
58*8975f5c5SAndroid Build Coastguard Worker     x |= x >> 2;
59*8975f5c5SAndroid Build Coastguard Worker     x |= x >> 4;
60*8975f5c5SAndroid Build Coastguard Worker     x |= x >> 8;
61*8975f5c5SAndroid Build Coastguard Worker     x |= x >> 16;
62*8975f5c5SAndroid Build Coastguard Worker     x++;
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker     return x;
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker 
67*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
clampCast(SrcT value)68*8975f5c5SAndroid Build Coastguard Worker inline DestT clampCast(SrcT value)
69*8975f5c5SAndroid Build Coastguard Worker {
70*8975f5c5SAndroid Build Coastguard Worker     // For floating-point types with denormalization, min returns the minimum positive normalized
71*8975f5c5SAndroid Build Coastguard Worker     // value. To find the value that has no values less than it, use numeric_limits::lowest.
72*8975f5c5SAndroid Build Coastguard Worker     constexpr const long double destLo =
73*8975f5c5SAndroid Build Coastguard Worker         static_cast<long double>(std::numeric_limits<DestT>::lowest());
74*8975f5c5SAndroid Build Coastguard Worker     constexpr const long double destHi =
75*8975f5c5SAndroid Build Coastguard Worker         static_cast<long double>(std::numeric_limits<DestT>::max());
76*8975f5c5SAndroid Build Coastguard Worker     constexpr const long double srcLo =
77*8975f5c5SAndroid Build Coastguard Worker         static_cast<long double>(std::numeric_limits<SrcT>::lowest());
78*8975f5c5SAndroid Build Coastguard Worker     constexpr long double srcHi = static_cast<long double>(std::numeric_limits<SrcT>::max());
79*8975f5c5SAndroid Build Coastguard Worker 
80*8975f5c5SAndroid Build Coastguard Worker     if (destHi < srcHi)
81*8975f5c5SAndroid Build Coastguard Worker     {
82*8975f5c5SAndroid Build Coastguard Worker         DestT destMax = std::numeric_limits<DestT>::max();
83*8975f5c5SAndroid Build Coastguard Worker         if (value >= static_cast<SrcT>(destMax))
84*8975f5c5SAndroid Build Coastguard Worker         {
85*8975f5c5SAndroid Build Coastguard Worker             return destMax;
86*8975f5c5SAndroid Build Coastguard Worker         }
87*8975f5c5SAndroid Build Coastguard Worker     }
88*8975f5c5SAndroid Build Coastguard Worker 
89*8975f5c5SAndroid Build Coastguard Worker     if (destLo > srcLo)
90*8975f5c5SAndroid Build Coastguard Worker     {
91*8975f5c5SAndroid Build Coastguard Worker         DestT destLow = std::numeric_limits<DestT>::lowest();
92*8975f5c5SAndroid Build Coastguard Worker         if (value <= static_cast<SrcT>(destLow))
93*8975f5c5SAndroid Build Coastguard Worker         {
94*8975f5c5SAndroid Build Coastguard Worker             return destLow;
95*8975f5c5SAndroid Build Coastguard Worker         }
96*8975f5c5SAndroid Build Coastguard Worker     }
97*8975f5c5SAndroid Build Coastguard Worker 
98*8975f5c5SAndroid Build Coastguard Worker     return static_cast<DestT>(value);
99*8975f5c5SAndroid Build Coastguard Worker }
100*8975f5c5SAndroid Build Coastguard Worker 
101*8975f5c5SAndroid Build Coastguard Worker // Specialize clampCast for bool->int conversion to avoid MSVS 2015 performance warning when the max
102*8975f5c5SAndroid Build Coastguard Worker // value is casted to the source type.
103*8975f5c5SAndroid Build Coastguard Worker template <>
clampCast(bool value)104*8975f5c5SAndroid Build Coastguard Worker inline unsigned int clampCast(bool value)
105*8975f5c5SAndroid Build Coastguard Worker {
106*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned int>(value);
107*8975f5c5SAndroid Build Coastguard Worker }
108*8975f5c5SAndroid Build Coastguard Worker 
109*8975f5c5SAndroid Build Coastguard Worker template <>
clampCast(bool value)110*8975f5c5SAndroid Build Coastguard Worker inline int clampCast(bool value)
111*8975f5c5SAndroid Build Coastguard Worker {
112*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(value);
113*8975f5c5SAndroid Build Coastguard Worker }
114*8975f5c5SAndroid Build Coastguard Worker 
115*8975f5c5SAndroid Build Coastguard Worker template <typename T, typename MIN, typename MAX>
clamp(T x,MIN min,MAX max)116*8975f5c5SAndroid Build Coastguard Worker inline T clamp(T x, MIN min, MAX max)
117*8975f5c5SAndroid Build Coastguard Worker {
118*8975f5c5SAndroid Build Coastguard Worker     // Since NaNs fail all comparison tests, a NaN value will default to min
119*8975f5c5SAndroid Build Coastguard Worker     return x > min ? (x > max ? max : x) : min;
120*8975f5c5SAndroid Build Coastguard Worker }
121*8975f5c5SAndroid Build Coastguard Worker 
122*8975f5c5SAndroid Build Coastguard Worker template <typename T>
clampForBitCount(T value,size_t bitCount)123*8975f5c5SAndroid Build Coastguard Worker T clampForBitCount(T value, size_t bitCount)
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
126*8975f5c5SAndroid Build Coastguard Worker 
127*8975f5c5SAndroid Build Coastguard Worker     if (bitCount == 0)
128*8975f5c5SAndroid Build Coastguard Worker     {
129*8975f5c5SAndroid Build Coastguard Worker         constexpr T kZero = 0;
130*8975f5c5SAndroid Build Coastguard Worker         return kZero;
131*8975f5c5SAndroid Build Coastguard Worker     }
132*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bitCount <= sizeof(T) * 8);
133*8975f5c5SAndroid Build Coastguard Worker 
134*8975f5c5SAndroid Build Coastguard Worker     constexpr bool kIsSigned = std::numeric_limits<T>::is_signed;
135*8975f5c5SAndroid Build Coastguard Worker     ASSERT((bitCount > 1) || !kIsSigned);
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker     T min = 0;
138*8975f5c5SAndroid Build Coastguard Worker     T max = 0;
139*8975f5c5SAndroid Build Coastguard Worker     if (bitCount == sizeof(T) * 8)
140*8975f5c5SAndroid Build Coastguard Worker     {
141*8975f5c5SAndroid Build Coastguard Worker         min = std::numeric_limits<T>::min();
142*8975f5c5SAndroid Build Coastguard Worker         max = std::numeric_limits<T>::max();
143*8975f5c5SAndroid Build Coastguard Worker     }
144*8975f5c5SAndroid Build Coastguard Worker     else
145*8975f5c5SAndroid Build Coastguard Worker     {
146*8975f5c5SAndroid Build Coastguard Worker         constexpr T kOne = 1;
147*8975f5c5SAndroid Build Coastguard Worker         min              = (kIsSigned) ? -1 * (kOne << (bitCount - 1)) : 0;
148*8975f5c5SAndroid Build Coastguard Worker         max              = (kIsSigned) ? (kOne << (bitCount - 1)) - 1 : (kOne << bitCount) - 1;
149*8975f5c5SAndroid Build Coastguard Worker     }
150*8975f5c5SAndroid Build Coastguard Worker 
151*8975f5c5SAndroid Build Coastguard Worker     return gl::clamp(value, min, max);
152*8975f5c5SAndroid Build Coastguard Worker }
153*8975f5c5SAndroid Build Coastguard Worker 
clamp01(float x)154*8975f5c5SAndroid Build Coastguard Worker inline float clamp01(float x)
155*8975f5c5SAndroid Build Coastguard Worker {
156*8975f5c5SAndroid Build Coastguard Worker     return clamp(x, 0.0f, 1.0f);
157*8975f5c5SAndroid Build Coastguard Worker }
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker template <const int n>
unorm(float x)160*8975f5c5SAndroid Build Coastguard Worker inline unsigned int unorm(float x)
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker     const unsigned int max = 0xFFFFFFFF >> (32 - n);
163*8975f5c5SAndroid Build Coastguard Worker 
164*8975f5c5SAndroid Build Coastguard Worker     if (x > 1)
165*8975f5c5SAndroid Build Coastguard Worker     {
166*8975f5c5SAndroid Build Coastguard Worker         return max;
167*8975f5c5SAndroid Build Coastguard Worker     }
168*8975f5c5SAndroid Build Coastguard Worker     else if (x < 0)
169*8975f5c5SAndroid Build Coastguard Worker     {
170*8975f5c5SAndroid Build Coastguard Worker         return 0;
171*8975f5c5SAndroid Build Coastguard Worker     }
172*8975f5c5SAndroid Build Coastguard Worker     else
173*8975f5c5SAndroid Build Coastguard Worker     {
174*8975f5c5SAndroid Build Coastguard Worker         return (unsigned int)(max * x + 0.5f);
175*8975f5c5SAndroid Build Coastguard Worker     }
176*8975f5c5SAndroid Build Coastguard Worker }
177*8975f5c5SAndroid Build Coastguard Worker 
178*8975f5c5SAndroid Build Coastguard Worker template <typename destType, typename sourceType>
bitCast(const sourceType & source)179*8975f5c5SAndroid Build Coastguard Worker destType bitCast(const sourceType &source)
180*8975f5c5SAndroid Build Coastguard Worker {
181*8975f5c5SAndroid Build Coastguard Worker     size_t copySize = std::min(sizeof(destType), sizeof(sourceType));
182*8975f5c5SAndroid Build Coastguard Worker     destType output;
183*8975f5c5SAndroid Build Coastguard Worker     memcpy(&output, &source, copySize);
184*8975f5c5SAndroid Build Coastguard Worker     return output;
185*8975f5c5SAndroid Build Coastguard Worker }
186*8975f5c5SAndroid Build Coastguard Worker 
187*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
unsafe_int_to_pointer_cast(SrcT src)188*8975f5c5SAndroid Build Coastguard Worker DestT unsafe_int_to_pointer_cast(SrcT src)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker     return reinterpret_cast<DestT>(static_cast<uintptr_t>(src));
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker 
193*8975f5c5SAndroid Build Coastguard Worker template <typename DestT, typename SrcT>
unsafe_pointer_to_int_cast(SrcT src)194*8975f5c5SAndroid Build Coastguard Worker DestT unsafe_pointer_to_int_cast(SrcT src)
195*8975f5c5SAndroid Build Coastguard Worker {
196*8975f5c5SAndroid Build Coastguard Worker     return static_cast<DestT>(reinterpret_cast<uintptr_t>(src));
197*8975f5c5SAndroid Build Coastguard Worker }
198*8975f5c5SAndroid Build Coastguard Worker 
199*8975f5c5SAndroid Build Coastguard Worker // https://stackoverflow.com/a/37581284
200*8975f5c5SAndroid Build Coastguard Worker template <typename T>
normalize(T value)201*8975f5c5SAndroid Build Coastguard Worker static constexpr double normalize(T value)
202*8975f5c5SAndroid Build Coastguard Worker {
203*8975f5c5SAndroid Build Coastguard Worker     return value < 0 ? -static_cast<double>(value) / std::numeric_limits<T>::min()
204*8975f5c5SAndroid Build Coastguard Worker                      : static_cast<double>(value) / std::numeric_limits<T>::max();
205*8975f5c5SAndroid Build Coastguard Worker }
206*8975f5c5SAndroid Build Coastguard Worker 
float32ToFloat16(float fp32)207*8975f5c5SAndroid Build Coastguard Worker inline unsigned short float32ToFloat16(float fp32)
208*8975f5c5SAndroid Build Coastguard Worker {
209*8975f5c5SAndroid Build Coastguard Worker     unsigned int fp32i = bitCast<unsigned int>(fp32);
210*8975f5c5SAndroid Build Coastguard Worker     unsigned int sign  = (fp32i & 0x80000000) >> 16;
211*8975f5c5SAndroid Build Coastguard Worker     unsigned int abs   = fp32i & 0x7FFFFFFF;
212*8975f5c5SAndroid Build Coastguard Worker 
213*8975f5c5SAndroid Build Coastguard Worker     if (abs > 0x7F800000)
214*8975f5c5SAndroid Build Coastguard Worker     {  // NaN
215*8975f5c5SAndroid Build Coastguard Worker         return 0x7FFF;
216*8975f5c5SAndroid Build Coastguard Worker     }
217*8975f5c5SAndroid Build Coastguard Worker     else if (abs > 0x47FFEFFF)
218*8975f5c5SAndroid Build Coastguard Worker     {  // Infinity
219*8975f5c5SAndroid Build Coastguard Worker         return static_cast<uint16_t>(sign | 0x7C00);
220*8975f5c5SAndroid Build Coastguard Worker     }
221*8975f5c5SAndroid Build Coastguard Worker     else if (abs < 0x38800000)  // Denormal
222*8975f5c5SAndroid Build Coastguard Worker     {
223*8975f5c5SAndroid Build Coastguard Worker         unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
224*8975f5c5SAndroid Build Coastguard Worker         int e                 = 113 - (abs >> 23);
225*8975f5c5SAndroid Build Coastguard Worker 
226*8975f5c5SAndroid Build Coastguard Worker         if (e < 24)
227*8975f5c5SAndroid Build Coastguard Worker         {
228*8975f5c5SAndroid Build Coastguard Worker             abs = mantissa >> e;
229*8975f5c5SAndroid Build Coastguard Worker         }
230*8975f5c5SAndroid Build Coastguard Worker         else
231*8975f5c5SAndroid Build Coastguard Worker         {
232*8975f5c5SAndroid Build Coastguard Worker             abs = 0;
233*8975f5c5SAndroid Build Coastguard Worker         }
234*8975f5c5SAndroid Build Coastguard Worker 
235*8975f5c5SAndroid Build Coastguard Worker         return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
236*8975f5c5SAndroid Build Coastguard Worker     }
237*8975f5c5SAndroid Build Coastguard Worker     else
238*8975f5c5SAndroid Build Coastguard Worker     {
239*8975f5c5SAndroid Build Coastguard Worker         return static_cast<unsigned short>(
240*8975f5c5SAndroid Build Coastguard Worker             sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
241*8975f5c5SAndroid Build Coastguard Worker     }
242*8975f5c5SAndroid Build Coastguard Worker }
243*8975f5c5SAndroid Build Coastguard Worker 
244*8975f5c5SAndroid Build Coastguard Worker float float16ToFloat32(unsigned short h);
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
247*8975f5c5SAndroid Build Coastguard Worker void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
248*8975f5c5SAndroid Build Coastguard Worker 
float32ToFloat11(float fp32)249*8975f5c5SAndroid Build Coastguard Worker inline unsigned short float32ToFloat11(float fp32)
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MantissaMask     = 0x7FFFFF;
252*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentMask     = 0x7F800000;
253*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32SignMask         = 0x80000000;
254*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ValueMask        = ~float32SignMask;
255*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentFirstBit = 23;
256*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentBias     = 127;
257*8975f5c5SAndroid Build Coastguard Worker 
258*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float11Max          = 0x7BF;
259*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float11MantissaMask = 0x3F;
260*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float11ExponentMask = 0x7C0;
261*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float11BitMask      = 0x7FF;
262*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float11ExponentBias   = 14;
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32Maxfloat11       = 0x477E0000;
265*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MinNormfloat11   = 0x38800000;
266*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MinDenormfloat11 = 0x35000080;
267*8975f5c5SAndroid Build Coastguard Worker 
268*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
269*8975f5c5SAndroid Build Coastguard Worker     const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
270*8975f5c5SAndroid Build Coastguard Worker 
271*8975f5c5SAndroid Build Coastguard Worker     unsigned int float32Val = float32Bits & float32ValueMask;
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker     if ((float32Val & float32ExponentMask) == float32ExponentMask)
274*8975f5c5SAndroid Build Coastguard Worker     {
275*8975f5c5SAndroid Build Coastguard Worker         // INF or NAN
276*8975f5c5SAndroid Build Coastguard Worker         if ((float32Val & float32MantissaMask) != 0)
277*8975f5c5SAndroid Build Coastguard Worker         {
278*8975f5c5SAndroid Build Coastguard Worker             return float11ExponentMask |
279*8975f5c5SAndroid Build Coastguard Worker                    (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
280*8975f5c5SAndroid Build Coastguard Worker                     float11MantissaMask);
281*8975f5c5SAndroid Build Coastguard Worker         }
282*8975f5c5SAndroid Build Coastguard Worker         else if (float32Sign)
283*8975f5c5SAndroid Build Coastguard Worker         {
284*8975f5c5SAndroid Build Coastguard Worker             // -INF is clamped to 0 since float11 is positive only
285*8975f5c5SAndroid Build Coastguard Worker             return 0;
286*8975f5c5SAndroid Build Coastguard Worker         }
287*8975f5c5SAndroid Build Coastguard Worker         else
288*8975f5c5SAndroid Build Coastguard Worker         {
289*8975f5c5SAndroid Build Coastguard Worker             return float11ExponentMask;
290*8975f5c5SAndroid Build Coastguard Worker         }
291*8975f5c5SAndroid Build Coastguard Worker     }
292*8975f5c5SAndroid Build Coastguard Worker     else if (float32Sign)
293*8975f5c5SAndroid Build Coastguard Worker     {
294*8975f5c5SAndroid Build Coastguard Worker         // float11 is positive only, so clamp to zero
295*8975f5c5SAndroid Build Coastguard Worker         return 0;
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker     else if (float32Val > float32Maxfloat11)
298*8975f5c5SAndroid Build Coastguard Worker     {
299*8975f5c5SAndroid Build Coastguard Worker         // The number is too large to be represented as a float11, set to max
300*8975f5c5SAndroid Build Coastguard Worker         return float11Max;
301*8975f5c5SAndroid Build Coastguard Worker     }
302*8975f5c5SAndroid Build Coastguard Worker     else if (float32Val < float32MinDenormfloat11)
303*8975f5c5SAndroid Build Coastguard Worker     {
304*8975f5c5SAndroid Build Coastguard Worker         // The number is too small to be represented as a denormalized float11, set to 0
305*8975f5c5SAndroid Build Coastguard Worker         return 0;
306*8975f5c5SAndroid Build Coastguard Worker     }
307*8975f5c5SAndroid Build Coastguard Worker     else
308*8975f5c5SAndroid Build Coastguard Worker     {
309*8975f5c5SAndroid Build Coastguard Worker         if (float32Val < float32MinNormfloat11)
310*8975f5c5SAndroid Build Coastguard Worker         {
311*8975f5c5SAndroid Build Coastguard Worker             // The number is too small to be represented as a normalized float11
312*8975f5c5SAndroid Build Coastguard Worker             // Convert it to a denormalized value.
313*8975f5c5SAndroid Build Coastguard Worker             const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
314*8975f5c5SAndroid Build Coastguard Worker                                        (float32Val >> float32ExponentFirstBit);
315*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shift < 32);
316*8975f5c5SAndroid Build Coastguard Worker             float32Val =
317*8975f5c5SAndroid Build Coastguard Worker                 ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
318*8975f5c5SAndroid Build Coastguard Worker         }
319*8975f5c5SAndroid Build Coastguard Worker         else
320*8975f5c5SAndroid Build Coastguard Worker         {
321*8975f5c5SAndroid Build Coastguard Worker             // Rebias the exponent to represent the value as a normalized float11
322*8975f5c5SAndroid Build Coastguard Worker             float32Val += 0xC8000000;
323*8975f5c5SAndroid Build Coastguard Worker         }
324*8975f5c5SAndroid Build Coastguard Worker 
325*8975f5c5SAndroid Build Coastguard Worker         return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
326*8975f5c5SAndroid Build Coastguard Worker     }
327*8975f5c5SAndroid Build Coastguard Worker }
328*8975f5c5SAndroid Build Coastguard Worker 
float32ToFloat10(float fp32)329*8975f5c5SAndroid Build Coastguard Worker inline unsigned short float32ToFloat10(float fp32)
330*8975f5c5SAndroid Build Coastguard Worker {
331*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MantissaMask     = 0x7FFFFF;
332*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentMask     = 0x7F800000;
333*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32SignMask         = 0x80000000;
334*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ValueMask        = ~float32SignMask;
335*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentFirstBit = 23;
336*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32ExponentBias     = 127;
337*8975f5c5SAndroid Build Coastguard Worker 
338*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float10Max          = 0x3DF;
339*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float10MantissaMask = 0x1F;
340*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float10ExponentMask = 0x3E0;
341*8975f5c5SAndroid Build Coastguard Worker     const unsigned short float10BitMask      = 0x3FF;
342*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float10ExponentBias   = 14;
343*8975f5c5SAndroid Build Coastguard Worker 
344*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32Maxfloat10       = 0x477C0000;
345*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MinNormfloat10   = 0x38800000;
346*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32MinDenormfloat10 = 0x35800040;
347*8975f5c5SAndroid Build Coastguard Worker 
348*8975f5c5SAndroid Build Coastguard Worker     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
349*8975f5c5SAndroid Build Coastguard Worker     const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
350*8975f5c5SAndroid Build Coastguard Worker 
351*8975f5c5SAndroid Build Coastguard Worker     unsigned int float32Val = float32Bits & float32ValueMask;
352*8975f5c5SAndroid Build Coastguard Worker 
353*8975f5c5SAndroid Build Coastguard Worker     if ((float32Val & float32ExponentMask) == float32ExponentMask)
354*8975f5c5SAndroid Build Coastguard Worker     {
355*8975f5c5SAndroid Build Coastguard Worker         // INF or NAN
356*8975f5c5SAndroid Build Coastguard Worker         if ((float32Val & float32MantissaMask) != 0)
357*8975f5c5SAndroid Build Coastguard Worker         {
358*8975f5c5SAndroid Build Coastguard Worker             return float10ExponentMask |
359*8975f5c5SAndroid Build Coastguard Worker                    (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
360*8975f5c5SAndroid Build Coastguard Worker                     float10MantissaMask);
361*8975f5c5SAndroid Build Coastguard Worker         }
362*8975f5c5SAndroid Build Coastguard Worker         else if (float32Sign)
363*8975f5c5SAndroid Build Coastguard Worker         {
364*8975f5c5SAndroid Build Coastguard Worker             // -INF is clamped to 0 since float10 is positive only
365*8975f5c5SAndroid Build Coastguard Worker             return 0;
366*8975f5c5SAndroid Build Coastguard Worker         }
367*8975f5c5SAndroid Build Coastguard Worker         else
368*8975f5c5SAndroid Build Coastguard Worker         {
369*8975f5c5SAndroid Build Coastguard Worker             return float10ExponentMask;
370*8975f5c5SAndroid Build Coastguard Worker         }
371*8975f5c5SAndroid Build Coastguard Worker     }
372*8975f5c5SAndroid Build Coastguard Worker     else if (float32Sign)
373*8975f5c5SAndroid Build Coastguard Worker     {
374*8975f5c5SAndroid Build Coastguard Worker         // float10 is positive only, so clamp to zero
375*8975f5c5SAndroid Build Coastguard Worker         return 0;
376*8975f5c5SAndroid Build Coastguard Worker     }
377*8975f5c5SAndroid Build Coastguard Worker     else if (float32Val > float32Maxfloat10)
378*8975f5c5SAndroid Build Coastguard Worker     {
379*8975f5c5SAndroid Build Coastguard Worker         // The number is too large to be represented as a float10, set to max
380*8975f5c5SAndroid Build Coastguard Worker         return float10Max;
381*8975f5c5SAndroid Build Coastguard Worker     }
382*8975f5c5SAndroid Build Coastguard Worker     else if (float32Val < float32MinDenormfloat10)
383*8975f5c5SAndroid Build Coastguard Worker     {
384*8975f5c5SAndroid Build Coastguard Worker         // The number is too small to be represented as a denormalized float10, set to 0
385*8975f5c5SAndroid Build Coastguard Worker         return 0;
386*8975f5c5SAndroid Build Coastguard Worker     }
387*8975f5c5SAndroid Build Coastguard Worker     else
388*8975f5c5SAndroid Build Coastguard Worker     {
389*8975f5c5SAndroid Build Coastguard Worker         if (float32Val < float32MinNormfloat10)
390*8975f5c5SAndroid Build Coastguard Worker         {
391*8975f5c5SAndroid Build Coastguard Worker             // The number is too small to be represented as a normalized float10
392*8975f5c5SAndroid Build Coastguard Worker             // Convert it to a denormalized value.
393*8975f5c5SAndroid Build Coastguard Worker             const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
394*8975f5c5SAndroid Build Coastguard Worker                                        (float32Val >> float32ExponentFirstBit);
395*8975f5c5SAndroid Build Coastguard Worker             ASSERT(shift < 32);
396*8975f5c5SAndroid Build Coastguard Worker             float32Val =
397*8975f5c5SAndroid Build Coastguard Worker                 ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
398*8975f5c5SAndroid Build Coastguard Worker         }
399*8975f5c5SAndroid Build Coastguard Worker         else
400*8975f5c5SAndroid Build Coastguard Worker         {
401*8975f5c5SAndroid Build Coastguard Worker             // Rebias the exponent to represent the value as a normalized float10
402*8975f5c5SAndroid Build Coastguard Worker             float32Val += 0xC8000000;
403*8975f5c5SAndroid Build Coastguard Worker         }
404*8975f5c5SAndroid Build Coastguard Worker 
405*8975f5c5SAndroid Build Coastguard Worker         return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
406*8975f5c5SAndroid Build Coastguard Worker     }
407*8975f5c5SAndroid Build Coastguard Worker }
408*8975f5c5SAndroid Build Coastguard Worker 
float11ToFloat32(unsigned short fp11)409*8975f5c5SAndroid Build Coastguard Worker inline float float11ToFloat32(unsigned short fp11)
410*8975f5c5SAndroid Build Coastguard Worker {
411*8975f5c5SAndroid Build Coastguard Worker     unsigned short exponent = (fp11 >> 6) & 0x1F;
412*8975f5c5SAndroid Build Coastguard Worker     unsigned short mantissa = fp11 & 0x3F;
413*8975f5c5SAndroid Build Coastguard Worker 
414*8975f5c5SAndroid Build Coastguard Worker     if (exponent == 0x1F)
415*8975f5c5SAndroid Build Coastguard Worker     {
416*8975f5c5SAndroid Build Coastguard Worker         // INF or NAN
417*8975f5c5SAndroid Build Coastguard Worker         return bitCast<float>(0x7f800000 | (mantissa << 17));
418*8975f5c5SAndroid Build Coastguard Worker     }
419*8975f5c5SAndroid Build Coastguard Worker     else
420*8975f5c5SAndroid Build Coastguard Worker     {
421*8975f5c5SAndroid Build Coastguard Worker         if (exponent != 0)
422*8975f5c5SAndroid Build Coastguard Worker         {
423*8975f5c5SAndroid Build Coastguard Worker             // normalized
424*8975f5c5SAndroid Build Coastguard Worker         }
425*8975f5c5SAndroid Build Coastguard Worker         else if (mantissa != 0)
426*8975f5c5SAndroid Build Coastguard Worker         {
427*8975f5c5SAndroid Build Coastguard Worker             // The value is denormalized
428*8975f5c5SAndroid Build Coastguard Worker             exponent = 1;
429*8975f5c5SAndroid Build Coastguard Worker 
430*8975f5c5SAndroid Build Coastguard Worker             do
431*8975f5c5SAndroid Build Coastguard Worker             {
432*8975f5c5SAndroid Build Coastguard Worker                 exponent--;
433*8975f5c5SAndroid Build Coastguard Worker                 mantissa <<= 1;
434*8975f5c5SAndroid Build Coastguard Worker             } while ((mantissa & 0x40) == 0);
435*8975f5c5SAndroid Build Coastguard Worker 
436*8975f5c5SAndroid Build Coastguard Worker             mantissa = mantissa & 0x3F;
437*8975f5c5SAndroid Build Coastguard Worker         }
438*8975f5c5SAndroid Build Coastguard Worker         else  // The value is zero
439*8975f5c5SAndroid Build Coastguard Worker         {
440*8975f5c5SAndroid Build Coastguard Worker             exponent = static_cast<unsigned short>(-112);
441*8975f5c5SAndroid Build Coastguard Worker         }
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
444*8975f5c5SAndroid Build Coastguard Worker     }
445*8975f5c5SAndroid Build Coastguard Worker }
446*8975f5c5SAndroid Build Coastguard Worker 
float10ToFloat32(unsigned short fp10)447*8975f5c5SAndroid Build Coastguard Worker inline float float10ToFloat32(unsigned short fp10)
448*8975f5c5SAndroid Build Coastguard Worker {
449*8975f5c5SAndroid Build Coastguard Worker     unsigned short exponent = (fp10 >> 5) & 0x1F;
450*8975f5c5SAndroid Build Coastguard Worker     unsigned short mantissa = fp10 & 0x1F;
451*8975f5c5SAndroid Build Coastguard Worker 
452*8975f5c5SAndroid Build Coastguard Worker     if (exponent == 0x1F)
453*8975f5c5SAndroid Build Coastguard Worker     {
454*8975f5c5SAndroid Build Coastguard Worker         // INF or NAN
455*8975f5c5SAndroid Build Coastguard Worker         return bitCast<float>(0x7f800000 | (mantissa << 17));
456*8975f5c5SAndroid Build Coastguard Worker     }
457*8975f5c5SAndroid Build Coastguard Worker     else
458*8975f5c5SAndroid Build Coastguard Worker     {
459*8975f5c5SAndroid Build Coastguard Worker         if (exponent != 0)
460*8975f5c5SAndroid Build Coastguard Worker         {
461*8975f5c5SAndroid Build Coastguard Worker             // normalized
462*8975f5c5SAndroid Build Coastguard Worker         }
463*8975f5c5SAndroid Build Coastguard Worker         else if (mantissa != 0)
464*8975f5c5SAndroid Build Coastguard Worker         {
465*8975f5c5SAndroid Build Coastguard Worker             // The value is denormalized
466*8975f5c5SAndroid Build Coastguard Worker             exponent = 1;
467*8975f5c5SAndroid Build Coastguard Worker 
468*8975f5c5SAndroid Build Coastguard Worker             do
469*8975f5c5SAndroid Build Coastguard Worker             {
470*8975f5c5SAndroid Build Coastguard Worker                 exponent--;
471*8975f5c5SAndroid Build Coastguard Worker                 mantissa <<= 1;
472*8975f5c5SAndroid Build Coastguard Worker             } while ((mantissa & 0x20) == 0);
473*8975f5c5SAndroid Build Coastguard Worker 
474*8975f5c5SAndroid Build Coastguard Worker             mantissa = mantissa & 0x1F;
475*8975f5c5SAndroid Build Coastguard Worker         }
476*8975f5c5SAndroid Build Coastguard Worker         else  // The value is zero
477*8975f5c5SAndroid Build Coastguard Worker         {
478*8975f5c5SAndroid Build Coastguard Worker             exponent = static_cast<unsigned short>(-112);
479*8975f5c5SAndroid Build Coastguard Worker         }
480*8975f5c5SAndroid Build Coastguard Worker 
481*8975f5c5SAndroid Build Coastguard Worker         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
482*8975f5c5SAndroid Build Coastguard Worker     }
483*8975f5c5SAndroid Build Coastguard Worker }
484*8975f5c5SAndroid Build Coastguard Worker 
485*8975f5c5SAndroid Build Coastguard Worker // Converts to and from float and 16.16 fixed point format.
ConvertFixedToFloat(int32_t fixedInput)486*8975f5c5SAndroid Build Coastguard Worker inline float ConvertFixedToFloat(int32_t fixedInput)
487*8975f5c5SAndroid Build Coastguard Worker {
488*8975f5c5SAndroid Build Coastguard Worker     return static_cast<float>(fixedInput) / 65536.0f;
489*8975f5c5SAndroid Build Coastguard Worker }
490*8975f5c5SAndroid Build Coastguard Worker 
ConvertFloatToFixed(float floatInput)491*8975f5c5SAndroid Build Coastguard Worker inline uint32_t ConvertFloatToFixed(float floatInput)
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker     static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
494*8975f5c5SAndroid Build Coastguard Worker     static constexpr uint32_t kLowest  = static_cast<uint32_t>(-32768 * 65536 + 65535);
495*8975f5c5SAndroid Build Coastguard Worker 
496*8975f5c5SAndroid Build Coastguard Worker     if (floatInput > 32767.65535)
497*8975f5c5SAndroid Build Coastguard Worker     {
498*8975f5c5SAndroid Build Coastguard Worker         return kHighest;
499*8975f5c5SAndroid Build Coastguard Worker     }
500*8975f5c5SAndroid Build Coastguard Worker     else if (floatInput < -32768.65535)
501*8975f5c5SAndroid Build Coastguard Worker     {
502*8975f5c5SAndroid Build Coastguard Worker         return kLowest;
503*8975f5c5SAndroid Build Coastguard Worker     }
504*8975f5c5SAndroid Build Coastguard Worker     else
505*8975f5c5SAndroid Build Coastguard Worker     {
506*8975f5c5SAndroid Build Coastguard Worker         return static_cast<uint32_t>(floatInput * 65536);
507*8975f5c5SAndroid Build Coastguard Worker     }
508*8975f5c5SAndroid Build Coastguard Worker }
509*8975f5c5SAndroid Build Coastguard Worker 
510*8975f5c5SAndroid Build Coastguard Worker template <typename T>
normalizedToFloat(T input)511*8975f5c5SAndroid Build Coastguard Worker inline float normalizedToFloat(T input)
512*8975f5c5SAndroid Build Coastguard Worker {
513*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
514*8975f5c5SAndroid Build Coastguard Worker 
515*8975f5c5SAndroid Build Coastguard Worker     if constexpr (sizeof(T) > 2)
516*8975f5c5SAndroid Build Coastguard Worker     {
517*8975f5c5SAndroid Build Coastguard Worker         // float has only a 23 bit mantissa, so we need to do the calculation in double precision
518*8975f5c5SAndroid Build Coastguard Worker         constexpr double inverseMax = 1.0 / std::numeric_limits<T>::max();
519*8975f5c5SAndroid Build Coastguard Worker         return static_cast<float>(input * inverseMax);
520*8975f5c5SAndroid Build Coastguard Worker     }
521*8975f5c5SAndroid Build Coastguard Worker     else
522*8975f5c5SAndroid Build Coastguard Worker     {
523*8975f5c5SAndroid Build Coastguard Worker         constexpr float inverseMax = 1.0f / std::numeric_limits<T>::max();
524*8975f5c5SAndroid Build Coastguard Worker         return input * inverseMax;
525*8975f5c5SAndroid Build Coastguard Worker     }
526*8975f5c5SAndroid Build Coastguard Worker }
527*8975f5c5SAndroid Build Coastguard Worker 
528*8975f5c5SAndroid Build Coastguard Worker template <unsigned int inputBitCount, typename T>
normalizedToFloat(T input)529*8975f5c5SAndroid Build Coastguard Worker inline float normalizedToFloat(T input)
530*8975f5c5SAndroid Build Coastguard Worker {
531*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
532*8975f5c5SAndroid Build Coastguard Worker     static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
533*8975f5c5SAndroid Build Coastguard Worker     ASSERT((input & ~((1 << inputBitCount) - 1)) == 0);
534*8975f5c5SAndroid Build Coastguard Worker 
535*8975f5c5SAndroid Build Coastguard Worker     if (inputBitCount > 23)
536*8975f5c5SAndroid Build Coastguard Worker     {
537*8975f5c5SAndroid Build Coastguard Worker         // float has only a 23 bit mantissa, so we need to do the calculation in double precision
538*8975f5c5SAndroid Build Coastguard Worker         constexpr double inverseMax = 1.0 / ((1 << inputBitCount) - 1);
539*8975f5c5SAndroid Build Coastguard Worker         return static_cast<float>(input * inverseMax);
540*8975f5c5SAndroid Build Coastguard Worker     }
541*8975f5c5SAndroid Build Coastguard Worker     else
542*8975f5c5SAndroid Build Coastguard Worker     {
543*8975f5c5SAndroid Build Coastguard Worker         constexpr float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
544*8975f5c5SAndroid Build Coastguard Worker         return input * inverseMax;
545*8975f5c5SAndroid Build Coastguard Worker     }
546*8975f5c5SAndroid Build Coastguard Worker }
547*8975f5c5SAndroid Build Coastguard Worker 
548*8975f5c5SAndroid Build Coastguard Worker template <typename T, typename R>
roundToNearest(T input)549*8975f5c5SAndroid Build Coastguard Worker inline R roundToNearest(T input)
550*8975f5c5SAndroid Build Coastguard Worker {
551*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_floating_point<T>::value);
552*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::numeric_limits<R>::is_integer);
553*8975f5c5SAndroid Build Coastguard Worker #if defined(__aarch64__) || defined(_M_ARM64)
554*8975f5c5SAndroid Build Coastguard Worker     // On armv8, this expression is compiled to a dedicated round-to-nearest instruction
555*8975f5c5SAndroid Build Coastguard Worker     return static_cast<R>(std::round(input));
556*8975f5c5SAndroid Build Coastguard Worker #else
557*8975f5c5SAndroid Build Coastguard Worker     static_assert(0.49999997f < 0.5f);
558*8975f5c5SAndroid Build Coastguard Worker     static_assert(0.49999997f + 0.5f == 1.0f);
559*8975f5c5SAndroid Build Coastguard Worker     static_assert(0.49999999999999994 < 0.5);
560*8975f5c5SAndroid Build Coastguard Worker     static_assert(0.49999999999999994 + 0.5 == 1.0);
561*8975f5c5SAndroid Build Coastguard Worker     constexpr T bias = sizeof(T) == 8 ? 0.49999999999999994 : 0.49999997f;
562*8975f5c5SAndroid Build Coastguard Worker     return static_cast<R>(input + (std::is_signed<R>::value ? std::copysign(bias, input) : bias));
563*8975f5c5SAndroid Build Coastguard Worker #endif
564*8975f5c5SAndroid Build Coastguard Worker }
565*8975f5c5SAndroid Build Coastguard Worker 
566*8975f5c5SAndroid Build Coastguard Worker template <typename T>
floatToNormalized(float input)567*8975f5c5SAndroid Build Coastguard Worker inline T floatToNormalized(float input)
568*8975f5c5SAndroid Build Coastguard Worker {
569*8975f5c5SAndroid Build Coastguard Worker     if constexpr (sizeof(T) > 2)
570*8975f5c5SAndroid Build Coastguard Worker     {
571*8975f5c5SAndroid Build Coastguard Worker         // float has only a 23 bit mantissa, so we need to do the calculation in double precision
572*8975f5c5SAndroid Build Coastguard Worker         return roundToNearest<double, T>(std::numeric_limits<T>::max() *
573*8975f5c5SAndroid Build Coastguard Worker                                          static_cast<double>(input));
574*8975f5c5SAndroid Build Coastguard Worker     }
575*8975f5c5SAndroid Build Coastguard Worker     else
576*8975f5c5SAndroid Build Coastguard Worker     {
577*8975f5c5SAndroid Build Coastguard Worker         return roundToNearest<float, T>(std::numeric_limits<T>::max() * input);
578*8975f5c5SAndroid Build Coastguard Worker     }
579*8975f5c5SAndroid Build Coastguard Worker }
580*8975f5c5SAndroid Build Coastguard Worker 
581*8975f5c5SAndroid Build Coastguard Worker template <unsigned int outputBitCount, typename T>
floatToNormalized(float input)582*8975f5c5SAndroid Build Coastguard Worker inline T floatToNormalized(float input)
583*8975f5c5SAndroid Build Coastguard Worker {
584*8975f5c5SAndroid Build Coastguard Worker     static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
585*8975f5c5SAndroid Build Coastguard Worker     static_assert(outputBitCount > (std::is_unsigned<T>::value ? 0 : 1),
586*8975f5c5SAndroid Build Coastguard Worker                   "outputBitCount must be at least 1 not counting the sign bit.");
587*8975f5c5SAndroid Build Coastguard Worker     constexpr unsigned int bits = std::is_unsigned<T>::value ? outputBitCount : outputBitCount - 1;
588*8975f5c5SAndroid Build Coastguard Worker 
589*8975f5c5SAndroid Build Coastguard Worker     if (bits > 23)
590*8975f5c5SAndroid Build Coastguard Worker     {
591*8975f5c5SAndroid Build Coastguard Worker         // float has only a 23 bit mantissa, so we need to do the calculation in double precision
592*8975f5c5SAndroid Build Coastguard Worker         return roundToNearest<double, T>(((1 << bits) - 1) * static_cast<double>(input));
593*8975f5c5SAndroid Build Coastguard Worker     }
594*8975f5c5SAndroid Build Coastguard Worker     else
595*8975f5c5SAndroid Build Coastguard Worker     {
596*8975f5c5SAndroid Build Coastguard Worker         return roundToNearest<float, T>(((1 << bits) - 1) * input);
597*8975f5c5SAndroid Build Coastguard Worker     }
598*8975f5c5SAndroid Build Coastguard Worker }
599*8975f5c5SAndroid Build Coastguard Worker 
600*8975f5c5SAndroid Build Coastguard Worker template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
getShiftedData(T input)601*8975f5c5SAndroid Build Coastguard Worker inline T getShiftedData(T input)
602*8975f5c5SAndroid Build Coastguard Worker {
603*8975f5c5SAndroid Build Coastguard Worker     static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
604*8975f5c5SAndroid Build Coastguard Worker                   "T must have at least as many bits as inputBitCount + inputBitStart.");
605*8975f5c5SAndroid Build Coastguard Worker     const T mask = (1 << inputBitCount) - 1;
606*8975f5c5SAndroid Build Coastguard Worker     return (input >> inputBitStart) & mask;
607*8975f5c5SAndroid Build Coastguard Worker }
608*8975f5c5SAndroid Build Coastguard Worker 
609*8975f5c5SAndroid Build Coastguard Worker template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
shiftData(T input)610*8975f5c5SAndroid Build Coastguard Worker inline T shiftData(T input)
611*8975f5c5SAndroid Build Coastguard Worker {
612*8975f5c5SAndroid Build Coastguard Worker     static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
613*8975f5c5SAndroid Build Coastguard Worker                   "T must have at least as many bits as inputBitCount + inputBitStart.");
614*8975f5c5SAndroid Build Coastguard Worker     const T mask = (1 << inputBitCount) - 1;
615*8975f5c5SAndroid Build Coastguard Worker     return (input & mask) << inputBitStart;
616*8975f5c5SAndroid Build Coastguard Worker }
617*8975f5c5SAndroid Build Coastguard Worker 
CountLeadingZeros(uint32_t x)618*8975f5c5SAndroid Build Coastguard Worker inline unsigned int CountLeadingZeros(uint32_t x)
619*8975f5c5SAndroid Build Coastguard Worker {
620*8975f5c5SAndroid Build Coastguard Worker     // Use binary search to find the amount of leading zeros.
621*8975f5c5SAndroid Build Coastguard Worker     unsigned int zeros = 32u;
622*8975f5c5SAndroid Build Coastguard Worker     uint32_t y;
623*8975f5c5SAndroid Build Coastguard Worker 
624*8975f5c5SAndroid Build Coastguard Worker     y = x >> 16u;
625*8975f5c5SAndroid Build Coastguard Worker     if (y != 0)
626*8975f5c5SAndroid Build Coastguard Worker     {
627*8975f5c5SAndroid Build Coastguard Worker         zeros = zeros - 16u;
628*8975f5c5SAndroid Build Coastguard Worker         x     = y;
629*8975f5c5SAndroid Build Coastguard Worker     }
630*8975f5c5SAndroid Build Coastguard Worker     y = x >> 8u;
631*8975f5c5SAndroid Build Coastguard Worker     if (y != 0)
632*8975f5c5SAndroid Build Coastguard Worker     {
633*8975f5c5SAndroid Build Coastguard Worker         zeros = zeros - 8u;
634*8975f5c5SAndroid Build Coastguard Worker         x     = y;
635*8975f5c5SAndroid Build Coastguard Worker     }
636*8975f5c5SAndroid Build Coastguard Worker     y = x >> 4u;
637*8975f5c5SAndroid Build Coastguard Worker     if (y != 0)
638*8975f5c5SAndroid Build Coastguard Worker     {
639*8975f5c5SAndroid Build Coastguard Worker         zeros = zeros - 4u;
640*8975f5c5SAndroid Build Coastguard Worker         x     = y;
641*8975f5c5SAndroid Build Coastguard Worker     }
642*8975f5c5SAndroid Build Coastguard Worker     y = x >> 2u;
643*8975f5c5SAndroid Build Coastguard Worker     if (y != 0)
644*8975f5c5SAndroid Build Coastguard Worker     {
645*8975f5c5SAndroid Build Coastguard Worker         zeros = zeros - 2u;
646*8975f5c5SAndroid Build Coastguard Worker         x     = y;
647*8975f5c5SAndroid Build Coastguard Worker     }
648*8975f5c5SAndroid Build Coastguard Worker     y = x >> 1u;
649*8975f5c5SAndroid Build Coastguard Worker     if (y != 0)
650*8975f5c5SAndroid Build Coastguard Worker     {
651*8975f5c5SAndroid Build Coastguard Worker         return zeros - 2u;
652*8975f5c5SAndroid Build Coastguard Worker     }
653*8975f5c5SAndroid Build Coastguard Worker     return zeros - x;
654*8975f5c5SAndroid Build Coastguard Worker }
655*8975f5c5SAndroid Build Coastguard Worker 
average(unsigned char a,unsigned char b)656*8975f5c5SAndroid Build Coastguard Worker inline unsigned char average(unsigned char a, unsigned char b)
657*8975f5c5SAndroid Build Coastguard Worker {
658*8975f5c5SAndroid Build Coastguard Worker     return ((a ^ b) >> 1) + (a & b);
659*8975f5c5SAndroid Build Coastguard Worker }
660*8975f5c5SAndroid Build Coastguard Worker 
average(signed char a,signed char b)661*8975f5c5SAndroid Build Coastguard Worker inline signed char average(signed char a, signed char b)
662*8975f5c5SAndroid Build Coastguard Worker {
663*8975f5c5SAndroid Build Coastguard Worker     return ((short)a + (short)b) / 2;
664*8975f5c5SAndroid Build Coastguard Worker }
665*8975f5c5SAndroid Build Coastguard Worker 
average(unsigned short a,unsigned short b)666*8975f5c5SAndroid Build Coastguard Worker inline unsigned short average(unsigned short a, unsigned short b)
667*8975f5c5SAndroid Build Coastguard Worker {
668*8975f5c5SAndroid Build Coastguard Worker     return ((a ^ b) >> 1) + (a & b);
669*8975f5c5SAndroid Build Coastguard Worker }
670*8975f5c5SAndroid Build Coastguard Worker 
average(signed short a,signed short b)671*8975f5c5SAndroid Build Coastguard Worker inline signed short average(signed short a, signed short b)
672*8975f5c5SAndroid Build Coastguard Worker {
673*8975f5c5SAndroid Build Coastguard Worker     return ((int)a + (int)b) / 2;
674*8975f5c5SAndroid Build Coastguard Worker }
675*8975f5c5SAndroid Build Coastguard Worker 
average(unsigned int a,unsigned int b)676*8975f5c5SAndroid Build Coastguard Worker inline unsigned int average(unsigned int a, unsigned int b)
677*8975f5c5SAndroid Build Coastguard Worker {
678*8975f5c5SAndroid Build Coastguard Worker     return ((a ^ b) >> 1) + (a & b);
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker 
average(int a,int b)681*8975f5c5SAndroid Build Coastguard Worker inline int average(int a, int b)
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker     long long average = (static_cast<long long>(a) + static_cast<long long>(b)) / 2LL;
684*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(average);
685*8975f5c5SAndroid Build Coastguard Worker }
686*8975f5c5SAndroid Build Coastguard Worker 
average(float a,float b)687*8975f5c5SAndroid Build Coastguard Worker inline float average(float a, float b)
688*8975f5c5SAndroid Build Coastguard Worker {
689*8975f5c5SAndroid Build Coastguard Worker     return (a + b) * 0.5f;
690*8975f5c5SAndroid Build Coastguard Worker }
691*8975f5c5SAndroid Build Coastguard Worker 
averageHalfFloat(unsigned short a,unsigned short b)692*8975f5c5SAndroid Build Coastguard Worker inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
693*8975f5c5SAndroid Build Coastguard Worker {
694*8975f5c5SAndroid Build Coastguard Worker     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
695*8975f5c5SAndroid Build Coastguard Worker }
696*8975f5c5SAndroid Build Coastguard Worker 
averageFloat11(unsigned int a,unsigned int b)697*8975f5c5SAndroid Build Coastguard Worker inline unsigned int averageFloat11(unsigned int a, unsigned int b)
698*8975f5c5SAndroid Build Coastguard Worker {
699*8975f5c5SAndroid Build Coastguard Worker     return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) +
700*8975f5c5SAndroid Build Coastguard Worker                              float11ToFloat32(static_cast<unsigned short>(b))) *
701*8975f5c5SAndroid Build Coastguard Worker                             0.5f);
702*8975f5c5SAndroid Build Coastguard Worker }
703*8975f5c5SAndroid Build Coastguard Worker 
averageFloat10(unsigned int a,unsigned int b)704*8975f5c5SAndroid Build Coastguard Worker inline unsigned int averageFloat10(unsigned int a, unsigned int b)
705*8975f5c5SAndroid Build Coastguard Worker {
706*8975f5c5SAndroid Build Coastguard Worker     return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
707*8975f5c5SAndroid Build Coastguard Worker                              float10ToFloat32(static_cast<unsigned short>(b))) *
708*8975f5c5SAndroid Build Coastguard Worker                             0.5f);
709*8975f5c5SAndroid Build Coastguard Worker }
710*8975f5c5SAndroid Build Coastguard Worker 
711*8975f5c5SAndroid Build Coastguard Worker template <typename T>
712*8975f5c5SAndroid Build Coastguard Worker class Range
713*8975f5c5SAndroid Build Coastguard Worker {
714*8975f5c5SAndroid Build Coastguard Worker   public:
Range()715*8975f5c5SAndroid Build Coastguard Worker     Range() {}
Range(T lo,T hi)716*8975f5c5SAndroid Build Coastguard Worker     Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
717*8975f5c5SAndroid Build Coastguard Worker 
718*8975f5c5SAndroid Build Coastguard Worker     bool operator==(const Range<T> &other) const
719*8975f5c5SAndroid Build Coastguard Worker     {
720*8975f5c5SAndroid Build Coastguard Worker         return mLow == other.mLow && mHigh == other.mHigh;
721*8975f5c5SAndroid Build Coastguard Worker     }
722*8975f5c5SAndroid Build Coastguard Worker 
length()723*8975f5c5SAndroid Build Coastguard Worker     T length() const { return (empty() ? 0 : (mHigh - mLow)); }
724*8975f5c5SAndroid Build Coastguard Worker 
intersects(const Range<T> & other)725*8975f5c5SAndroid Build Coastguard Worker     bool intersects(const Range<T> &other) const
726*8975f5c5SAndroid Build Coastguard Worker     {
727*8975f5c5SAndroid Build Coastguard Worker         if (mLow <= other.mLow)
728*8975f5c5SAndroid Build Coastguard Worker         {
729*8975f5c5SAndroid Build Coastguard Worker             return other.mLow < mHigh;
730*8975f5c5SAndroid Build Coastguard Worker         }
731*8975f5c5SAndroid Build Coastguard Worker         else
732*8975f5c5SAndroid Build Coastguard Worker         {
733*8975f5c5SAndroid Build Coastguard Worker             return mLow < other.mHigh;
734*8975f5c5SAndroid Build Coastguard Worker         }
735*8975f5c5SAndroid Build Coastguard Worker     }
736*8975f5c5SAndroid Build Coastguard Worker 
intersectsOrContinuous(const Range<T> & other)737*8975f5c5SAndroid Build Coastguard Worker     bool intersectsOrContinuous(const Range<T> &other) const
738*8975f5c5SAndroid Build Coastguard Worker     {
739*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!empty());
740*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!other.empty());
741*8975f5c5SAndroid Build Coastguard Worker         if (mLow <= other.mLow)
742*8975f5c5SAndroid Build Coastguard Worker         {
743*8975f5c5SAndroid Build Coastguard Worker             return mHigh >= other.mLow;
744*8975f5c5SAndroid Build Coastguard Worker         }
745*8975f5c5SAndroid Build Coastguard Worker         else
746*8975f5c5SAndroid Build Coastguard Worker         {
747*8975f5c5SAndroid Build Coastguard Worker             return mLow <= other.mHigh;
748*8975f5c5SAndroid Build Coastguard Worker         }
749*8975f5c5SAndroid Build Coastguard Worker     }
750*8975f5c5SAndroid Build Coastguard Worker 
merge(const Range<T> & other)751*8975f5c5SAndroid Build Coastguard Worker     void merge(const Range<T> &other)
752*8975f5c5SAndroid Build Coastguard Worker     {
753*8975f5c5SAndroid Build Coastguard Worker         if (mLow > other.mLow)
754*8975f5c5SAndroid Build Coastguard Worker         {
755*8975f5c5SAndroid Build Coastguard Worker             mLow = other.mLow;
756*8975f5c5SAndroid Build Coastguard Worker         }
757*8975f5c5SAndroid Build Coastguard Worker 
758*8975f5c5SAndroid Build Coastguard Worker         if (mHigh < other.mHigh)
759*8975f5c5SAndroid Build Coastguard Worker         {
760*8975f5c5SAndroid Build Coastguard Worker             mHigh = other.mHigh;
761*8975f5c5SAndroid Build Coastguard Worker         }
762*8975f5c5SAndroid Build Coastguard Worker     }
763*8975f5c5SAndroid Build Coastguard Worker 
764*8975f5c5SAndroid Build Coastguard Worker     // Assumes that end is non-inclusive.. for example, extending to 5 will make "end" 6.
extend(T value)765*8975f5c5SAndroid Build Coastguard Worker     void extend(T value)
766*8975f5c5SAndroid Build Coastguard Worker     {
767*8975f5c5SAndroid Build Coastguard Worker         mLow  = value < mLow ? value : mLow;
768*8975f5c5SAndroid Build Coastguard Worker         mHigh = value >= mHigh ? (value + 1) : mHigh;
769*8975f5c5SAndroid Build Coastguard Worker     }
770*8975f5c5SAndroid Build Coastguard Worker 
empty()771*8975f5c5SAndroid Build Coastguard Worker     bool empty() const { return mHigh <= mLow; }
772*8975f5c5SAndroid Build Coastguard Worker 
contains(T value)773*8975f5c5SAndroid Build Coastguard Worker     bool contains(T value) const { return value >= mLow && value < mHigh; }
774*8975f5c5SAndroid Build Coastguard Worker 
775*8975f5c5SAndroid Build Coastguard Worker     class Iterator final
776*8975f5c5SAndroid Build Coastguard Worker     {
777*8975f5c5SAndroid Build Coastguard Worker       public:
Iterator(T value)778*8975f5c5SAndroid Build Coastguard Worker         Iterator(T value) : mCurrent(value) {}
779*8975f5c5SAndroid Build Coastguard Worker 
780*8975f5c5SAndroid Build Coastguard Worker         Iterator &operator++()
781*8975f5c5SAndroid Build Coastguard Worker         {
782*8975f5c5SAndroid Build Coastguard Worker             mCurrent++;
783*8975f5c5SAndroid Build Coastguard Worker             return *this;
784*8975f5c5SAndroid Build Coastguard Worker         }
785*8975f5c5SAndroid Build Coastguard Worker         bool operator==(const Iterator &other) const { return mCurrent == other.mCurrent; }
786*8975f5c5SAndroid Build Coastguard Worker         bool operator!=(const Iterator &other) const { return mCurrent != other.mCurrent; }
787*8975f5c5SAndroid Build Coastguard Worker         T operator*() const { return mCurrent; }
788*8975f5c5SAndroid Build Coastguard Worker 
789*8975f5c5SAndroid Build Coastguard Worker       private:
790*8975f5c5SAndroid Build Coastguard Worker         T mCurrent;
791*8975f5c5SAndroid Build Coastguard Worker     };
792*8975f5c5SAndroid Build Coastguard Worker 
begin()793*8975f5c5SAndroid Build Coastguard Worker     Iterator begin() const { return Iterator(mLow); }
794*8975f5c5SAndroid Build Coastguard Worker 
end()795*8975f5c5SAndroid Build Coastguard Worker     Iterator end() const { return Iterator(mHigh); }
796*8975f5c5SAndroid Build Coastguard Worker 
low()797*8975f5c5SAndroid Build Coastguard Worker     T low() const { return mLow; }
high()798*8975f5c5SAndroid Build Coastguard Worker     T high() const { return mHigh; }
799*8975f5c5SAndroid Build Coastguard Worker 
invalidate()800*8975f5c5SAndroid Build Coastguard Worker     void invalidate()
801*8975f5c5SAndroid Build Coastguard Worker     {
802*8975f5c5SAndroid Build Coastguard Worker         mLow  = std::numeric_limits<T>::max();
803*8975f5c5SAndroid Build Coastguard Worker         mHigh = std::numeric_limits<T>::min();
804*8975f5c5SAndroid Build Coastguard Worker     }
805*8975f5c5SAndroid Build Coastguard Worker 
806*8975f5c5SAndroid Build Coastguard Worker   private:
807*8975f5c5SAndroid Build Coastguard Worker     T mLow;
808*8975f5c5SAndroid Build Coastguard Worker     T mHigh;
809*8975f5c5SAndroid Build Coastguard Worker };
810*8975f5c5SAndroid Build Coastguard Worker 
811*8975f5c5SAndroid Build Coastguard Worker typedef Range<int> RangeI;
812*8975f5c5SAndroid Build Coastguard Worker typedef Range<unsigned int> RangeUI;
813*8975f5c5SAndroid Build Coastguard Worker static_assert(std::is_trivially_copyable<RangeUI>(),
814*8975f5c5SAndroid Build Coastguard Worker               "RangeUI should be trivial copyable so that we can memcpy");
815*8975f5c5SAndroid Build Coastguard Worker 
816*8975f5c5SAndroid Build Coastguard Worker struct IndexRange
817*8975f5c5SAndroid Build Coastguard Worker {
818*8975f5c5SAndroid Build Coastguard Worker     struct Undefined
819*8975f5c5SAndroid Build Coastguard Worker     {};
IndexRangeIndexRange820*8975f5c5SAndroid Build Coastguard Worker     IndexRange(Undefined) {}
IndexRangeIndexRange821*8975f5c5SAndroid Build Coastguard Worker     IndexRange() : IndexRange(0, 0, 0) {}
IndexRangeIndexRange822*8975f5c5SAndroid Build Coastguard Worker     IndexRange(size_t start_, size_t end_, size_t vertexIndexCount_)
823*8975f5c5SAndroid Build Coastguard Worker         : start(start_), end(end_), vertexIndexCount(vertexIndexCount_)
824*8975f5c5SAndroid Build Coastguard Worker     {
825*8975f5c5SAndroid Build Coastguard Worker         ASSERT(start <= end);
826*8975f5c5SAndroid Build Coastguard Worker     }
827*8975f5c5SAndroid Build Coastguard Worker 
828*8975f5c5SAndroid Build Coastguard Worker     // Number of vertices in the range.
vertexCountIndexRange829*8975f5c5SAndroid Build Coastguard Worker     size_t vertexCount() const { return (end - start) + 1; }
830*8975f5c5SAndroid Build Coastguard Worker 
831*8975f5c5SAndroid Build Coastguard Worker     // Inclusive range of indices that are not primitive restart
832*8975f5c5SAndroid Build Coastguard Worker     size_t start;
833*8975f5c5SAndroid Build Coastguard Worker     size_t end;
834*8975f5c5SAndroid Build Coastguard Worker 
835*8975f5c5SAndroid Build Coastguard Worker     // Number of non-primitive restart indices
836*8975f5c5SAndroid Build Coastguard Worker     size_t vertexIndexCount;
837*8975f5c5SAndroid Build Coastguard Worker };
838*8975f5c5SAndroid Build Coastguard Worker 
839*8975f5c5SAndroid Build Coastguard Worker // Combine a floating-point value representing a mantissa (x) and an integer exponent (exp) into a
840*8975f5c5SAndroid Build Coastguard Worker // floating-point value. As in GLSL ldexp() built-in.
Ldexp(float x,int exp)841*8975f5c5SAndroid Build Coastguard Worker inline float Ldexp(float x, int exp)
842*8975f5c5SAndroid Build Coastguard Worker {
843*8975f5c5SAndroid Build Coastguard Worker     if (exp > 128)
844*8975f5c5SAndroid Build Coastguard Worker     {
845*8975f5c5SAndroid Build Coastguard Worker         return std::numeric_limits<float>::infinity();
846*8975f5c5SAndroid Build Coastguard Worker     }
847*8975f5c5SAndroid Build Coastguard Worker     if (exp < -126)
848*8975f5c5SAndroid Build Coastguard Worker     {
849*8975f5c5SAndroid Build Coastguard Worker         return 0.0f;
850*8975f5c5SAndroid Build Coastguard Worker     }
851*8975f5c5SAndroid Build Coastguard Worker     double result = static_cast<double>(x) * std::pow(2.0, static_cast<double>(exp));
852*8975f5c5SAndroid Build Coastguard Worker     return static_cast<float>(result);
853*8975f5c5SAndroid Build Coastguard Worker }
854*8975f5c5SAndroid Build Coastguard Worker 
855*8975f5c5SAndroid Build Coastguard Worker // First, both normalized floating-point values are converted into 16-bit integer values.
856*8975f5c5SAndroid Build Coastguard Worker // Then, the results are packed into the returned 32-bit unsigned integer.
857*8975f5c5SAndroid Build Coastguard Worker // The first float value will be written to the least significant bits of the output;
858*8975f5c5SAndroid Build Coastguard Worker // the last float value will be written to the most significant bits.
859*8975f5c5SAndroid Build Coastguard Worker // The conversion of each value to fixed point is done as follows :
860*8975f5c5SAndroid Build Coastguard Worker // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
packSnorm2x16(float f1,float f2)861*8975f5c5SAndroid Build Coastguard Worker inline uint32_t packSnorm2x16(float f1, float f2)
862*8975f5c5SAndroid Build Coastguard Worker {
863*8975f5c5SAndroid Build Coastguard Worker     int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
864*8975f5c5SAndroid Build Coastguard Worker     int16_t mostSignificantBits  = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
865*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint32_t>(mostSignificantBits) << 16 |
866*8975f5c5SAndroid Build Coastguard Worker            (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
867*8975f5c5SAndroid Build Coastguard Worker }
868*8975f5c5SAndroid Build Coastguard Worker 
869*8975f5c5SAndroid Build Coastguard Worker // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
870*8975f5c5SAndroid Build Coastguard Worker // each component is converted to a normalized floating-point value to generate the returned two
871*8975f5c5SAndroid Build Coastguard Worker // float values. The first float value will be extracted from the least significant bits of the
872*8975f5c5SAndroid Build Coastguard Worker // input; the last float value will be extracted from the most-significant bits. The conversion for
873*8975f5c5SAndroid Build Coastguard Worker // unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
874*8975f5c5SAndroid Build Coastguard Worker // 32767.0, -1, +1)
unpackSnorm2x16(uint32_t u,float * f1,float * f2)875*8975f5c5SAndroid Build Coastguard Worker inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
876*8975f5c5SAndroid Build Coastguard Worker {
877*8975f5c5SAndroid Build Coastguard Worker     int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
878*8975f5c5SAndroid Build Coastguard Worker     int16_t mostSignificantBits  = static_cast<int16_t>(u >> 16);
879*8975f5c5SAndroid Build Coastguard Worker     *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
880*8975f5c5SAndroid Build Coastguard Worker     *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
881*8975f5c5SAndroid Build Coastguard Worker }
882*8975f5c5SAndroid Build Coastguard Worker 
883*8975f5c5SAndroid Build Coastguard Worker // First, both normalized floating-point values are converted into 16-bit integer values.
884*8975f5c5SAndroid Build Coastguard Worker // Then, the results are packed into the returned 32-bit unsigned integer.
885*8975f5c5SAndroid Build Coastguard Worker // The first float value will be written to the least significant bits of the output;
886*8975f5c5SAndroid Build Coastguard Worker // the last float value will be written to the most significant bits.
887*8975f5c5SAndroid Build Coastguard Worker // The conversion of each value to fixed point is done as follows:
888*8975f5c5SAndroid Build Coastguard Worker // packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
packUnorm2x16(float f1,float f2)889*8975f5c5SAndroid Build Coastguard Worker inline uint32_t packUnorm2x16(float f1, float f2)
890*8975f5c5SAndroid Build Coastguard Worker {
891*8975f5c5SAndroid Build Coastguard Worker     uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
892*8975f5c5SAndroid Build Coastguard Worker     uint16_t mostSignificantBits  = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
893*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint32_t>(mostSignificantBits) << 16 |
894*8975f5c5SAndroid Build Coastguard Worker            static_cast<uint32_t>(leastSignificantBits);
895*8975f5c5SAndroid Build Coastguard Worker }
896*8975f5c5SAndroid Build Coastguard Worker 
897*8975f5c5SAndroid Build Coastguard Worker // First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
898*8975f5c5SAndroid Build Coastguard Worker // each component is converted to a normalized floating-point value to generate the returned two
899*8975f5c5SAndroid Build Coastguard Worker // float values. The first float value will be extracted from the least significant bits of the
900*8975f5c5SAndroid Build Coastguard Worker // input; the last float value will be extracted from the most-significant bits. The conversion for
901*8975f5c5SAndroid Build Coastguard Worker // unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
unpackUnorm2x16(uint32_t u,float * f1,float * f2)902*8975f5c5SAndroid Build Coastguard Worker inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
903*8975f5c5SAndroid Build Coastguard Worker {
904*8975f5c5SAndroid Build Coastguard Worker     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
905*8975f5c5SAndroid Build Coastguard Worker     uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
906*8975f5c5SAndroid Build Coastguard Worker     *f1                           = static_cast<float>(leastSignificantBits) / 65535.0f;
907*8975f5c5SAndroid Build Coastguard Worker     *f2                           = static_cast<float>(mostSignificantBits) / 65535.0f;
908*8975f5c5SAndroid Build Coastguard Worker }
909*8975f5c5SAndroid Build Coastguard Worker 
910*8975f5c5SAndroid Build Coastguard Worker // Helper functions intended to be used only here.
911*8975f5c5SAndroid Build Coastguard Worker namespace priv
912*8975f5c5SAndroid Build Coastguard Worker {
913*8975f5c5SAndroid Build Coastguard Worker 
ToPackedUnorm8(float f)914*8975f5c5SAndroid Build Coastguard Worker inline uint8_t ToPackedUnorm8(float f)
915*8975f5c5SAndroid Build Coastguard Worker {
916*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint8_t>(roundf(clamp(f, 0.0f, 1.0f) * 255.0f));
917*8975f5c5SAndroid Build Coastguard Worker }
918*8975f5c5SAndroid Build Coastguard Worker 
ToPackedSnorm8(float f)919*8975f5c5SAndroid Build Coastguard Worker inline int8_t ToPackedSnorm8(float f)
920*8975f5c5SAndroid Build Coastguard Worker {
921*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int8_t>(roundf(clamp(f, -1.0f, 1.0f) * 127.0f));
922*8975f5c5SAndroid Build Coastguard Worker }
923*8975f5c5SAndroid Build Coastguard Worker 
924*8975f5c5SAndroid Build Coastguard Worker }  // namespace priv
925*8975f5c5SAndroid Build Coastguard Worker 
926*8975f5c5SAndroid Build Coastguard Worker // Packs 4 normalized unsigned floating-point values to a single 32-bit unsigned integer. Works
927*8975f5c5SAndroid Build Coastguard Worker // similarly to packUnorm2x16. The floats are clamped to the range 0.0 to 1.0, and written to the
928*8975f5c5SAndroid Build Coastguard Worker // unsigned integer starting from the least significant bits.
PackUnorm4x8(float f1,float f2,float f3,float f4)929*8975f5c5SAndroid Build Coastguard Worker inline uint32_t PackUnorm4x8(float f1, float f2, float f3, float f4)
930*8975f5c5SAndroid Build Coastguard Worker {
931*8975f5c5SAndroid Build Coastguard Worker     uint8_t bits[4];
932*8975f5c5SAndroid Build Coastguard Worker     bits[0]         = priv::ToPackedUnorm8(f1);
933*8975f5c5SAndroid Build Coastguard Worker     bits[1]         = priv::ToPackedUnorm8(f2);
934*8975f5c5SAndroid Build Coastguard Worker     bits[2]         = priv::ToPackedUnorm8(f3);
935*8975f5c5SAndroid Build Coastguard Worker     bits[3]         = priv::ToPackedUnorm8(f4);
936*8975f5c5SAndroid Build Coastguard Worker     uint32_t result = 0u;
937*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i)
938*8975f5c5SAndroid Build Coastguard Worker     {
939*8975f5c5SAndroid Build Coastguard Worker         int shift = i * 8;
940*8975f5c5SAndroid Build Coastguard Worker         result |= (static_cast<uint32_t>(bits[i]) << shift);
941*8975f5c5SAndroid Build Coastguard Worker     }
942*8975f5c5SAndroid Build Coastguard Worker     return result;
943*8975f5c5SAndroid Build Coastguard Worker }
944*8975f5c5SAndroid Build Coastguard Worker 
945*8975f5c5SAndroid Build Coastguard Worker // Unpacks 4 normalized unsigned floating-point values from a single 32-bit unsigned integer into f.
946*8975f5c5SAndroid Build Coastguard Worker // Works similarly to unpackUnorm2x16. The floats are unpacked starting from the least significant
947*8975f5c5SAndroid Build Coastguard Worker // bits.
UnpackUnorm4x8(uint32_t u,float * f)948*8975f5c5SAndroid Build Coastguard Worker inline void UnpackUnorm4x8(uint32_t u, float *f)
949*8975f5c5SAndroid Build Coastguard Worker {
950*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i)
951*8975f5c5SAndroid Build Coastguard Worker     {
952*8975f5c5SAndroid Build Coastguard Worker         int shift    = i * 8;
953*8975f5c5SAndroid Build Coastguard Worker         uint8_t bits = static_cast<uint8_t>((u >> shift) & 0xFF);
954*8975f5c5SAndroid Build Coastguard Worker         f[i]         = static_cast<float>(bits) / 255.0f;
955*8975f5c5SAndroid Build Coastguard Worker     }
956*8975f5c5SAndroid Build Coastguard Worker }
957*8975f5c5SAndroid Build Coastguard Worker 
958*8975f5c5SAndroid Build Coastguard Worker // Packs 4 normalized signed floating-point values to a single 32-bit unsigned integer. The floats
959*8975f5c5SAndroid Build Coastguard Worker // are clamped to the range -1.0 to 1.0, and written to the unsigned integer starting from the least
960*8975f5c5SAndroid Build Coastguard Worker // significant bits.
PackSnorm4x8(float f1,float f2,float f3,float f4)961*8975f5c5SAndroid Build Coastguard Worker inline uint32_t PackSnorm4x8(float f1, float f2, float f3, float f4)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker     int8_t bits[4];
964*8975f5c5SAndroid Build Coastguard Worker     bits[0]         = priv::ToPackedSnorm8(f1);
965*8975f5c5SAndroid Build Coastguard Worker     bits[1]         = priv::ToPackedSnorm8(f2);
966*8975f5c5SAndroid Build Coastguard Worker     bits[2]         = priv::ToPackedSnorm8(f3);
967*8975f5c5SAndroid Build Coastguard Worker     bits[3]         = priv::ToPackedSnorm8(f4);
968*8975f5c5SAndroid Build Coastguard Worker     uint32_t result = 0u;
969*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i)
970*8975f5c5SAndroid Build Coastguard Worker     {
971*8975f5c5SAndroid Build Coastguard Worker         int shift = i * 8;
972*8975f5c5SAndroid Build Coastguard Worker         result |= ((static_cast<uint32_t>(bits[i]) & 0xFF) << shift);
973*8975f5c5SAndroid Build Coastguard Worker     }
974*8975f5c5SAndroid Build Coastguard Worker     return result;
975*8975f5c5SAndroid Build Coastguard Worker }
976*8975f5c5SAndroid Build Coastguard Worker 
977*8975f5c5SAndroid Build Coastguard Worker // Unpacks 4 normalized signed floating-point values from a single 32-bit unsigned integer into f.
978*8975f5c5SAndroid Build Coastguard Worker // Works similarly to unpackSnorm2x16. The floats are unpacked starting from the least significant
979*8975f5c5SAndroid Build Coastguard Worker // bits, and clamped to the range -1.0 to 1.0.
UnpackSnorm4x8(uint32_t u,float * f)980*8975f5c5SAndroid Build Coastguard Worker inline void UnpackSnorm4x8(uint32_t u, float *f)
981*8975f5c5SAndroid Build Coastguard Worker {
982*8975f5c5SAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i)
983*8975f5c5SAndroid Build Coastguard Worker     {
984*8975f5c5SAndroid Build Coastguard Worker         int shift   = i * 8;
985*8975f5c5SAndroid Build Coastguard Worker         int8_t bits = static_cast<int8_t>((u >> shift) & 0xFF);
986*8975f5c5SAndroid Build Coastguard Worker         f[i]        = clamp(static_cast<float>(bits) / 127.0f, -1.0f, 1.0f);
987*8975f5c5SAndroid Build Coastguard Worker     }
988*8975f5c5SAndroid Build Coastguard Worker }
989*8975f5c5SAndroid Build Coastguard Worker 
990*8975f5c5SAndroid Build Coastguard Worker // Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
991*8975f5c5SAndroid Build Coastguard Worker // floating-point representation found in the OpenGL ES Specification, and then packing these
992*8975f5c5SAndroid Build Coastguard Worker // two 16-bit integers into a 32-bit unsigned integer.
993*8975f5c5SAndroid Build Coastguard Worker // f1: The 16 least-significant bits of the result;
994*8975f5c5SAndroid Build Coastguard Worker // f2: The 16 most-significant bits.
packHalf2x16(float f1,float f2)995*8975f5c5SAndroid Build Coastguard Worker inline uint32_t packHalf2x16(float f1, float f2)
996*8975f5c5SAndroid Build Coastguard Worker {
997*8975f5c5SAndroid Build Coastguard Worker     uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
998*8975f5c5SAndroid Build Coastguard Worker     uint16_t mostSignificantBits  = static_cast<uint16_t>(float32ToFloat16(f2));
999*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint32_t>(mostSignificantBits) << 16 |
1000*8975f5c5SAndroid Build Coastguard Worker            static_cast<uint32_t>(leastSignificantBits);
1001*8975f5c5SAndroid Build Coastguard Worker }
1002*8975f5c5SAndroid Build Coastguard Worker 
1003*8975f5c5SAndroid Build Coastguard Worker // Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
1004*8975f5c5SAndroid Build Coastguard Worker // 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
1005*8975f5c5SAndroid Build Coastguard Worker // ES Specification, and converting them to 32-bit floating-point values. The first float value is
1006*8975f5c5SAndroid Build Coastguard Worker // obtained from the 16 least-significant bits of u; the second component is obtained from the 16
1007*8975f5c5SAndroid Build Coastguard Worker // most-significant bits of u.
unpackHalf2x16(uint32_t u,float * f1,float * f2)1008*8975f5c5SAndroid Build Coastguard Worker inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
1009*8975f5c5SAndroid Build Coastguard Worker {
1010*8975f5c5SAndroid Build Coastguard Worker     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
1011*8975f5c5SAndroid Build Coastguard Worker     uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
1012*8975f5c5SAndroid Build Coastguard Worker 
1013*8975f5c5SAndroid Build Coastguard Worker     *f1 = float16ToFloat32(leastSignificantBits);
1014*8975f5c5SAndroid Build Coastguard Worker     *f2 = float16ToFloat32(mostSignificantBits);
1015*8975f5c5SAndroid Build Coastguard Worker }
1016*8975f5c5SAndroid Build Coastguard Worker 
sRGBToLinear(uint8_t srgbValue)1017*8975f5c5SAndroid Build Coastguard Worker inline float sRGBToLinear(uint8_t srgbValue)
1018*8975f5c5SAndroid Build Coastguard Worker {
1019*8975f5c5SAndroid Build Coastguard Worker     float value = srgbValue / 255.0f;
1020*8975f5c5SAndroid Build Coastguard Worker     if (value <= 0.04045f)
1021*8975f5c5SAndroid Build Coastguard Worker     {
1022*8975f5c5SAndroid Build Coastguard Worker         value = value / 12.92f;
1023*8975f5c5SAndroid Build Coastguard Worker     }
1024*8975f5c5SAndroid Build Coastguard Worker     else
1025*8975f5c5SAndroid Build Coastguard Worker     {
1026*8975f5c5SAndroid Build Coastguard Worker         value = std::pow((value + 0.055f) / 1.055f, 2.4f);
1027*8975f5c5SAndroid Build Coastguard Worker     }
1028*8975f5c5SAndroid Build Coastguard Worker     ASSERT(value >= 0.0f && value <= 1.0f);
1029*8975f5c5SAndroid Build Coastguard Worker     return value;
1030*8975f5c5SAndroid Build Coastguard Worker }
1031*8975f5c5SAndroid Build Coastguard Worker 
linearToSRGB(float value)1032*8975f5c5SAndroid Build Coastguard Worker inline uint8_t linearToSRGB(float value)
1033*8975f5c5SAndroid Build Coastguard Worker {
1034*8975f5c5SAndroid Build Coastguard Worker     ASSERT(value >= 0.0f && value <= 1.0f);
1035*8975f5c5SAndroid Build Coastguard Worker     if (value < 0.0031308f)
1036*8975f5c5SAndroid Build Coastguard Worker     {
1037*8975f5c5SAndroid Build Coastguard Worker         value = value * 12.92f;
1038*8975f5c5SAndroid Build Coastguard Worker     }
1039*8975f5c5SAndroid Build Coastguard Worker     else
1040*8975f5c5SAndroid Build Coastguard Worker     {
1041*8975f5c5SAndroid Build Coastguard Worker         value = std::pow(value, 0.41666f) * 1.055f - 0.055f;
1042*8975f5c5SAndroid Build Coastguard Worker     }
1043*8975f5c5SAndroid Build Coastguard Worker     return static_cast<uint8_t>(value * 255.0f + 0.5f);
1044*8975f5c5SAndroid Build Coastguard Worker }
1045*8975f5c5SAndroid Build Coastguard Worker 
1046*8975f5c5SAndroid Build Coastguard Worker // Reverse the order of the bits.
BitfieldReverse(uint32_t value)1047*8975f5c5SAndroid Build Coastguard Worker inline uint32_t BitfieldReverse(uint32_t value)
1048*8975f5c5SAndroid Build Coastguard Worker {
1049*8975f5c5SAndroid Build Coastguard Worker     // TODO([email protected]): Optimize this if needed. There don't seem to be compiler intrinsics
1050*8975f5c5SAndroid Build Coastguard Worker     // for this, and right now it's not used in performance-critical paths.
1051*8975f5c5SAndroid Build Coastguard Worker     uint32_t result = 0u;
1052*8975f5c5SAndroid Build Coastguard Worker     for (size_t j = 0u; j < 32u; ++j)
1053*8975f5c5SAndroid Build Coastguard Worker     {
1054*8975f5c5SAndroid Build Coastguard Worker         result |= (((value >> j) & 1u) << (31u - j));
1055*8975f5c5SAndroid Build Coastguard Worker     }
1056*8975f5c5SAndroid Build Coastguard Worker     return result;
1057*8975f5c5SAndroid Build Coastguard Worker }
1058*8975f5c5SAndroid Build Coastguard Worker 
1059*8975f5c5SAndroid Build Coastguard Worker // Count the 1 bits.
1060*8975f5c5SAndroid Build Coastguard Worker #if defined(_MSC_VER) && !defined(__clang__)
1061*8975f5c5SAndroid Build Coastguard Worker #    if defined(_M_IX86) || defined(_M_X64)
1062*8975f5c5SAndroid Build Coastguard Worker namespace priv
1063*8975f5c5SAndroid Build Coastguard Worker {
1064*8975f5c5SAndroid Build Coastguard Worker // Check POPCNT instruction support and cache the result.
1065*8975f5c5SAndroid Build Coastguard Worker // https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64#remarks
1066*8975f5c5SAndroid Build Coastguard Worker static const bool kHasPopcnt = [] {
1067*8975f5c5SAndroid Build Coastguard Worker     int info[4];
1068*8975f5c5SAndroid Build Coastguard Worker     __cpuid(&info[0], 1);
1069*8975f5c5SAndroid Build Coastguard Worker     return static_cast<bool>(info[2] & 0x800000);
1070*8975f5c5SAndroid Build Coastguard Worker }();
1071*8975f5c5SAndroid Build Coastguard Worker }  // namespace priv
1072*8975f5c5SAndroid Build Coastguard Worker 
1073*8975f5c5SAndroid Build Coastguard Worker // Polyfills for x86/x64 CPUs without POPCNT.
1074*8975f5c5SAndroid Build Coastguard Worker // https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
BitCountPolyfill(uint32_t bits)1075*8975f5c5SAndroid Build Coastguard Worker inline int BitCountPolyfill(uint32_t bits)
1076*8975f5c5SAndroid Build Coastguard Worker {
1077*8975f5c5SAndroid Build Coastguard Worker     bits = bits - ((bits >> 1) & 0x55555555);
1078*8975f5c5SAndroid Build Coastguard Worker     bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
1079*8975f5c5SAndroid Build Coastguard Worker     bits = ((bits + (bits >> 4) & 0x0F0F0F0F) * 0x01010101) >> 24;
1080*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(bits);
1081*8975f5c5SAndroid Build Coastguard Worker }
1082*8975f5c5SAndroid Build Coastguard Worker 
BitCountPolyfill(uint64_t bits)1083*8975f5c5SAndroid Build Coastguard Worker inline int BitCountPolyfill(uint64_t bits)
1084*8975f5c5SAndroid Build Coastguard Worker {
1085*8975f5c5SAndroid Build Coastguard Worker     bits = bits - ((bits >> 1) & 0x5555555555555555ull);
1086*8975f5c5SAndroid Build Coastguard Worker     bits = (bits & 0x3333333333333333ull) + ((bits >> 2) & 0x3333333333333333ull);
1087*8975f5c5SAndroid Build Coastguard Worker     bits = ((bits + (bits >> 4) & 0x0F0F0F0F0F0F0F0Full) * 0x0101010101010101ull) >> 56;
1088*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(bits);
1089*8975f5c5SAndroid Build Coastguard Worker }
1090*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint32_t bits)1091*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint32_t bits)
1092*8975f5c5SAndroid Build Coastguard Worker {
1093*8975f5c5SAndroid Build Coastguard Worker     if (priv::kHasPopcnt)
1094*8975f5c5SAndroid Build Coastguard Worker     {
1095*8975f5c5SAndroid Build Coastguard Worker         return static_cast<int>(__popcnt(bits));
1096*8975f5c5SAndroid Build Coastguard Worker     }
1097*8975f5c5SAndroid Build Coastguard Worker     return BitCountPolyfill(bits);
1098*8975f5c5SAndroid Build Coastguard Worker }
1099*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint64_t bits)1100*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint64_t bits)
1101*8975f5c5SAndroid Build Coastguard Worker {
1102*8975f5c5SAndroid Build Coastguard Worker     if (priv::kHasPopcnt)
1103*8975f5c5SAndroid Build Coastguard Worker     {
1104*8975f5c5SAndroid Build Coastguard Worker #        if defined(_M_X64)
1105*8975f5c5SAndroid Build Coastguard Worker         return static_cast<int>(__popcnt64(bits));
1106*8975f5c5SAndroid Build Coastguard Worker #        else   // x86
1107*8975f5c5SAndroid Build Coastguard Worker         return static_cast<int>(__popcnt(static_cast<uint32_t>(bits >> 32)) +
1108*8975f5c5SAndroid Build Coastguard Worker                                 __popcnt(static_cast<uint32_t>(bits)));
1109*8975f5c5SAndroid Build Coastguard Worker #        endif  // defined(_M_X64)
1110*8975f5c5SAndroid Build Coastguard Worker     }
1111*8975f5c5SAndroid Build Coastguard Worker     return BitCountPolyfill(bits);
1112*8975f5c5SAndroid Build Coastguard Worker }
1113*8975f5c5SAndroid Build Coastguard Worker 
1114*8975f5c5SAndroid Build Coastguard Worker #    elif defined(_M_ARM) || defined(_M_ARM64)
1115*8975f5c5SAndroid Build Coastguard Worker 
1116*8975f5c5SAndroid Build Coastguard Worker // MSVC's _CountOneBits* intrinsics are not defined for ARM64, moreover they do not use dedicated
1117*8975f5c5SAndroid Build Coastguard Worker // NEON instructions.
1118*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint32_t bits)1119*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint32_t bits)
1120*8975f5c5SAndroid Build Coastguard Worker {
1121*8975f5c5SAndroid Build Coastguard Worker     // cast bits to 8x8 datatype and use VCNT on it
1122*8975f5c5SAndroid Build Coastguard Worker     const uint8x8_t vsum = vcnt_u8(vcreate_u8(static_cast<uint64_t>(bits)));
1123*8975f5c5SAndroid Build Coastguard Worker 
1124*8975f5c5SAndroid Build Coastguard Worker     // pairwise sums: 8x8 -> 16x4 -> 32x2
1125*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(vget_lane_u32(vpaddl_u16(vpaddl_u8(vsum)), 0));
1126*8975f5c5SAndroid Build Coastguard Worker }
1127*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint64_t bits)1128*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint64_t bits)
1129*8975f5c5SAndroid Build Coastguard Worker {
1130*8975f5c5SAndroid Build Coastguard Worker     // cast bits to 8x8 datatype and use VCNT on it
1131*8975f5c5SAndroid Build Coastguard Worker     const uint8x8_t vsum = vcnt_u8(vcreate_u8(bits));
1132*8975f5c5SAndroid Build Coastguard Worker 
1133*8975f5c5SAndroid Build Coastguard Worker     // pairwise sums: 8x8 -> 16x4 -> 32x2 -> 64x1
1134*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int>(vget_lane_u64(vpaddl_u32(vpaddl_u16(vpaddl_u8(vsum))), 0));
1135*8975f5c5SAndroid Build Coastguard Worker }
1136*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(_M_IX86) || defined(_M_X64)
1137*8975f5c5SAndroid Build Coastguard Worker #endif      // defined(_MSC_VER) && !defined(__clang__)
1138*8975f5c5SAndroid Build Coastguard Worker 
1139*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_POSIX) || defined(__clang__) || defined(__GNUC__)
BitCount(uint32_t bits)1140*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint32_t bits)
1141*8975f5c5SAndroid Build Coastguard Worker {
1142*8975f5c5SAndroid Build Coastguard Worker     return __builtin_popcount(bits);
1143*8975f5c5SAndroid Build Coastguard Worker }
1144*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint64_t bits)1145*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint64_t bits)
1146*8975f5c5SAndroid Build Coastguard Worker {
1147*8975f5c5SAndroid Build Coastguard Worker     return __builtin_popcountll(bits);
1148*8975f5c5SAndroid Build Coastguard Worker }
1149*8975f5c5SAndroid Build Coastguard Worker #endif  // defined(ANGLE_PLATFORM_POSIX) || defined(__clang__) || defined(__GNUC__)
1150*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint8_t bits)1151*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint8_t bits)
1152*8975f5c5SAndroid Build Coastguard Worker {
1153*8975f5c5SAndroid Build Coastguard Worker     return BitCount(static_cast<uint32_t>(bits));
1154*8975f5c5SAndroid Build Coastguard Worker }
1155*8975f5c5SAndroid Build Coastguard Worker 
BitCount(uint16_t bits)1156*8975f5c5SAndroid Build Coastguard Worker inline int BitCount(uint16_t bits)
1157*8975f5c5SAndroid Build Coastguard Worker {
1158*8975f5c5SAndroid Build Coastguard Worker     return BitCount(static_cast<uint32_t>(bits));
1159*8975f5c5SAndroid Build Coastguard Worker }
1160*8975f5c5SAndroid Build Coastguard Worker 
1161*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_WINDOWS)
1162*8975f5c5SAndroid Build Coastguard Worker // Return the index of the least significant bit set. Indexing is such that bit 0 is the least
1163*8975f5c5SAndroid Build Coastguard Worker // significant bit. Implemented for different bit widths on different platforms.
ScanForward(uint32_t bits)1164*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint32_t bits)
1165*8975f5c5SAndroid Build Coastguard Worker {
1166*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1167*8975f5c5SAndroid Build Coastguard Worker     unsigned long firstBitIndex = 0ul;
1168*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret           = _BitScanForward(&firstBitIndex, bits);
1169*8975f5c5SAndroid Build Coastguard Worker     ASSERT(ret != 0u);
1170*8975f5c5SAndroid Build Coastguard Worker     return firstBitIndex;
1171*8975f5c5SAndroid Build Coastguard Worker }
1172*8975f5c5SAndroid Build Coastguard Worker 
ScanForward(uint64_t bits)1173*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint64_t bits)
1174*8975f5c5SAndroid Build Coastguard Worker {
1175*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1176*8975f5c5SAndroid Build Coastguard Worker     unsigned long firstBitIndex = 0ul;
1177*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_IS_64_BIT_CPU)
1178*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret = _BitScanForward64(&firstBitIndex, bits);
1179*8975f5c5SAndroid Build Coastguard Worker #    else
1180*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret;
1181*8975f5c5SAndroid Build Coastguard Worker     if (static_cast<uint32_t>(bits) == 0)
1182*8975f5c5SAndroid Build Coastguard Worker     {
1183*8975f5c5SAndroid Build Coastguard Worker         ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits >> 32));
1184*8975f5c5SAndroid Build Coastguard Worker         firstBitIndex += 32ul;
1185*8975f5c5SAndroid Build Coastguard Worker     }
1186*8975f5c5SAndroid Build Coastguard Worker     else
1187*8975f5c5SAndroid Build Coastguard Worker     {
1188*8975f5c5SAndroid Build Coastguard Worker         ret = _BitScanForward(&firstBitIndex, static_cast<uint32_t>(bits));
1189*8975f5c5SAndroid Build Coastguard Worker     }
1190*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_IS_64_BIT_CPU)
1191*8975f5c5SAndroid Build Coastguard Worker     ASSERT(ret != 0u);
1192*8975f5c5SAndroid Build Coastguard Worker     return firstBitIndex;
1193*8975f5c5SAndroid Build Coastguard Worker }
1194*8975f5c5SAndroid Build Coastguard Worker 
1195*8975f5c5SAndroid Build Coastguard Worker // Return the index of the most significant bit set. Indexing is such that bit 0 is the least
1196*8975f5c5SAndroid Build Coastguard Worker // significant bit.
ScanReverse(uint32_t bits)1197*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint32_t bits)
1198*8975f5c5SAndroid Build Coastguard Worker {
1199*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1200*8975f5c5SAndroid Build Coastguard Worker     unsigned long lastBitIndex = 0ul;
1201*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret          = _BitScanReverse(&lastBitIndex, bits);
1202*8975f5c5SAndroid Build Coastguard Worker     ASSERT(ret != 0u);
1203*8975f5c5SAndroid Build Coastguard Worker     return lastBitIndex;
1204*8975f5c5SAndroid Build Coastguard Worker }
1205*8975f5c5SAndroid Build Coastguard Worker 
ScanReverse(uint64_t bits)1206*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint64_t bits)
1207*8975f5c5SAndroid Build Coastguard Worker {
1208*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1209*8975f5c5SAndroid Build Coastguard Worker     unsigned long lastBitIndex = 0ul;
1210*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_IS_64_BIT_CPU)
1211*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret = _BitScanReverse64(&lastBitIndex, bits);
1212*8975f5c5SAndroid Build Coastguard Worker #    else
1213*8975f5c5SAndroid Build Coastguard Worker     unsigned char ret;
1214*8975f5c5SAndroid Build Coastguard Worker     if (static_cast<uint32_t>(bits >> 32) == 0)
1215*8975f5c5SAndroid Build Coastguard Worker     {
1216*8975f5c5SAndroid Build Coastguard Worker         ret = _BitScanReverse(&lastBitIndex, static_cast<uint32_t>(bits));
1217*8975f5c5SAndroid Build Coastguard Worker     }
1218*8975f5c5SAndroid Build Coastguard Worker     else
1219*8975f5c5SAndroid Build Coastguard Worker     {
1220*8975f5c5SAndroid Build Coastguard Worker         ret = _BitScanReverse(&lastBitIndex, static_cast<uint32_t>(bits >> 32));
1221*8975f5c5SAndroid Build Coastguard Worker         lastBitIndex += 32ul;
1222*8975f5c5SAndroid Build Coastguard Worker     }
1223*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_IS_64_BIT_CPU)
1224*8975f5c5SAndroid Build Coastguard Worker     ASSERT(ret != 0u);
1225*8975f5c5SAndroid Build Coastguard Worker     return lastBitIndex;
1226*8975f5c5SAndroid Build Coastguard Worker }
1227*8975f5c5SAndroid Build Coastguard Worker #endif  // defined(ANGLE_PLATFORM_WINDOWS)
1228*8975f5c5SAndroid Build Coastguard Worker 
1229*8975f5c5SAndroid Build Coastguard Worker #if defined(ANGLE_PLATFORM_POSIX)
ScanForward(uint32_t bits)1230*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint32_t bits)
1231*8975f5c5SAndroid Build Coastguard Worker {
1232*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1233*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned long>(__builtin_ctz(bits));
1234*8975f5c5SAndroid Build Coastguard Worker }
1235*8975f5c5SAndroid Build Coastguard Worker 
ScanForward(uint64_t bits)1236*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint64_t bits)
1237*8975f5c5SAndroid Build Coastguard Worker {
1238*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1239*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_IS_64_BIT_CPU)
1240*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned long>(__builtin_ctzll(bits));
1241*8975f5c5SAndroid Build Coastguard Worker #    else
1242*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned long>(static_cast<uint32_t>(bits) == 0
1243*8975f5c5SAndroid Build Coastguard Worker                                           ? __builtin_ctz(static_cast<uint32_t>(bits >> 32)) + 32
1244*8975f5c5SAndroid Build Coastguard Worker                                           : __builtin_ctz(static_cast<uint32_t>(bits)));
1245*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_IS_64_BIT_CPU)
1246*8975f5c5SAndroid Build Coastguard Worker }
1247*8975f5c5SAndroid Build Coastguard Worker 
ScanReverse(uint32_t bits)1248*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint32_t bits)
1249*8975f5c5SAndroid Build Coastguard Worker {
1250*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1251*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned long>(sizeof(uint32_t) * CHAR_BIT - 1 - __builtin_clz(bits));
1252*8975f5c5SAndroid Build Coastguard Worker }
1253*8975f5c5SAndroid Build Coastguard Worker 
ScanReverse(uint64_t bits)1254*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint64_t bits)
1255*8975f5c5SAndroid Build Coastguard Worker {
1256*8975f5c5SAndroid Build Coastguard Worker     ASSERT(bits != 0u);
1257*8975f5c5SAndroid Build Coastguard Worker #    if defined(ANGLE_IS_64_BIT_CPU)
1258*8975f5c5SAndroid Build Coastguard Worker     return static_cast<unsigned long>(sizeof(uint64_t) * CHAR_BIT - 1 - __builtin_clzll(bits));
1259*8975f5c5SAndroid Build Coastguard Worker #    else
1260*8975f5c5SAndroid Build Coastguard Worker     if (static_cast<uint32_t>(bits >> 32) == 0)
1261*8975f5c5SAndroid Build Coastguard Worker     {
1262*8975f5c5SAndroid Build Coastguard Worker         return sizeof(uint32_t) * CHAR_BIT - 1 - __builtin_clz(static_cast<uint32_t>(bits));
1263*8975f5c5SAndroid Build Coastguard Worker     }
1264*8975f5c5SAndroid Build Coastguard Worker     else
1265*8975f5c5SAndroid Build Coastguard Worker     {
1266*8975f5c5SAndroid Build Coastguard Worker         return sizeof(uint32_t) * CHAR_BIT - 1 - __builtin_clz(static_cast<uint32_t>(bits >> 32)) +
1267*8975f5c5SAndroid Build Coastguard Worker                32;
1268*8975f5c5SAndroid Build Coastguard Worker     }
1269*8975f5c5SAndroid Build Coastguard Worker #    endif  // defined(ANGLE_IS_64_BIT_CPU)
1270*8975f5c5SAndroid Build Coastguard Worker }
1271*8975f5c5SAndroid Build Coastguard Worker #endif  // defined(ANGLE_PLATFORM_POSIX)
1272*8975f5c5SAndroid Build Coastguard Worker 
ScanForward(uint8_t bits)1273*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint8_t bits)
1274*8975f5c5SAndroid Build Coastguard Worker {
1275*8975f5c5SAndroid Build Coastguard Worker     return ScanForward(static_cast<uint32_t>(bits));
1276*8975f5c5SAndroid Build Coastguard Worker }
1277*8975f5c5SAndroid Build Coastguard Worker 
ScanForward(uint16_t bits)1278*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanForward(uint16_t bits)
1279*8975f5c5SAndroid Build Coastguard Worker {
1280*8975f5c5SAndroid Build Coastguard Worker     return ScanForward(static_cast<uint32_t>(bits));
1281*8975f5c5SAndroid Build Coastguard Worker }
1282*8975f5c5SAndroid Build Coastguard Worker 
ScanReverse(uint8_t bits)1283*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint8_t bits)
1284*8975f5c5SAndroid Build Coastguard Worker {
1285*8975f5c5SAndroid Build Coastguard Worker     return ScanReverse(static_cast<uint32_t>(bits));
1286*8975f5c5SAndroid Build Coastguard Worker }
1287*8975f5c5SAndroid Build Coastguard Worker 
ScanReverse(uint16_t bits)1288*8975f5c5SAndroid Build Coastguard Worker inline unsigned long ScanReverse(uint16_t bits)
1289*8975f5c5SAndroid Build Coastguard Worker {
1290*8975f5c5SAndroid Build Coastguard Worker     return ScanReverse(static_cast<uint32_t>(bits));
1291*8975f5c5SAndroid Build Coastguard Worker }
1292*8975f5c5SAndroid Build Coastguard Worker 
1293*8975f5c5SAndroid Build Coastguard Worker // Returns -1 on 0, otherwise the index of the least significant 1 bit as in GLSL.
1294*8975f5c5SAndroid Build Coastguard Worker template <typename T>
FindLSB(T bits)1295*8975f5c5SAndroid Build Coastguard Worker int FindLSB(T bits)
1296*8975f5c5SAndroid Build Coastguard Worker {
1297*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_integral<T>::value, "must be integral type.");
1298*8975f5c5SAndroid Build Coastguard Worker     if (bits == 0u)
1299*8975f5c5SAndroid Build Coastguard Worker     {
1300*8975f5c5SAndroid Build Coastguard Worker         return -1;
1301*8975f5c5SAndroid Build Coastguard Worker     }
1302*8975f5c5SAndroid Build Coastguard Worker     else
1303*8975f5c5SAndroid Build Coastguard Worker     {
1304*8975f5c5SAndroid Build Coastguard Worker         return static_cast<int>(ScanForward(bits));
1305*8975f5c5SAndroid Build Coastguard Worker     }
1306*8975f5c5SAndroid Build Coastguard Worker }
1307*8975f5c5SAndroid Build Coastguard Worker 
1308*8975f5c5SAndroid Build Coastguard Worker // Returns -1 on 0, otherwise the index of the most significant 1 bit as in GLSL.
1309*8975f5c5SAndroid Build Coastguard Worker template <typename T>
FindMSB(T bits)1310*8975f5c5SAndroid Build Coastguard Worker int FindMSB(T bits)
1311*8975f5c5SAndroid Build Coastguard Worker {
1312*8975f5c5SAndroid Build Coastguard Worker     static_assert(std::is_integral<T>::value, "must be integral type.");
1313*8975f5c5SAndroid Build Coastguard Worker     if (bits == 0u)
1314*8975f5c5SAndroid Build Coastguard Worker     {
1315*8975f5c5SAndroid Build Coastguard Worker         return -1;
1316*8975f5c5SAndroid Build Coastguard Worker     }
1317*8975f5c5SAndroid Build Coastguard Worker     else
1318*8975f5c5SAndroid Build Coastguard Worker     {
1319*8975f5c5SAndroid Build Coastguard Worker         return static_cast<int>(ScanReverse(bits));
1320*8975f5c5SAndroid Build Coastguard Worker     }
1321*8975f5c5SAndroid Build Coastguard Worker }
1322*8975f5c5SAndroid Build Coastguard Worker 
1323*8975f5c5SAndroid Build Coastguard Worker // Returns whether the argument is Not a Number.
1324*8975f5c5SAndroid Build Coastguard Worker // IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
1325*8975f5c5SAndroid Build Coastguard Worker // non-zero.
isNaN(float f)1326*8975f5c5SAndroid Build Coastguard Worker inline bool isNaN(float f)
1327*8975f5c5SAndroid Build Coastguard Worker {
1328*8975f5c5SAndroid Build Coastguard Worker     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
1329*8975f5c5SAndroid Build Coastguard Worker     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
1330*8975f5c5SAndroid Build Coastguard Worker     return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
1331*8975f5c5SAndroid Build Coastguard Worker            (bitCast<uint32_t>(f) & 0x7fffffu);
1332*8975f5c5SAndroid Build Coastguard Worker }
1333*8975f5c5SAndroid Build Coastguard Worker 
1334*8975f5c5SAndroid Build Coastguard Worker // Returns whether the argument is infinity.
1335*8975f5c5SAndroid Build Coastguard Worker // IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
1336*8975f5c5SAndroid Build Coastguard Worker // zero.
isInf(float f)1337*8975f5c5SAndroid Build Coastguard Worker inline bool isInf(float f)
1338*8975f5c5SAndroid Build Coastguard Worker {
1339*8975f5c5SAndroid Build Coastguard Worker     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
1340*8975f5c5SAndroid Build Coastguard Worker     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
1341*8975f5c5SAndroid Build Coastguard Worker     return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
1342*8975f5c5SAndroid Build Coastguard Worker            !(bitCast<uint32_t>(f) & 0x7fffffu);
1343*8975f5c5SAndroid Build Coastguard Worker }
1344*8975f5c5SAndroid Build Coastguard Worker 
1345*8975f5c5SAndroid Build Coastguard Worker namespace priv
1346*8975f5c5SAndroid Build Coastguard Worker {
1347*8975f5c5SAndroid Build Coastguard Worker template <unsigned int N, unsigned int R>
1348*8975f5c5SAndroid Build Coastguard Worker struct iSquareRoot
1349*8975f5c5SAndroid Build Coastguard Worker {
solveiSquareRoot1350*8975f5c5SAndroid Build Coastguard Worker     static constexpr unsigned int solve()
1351*8975f5c5SAndroid Build Coastguard Worker     {
1352*8975f5c5SAndroid Build Coastguard Worker         return (R * R > N)
1353*8975f5c5SAndroid Build Coastguard Worker                    ? 0
1354*8975f5c5SAndroid Build Coastguard Worker                    : ((R * R == N) ? R : static_cast<unsigned int>(iSquareRoot<N, R + 1>::value));
1355*8975f5c5SAndroid Build Coastguard Worker     }
1356*8975f5c5SAndroid Build Coastguard Worker     enum Result
1357*8975f5c5SAndroid Build Coastguard Worker     {
1358*8975f5c5SAndroid Build Coastguard Worker         value = iSquareRoot::solve()
1359*8975f5c5SAndroid Build Coastguard Worker     };
1360*8975f5c5SAndroid Build Coastguard Worker };
1361*8975f5c5SAndroid Build Coastguard Worker 
1362*8975f5c5SAndroid Build Coastguard Worker template <unsigned int N>
1363*8975f5c5SAndroid Build Coastguard Worker struct iSquareRoot<N, N>
1364*8975f5c5SAndroid Build Coastguard Worker {
1365*8975f5c5SAndroid Build Coastguard Worker     enum result
1366*8975f5c5SAndroid Build Coastguard Worker     {
1367*8975f5c5SAndroid Build Coastguard Worker         value = N
1368*8975f5c5SAndroid Build Coastguard Worker     };
1369*8975f5c5SAndroid Build Coastguard Worker };
1370*8975f5c5SAndroid Build Coastguard Worker 
1371*8975f5c5SAndroid Build Coastguard Worker }  // namespace priv
1372*8975f5c5SAndroid Build Coastguard Worker 
1373*8975f5c5SAndroid Build Coastguard Worker template <unsigned int N>
1374*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned int iSquareRoot()
1375*8975f5c5SAndroid Build Coastguard Worker {
1376*8975f5c5SAndroid Build Coastguard Worker     return priv::iSquareRoot<N, 1>::value;
1377*8975f5c5SAndroid Build Coastguard Worker }
1378*8975f5c5SAndroid Build Coastguard Worker 
1379*8975f5c5SAndroid Build Coastguard Worker // Sum, difference and multiplication operations for signed ints that wrap on 32-bit overflow.
1380*8975f5c5SAndroid Build Coastguard Worker //
1381*8975f5c5SAndroid Build Coastguard Worker // Unsigned types are defined to do arithmetic modulo 2^n in C++. For signed types, overflow
1382*8975f5c5SAndroid Build Coastguard Worker // behavior is undefined.
1383*8975f5c5SAndroid Build Coastguard Worker 
1384*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1385*8975f5c5SAndroid Build Coastguard Worker inline T WrappingSum(T lhs, T rhs)
1386*8975f5c5SAndroid Build Coastguard Worker {
1387*8975f5c5SAndroid Build Coastguard Worker     uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
1388*8975f5c5SAndroid Build Coastguard Worker     uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
1389*8975f5c5SAndroid Build Coastguard Worker     return static_cast<T>(lhsUnsigned + rhsUnsigned);
1390*8975f5c5SAndroid Build Coastguard Worker }
1391*8975f5c5SAndroid Build Coastguard Worker 
1392*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1393*8975f5c5SAndroid Build Coastguard Worker inline T WrappingDiff(T lhs, T rhs)
1394*8975f5c5SAndroid Build Coastguard Worker {
1395*8975f5c5SAndroid Build Coastguard Worker     uint32_t lhsUnsigned = static_cast<uint32_t>(lhs);
1396*8975f5c5SAndroid Build Coastguard Worker     uint32_t rhsUnsigned = static_cast<uint32_t>(rhs);
1397*8975f5c5SAndroid Build Coastguard Worker     return static_cast<T>(lhsUnsigned - rhsUnsigned);
1398*8975f5c5SAndroid Build Coastguard Worker }
1399*8975f5c5SAndroid Build Coastguard Worker 
1400*8975f5c5SAndroid Build Coastguard Worker inline int32_t WrappingMul(int32_t lhs, int32_t rhs)
1401*8975f5c5SAndroid Build Coastguard Worker {
1402*8975f5c5SAndroid Build Coastguard Worker     int64_t lhsWide = static_cast<int64_t>(lhs);
1403*8975f5c5SAndroid Build Coastguard Worker     int64_t rhsWide = static_cast<int64_t>(rhs);
1404*8975f5c5SAndroid Build Coastguard Worker     // The multiplication is guaranteed not to overflow.
1405*8975f5c5SAndroid Build Coastguard Worker     int64_t resultWide = lhsWide * rhsWide;
1406*8975f5c5SAndroid Build Coastguard Worker     // Implement the desired wrapping behavior by masking out the high-order 32 bits.
1407*8975f5c5SAndroid Build Coastguard Worker     resultWide = resultWide & 0xffffffffLL;
1408*8975f5c5SAndroid Build Coastguard Worker     // Casting to a narrower signed type is fine since the casted value is representable in the
1409*8975f5c5SAndroid Build Coastguard Worker     // narrower type.
1410*8975f5c5SAndroid Build Coastguard Worker     return static_cast<int32_t>(resultWide);
1411*8975f5c5SAndroid Build Coastguard Worker }
1412*8975f5c5SAndroid Build Coastguard Worker 
1413*8975f5c5SAndroid Build Coastguard Worker inline float scaleScreenDimensionToNdc(float dimensionScreen, float viewportDimension)
1414*8975f5c5SAndroid Build Coastguard Worker {
1415*8975f5c5SAndroid Build Coastguard Worker     return 2.0f * dimensionScreen / viewportDimension;
1416*8975f5c5SAndroid Build Coastguard Worker }
1417*8975f5c5SAndroid Build Coastguard Worker 
1418*8975f5c5SAndroid Build Coastguard Worker inline float scaleScreenCoordinateToNdc(float coordinateScreen, float viewportDimension)
1419*8975f5c5SAndroid Build Coastguard Worker {
1420*8975f5c5SAndroid Build Coastguard Worker     float halfShifted = coordinateScreen / viewportDimension;
1421*8975f5c5SAndroid Build Coastguard Worker     return 2.0f * (halfShifted - 0.5f);
1422*8975f5c5SAndroid Build Coastguard Worker }
1423*8975f5c5SAndroid Build Coastguard Worker 
1424*8975f5c5SAndroid Build Coastguard Worker }  // namespace gl
1425*8975f5c5SAndroid Build Coastguard Worker 
1426*8975f5c5SAndroid Build Coastguard Worker namespace rx
1427*8975f5c5SAndroid Build Coastguard Worker {
1428*8975f5c5SAndroid Build Coastguard Worker 
1429*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1430*8975f5c5SAndroid Build Coastguard Worker T roundUp(const T value, const T alignment)
1431*8975f5c5SAndroid Build Coastguard Worker {
1432*8975f5c5SAndroid Build Coastguard Worker     auto temp = value + alignment - static_cast<T>(1);
1433*8975f5c5SAndroid Build Coastguard Worker     return temp - temp % alignment;
1434*8975f5c5SAndroid Build Coastguard Worker }
1435*8975f5c5SAndroid Build Coastguard Worker 
1436*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1437*8975f5c5SAndroid Build Coastguard Worker constexpr T roundUpPow2(const T value, const T alignment)
1438*8975f5c5SAndroid Build Coastguard Worker {
1439*8975f5c5SAndroid Build Coastguard Worker     ASSERT(gl::isPow2(alignment));
1440*8975f5c5SAndroid Build Coastguard Worker     return (value + alignment - 1) & ~(alignment - 1);
1441*8975f5c5SAndroid Build Coastguard Worker }
1442*8975f5c5SAndroid Build Coastguard Worker 
1443*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1444*8975f5c5SAndroid Build Coastguard Worker constexpr T roundDownPow2(const T value, const T alignment)
1445*8975f5c5SAndroid Build Coastguard Worker {
1446*8975f5c5SAndroid Build Coastguard Worker     ASSERT(gl::isPow2(alignment));
1447*8975f5c5SAndroid Build Coastguard Worker     return value & ~(alignment - 1);
1448*8975f5c5SAndroid Build Coastguard Worker }
1449*8975f5c5SAndroid Build Coastguard Worker 
1450*8975f5c5SAndroid Build Coastguard Worker template <typename T>
1451*8975f5c5SAndroid Build Coastguard Worker angle::CheckedNumeric<T> CheckedRoundUp(const T value, const T alignment)
1452*8975f5c5SAndroid Build Coastguard Worker {
1453*8975f5c5SAndroid Build Coastguard Worker     angle::CheckedNumeric<T> checkedValue(value);
1454*8975f5c5SAndroid Build Coastguard Worker     angle::CheckedNumeric<T> checkedAlignment(alignment);
1455*8975f5c5SAndroid Build Coastguard Worker     return roundUp(checkedValue, checkedAlignment);
1456*8975f5c5SAndroid Build Coastguard Worker }
1457*8975f5c5SAndroid Build Coastguard Worker 
1458*8975f5c5SAndroid Build Coastguard Worker inline constexpr unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
1459*8975f5c5SAndroid Build Coastguard Worker {
1460*8975f5c5SAndroid Build Coastguard Worker     unsigned int divided = value / divisor;
1461*8975f5c5SAndroid Build Coastguard Worker     return (divided + ((value % divisor == 0) ? 0 : 1));
1462*8975f5c5SAndroid Build Coastguard Worker }
1463*8975f5c5SAndroid Build Coastguard Worker 
1464*8975f5c5SAndroid Build Coastguard Worker #if defined(__has_builtin)
1465*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_HAS_BUILTIN(x) __has_builtin(x)
1466*8975f5c5SAndroid Build Coastguard Worker #else
1467*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_HAS_BUILTIN(x) 0
1468*8975f5c5SAndroid Build Coastguard Worker #endif
1469*8975f5c5SAndroid Build Coastguard Worker 
1470*8975f5c5SAndroid Build Coastguard Worker #if defined(_MSC_VER)
1471*8975f5c5SAndroid Build Coastguard Worker 
1472*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL(x, y) _rotl(x, y)
1473*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL64(x, y) _rotl64(x, y)
1474*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTR16(x, y) _rotr16(x, y)
1475*8975f5c5SAndroid Build Coastguard Worker 
1476*8975f5c5SAndroid Build Coastguard Worker #elif defined(__clang__) && ANGLE_HAS_BUILTIN(__builtin_rotateleft32) && \
1477*8975f5c5SAndroid Build Coastguard Worker     ANGLE_HAS_BUILTIN(__builtin_rotateleft64) && ANGLE_HAS_BUILTIN(__builtin_rotateright16)
1478*8975f5c5SAndroid Build Coastguard Worker 
1479*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL(x, y) __builtin_rotateleft32(x, y)
1480*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL64(x, y) __builtin_rotateleft64(x, y)
1481*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTR16(x, y) __builtin_rotateright16(x, y)
1482*8975f5c5SAndroid Build Coastguard Worker 
1483*8975f5c5SAndroid Build Coastguard Worker #else
1484*8975f5c5SAndroid Build Coastguard Worker 
1485*8975f5c5SAndroid Build Coastguard Worker inline uint32_t RotL(uint32_t x, int8_t r)
1486*8975f5c5SAndroid Build Coastguard Worker {
1487*8975f5c5SAndroid Build Coastguard Worker     return (x << r) | (x >> (32 - r));
1488*8975f5c5SAndroid Build Coastguard Worker }
1489*8975f5c5SAndroid Build Coastguard Worker 
1490*8975f5c5SAndroid Build Coastguard Worker inline uint64_t RotL64(uint64_t x, int8_t r)
1491*8975f5c5SAndroid Build Coastguard Worker {
1492*8975f5c5SAndroid Build Coastguard Worker     return (x << r) | (x >> (64 - r));
1493*8975f5c5SAndroid Build Coastguard Worker }
1494*8975f5c5SAndroid Build Coastguard Worker 
1495*8975f5c5SAndroid Build Coastguard Worker inline uint16_t RotR16(uint16_t x, int8_t r)
1496*8975f5c5SAndroid Build Coastguard Worker {
1497*8975f5c5SAndroid Build Coastguard Worker     return (x >> r) | (x << (16 - r));
1498*8975f5c5SAndroid Build Coastguard Worker }
1499*8975f5c5SAndroid Build Coastguard Worker 
1500*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
1501*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTL64(x, y) ::rx::RotL64(x, y)
1502*8975f5c5SAndroid Build Coastguard Worker #    define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
1503*8975f5c5SAndroid Build Coastguard Worker 
1504*8975f5c5SAndroid Build Coastguard Worker #endif  // namespace rx
1505*8975f5c5SAndroid Build Coastguard Worker 
1506*8975f5c5SAndroid Build Coastguard Worker constexpr unsigned int Log2(unsigned int bytes)
1507*8975f5c5SAndroid Build Coastguard Worker {
1508*8975f5c5SAndroid Build Coastguard Worker     return bytes == 1 ? 0 : (1 + Log2(bytes / 2));
1509*8975f5c5SAndroid Build Coastguard Worker }
1510*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
1511*8975f5c5SAndroid Build Coastguard Worker 
1512*8975f5c5SAndroid Build Coastguard Worker #endif  // COMMON_MATHUTIL_H_
1513