blob: 0b4abe64b3007991e44d3ec9921302caac343619 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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 <cmath>
21#if defined(_MSC_VER)
22 #include <intrin.h>
23#endif
24
25namespace sw
26{
27 using std::abs;
28
29 #undef min
30 #undef max
31
32 template<class T>
33 inline T max(T a, T b)
34 {
35 return a > b ? a : b;
36 }
37
38 template<class T>
39 inline T min(T a, T b)
40 {
41 return a < b ? a : b;
42 }
43
44 template<class T>
45 inline T max(T a, T b, T c)
46 {
47 return max(max(a, b), c);
48 }
49
50 template<class T>
51 inline T min(T a, T b, T c)
52 {
53 return min(min(a, b), c);
54 }
55
56 template<class T>
57 inline T max(T a, T b, T c, T d)
58 {
59 return max(max(a, b), max(c, d));
60 }
61
62 template<class T>
63 inline T min(T a, T b, T c, T d)
64 {
65 return min(min(a, b), min(c, d));
66 }
67
68 template<class T>
69 inline void swap(T &a, T &b)
70 {
71 T t = a;
72 a = b;
73 b = t;
74 }
75
76 inline int iround(float x)
77 {
78 return (int)floor(x + 0.5f);
79 // return _mm_cvtss_si32(_mm_load_ss(&x)); // FIXME: Demands SSE support
80 }
81
82 inline int ifloor(float x)
83 {
84 return (int)floor(x);
85 }
86
87 inline int ceilFix4(int x)
88 {
89 return (x + 0xF) & 0xFFFFFFF0;
90 }
91
92 inline int ceilInt4(int x)
93 {
94 return (x + 0xF) >> 4;
95 }
96
97 #define BITS(x) ( \
98 !!((x) & 0x80000000) + \
99 !!((x) & 0xC0000000) + \
100 !!((x) & 0xE0000000) + \
101 !!((x) & 0xF0000000) + \
102 !!((x) & 0xF8000000) + \
103 !!((x) & 0xFC000000) + \
104 !!((x) & 0xFE000000) + \
105 !!((x) & 0xFF000000) + \
106 !!((x) & 0xFF800000) + \
107 !!((x) & 0xFFC00000) + \
108 !!((x) & 0xFFE00000) + \
109 !!((x) & 0xFFF00000) + \
110 !!((x) & 0xFFF80000) + \
111 !!((x) & 0xFFFC0000) + \
112 !!((x) & 0xFFFE0000) + \
113 !!((x) & 0xFFFF0000) + \
114 !!((x) & 0xFFFF8000) + \
115 !!((x) & 0xFFFFC000) + \
116 !!((x) & 0xFFFFE000) + \
117 !!((x) & 0xFFFFF000) + \
118 !!((x) & 0xFFFFF800) + \
119 !!((x) & 0xFFFFFC00) + \
120 !!((x) & 0xFFFFFE00) + \
121 !!((x) & 0xFFFFFF00) + \
122 !!((x) & 0xFFFFFF80) + \
123 !!((x) & 0xFFFFFFC0) + \
124 !!((x) & 0xFFFFFFE0) + \
125 !!((x) & 0xFFFFFFF0) + \
126 !!((x) & 0xFFFFFFF8) + \
127 !!((x) & 0xFFFFFFFC) + \
128 !!((x) & 0xFFFFFFFE) + \
129 !!((x) & 0xFFFFFFFF))
130
131 #define MAX(x, y) ((x) > (y) ? (x) : (y))
132 #define MIN(x, y) ((x) < (y) ? (x) : (y))
133
134 inline float exp2(float x)
135 {
136 return exp2f(x);
137 }
138
139 inline int exp2(int x)
140 {
141 return 1 << x;
142 }
143
144 inline unsigned long log2(int x)
145 {
146 #if defined(_MSC_VER)
147 unsigned long y;
148 _BitScanReverse(&y, x);
149 return y;
150 #else
151 return 31 - __builtin_clz(x);
152 #endif
153 }
154
155 inline int ilog2(float x)
156 {
157 unsigned int y = *(unsigned int*)&x;
158
159 return ((y & 0x7F800000) >> 23) - 127;
160 }
161
162 inline float log2(float x)
163 {
164 return logf(x) * 1.44269504f; // 1.0 / log[e](2)
165 }
166
167 inline bool isPow2(int x)
168 {
169 return (x & -x) == x;
170 }
171
172 template<class T>
173 inline T clamp(T x, T a, T b)
174 {
175 if(x < a) x = a;
176 if(x > b) x = b;
177
178 return x;
179 }
180
181 inline float clamp01(float x)
182 {
183 return clamp(x, 0.0f, 1.0f);
184 }
185
186 inline int ceilPow2(int x)
187 {
188 int i = 1;
189
190 while(i < x)
191 {
192 i <<= 1;
193 }
194
195 return i;
196 }
197
198 inline int floorDiv(int a, int b)
199 {
200 return a / b + ((a % b) >> 31);
201 }
202
203 inline int floorMod(int a, int b)
204 {
205 int r = a % b;
206 return r + ((r >> 31) & b);
207 }
208
209 inline int ceilDiv(int a, int b)
210 {
211 return a / b - (-(a % b) >> 31);
212 }
213
214 inline int ceilMod(int a, int b)
215 {
216 int r = a % b;
217 return r - ((-r >> 31) & b);
218 }
219
220 template<const int n>
221 inline unsigned int unorm(float x)
222 {
223 static const unsigned int max = 0xFFFFFFFF >> (32 - n);
224 static const float maxf = static_cast<float>(max);
225
226 if(x >= 1.0f)
227 {
228 return max;
229 }
230 else if(x <= 0.0f)
231 {
232 return 0;
233 }
234 else
235 {
236 return static_cast<unsigned int>(maxf * x + 0.5f);
237 }
238 }
239
240 template<const int n>
241 inline int snorm(float x)
242 {
243 static const unsigned int min = 0x80000000 >> (32 - n);
244 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
245 static const float maxf = static_cast<float>(max);
246 static const unsigned int range = 0xFFFFFFFF >> (32 - n);
247
248 if(x >= 0.0f)
249 {
250 if(x >= 1.0f)
251 {
252 return max;
253 }
254 else
255 {
256 return static_cast<int>(maxf * x + 0.5f);
257 }
258 }
259 else
260 {
261 if(x <= -1.0f)
262 {
263 return min;
264 }
265 else
266 {
267 return static_cast<int>(maxf * x - 0.5f) & range;
268 }
269 }
270 }
271
272 template<const int n>
273 inline unsigned int ucast(float x)
274 {
275 static const unsigned int max = 0xFFFFFFFF >> (32 - n);
276 static const float maxf = static_cast<float>(max);
277
278 if(x >= maxf)
279 {
280 return max;
281 }
282 else if(x <= 0.0f)
283 {
284 return 0;
285 }
286 else
287 {
288 return static_cast<unsigned int>(x + 0.5f);
289 }
290 }
291
292 template<const int n>
293 inline int scast(float x)
294 {
295 static const unsigned int min = 0x80000000 >> (32 - n);
296 static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
297 static const float maxf = static_cast<float>(max);
298 static const unsigned int range = 0xFFFFFFFF >> (32 - n);
299
300 if(x > 0.0f)
301 {
302 if(x >= maxf)
303 {
304 return max;
305 }
306 else
307 {
308 return static_cast<int>(maxf * x + 0.5f);
309 }
310 }
311 else
312 {
313 if(x <= -1.0f)
314 {
315 return min;
316 }
317 else
318 {
319 return static_cast<int>(maxf * x - 0.5f) & range;
320 }
321 }
322 }
323
324 inline float sRGBtoLinear(float c)
325 {
326 if(c <= 0.04045f)
327 {
328 return c * 0.07739938f; // 1.0f / 12.92f;
329 }
330 else
331 {
332 return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f
333 }
334 }
335
336 inline float linearToSRGB(float c)
337 {
338 if(c <= 0.0031308f)
339 {
340 return c * 12.92f;
341 }
342 else
343 {
344 return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f
345 }
346 }
347
348 unsigned char sRGB8toLinear8(unsigned char value);
349
350 uint64_t FNV_1a(const unsigned char *data, int size); // Fowler-Noll-Vo hash function
351
352 // Round up to the next multiple of alignment
353 inline unsigned int align(unsigned int value, unsigned int alignment)
354 {
355 return ((value + alignment - 1) / alignment) * alignment;
356 }
357
358 inline int clampToSignedInt(unsigned int x)
359 {
360 return static_cast<int>(min(x, 0x7FFFFFFFu));
361 }
362
363 class RGB9E5Data
364 {
365 unsigned int R : 9;
366 unsigned int G : 9;
367 unsigned int B : 9;
368 unsigned int E : 5;
369
370 public:
371 void toRGBFloats(float* rgb) const
372 {
373 static const float Offset = -24.0f; // Exponent Bias (15) + Number of mantissa bits per component (9) = 24
374
375 const float factor = powf(2.0f, static_cast<float>(E) + Offset);
376 rgb[0] = static_cast<float>(R) * factor;
377 rgb[1] = static_cast<float>(G) * factor;
378 rgb[2] = static_cast<float>(B) * factor;
379 }
380 };
381
382 class R11G11B10FData
383 {
384 unsigned int R : 11;
385 unsigned int G : 11;
386 unsigned int B : 10;
387
388 static inline float float11ToFloat32(unsigned short fp11)
389 {
390 unsigned short exponent = (fp11 >> 6) & 0x1F;
391 unsigned short mantissa = fp11 & 0x3F;
392
393 unsigned int output;
394 if(exponent == 0x1F)
395 {
396 // INF or NAN
397 output = 0x7f800000 | (mantissa << 17);
398 }
399 else
400 {
401 if(exponent != 0)
402 {
403 // normalized
404 }
405 else if(mantissa != 0)
406 {
407 // The value is denormalized
408 exponent = 1;
409
410 do
411 {
412 exponent--;
413 mantissa <<= 1;
414 } while((mantissa & 0x40) == 0);
415
416 mantissa = mantissa & 0x3F;
417 }
418 else // The value is zero
419 {
420 exponent = static_cast<unsigned short>(-112);
421 }
422
423 output = ((exponent + 112) << 23) | (mantissa << 17);
424 }
425
426 return *(float*)(&output);
427 }
428
429 static inline float float10ToFloat32(unsigned short fp10)
430 {
431 unsigned short exponent = (fp10 >> 5) & 0x1F;
432 unsigned short mantissa = fp10 & 0x1F;
433
434 unsigned int output;
435 if(exponent == 0x1F)
436 {
437 // INF or NAN
438 output = 0x7f800000 | (mantissa << 17);
439 }
440 else
441 {
442 if(exponent != 0)
443 {
444 // normalized
445 }
446 else if(mantissa != 0)
447 {
448 // The value is denormalized
449 exponent = 1;
450
451 do
452 {
453 exponent--;
454 mantissa <<= 1;
455 } while((mantissa & 0x20) == 0);
456
457 mantissa = mantissa & 0x1F;
458 }
459 else // The value is zero
460 {
461 exponent = static_cast<unsigned short>(-112);
462 }
463
464 output = ((exponent + 112) << 23) | (mantissa << 18);
465 }
466
467 return *(float*)(&output);
468 }
469
470 public:
471 void toRGBFloats(float* rgb) const
472 {
473 rgb[0] = float11ToFloat32(R);
474 rgb[1] = float11ToFloat32(G);
475 rgb[2] = float10ToFloat32(B);
476 }
477 };
478}
479
480#endif // sw_Math_hpp