blob: a9955616b4b4b4ad4acea13bdb78198c859fb9bd [file] [log] [blame]
// SwiftShader Software Renderer
//
// Copyright(c) 2005-2011 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//
#ifndef sw_Math_hpp
#define sw_Math_hpp
#include "Types.hpp"
#include <math.h>
#include <intrin.h>
namespace sw
{
extern const float M_PI;
extern const float M_PI_180;
extern const float M_180_PI;
extern const float M_2PI;
extern const float M_PI_2;
inline float rad(float deg)
{
return deg * M_PI_180;
}
inline float deg(float rad)
{
return rad * M_180_PI;
}
inline float sin(float x)
{
return sinf(x);
}
inline float asin(float x)
{
return asinf(x);
}
inline float sinh(float x)
{
return sinhf(x);
}
inline float cos(float x)
{
return cosf(x);
}
inline float acos(float x)
{
return acosf(x);
}
inline float cosh(float x)
{
return coshf(x);
}
inline float tan(float x)
{
return tanf(x);
}
inline float cot(float x)
{
return 1.0f / tan(x);
}
inline float atan(float x)
{
return atanf(x);
}
inline float tanh(float x)
{
return tanhf(x);
}
inline float sqrt(float x)
{
return sqrtf(x);
}
inline float exp(float x)
{
return expf(x);
}
inline float exp2(float x)
{
static const float ln2 = logf(2);
return exp(ln2 * x);
}
inline float pow(float x, float y)
{
return powf(x, y);
}
inline float pow2(float x)
{
return x * x;
}
inline float abs(float x)
{
return fabsf(x);
}
#undef min
#undef max
inline float max(float a, float b)
{
return a > b ? a : b;
}
inline float min(float a, float b)
{
return a < b ? a : b;
}
inline float max(float a, float b, float c)
{
return max(max(a, b), c);
}
inline float min(float a, float b, float c)
{
return min(min(a, b), c);
}
inline float max(float a, float b, float c, float d)
{
return max(max(a, b), max(c, d));
}
inline float min(float a, float b, float c, float d)
{
return min(min(a, b), min(c, d));
}
inline int max(int a, int b)
{
return a > b ? a : b;
}
inline int min(int a, int b)
{
return a < b ? a : b;
}
inline int max(int a, int b, int c)
{
return max(max(a, b), c);
}
inline int min(int a, int b, int c)
{
return min(min(a, b), c);
}
inline int max(int a, int b, int c, int d)
{
return max(max(a, b), max(c, d));
}
inline int min(int a, int b, int c, int d)
{
return min(min(a, b), min(c, d));
}
template<class T>
inline void swap(T &a, T &b)
{
T t = a;
a = b;
b = t;
}
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 int exp2(int x)
{
return 1 << x;
}
inline unsigned long log2(int x)
{
unsigned long y;
_BitScanReverse(&y, x);
return y;
}
inline int ilog2(float x)
{
unsigned int y = *(unsigned int*)&x;
return ((y & 0x7F800000) >> 23) - 127;
}
inline float log2(float x)
{
unsigned int y = (*(unsigned int*)&x);
return (float)((y & 0x7F800000) >> 23) - 127 + (float)((*(unsigned int*)&x) & 0x007FFFFF) / 16777216.0f;
}
inline bool isPow2(int x)
{
return (x & -x) == x;
}
template<class T>
inline T clamp(T x, T a, T b)
{
if(x < a) x = a;
if(x > b) x = b;
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)
{
const unsigned int max = 0xFFFFFFFF >> (32 - n);
if(x > 1)
{
return max;
}
else if(x < 0)
{
return 0;
}
else
{
return (unsigned int)(max * x + 0.5f);
}
}
template<const int n>
inline int snorm(float x)
{
const unsigned int min = 0x80000000 >> (32 - n);
const unsigned int max = 0xFFFFFFFF >> (32 - n + 1);
const unsigned int range = 0xFFFFFFFF >> (32 - n);
if(x > 0)
{
if(x > 1)
{
return max;
}
else
{
return (int)(max * x + 0.5f);
}
}
else
{
if(x < -1)
{
return min;
}
else
{
return (int)(max * x - 0.5f) & range;
}
}
}
inline float sRGBtoLinear(float c)
{
if(c <= 0.04045f)
{
return c * 0.07739938f; // 1.0f / 12.92f;
}
else
{
return powf((c + 0.055f) * 0.9478673f, 2.4f); // 1.0f / 1.055f
}
}
inline float linearToSRGB(float c)
{
if(c <= 0.0031308f)
{
return c * 12.92f;
}
else
{
return 1.055f * powf(c, 0.4166667f) - 0.055f; // 1.0f / 2.4f
}
}
int64_t FNV_1(const unsigned char *data, int size); // Fowler-Noll-Vo hash function
}
#endif // sw_Math_hpp