#ifndef FrameworkMath_H
#define FrameworkMath_H

#include <math.h>
#include <functional>
#include "Betriebssystem.h"

namespace Framework
{
#define PI 3.14159265

    //! Gibt die größere Zahl zurück ohne if zu verwenden
    //! Funktioniert nur, wenn die Zahlen nicht mehr als 16 bits verwenden
    //! \param a Eine der beiden Zahlen
    //! \param b Eine der beiden Zahlen
    inline int maxInt( int a, int b )
    {
        return ( ( ( a - b ) >> 16 ) & b ) | ( ~( ( a - b ) >> 16 ) & a );
    }

    //! Gibt die kleinere Zahl zurück ohne if zu verwenden
    //! Funktioniert nur, wenn die Zahlen nicht mehr als 16 bits verwenden
    //! \param a Eine der beiden Zahlen
    //! \param b Eine der beiden Zahlen
    inline int minInt( int a, int b )
    {
        return ( ( ( a - b ) >> 16 ) & a ) | ( ~( ( a - b ) >> 16 ) & b );
    }

    //! Gibt den positiven Wert eines Zeichnunges zurück.
    //! Klappt nur, wenn der - und der < 0 operator definiert ist
    template< typename T>
    inline T abs( T t )
    {
        if( t < 0 )
            return -t;
        return t;
    }

    inline float lowPrecisionSin( float radiant )
    {
        while( radiant < -3.14159265f )
            radiant += 6.28318531f;
        while( radiant > 3.14159265f )
            radiant -= 6.28318531f;
        float sin = 0;
        if( radiant < 0 )
        {
            sin = 1.27323954f * radiant + .405284735f * radiant * radiant;

            if( sin < 0 )
                sin = .225f * ( sin *-sin - sin ) + sin;
            else
                sin = .225f * ( sin * sin - sin ) + sin;
        }
        else
        {
            sin = 1.27323954f * radiant - 0.405284735f * radiant * radiant;

            if( sin < 0 )
                sin = .225f * ( sin *-sin - sin ) + sin;
            else
                sin = .225f * ( sin * sin - sin ) + sin;
        }
        return sin;
    }

    inline float lowPrecisionCos( float radiant )
    {
        return lowPrecisionSin( radiant + 3.14159265f / 2.f );
    }

    inline float lowPrecisionTan( float radiant )
    {
        return lowPrecisionSin( radiant ) / lowPrecisionCos( radiant );
    }

    inline float lowPrecisionACos( float cos )
    {
        float negate = float( cos < 0 );
        cos = abs( cos );
        float ret = -0.0187293f;
        ret = ret * cos;
        ret = ret + 0.0742610f;
        ret = ret * cos;
        ret = ret - 0.2121144f;
        ret = ret * cos;
        ret = ret + 1.5707288f;
        ret = ret * (float)sqrt( 1.0 - cos );
        ret = ret - 2 * negate * ret;
        return negate * 3.14159265358979f + ret;
    }

    inline float lowPrecisionASin( float sin )
    {
        return 3.14159265358979f / 2.f - lowPrecisionACos( sin );
    }
}

#endif