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