Home | History | Annotate | Download | only in System
      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>
     34 	inline T max(T a, T b)
     35 	{
     36 		return a > b ? a : b;
     37 	}
     38 
     39 	template<class T>
     40 	inline T min(T a, T b)
     41 	{
     42 		return a < b ? a : b;
     43 	}
     44 
     45 	template<class T>
     46 	inline T max(T a, T b, T c)
     47 	{
     48 		return max(max(a, b), c);
     49 	}
     50 
     51 	template<class T>
     52 	inline T min(T a, T b, T c)
     53 	{
     54 		return min(min(a, b), c);
     55 	}
     56 
     57 	template<class T>
     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>
     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>
     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>
     78 	destType bit_cast(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 
     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 
     95 	inline int ifloor(float x)
     96 	{
     97 		return (int)floor(x);
     98 	}
     99 
    100 	inline int ceilFix4(int x)
    101 	{
    102 		return (x + 0xF) & 0xFFFFFFF0;
    103 	}
    104 
    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 
    147 	inline float exp2(float x)
    148 	{
    149 		return exp2f(x);
    150 	}
    151 
    152 	inline int exp2(int x)
    153 	{
    154 		return 1 << x;
    155 	}
    156 
    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 
    168 	inline int ilog2(float x)
    169 	{
    170 		unsigned int y = *(unsigned int*)&x;
    171 
    172 		return ((y & 0x7F800000) >> 23) - 127;
    173 	}
    174 
    175 	inline float log2(float x)
    176 	{
    177 		return logf(x) * 1.44269504f;   // 1.0 / log[e](2)
    178 	}
    179 
    180 	inline bool isPow2(int x)
    181 	{
    182 		return (x & -x) == x;
    183 	}
    184 
    185 	template<class T>
    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 
    194 	inline float clamp01(float x)
    195 	{
    196 		return clamp(x, 0.0f, 1.0f);
    197 	}
    198 
    199 	// Bit-cast of a floating-point value into a two's complement integer representation.
    200 	// This makes floating-point values comparable as integers.
    201 	inline int32_t float_as_twos_complement(float f)
    202 	{
    203 		// IEEE-754 floating-point numbers are sorted by magnitude in the same way as integers,
    204 		// except negative values are like one's complement integers. Convert them to two's complement.
    205 		int32_t i = bit_cast<int32_t>(f);
    206 		return (i < 0) ? (0x7FFFFFFFu - i) : i;
    207 	}
    208 
    209 	// 'Safe' clamping operation which always returns a value between min and max (inclusive).
    210 	inline float clamp_s(float x, float min, float max)
    211 	{
    212 		// NaN values can't be compared directly
    213 		if(float_as_twos_complement(x) < float_as_twos_complement(min)) x = min;
    214 		if(float_as_twos_complement(x) > float_as_twos_complement(max)) x = max;
    215 
    216 		return x;
    217 	}
    218 
    219 	inline int ceilPow2(int x)
    220 	{
    221 		int i = 1;
    222 
    223 		while(i < x)
    224 		{
    225 			i <<= 1;
    226 		}
    227 
    228 		return i;
    229 	}
    230 
    231 	inline int floorDiv(int a, int b)
    232 	{
    233 		return a / b + ((a % b) >> 31);
    234 	}
    235 
    236 	inline int floorMod(int a, int b)
    237 	{
    238 		int r = a % b;
    239 		return r + ((r >> 31) & b);
    240 	}
    241 
    242 	inline int ceilDiv(int a, int b)
    243 	{
    244 		return a / b - (-(a % b) >> 31);
    245 	}
    246 
    247 	inline int ceilMod(int a, int b)
    248 	{
    249 		int r = a % b;
    250 		return r - ((-r >> 31) & b);
    251 	}
    252 
    253 	template<const int n>
    254 	inline unsigned int unorm(float x)
    255 	{
    256 		static const unsigned int max = 0xFFFFFFFF >> (32 - n);
    257 		static const float maxf = static_cast<float>(max);
    258 
    259 		if(x >= 1.0f)
    260 		{
    261 			return max;
    262 		}
    263 		else if(x <= 0.0f)
    264 		{
    265 			return 0;
    266 		}
    267 		else
    268 		{
    269 			return static_cast<unsigned int>(maxf * x + 0.5f);
    270 		}
    271 	}
    272 
    273 	template<const int n>
    274 	inline int snorm(float x)
    275 	{
    276 		static const unsigned int min = 0x80000000 >> (32 - n);
    277 		static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
    278 		static const float maxf = static_cast<float>(max);
    279 		static const unsigned int range = 0xFFFFFFFF >> (32 - n);
    280 
    281 		if(x >= 0.0f)
    282 		{
    283 			if(x >= 1.0f)
    284 			{
    285 				return max;
    286 			}
    287 			else
    288 			{
    289 				return static_cast<int>(maxf * x + 0.5f);
    290 			}
    291 		}
    292 		else
    293 		{
    294 			if(x <= -1.0f)
    295 			{
    296 				return min;
    297 			}
    298 			else
    299 			{
    300 				return static_cast<int>(maxf * x - 0.5f) & range;
    301 			}
    302 		}
    303 	}
    304 
    305 	template<const int n>
    306 	inline unsigned int ucast(float x)
    307 	{
    308 		static const unsigned int max = 0xFFFFFFFF >> (32 - n);
    309 		static const float maxf = static_cast<float>(max);
    310 
    311 		if(x >= maxf)
    312 		{
    313 			return max;
    314 		}
    315 		else if(x <= 0.0f)
    316 		{
    317 			return 0;
    318 		}
    319 		else
    320 		{
    321 			return static_cast<unsigned int>(x + 0.5f);
    322 		}
    323 	}
    324 
    325 	template<const int n>
    326 	inline int scast(float x)
    327 	{
    328 		static const unsigned int min = 0x80000000 >> (32 - n);
    329 		static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
    330 		static const float maxf = static_cast<float>(max);
    331 		static const float minf = static_cast<float>(min);
    332 		static const unsigned int range = 0xFFFFFFFF >> (32 - n);
    333 
    334 		if(x > 0.0f)
    335 		{
    336 			if(x >= maxf)
    337 			{
    338 				return max;
    339 			}
    340 			else
    341 			{
    342 				return static_cast<int>(x + 0.5f);
    343 			}
    344 		}
    345 		else
    346 		{
    347 			if(x <= -minf)
    348 			{
    349 				return min;
    350 			}
    351 			else
    352 			{
    353 				return static_cast<int>(x - 0.5f) & range;
    354 			}
    355 		}
    356 	}
    357 
    358 	inline float sRGBtoLinear(float c)
    359 	{
    360 		if(c <= 0.04045f)
    361 		{
    362 			return c * 0.07739938f;   // 1.0f / 12.92f;
    363 		}
    364 		else
    365 		{
    366 			return powf((c + 0.055f) * 0.9478673f, 2.4f);   // 1.0f / 1.055f
    367 		}
    368 	}
    369 
    370 	inline float linearToSRGB(float c)
    371 	{
    372 		if(c <= 0.0031308f)
    373 		{
    374 			return c * 12.92f;
    375 		}
    376 		else
    377 		{
    378 			return 1.055f * powf(c, 0.4166667f) - 0.055f;   // 1.0f / 2.4f
    379 		}
    380 	}
    381 
    382 	unsigned char sRGB8toLinear8(unsigned char value);
    383 
    384 	uint64_t FNV_1a(const unsigned char *data, int size);   // Fowler-Noll-Vo hash function
    385 
    386 	// Round up to the next multiple of alignment
    387 	template<typename T>
    388 	inline T align(T value, unsigned int alignment)
    389 	{
    390 		return ((value + alignment - 1) / alignment) * alignment;
    391 	}
    392 
    393 	template<unsigned int alignment, typename T>
    394 	inline T align(T value)
    395 	{
    396 		return ((value + alignment - 1) / alignment) * alignment;
    397 	}
    398 
    399 	inline int clampToSignedInt(unsigned int x)
    400 	{
    401 		return static_cast<int>(min(x, 0x7FFFFFFFu));
    402 	}
    403 }
    404 
    405 #endif   // sw_Math_hpp
    406