/*
 *  Negaters
 *
 */

template <class Pred>
class unary_negate : public unary_function<typename Pred::argument_type,bool> 
{
    Pred op;
public:
    explicit unary_negate(const Pred& p) : op(p) { }
    bool operator()(const argument_type& x) const { return !op(x); }
};

template <class Pred>
class binary_negate : public binary_function<typename Pred::first_argument_type,
        typename Pred::second_argument_type, bool> 
{
    typedef first_argument_type Arg;
    typedef second_argument_type Arg2;

    Pred op;
public:
    explicit binary_negate(const Pred& p) : op(p) { }
    bool operator()(const Arg& x, const Arg2& y) const { return !op(x,y); }
};

template<class Pred> unary_negate<Pred> not1(const Pred& p);    // negate unary
template<class Pred> binary_negate<Pred> not2(const Pred& p);   // negate binary