mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			531 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			531 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
| ===========================================================================
 | |
| The Open Game Libraries.
 | |
| Copyright (C) 2007-2010 Lusito Software
 | |
| 
 | |
| Author:  Santo Pfingsten (TTK-Bandit)
 | |
| Purpose: Math namespace
 | |
| -----------------------------------------
 | |
| 
 | |
| This software is provided 'as-is', without any express or implied
 | |
| warranty. In no event will the authors be held liable for any damages
 | |
| arising from the use of this software.
 | |
| 
 | |
| Permission is granted to anyone to use this software for any purpose,
 | |
| including commercial applications, and to alter it and redistribute it
 | |
| freely, subject to the following restrictions:
 | |
| 
 | |
| 1. The origin of this software must not be misrepresented; you must not
 | |
|    claim that you wrote the original software. If you use this software
 | |
|    in a product, an acknowledgment in the product documentation would be
 | |
|    appreciated but is not required.
 | |
| 
 | |
| 2. Altered source versions must be plainly marked as such, and must not be
 | |
|    misrepresented as being the original software.
 | |
| 
 | |
| 3. This notice may not be removed or altered from any source distribution.
 | |
| ===========================================================================
 | |
| */
 | |
| 
 | |
| #ifndef __OG_MATH_INL__
 | |
| #define __OG_MATH_INL__
 | |
| 
 | |
| namespace og {
 | |
| 
 | |
| /*
 | |
| ==============================================================================
 | |
| 
 | |
|   Math
 | |
| 
 | |
| ==============================================================================
 | |
| */
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Abs
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::Abs( int i ) {
 | |
| #if 1
 | |
| 	if ( i & 0x80000000 )
 | |
| 		return 0x80000000 - (i & MASK_SIGNED);
 | |
| 	return i;
 | |
| #else
 | |
|    int y = x >> 31;
 | |
|    return ( ( x ^ y ) - y );
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Fabs
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Fabs( float f ) {
 | |
| #if 1
 | |
| 	uInt *pf = reinterpret_cast<uInt*>(&f);
 | |
| 	*(pf) &= MASK_SIGNED;
 | |
| 	return f;
 | |
| #else
 | |
| 	return fabsf( f );
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Round
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Round( float f ) {
 | |
| 	return floorf( f + 0.5f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Floor
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Floor( float f ) {
 | |
| 	return floorf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Ceil
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Ceil( float f ) {
 | |
| 	return ceilf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Ftoi
 | |
| 
 | |
| ok since this is SSE, why should the other ftoi be the faster one ?
 | |
| and: we might need to add a check for SSE extensions..
 | |
| because sse isn't *really* faster (I actually read that GCC does not handle
 | |
| SSE extensions perfectly. I'll find the link and send it to you when you're online)
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::Ftoi( float f ) {
 | |
| 	//! @todo	needs testing
 | |
| 	// note: sse function cvttss2si
 | |
| #if OG_ASM_MSVC
 | |
| 	int i;
 | |
| #if defined(OG_FTOI_USE_SSE)
 | |
| 	if( SysInfo::cpu.general.SSE ) {
 | |
| 		__asm cvttss2si	eax, f
 | |
| 		__asm mov		i, eax
 | |
| 		return i;
 | |
| 	} else
 | |
| #endif
 | |
| 	{
 | |
| 		__asm fld		f
 | |
| 		__asm fistp		i
 | |
| 		//__asm mov eax, i // do we need this ? O_o
 | |
| 	}
 | |
| 	return i;
 | |
| #elif OG_ASM_GNU
 | |
| 	int i;
 | |
| #if defined(OG_FTOI_USE_SSE)
 | |
| 	if( SysInfo::cpu.general.SSE ) {
 | |
| 		__asm__ __volatile__( "cvttss2si %1    \n\t"
 | |
| 			: "=m" (i)
 | |
| 			: "m" (f)
 | |
| 		);
 | |
| 	} else
 | |
| #endif
 | |
| 	{
 | |
| 		__asm__ __volatile__( "flds %1    \n\t"
 | |
| 							  "fistpl %0  \n\t"
 | |
| 			: "=m" (i)
 | |
| 			: "m" (f)
 | |
| 		);
 | |
| 	}
 | |
| 	return i;
 | |
| #else
 | |
| 	// we use c++ cast instead of c cast (not sure why id did that)
 | |
| 	return static_cast<int>(f);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::FtoiFast
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::FtoiFast( float f ) {
 | |
| #if OG_ASM_MSVC
 | |
| 	int i;
 | |
| 	__asm fld		f
 | |
| 	__asm fistp		i
 | |
| 	//__asm mov eax, i // do we need this ? O_o
 | |
| 	return i;
 | |
| #elif OG_ASM_GNU
 | |
| 	int i;
 | |
| 	__asm__ __volatile__( "flds %1    \n\t"
 | |
| 						  "fistpl %0  \n\t"
 | |
| 		: "=m" (i)
 | |
| 		: "m" (f)
 | |
| 	);
 | |
| 	return i;
 | |
| #else
 | |
| 	// we use c++ cast instead of c cast (not sure why id did that)
 | |
| 	return static_cast<int>(f);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Ftol
 | |
| ================
 | |
| */
 | |
| OG_INLINE long Math::Ftol( float f ) {
 | |
| #if OG_ASM_MSVC
 | |
| 	long i;
 | |
| 	__asm fld		f
 | |
| 	__asm fistp		i
 | |
| 	//__asm mov eax, i // do we need this ? O_o
 | |
| 	return i;
 | |
| #elif OG_ASM_GNU
 | |
| 	long i;
 | |
| 	__asm__ __volatile__( "flds %1    \n\t"
 | |
| 						  "fistpl %0  \n\t"
 | |
| 		: "=m" (i)
 | |
| 		: "m" (f)
 | |
| 	);
 | |
| 	return i;
 | |
| #else
 | |
| 	// we use c++ cast instead of c cast (not sure why id did that)
 | |
| 	return static_cast<long>(f);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Sign
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Sign( float f )	{
 | |
| 	if ( f > 0.0f )
 | |
| 		return 1.0f;
 | |
| 	if ( f < 0.0f )
 | |
| 		return -1.0f;
 | |
| 	return 0.0f;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Fmod
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Fmod( float numerator, float denominator ) {
 | |
| 	return fmodf( numerator, denominator );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Modf
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Modf( float f, float& i ) {
 | |
| 	return modff( f, &i );
 | |
| }
 | |
| OG_INLINE float Math::Modf( float f ) {
 | |
| 	float i;
 | |
| 	return modff( f, &i );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Sqrt
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Sqrt( float f ) {
 | |
| 	return sqrtf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::InvSqrt
 | |
| 
 | |
| Cannot be 0.0f
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::InvSqrt( float f ) {
 | |
| 	OG_ASSERT( f != 0.0f );
 | |
| 	return 1.0f / sqrtf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::RSqrt
 | |
| 
 | |
| Can be 0.0f
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::RSqrt( float f ) {
 | |
| 	float g = 0.5f * f;
 | |
| 	int i = *reinterpret_cast<int *>(&f);
 | |
| 
 | |
| 	// do a guess
 | |
| 	i = 0x5f375a86 - ( i>>1 );
 | |
| 	f = *reinterpret_cast<float *>(&i);
 | |
| 
 | |
| 	// Newtons calculation
 | |
| 	f = f * ( 1.5f - g * f * f );
 | |
| 	return f;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Log/Log2/Log10
 | |
| 
 | |
| Log of 0 is bad.
 | |
| I've also heard you're not really
 | |
| supposed to do log of negatives, yet
 | |
| they work fine.
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Log( float f ) {
 | |
| 	OG_ASSERT( f != 0.0f );
 | |
| 	return logf( f );
 | |
| }
 | |
| OG_INLINE float Math::Log2( float f ) {
 | |
| 	OG_ASSERT( f != 0.0f );
 | |
| 	return INV_LN_2 * logf( f );
 | |
| }
 | |
| OG_INLINE float Math::Log10( float f ) {
 | |
| 	OG_ASSERT( f != 0.0f );
 | |
| 	return INV_LN_10 * logf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Pow
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Pow( float base, float exp ) {
 | |
| 	return powf( base, exp );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Exp
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Exp( float f ) {
 | |
| 	return expf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::IsPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE bool Math::IsPowerOfTwo( int x ) {
 | |
| 	// This is the faster of the two known methods
 | |
| 	// with the x > 0 check moved to the beginning
 | |
| 	return x > 0 && ( x & ( x - 1 ) ) == 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::HigherPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::HigherPowerOfTwo( int x ) {
 | |
| 	x--;
 | |
| 	x |= x >> 1;
 | |
| 	x |= x >> 2;
 | |
| 	x |= x >> 4;
 | |
| 	x |= x >> 8;
 | |
| 	x |= x >> 16;
 | |
| 	return x + 1;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::LowerPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::LowerPowerOfTwo( int x ) {
 | |
| 	return HigherPowerOfTwo( x ) >> 1;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::FloorPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::FloorPowerOfTwo( int x ) {
 | |
| 	return IsPowerOfTwo( x ) ? x : LowerPowerOfTwo( x );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::CeilPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::CeilPowerOfTwo( int x ) {
 | |
| 	return IsPowerOfTwo( x ) ? x : HigherPowerOfTwo( x );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::ClosestPowerOfTwo
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::ClosestPowerOfTwo( int x ) {
 | |
| 	if ( IsPowerOfTwo( x ) )
 | |
| 		return x;
 | |
| 	int high = HigherPowerOfTwo( x );
 | |
| 	int low = high >> 1;
 | |
| 	return ((high-x) < (x-low)) ? high : low;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Digits
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::Digits( int x ) {
 | |
| 	int digits = 1;
 | |
| 	int step = 10;
 | |
| 	while (step <= x) {
 | |
| 		digits++;
 | |
| 		step *= 10;
 | |
| 	}
 | |
| 	return digits;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Sin/ASin
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Sin( float f ) {
 | |
| 	return sinf( f );
 | |
| }
 | |
| OG_INLINE float Math::ASin( float f ) {
 | |
| 	if ( f <= -1.0f )
 | |
| 		return -HALF_PI;
 | |
| 	if ( f >= 1.0f )
 | |
| 		return HALF_PI;
 | |
| 	return asinf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Cos/ACos
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Cos( float f ) {
 | |
| 	return cosf( f );
 | |
| }
 | |
| OG_INLINE float Math::ACos( float f ) {
 | |
| 	if ( f <= -1.0f )
 | |
| 		return PI;
 | |
| 	if ( f >= 1.0f )
 | |
| 		return 0.0f;
 | |
| 	return acosf( f );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Tan/ATan
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Tan( float f ) {
 | |
| 	return tanf( f );
 | |
| }
 | |
| OG_INLINE float Math::ATan( float f ) {
 | |
| 	return atanf( f );
 | |
| }
 | |
| OG_INLINE float Math::ATan( float f1, float f2 ) {
 | |
| 	return atan2f( f1, f2 );
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::SinCos
 | |
| ================
 | |
| */
 | |
| OG_INLINE void Math::SinCos( float f, float &s, float &c ) {
 | |
| #if OG_ASM_MSVC
 | |
| 	// sometimes assembler is just waaayy faster
 | |
| 	_asm {
 | |
| 		fld		f
 | |
| 		fsincos
 | |
| 		mov		ecx, c
 | |
| 		mov		edx, s
 | |
| 		fstp	dword ptr [ecx]
 | |
| 		fstp	dword ptr [edx]
 | |
| 	}
 | |
| #elif OG_ASM_GNU
 | |
| 	asm ("fsincos" : "=t" (c), "=u" (s) : "0" (f));
 | |
| #else
 | |
| 	s = Sin(f);
 | |
| 	c = Sqrt( 1.0f - s * s ); // faster than calling Cos(f)
 | |
| #endif
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Deg2Rad
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Deg2Rad( float f ) {
 | |
| 	return f * DEG_TO_RAD;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Rad2Deg
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Rad2Deg( float f ) {
 | |
| 	return f * RAD_TO_DEG;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Square
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Square( float v ) {
 | |
| 	return v * v;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Cube
 | |
| ================
 | |
| */
 | |
| OG_INLINE float Math::Cube( float v ) {
 | |
| 	return v * v * v;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Sec2Ms
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::Sec2Ms( int sec ) {
 | |
| 	return sec * 1000;
 | |
| }
 | |
| 
 | |
| /*
 | |
| ================
 | |
| Math::Ms2Sec
 | |
| ================
 | |
| */
 | |
| OG_INLINE int Math::Ms2Sec( int ms ) {
 | |
| 	return FtoiFast( ms * 0.001f );
 | |
| }
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 |