/*
 * 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_VECTOR_EVAL_H
#define TVMET_VECTOR_EVAL_H

/* forwards */
template <class T> class std::complex;

namespace tvmet {

/**
 * \fn bool all_elements(const XprVector<E, Sz>& e)
 * \brief check on statements for all elements
 * \ingroup _unary_function
 * This is for use with boolean operators like
 * \code
 * all_elements(vec > 0)
 * \endcode
 */
template<class E, std::size_t Sz>
inline
bool all_elements(const XprVector<E, Sz>& e) {
  return meta::Vector<Sz>::all_elements(e);
}


/**
 * \fn bool any_elements(const XprVector<E, Sz>& e)
 * \brief check on statements for any elements
 * \ingroup _unary_function
 * This is for use with boolean operators like
 * \code
 * all_elements(vec > 0)
 * \endcode
 */
template<class E, std::size_t Sz>
inline
bool any_elements(const XprVector<E, Sz>& e) {
  return meta::Vector<Sz>::any_elements(e);
}

/**
 * \fn bool eval(XprVector<E, Sz> e)
 * \brief Evals the vector expressions to bool.
 * \ingroup _unary_function
 * This eval is for use for branches, like
 * \code
 * if(Vector1 > Vector2) {
 *     // true branch
 * } else {
 *     // false branch
 * }\endcode
 */
template<class E, std::size_t Sz>
inline
bool eval(XprVector<E, Sz> e) {
  return meta::Vector<Sz>::eval(e);
}

/*
 * XprVector<E1, Sz> ? Vector<T2, Sz> : Vector<T3, Sz>
 * XprVector<E1, Sz> ? Vector<T2, Sz> : XprVector<E3, Sz>
 * XprVector<E1, Sz> ? XprVector<E2, Sz> : Vector<T3, Sz>
 * XprVector<E1, Sz> ? XprVector<E2, Sz> : XprVector<E3, Sz>
 */

/**
 * eval(XprVector<E1, Sz>, const Vector<T2, Sz>&, const Vector<T3, Sz>&)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class T2, class T3, std::size_t Sz>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    VectorConstReference<T2, Sz>,
    VectorConstReference<T3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, const Vector<T2, Sz>& v2, const Vector<T3, Sz>& v3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    VectorConstReference<T2, Sz>,
    VectorConstReference<T3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, v2.cref(), v3.cref()));
}

/**
 * eval(XprVector<E1, Sz> e1, const Vector<T2, Sz>& v2, XprVector<E3, Sz> e3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class T2, class E3, std::size_t Sz>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    VectorConstReference<T2, Sz>,
    XprVector<E3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, const Vector<T2, Sz>& v2, XprVector<E3, Sz> e3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    VectorConstReference<T2, Sz>,
    XprVector<E3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, v2.cref(), e3));
}

/**
 * eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, const Vector<T3, Sz>& v3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class E2, class T3, std::size_t Sz>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    VectorConstReference<T3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, const Vector<T3, Sz>& v3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    VectorConstReference<T3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, e2, v3.cref()));
}

/**
 * eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, XprVector<E3, Sz> e3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class E2, class E3, std::size_t Sz>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprVector<E3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, XprVector<E3, Sz> e3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprVector<E3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, e2, e3));
}

/*
 * XprVector<E, Sz> ? POD1 : POD2
 * XprVector<E1, Sz> ? POD : XprVector<E3, Sz>
 * XprVector<E1, Sz> ? XprVector<E2, Sz> : POD
 */
#define TVMET_EVAL(POD)               					\
template<class E, std::size_t Sz>      					\
inline               							\
XprVector<               						\
  XprEval<               						\
    XprVector<E, Sz>,               					\
    XprLiteral< POD >,               					\
    XprLiteral< POD >               					\
  >,                							\
  Sz									\
>               							\
eval(XprVector<E, Sz> e, POD x2, POD x3) {             			\
  typedef XprEval<               					\
    XprVector<E, Sz>,               					\
    XprLiteral< POD >,                					\
    XprLiteral< POD >                					\
  > 							expr_type; 	\
  return XprVector<expr_type, Sz>(expr_type(e, XprLiteral< POD >(x2), XprLiteral< POD >(x3))); \
}               							\
               								\
template<class E1, class E3, std::size_t Sz>   				\
inline               							\
XprVector<               						\
  XprEval<               						\
    XprVector<E1, Sz>,               					\
    XprLiteral< POD >,               					\
    XprVector<E3, Sz>               					\
  >,                							\
  Sz									\
>               							\
eval(XprVector<E1, Sz> e1, POD x2, XprVector<E3, Sz> e3) {             	\
  typedef XprEval<               					\
    XprVector<E1, Sz>,               					\
    XprLiteral< POD >,                					\
    XprVector<E3, Sz>               					\
  > 							expr_type; 	\
  return XprVector<expr_type, Sz>(expr_type(e1, XprLiteral< POD >(x2), e3)); \
}               							\
               								\
template<class E1, class E2, std::size_t Sz>   				\
inline               							\
XprVector<               						\
  XprEval<               						\
    XprVector<E1, Sz>,               					\
    XprVector<E2, Sz>,               					\
    XprLiteral< POD >               					\
  >,                							\
  Sz									\
>               							\
eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, POD x3) {             	\
  typedef XprEval<               					\
    XprVector<E1, Sz>,               					\
    XprVector<E2, Sz>,               					\
    XprLiteral< POD >                					\
  > 							expr_type; 	\
  return XprVector<expr_type, Sz>(expr_type(e1, e2, XprLiteral< POD >(x3))); \
}

TVMET_EVAL(int)
TVMET_EVAL(float)
TVMET_EVAL(double)
#ifdef TVMET_HAVE_LONG_DOUBLE
TVMET_EVAL(long double)
#endif // TVMET_HAVE_LONG_DOUBLE

#undef TVMET_EVAL

#ifdef TVMET_HAVE_COMPLEX

/*
 * eval with complex<> types
 * XprVector<E, Sz> e, std::complex<T> z2, std::complex<T> z3
 * XprVector<E1, Sz> e1, std::complex<T> z2, XprVector<E3, Sz> e3
 * XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, std::complex<T> z3
 */

/**
 * eval(XprVector<E, Sz> e, std::complex<T> z2, std::complex<T> z3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E, std::size_t Sz, class T>
inline
XprVector<
  XprEval<
    XprVector<E, Sz>,
    XprLiteral< std::complex<T> >,
    XprLiteral< std::complex<T> >
  >,
  Sz
>
eval(XprVector<E, Sz> e, std::complex<T> z2, std::complex<T> z3) {
  typedef XprEval<
    XprVector<E, Sz>,
    XprLiteral< std::complex<T> >,
    XprLiteral< std::complex<T> >
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e, XprLiteral< std::complex<T> >(z2), XprLiteral< std::complex<T> >(z3)));
}

/**
 * eval(XprVector<E1, Sz> e1, std::complex<T> z2, XprVector<E3, Sz> e3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class E3, std::size_t Sz, class T>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    XprLiteral< std::complex<T> >,
    XprVector<E3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, std::complex<T> z2, XprVector<E3, Sz> e3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    XprLiteral< std::complex<T> >,
    XprVector<E3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, XprLiteral< std::complex<T> >(z2), e3));
}

/**
 * eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, std::complex<T> z3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class E2, std::size_t Sz, class T>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprLiteral< std::complex<T> >
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, std::complex<T> z3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprLiteral< std::complex<T> >
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, e2, XprLiteral< std::complex<T> >(z3)));
}

// *** new ***

/**
 * eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, XprVector<E3, Sz> e3)
 * \brief Evals the vector expressions.
 * \ingroup _trinary_function
 * This eval is for the a?b:c syntax, since it's not allowed to overload
 * these operators.
 */
template<class E1, class E2, class E3, std::size_t Sz, class T>
inline
XprVector<
  XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprVector<E3, Sz>
  >,
  Sz
>
eval(XprVector<E1, Sz> e1, XprVector<E2, Sz> e2, XprVector<E3, Sz> e3) {
  typedef XprEval<
    XprVector<E1, Sz>,
    XprVector<E2, Sz>,
    XprVector<E3, Sz>
  > 							expr_type;
  return XprVector<expr_type, Sz>(expr_type(e1, e2, e3));
}

#endif // TVMET_HAVE_COMPLEX


} // namespace tvmet

#endif // TVMET_VECTOR_EVAL_H

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