/********************************************
libmawk (C) 2009-2014, Tibor 'Igor2' Palinkas;

This is a source file for libmawk, an implementation of
the AWK programming language, fork of mawk.

Libmawk is distributed without warranty under the terms of
the GNU General Public License, version 2, 1991.
********************************************/

#include "mawk.h"
#include "num.h"
#include "math_wrap.h"

const mawk_num_id_t mawk_num_id = MAWK_NUM_ID_DOUBLE;

/* convert a number to Int (this is not as simple as a
   mawk_cast because the results are undefined if it won't fit).
   Truncate large values to +Max_Int or -Max_Int
   Send nans to -Max_Int
*/

Int mawk_d_to_I(mawk_num_t d)
{
	if (d >= Max_Int)
		return Max_Int;
	if (d > -Max_Int)
		return (Int) d;
	return -Max_Int;
}

const char *mawk_num_print_spec(mawk_num_t d)
{
	if (P_isnan(d))
		return "nan";
	return NULL;
}

double P_fmod(double x, double y)
{
	double modf();
	double ipart;

	if (y == 0)
		return P_nan();
	PM_BEGIN
		modf(x / y, &ipart);
	PM_ERROR
		return P_nan();
	PM_END
	return x - ipart * y;
}

double mawk_num_pow(double x, double y)
{
	double r;

	if (P_isnan(x) || P_isnan(y))
		return P_nan();
	if ((x < 0.0) && (y != (double)((int)(y+0.5))))
		return P_nan();
	PM_BEGIN
		r = pow(x, y);
	PM_ERROR
		return P_nan();
	PM_END
	return r;
}

#ifndef MAWK_HAVE_SAFE_NAN
double mawk_strtonum_(const char *nptr, char **endptr)
{
	if (((nptr[0] == 'n')  || (nptr[0] == 'N')) && ((nptr[1] == 'a')  || (nptr[1] == 'A')) && ((nptr[2] == 'n')  || (nptr[2] == 'N'))) {
		if (endptr != NULL)
			*endptr = (char *)(nptr+3);
		return P_nan();
	}
	return strtod(nptr, endptr);
}
#endif
