#ifndef RIMATH_H
#define RIMATH_H

#ifndef RICOMMON_H
#include <RiCommon.H>
#endif

#ifndef __MATH_H__
#include <math.h>
#endif

#ifndef __FLOAT_H__
#include <float.h>
#endif


// recodings of Pi and real limits from "float.h" 
#ifdef RI_REAL_IS_FLOAT
#define RiRealMin       FLT_MIN
#define RiRealMax       FLT_MAX
#define RiRealEpsilon   FLT_EPSILON
#define RiRealAlmostOne (1.0F - FLT_EPSILON)
#define RiPi            3.14159265358979323846F
#else
#define RiRealMin       DBL_MIN
#define RiRealMax       DBL_MAX
#define RiRealEpsilon   DBL_EPSILON
#define RiRealAlmostOne (1.0F - DBL_EPSILON)
#define RiPi            3.14159265358979323846
#endif

// in case M_PI isn't in math.h
#ifndef M_PI
#define M_PI            3.14159265358979323846
#endif


//// a NaN constant
extern const RiReal RI_NAN;
//// a constant equal to infinity.
extern const RiReal RI_INF;

/**********************************************************
// FUNCTION GROUP: Use faster functions when RiReal is a float
// FUNCTION GROUP: These simply overload the double versions
 **********************************************************/
				////
inline float sqrt(float f)
{
    return sqrtf(f);
}
				////
inline float cos(float f)
{
    return cosf(f);
}

inline float sin(float f)
{
    return sinf(f);
}

inline float tan(float f)
{
    return tanf(f);
}

inline float acos(float f)
{
    return acosf(f);
}

inline float asin(float f)
{
    return asinf(f);
}

inline float pow(float f, float exp)
{
    return powf(f, exp);
}

inline float atan2(float a, float b)
{
    return atan2f( a, b );
}

/*
inline float erf(float f)
{
    return ferf(f);
}

inline float erfc(float f)
{
    return ferfc(f);
}
*/

inline float fabs(float f)
{
    return fabsf(f);
}

inline float floor(float f)
{
    return floorf(f);
}

/**********************************************************
// FUNCTION GROUP: Comparisons between RiReals
// 
// ********************************************************/

inline RiReal RiClamp(RiReal min, RiReal max, RiReal num)
{
    if(num < min) return min;
    if(num > max) return max;
    return num;
}

				////
inline RiReal RiMin(RiReal a, RiReal b)
{
    return (a < b) ? a : b;
}
				////
inline RiReal RiMin(RiReal a, RiReal b, RiReal c)
{
    return RiMin(RiMin(a,b), c);
}
				////
inline RiReal RiMin(RiReal a, RiReal b, RiReal c, RiReal d)
{
    return RiMin(RiMin(a,b), RiMin(c,d));
}
				////
inline RiReal RiMax(RiReal a, RiReal b)
{
    return (a > b) ? a : b;
}
				////
inline RiReal RiMax(RiReal a, RiReal b, RiReal c)
{
    return RiMax(RiMax(a,b), c);
}
				////
inline RiReal RiMax(RiReal a, RiReal b, RiReal c, RiReal d)
{
    return RiMax(RiMax(a,b), RiMax(c,d));
}
				////  Compares to RiReals based on an epsilon
				// This function should be moved in with a
				// group of fuzzy compares (for RiReal, RiVector3,
                                // Directions, Planes, etc)
inline bool RiClose(RiReal a, RiReal b, RiReal eps = RiRealEpsilon) {
    return (fabs(a - b) <=  eps );
}

#endif // RIMATH_H


