#ifndef _WDL_FPCMP_H_
#define _WDL_FPCMP_H_

#include <math.h>
#include <float.h>

// Floating point comparisons are based from:
// The Art of Computer Programming by Donald E. Knuth.

inline bool WDL_ApproximatelyEqual(float a, float b)
{
  return fabs(a - b) <= ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * FLT_EPSILON);
}

inline bool WDL_ApproximatelyEqual(double a, double b)
{
  return fabs(a - b) <= ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * DBL_EPSILON);
}

inline bool WDL_EssentiallyEqual(float a, float b)
{
  return fabs(a - b) <= ((fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * FLT_EPSILON);
}

inline bool WDL_EssentiallyEqual(double a, double b)
{
  return fabs(a - b) <= ((fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * DBL_EPSILON);
}

inline bool WDL_DefinitelyGreaterThan(float a, float b)
{
  return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * FLT_EPSILON);
}

inline bool WDL_DefinitelyGreaterThan(double a, double b)
{
  return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * DBL_EPSILON);
}

inline bool WDL_DefinitelyLessThan(float a, float b)
{
  return (b - a) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * FLT_EPSILON);
}

inline bool WDL_DefinitelyLessThan(double a, double b)
{
  return (b - a) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * DBL_EPSILON);
}

#endif // _WDL_FPCMP_H_
