| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Copyright 2013 Dolphin Emulator Project
 | 
					
						
							|  |  |  | // Licensed under GPLv2
 | 
					
						
							|  |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-10 13:54:46 -05:00
										 |  |  | #pragma once
 | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-20 04:11:52 +01:00
										 |  |  | #include <cstdlib>
 | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "Common/Common.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-12 21:58:32 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | namespace MathUtil | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-04 20:43:07 -05:00
										 |  |  | template<class T> | 
					
						
							| 
									
										
										
										
											2014-02-05 04:04:35 -05:00
										 |  |  | inline void Clamp(T* val, const T& min, const T& max) | 
					
						
							| 
									
										
										
										
											2014-02-04 20:43:07 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-02-05 04:04:35 -05:00
										 |  |  | 	if (*val < min) | 
					
						
							|  |  |  | 		*val = min; | 
					
						
							|  |  |  | 	else if (*val > max) | 
					
						
							|  |  |  | 		*val = max; | 
					
						
							| 
									
										
										
										
											2014-02-04 20:43:07 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-07-15 00:42:33 +12:00
										 |  |  | template<class T> | 
					
						
							|  |  |  | inline T Clamp(const T val, const T& min, const T& max) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	T ret = val; | 
					
						
							|  |  |  | 	Clamp(&ret, min, max); | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | // The most significant bit of the fraction is an is-quiet bit on all architectures we care about.
 | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | static const u64 DOUBLE_SIGN = 0x8000000000000000ULL, | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  |                  DOUBLE_EXP  = 0x7FF0000000000000ULL, | 
					
						
							|  |  |  |                  DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL, | 
					
						
							|  |  |  |                  DOUBLE_ZERO = 0x0000000000000000ULL, | 
					
						
							|  |  |  |                  DOUBLE_QBIT = 0x0008000000000000ULL; | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-25 18:14:29 +00:00
										 |  |  | static const u32 FLOAT_SIGN = 0x80000000, | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  |                  FLOAT_EXP  = 0x7F800000, | 
					
						
							|  |  |  |                  FLOAT_FRAC = 0x007FFFFF, | 
					
						
							|  |  |  |                  FLOAT_ZERO = 0x00000000; | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | union IntDouble { | 
					
						
							|  |  |  | 	double d; | 
					
						
							|  |  |  | 	u64 i; | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	explicit IntDouble(u64 _i) : i(_i) {} | 
					
						
							|  |  |  | 	explicit IntDouble(double _d) : d(_d) {} | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | union IntFloat { | 
					
						
							|  |  |  | 	float f; | 
					
						
							|  |  |  | 	u32 i; | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	explicit IntFloat(u32 _i) : i(_i) {} | 
					
						
							|  |  |  | 	explicit IntFloat(float _f) : f(_f) {} | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | inline bool IsINF(double d) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntDouble x(d); | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	return (x.i & ~DOUBLE_SIGN) == DOUBLE_EXP; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | inline bool IsNAN(double d) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntDouble x(d); | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && | 
					
						
							|  |  |  | 	       ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO); | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline bool IsQNAN(double d) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntDouble x(d); | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && | 
					
						
							|  |  |  | 	       ((x.i & DOUBLE_QBIT) == DOUBLE_QBIT); | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline bool IsSNAN(double d) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntDouble x(d); | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	return ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && | 
					
						
							|  |  |  | 	       ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) && | 
					
						
							|  |  |  | 	       ((x.i & DOUBLE_QBIT) == DOUBLE_ZERO); | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | inline float FlushToZero(float f) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntFloat x(f); | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 	if ((x.i & FLOAT_EXP) == 0) | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 		x.i &= FLOAT_SIGN;  // turn into signed zero
 | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 	return x.f; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-24 22:05:53 +02:00
										 |  |  | inline double FlushToZero(double d) | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-03-23 10:24:06 +01:00
										 |  |  | 	IntDouble x(d); | 
					
						
							| 
									
										
										
										
											2013-10-24 22:05:53 +02:00
										 |  |  | 	if ((x.i & DOUBLE_EXP) == 0) | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 		x.i &= DOUBLE_SIGN;  // turn into signed zero
 | 
					
						
							| 
									
										
										
										
											2014-03-09 19:34:58 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 	return x.d; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | enum PPCFpClass | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PPC_FPCLASS_QNAN = 0x11, | 
					
						
							|  |  |  | 	PPC_FPCLASS_NINF = 0x9, | 
					
						
							|  |  |  | 	PPC_FPCLASS_NN   = 0x8, | 
					
						
							|  |  |  | 	PPC_FPCLASS_ND   = 0x18, | 
					
						
							|  |  |  | 	PPC_FPCLASS_NZ   = 0x12, | 
					
						
							|  |  |  | 	PPC_FPCLASS_PZ   = 0x2, | 
					
						
							|  |  |  | 	PPC_FPCLASS_PD   = 0x14, | 
					
						
							|  |  |  | 	PPC_FPCLASS_PN   = 0x4, | 
					
						
							|  |  |  | 	PPC_FPCLASS_PINF = 0x5, | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | // Uses PowerPC conventions for the return value, so it can be easily
 | 
					
						
							|  |  |  | // used directly in CPU emulation.
 | 
					
						
							| 
									
										
										
										
											2011-05-25 18:14:29 +00:00
										 |  |  | u32 ClassifyDouble(double dvalue); | 
					
						
							| 
									
										
										
										
											2009-06-15 21:10:11 +00:00
										 |  |  | // More efficient float version.
 | 
					
						
							| 
									
										
										
										
											2011-05-25 18:14:29 +00:00
										 |  |  | u32 ClassifyFloat(float fvalue); | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 00:51:24 +00:00
										 |  |  | template<class T> | 
					
						
							|  |  |  | struct Rectangle | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	T left; | 
					
						
							|  |  |  | 	T top; | 
					
						
							|  |  |  | 	T right; | 
					
						
							|  |  |  | 	T bottom; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-08 07:39:36 +00:00
										 |  |  | 	Rectangle() | 
					
						
							|  |  |  | 	{ } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Rectangle(T theLeft, T theTop, T theRight, T theBottom) | 
					
						
							|  |  |  | 		: left(theLeft), top(theTop), right(theRight), bottom(theBottom) | 
					
						
							|  |  |  | 	{ } | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-09 19:22:21 +01:00
										 |  |  | 	bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } | 
					
						
							| 
									
										
										
										
											2011-03-08 07:39:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-15 00:51:24 +00:00
										 |  |  | 	T GetWidth() const { return abs(right - left); } | 
					
						
							|  |  |  | 	T GetHeight() const { return abs(bottom - top); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If the rectangle is in a coordinate system with a lower-left origin, use
 | 
					
						
							|  |  |  | 	// this Clamp.
 | 
					
						
							|  |  |  | 	void ClampLL(T x1, T y1, T x2, T y2) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (left < x1) left = x1; | 
					
						
							|  |  |  | 		if (right > x2) right = x2; | 
					
						
							|  |  |  | 		if (top > y1) top = y1; | 
					
						
							|  |  |  | 		if (bottom < y2) bottom = y2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-08 07:39:36 +00:00
										 |  |  | 	// If the rectangle is in a coordinate system with an upper-left origin,
 | 
					
						
							| 
									
										
										
										
											2009-07-15 00:51:24 +00:00
										 |  |  | 	// use this Clamp.
 | 
					
						
							| 
									
										
										
										
											2013-10-29 01:23:17 -04:00
										 |  |  | 	void ClampUL(T x1, T y1, T x2, T y2) | 
					
						
							| 
									
										
										
										
											2009-07-15 00:51:24 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (left < x1) left = x1; | 
					
						
							|  |  |  | 		if (right > x2) right = x2; | 
					
						
							|  |  |  | 		if (top < y1) top = y1; | 
					
						
							|  |  |  | 		if (bottom > y2) bottom = y2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | }  // namespace MathUtil
 | 
					
						
							| 
									
										
										
										
											2009-06-14 10:59:06 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | inline float pow2f(float x) {return x * x;} | 
					
						
							|  |  |  | inline double pow2(double x) {return x * x;} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-28 07:40:18 +00:00
										 |  |  | float MathFloatVectorSum(const std::vector<float>&); | 
					
						
							| 
									
										
										
										
											2008-12-08 04:46:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 18:29:13 -05:00
										 |  |  | #define ROUND_UP(x, a)   (((x) + (a) - 1) & ~((a) - 1))
 | 
					
						
							|  |  |  | #define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
 | 
					
						
							| 
									
										
										
										
											2009-02-22 00:40:52 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 15:48:57 -06:00
										 |  |  | // Rounds down. 0 -> undefined
 | 
					
						
							| 
									
										
										
										
											2014-02-24 10:20:53 +01:00
										 |  |  | inline int Log2(u64 val) | 
					
						
							| 
									
										
										
										
											2013-03-05 03:12:17 -06:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-03-05 15:48:57 -06:00
										 |  |  | #if defined(__GNUC__)
 | 
					
						
							|  |  |  | 	return 63 - __builtin_clzll(val); | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-02 05:21:50 -06:00
										 |  |  | #elif defined(_MSC_VER) && _ARCH_64
 | 
					
						
							| 
									
										
										
										
											2013-03-05 15:48:57 -06:00
										 |  |  | 	unsigned long result = -1; | 
					
						
							|  |  |  | 	_BitScanReverse64(&result, val); | 
					
						
							| 
									
										
										
										
											2013-03-05 03:12:17 -06:00
										 |  |  | 	return result; | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-05 03:12:17 -06:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2014-02-24 10:20:53 +01:00
										 |  |  | 	int result = -1; | 
					
						
							| 
									
										
										
										
											2013-03-05 03:12:17 -06:00
										 |  |  | 	while (val != 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		val >>= 1; | 
					
						
							|  |  |  | 		++result; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return result; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Tiny matrix/vector library.
 | 
					
						
							| 
									
										
										
										
											2011-02-14 02:18:03 +00:00
										 |  |  | // Used for things like Free-Look in the gfx backend.
 | 
					
						
							| 
									
										
										
										
											2009-06-14 11:30:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | class Matrix33 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	static void LoadIdentity(Matrix33 &mtx); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	// set mtx to be a rotation matrix around the x axis
 | 
					
						
							|  |  |  | 	static void RotateX(Matrix33 &mtx, float rad); | 
					
						
							|  |  |  | 	// set mtx to be a rotation matrix around the y axis
 | 
					
						
							|  |  |  | 	static void RotateY(Matrix33 &mtx, float rad); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	// set result = a x b
 | 
					
						
							|  |  |  | 	static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result); | 
					
						
							|  |  |  | 	static void Multiply(const Matrix33 &a, const float vec[3], float result[3]); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	float data[9]; | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class Matrix44 | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	static void LoadIdentity(Matrix44 &mtx); | 
					
						
							|  |  |  | 	static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33); | 
					
						
							|  |  |  | 	static void Set(Matrix44 &mtx, const float mtxArray[16]); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	static void Translate(Matrix44 &mtx, const float vec[3]); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result); | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 21:51:12 -04:00
										 |  |  | 	float data[16]; | 
					
						
							| 
									
										
										
										
											2009-04-19 10:10:45 +00:00
										 |  |  | }; |