#include <amsmathutil25/amsmathutil25.hpp>

namespace ams
{

bool isnan(double d)
{
    bool ret = 0;
    if(d!=d)
    {
        ret = 1;
    }
    return ret;
}

bool isinf(double d)
{
    bool ret = 0;
    ret = std::isinf(d);
    return ret;
}

bool isinfnan(double d)
{
    bool ret = 0;
    ret = ams::isinf(d) || ams::isnan(d);
    return ret;
}

bool isnan(float f)
{
    bool ret = 0;
    if(f!=f)
    {
        ret = 1;
    }
    return ret;
}

bool isinf(float f)
{
    bool ret = 0;
    ret = std::isinf(f);
    return ret;
}

bool isinfnan(float f)
{
    bool ret = 0;
    ret = ams::isinf(f) || ams::isnan(f);
    return ret;
}

double arg(double x, double y)
{
    double ret = 0.0;
    double z = ::sqrt(x*x+y*y);

    if(z>1.0E-10)
    {
        ret = ::atan2(y,x);
        if(ret<0.0) ret = ret + 2.0*ams::pi;
    }
    return ret;
}

float arg(float x, float y)
{
    float ret = 0.0f;
    float z = ::sqrtf(x*x+y*y);

    if(z>1.0E-10)
    {
        ret = ::atan2f(y,x);
        if(ret<0.0f) ret = ret + ams::pif;
    }
    return ret;
}

double sgn(double d)
{
    double ret = 0.0;
    ret = (d>0.0) ? 1.0 : ret;
    ret = (d<0.0) ? -1.0 : ret;

    return ret;
}

float sgn(float f)
{
    float ret = 0.0f;
    ret = (f>0.0f) ? 1.0f : ret;
    ret = (f<0.0f) ? -1.0f : ret;

    return ret;
}

//It has come to my attention that the behavior of Cs
//fmod is odd: Negative numbers have negative moduli
//I need to fix this with a proper modular function, whose values are in [0,N)
double mod(double x, double n)
{
    x = ::fmod(x,n);
  	if(x<0)
  	{
  		x = x + n;
  	}
  	return x;
}
float mod(float x, float n)
{
    x = ::fmodf(x,n);
  	if(x<0)
  	{
  		x = x + n;
  	}
  	return x;
}

int32_t mod(int32_t x, int32_t n)
{
    x = x % n;
    if(x<0)
    {
        x = x + n;
    }
    return x;
}

int64_t mod(int64_t x, int64_t n)
{
    x = x % n;
    if(x<0)
    {
        x = x + n;
    }
    return x;
}

int32_t truediv(int32_t x, int32_t y)
{
    int32_t z = 0;
    if(x>=0 && y>0)
    {
        z = x/y;
    }
    else if(x<0 && y>0)
    {
        z = -((-x)/y) - 1;
    }
    else if(x>=0 && y<0)
    {
        z = -(x/(-y)) - 1;
    }
    else if(x<0 && y<0)
    {
        z = ((-x)/(-y));
    }

    return z;
}

int64_t truediv(int64_t x, int64_t y)
{
    int64_t z = 0;
    if(x>=0 && y>0)
    {
        z = x/y;
    }
    else if(x<0 && y>0)
    {
        z = -((-x)/y) - 1;
    }
    else if(x>=0 && y<0)
    {
        z = -(x/(-y)) - 1;
    }
    else if(x<0 && y<0)
    {
        z = ((-x)/(-y));
    }

    return z;
}

double abs(double a)
{
    double ret = ::fabs(a);
    return ret;

}

float abs(float a)
{
    float ret = ::fabsf(a);
    return ret;
}

int32_t abs(int32_t a)
{
    int32_t ret = (a<0) ? -a : a;
    return ret;
}

int64_t abs(int64_t a)
{
    int64_t ret = (a<0) ? -a : a;
    return ret;
}

}; //end namespace ams