/*
 * Tiny Vector Matrix Library
 * Dense Vector Matrix Libary of Tiny size using Expression Templates
 *
 * Copyright (C) 2001, 2002 Olaf Petzold <opetzold@wit.regiocom.net>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * "$Id:"
 */

#ifndef TVMET_UNARY_FUNCTIONAL_H
#define TVMET_UNARY_FUNCTIONAL_H

namespace tvmet {


/*
 *
 */
#define TVMET_UNARY_FUNCTIONAL(OPNAME, OP)                   		\
template <class T>	                                 		\
struct OPNAME : public UnaryFunctional {                		\
  typedef bool						value_type;	\
  static inline value_type applyOn(T rhs) {		        	\
    return OP rhs;                                         		\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #OPNAME << "<"	 			\
       << typeid(T).name() << ">,"                         		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_FUNCTIONAL(fcnl_LogicalNot, !)

/** \class fcnl_LogicalNot	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#undef TVMET_UNARY_FUNCTIONAL


/*
 *
 */
#define TVMET_UNARY_FUNCTIONAL(OPNAME, OP)                   		\
template <class T>	                                 		\
struct OPNAME : public UnaryFunctional {                		\
  typedef T						value_type;	\
  static inline value_type applyOn(T rhs) {		        	\
    return OP rhs;                                         		\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #OPNAME << "<"	 			\
       << typeid(T).name() << ">,"                         		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_FUNCTIONAL(fcnl_BitwiseNot, ~)
TVMET_UNARY_FUNCTIONAL(fcnl_Negate, -)

/** \class fcnl_BitwiseNot	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_Negate		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#undef TVMET_UNARY_FUNCTIONAL


/*
 *
 */
#define TVMET_UNARY_FUNCTIONAL(FUNCNAME, MATHFUNC)             		\
template <class T>	                                 		\
struct FUNCNAME : public UnaryFunctional {                		\
  typedef T						value_type;	\
  static inline value_type applyOn(T rhs) {		        	\
    return MATHFUNC(rhs);               				\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #FUNCNAME << "<"	 			\
       << typeid(T).name() << ">,"                         		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_FUNCTIONAL(fcnl_abs, std::abs)
TVMET_UNARY_FUNCTIONAL(fcnl_cbrt, std::cbrt)
TVMET_UNARY_FUNCTIONAL(fcnl_ceil, std::ceil)
TVMET_UNARY_FUNCTIONAL(fcnl_floor, std::floor)
TVMET_UNARY_FUNCTIONAL(fcnl_rint, std::rint)
TVMET_UNARY_FUNCTIONAL(fcnl_sin, std::sin)
TVMET_UNARY_FUNCTIONAL(fcnl_cos, std::cos)
TVMET_UNARY_FUNCTIONAL(fcnl_tan, std::tan)
TVMET_UNARY_FUNCTIONAL(fcnl_sinh, std::sinh)
TVMET_UNARY_FUNCTIONAL(fcnl_cosh, std::cosh)
TVMET_UNARY_FUNCTIONAL(fcnl_tanh, std::tanh)
TVMET_UNARY_FUNCTIONAL(fcnl_asin, std::asin)
TVMET_UNARY_FUNCTIONAL(fcnl_acos, std::acos)
TVMET_UNARY_FUNCTIONAL(fcnl_atan, std::atan)
TVMET_UNARY_FUNCTIONAL(fcnl_exp, std::exp)
TVMET_UNARY_FUNCTIONAL(fcnl_log, std::log)
TVMET_UNARY_FUNCTIONAL(fcnl_log10, std::log10)
TVMET_UNARY_FUNCTIONAL(fcnl_sqrt, std::sqrt)

/** \class fcnl_abs		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_cbrt		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_ceil		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_floor		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_rint		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_sin		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_cos		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_tan		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_sinh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_cosh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_tanh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_asin		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_acos		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_atan		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_exp		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_log		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_log10		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_sqrt		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#ifdef TVMET_HAVE_IEEE_MATH

TVMET_UNARY_FUNCTIONAL(fcnl_asinh, ::asinh)
TVMET_UNARY_FUNCTIONAL(fcnl_acosh, ::acosh)
TVMET_UNARY_FUNCTIONAL(fcnl_atanh, ::atanh)
TVMET_UNARY_FUNCTIONAL(fcnl_expm1, ::expm1)
TVMET_UNARY_FUNCTIONAL(fcnl_log1p, ::log1p)
TVMET_UNARY_FUNCTIONAL(fcnl_erf, ::erf)
TVMET_UNARY_FUNCTIONAL(fcnl_erfc, ::erfc)
TVMET_UNARY_FUNCTIONAL(fcnl_j0, ::j0)
TVMET_UNARY_FUNCTIONAL(fcnl_j1, ::j1)
TVMET_UNARY_FUNCTIONAL(fcnl_y0, ::y0)
TVMET_UNARY_FUNCTIONAL(fcnl_y1, ::y1)
TVMET_UNARY_FUNCTIONAL(fcnl_lgamma, ::lgamma)

/** \class fcnl_asinh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_acosh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_atanh		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_expm1		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_log1p		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_erf		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_erfc		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_j0		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_j1		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_y0		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_y1		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_lgamma		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#endif // TVMET_HAVE_IEEE_MATH

#undef TVMET_UNARY_FUNCTIONAL


/*
 *
 */
#define TVMET_UNARY_TYPED_ARG_FUNCTIONAL(FUNCNAME, MATHFUNC, POD)    	\
template <>	                                 			\
struct FUNCNAME< POD > : public UnaryFunctional {           		\
  typedef POD						value_type;	\
  static inline value_type applyOn(POD rhs) {	        		\
    return MATHFUNC(rhs);               				\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #FUNCNAME << "<"	 			\
       << typeid(POD).name() << ">,"                         		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_TYPED_ARG_FUNCTIONAL(fcnl_abs, std::labs, long int)
TVMET_UNARY_TYPED_ARG_FUNCTIONAL(fcnl_abs, std::fabs, double)
#ifdef TVMET_HAVE_LONG_DOUBLE
TVMET_UNARY_TYPED_ARG_FUNCTIONAL(fcnl_abs, std::fabs, long double)
#endif // TVMET_HAVE_LONG_DOUBLE

/** \class fcnl_abs<long int>	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_abs<double>	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_abs<long double> UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#undef TVMET_UNARY_TYPED_ARG_FUNCTIONAL


/*
 *
 */
#define TVMET_UNARY_TYPED_RET_FUNCTIONAL(FUNCNAME, MATHFUNC, POD)    	\
template <class T>                                 			\
struct FUNCNAME : public UnaryFunctional {           			\
  typedef T						value_type;	\
  static inline POD applyOn(T rhs) {		        		\
    return MATHFUNC(rhs);               				\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #FUNCNAME << "<"	 			\
       << typeid(POD).name() << ">,"                         		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_TYPED_RET_FUNCTIONAL(fcnl_isnan, ::isnan, int)
TVMET_UNARY_TYPED_RET_FUNCTIONAL(fcnl_isinf, ::isinf, int)
TVMET_UNARY_TYPED_RET_FUNCTIONAL(fcnl_finite, ::finite, int)

/** \class fcnl_isnan		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_isinf		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
/** \class fcnl_finite		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#undef TVMET_UNARY_TYPED_RET_FUNCTIONAL


#ifdef TVMET_HAVE_COMPLEX_MATH

/*
 * complex<> types
 */
template <class T>                                 			\
struct FUNCNAME : public UnaryFunctional {           			\
  typedef T						value_type;	\
  static inline std::complex<T> applyOn(std::complex<T>& rhs) {		\
    return MATHFUNC(rhs);               				\
  }                                                         		\
  static void print_on(std::ostream& os, std::size_t l=0) {    		\
    os << IndentLevel(l) << #FUNCNAME << "<"	 			\
       << typeid(std::complex<T>).name() << ">,"               		\
       << std::endl;                          				\
  }     								\
};

TVMET_UNARY_TYPED_ARG_FUNCTIONAL(fcnl_abs, std::abs)

/** \class fcnl_abs< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */

#undef TVMET_UNARY_TYPED_RET_FUNCTIONAL

#endif // TVMET_HAVE_COMPLEX_MATH


} // namespace tvmet

#endif // TVMET_UNARY_FUNCTIONAL_H

// Local Variables:
// mode:C++
// End:
