#ifndef FUNCTIONALOBJECTOPERATORS_H
#define FUNCTIONALOBJECTOPERATORS_H

#include <typedefs.h>

// The aim of this file is to add functional operators when needed.
// ie Encountering a situation where new operators are needed or
// the current solution is inadequate.

// STL has implemented functional operators with nasty baggage.
// For example the not2 operator requires the binary operator
// to have certain data members which is totally unnecessary.

/*!
\brief Negate a binary operator.

\par Example
  // fwd is a binary operator.
  // Sort in reverse.
  sort(v+i,v+i+width,mynot2(fwd))
*/
//template< typename F, typename T >
template< typename F >
class mynot2object
{
public:
  F f;

  /** Pass in the binary operator. */
  mynot2object(F const & f_)
    : f(f_) {}

  /** Binary operator being negated. */
  template< typename T >
  boolc operator()(T const & p1, T const & p2)
    { return !f(p1,p2); }
};

template< typename F >
mynot2object<F> mynot2(F const & f_)
{
  return mynot2object<F>(f_);
}



template< typename F >
class mycomparexobject
{
public:

  /** Binary operator. */
  F bin;

  /** Constructor. */
  mycomparexobject() {}
  /** Pass in the binary operator. */
  mycomparexobject(F const & bin_)
    : bin(bin_) {}

  /** The x components being compared with a binary
      operator. */
  template< typename T >
  boolc operator()(T const & p1, T const & p2)
    { return bin(p1.x,p2.x); }
};

template< typename F >
mycomparexobject<F> mycomparex(F const & f_)
{
  return mycomparexobject<F>(f_);
}



template< typename F >
class mycompareyobject
{
public:

  /** Binary operator. */
  F bin;

  /** Constructor. */
  mycompareyobject() {}
  /** Pass in the binary operator. */
  mycompareyobject(F const & bin_)
    : bin(bin_) {}

  /** The x components being compared with a binary
      operator. */
  template< typename T >
  boolc operator()(T const & p1, T const & p2)
    { return bin(p1.y,p2.y); }
};

template< typename F >
mycompareyobject<F> mycomparey(F const & f_)
{
  return mycompareyobject<F>(f_);
}


template< typename F >
class mycomparezobject
{
public:

  /** Binary operator. */
  F bin;

  /** Constructor. */
  mycomparezobject() {}
  /** Pass in the binary operator. */
  mycomparezobject(F const & bin_)
    : bin(bin_) {}

  /** The x components being compared with a binary
      operator. */
  template< typename T >
  boolc operator()(T const & p1, T const & p2)
    { return bin(p1.z,p2.z); }
};

template< typename F >
mycomparezobject<F> mycomparez(F const & f_)
{
  return mycomparezobject<F>(f_);
}


#endif



