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 #include "Half.hpp"
20 
21 #include <cmath>
22 #if defined(_MSC_VER)
23 	#include <intrin.h>
24 #endif
25 
26 namespace sw
27 {
28 	using std::abs;
29 
30 	#undef min
31 	#undef max
32 
33 	template<class T>
max(T a,T b)34 	inline T max(T a, T b)
35 	{
36 		return a > b ? a : b;
37 	}
38 
39 	template<class T>
min(T a,T b)40 	inline T min(T a, T b)
41 	{
42 		return a < b ? a : b;
43 	}
44 
45 	template<class T>
max(T a,T b,T c)46 	inline T max(T a, T b, T c)
47 	{
48 		return max(max(a, b), c);
49 	}
50 
51 	template<class T>
min(T a,T b,T c)52 	inline T min(T a, T b, T c)
53 	{
54 		return min(min(a, b), c);
55 	}
56 
57 	template<class T>
max(T a,T b,T c,T d)58 	inline T max(T a, T b, T c, T d)
59 	{
60 		return max(max(a, b), max(c, d));
61 	}
62 
63 	template<class T>
min(T a,T b,T c,T d)64 	inline T min(T a, T b, T c, T d)
65 	{
66 		return min(min(a, b), min(c, d));
67 	}
68 
69 	template<class T>
swap(T & a,T & b)70 	inline void swap(T &a, T &b)
71 	{
72 		T t = a;
73 		a = b;
74 		b = t;
75 	}
76 
77 	template <typename destType, typename sourceType>
bitCast(const sourceType & source)78 	destType bitCast(const sourceType &source)
79 	{
80 		union
81 		{
82 			sourceType s;
83 			destType d;
84 		} sd;
85 		sd.s = source;
86 		return sd.d;
87 	}
88 
iround(float x)89 	inline int iround(float x)
90 	{
91 		return (int)floor(x + 0.5f);
92 	//	return _mm_cvtss_si32(_mm_load_ss(&x));   // FIXME: Demands SSE support
93 	}
94 
ifloor(float x)95 	inline int ifloor(float x)
96 	{
97 		return (int)floor(x);
98 	}
99 
ceilFix4(int x)100 	inline int ceilFix4(int x)
101 	{
102 		return (x + 0xF) & 0xFFFFFFF0;
103 	}
104 
ceilInt4(int x)105 	inline int ceilInt4(int x)
106 	{
107 		return (x + 0xF) >> 4;
108 	}
109 
110 	#define BITS(x)    ( \
111 	!!((x) & 0x80000000) + \
112 	!!((x) & 0xC0000000) + \
113 	!!((x) & 0xE0000000) + \
114 	!!((x) & 0xF0000000) + \
115 	!!((x) & 0xF8000000) + \
116 	!!((x) & 0xFC000000) + \
117 	!!((x) & 0xFE000000) + \
118 	!!((x) & 0xFF000000) + \
119 	!!((x) & 0xFF800000) + \
120 	!!((x) & 0xFFC00000) + \
121 	!!((x) & 0xFFE00000) + \
122 	!!((x) & 0xFFF00000) + \
123 	!!((x) & 0xFFF80000) + \
124 	!!((x) & 0xFFFC0000) + \
125 	!!((x) & 0xFFFE0000) + \
126 	!!((x) & 0xFFFF0000) + \
127 	!!((x) & 0xFFFF8000) + \
128 	!!((x) & 0xFFFFC000) + \
129 	!!((x) & 0xFFFFE000) + \
130 	!!((x) & 0xFFFFF000) + \
131 	!!((x) & 0xFFFFF800) + \
132 	!!((x) & 0xFFFFFC00) + \
133 	!!((x) & 0xFFFFFE00) + \
134 	!!((x) & 0xFFFFFF00) + \
135 	!!((x) & 0xFFFFFF80) + \
136 	!!((x) & 0xFFFFFFC0) + \
137 	!!((x) & 0xFFFFFFE0) + \
138 	!!((x) & 0xFFFFFFF0) + \
139 	!!((x) & 0xFFFFFFF8) + \
140 	!!((x) & 0xFFFFFFFC) + \
141 	!!((x) & 0xFFFFFFFE) + \
142 	!!((x) & 0xFFFFFFFF))
143 
144 	#define MAX(x, y) ((x) > (y) ? (x) : (y))
145 	#define MIN(x, y) ((x) < (y) ? (x) : (y))
146 
exp2(float x)147 	inline float exp2(float x)
148 	{
149 		return exp2f(x);
150 	}
151 
exp2(int x)152 	inline int exp2(int x)
153 	{
154 		return 1 << x;
155 	}
156 
log2(int x)157 	inline unsigned long log2(int x)
158 	{
159 		#if defined(_MSC_VER)
160 			unsigned long y;
161 			_BitScanReverse(&y, x);
162 			return y;
163 		#else
164 			return 31 - __builtin_clz(x);
165 		#endif
166 	}
167 
ilog2(float x)168 	inline int ilog2(float x)
169 	{
170 		unsigned int y = *(unsigned int*)&x;
171 
172 		return ((y & 0x7F800000) >> 23) - 127;
173 	}
174 
log2(float x)175 	inline float log2(float x)
176 	{
177 		return logf(x) * 1.44269504f;   // 1.0 / log[e](2)
178 	}
179 
isPow2(int x)180 	inline bool isPow2(int x)
181 	{
182 		return (x & -x) == x;
183 	}
184 
185 	template<class T>
clamp(T x,T a,T b)186 	inline T clamp(T x, T a, T b)
187 	{
188 		if(x < a) x = a;
189 		if(x > b) x = b;
190 
191 		return x;
192 	}
193 
clamp01(float x)194 	inline float clamp01(float x)
195 	{
196 		return clamp(x, 0.0f, 1.0f);
197 	}
198 
ceilPow2(int x)199 	inline int ceilPow2(int x)
200 	{
201 		int i = 1;
202 
203 		while(i < x)
204 		{
205 			i <<= 1;
206 		}
207 
208 		return i;
209 	}
210 
floorDiv(int a,int b)211 	inline int floorDiv(int a, int b)
212 	{
213 		return a / b + ((a % b) >> 31);
214 	}
215 
floorMod(int a,int b)216 	inline int floorMod(int a, int b)
217 	{
218 		int r = a % b;
219 		return r + ((r >> 31) & b);
220 	}
221 
ceilDiv(int a,int b)222 	inline int ceilDiv(int a, int b)
223 	{
224 		return a / b - (-(a % b) >> 31);
225 	}
226 
ceilMod(int a,int b)227 	inline int ceilMod(int a, int b)
228 	{
229 		int r = a % b;
230 		return r - ((-r >> 31) & b);
231 	}
232 
233 	template<const int n>
unorm(float x)234 	inline unsigned int unorm(float x)
235 	{
236 		static const unsigned int max = 0xFFFFFFFF >> (32 - n);
237 		static const float maxf = static_cast<float>(max);
238 
239 		if(x >= 1.0f)
240 		{
241 			return max;
242 		}
243 		else if(x <= 0.0f)
244 		{
245 			return 0;
246 		}
247 		else
248 		{
249 			return static_cast<unsigned int>(maxf * x + 0.5f);
250 		}
251 	}
252 
253 	template<const int n>
snorm(float x)254 	inline int snorm(float x)
255 	{
256 		static const unsigned int min = 0x80000000 >> (32 - n);
257 		static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
258 		static const float maxf = static_cast<float>(max);
259 		static const unsigned int range = 0xFFFFFFFF >> (32 - n);
260 
261 		if(x >= 0.0f)
262 		{
263 			if(x >= 1.0f)
264 			{
265 				return max;
266 			}
267 			else
268 			{
269 				return static_cast<int>(maxf * x + 0.5f);
270 			}
271 		}
272 		else
273 		{
274 			if(x <= -1.0f)
275 			{
276 				return min;
277 			}
278 			else
279 			{
280 				return static_cast<int>(maxf * x - 0.5f) & range;
281 			}
282 		}
283 	}
284 
285 	template<const int n>
ucast(float x)286 	inline unsigned int ucast(float x)
287 	{
288 		static const unsigned int max = 0xFFFFFFFF >> (32 - n);
289 		static const float maxf = static_cast<float>(max);
290 
291 		if(x >= maxf)
292 		{
293 			return max;
294 		}
295 		else if(x <= 0.0f)
296 		{
297 			return 0;
298 		}
299 		else
300 		{
301 			return static_cast<unsigned int>(x + 0.5f);
302 		}
303 	}
304 
305 	template<const int n>
scast(float x)306 	inline int scast(float x)
307 	{
308 		static const unsigned int min = 0x80000000 >> (32 - n);
309 		static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
310 		static const float maxf = static_cast<float>(max);
311 		static const float minf = static_cast<float>(min);
312 		static const unsigned int range = 0xFFFFFFFF >> (32 - n);
313 
314 		if(x > 0.0f)
315 		{
316 			if(x >= maxf)
317 			{
318 				return max;
319 			}
320 			else
321 			{
322 				return static_cast<int>(x + 0.5f);
323 			}
324 		}
325 		else
326 		{
327 			if(x <= -minf)
328 			{
329 				return min;
330 			}
331 			else
332 			{
333 				return static_cast<int>(x - 0.5f) & range;
334 			}
335 		}
336 	}
337 
sRGBtoLinear(float c)338 	inline float sRGBtoLinear(float c)
339 	{
340 		if(c <= 0.04045f)
341 		{
342 			return c * 0.07739938f;   // 1.0f / 12.92f;
343 		}
344 		else
345 		{
346 			return powf((c + 0.055f) * 0.9478673f, 2.4f);   // 1.0f / 1.055f
347 		}
348 	}
349 
linearToSRGB(float c)350 	inline float linearToSRGB(float c)
351 	{
352 		if(c <= 0.0031308f)
353 		{
354 			return c * 12.92f;
355 		}
356 		else
357 		{
358 			return 1.055f * powf(c, 0.4166667f) - 0.055f;   // 1.0f / 2.4f
359 		}
360 	}
361 
362 	unsigned char sRGB8toLinear8(unsigned char value);
363 
364 	uint64_t FNV_1a(const unsigned char *data, int size);   // Fowler-Noll-Vo hash function
365 
366 	// Round up to the next multiple of alignment
align(unsigned int value,unsigned int alignment)367 	inline unsigned int align(unsigned int value, unsigned int alignment)
368 	{
369 		return ((value + alignment - 1) / alignment) * alignment;
370 	}
371 
clampToSignedInt(unsigned int x)372 	inline int clampToSignedInt(unsigned int x)
373 	{
374 		return static_cast<int>(min(x, 0x7FFFFFFFu));
375 	}
376 }
377 
378 #endif   // sw_Math_hpp
379