1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef sw_Math_hpp
16#define sw_Math_hpp
17
18#include "Types.hpp"
19
20#include "Vulkan/VkDebug.hpp"
21
22#include <cmath>
23#if defined(_MSC_VER)
24 #include <intrin.h>
25#endif
26
27namespace sw
28{
29 using std::abs;
30
31 #undef min
32 #undef max
33
34 template<class T>
35 inline T constexpr max(T a, T b)
36 {
37 return a > b ? a : b;
38 }
39
40 template<class T>
41 inline constexpr T min(T a, T b)
42 {
43 return a < b ? a : b;
44 }
45
46 template<class T>
47 inline constexpr T max(T a, T b, T c)
48 {
49 return max(max(a, b), c);
50 }
51
52 template<class T>
53 inline constexpr T min(T a, T b, T c)
54 {
55 return min(min(a, b), c);
56 }
57
58 template<class T>
59 inline constexpr T max(T a, T b, T c, T d)
60 {
61 return max(max(a, b), max(c, d));
62 }
63
64 template<class T>
65 inline constexpr T min(T a, T b, T c, T d)
66 {
67 return min(min(a, b), min(c, d));
68 }
69
70 template <typename destType, typename sourceType>
71 destType bit_cast(const sourceType &source)
72 {
73 union
74 {
75 sourceType s;
76 destType d;
77 } sd;
78 sd.s = source;
79 return sd.d;
80 }
81
82 inline int iround(float x)
83 {
84 return (int)floor(x + 0.5f);
85 // return _mm_cvtss_si32(_mm_load_ss(&x)); // FIXME: Demands SSE support
86 }
87
88 inline int ifloor(float x)
89 {
90 return (int)floor(x);
91 }
92
93 inline int ceilFix4(int x)
94 {
95 return (x + 0xF) & 0xFFFFFFF0;
96 }
97
98 inline int ceilInt4(int x)
99 {
100 return (x + 0xF) >> 4;
101 }
102
103 #define BITS(x) ( \
104 !!((x) & 0x80000000) + \
105 !!((x) & 0xC0000000) + \
106 !!((x) & 0xE0000000) + \
107 !!((x) & 0xF0000000) + \
108 !!((x) & 0xF8000000) + \
109 !!((x) & 0xFC000000) + \
110 !!((x) & 0xFE000000) + \
111 !!((x) & 0xFF000000) + \
112 !!((x) & 0xFF800000) + \
113 !!((x) & 0xFFC00000) + \
114 !!((x) & 0xFFE00000) + \
115 !!((x) & 0xFFF00000) + \
116 !!((x) & 0xFFF80000) + \
117 !!((x) & 0xFFFC0000) + \
118 !!((x) & 0xFFFE0000) + \
119 !!((x) & 0xFFFF0000) + \
120 !!((x) & 0xFFFF8000) + \
121 !!((x) & 0xFFFFC000) + \
122 !!((x) & 0xFFFFE000) + \
123 !!((x) & 0xFFFFF000) + \
124 !!((x) & 0xFFFFF800) + \
125 !!((x) & 0xFFFFFC00) + \
126 !!((x) & 0xFFFFFE00) + \
127 !!((x) & 0xFFFFFF00) + \
128 !!((x) & 0xFFFFFF80) + \
129 !!((x) & 0xFFFFFFC0) + \
130 !!((x) & 0xFFFFFFE0) + \
131 !!((x) & 0xFFFFFFF0) + \
132 !!((x) & 0xFFFFFFF8) + \
133 !!((x) & 0xFFFFFFFC) + \
134 !!((x) & 0xFFFFFFFE) + \
135 !!((x) & 0xFFFFFFFF))
136
137 #define MAX(x, y) ((x) > (y) ? (x) : (y))
138 #define MIN(x, y) ((x) < (y) ? (x) : (y))
139
140 inline unsigned long log2i(int x)
141 {
142 #if defined(_MSC_VER)
143 unsigned long y;
144 _BitScanReverse(&y, x);
145 return y;
146 #else
147 return 31 - __builtin_clz(x);
148 #endif
149 }
150
151 inline bool isPow2(int x)
152 {
153 return (x & -x) == x;
154 }
155
156 template<class T>
157 inline T clamp(T x, T a, T b)
158 {
159 ASSERT(a <= b);
160 if(x < a) x = a;
161 if(x > b) x = b;
162
163 return x;
164 }
165
166 inline float clamp01(float x)
167 {
168 return clamp(x, 0.0f, 1.0f);
169 }
170
171 // Bit-cast of a floating-point value into a two's complement integer representation.
172 // This makes floating-point values comparable as integers.
173 inline int32_t float_as_twos_complement(float f)
174 {
175 // IEEE-754 floating-point numbers are sorted by magnitude in the same way as integers,
176 // except negative values are like one's complement integers. Convert them to two's complement.
177 int32_t i = bit_cast<int32_t>(f);
178 return (i < 0) ? (0x7FFFFFFFu - i) : i;
179 }
180
181 // 'Safe' clamping operation which always returns a value between min and max (inclusive).
182 inline float clamp_s(float x, float min, float max)
183 {
184 // NaN values can't be compared directly
185 if(float_as_twos_complement(x) < float_as_twos_complement(min)) x = min;
186 if(float_as_twos_complement(x) > float_as_twos_complement(max)) x = max;
187
188 return x;
189 }
190
191 inline int ceilPow2(int x)
192 {
193 int i = 1;
194
195 while(i < x)
196 {
197 i <<= 1;
198 }
199
200 return i;
201 }
202
203 inline int floorDiv(int a, int b)
204 {
205 return a / b + ((a % b) >> 31);
206 }
207
208 inline int floorMod(int a, int b)
209 {
210 int r = a % b;
211 return r + ((r >> 31) & b);
212 }
213
214 inline int ceilDiv(int a, int b)
215 {
216 return a / b - (-(a % b) >> 31);
217 }
218
219 inline int ceilMod(int a, int b)
220 {
221 int r = a % b;
222 return r - ((-r >> 31) & b);
223 }
224
225 template<const int n>
226 inline unsigned int unorm(float x)
227 {
228 static const unsigned int max = 0xFFFFFFFF >> (32 - n);
229 static const float maxf = static_cast<float>(max);
230
231 if(x >= 1.0f)
232 {
233 return max;
234 }
235 else if(x <= 0.0f)
236 {
237 return 0;
238 }
239 else
240 {
241 return static_cast<unsigned int>(maxf * x + 0.5f);
242 }
243 }
244
245 template<const int n>
246 inline int snorm(float x)
247 {
248 static const unsigned int min = 0x80000000 >> (32 - n);
249 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
250 static const float maxf = static_cast<float>(max);
251 static const unsigned int range = 0xFFFFFFFF >> (32 - n);
252
253 if(x >= 0.0f)
254 {
255 if(x >= 1.0f)
256 {
257 return max;
258 }
259 else
260 {
261 return static_cast<int>(maxf * x + 0.5f);
262 }
263 }
264 else
265 {
266 if(x <= -1.0f)
267 {
268 return min;
269 }
270 else
271 {
272 return static_cast<int>(maxf * x - 0.5f) & range;
273 }
274 }
275 }
276
277 template<const int n>
278 inline unsigned int ucast(float x)
279 {
280 static const unsigned int max = 0xFFFFFFFF >> (32 - n);
281 static const float maxf = static_cast<float>(max);
282
283 if(x >= maxf)
284 {
285 return max;
286 }
287 else if(x <= 0.0f)
288 {
289 return 0;
290 }
291 else
292 {
293 return static_cast<unsigned int>(x + 0.5f);
294 }
295 }
296
297 template<const int n>
298 inline int scast(float x)
299 {
300 static const unsigned int min = 0x80000000 >> (32 - n);
301 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
302 static const float maxf = static_cast<float>(max);
303 static const float minf = static_cast<float>(min);
304 static const unsigned int range = 0xFFFFFFFF >> (32 - n);
305
306 if(x > 0.0f)
307 {
308 if(x >= maxf)
309 {
310 return max;
311 }
312 else
313 {
314 return static_cast<int>(x + 0.5f);
315 }
316 }
317 else
318 {
319 if(x <= -minf)
320 {
321 return min;
322 }
323 else
324 {
325 return static_cast<int>(x - 0.5f) & range;
326 }
327 }
328 }
329
330 inline float sRGBtoLinear(float c)
331 {
332 if(c <= 0.04045f)
333 {
334 return c * 0.07739938f; // 1.0f / 12.92f;
335 }
336 else
337 {
338 return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f
339 }
340 }
341
342 inline float linearToSRGB(float c)
343 {
344 if(c <= 0.0031308f)
345 {
346 return c * 12.92f;
347 }
348 else
349 {
350 return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f
351 }
352 }
353
354 unsigned char sRGB8toLinear8(unsigned char value);
355
356 uint64_t FNV_1a(const unsigned char *data, int size); // Fowler-Noll-Vo hash function
357
358 // Round up to the next multiple of alignment
359 template<typename T>
360 inline T align(T value, unsigned int alignment)
361 {
362 return ((value + alignment - 1) / alignment) * alignment;
363 }
364
365 template<unsigned int alignment, typename T>
366 inline T align(T value)
367 {
368 return ((value + alignment - 1) / alignment) * alignment;
369 }
370
371 inline int clampToSignedInt(unsigned int x)
372 {
373 return static_cast<int>(min(x, 0x7FFFFFFFu));
374 }
375
376 // Convert floating value v to fixed point with p digits after the decimal point
377 constexpr int toFixedPoint(float v, int p) {
378 return static_cast<int>(v * (1 << p));
379 }
380}
381
382#endif // sw_Math_hpp
383