#ifndef NEARLYEQUAL_H__
#define NEARLYEQUAL_H__ 


// Einfach: Alle Definitionen in einer h-Datei, keine cpp-Datei. 
// Zur Aufteilung der Definitionen und Deklarationen in eine cpp-Datei 
// und eine h-Datei: Siehe Abschnitt 3.23 und 3.23.5.


#include <cmath> // für fabs und pow

namespace rk1 {

bool NearlyEqual(double x,double y,int p)
{ // true, falls sich x und y um weniger als 5 Einheiten in der (p+1)-ten
  // Stelle unterscheiden. p=10 ist für double Argumente normalerweise
  // ausreichend
double eps =1E-10;
if ((0<=p) && (p<=16)) eps=5*std::pow(0.1,p);
double diff=std::fabs(x - y);
if (x==0 || y==0) // NearlyEqual(x,0) ==> diff=|x|
  return diff<eps;
else // x!=0 and y!=0
  return (diff/std::fabs(x) <= eps) && (diff/std::fabs(y) <= eps);
}

bool DefinitelyLess(double x, double y, int p)
{ // returns true, if x is definitely less then y
return (x<y) && (!NearlyEqual(x,y,p));
}

} // end of namespace rk1 


// Vermeide Überläufe und Unterläufe bei x/y

#include <limits> // für numeric_limits<double>::max und min

namespace rk1 {

double SafeDivision(double x, double y)
{
#if _MSC_VER >= 1800
  const double MaxDouble=DBL_MAX;
  const double MinDouble=DBL_MIN;
#elif  __GNUG__
  const double MaxDouble=std::numeric_limits<double>::max();
  const double MinDouble=std::numeric_limits<double>::min();  
#endif

if   (y < 1 && x > y*MaxDouble) // Überlauf bei x/y
  return MaxDouble;
else if (y > 1 && x < y*MinDouble || x == 0) // Unterlauf
  return 0;                                  // bei x/y
else return x/y;
}

bool NearlyEqual2(long double x,long double y,int p)
{
double eps =1E-10;
if ((0<=p) && (p<=16)) eps=5*std::pow(0.1,p);
double diff=std::fabs(x - y);
if (x==0 || y==0) // NearlyEqual(x,0) ==> diff=|x|
  return diff<eps;
else // x!=0 and y!=0
  {
    double d1 = SafeDivision(diff, std::fabs(y));
    double d2 = SafeDivision(diff, std::fabs(x));
    return (d1 <= eps) && (d2 <= eps);
  }
}

} // end of namespace rk1 

#endif
