| // Copyright 2016 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #ifndef sw_Math_hpp | 
 | #define sw_Math_hpp | 
 |  | 
 | #include "Debug.hpp" | 
 | #include "Types.hpp" | 
 |  | 
 | #include <cmath> | 
 | #if defined(_MSC_VER) | 
 | #	include <intrin.h> | 
 | #endif | 
 |  | 
 | namespace sw { | 
 |  | 
 | using std::abs; | 
 |  | 
 | #undef min | 
 | #undef max | 
 |  | 
 | template<class T> | 
 | inline T constexpr max(T a, T b) | 
 | { | 
 | 	return a > b ? a : b; | 
 | } | 
 |  | 
 | template<class T> | 
 | inline constexpr T min(T a, T b) | 
 | { | 
 | 	return a < b ? a : b; | 
 | } | 
 |  | 
 | template<class T> | 
 | inline constexpr T max(T a, T b, T c) | 
 | { | 
 | 	return max(max(a, b), c); | 
 | } | 
 |  | 
 | template<class T> | 
 | inline constexpr T min(T a, T b, T c) | 
 | { | 
 | 	return min(min(a, b), c); | 
 | } | 
 |  | 
 | template<class T> | 
 | inline constexpr T max(T a, T b, T c, T d) | 
 | { | 
 | 	return max(max(a, b), max(c, d)); | 
 | } | 
 |  | 
 | template<class T> | 
 | inline constexpr T min(T a, T b, T c, T d) | 
 | { | 
 | 	return min(min(a, b), min(c, d)); | 
 | } | 
 |  | 
 | template<typename destType, typename sourceType> | 
 | destType bit_cast(const sourceType &source) | 
 | { | 
 | 	union | 
 | 	{ | 
 | 		sourceType s; | 
 | 		destType d; | 
 | 	} sd; | 
 | 	sd.s = source; | 
 | 	return sd.d; | 
 | } | 
 |  | 
 | inline int iround(float x) | 
 | { | 
 | 	return (int)floor(x + 0.5f); | 
 | 	//	return _mm_cvtss_si32(_mm_load_ss(&x));   // FIXME: Demands SSE support | 
 | } | 
 |  | 
 | inline int ifloor(float x) | 
 | { | 
 | 	return (int)floor(x); | 
 | } | 
 |  | 
 | inline int ceilFix4(int x) | 
 | { | 
 | 	return (x + 0xF) & 0xFFFFFFF0; | 
 | } | 
 |  | 
 | inline int ceilInt4(int x) | 
 | { | 
 | 	return (x + 0xF) >> 4; | 
 | } | 
 |  | 
 | #define BITS(x) (        \ | 
 | 	!!((x)&0x80000000) + \ | 
 | 	!!((x)&0xC0000000) + \ | 
 | 	!!((x)&0xE0000000) + \ | 
 | 	!!((x)&0xF0000000) + \ | 
 | 	!!((x)&0xF8000000) + \ | 
 | 	!!((x)&0xFC000000) + \ | 
 | 	!!((x)&0xFE000000) + \ | 
 | 	!!((x)&0xFF000000) + \ | 
 | 	!!((x)&0xFF800000) + \ | 
 | 	!!((x)&0xFFC00000) + \ | 
 | 	!!((x)&0xFFE00000) + \ | 
 | 	!!((x)&0xFFF00000) + \ | 
 | 	!!((x)&0xFFF80000) + \ | 
 | 	!!((x)&0xFFFC0000) + \ | 
 | 	!!((x)&0xFFFE0000) + \ | 
 | 	!!((x)&0xFFFF0000) + \ | 
 | 	!!((x)&0xFFFF8000) + \ | 
 | 	!!((x)&0xFFFFC000) + \ | 
 | 	!!((x)&0xFFFFE000) + \ | 
 | 	!!((x)&0xFFFFF000) + \ | 
 | 	!!((x)&0xFFFFF800) + \ | 
 | 	!!((x)&0xFFFFFC00) + \ | 
 | 	!!((x)&0xFFFFFE00) + \ | 
 | 	!!((x)&0xFFFFFF00) + \ | 
 | 	!!((x)&0xFFFFFF80) + \ | 
 | 	!!((x)&0xFFFFFFC0) + \ | 
 | 	!!((x)&0xFFFFFFE0) + \ | 
 | 	!!((x)&0xFFFFFFF0) + \ | 
 | 	!!((x)&0xFFFFFFF8) + \ | 
 | 	!!((x)&0xFFFFFFFC) + \ | 
 | 	!!((x)&0xFFFFFFFE) + \ | 
 | 	!!((x)&0xFFFFFFFF)) | 
 |  | 
 | inline unsigned long log2i(int x) | 
 | { | 
 | #if defined(_MSC_VER) | 
 | 	unsigned long y; | 
 | 	_BitScanReverse(&y, x); | 
 | 	return y; | 
 | #else | 
 | 	return 31 - __builtin_clz(x); | 
 | #endif | 
 | } | 
 |  | 
 | inline bool isPow2(int x) | 
 | { | 
 | 	return (x & -x) == x; | 
 | } | 
 |  | 
 | template<class T> | 
 | inline T clamp(T x, T a, T b) | 
 | { | 
 | 	ASSERT(a <= b); | 
 | 	if(x < a) x = a; | 
 | 	if(x > b) x = b; | 
 |  | 
 | 	return x; | 
 | } | 
 |  | 
 | inline float clamp01(float x) | 
 | { | 
 | 	return clamp(x, 0.0f, 1.0f); | 
 | } | 
 |  | 
 | // Bit-cast of a floating-point value into a two's complement integer representation. | 
 | // This makes floating-point values comparable as integers. | 
 | inline int32_t float_as_twos_complement(float f) | 
 | { | 
 | 	// IEEE-754 floating-point numbers are sorted by magnitude in the same way as integers, | 
 | 	// except negative values are like one's complement integers. Convert them to two's complement. | 
 | 	int32_t i = bit_cast<int32_t>(f); | 
 | 	return (i < 0) ? (0x7FFFFFFFu - i) : i; | 
 | } | 
 |  | 
 | // 'Safe' clamping operation which always returns a value between min and max (inclusive). | 
 | inline float clamp_s(float x, float min, float max) | 
 | { | 
 | 	// NaN values can't be compared directly | 
 | 	if(float_as_twos_complement(x) < float_as_twos_complement(min)) x = min; | 
 | 	if(float_as_twos_complement(x) > float_as_twos_complement(max)) x = max; | 
 |  | 
 | 	return x; | 
 | } | 
 |  | 
 | inline int ceilPow2(int x) | 
 | { | 
 | 	int i = 1; | 
 |  | 
 | 	while(i < x) | 
 | 	{ | 
 | 		i <<= 1; | 
 | 	} | 
 |  | 
 | 	return i; | 
 | } | 
 |  | 
 | inline int floorDiv(int a, int b) | 
 | { | 
 | 	return a / b + ((a % b) >> 31); | 
 | } | 
 |  | 
 | inline int floorMod(int a, int b) | 
 | { | 
 | 	int r = a % b; | 
 | 	return r + ((r >> 31) & b); | 
 | } | 
 |  | 
 | inline int ceilDiv(int a, int b) | 
 | { | 
 | 	return a / b - (-(a % b) >> 31); | 
 | } | 
 |  | 
 | inline int ceilMod(int a, int b) | 
 | { | 
 | 	int r = a % b; | 
 | 	return r - ((-r >> 31) & b); | 
 | } | 
 |  | 
 | template<const int n> | 
 | inline unsigned int unorm(float x) | 
 | { | 
 | 	static const unsigned int max = 0xFFFFFFFF >> (32 - n); | 
 | 	static const float maxf = static_cast<float>(max); | 
 |  | 
 | 	if(x >= 1.0f) | 
 | 	{ | 
 | 		return max; | 
 | 	} | 
 | 	else if(x <= 0.0f) | 
 | 	{ | 
 | 		return 0; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		return static_cast<unsigned int>(maxf * x + 0.5f); | 
 | 	} | 
 | } | 
 |  | 
 | template<const int n> | 
 | inline int snorm(float x) | 
 | { | 
 | 	static const unsigned int min = 0x80000000 >> (32 - n); | 
 | 	static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); | 
 | 	static const float maxf = static_cast<float>(max); | 
 | 	static const unsigned int range = 0xFFFFFFFF >> (32 - n); | 
 |  | 
 | 	if(x >= 0.0f) | 
 | 	{ | 
 | 		if(x >= 1.0f) | 
 | 		{ | 
 | 			return max; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return static_cast<int>(maxf * x + 0.5f); | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		if(x <= -1.0f) | 
 | 		{ | 
 | 			return min; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return static_cast<int>(maxf * x - 0.5f) & range; | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | template<const int n> | 
 | inline unsigned int ucast(float x) | 
 | { | 
 | 	static const unsigned int max = 0xFFFFFFFF >> (32 - n); | 
 | 	static const float maxf = static_cast<float>(max); | 
 |  | 
 | 	if(x >= maxf) | 
 | 	{ | 
 | 		return max; | 
 | 	} | 
 | 	else if(x <= 0.0f) | 
 | 	{ | 
 | 		return 0; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		return static_cast<unsigned int>(x + 0.5f); | 
 | 	} | 
 | } | 
 |  | 
 | template<const int n> | 
 | inline int scast(float x) | 
 | { | 
 | 	static const unsigned int min = 0x80000000 >> (32 - n); | 
 | 	static const unsigned int max = 0xFFFFFFFF >> (32 - n + 1); | 
 | 	static const float maxf = static_cast<float>(max); | 
 | 	static const float minf = static_cast<float>(min); | 
 | 	static const unsigned int range = 0xFFFFFFFF >> (32 - n); | 
 |  | 
 | 	if(x > 0.0f) | 
 | 	{ | 
 | 		if(x >= maxf) | 
 | 		{ | 
 | 			return max; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return static_cast<int>(x + 0.5f); | 
 | 		} | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		if(x <= -minf) | 
 | 		{ | 
 | 			return min; | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			return static_cast<int>(x - 0.5f) & range; | 
 | 		} | 
 | 	} | 
 | } | 
 |  | 
 | inline float sRGBtoLinear(float c) | 
 | { | 
 | 	if(c <= 0.04045f) | 
 | 	{ | 
 | 		return c / 12.92f; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		return powf((c + 0.055f) / 1.055f, 2.4f); | 
 | 	} | 
 | } | 
 |  | 
 | inline float linearToSRGB(float c) | 
 | { | 
 | 	if(c <= 0.0031308f) | 
 | 	{ | 
 | 		return c * 12.92f; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		return 1.055f * powf(c, 1.0f / 2.4f) - 0.055f; | 
 | 	} | 
 | } | 
 |  | 
 | unsigned char sRGB8toLinear8(unsigned char value); | 
 |  | 
 | uint64_t FNV_1a(const unsigned char *data, int size);  // Fowler-Noll-Vo hash function | 
 |  | 
 | // Round up to the next multiple of alignment | 
 | template<typename T> | 
 | inline T align(T value, unsigned int alignment) | 
 | { | 
 | 	return ((value + alignment - 1) / alignment) * alignment; | 
 | } | 
 |  | 
 | template<unsigned int alignment, typename T> | 
 | inline T align(T value) | 
 | { | 
 | 	return ((value + alignment - 1) / alignment) * alignment; | 
 | } | 
 |  | 
 | inline int clampToSignedInt(unsigned int x) | 
 | { | 
 | 	return static_cast<int>(min(x, 0x7FFFFFFFu)); | 
 | } | 
 |  | 
 | // Convert floating value v to fixed point with p digits after the decimal point | 
 | constexpr int toFixedPoint(float v, int p) | 
 | { | 
 | 	return static_cast<int>(v * (1 << p)); | 
 | } | 
 |  | 
 | }  // namespace sw | 
 |  | 
 | #endif  // sw_Math_hpp |