www.pudn.com > ZFXMath-latest.zip > BasicMath.h


/// \file
///
/// \if DE
/// @brief Basis-Mathefunktionen und Konstanten.
/// \else
/// @brief Basic math functions and constants.
/// \endif

#ifndef	_ZFXMATH_INCLUDE_BASICMATH_H_
#define	_ZFXMATH_INCLUDE_BASICMATH_H_

#include 

/// \if DE
/// @brief Hauptnamespace
/// \else
/// @brief main namespace
/// \endif
namespace ZFXMath
{
	#undef DELTA
	#undef E
	#undef LOG2_E
	#undef LOG10_E
	#undef LOGE_2
	#undef LOGE_10
	#undef PI
	#undef SQRT_2

	/// \if DE
	/// @brief Genauigkeit
	/// \else
	/// @brief accuracy
	/// \endif
	const double EPSILON = 0.00001;

	/// \if DE
	/// @brief Eulersche Zahl E
	/// \else
	/// @brief mathematical constant e
	/// \endif
	const double E = 2.71828182845904523536;

	/// \if DE
	/// @brief Logarithmus von E zur Basis 2
	/// \else
	/// @brief logarithm of e to the base 2
	/// \endif
	const double LOG2_E = 1.44269504088896340736;

	/// \if DE
	/// @brief Logarithmus von E zur Basis 10
	/// \else
	/// @brief logarithm of e to the base 10
	/// \endif
	const double LOG10_E = 0.434294481903251827651;

	/// \if DE
	/// @brief Logarithmus von 2 zur Basis E
	/// \else
	/// @brief logarithm of 2 to the base e
	/// \endif
	const double LOGE_2 = 0.693147180559945309417;

	/// \if DE
	/// @brief Logarithmus von 10 zur Basis E
	/// \else
	/// @brief logarithm of 10 to the base e
	/// \endif
	const double LOGE_10 = 2.30258509299404568402;

	/// \if DE
	/// @brief Kreiszahl pi
	/// \else
	/// @brief mathematical constant pi
	/// \endif
	const double PI = 3.14159265358979323846;

	/// \if DE
	/// @brief Wurzel aus 2
	/// \else
	/// @brief quareroot of 2
	/// \endif
	const double SQRT_2 = 1.41421356237309504880;

	/// \if DE
	/// @brief Konvertierung von Radian in Grad
	/// \else
	/// @brief conversion from radian to degree
	/// \endif
	template inline T RadToDeg(T& rad)
	{
		// rad * 180° / pi
		return rad * 57.295779513082320876798154814105;
	}

	/// \if DE
	/// @brief Konvertierung von Grad in Radian
	/// \else
	/// @brief conversion from degree to radian
	/// \endif
	template inline T DegToRad(T& degree)
	{
		// degree * pi / 180°
		return degree * 0.017453292519943295769236907684886;
	}

	/// \if DE
	/// @brief Sinus
	/// \else
	/// @brief sine
	/// \endif
	template inline T Sin(const T& rad)
	{
		return ::sin(rad);
	}

	/// \if DE
	/// @brief Kosinus
	/// \else
	/// @brief cosine
	/// \endif
	template inline T Cos(const T& rad)
	{
		return ::cos(rad);
	}

	/// \if DE
	/// @brief Sinus und Kosinus
	/// \else
	/// @brief sine and cosine
	/// \endif
	template inline void SinCos( const T& rad, T& retSin, T& retCos )
	{
		retSin = Sin( rad );
		retCos = Cos( rad );
	}

	/// \if DE
	/// @brief Tangens
	/// \else
	/// @brief tangent
	/// \endif
	template inline T Tan(const T& rad)
	{
		return ::tan(rad);
	}

	/// \if DE
	/// @brief Arcus Sinus
	/// \else
	/// @brief arcsine
	/// \endif
	template inline T ASin(const T& value)
	{
		return ::asin(value);
	}

	/// \if DE
	/// @brief Arcus Kosinus
	/// \else
	/// @brief arcsine
	/// \endif
	template inline T ACos(const T& value)
	{
		return ::acos(value);
	}

	/// \if DE
	/// @brief Arcus Tangens
	/// \else
	/// @brief arctangent
	/// \endif
	template inline T ATan(const T& value)
	{
		return ::atan(value);
	}

	/// \if DE
	/// @brief Quadratwurzel
	/// \else
	/// @brief squareroot
	/// \endif
	template inline T Sqrt(const T& value)
	{
		return ::sqrt(value);
	}

	/// \if DE
	/// @brief Quadrat
	/// \else
	/// @brief square
	/// \endif
	template inline T Pow2(const T& base)
	{
		return base*base;
	}

	/// \if DE
	/// @brief Potenz
	/// \else
	/// @brief exponentiation
	/// \endif
	template inline T Pow(const T& base, const T& exp)
	{
		return ::pow(base,exp);
	}

	/// \if DE
	/// @brief Berechnet value1 % value2
	/// \else
	/// @brief calculates value1 % value2
	/// \endif
	template inline T Mod(const T& value1, const T& value2)
	{
		return ::fmod(value1,value2);
		//return ( value1 - RoundDown(value1 / value2) * value2 );
	}

	/// \if DE
	/// @brief Berechnet |value|
	/// \else
	/// @brief calculates |value|
	/// \endif
	template inline T Abs(const T& value)
	{
		return ((value < 0) ? -value : value); 
	}

	/// \if DE
	/// @brief Logarithmus von 'num' zur Basis E
	/// \else
	/// @brief logarithm of 'num' to the base e
	/// \endif
	template inline T LogE(T& num)
	{
		return ::log(num);
	}

	/// \if DE
	/// @brief Logarithmus von 'num' zur Basis 10
	/// \else
	/// @brief logarithm of 'num' to the base 10
	/// \endif
	template inline T Log10(T& num)
	{
		return ::log10(num);
	}

	/// \if DE
	/// @brief Logarithmus von 'num' zur Basis 'base'
	/// \else
	/// @brief logarithm of 'num' to the base 'base'
	/// \endif
	template inline T Log(T& base, T& num)
	{
		return ( ::log(num) / ::log(base) );
	}

	/// \if DE
	/// @brief Runden
	/// \else
	/// @brief round to nearest integer
	/// \endif
	template inline int Round(T& value)
	{
		return (int)(d<0 ? d-0.5 : d+0.5);
	}

	/// \if DE
	/// @brief Runden auf bestimmte Stellen
	/// Wenn 'digit' negativ, wird auf 'digit' Stellen nach dem Komma gerundet.
	/// Wenn 'digit' positiv, wird auf 'digit' Stellen vor dem Komma gerundet.
	/// 'digit' darf maximal den Wert 20 und minimal den Wert -20 haben.
	/// \else
	/// @brief round to an number of digits
	/// 
	/// \endif
	template inline T Round(T& value, int digits)
	{
		assert(digits >= -20 && digits <= 20);
		T v[] = {	-1e20, -1e19, -1e18, -1e17, -1e16, -1e15, -1e14, -1e13, -1e12,
					-1e11, -1e10, -1e9, -1e8, -1e7, -1e6, -1e5, -1e4, -1e3, -1e2,
					-10, 1, 10, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
					1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20 };
		return RoundDown(value / v[digits+20] + 0.5) * v[digits+20];
	}

	/// \if DE
	/// @brief Aufrunden
	/// \else
	/// @brief round up
	/// \endif
	template inline int RoundUp(T& value)
	{
		//if(value - RoundDown(value) == 0)
		//	return (int)value;
		//else return (int)(value+1);
		return (int)::ceil(value);
	}

	/// \if DE
	/// @brief Abrunden
	/// \else
	/// @brief round down
	/// \endif
	template inline T RoundDown(T& value)
	{
		return (int)value;
	}

	/// \if DE
	/// @brief Testet ob die Zahl gerade oder Ungerade ist
	/// \else
	/// @brief test if number is even or not
	/// \endif
    template  inline const bool IsEven(const T& value)
    {
        return (!(value&1));
    }

	/// \if DE
	/// @brief kleinere Zahl von  und 
	/// \else
	/// @brief less number of  and 
	/// \endif
	template inline const T& Min(const T& value1, const T& value2)
	{
		return ( (value1 < value2) ? value1 : value2 );
	}

	/// \if DE
	/// @brief größere Zahl von  und 
	/// \else
	/// @brief bigger number of  and 
	/// \endif
	template inline const T& Max(const T& value1, const T& value2)
	{
		return ( (value1 > value2) ? value1 : value2 );
	}

	/// \if DE
	/// @brief  auf  und  begrenzen
	/// \else
	/// @brief clamp  to  and 
	/// \endif
	template inline const T& Clamp(const T& value, const T& min, const T& max)
	{
		return ( (value < min) ? min : ( (value > max) ? max : value) );
	}

	/// \if DE
	/// @brief Wert ist nahe einem Anderen
	/// \else
	/// @brief value is near to another
	/// \endif
	template inline bool NearTo( const T& value, const T& nearto )
	{
		return Abs( nearto - value ) <= EPSILON;
	}

	/// \if DE
	/// @brief Wenn t<0, dann -1, wenn t>0, dann 1, ansonsten 0
	/// \else
	/// @brief if t<0, than -1, if t>0, than 1, else 0
	/// \endif
	template inline T Sign(const T& value)
	{
		return (T)((t < 0) ? (-1) : (t > 0 ? 1 : 0));
	}

	/// \if DE
	/// @brief interpoliert linear zwischen zwei werten
	/// \else
	/// @brief interpolates linearly between two values
	/// \endif
	template inline T1 Interpolate( const T1& v1, const T1& v2, const T2& lerp )
	{
		return v1 + ( v2 - v1 ) * lerp;
	}

	/// \if DE
	/// @brief berechnet Fakultät
	/// \else
	/// @brief computes factorial
	/// \endif
	template 
	T Fac( T value )
	{
		assert( value >= 0 );
		T res = 1;
		while( value > 1 )
		{
			res *= value;
			value--;
		}
		return res;
	}


	/// \if DE
	/// @brief berechnet Nachkommastellen
	/// \else
	/// @brief computes fraction
	/// \endif
	template 
	T Frac( T value )
	{
		return value - RoundDown( value );
	}

	/// \if DE
	/// @brief 1D-Perlin Noise Funktion
	/// \else
	/// @brief 1D-Perlin Noise function
	/// \endif
	double Noise( unsigned int x )
	{
		x = ( x << 13 ) ^ x;
		return ( 1.0 - ( ( x * ( x * x * 15731 + 789221 ) + 1376312589) & 0x7FFFFFFF ) / 1073741824.0 );    
	}


	/// \if DE
	/// @brief 2D-Perlin Noise Funktion
	/// \else
	/// @brief 2D-Perlin Noise function
	/// \endif
	double Noise( unsigned int x, unsigned int y )
	{
		unsigned int n = x + y * 57;
		n = ( n << 13 ) ^ n;
		unsigned int result = ( ( n * ( n * n * 15731 + 789221 ) + 1376312589 ) & 0x7FFFFFFF);

		return ( 1.0 - double(result) / 1073741824.0 );
	}

	/// \if DE
	/// @brief Weiches 1D-Noise (Gausssche Verteilung)
	/// \else
	/// @brief Smooth 1D-Noise (Gaussian Distribution)
	/// \endif
	double SmoothNoise( unsigned int x )
	{
		double sides   = ( Noise( x - 1 ) + Noise( x + 1 ) ) /  4.0;
		double center  =   Noise( x ) / 2.0;
		return sides + center;
	}

	/// \if DE
	/// @brief Weiches 2D-Noise (Gausssche Verteilung)
	/// \else
	/// @brief Smooth 2D-Noise (Gaussian Distribution)
	/// \endif
	double SmoothNoise( unsigned int x, unsigned int y )
	{
		double corners = ( Noise(x-1, y-1)+Noise(x+1, y-1)+Noise(x-1, y+1)+Noise(x+1, y+1) ) / 16.0;
		double sides   = ( Noise(x-1, y)  +Noise(x+1, y)  +Noise(x, y-1)  +Noise(x, y+1) ) /  8.0;
		double center  =   Noise(x, y) / 4.0;
		return corners + sides + center;
	}

	/// \if DE
	/// @brief 2D-Noise basierend auf Fließkommazahlparameter
	/// \else
	/// @brief 2D-Noise based on floatingpoint parameters
	/// \endif
	double InterpolatedNoise( double x, double y )
	{
		int		integer_X    = int(x);
		double	fractional_X = x - integer_X;

		int		integer_Y    = int(y);
		double	fractional_Y = y - integer_Y;

		double v1 = Noise( integer_X,     integer_Y );
		double v2 = Noise( integer_X + 1, integer_Y);
		double v3 = Noise( integer_X,     integer_Y + 1 );
		double v4 = Noise( integer_X + 1, integer_Y + 1 );

		double i1 = Interpolate( v1, v2, fractional_X );
		double i2 = Interpolate( v3, v4, fractional_X );

		return Interpolate( i1, i2, fractional_Y );
	}

	/// \if DE
	/// @brief Weiches 2D-Noise basierend auf Fließkommazahlparameter
	/// \else
	/// @brief Smooth 2D-Noise based on floatingpoint parameters
	/// \endif
	double SmoothInterpolatedNoise( double x, double y )
	{
		int		integer_X    = int(x);
		double	fractional_X = x - integer_X;

		int		integer_Y    = int(y);
		double	fractional_Y = y - integer_Y;

		double v1 = SmoothNoise( integer_X,     integer_Y );
		double v2 = SmoothNoise( integer_X + 1, integer_Y);
		double v3 = SmoothNoise( integer_X,     integer_Y + 1 );
		double v4 = SmoothNoise( integer_X + 1, integer_Y + 1 );

		double i1 = Interpolate( v1, v2, fractional_X );
		double i2 = Interpolate( v3, v4, fractional_X );

		return Interpolate( i1, i2, fractional_Y );
	}



	struct ARGB
	{
		union
		{
			unsigned long	argb;
			struct
			{
#ifdef LITTLE_ENDIAN
				unsigned char B : 8;
				unsigned char G : 8;
				unsigned char R : 8;
				unsigned char A : 8;
#else
				unsigned char A : 8;
				unsigned char R : 8;
				unsigned char G : 8;
				unsigned char B : 8;
#endif
			};
		};

		ARGB() {}

		template
		ARGB( const T& r, const T& g, const T& b, const T& a )
		{
			R = (unsigned char) ( r * 255.0 );
			G = (unsigned char) ( g * 255.0 );
			B = (unsigned char) ( b * 255.0 );
			A = (unsigned char) ( a * 255.0 );
		}

		ARGB( unsigned char r, unsigned char g, unsigned char b, unsigned char a )
		{
			R = r;
			G = g;
			B = b;
			A = a;
		}

		operator unsigned long ()	{ return argb; }
		operator const unsigned long () const { return argb; }

	};


}

#endif //_ZFXMATH_INCLUDE_BASICMATH_H_