/*
    C++ Mesh Generation Library
    Copyright (c) 2000echet <eric at bechet dot ca>

    This file is part of the C++ Mesh Generation Library.

    See the NOTICE & LICENSE files for conditions.
*/
//---------------------------------------------------------------------------
#ifndef COMPARATORS_H
#define COMPARATORS_H
//---------------------------------------------------------------------------


#include "mesh_const.h"
#include <algorithm>

/// fonction template d'egalite "floue"
template <class T> bool IsEqual ( const T &lhs, const T &rhs )
{
  T theMin = std::min ( lhs, rhs );
  T theMax = std::max ( lhs, rhs );

  T difference = theMax - theMin;

  T absMin = ( theMin < 0.0 ) ? -theMin : theMin;
  T absMax = ( theMax < 0.0 ) ? -theMax : theMax;
  T largestMagnitude = std::max ( absMin, absMax );

  T truc= ( 1e-15/*numeric_limits<T>::epsilon()*/ ) *largestMagnitude*rounding_factor;
  T truc2= ( truc<constant_rounding_factor ) ? constant_rounding_factor : truc;
  bool t=difference<=truc2;
//  if (((fabs(lhs-4.23))<1e-2)||((fabs(rhs-4.23))<1e-2)) cout << lhs << "==?"<< rhs << (t ? "true" : "false") << endl;
  return t;
}


/// template function for comparing 2 real numbers (fuzzy)
template <class T> bool IsLess ( const T &lhs, const T &rhs )
{
  if ( lhs<rhs )
    if ( !IsEqual<T> ( lhs,rhs ) )
    {
      return true;
    }

  return false;
}

/// template function for comparing 2 real numbers (fuzzy)
template <class T> bool IsLessOrEqual ( const T &lhs, const T &rhs )
{
  if ( lhs>rhs )
    if ( !IsEqual<T> ( lhs,rhs ) )
    {
      return false;
    }

  return true;
}

/// template function for comparing 2 real numbers (fuzzy)
template <class T> bool IsGreater ( const T &lhs, const T &rhs )
{
  if ( lhs>rhs )
    if ( !IsEqual<T> ( lhs,rhs ) )
    {
      return true;
    }

  return false;

}

/// template function for comparing 2 real numbers (fuzzy)
template <class T> bool IsGreaterOrEqual ( const T &lhs, const T &rhs )
{
  if ( lhs<rhs )
    if ( !IsEqual<T> ( lhs,rhs ) )
    {
      return false;
    }

  return true;

}

/**function object to be used in STL
 equality check */
template<class T> class Equ
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
    return ( v1==v2 );
  }
};

/** function object to be used in STL
 equality check over pointers */
template<class T> class Equ_Ptr_Type
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
    return ( *v1==*v2 );
  }
};

/** function object to be used in STL
"less than" check, over pointers */
template<class T> class Less_Ptr_Type
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
    return ( ( *v1 ) < ( *v2 ) );
  }
};

/** function object to be used in STL
 "less than" compares the adress of pointers */
template<class T> class Less_Ptr // cela ne me plait pas vraiment, en passant
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
    return ( ( & ( *v1 ) ) < ( & ( *v2 ) ) );
  }
};

/** function object to be used in STL
"less than" compares the ID numbers of any entity */
template<class T> class Less_Ptr_ID
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
    return ( ( ( *v1 ).GetID() ) < ( ( *v2 ).GetID() ) );
  }
};

/** function object to be used in STL
"less than" compares the metric size any entity (typically bipoints) */
template<class T> class Less_Ptr_Size
{
public:
///
  bool operator() ( const T& v1,const T& v2 ) const
  {
//   if ((*v1).Get_Metric_Size()==(*v2).Get_Metric_Size()) return ((&(*v1)<&(*v2))); else
    return ( ( *v1 ).Get_Metric_Size() < ( *v2 ).Get_Metric_Size() );
  }
};

/** function object to be used in STL hashed containers
hashes a object of type T */
template<class T> class Hash
{
public:
///
  size_t operator () ( const T & to_hash ) const
  {
    return to_hash.hash();
  }
};

/** function object to be used in STL hashed containers
hashes an iterator (get the object's adress) */
template<class T> class Hash_Ptr
{
public:
///
  size_t operator () ( const T & to_hash ) const
  {
    return ( size_t ) & ( *to_hash );
  }
};

/** function object to be used in STL hashed containers
hashes a object pointed by an iterator on T */
template<class T> class Hash_Ptr_Type
{
public:
///
  size_t operator () ( const T & to_hash ) const
  {
    return ( *to_hash ).hash();
  }
};

#endif // COMPARATORS_H

 
