This is the Tiny Vector Matrix Expression Templates library found at http://tvmet.sourceforge.net. It is the fastest and most compact matrix lib out there (for < 10x10 matricies). I have done some minor tweaks to make it compile for mbed. For examples and hints on how to use, see: http://tvmet.sourceforge.net/usage.html

Dependents:   Eurobot_2012_Secondary

Files at this revision

API Documentation at this revision

Comitter:
madcowswe
Date:
Wed Mar 28 15:53:45 2012 +0000
Commit message:

Changed in this revision

AliasProxy.h Show annotated file Show diff for this revision Revisions of this file
BinaryFunctionals.h Show annotated file Show diff for this revision Revisions of this file
CommaInitializer.h Show annotated file Show diff for this revision Revisions of this file
CompileTimeError.h Show annotated file Show diff for this revision Revisions of this file
Extremum.h Show annotated file Show diff for this revision Revisions of this file
Functional.h Show annotated file Show diff for this revision Revisions of this file
Io.h Show annotated file Show diff for this revision Revisions of this file
Matrix.h Show annotated file Show diff for this revision Revisions of this file
MatrixBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
MatrixEval.h Show annotated file Show diff for this revision Revisions of this file
MatrixFunctions.h Show annotated file Show diff for this revision Revisions of this file
MatrixImpl.h Show annotated file Show diff for this revision Revisions of this file
MatrixOperators.h Show annotated file Show diff for this revision Revisions of this file
MatrixUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
NumericTraits.h Show annotated file Show diff for this revision Revisions of this file
RunTimeError.h Show annotated file Show diff for this revision Revisions of this file
TvmetBase.h Show annotated file Show diff for this revision Revisions of this file
TypePromotion.h Show annotated file Show diff for this revision Revisions of this file
UnaryFunctionals.h Show annotated file Show diff for this revision Revisions of this file
Vector.h Show annotated file Show diff for this revision Revisions of this file
VectorBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
VectorEval.h Show annotated file Show diff for this revision Revisions of this file
VectorFunctions.h Show annotated file Show diff for this revision Revisions of this file
VectorImpl.h Show annotated file Show diff for this revision Revisions of this file
VectorOperators.h Show annotated file Show diff for this revision Revisions of this file
VectorUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
config/config-gcc.h Show annotated file Show diff for this revision Revisions of this file
config/config-icc.h Show annotated file Show diff for this revision Revisions of this file
config/config-kcc.h Show annotated file Show diff for this revision Revisions of this file
config/config-pgi.h Show annotated file Show diff for this revision Revisions of this file
config/config-vc71.h Show annotated file Show diff for this revision Revisions of this file
loop/Gemm.h Show annotated file Show diff for this revision Revisions of this file
loop/Gemmt.h Show annotated file Show diff for this revision Revisions of this file
loop/Gemtm.h Show annotated file Show diff for this revision Revisions of this file
loop/Gemtv.h Show annotated file Show diff for this revision Revisions of this file
loop/Gemv.h Show annotated file Show diff for this revision Revisions of this file
loop/Matrix.h Show annotated file Show diff for this revision Revisions of this file
loop/Vector.h Show annotated file Show diff for this revision Revisions of this file
meta/Gemm.h Show annotated file Show diff for this revision Revisions of this file
meta/Gemmt.h Show annotated file Show diff for this revision Revisions of this file
meta/Gemtm.h Show annotated file Show diff for this revision Revisions of this file
meta/Gemtv.h Show annotated file Show diff for this revision Revisions of this file
meta/Gemv.h Show annotated file Show diff for this revision Revisions of this file
meta/Matrix.h Show annotated file Show diff for this revision Revisions of this file
meta/Vector.h Show annotated file Show diff for this revision Revisions of this file
tvmet.h Show annotated file Show diff for this revision Revisions of this file
util/General.h Show annotated file Show diff for this revision Revisions of this file
util/Incrementor.h Show annotated file Show diff for this revision Revisions of this file
util/Random.h Show annotated file Show diff for this revision Revisions of this file
util/Timer.h Show annotated file Show diff for this revision Revisions of this file
xpr/BinOperator.h Show annotated file Show diff for this revision Revisions of this file
xpr/Eval.h Show annotated file Show diff for this revision Revisions of this file
xpr/Identity.h Show annotated file Show diff for this revision Revisions of this file
xpr/Literal.h Show annotated file Show diff for this revision Revisions of this file
xpr/MMProduct.h Show annotated file Show diff for this revision Revisions of this file
xpr/MMProductTransposed.h Show annotated file Show diff for this revision Revisions of this file
xpr/MMtProduct.h Show annotated file Show diff for this revision Revisions of this file
xpr/MVProduct.h Show annotated file Show diff for this revision Revisions of this file
xpr/Matrix.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixCol.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixDiag.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixFunctions.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixOperators.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixRow.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixTranspose.h Show annotated file Show diff for this revision Revisions of this file
xpr/MatrixUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
xpr/MtMProduct.h Show annotated file Show diff for this revision Revisions of this file
xpr/MtVProduct.h Show annotated file Show diff for this revision Revisions of this file
xpr/Null.h Show annotated file Show diff for this revision Revisions of this file
xpr/UnOperator.h Show annotated file Show diff for this revision Revisions of this file
xpr/Vector.h Show annotated file Show diff for this revision Revisions of this file
xpr/VectorBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
xpr/VectorFunctions.h Show annotated file Show diff for this revision Revisions of this file
xpr/VectorOperators.h Show annotated file Show diff for this revision Revisions of this file
xpr/VectorUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AliasProxy.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,128 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: AliasProxy.h,v 1.8 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_ALIAS_PROXY_H
+#define TVMET_ALIAS_PROXY_H
+
+namespace tvmet {
+
+
+/** forwards */
+template<class E> class AliasProxy;
+
+
+/**
+ * \brief Simplify syntax for alias Matrices and Vectors,
+ *        where aliasing left hand values appear in the
+ *        expression.
+ * \par Example:
+ * \code
+ * typedef tvmet::Matrix<double, 10, 10>	matrix_type;
+ * matrix_type					m;
+ * ...
+ * alias(m) += trans(m);
+ * \endcode
+ * \sa AliasProxy
+ * \sa Some Notes \ref alias
+ */
+template<class E>
+AliasProxy<E> alias(E& expr) { return AliasProxy<E>(expr); }
+
+
+/**
+ * \class AliasProxy AliasProxy.h "tvmet/AliasProxy.h"
+ * \brief Assign proxy for alias Matrices and Vectors.
+ *
+ *        A short lived object to provide simplified alias syntax.
+ *        Only the friend function alias is allowed to create
+ *        such a object. The proxy calls the appropriate member
+ *        alias_xyz() which have to use temporaries to avoid
+ *        overlapping memory regions.
+ * \sa alias
+ * \sa Some Notes \ref alias
+ * \note Thanks to ublas-dev group, where the principle idea
+ *       comes from.
+ */
+template<class E>
+class AliasProxy
+{
+  AliasProxy(const AliasProxy&);
+  AliasProxy& operator=(const AliasProxy&);
+
+  friend AliasProxy<E> alias<>(E& expr);
+
+public:
+  AliasProxy(E& expr) : m_expr(expr) { }
+
+
+  template<class E2>
+  E& operator=(const E2& expr) {
+    return m_expr.alias_assign(expr);
+  }
+
+  template<class E2>
+  E& operator+=(const E2& expr) {
+    return m_expr.alias_add_eq(expr);
+  }
+
+  template<class E2>
+  E& operator-=(const E2& expr) {
+    return m_expr.alias_sub_eq(expr);
+  }
+
+  template<class E2>
+  E& operator*=(const E2& expr) {
+    return m_expr.alias_mul_eq(expr);
+  }
+
+  template<class E2>
+  E& operator/=(const E2& expr) {
+    return m_expr.alias_div_eq(expr);
+  }
+
+private:
+  E&						m_expr;
+};
+
+
+#if 0
+namespace element_wise {
+// \todo to write
+template<class E, class E2>
+E& operator/=(AliasProxy<E>& proxy, const E2& rhs) {
+  return proxy.div_upd(rhs);
+}
+
+}
+#endif
+
+
+} // namespace tvmet
+
+
+#endif /* TVMET_ALIAS_PROXY_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BinaryFunctionals.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,303 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: BinaryFunctionals.h,v 1.24 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_BINARY_FUNCTIONAL_H
+#define TVMET_BINARY_FUNCTIONAL_H
+
+namespace tvmet {
+
+
+/**
+ * \class Fcnl_assign BinaryFunctionals.h "tvmet/BinaryFunctionals.h"
+ * \brief Binary operator for assign operations.
+ *
+ * Unfortunally we have sometimes to cast on assign operations e.g.,
+ * on assign on different POD. So we avoid warnings.
+ */
+template <class T1, class T2>
+struct Fcnl_assign : public BinaryFunctional {
+  static inline
+  void apply_on(T1& _tvmet_restrict lhs, T2 rhs) {
+    lhs = static_cast<T1>(rhs);
+  }
+
+  static
+  void print_xpr(std::ostream& os, std::size_t l=0) {
+    os << IndentLevel(l) << "fcnl_assign<T1="
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"
+       << std::endl;
+  }
+};
+
+
+/** \class Fcnl_add_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_sub_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_mul_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_div_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_mod_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_xor_eq		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_and_eq		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_or_eq		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_shl_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_shr_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class T1, class T2>						\
+struct Fcnl_##NAME : public BinaryFunctional {				\
+  typedef void						value_type;	\
+									\
+  static inline								\
+  void apply_on(T1& _tvmet_restrict lhs, T2 rhs) {			\
+    lhs OP rhs;								\
+  }									\
+									\
+  static								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l)						\
+       << "Fcnl_" << #NAME << "<T1="					\
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"	\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(add_eq, +=)
+TVMET_IMPLEMENT_MACRO(sub_eq, -=)
+TVMET_IMPLEMENT_MACRO(mul_eq, *=)
+TVMET_IMPLEMENT_MACRO(div_eq, /=)
+TVMET_IMPLEMENT_MACRO(mod_eq, %=)
+TVMET_IMPLEMENT_MACRO(xor_eq, ^=)
+TVMET_IMPLEMENT_MACRO(and_eq, &=)
+TVMET_IMPLEMENT_MACRO(or_eq, |=)
+TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
+TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_add 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_sub 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_mul 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_div 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_mod 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_bitxor		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_bitand		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_bitor		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_shl 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_shr 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class T1, class T2>						\
+struct Fcnl_##NAME : public BinaryFunctional {				\
+  typedef typename  PromoteTraits<T1, T2>::value_type	value_type;	\
+  									\
+  static inline 							\
+  value_type apply_on(T1 lhs, T2 rhs) {					\
+    return lhs OP rhs;							\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l)						\
+       << "Fcnl_" << #NAME << "<T1="					\
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"	\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(add, +)
+TVMET_IMPLEMENT_MACRO(sub, -)
+TVMET_IMPLEMENT_MACRO(mul, *)
+TVMET_IMPLEMENT_MACRO(div, /)
+TVMET_IMPLEMENT_MACRO(mod, %)
+TVMET_IMPLEMENT_MACRO(bitxor, ^)
+TVMET_IMPLEMENT_MACRO(bitand, &)
+TVMET_IMPLEMENT_MACRO(bitor, |)
+TVMET_IMPLEMENT_MACRO(shl, <<)
+TVMET_IMPLEMENT_MACRO(shr, >>)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_greater 	BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_greater_eq 	BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_less 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_less_eq 	BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_not_eq 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_and 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_or 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class T1, class T2>						\
+struct Fcnl_##NAME : public BinaryFunctional {				\
+  typedef bool						value_type;	\
+  									\
+  static inline								\
+  bool apply_on(T1 lhs, T2 rhs) {					\
+    return lhs OP rhs;							\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l)						\
+       << "Fcnl_" << #NAME << "<T1="					\
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"	\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_atan2 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_fmod 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_pow 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T1, class T2>						\
+struct Fcnl_##NAME : public BinaryFunctional {				\
+  typedef typename PromoteTraits<T1, T2>::value_type	value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(T1 lhs, T2 rhs) {					\
+    return TVMET_STD_SCOPE(NAME)(lhs, rhs);				\
+  }									\
+   									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l)						\
+       << "Fcnl_" << #NAME << "<T1="					\
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"	\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(pow)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_drem 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_hypot 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_jn 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+/** \class Fcnl_yn 		BinaryFunctionals.h "tvmet/BinaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T1, class T2>						\
+struct Fcnl_##NAME : public BinaryFunctional {				\
+  typedef typename PromoteTraits<T1, T2>::value_type	value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(T1 lhs, T2 rhs) {					\
+    return TVMET_GLOBAL_SCOPE(NAME)(lhs, rhs);				\
+  }									\
+   									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l)						\
+       << "Fcnl_" << #NAME << "<T1="					\
+       << typeid(T1).name() << ", T2=" << typeid(T2).name() << ">,"	\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/**
+ * \class Fcnl_polar BinaryFunctionals.h "tvmet/BinaryFunctionals.h"
+ * \brief %Functional for polar.
+ */
+template <class T1, class T2> struct Fcnl_polar : public BinaryFunctional { };
+
+
+/**
+ * \class Fcnl_polar<T,T> BinaryFunctionals.h "tvmet/BinaryFunctionals.h"
+ * \brief %Functional for polar.
+ * \note  This functional is partialy specialized due to the declaration
+ *        of %polar in namespace std <tt>complex<T> polar(T, T)</tt>.
+ *        This means especially that type promotion isn't avaible here.
+ */
+template <class T>
+struct Fcnl_polar<T,T> : public BinaryFunctional {
+  typedef std::complex<T>                               value_type;
+
+  static inline
+  value_type apply_on(T lhs, T rhs) {
+    return std::polar(lhs, rhs);
+  }
+
+  static
+  void print_xpr(std::ostream& os, std::size_t l=0) {
+    os << IndentLevel(l) << "Fcnl_polar<T1="
+       << typeid(T).name() << ", T2=" << typeid(T).name() << ">,"
+       << std::endl;
+  }
+};
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/**
+ * \class Fcnl_swap BinaryFunctionals.h "tvmet/BinaryFunctionals.h"
+ * \brief Binary operator for swapping values using temporaries.
+ */
+template <class T1, class T2>
+struct Fcnl_swap : public BinaryFunctional {
+  static inline
+  void apply_on(T1& _tvmet_restrict lhs, T2& _tvmet_restrict rhs) {
+    typedef typename  PromoteTraits<T1, T2>::value_type	temp_type;
+
+    temp_type 						temp(lhs);
+    lhs = static_cast<T1>(rhs);
+    rhs = static_cast<T2>(temp);
+  }
+
+  static
+  void print_xpr(std::ostream& os, std::size_t l=0) {
+    os << IndentLevel(l) << "Fcnl_swap<T1="
+       << typeid(T1).name() << ", T2" << typeid(T2).name() << ">,"
+       << std::endl;
+  }
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_BINARY_FUNCTIONAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CommaInitializer.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,164 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: CommaInitializer.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_COMMA_INITIALIZER_H
+#define TVMET_COMMA_INITIALIZER_H
+
+#include <tvmet/CompileTimeError.h>
+
+namespace tvmet {
+
+
+/**
+ * \class CommaInitializer CommaInitializer.h "tvmet/CommaInitializer.h"
+ * \brief Initialize classes using a comma separated lists.
+ *
+ * The comma operator is called when it appears next to an object of
+ * the type the comma is defined for. However, "operator," is not called
+ * for function argument lists, only for objects that are out in the open,
+ * separated by commas (Thinking C++
+ * <a href=http://www.ida.liu.se/~TDDA14/online/v1ticpp/Chapter12.html>
+ * Ch.12: Operator comma</a>).
+ *
+ * This implementation uses the same technique as described in Todd Veldhuizen
+ * Techniques for Scientific C++
+ * <a href=http://extreme.indiana.edu/~tveldhui/papers/techniques/techniques01.html#l43>
+ * chapter 1.11 Comma overloading</a>.
+ *
+ * The initializer list is avaible after instanciation of the object,
+ * therefore use it like:
+ * \code
+ * vector3d t;
+ * t = 1.0, 2.0, 3.0;
+ * \endcode
+ * It's evaluated to (((t = 1.0), 2.0), 3.0)
+ *
+ * For matrizes the initilization is done row wise.
+ *
+ * If the comma separted list of values longer then the size of the vector
+ * or matrix a compile time error will occour. Otherwise the pending values
+ * will be written random into the memory.
+ *
+ */
+template<class Obj, std::size_t LEN>
+class CommaInitializer
+{
+  CommaInitializer();
+  CommaInitializer& operator=(const CommaInitializer&);
+
+private:
+  /**
+   * \class Initializer
+   * \brief Helper fo recursive overloaded comma operator.
+   */
+  template<class T, std::size_t N> class Initializer
+  {
+    Initializer();
+    Initializer& operator=(const Initializer&);
+
+  public:
+    typedef T						value_type;
+    typedef T*						iterator;
+
+  public:
+    Initializer(iterator iter) : m_iter(iter) { }
+
+    /** Overloads the comma operator for recursive assign values from comma
+	separated list. */
+    Initializer<value_type, N+1> operator,(value_type rhs)
+    {
+      TVMET_CT_CONDITION(N < LEN, CommaInitializerList_is_too_long)
+      *m_iter = rhs;
+      return Initializer<value_type, N+1>(m_iter + 1);
+    }
+
+  private:
+    iterator 						m_iter;
+  };
+
+public:
+  typedef typename Obj::value_type 			value_type;
+  typedef value_type*					iterator;
+
+public:
+  CommaInitializer(const CommaInitializer& rhs)
+    : m_object(rhs.m_object),
+      m_data(rhs.m_data),
+      m_wipeout_on_destruct(true)
+  {
+    rhs.disable();
+  }
+
+  /** Constructor used by Vector or Matrix operator(value_type rhs) */
+  CommaInitializer(Obj& obj, value_type x)
+    : m_object(obj),
+      m_data(x),
+      m_wipeout_on_destruct(true)
+  { }
+
+  /** Destructs and assigns the comma separated value. */
+  ~CommaInitializer() {
+    if(m_wipeout_on_destruct) m_object.assign_value(m_data);
+  }
+
+  /** Overloaded comma operator, called only once for the first occoured comma. This
+      means the first value is assigned by %operator=() and the 2nd value after the
+      comma. Therfore we call the %Initializer::operator,() for the list starting
+      after the 2nd. */
+  Initializer<value_type, 2> operator,(value_type rhs);
+
+  void disable() const { m_wipeout_on_destruct = false; }
+
+private:
+  Obj& 							m_object;
+  value_type 						m_data;
+  mutable bool 						m_wipeout_on_destruct;
+};
+
+
+/*
+ * Implementation
+ */
+template<class Obj, std::size_t LEN>
+typename CommaInitializer<Obj, LEN>::template Initializer<typename Obj::value_type, 2>
+CommaInitializer<Obj, LEN>::operator,(typename Obj::value_type rhs)
+{
+  m_wipeout_on_destruct = false;
+  iterator iter1 = m_object.data();
+  *iter1         = m_data;
+  iterator iter2 = iter1 + 1;
+  *iter2         = rhs;
+  return Initializer<value_type, 2>(iter2 + 1);
+}
+
+
+
+} // namespace tvmet
+
+
+#endif //  TVMET_COMMA_INITIALIZER_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CompileTimeError.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,60 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: CompileTimeError.h,v 1.11 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_COMPILE_TIME_ERROR_H
+#define TVMET_COMPILE_TIME_ERROR_H
+
+namespace tvmet {
+
+/**
+ * \class CompileTimeError CompileTimeError.h "tvmet/CompileTimeError.h"
+ * \brief Compile Time Assertation classes.
+ */
+template<bool> struct CompileTimeError;
+
+/**
+ * \class CompileTimeError<true> CompileTimeError.h "tvmet/CompileTimeError.h"
+ * \brief Specialized Compile Time Assertation for successfully condition.
+ * This results in a compiler pass.
+ */
+template<> struct CompileTimeError<true> { };
+
+
+/**
+ * \def TVMET_CT_CONDITION(XPR, MSG)
+ * \brief Simplify the Compile Time Assertation by using an expression
+ * Xpr and an error message MSG.
+ */
+#define TVMET_CT_CONDITION(XPR, MSG) {				\
+  CompileTimeError<(XPR)> tvmet_ERROR_##MSG;			\
+  (void)tvmet_ERROR_##MSG;					\
+}
+
+} // namespace tvmet
+
+#endif // TVMET_COMPILE_TIME_ERROR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Extremum.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,108 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Extremum.h,v 1.10 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_EXTREMUM_H
+#define TVMET_EXTREMUM_H
+
+namespace tvmet {
+
+
+/**
+ * \class matrix_tag Extremum.h "tvmet/Extremum.h"
+ * \brief For use with Extremum to simplify max handling.
+ * This allows the min/max functions to return an Extremum object.
+ */
+struct matrix_tag { };
+
+
+/**
+ * \class vector_tag Extremum.h "tvmet/Extremum.h"
+ * \brief For use with Extremum to simplify max handling.
+ * This allows the min/max functions to return an Extremum object.
+ */
+struct vector_tag { };
+
+
+/**
+ * \class Extremum Extremum.h "tvmet/Extremum.h"
+ * \brief Generell class for storing extremums determined by min/max.
+ */
+template<class T1, class T2, class Tag>
+class Extremum { };
+
+
+/**
+ * \class Extremum<T1, T2, vector_tag> Extremum.h "tvmet/Extremum.h"
+ * \brief Partial specialzed for vectors to store extremums by value and index.
+ */
+template<class T1, class T2>
+class Extremum<T1, T2, vector_tag>
+{
+public:
+  typedef T1					value_type;
+  typedef T2					index_type;
+
+public:
+  Extremum(value_type value, index_type index)
+    : m_value(value), m_index(index) { }
+  value_type value() const { return m_value; }
+  index_type index() const { return m_index; }
+
+private:
+  value_type 					m_value;
+  index_type 					m_index;
+};
+
+
+/**
+ * \class Extremum<T1, T2, matrix_tag> Extremum.h "tvmet/Extremum.h"
+ * \brief Partial specialzed for matrix to store extremums by value, row and column.
+ */
+template<class T1, class T2>
+class Extremum<T1, T2, matrix_tag>
+{
+public:
+  typedef T1					value_type;
+  typedef T2					index_type;
+
+public:
+  Extremum(value_type value, index_type row, index_type col)
+    : m_value(value), m_row(row), m_col(col) { }
+  value_type value() const { return m_value; }
+  index_type row() const { return m_row; }
+  index_type col() const { return m_col; }
+
+private:
+  value_type 					m_value;
+  index_type 					m_row, m_col;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_EXTREMUM_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Functional.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,88 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Functional.h,v 1.11 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_FUNCTIONAL_H
+#define TVMET_FUNCTIONAL_H
+
+#include <tvmet/TypePromotion.h>
+
+namespace tvmet {
+
+
+/**
+ * \class Functional Functional.h "tvmet/Functional.h"
+ * \brief Base class for all binary und unary functionals.
+ *
+ * All functional operators and functions have a static apply
+ * member function for evaluating the expressions inside.
+ */
+struct Functional { };
+
+
+/**
+ * \class BinaryFunctional Functional.h "tvmet/Functional.h"
+ * \brief Base class for all binary functions.
+ * \note Used for collecting classes for doxygen.
+ */
+struct BinaryFunctional : public Functional { };
+
+
+/**
+ * \class UnaryFunctional Functional.h "tvmet/Functional.h"
+ * \brief Base class for all unary functions.
+ * \note Used for collecting classes for doxygen.
+ */
+struct UnaryFunctional : public Functional { };
+
+
+/*
+ * some macro magic need below
+ */
+
+/**
+ * \def TVMET_STD_SCOPE(x)
+ * \brief Simple macro to allow using macros for namespace std functions.
+ */
+#define TVMET_STD_SCOPE(x) std::x
+
+
+/**
+ * \def TVMET_GLOBAL_SCOPE(x)
+ * \brief Simple macro to allow using macros for global namespace functions.
+ */
+#define TVMET_GLOBAL_SCOPE(x) ::x
+
+
+} // namespace tvmet
+
+
+#include <tvmet/BinaryFunctionals.h>
+#include <tvmet/UnaryFunctionals.h>
+
+
+#endif // TVMET_FUNCTIONAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Io.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,69 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Io.h,v 1.8 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_IO_H
+#define TVMET_IO_H
+
+namespace tvmet {
+
+/**
+ * \class IoPrintHelper Io.h "tvmet/Io.h"
+ * \brief Determines the number of digits regarding the sign of the
+ *        container.
+ *        This class is nesessary due to the complex type and the
+ *        function min(), which are not defined for this type.
+ *        So we have to dispatch between pod and complex types
+ *        to get an information about the extra space for signs.
+ */
+template<class C>
+class IoPrintHelper {
+  IoPrintHelper();
+  IoPrintHelper(const IoPrintHelper&);
+  IoPrintHelper& operator=(const IoPrintHelper&);
+
+private:
+  static std::streamsize width(const C& e) {
+    std::streamsize w = static_cast<std::streamsize>(std::log10(max(abs(e)))+1);
+    return w > 0 ? w : 0;
+  }
+
+public:
+  static std::streamsize width(dispatch<true>, const C& e) {
+    return width(e);
+  }
+  static std::streamsize width(dispatch<false>, const C& e) {
+    std::streamsize w = width(e);
+    if(min(e) < 0) return w+1;
+    else return w;
+  }
+};
+
+
+}
+
+#endif /* TVMET_IO_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Matrix.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,476 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Matrix.h,v 1.58 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_H
+#define TVMET_MATRIX_H
+
+#include <iterator>					// reverse_iterator
+
+#include <tvmet/tvmet.h>
+#include <tvmet/TypePromotion.h>
+#include <tvmet/CommaInitializer.h>
+#include <tvmet/RunTimeError.h>
+
+#include <tvmet/xpr/Matrix.h>
+#include <tvmet/xpr/MatrixRow.h>
+#include <tvmet/xpr/MatrixCol.h>
+#include <tvmet/xpr/MatrixDiag.h>
+
+namespace tvmet {
+
+
+/* forwards */
+template<class T, std::size_t Rows, std::size_t Cols> class Matrix;
+template<class T,
+	 std::size_t RowsBgn, std::size_t RowsEnd,
+	 std::size_t ColsBgn, std::size_t ColsEnd,
+	 std::size_t RowStride, std::size_t ColStride /*=1*/>
+class MatrixSliceConstReference; // unused here; for me only
+
+
+/**
+ * \class MatrixConstReference Matrix.h "tvmet/Matrix.h"
+ * \brief value iterator for ET
+ */
+template<class T, std::size_t NRows, std::size_t NCols>
+class MatrixConstReference
+  : public TvmetBase < MatrixConstReference<T, NRows, NCols> >
+{
+public:
+  typedef T						value_type;
+  typedef T*						pointer;
+  typedef const T*					const_pointer;
+
+  /** Dimensions. */
+  enum {
+    Rows = NRows,			/**< Number of rows. */
+    Cols = NCols,			/**< Number of cols. */
+    Size = Rows * Cols			/**< Complete Size of Matrix. */
+  };
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops       = Rows * Cols
+  };
+
+private:
+  MatrixConstReference();
+  MatrixConstReference& operator=(const MatrixConstReference&);
+
+public:
+  /** Constructor. */
+  explicit MatrixConstReference(const Matrix<T, Rows, Cols>& rhs)
+    : m_data(rhs.data())
+  { }
+
+  /** Constructor by a given memory pointer. */
+  explicit MatrixConstReference(const_pointer data)
+    : m_data(data)
+  { }
+
+public: // access operators
+  /** access by index. */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Rows) && (j < Cols), "MatrixConstReference Bounce Violation")
+    return m_data[i * Cols + j];
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l)
+       << "MatrixConstReference[O=" << ops << "]<"
+       << "T=" << typeid(value_type).name() << ">,"
+       << std::endl;
+  }
+
+private:
+  const_pointer _tvmet_restrict 			m_data;
+};
+
+
+/**
+ * \class Matrix Matrix.h "tvmet/Matrix.h"
+ * \brief A tiny matrix class.
+ *
+ * The array syntax A[j][j] isn't supported here. The reason is that
+ * operator[] always takes exactly one parameter, but operator() can
+ * take any number of parameters (in the case of a rectangular matrix,
+ * two paramters are needed). Therefore the cleanest way to do it is
+ * with operator() rather than with operator[]. \see C++ FAQ Lite 13.8
+ */
+template<class T, std::size_t NRows, std::size_t NCols>
+class Matrix
+{
+public:
+  /** Data type of the tvmet::Matrix. */
+  typedef T						value_type;
+
+  /** Reference type of the tvmet::Matrix data elements. */
+  typedef T&     					reference;
+
+  /** const reference type of the tvmet::Matrix data elements. */
+  typedef const T&     					const_reference;
+
+  /** STL iterator interface. */
+  typedef T*     					iterator;
+
+  /** STL const_iterator interface. */
+  typedef const T*     					const_iterator;
+
+  /** STL reverse iterator interface. */
+  typedef std::reverse_iterator<iterator> 		reverse_iterator;
+
+  /** STL const reverse iterator interface. */
+  typedef std::reverse_iterator<const_iterator> 	const_reverse_iterator;
+
+public:
+  /** Dimensions. */
+  enum {
+    Rows = NRows,			/**< Number of rows. */
+    Cols = NCols,			/**< Number of cols. */
+    Size = Rows * Cols			/**< Complete Size of Matrix. */
+  };
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_assign = Rows * Cols,
+    ops        = ops_assign,
+    use_meta   = ops < TVMET_COMPLEXITY_M_ASSIGN_TRIGGER ? true : false
+  };
+
+public: // STL  interface
+  /** STL iterator interface. */
+  iterator begin() { return m_data; }
+
+  /** STL iterator interface. */
+  iterator end() { return m_data + Size; }
+
+  /** STL const_iterator interface. */
+  const_iterator begin() const { return m_data; }
+
+  /** STL const_iterator interface. */
+  const_iterator end() const { return m_data + Size; }
+
+  /** STL reverse iterator interface reverse begin. */
+  reverse_iterator rbegin() { return reverse_iterator( end() ); }
+
+  /** STL const reverse iterator interface reverse begin. */
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator( end() );
+  }
+
+  /** STL reverse iterator interface reverse end. */
+  reverse_iterator rend() { return reverse_iterator( begin() ); }
+
+  /** STL const reverse iterator interface reverse end. */
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator( begin() );
+  }
+
+  /** The size of the matrix. */
+  static std::size_t size() { return Size; }
+
+  /** STL vector max_size() - returns allways rows()*cols(). */
+  static std::size_t max_size() { return Size; }
+
+  /** STL vector empty() - returns allways false. */
+  static bool empty() { return false; }
+
+public:
+  /** The number of rows of matrix. */
+  static std::size_t rows() { return Rows; }
+
+  /** The number of columns of matrix. */
+  static std::size_t cols() { return Cols; }
+
+public:
+  /** Default Destructor */
+  ~Matrix() {
+#if defined(TVMET_DYNAMIC_MEMORY)
+    delete [] m_data;
+#endif
+  }
+
+  /** Default Constructor. The allocated memory region isn't cleared. If you want
+   a clean use the constructor argument zero. */
+  explicit Matrix()
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  { }
+
+  /** Copy Constructor, not explicit! */
+  Matrix(const Matrix& rhs)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    *this = XprMatrix<ConstReference, Rows, Cols>(rhs.const_ref());
+  }
+
+  /**
+   * Constructor with STL iterator interface. The data will be copied into the matrix
+   * self, there isn't any stored reference to the array pointer.
+   */
+  template<class InputIterator>
+  explicit Matrix(InputIterator first, InputIterator last)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_RT_CONDITION(static_cast<std::size_t>(std::distance(first, last)) <= Size,
+		       "InputIterator doesn't fits in size" )
+    std::copy(first, last, m_data);
+  }
+
+  /**
+   * Constructor with STL iterator interface. The data will be copied into the matrix
+   * self, there isn't any stored reference to the array pointer.
+   */
+  template<class InputIterator>
+  explicit Matrix(InputIterator first, std::size_t sz)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_RT_CONDITION(sz <= Size, "InputIterator doesn't fits in size" )
+    std::copy(first, first + sz, m_data);
+  }
+
+  /** Construct the matrix by value. */
+  explicit Matrix(value_type rhs)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    typedef XprLiteral<value_type> expr_type;
+    *this = XprMatrix<expr_type, Rows, Cols>(expr_type(rhs));
+  }
+
+  /** Construct a matrix by expression. */
+  template<class E>
+  explicit Matrix(const XprMatrix<E, Rows, Cols>& e)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    *this = e;
+  }
+
+  /** assign a value_type on array, this can be used for a single value
+      or a comma separeted list of values. */
+  CommaInitializer<Matrix, Size> operator=(value_type rhs) {
+    return CommaInitializer<Matrix, Size>(*this, rhs);
+  }
+
+public: // access operators
+  value_type* _tvmet_restrict data() { return m_data; }
+  const value_type* _tvmet_restrict data() const { return m_data; }
+
+public: // index access operators
+  value_type& _tvmet_restrict operator()(std::size_t i, std::size_t j) {
+    // Note: g++-2.95.3 does have problems on typedef reference
+    TVMET_RT_CONDITION((i < Rows) && (j < Cols), "Matrix Bounce Violation")
+    return m_data[i * Cols + j];
+  }
+
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Rows) && (j < Cols), "Matrix Bounce Violation")
+    return m_data[i * Cols + j];
+  }
+
+public: // ET interface
+  typedef MatrixConstReference<T, Rows, Cols>   	ConstReference;
+
+  typedef MatrixSliceConstReference<
+    T,
+    0, Rows, 0, Cols,
+    Rows, 1
+  >							SliceConstReference;
+
+  /** Return a const Reference of the internal data */
+  ConstReference const_ref() const { return ConstReference(*this); }
+
+  /**
+   * Return a sliced const Reference of the internal data.
+   * \note Doesn't work since isn't implemented, but it is in
+   * progress. Therefore this is a placeholder. */
+  ConstReference const_sliceref() const { return SliceConstReference(*this); }
+
+  /** Return the vector as const expression. */
+  XprMatrix<ConstReference, Rows, Cols> as_expr() const {
+    return XprMatrix<ConstReference, Rows, Cols>(this->const_ref());
+  }
+
+private:
+  /** Wrapper for meta assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    meta::Matrix<Rows, Cols, 0, 0>::assign(dest, src, assign_fn);
+  }
+
+  /** Wrapper for loop assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    loop::Matrix<Rows, Cols>::assign(dest, src, assign_fn);
+  }
+
+private:
+  /** assign this to a matrix  of a different type T2 using
+      the functional assign_fn. */
+  template<class T2, class Assign>
+  void assign_to(Matrix<T2, Rows, Cols>& dest, const Assign& assign_fn) const {
+    do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
+  }
+
+public:  // assign operations
+  /** assign a given matrix of a different type T2 element wise
+      to this matrix. The operator=(const Matrix&) is compiler
+      generated. */
+  template<class T2>
+  Matrix& operator=(const Matrix<T2, Rows, Cols>& rhs) {
+    rhs.assign_to(*this, Fcnl_assign<value_type, T2>());
+    return *this;
+  }
+
+  /** assign a given XprMatrix element wise to this matrix. */
+  template <class E>
+  Matrix& operator=(const XprMatrix<E, Rows, Cols>& rhs) {
+    rhs.assign_to(*this, Fcnl_assign<value_type, typename E::value_type>());
+    return *this;
+  }
+
+private:
+  template<class Obj, std::size_t LEN> friend class CommaInitializer;
+
+  /** This is a helper for assigning a comma separated initializer
+      list. It's equal to Matrix& operator=(value_type) which does
+      replace it. */
+  Matrix& assign_value(value_type rhs) {
+    typedef XprLiteral<value_type> 			expr_type;
+    *this = XprMatrix<expr_type, Rows, Cols>(expr_type(rhs));
+    return *this;
+  }
+
+public: // math operators with scalars
+  // NOTE: this meaning is clear - element wise ops even if not in ns element_wise
+  Matrix& operator+=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator-=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator*=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator/=(value_type) TVMET_CXX_ALWAYS_INLINE;
+
+  Matrix& operator%=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator^=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator&=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator|=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator<<=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Matrix& operator>>=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+
+public: // math operators with matrizes
+  // NOTE: access using the operators in ns element_wise, since that's what is does
+  template <class T2> Matrix& M_add_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_sub_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_mul_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_div_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_mod_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_xor_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_and_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_or_eq (const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_shl_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& M_shr_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // math operators with expressions
+  // NOTE: access using the operators in ns element_wise, since that's what is does
+  template <class E> Matrix& M_add_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_sub_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_mul_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_div_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_mod_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_xor_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_and_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_or_eq (const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_shl_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& M_shr_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // aliased math operators with expressions
+  template <class T2> Matrix& alias_assign(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& alias_add_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& alias_sub_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& alias_mul_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Matrix& alias_div_eq(const Matrix<T2, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+
+  template <class E> Matrix& alias_assign(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& alias_add_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& alias_sub_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& alias_mul_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Matrix& alias_div_eq(const XprMatrix<E, Rows, Cols>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // io
+  /** Structure for info printing as Matrix<T, Rows, Cols>. */
+  struct Info : public TvmetBase<Info> {
+    std::ostream& print_xpr(std::ostream& os) const {
+      os << "Matrix<T=" << typeid(value_type).name()
+	 << ", R=" << Rows << ", C=" << Cols << ">";
+      return os;
+    }
+  };
+
+  /** Get an info object of this matrix. */
+  static Info info() { return Info(); }
+
+  /** Member function for expression level printing. */
+  std::ostream& print_xpr(std::ostream& os, std::size_t l=0) const;
+
+  /** Member function for printing internal data. */
+  std::ostream& print_on(std::ostream& os) const;
+
+private:
+  /** The data of matrix self. */
+#if defined(TVMET_DYNAMIC_MEMORY)
+  value_type*						m_data;
+#else
+  value_type 						m_data[Size];
+#endif
+};
+
+
+} // namespace tvmet
+
+#include <tvmet/MatrixImpl.h>
+#include <tvmet/MatrixFunctions.h>
+#include <tvmet/MatrixBinaryFunctions.h>
+#include <tvmet/MatrixUnaryFunctions.h>
+#include <tvmet/MatrixOperators.h>
+#include <tvmet/MatrixEval.h>
+#include <tvmet/AliasProxy.h>
+
+#endif // TVMET_MATRIX_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixBinaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,533 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixBinaryFunctions.h,v 1.16 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_BINARY_FUNCTIONS_H
+#define TVMET_MATRIX_BINARY_FUNCTIONS_H
+
+namespace tvmet {
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * binary_function(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * binary_function(Matrix<T1, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ * binary_function(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>	\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    MatrixConstReference<T1, Rows, Cols>,				\
+    MatrixConstReference<T2, Rows, Cols>				\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const Matrix<T1, Rows, Cols>& lhs, 				\
+     const Matrix<T2, Cols, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, class T, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, 				\
+     const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+									\
+template<class E, class T, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const Matrix<T, Rows, Cols>& lhs, 					\
+     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+TVMET_DECLARE_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_DECLARE_MACRO(polar)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * binary_function(Matrix<T, Rows, Cols>, POD)
+ */
+#define TVMET_DECLARE_MACRO(NAME, TP)					\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, TP >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral< TP >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const Matrix<T, Rows, Cols>& lhs, TP rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2, int)
+TVMET_DECLARE_MACRO(drem, int)
+TVMET_DECLARE_MACRO(fmod, int)
+TVMET_DECLARE_MACRO(hypot, int)
+TVMET_DECLARE_MACRO(jn, int)
+TVMET_DECLARE_MACRO(yn, int)
+TVMET_DECLARE_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(atan2, long long int)
+TVMET_DECLARE_MACRO(drem, long long int)
+TVMET_DECLARE_MACRO(fmod, long long int)
+TVMET_DECLARE_MACRO(hypot, long long int)
+TVMET_DECLARE_MACRO(jn, long long int)
+TVMET_DECLARE_MACRO(yn, long long int)
+TVMET_DECLARE_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(atan2, float)
+TVMET_DECLARE_MACRO(drem, float)
+TVMET_DECLARE_MACRO(fmod, float)
+TVMET_DECLARE_MACRO(hypot, float)
+TVMET_DECLARE_MACRO(jn, float)
+TVMET_DECLARE_MACRO(yn, float)
+TVMET_DECLARE_MACRO(pow, float)
+
+TVMET_DECLARE_MACRO(atan2, double)
+TVMET_DECLARE_MACRO(drem, double)
+TVMET_DECLARE_MACRO(fmod, double)
+TVMET_DECLARE_MACRO(hypot, double)
+TVMET_DECLARE_MACRO(jn, double)
+TVMET_DECLARE_MACRO(yn, double)
+TVMET_DECLARE_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(atan2, long double)
+TVMET_DECLARE_MACRO(drem, long double)
+TVMET_DECLARE_MACRO(fmod, long double)
+TVMET_DECLARE_MACRO(hypot, long double)
+TVMET_DECLARE_MACRO(jn, long double)
+TVMET_DECLARE_MACRO(yn, long double)
+TVMET_DECLARE_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * complex math
+ */
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+pow(const Matrix<T, Rows, Cols>& lhs,
+    const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow< std::complex<T>, std::complex<T> >,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs,
+    const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/**
+ * \fn pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, const T& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<T>
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs,
+    const T& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/**
+ * \fn pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, int rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<int>
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs,
+    int rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprBinOp<
+    Fcnl_polar<T, T>,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral<T>
+  >,
+  Rows, Cols
+>
+polar(const Matrix<T, Rows, Cols>& lhs,
+      const T& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+// to be written (atan2)
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+/*
+ * binary_function(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * binary_function(Matrix<T1, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ * binary_function(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)						\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME(const Matrix<T1, Rows, Cols>& lhs, const Matrix<T2, Cols, Cols>& rhs) {	\
+  typedef XprBinOp <								\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >							expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs.const_ref(), rhs.const_ref()));				\
+}										\
+										\
+template<class E, class T, std::size_t Rows, std::size_t Cols>			\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    XprMatrix<E, Rows, Cols>,							\
+    MatrixConstReference<T, Rows, Cols>						\
+  > 							 expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs, rhs.const_ref()));						\
+}										\
+										\
+template<class E, class T, std::size_t Rows, std::size_t Cols>			\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T, typename E::value_type>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME(const Matrix<T, Rows, Cols>& lhs, const XprMatrix<E, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  > 						 	expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs.const_ref(), rhs));						\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+TVMET_IMPLEMENT_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_IMPLEMENT_MACRO(polar)
+#endif
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * binary_function(Matrix<T, Rows, Cols>, POD)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, TP)					\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, TP >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral< TP >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const Matrix<T, Rows, Cols>& lhs, TP rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, TP >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs.const_ref(), XprLiteral< TP >(rhs)));			\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2, int)
+TVMET_IMPLEMENT_MACRO(drem, int)
+TVMET_IMPLEMENT_MACRO(fmod, int)
+TVMET_IMPLEMENT_MACRO(hypot, int)
+TVMET_IMPLEMENT_MACRO(jn, int)
+TVMET_IMPLEMENT_MACRO(yn, int)
+TVMET_IMPLEMENT_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(atan2, long long int)
+TVMET_IMPLEMENT_MACRO(drem, long long int)
+TVMET_IMPLEMENT_MACRO(fmod, long long int)
+TVMET_IMPLEMENT_MACRO(hypot, long long int)
+TVMET_IMPLEMENT_MACRO(jn, long long int)
+TVMET_IMPLEMENT_MACRO(yn, long long int)
+TVMET_IMPLEMENT_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(atan2, float)
+TVMET_IMPLEMENT_MACRO(drem, float)
+TVMET_IMPLEMENT_MACRO(fmod, float)
+TVMET_IMPLEMENT_MACRO(hypot, float)
+TVMET_IMPLEMENT_MACRO(jn, float)
+TVMET_IMPLEMENT_MACRO(yn, float)
+TVMET_IMPLEMENT_MACRO(pow, float)
+
+TVMET_IMPLEMENT_MACRO(atan2, double)
+TVMET_IMPLEMENT_MACRO(drem, double)
+TVMET_IMPLEMENT_MACRO(fmod, double)
+TVMET_IMPLEMENT_MACRO(hypot, double)
+TVMET_IMPLEMENT_MACRO(jn, double)
+TVMET_IMPLEMENT_MACRO(yn, double)
+TVMET_IMPLEMENT_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(atan2, long double)
+TVMET_IMPLEMENT_MACRO(drem, long double)
+TVMET_IMPLEMENT_MACRO(fmod, long double)
+TVMET_IMPLEMENT_MACRO(hypot, long double)
+TVMET_IMPLEMENT_MACRO(jn, long double)
+TVMET_IMPLEMENT_MACRO(yn, long double)
+TVMET_IMPLEMENT_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * complex math
+ */
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+/**
+ * \fn pow(const Matrix<T, Rows, Cols>& lhs, const std::complex<T>& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+pow(const Matrix<T, Rows, Cols>& lhs, const std::complex<T>& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+      expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));
+}
+
+
+/**
+ * \fn pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, const std::complex<T>& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow< std::complex<T>, std::complex<T> >,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, const std::complex<T>& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow< std::complex<T>, std::complex<T> >,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+      expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));
+}
+
+
+/**
+ * \fn pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, const T& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<T>
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, const T& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<T>
+  >							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+      expr_type(lhs.const_ref(), XprLiteral<T>(rhs)));
+}
+
+
+/**
+ * \fn pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, int rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<int>
+  >,
+  Rows, Cols
+>
+pow(const Matrix<std::complex<T>, Rows, Cols>& lhs, int rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    MatrixConstReference<std::complex<T>, Rows, Cols>,
+    XprLiteral<int>
+  >							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+      expr_type(lhs.const_ref(), XprLiteral<int>(rhs)));
+}
+
+
+/**
+ * \fn polar(const Matrix<T, Rows, Cols>& lhs, const T& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprBinOp<
+    Fcnl_polar<T, T>,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral<T>
+  >,
+  Rows, Cols
+>
+polar(const Matrix<T, Rows, Cols>& lhs, const T& rhs) {
+  typedef XprBinOp<
+    Fcnl_polar<T, T>,
+    MatrixConstReference<T, Rows, Cols>,
+    XprLiteral<T>
+  >							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+      expr_type(lhs.const_ref(), XprLiteral<T>(rhs)));
+}
+
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+// to be written (atan2)
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_BINARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixEval.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,387 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixEval.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_EVAL_H
+#define TVMET_MATRIX_EVAL_H
+
+namespace tvmet {
+
+
+/**
+ * \fn bool all_elements(const XprMatrix<E, Rows, Cols>& e)
+ * \brief check on statements for all elements
+ * \ingroup _unary_function
+ * This is for use with boolean operators like
+ * \par Example:
+ * \code
+ * all_elements(matrix > 0) {
+ *     // true branch
+ * } else {
+ *     // false branch
+ * }
+ * \endcode
+ * \sa \ref compare
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+bool all_elements(const XprMatrix<E, Rows, Cols>& e) {
+  return meta::Matrix<Rows, Cols, 0, 0>::all_elements(e);
+}
+
+
+/**
+ * \fn bool any_elements(const XprMatrix<E, Rows, Cols>& e)
+ * \brief check on statements for any elements
+ * \ingroup _unary_function
+ * This is for use with boolean operators like
+ * \par Example:
+ * \code
+ * any_elements(matrix > 0) {
+ *     // true branch
+ * } else {
+ *     // false branch
+ * }
+ * \endcode
+ * \sa \ref compare
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+bool any_elements(const XprMatrix<E, Rows, Cols>& e) {
+  return meta::Matrix<Rows, Cols, 0, 0>::any_elements(e);
+}
+
+
+/*
+ * trinary evaluation functions with matrizes and xpr of
+ *
+ * XprMatrix<E1, Rows, Cols> ? Matrix<T2, Rows, Cols> : Matrix<T3, Rows, Cols>
+ * XprMatrix<E1, Rows, Cols> ? Matrix<T2, Rows, Cols> : XprMatrix<E3, Rows, Cols>
+ * XprMatrix<E1, Rows, Cols> ? XprMatrix<E2, Rows, Cols> : Matrix<T3, Rows, Cols>
+ * XprMatrix<E1, Rows, Cols> ? XprMatrix<E2, Rows, Cols> : XprMatrix<E3, Rows, Cols>
+ */
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const Matrix<T2, Rows, Cols>& m2, const Matrix<T3, Rows, Cols>& m3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    MatrixConstReference<T2, Rows, Cols>,
+    MatrixConstReference<T3, Rows, Cols>
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1,
+     const Matrix<T2, Rows, Cols>& m2,
+     const Matrix<T3, Rows, Cols>& m3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    MatrixConstReference<T2, Rows, Cols>,
+    MatrixConstReference<T3, Rows, Cols>
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e1, m2.const_ref(), m3.const_ref()));
+}
+
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const Matrix<T2, Rows, Cols>& m2, const XprMatrix<E3, Rows, Cols>& e3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    MatrixConstReference<T2, Rows, Cols>,
+    XprMatrix<E3, Rows, Cols>
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1,
+     const Matrix<T2, Rows, Cols>& m2,
+     const XprMatrix<E3, Rows, Cols>& e3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    MatrixConstReference<T2, Rows, Cols>,
+    XprMatrix<E3, Rows, Cols>
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e1, m2.const_ref(), e3));
+}
+
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const XprMatrix<E2, Rows, Cols>& e2, const Matrix<T3, Rows, Cols>& m3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    MatrixConstReference<T3, Rows, Cols>
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1,
+    const  XprMatrix<E2, Rows, Cols>& e2,
+     const Matrix<T3, Rows, Cols>& m3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    MatrixConstReference<T3, Rows, Cols>
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e1, e2, m3.const_ref()));
+}
+
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const XprMatrix<E2, Rows, Cols>& e2, const XprMatrix<E3, Rows, Cols>& e3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    XprMatrix<E3, Rows, Cols>
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1,
+     const XprMatrix<E2, Rows, Cols>& e2,
+     const XprMatrix<E3, Rows, Cols>& e3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    XprMatrix<E3, Rows, Cols>
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(e1, e2, e3));
+}
+
+
+/*
+ * trinary evaluation functions with matrizes, xpr of and POD
+ *
+ * XprMatrix<E, Rows, Cols> ? POD1 : POD2
+ * XprMatrix<E1, Rows, Cols> ? POD : XprMatrix<E3, Rows, Cols>
+ * XprMatrix<E1, Rows, Cols> ? XprMatrix<E2, Rows, Cols> : POD
+ */
+#define TVMET_IMPLEMENT_MACRO(POD)               			\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline               							\
+XprMatrix<               						\
+  XprEval<               						\
+    XprMatrix<E, Rows, Cols>,               			      	\
+    XprLiteral< POD >,               					\
+    XprLiteral< POD >               					\
+  >,                							\
+  Rows, Cols								\
+>               							\
+eval(const XprMatrix<E, Rows, Cols>& e, POD x2, POD x3) {      		\
+  typedef XprEval<               					\
+    XprMatrix<E, Rows, Cols>,               				\
+    XprLiteral< POD >,                					\
+    XprLiteral< POD >                					\
+  > 							expr_type; 	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(e, XprLiteral< POD >(x2), XprLiteral< POD >(x3))); 	\
+}               							\
+               								\
+template<class E1, class E3, std::size_t Rows, std::size_t Cols> 	\
+inline               							\
+XprMatrix<               						\
+  XprEval<               						\
+    XprMatrix<E1, Rows, Cols>,               				\
+    XprLiteral< POD >,               					\
+    XprMatrix<E3, Rows, Cols>               				\
+  >,                							\
+  Rows, Cols								\
+>               							\
+eval(const XprMatrix<E1, Rows, Cols>& e1, POD x2, const XprMatrix<E3, Rows, Cols>& e3) { \
+  typedef XprEval<               					\
+    XprMatrix<E1, Rows, Cols>,               				\
+    XprLiteral< POD >,                					\
+    XprMatrix<E3, Rows, Cols>               				\
+  > 							expr_type; 	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(e1, XprLiteral< POD >(x2), e3)); 				\
+}               							\
+               								\
+template<class E1, class E2, std::size_t Rows, std::size_t Cols>	\
+inline               							\
+XprMatrix<               						\
+  XprEval<               						\
+    XprMatrix<E1, Rows, Cols>,               				\
+    XprMatrix<E2, Rows, Cols>,               				\
+    XprLiteral< POD >               					\
+  >,                							\
+  Rows, Cols								\
+>               							\
+eval(const XprMatrix<E1, Rows, Cols>& e1, const XprMatrix<E2, Rows, Cols>& e2, POD x3) { \
+  typedef XprEval<               					\
+    XprMatrix<E1, Rows, Cols>,               				\
+    XprMatrix<E2, Rows, Cols>,               				\
+    XprLiteral< POD >                					\
+  > 							expr_type; 	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(e1, e2, XprLiteral< POD >(x3))); 				\
+}
+
+TVMET_IMPLEMENT_MACRO(int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(float)
+TVMET_IMPLEMENT_MACRO(double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * trinary evaluation functions with matrizes, xpr of and complex<> types
+ *
+ * XprMatrix<E, Rows, Cols> e, std::complex<T> z2, std::complex<T> z3
+ * XprMatrix<E1, Rows, Cols> e1, std::complex<T> z2, XprMatrix<E3, Rows, Cols> e3
+ * XprMatrix<E1, Rows, Cols> e1, XprMatrix<E2, Rows, Cols> e2, std::complex<T> z3
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+
+/**
+ * \fn eval(const XprMatrix<E, Rows, Cols>& e, const std::complex<T>& x2, const std::complex<T>& x3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols, class T>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E, Rows, Cols>,
+    XprLiteral< std::complex<T> >,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E, Rows, Cols>& e, const std::complex<T>& x2, const std::complex<T>& x3) {
+  typedef XprEval<
+    XprMatrix<E, Rows, Cols>,
+    XprLiteral< std::complex<T> >,
+    XprLiteral< std::complex<T> >
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e, XprLiteral< std::complex<T> >(x2), XprLiteral< std::complex<T> >(x3)));
+}
+
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const std::complex<T>& x2, const XprMatrix<E3, Rows, Cols>& e3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols, class T>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprLiteral< std::complex<T> >,
+    XprMatrix<E3, Rows, Cols>
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1, const std::complex<T>& x2, const XprMatrix<E3, Rows, Cols>& e3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprLiteral< std::complex<T> >,
+    XprMatrix<E3, Rows, Cols>
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e1, XprLiteral< std::complex<T> >(x2), e3));
+}
+
+
+/**
+ * \fn eval(const XprMatrix<E1, Rows, Cols>& e1, const XprMatrix<E2, Rows, Cols>& e2, const std::complex<T>& x3)
+ * \brief Evals the matrix 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 Rows, std::size_t Cols, class T>
+inline
+XprMatrix<
+  XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  >,
+  Rows, Cols
+>
+eval(const XprMatrix<E1, Rows, Cols>& e1, const XprMatrix<E2, Rows, Cols>& e2, const std::complex<T>& x3) {
+  typedef XprEval<
+    XprMatrix<E1, Rows, Cols>,
+    XprMatrix<E2, Rows, Cols>,
+    XprLiteral< std::complex<T> >
+  > 							expr_type;
+  return XprMatrix<expr_type, Rows, Cols>(
+    expr_type(e1, e2, XprLiteral< std::complex<T> >(x3)));
+}
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_EVAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,1377 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixFunctions.h,v 1.65 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_FUNCTIONS_H
+#define TVMET_MATRIX_FUNCTIONS_H
+
+#include <tvmet/Extremum.h>
+
+namespace tvmet {
+
+/* forwards */
+template<class T, std::size_t Sz> class Vector;
+template<class T, std::size_t Sz> class VectorConstReference;
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * function(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ * function(Matrix<T, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>	\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    MatrixConstReference<T1, Rows, Cols>,				\
+    MatrixConstReference<T2, Rows, Cols>				\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const Matrix<T1, Rows, Cols>& lhs,				\
+      const Matrix<T2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, class T, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprMatrix<E, Rows, Cols>,						\
+    MatrixConstReference<T, Rows, Cols>					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E, Rows, Cols>& lhs,				\
+      const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class T, class E, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const Matrix<T, Rows, Cols>& lhs,					\
+      const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)			// per se element wise
+TVMET_DECLARE_MACRO(sub)			// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mul)			// not defined for matrizes
+  TVMET_DECLARE_MACRO(div)			// not defined for matrizes
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * function(Matrix<T, Rows, Cols>, POD)
+ * function(POD, Matrix<T, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, POD)					\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, POD >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral<POD >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const Matrix<T, Rows, Cols>& lhs, 				\
+      POD rhs) TVMET_CXX_ALWAYS_INLINE;					\
+									\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    MatrixConstReference<T, Rows, Cols>					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (POD lhs, 								\
+      const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, int)
+TVMET_DECLARE_MACRO(sub, int)
+TVMET_DECLARE_MACRO(mul, int)
+TVMET_DECLARE_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, long long int)
+TVMET_DECLARE_MACRO(sub, long long int)
+TVMET_DECLARE_MACRO(mul, long long int)
+TVMET_DECLARE_MACRO(div, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, float)
+TVMET_DECLARE_MACRO(sub, float)
+TVMET_DECLARE_MACRO(mul, float)
+TVMET_DECLARE_MACRO(div, float)
+
+TVMET_DECLARE_MACRO(add, double)
+TVMET_DECLARE_MACRO(sub, double)
+TVMET_DECLARE_MACRO(mul, double)
+TVMET_DECLARE_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, long double)
+TVMET_DECLARE_MACRO(sub, long double)
+TVMET_DECLARE_MACRO(mul, long double)
+TVMET_DECLARE_MACRO(div, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(Matrix<T, Rows, Cols>, complex<T>)
+ * function(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME)						\
+template<class T, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,				\
+    XprLiteral<std::complex<T> >						\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME (const Matrix< std::complex<T>, Rows, Cols>& lhs,				\
+      const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;			\
+										\
+template<class T, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    XprLiteral< std::complex<T> >,						\
+    MatrixConstReference< std::complex<T>, Rows, Cols>				\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME (const std::complex<T>& lhs,						\
+      const Matrix< std::complex<T>, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)
+TVMET_DECLARE_MACRO(sub)
+TVMET_DECLARE_MACRO(mul)
+TVMET_DECLARE_MACRO(div)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2 		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const Matrix<T1, Rows1, Cols1>& lhs,
+     const Matrix<T2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,			// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const XprMatrix<E1, Rows1, Cols1>& lhs,
+     const Matrix<T2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2				// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const Matrix<T1, Rows1, Cols1>& lhs,
+     const XprMatrix<E2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+XprMatrix<
+  XprMMProductTransposed<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Cols2, Rows1							// return Dim
+>
+trans_prod(const Matrix<T1, Rows1, Cols1>& lhs,
+	   const Matrix<T2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>	// Rows2 = Rows1
+XprMatrix<
+  XprMtMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Rows1, Cols2>, Cols2		// M2(Rows1, Cols2)
+  >,
+  Cols1, Cols2							// return Dim
+>
+MtM_prod(const Matrix<T1, Rows1, Cols1>& lhs,
+	 const Matrix<T2, Rows1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Rows2>
+XprMatrix<
+  XprMMtProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Rows2, Cols1>, Cols1 		// M2(Rows2, Cols1)
+  >,
+  Rows1, Rows2							// return Dim
+>
+MMt_prod(const Matrix<T1, Rows1, Cols1>& lhs,
+	 const Matrix<T2, Rows2, Cols1>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,	// M(Rows, Cols)
+    VectorConstReference<T2, Cols> 			// V
+  >,
+  Rows
+>
+prod(const Matrix<T1, Rows, Cols>& lhs,
+     const Vector<T2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, class E2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+prod(const Matrix<T1, Rows, Cols>& lhs,
+     const XprVector<E2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, class T2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,		// M(Rows, Cols)
+    VectorConstReference<T2, Cols> 			// V
+  >,
+  Rows
+>
+prod(const XprMatrix<E1, Rows, Cols>& lhs,
+     const Vector<T2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMtVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows,	Cols,   // M(Rows, Cols)
+    VectorConstReference<T2, Rows> 			// V
+  >,
+  Cols
+>
+Mtx_prod(const Matrix<T1, Rows, Cols>& lhs,
+	 const Vector<T2, Rows>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprMatrixTranspose<
+    MatrixConstReference<T, Rows, Cols>
+  >,
+  Cols, Rows
+>
+trans(const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+typename NumericTraits<T>::sum_type
+trace(const Matrix<T, Sz, Sz>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMatrixRow<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >,
+  Cols
+>
+row(const Matrix<T, Rows, Cols>& m,
+    std::size_t no) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMatrixCol<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >,
+  Rows
+>
+col(const Matrix<T, Rows, Cols>& m,
+    std::size_t no) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprMatrixDiag<
+    MatrixConstReference<T, Sz, Sz>,
+    Sz
+  >,
+  Sz
+>
+diag(const Matrix<T, Sz, Sz>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * min/max unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+Extremum<typename E::value_type, std::size_t, matrix_tag>
+maximum(const XprMatrix<E, Rows, Cols>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+Extremum<T, std::size_t, matrix_tag>
+maximum(const Matrix<T, Rows, Cols>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+Extremum<typename E::value_type, std::size_t, matrix_tag>
+minimum(const XprMatrix<E, Rows, Cols>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+Extremum<T, std::size_t, matrix_tag>
+minimum(const Matrix<T, Rows, Cols>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+typename E::value_type
+max(const XprMatrix<E, Rows, Cols>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+T max(const Matrix<T, Rows, Cols>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+typename E::value_type
+min(const XprMatrix<E, Rows, Cols>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+T min(const Matrix<T, Rows, Cols>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * other unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprIdentity<T, Rows, Cols>,
+  Rows, Cols
+>
+identity() TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class M>
+XprMatrix<
+  XprIdentity<
+    typename M::value_type,
+    M::Rows, M::Cols>,
+  M::Rows, M::Cols
+>
+identity() TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  MatrixConstReference<T, Rows, Cols>,
+  Rows, Cols
+>
+cmatrix_ref(const T* mem) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * function(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ * function(Matrix<T, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)						\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME (const Matrix<T1, Rows, Cols>& lhs, const Matrix<T2, Rows, Cols>& rhs) {	\
+  typedef XprBinOp <								\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >							expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs.const_ref(), rhs.const_ref()));				\
+}										\
+										\
+template<class E, class T, std::size_t Rows, std::size_t Cols>			\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    XprMatrix<E, Rows, Cols>,							\
+    MatrixConstReference<T, Rows, Cols>						\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME (const XprMatrix<E, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    XprMatrix<E, Rows, Cols>,							\
+    MatrixConstReference<T, Rows, Cols>						\
+  > 							 expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs, rhs.const_ref()));						\
+}										\
+										\
+template<class T, class E, std::size_t Rows, std::size_t Cols>			\
+inline										\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+NAME (const Matrix<T, Rows, Cols>& lhs, const XprMatrix<E, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >	 						 expr_type;		\
+  return XprMatrix<expr_type, Rows, Cols>(					\
+    expr_type(lhs.const_ref(), rhs));						\
+}
+
+TVMET_IMPLEMENT_MACRO(add)			// per se element wise
+TVMET_IMPLEMENT_MACRO(sub)			// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mul)			// not defined for matrizes
+  TVMET_IMPLEMENT_MACRO(div)			// not defined for matrizes
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * function(Matrix<T, Rows, Cols>, POD)
+ * function(POD, Matrix<T, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, POD >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral<POD >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const Matrix<T, Rows, Cols>& lhs, POD rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, POD >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral< POD >							\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs.const_ref(), XprLiteral< POD >(rhs)));		\
+}									\
+									\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    MatrixConstReference<T, Rows, Cols>					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (POD lhs, const Matrix<T, Rows, Cols>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    MatrixConstReference<T, Rows, Cols>					\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< POD >(lhs), rhs.const_ref()));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add, int)
+TVMET_IMPLEMENT_MACRO(sub, int)
+TVMET_IMPLEMENT_MACRO(mul, int)
+TVMET_IMPLEMENT_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, long long int)
+TVMET_IMPLEMENT_MACRO(sub, long long int)
+TVMET_IMPLEMENT_MACRO(mul, long long int)
+TVMET_IMPLEMENT_MACRO(div, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, float)
+TVMET_IMPLEMENT_MACRO(sub, float)
+TVMET_IMPLEMENT_MACRO(mul, float)
+TVMET_IMPLEMENT_MACRO(div, float)
+
+TVMET_IMPLEMENT_MACRO(add, double)
+TVMET_IMPLEMENT_MACRO(sub, double)
+TVMET_IMPLEMENT_MACRO(mul, double)
+TVMET_IMPLEMENT_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, long double)
+TVMET_IMPLEMENT_MACRO(sub, long double)
+TVMET_IMPLEMENT_MACRO(mul, long double)
+TVMET_IMPLEMENT_MACRO(div, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(Matrix<T, Rows, Cols>, complex<T>)
+ * function(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,			\
+    XprLiteral<std::complex<T> >					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const Matrix< std::complex<T>, Rows, Cols>& lhs,			\
+      const std::complex<T>& rhs) {					\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,			\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));	\
+}									\
+									\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    XprLiteral< std::complex<T> >,					\
+    MatrixConstReference< std::complex<T>, Rows, Cols>			\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const std::complex<T>& lhs,					\
+      const Matrix< std::complex<T>, Rows, Cols>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    XprLiteral< std::complex<T> >,					\
+    MatrixConstReference<std::complex<T>, Rows, Cols>			\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs.const_ref()));	\
+}
+
+TVMET_IMPLEMENT_MACRO(add)
+TVMET_IMPLEMENT_MACRO(sub)
+TVMET_IMPLEMENT_MACRO(mul)
+TVMET_IMPLEMENT_MACRO(div)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ * \brief Function for the matrix-matrix-product.
+ * \ingroup _binary_function
+ * \note The rows2 has to be equal to cols1.
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2 		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs) {
+  typedef XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Cols2>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/**
+ * \fn prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of XprMatrix and Matrix.
+ * \ingroup _binary_function
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,			// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs) {
+  typedef XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Cols2>(
+    expr_type(lhs, rhs.const_ref()));
+}
+
+
+/**
+ * \fn prod(const Matrix<T1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of Matrix and XprMatrix.
+ * \ingroup _binary_function
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2				// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2							// return Dim
+>
+prod(const Matrix<T1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs) {
+  typedef XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Cols2>(
+    expr_type(lhs.const_ref(), rhs));
+}
+
+
+/**
+ * \fn trans_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ * \brief Function for the trans(matrix-matrix-product)
+ * \ingroup _binary_function
+ * Perform on given Matrix M1 and M2:
+ * \f[
+ * (M_1\,M_2)^T
+ * \f]
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProductTransposed<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Cols2, Rows1							// return Dim
+>
+trans_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs) {
+  typedef XprMMProductTransposed<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Cols2, Rows1>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/**
+ * \fn MtM_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Rows1, Cols2>& rhs)
+ * \brief Function for the trans(matrix)-matrix-product.
+ * \ingroup _binary_function
+ *        using formula
+ *        \f[
+ *        M_1^{T}\,M_2
+ *        \f]
+ * \note The number of cols of matrix 2 have to be equal to number of rows of
+ *       matrix 1, since matrix 1 is trans - the result is a (Cols1 x Cols2)
+ *       matrix.
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>	// Rows2 = Rows1
+inline
+XprMatrix<
+  XprMtMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Rows1, Cols2>, Cols2		// M2(Rows1, Cols2)
+  >,
+  Cols1, Cols2							// return Dim
+>
+MtM_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Rows1, Cols2>& rhs) {
+  typedef XprMtMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Rows1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Cols1, Cols2>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/**
+ * \fn MMt_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Rows2, Cols1>& rhs)
+ * \brief Function for the matrix-trans(matrix)-product.
+ * \ingroup _binary_function
+ * \note The Cols2 has to be equal to Cols1.
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Rows2>
+inline
+XprMatrix<
+  XprMMtProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    MatrixConstReference<T2, Rows2, Cols1>, Cols1 		// M2(Rows2, Cols1)
+  >,
+  Rows1, Rows2							// return Dim
+>
+MMt_prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Rows2, Cols1>& rhs) {
+  typedef XprMMtProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Rows2, Cols1>, Cols1
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Rows2>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn prod(const Matrix<T1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs)
+ * \brief Function for the matrix-vector-product
+ * \ingroup _binary_function
+ */
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,	// M(Rows, Cols)
+    VectorConstReference<T2, Cols> 			// V
+  >,
+  Rows
+>
+prod(const Matrix<T1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs) {
+  typedef XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  > 							expr_type;
+  return XprVector<expr_type, Rows>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/**
+ * \fn prod(const Matrix<T1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs)
+ * \brief Function for the matrix-vector-product
+ * \ingroup _binary_function
+ */
+template<class T1, class E2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+prod(const Matrix<T1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs) {
+  typedef XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  > 							expr_type;
+  return XprVector<expr_type, Rows>(
+    expr_type(lhs.const_ref(), rhs));
+}
+
+
+/*
+ * \fn prod(const XprMatrix<E, Rows, Cols>& lhs, const Vector<T, Cols>& rhs)
+ * \brief Compute the product of an XprMatrix with a Vector.
+ * \ingroup _binary_function
+ */
+template<class E1, class T2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,		// M(Rows, Cols)
+    VectorConstReference<T2, Cols> 			// V
+  >,
+  Rows
+>
+prod(const XprMatrix<E1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs) {
+  typedef XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  > 							expr_type;
+  return XprVector<expr_type, Rows>(
+    expr_type(lhs, rhs.const_ref()));
+}
+
+
+/**
+ * \fn Mtx_prod(const Matrix<T1, Rows, Cols>& matrix, const Vector<T2, Rows>& vector)
+ * \brief Function for the trans(matrix)-vector-product
+ * \ingroup _binary_function
+ * Perform on given Matrix M and vector x:
+ * \f[
+ * M^T\, x
+ * \f]
+ */
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMtVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows,	Cols,   // M(Rows, Cols)
+    VectorConstReference<T2, Rows> 			// V
+  >,
+  Cols
+>
+Mtx_prod(const Matrix<T1, Rows, Cols>& lhs, const Vector<T2, Rows>& rhs) {
+  typedef XprMtVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Rows>
+  > 							expr_type;
+  return XprVector<expr_type, Cols>(
+    expr_type(lhs.const_ref(), rhs.const_ref()));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn trans(const Matrix<T, Rows, Cols>& rhs)
+ * \brief Transpose the matrix
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprMatrixTranspose<
+    MatrixConstReference<T, Rows, Cols>
+  >,
+  Cols, Rows
+>
+trans(const Matrix<T, Rows, Cols>& rhs) {
+  typedef XprMatrixTranspose<
+    MatrixConstReference<T, Rows, Cols>
+  >							expr_type;
+  return XprMatrix<expr_type, Cols, Rows>(
+    expr_type(rhs.const_ref()));
+}
+
+
+/*
+ * \fn trace(const Matrix<T, Sz, Sz>& m)
+ * \brief Compute the trace of a square matrix.
+ * \ingroup _unary_function
+ *
+ * Simply compute the trace of the given matrix as:
+ * \f[
+ *  \sum_{k = 0}^{Sz-1} m(k, k)
+ * \f]
+ */
+template<class T, std::size_t Sz>
+inline
+typename NumericTraits<T>::sum_type
+trace(const Matrix<T, Sz, Sz>& m) {
+  return meta::Matrix<Sz, Sz, 0, 0>::trace(m);
+}
+
+
+/**
+ * \fn row(const Matrix<T, Rows, Cols>& m, std::size_t no)
+ * \brief Returns a row vector of the given matrix.
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMatrixRow<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >,
+  Cols
+>
+row(const Matrix<T, Rows, Cols>& m, std::size_t no) {
+  typedef XprMatrixRow<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >							expr_type;
+  return XprVector<expr_type, Cols>(expr_type(m.const_ref(), no));
+}
+
+
+/**
+ * \fn col(const Matrix<T, Rows, Cols>& m, std::size_t no)
+ * \brief Returns a column vector of the given matrix.
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMatrixCol<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >,
+  Rows
+>
+col(const Matrix<T, Rows, Cols>& m, std::size_t no) {
+  typedef XprMatrixCol<
+    MatrixConstReference<T, Rows, Cols>,
+    Rows, Cols
+  >							expr_type;
+  return XprVector<expr_type, Rows>(expr_type(m.const_ref(), no));
+}
+
+
+/**
+ * \fn diag(const Matrix<T, Sz, Sz>& m)
+ * \brief Returns the diagonal vector of the given square matrix.
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprMatrixDiag<
+    MatrixConstReference<T, Sz, Sz>,
+    Sz
+  >,
+  Sz
+>
+diag(const Matrix<T, Sz, Sz>& m) {
+  typedef XprMatrixDiag<
+    MatrixConstReference<T, Sz, Sz>,
+    Sz
+  >							expr_type;
+  return XprVector<expr_type, Sz>(expr_type(m.const_ref()));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * min/max unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn maximum(const XprMatrix<E, Rows, Cols>& e)
+ * \brief Find the maximum of a matrix expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+Extremum<typename E::value_type, std::size_t, matrix_tag>
+maximum(const XprMatrix<E, Rows, Cols>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						temp(e(0, 0));
+  std::size_t 						row_no(0), col_no(0);
+
+  for(std::size_t i = 0; i != Rows; ++i) {
+    for(std::size_t j = 0; j != Cols; ++j) {
+      if(e(i, j) > temp) {
+	temp = e(i, j);
+	row_no = i;
+	col_no = j;
+      }
+    }
+  }
+
+  return Extremum<value_type, std::size_t, matrix_tag>(temp, row_no, col_no);
+}
+
+
+/**
+ * \fn maximum(const Matrix<T, Rows, Cols>& m)
+ * \brief Find the maximum of a matrix
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+Extremum<T, std::size_t, matrix_tag>
+maximum(const Matrix<T, Rows, Cols>& m) { return maximum(m.as_expr()); }
+
+
+/**
+ * \fn minimum(const XprMatrix<E, Rows, Cols>& e)
+ * \brief Find the minimum of a matrix expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+Extremum<typename E::value_type, std::size_t, matrix_tag>
+minimum(const XprMatrix<E, Rows, Cols>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						temp(e(0, 0));
+  std::size_t 						row_no(0), col_no(0);
+
+  for(std::size_t i = 0; i != Rows; ++i) {
+    for(std::size_t j = 0; j != Cols; ++j) {
+      if(e(i, j) < temp) {
+	temp = e(i, j);
+	row_no = i;
+	col_no = j;
+      }
+    }
+  }
+
+  return Extremum<value_type, std::size_t, matrix_tag>(temp, row_no, col_no);
+}
+
+
+/**
+ * \fn minimum(const Matrix<T, Rows, Cols>& m)
+ * \brief Find the minimum of a matrix
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+Extremum<T, std::size_t, matrix_tag>
+minimum(const Matrix<T, Rows, Cols>& m) { return minimum(m.as_expr()); }
+
+
+/**
+ * \fn max(const XprMatrix<E, Rows, Cols>& e)
+ * \brief Find the maximum of a matrix expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+typename E::value_type
+max(const XprMatrix<E, Rows, Cols>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						temp(e(0, 0));
+
+  for(std::size_t i = 0; i != Rows; ++i)
+    for(std::size_t j = 0; j != Cols; ++j)
+      if(e(i, j) > temp)
+	temp = e(i, j);
+
+  return temp;
+}
+
+
+/**
+ * \fn max(const Matrix<T, Rows, Cols>& m)
+ * \brief Find the maximum of a matrix
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+T max(const Matrix<T, Rows, Cols>& m) {
+  typedef T			 			value_type;
+  typedef typename Matrix<
+   T, Rows, Cols
+  >::const_iterator					const_iterator;
+
+  const_iterator					iter(m.begin());
+  const_iterator					last(m.end());
+  value_type 						temp(*iter);
+
+  for( ; iter != last; ++iter)
+    if(*iter > temp)
+      temp = *iter;
+
+  return temp;
+}
+
+
+/**
+ * \fn min(const XprMatrix<E, Rows, Cols>& e)
+ * \brief Find the minimum of a matrix expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+typename E::value_type
+min(const XprMatrix<E, Rows, Cols>& e) {
+  typedef typename E::value_type			value_type;
+
+  value_type 						temp(e(0, 0));
+
+  for(std::size_t i = 0; i != Rows; ++i)
+    for(std::size_t j = 0; j != Cols; ++j)
+      if(e(i, j) < temp)
+	temp = e(i, j);
+
+  return temp;
+}
+
+
+/**
+ * \fn min(const Matrix<T, Rows, Cols>& m)
+ * \brief Find the minimum of a matrix
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+T min(const Matrix<T, Rows, Cols>& m) {
+  typedef T			 			value_type;
+  typedef typename Matrix<
+   T, Rows, Cols
+  >::const_iterator					const_iterator;
+
+  const_iterator					iter(m.begin());
+  const_iterator					last(m.end());
+  value_type 						temp(*iter);
+
+  for( ; iter != last; ++iter)
+    if(*iter < temp)
+      temp = *iter;
+
+  return temp;
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * other unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn XprMatrix<XprIdentity<typename M::value_type, M::Rows, M::Cols>, M::Rows, M::Cols>identity()
+ * \brief Fill a matrix to an identity matrix.
+ * \ingroup _unary_function
+ *
+ * \note The matrix doesn't need to be square. Only the elements
+ *       where the current number of rows are equal to columns
+ *       will be set to 1, else to 0.
+ *
+ * \par Usage:
+ * \code
+ * typedef Matrix<double,3,3>		matrix_type;
+ * ...
+ * matrix_type E( identity<double, 3, 3>() );
+ * \endcode
+ *
+ * Note, we have to specify the type, number of rows and columns
+ * since ADL can't work here.
+ *
+ *
+ *
+ * \since release 1.6.0
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprIdentity<T, Rows, Cols>,
+  Rows, Cols
+>
+identity() {
+  typedef XprIdentity<T, Rows, Cols>		expr_type;
+
+  return XprMatrix<expr_type, Rows, Cols>(expr_type());
+}
+
+/**
+ * \fn XprMatrix<XprIdentity<typename M::value_type, M::Rows, M::Cols>, M::Rows, M::Cols>identity()
+ * \brief Fill a matrix to an identity matrix (convenience wrapper
+ *        for matrix typedefs).
+ * \ingroup _unary_function
+ *
+ * \note The matrix doesn't need to be square. Only the elements
+ *       where the current number of rows are equal to columns
+ *       will be set to 1, else to 0.
+ *
+ * \par Usage:
+ * \code
+ * typedef Matrix<double,3,3>		matrix_type;
+ * ...
+ * matrix_type E( identity<matrix_type>() );
+ * \endcode
+ *
+ * Note, we have to specify the matrix type, since ADL can't work here.
+ *
+ * \since release 1.6.0
+ */
+template<class M>
+inline
+XprMatrix<
+  XprIdentity<
+    typename M::value_type,
+    M::Rows, M::Cols>,
+  M::Rows, M::Cols
+>
+identity() {
+  return identity<typename M::value_type, M::Rows, M::Cols>();
+}
+
+
+/**
+ * \fn cmatrix_ref(const T* mem)
+ * \brief Creates an expression wrapper for a C like matrices.
+ * \ingroup _unary_function
+ *
+ * This is like creating a matrix of external data, as described
+ * at \ref construct. With this function you wrap an expression
+ * around a C style matrix and you can operate directly with it
+ * as usual.
+ *
+ * \par Example:
+ * \code
+ * static float lhs[3][3] = {
+ *   {-1,  0,  1}, { 1,  0,  1}, {-1,  0, -1}
+ * };
+ * static float rhs[3][3] = {
+ *   { 0,  1,  1}, { 0,  1, -1}, { 0, -1,  1}
+ * };
+ * ...
+ *
+ * typedef Matrix<float, 3, 3>			matrix_type;
+ *
+ * matrix_type M( cmatrix_ref<float, 3, 3>(&lhs[0][0])
+ *                *  cmatrix_ref<float, 3, 3>(&rhs[0][0]) );
+ * \endcode
+ *
+ * \since release 1.6.0
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  MatrixConstReference<T, Rows, Cols>,
+  Rows, Cols
+>
+cmatrix_ref(const T* mem) {
+  typedef MatrixConstReference<T, Rows, Cols>	expr_type;
+
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(mem));
+}
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixImpl.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,218 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixImpl.h,v 1.31 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_IMPL_H
+#define TVMET_MATRIX_IMPL_H
+
+#include <iomanip>			// setw
+
+#include <tvmet/Functional.h>
+#include <tvmet/Io.h>
+
+
+namespace tvmet {
+
+
+/*
+ * member operators for i/o
+ */
+template<class T, std::size_t NRows, std::size_t NCols>
+std::ostream& Matrix<T, NRows, NCols>::print_xpr(std::ostream& os, std::size_t l) const
+{
+  os << IndentLevel(l++) << "Matrix[" << ops << "]<"
+     << typeid(T).name() << ", " << Rows << ", " << Cols << ">,"
+     << IndentLevel(--l)
+     << std::endl;
+
+  return os;
+}
+
+
+template<class T, std::size_t NRows, std::size_t NCols>
+std::ostream& Matrix<T, NRows, NCols>::print_on(std::ostream& os) const
+{
+  enum {
+    complex_type = NumericTraits<value_type>::is_complex
+  };
+
+  std::streamsize w = IoPrintHelper<Matrix>::width(dispatch<complex_type>(), *this);
+
+  os << std::setw(0) << "[\n";
+  for(std::size_t i = 0; i < Rows; ++i) {
+    os << " [";
+    for(std::size_t j = 0; j < (Cols - 1); ++j) {
+      os << std::setw(w) << this->operator()(i, j) << ", ";
+    }
+    os << std::setw(w) << this->operator()(i, Cols - 1)
+       << (i != (Rows-1) ? "],\n" : "]\n");
+    }
+  os << "]";
+
+  return os;
+}
+
+
+/*
+ * member operators with scalars, per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				    \
+template<class T, std::size_t NRows, std::size_t NCols>		    \
+inline 								    \
+Matrix<T, NRows, NCols>&					    \
+Matrix<T, NRows, NCols>::operator OP (value_type rhs) {		    \
+  typedef XprLiteral<value_type> 			expr_type;  \
+  this->M_##NAME(XprMatrix<expr_type, Rows, Cols>(expr_type(rhs))); \
+  return *this;							    \
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq, +=)
+TVMET_IMPLEMENT_MACRO(sub_eq, -=)
+TVMET_IMPLEMENT_MACRO(mul_eq, *=)
+TVMET_IMPLEMENT_MACRO(div_eq, /=)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				    \
+template<class T, std::size_t NRows, std::size_t NCols>		    \
+inline 								    \
+Matrix<T, NRows, NCols>&					    \
+Matrix<T, NRows, NCols>::operator OP (std::size_t rhs) {	    \
+  typedef XprLiteral<value_type> 			expr_type;  \
+  this->M_##NAME(XprMatrix<expr_type, Rows, Cols>(expr_type(rhs))); \
+  return *this;							    \
+}
+
+TVMET_IMPLEMENT_MACRO(mod_eq, %=)
+TVMET_IMPLEMENT_MACRO(xor_eq,^=)
+TVMET_IMPLEMENT_MACRO(and_eq, &=)
+TVMET_IMPLEMENT_MACRO(or_eq, |=)
+TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
+TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ *  member functions (operators) with matrizes, for use with +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)									     \
+template<class T1, std::size_t NRows, std::size_t NCols>						     \
+template <class T2>											     \
+inline 													     \
+Matrix<T1, NRows, NCols>&										     \
+Matrix<T1, NRows, NCols>::M_##NAME (const Matrix<T2, Rows, Cols>& rhs) {				     \
+  this->M_##NAME( XprMatrix<typename Matrix<T2, Rows, Cols>::ConstReference, Rows, Cols>(rhs.const_ref()) ); \
+  return *this;												     \
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+TVMET_IMPLEMENT_MACRO(mod_eq)
+TVMET_IMPLEMENT_MACRO(xor_eq)
+TVMET_IMPLEMENT_MACRO(and_eq)
+TVMET_IMPLEMENT_MACRO(or_eq)
+TVMET_IMPLEMENT_MACRO(shl_eq)
+TVMET_IMPLEMENT_MACRO(shr_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * member functions (operators) with expressions, for use width +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					   \
+template<class T, std::size_t NRows, std::size_t NCols>			   \
+template<class E>							   \
+inline 									   \
+Matrix<T, NRows, NCols>&						   \
+Matrix<T, NRows, NCols>::M_##NAME (const XprMatrix<E, Rows, Cols>& rhs) {  \
+  rhs.assign_to(*this, Fcnl_##NAME<value_type, typename E::value_type>()); \
+  return *this;								   \
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+TVMET_IMPLEMENT_MACRO(mod_eq)
+TVMET_IMPLEMENT_MACRO(xor_eq)
+TVMET_IMPLEMENT_MACRO(and_eq)
+TVMET_IMPLEMENT_MACRO(or_eq)
+TVMET_IMPLEMENT_MACRO(shl_eq)
+TVMET_IMPLEMENT_MACRO(shr_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * aliased member functions (operators) with matrizes,
+ * for use with +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)										 \
+template<class T1, std::size_t NRows, std::size_t NCols>							 \
+template <class T2>												 \
+inline 														 \
+Matrix<T1, NRows, NCols>&											 \
+Matrix<T1, NRows, NCols>::alias_##NAME (const Matrix<T2, Rows, Cols>& rhs) {					 \
+  this->alias_##NAME( XprMatrix<typename Matrix<T2, Rows, Cols>::ConstReference, Rows, Cols>(rhs.const_ref()) ); \
+  return *this;													 \
+}
+
+TVMET_IMPLEMENT_MACRO(assign)
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * aliased member functions (operators) with expressions,
+ * for use width +=,-= ... <<= and aliased(),
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)						      \
+template<class T, std::size_t NRows, std::size_t NCols>				      \
+template<class E>								      \
+inline 										      \
+Matrix<T, NRows, NCols>&							      \
+Matrix<T, NRows, NCols>::alias_##NAME (const XprMatrix<E, Rows, Cols>& rhs) {	      \
+  typedef Matrix<T, NRows, NCols> 			temp_type;		      \
+  temp_type(rhs).assign_to(*this, Fcnl_##NAME<value_type, typename E::value_type>()); \
+  return *this;									      \
+}
+
+TVMET_IMPLEMENT_MACRO(assign)
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_IMPL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixOperators.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,1287 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixOperators.h,v 1.37 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_OPERATORS_H
+#define TVMET_MATRIX_OPERATORS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+template<class T, std::size_t Rows, std::size_t Cols>
+std::ostream& operator<<(std::ostream& os,
+			 const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Member operators (arithmetic and bit ops)
+ *++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * update_operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * update_operator(Matrix<T1, Rows, Cols>, XprMatrix<E, Rows, Cols> rhs)
+ * Note: per se element wise
+ * \todo: the operator*= can have element wise mul oder product, decide!
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		\
+Matrix<T1, Rows, Cols>&								\
+operator OP (Matrix<T1, Rows, Cols>& lhs, 					\
+	     const Matrix<T2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+										\
+template<class T, class E, std::size_t Rows,  std::size_t Cols>			\
+Matrix<T, Rows, Cols>&								\
+operator OP (Matrix<T, Rows, Cols>& lhs, 					\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add_eq, +=)		// per se element wise
+TVMET_DECLARE_MACRO(sub_eq, -=)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mul_eq, *=)		// see note
+  TVMET_DECLARE_MACRO(div_eq, /=)		// not defined for vectors
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod_eq, %=)
+  TVMET_DECLARE_MACRO(xor_eq, ^=)
+  TVMET_DECLARE_MACRO(and_eq, &=)
+  TVMET_DECLARE_MACRO(or_eq, |=)
+  TVMET_DECLARE_MACRO(shl_eq, <<=)
+  TVMET_DECLARE_MACRO(shr_eq, >>=)
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * operator(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ * operator(Matrix<T, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ * Note: per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const Matrix<T1, Rows, Cols>& lhs,					\
+	     const Matrix<T2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+										\
+template<class E, class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    XprMatrix<E, Rows, Cols>,							\
+    MatrixConstReference<T, Rows, Cols>						\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 				\
+	     const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class T, class E, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const Matrix<T, Rows, Cols>& lhs, 					\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)			// per se element wise
+TVMET_DECLARE_MACRO(sub, -)			// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mul, *)			// see as prod()
+  TVMET_DECLARE_MACRO(div, /)			// not defined for matrizes
+}
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * operator(Matrix<T, Rows, Cols>, POD)
+ * operator(POD, Matrix<T, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, POD)				\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, POD >,						\
+    MatrixConstReference<T, Rows, Cols>,				\
+    XprLiteral<POD >							\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const Matrix<T, Rows, Cols>& lhs, 				\
+	     POD rhs) TVMET_CXX_ALWAYS_INLINE;				\
+									\
+template<class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    MatrixConstReference<T, Rows, Cols>					\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (POD lhs, 							\
+	     const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +, int)
+TVMET_DECLARE_MACRO(sub, -, int)
+TVMET_DECLARE_MACRO(mul, *, int)
+TVMET_DECLARE_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, +, long long int)
+TVMET_DECLARE_MACRO(sub, -, long long int)
+TVMET_DECLARE_MACRO(mul, *, long long int)
+TVMET_DECLARE_MACRO(div, /, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(add, +, float)
+TVMET_DECLARE_MACRO(sub, -, float)
+TVMET_DECLARE_MACRO(mul, *, float)
+TVMET_DECLARE_MACRO(div, /, float)
+
+TVMET_DECLARE_MACRO(add, +, double)
+TVMET_DECLARE_MACRO(sub, -, double)
+TVMET_DECLARE_MACRO(mul, *, double)
+TVMET_DECLARE_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, +, long double)
+TVMET_DECLARE_MACRO(sub, -, long double)
+TVMET_DECLARE_MACRO(mul, *, long double)
+TVMET_DECLARE_MACRO(div, /, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Matrix<T, Rows, Cols>, complex<T>)
+ * operator(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)							\
+template<class T, std::size_t Rows, std::size_t Cols>					\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,					\
+    XprLiteral<std::complex<T> >							\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const Matrix< std::complex<T>, Rows, Cols>& lhs,				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;			\
+											\
+template<class T, std::size_t Rows, std::size_t Cols>					\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    XprLiteral< std::complex<T> >,							\
+    MatrixConstReference< std::complex<T>, Rows, Cols>					\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const std::complex<T>& lhs,						\
+	     const Matrix< std::complex<T>, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)
+TVMET_DECLARE_MACRO(sub, -)
+TVMET_DECLARE_MACRO(mul, *)
+TVMET_DECLARE_MACRO(div, /)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific operator*() = prod() operations
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const Matrix<T1, Rows1, Cols1>& lhs,
+	  const Matrix<T2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const XprMatrix<E1, Rows1, Cols1>& lhs,
+	  const Matrix<T2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const Matrix<T1, Rows1, Cols1>& lhs,
+	  const XprMatrix<E2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T1, std::size_t Rows, std::size_t Cols, class T2>
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  >,
+  Rows
+>
+operator*(const Matrix<T1, Rows, Cols>& lhs,
+	  const Vector<T2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, class E2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+operator*(const Matrix<T1, Rows, Cols>& lhs,
+	  const XprVector<E2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, class T2, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  >,
+  Rows
+>
+operator*(const XprMatrix<E1, Rows, Cols>& lhs,
+	  const Vector<T2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * operator(XprMatrix<E>, Matrix<T, Rows, Cols>)
+ * operator(Matrix<T, Rows, Cols>, XprMatrix<E>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class T1, std::size_t Rows, std::size_t Cols,				\
+	 class T2>								\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T1, T2>,							\
+    MatrixConstReference<T1, Rows, Cols>,					\
+    MatrixConstReference<T2, Rows, Cols>					\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const Matrix<T1, Rows, Cols>& lhs,					\
+	     const Matrix<T2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+										\
+template<class E,								\
+	 class T, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    XprMatrix<E, Rows, Cols>,							\
+    MatrixConstReference<T, Rows, Cols>						\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 				\
+	     const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class T, std::size_t Rows, std::size_t Cols,				\
+	 class E>								\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,					\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const Matrix<T, Rows, Cols>& lhs, 					\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %)
+  TVMET_DECLARE_MACRO(bitxor, ^)
+  TVMET_DECLARE_MACRO(bitand, &)
+  TVMET_DECLARE_MACRO(bitor, |)
+  TVMET_DECLARE_MACRO(shl, <<)
+  TVMET_DECLARE_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Matrix<T, Rows, Cols>, complex<T>)
+ * operator(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)							\
+template<class T, std::size_t Rows, std::size_t Cols>					\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,					\
+    XprLiteral<std::complex<T> >							\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const Matrix< std::complex<T>, Rows, Cols>& lhs,				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;			\
+											\
+template<class T, std::size_t Rows, std::size_t Cols>					\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    XprLiteral< std::complex<T> >,							\
+    MatrixConstReference< std::complex<T>, Rows, Cols>					\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const std::complex<T>& lhs,						\
+	     const Matrix< std::complex<T>, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(Matrix<T, Rows, Cols>, POD)
+ * operator(POD, Matrix<T, Rows, Cols>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, TP)					\
+template<class T, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<T, TP >,							\
+    MatrixConstReference<T, Rows, Cols>,					\
+    XprLiteral<TP >								\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const Matrix<T, Rows, Cols>& lhs, TP rhs) TVMET_CXX_ALWAYS_INLINE;	\
+										\
+template<class T, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME< TP, T>,							\
+    XprLiteral< TP >,								\
+    MatrixConstReference<T, Rows, Cols>						\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (TP lhs, const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, int)
+  TVMET_DECLARE_MACRO(bitxor, ^, int)
+  TVMET_DECLARE_MACRO(bitand, &, int)
+  TVMET_DECLARE_MACRO(bitor, |, int)
+  TVMET_DECLARE_MACRO(shl, <<, int)
+  TVMET_DECLARE_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, int)
+TVMET_DECLARE_MACRO(less, <, int)
+TVMET_DECLARE_MACRO(greater_eq, >=, int)
+TVMET_DECLARE_MACRO(less_eq, <=, int)
+TVMET_DECLARE_MACRO(eq, ==, int)
+TVMET_DECLARE_MACRO(not_eq, !=, int)
+TVMET_DECLARE_MACRO(and, &&, int)
+TVMET_DECLARE_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, long long int)
+  TVMET_DECLARE_MACRO(bitxor, ^, long long int)
+  TVMET_DECLARE_MACRO(bitand, &, long long int)
+  TVMET_DECLARE_MACRO(bitor, |, long long int)
+  TVMET_DECLARE_MACRO(shl, <<, long long int)
+  TVMET_DECLARE_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long long int)
+TVMET_DECLARE_MACRO(less, <, long long int)
+TVMET_DECLARE_MACRO(greater_eq, >=, long long int)
+TVMET_DECLARE_MACRO(less_eq, <=, long long int)
+TVMET_DECLARE_MACRO(eq, ==, long long int)
+TVMET_DECLARE_MACRO(not_eq, !=, long long int)
+TVMET_DECLARE_MACRO(and, &&, long long int)
+TVMET_DECLARE_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, float)
+TVMET_DECLARE_MACRO(less, <, float)
+TVMET_DECLARE_MACRO(greater_eq, >=, float)
+TVMET_DECLARE_MACRO(less_eq, <=, float)
+TVMET_DECLARE_MACRO(eq, ==, float)
+TVMET_DECLARE_MACRO(not_eq, !=, float)
+TVMET_DECLARE_MACRO(and, &&, float)
+TVMET_DECLARE_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, double)
+TVMET_DECLARE_MACRO(less, <, double)
+TVMET_DECLARE_MACRO(greater_eq, >=, double)
+TVMET_DECLARE_MACRO(less_eq, <=, double)
+TVMET_DECLARE_MACRO(eq, ==, double)
+TVMET_DECLARE_MACRO(not_eq, !=, double)
+TVMET_DECLARE_MACRO(and, &&, double)
+TVMET_DECLARE_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long double)
+TVMET_DECLARE_MACRO(less, <, long double)
+TVMET_DECLARE_MACRO(greater_eq, >=, long double)
+TVMET_DECLARE_MACRO(less_eq, <=, long double)
+TVMET_DECLARE_MACRO(eq, ==, long double)
+TVMET_DECLARE_MACRO(not_eq, !=, long double)
+TVMET_DECLARE_MACRO(and, &&, long double)
+TVMET_DECLARE_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(Matrix<T, Rows, Cols>)
+ * Note: per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template <class T, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprUnOp<								\
+    Fcnl_##NAME<T>,							\
+    MatrixConstReference<T, Rows, Cols>					\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(not, !)
+TVMET_DECLARE_MACRO(compl, ~)
+TVMET_DECLARE_MACRO(neg, -)
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/**
+ * \fn operator<<(std::ostream& os, const Matrix<T, Rows, Cols>& rhs)
+ * \brief Overload operator for i/o
+ * \ingroup _binary_operator
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+std::ostream& operator<<(std::ostream& os, const Matrix<T, Rows, Cols>& rhs) {
+  return rhs.print_on(os);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Member operators (arithmetic and bit ops)
+ *++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * update_operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * update_operator(Matrix<T1, Rows, Cols>, XprMatrix<E, Rows, Cols> rhs)
+ * Note: per se element wise
+ * \todo: the operator*= can have element wise mul oder product, decide!
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)						\
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		\
+inline 										\
+Matrix<T1, Rows, Cols>&								\
+operator OP (Matrix<T1, Rows, Cols>& lhs, const Matrix<T2, Rows, Cols>& rhs) {	\
+  return lhs.M_##NAME(rhs);							\
+}										\
+										\
+template<class T, class E, std::size_t Rows,  std::size_t Cols>			\
+inline 										\
+Matrix<T, Rows, Cols>&								\
+operator OP (Matrix<T, Rows, Cols>& lhs, const XprMatrix<E, Rows, Cols>& rhs) {	\
+  return lhs.M_##NAME(rhs);							\
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq, +=)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub_eq, -=)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mul_eq, *=)		// see note
+  TVMET_IMPLEMENT_MACRO(div_eq, /=)		// not defined for vectors
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod_eq, %=)
+  TVMET_IMPLEMENT_MACRO(xor_eq, ^=)
+  TVMET_IMPLEMENT_MACRO(and_eq, &=)
+  TVMET_IMPLEMENT_MACRO(or_eq, |=)
+  TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
+  TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * operator(XprMatrix<E, Rows, Cols>, Matrix<T, Rows, Cols>)
+ * operator(Matrix<T, Rows, Cols>, XprMatrix<E, Rows, Cols>)
+ * Note: per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)						      \
+template<class T1, class T2, std::size_t Rows, std::size_t Cols>		      \
+inline										      \
+XprMatrix<									      \
+  XprBinOp<									      \
+    Fcnl_##NAME<T1, T2>,							      \
+    MatrixConstReference<T1, Rows, Cols>,					      \
+    MatrixConstReference<T2, Rows, Cols>					      \
+  >,										      \
+  Rows, Cols									      \
+>										      \
+operator OP (const Matrix<T1, Rows, Cols>& lhs,	const Matrix<T2, Rows, Cols>& rhs) {  \
+  return NAME(lhs, rhs);							      \
+}										      \
+										      \
+template<class E, class T, std::size_t Rows, std::size_t Cols>			      \
+inline										      \
+XprMatrix<									      \
+  XprBinOp<									      \
+    Fcnl_##NAME<typename E::value_type, T>,					      \
+    XprMatrix<E, Rows, Cols>,							      \
+    MatrixConstReference<T, Rows, Cols>						      \
+  >,										      \
+  Rows, Cols									      \
+>										      \
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs) { \
+  return NAME(lhs, rhs);							      \
+}										      \
+										      \
+template<class T, class E, std::size_t Rows, std::size_t Cols>			      \
+inline										      \
+XprMatrix<									      \
+  XprBinOp<									      \
+    Fcnl_##NAME<typename E::value_type, T>,					      \
+    MatrixConstReference<T, Rows, Cols>,					      \
+    XprMatrix<E, Rows, Cols>							      \
+  >,										      \
+  Rows, Cols									      \
+>										      \
+operator OP (const Matrix<T, Rows, Cols>& lhs, const XprMatrix<E, Rows, Cols>& rhs) { \
+  return NAME(lhs, rhs);							      \
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)			// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)			// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mul, *)			// see as prod()
+  TVMET_IMPLEMENT_MACRO(div, /)			// not defined for matrizes
+}
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * operator(Matrix<T, Rows, Cols>, POD)
+ * operator(POD, Matrix<T, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, POD)			\
+template<class T, std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T, POD >,					\
+    MatrixConstReference<T, Rows, Cols>,			\
+    XprLiteral<POD >						\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const Matrix<T, Rows, Cols>& lhs, POD rhs) {	\
+  return NAME (lhs, rhs);					\
+}								\
+								\
+template<class T, std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME< POD, T>,					\
+    XprLiteral< POD >,						\
+    MatrixConstReference<T, Rows, Cols>				\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (POD lhs, const Matrix<T, Rows, Cols>& rhs) {	\
+  return NAME (lhs, rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +, int)
+TVMET_IMPLEMENT_MACRO(sub, -, int)
+TVMET_IMPLEMENT_MACRO(mul, *, int)
+TVMET_IMPLEMENT_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, +, long long int)
+TVMET_IMPLEMENT_MACRO(sub, -, long long int)
+TVMET_IMPLEMENT_MACRO(mul, *, long long int)
+TVMET_IMPLEMENT_MACRO(div, /, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(add, +, float)
+TVMET_IMPLEMENT_MACRO(sub, -, float)
+TVMET_IMPLEMENT_MACRO(mul, *, float)
+TVMET_IMPLEMENT_MACRO(div, /, float)
+
+TVMET_IMPLEMENT_MACRO(add, +, double)
+TVMET_IMPLEMENT_MACRO(sub, -, double)
+TVMET_IMPLEMENT_MACRO(mul, *, double)
+TVMET_IMPLEMENT_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, +, long double)
+TVMET_IMPLEMENT_MACRO(sub, -, long double)
+TVMET_IMPLEMENT_MACRO(mul, *, long double)
+TVMET_IMPLEMENT_MACRO(div, /, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Matrix<T, Rows, Cols>, complex<T>)
+ * operator(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				\
+template<class T, std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		\
+    MatrixConstReference< std::complex<T>, Rows, Cols>,		\
+    XprLiteral<std::complex<T> >				\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const Matrix< std::complex<T>, Rows, Cols>& lhs,	\
+	     const std::complex<T>& rhs) {			\
+  return NAME (lhs, rhs);					\
+}								\
+								\
+template<class T, std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		\
+    XprLiteral< std::complex<T> >,				\
+    MatrixConstReference< std::complex<T>, Rows, Cols>		\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const std::complex<T>& lhs,			\
+	     const Matrix< std::complex<T>, Rows, Cols>& rhs) {	\
+  return NAME (lhs, rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)
+TVMET_IMPLEMENT_MACRO(sub, -)
+TVMET_IMPLEMENT_MACRO(mul, *)
+TVMET_IMPLEMENT_MACRO(div, /)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific operator*() = prod() operations
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ * \brief multiply two Matrices.
+ * \ingroup _binary_operator
+ * \note The rows2 has to be equal to cols1.
+ * \sa prod(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const Matrix<T1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of XprMatrix and Matrix.
+ * \ingroup _binary_operator
+ * \sa prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs)
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class T2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    MatrixConstReference<T2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const XprMatrix<E1, Rows1, Cols1>& lhs, const Matrix<T2, Cols1, Cols2>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/**
+ * \fn operator*(const Matrix<T1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of Matrix and XprMatrix.
+ * \ingroup _binary_operator
+ * \sa prod(const Matrix<T, Rows1, Cols1>& lhs, const XprMatrix<E, Cols1, Cols2>& rhs)
+ */
+template<class T1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    MatrixConstReference<T1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2
+>
+operator*(const Matrix<T1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const Matrix<T1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs)
+ * \brief multiply a Matrix with a Vector.
+ * \ingroup _binary_operator
+ * \note The length of the Vector has to be equal to the number of Columns.
+ * \sa prod(const Matrix<T1, Rows, Cols>& m, const Vector<T2, Cols>& v)
+ */
+template<class T1, std::size_t Rows, std::size_t Cols, class T2>
+inline
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  >,
+  Rows
+>
+operator*(const Matrix<T1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/**
+ * \fn operator*(const Matrix<T1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs)
+ * \brief Function for the matrix-vector-product
+ * \ingroup _binary_operator
+ * \sa prod(const Matrix<T, Rows, Cols>& lhs, const XprVector<E, Cols>& rhs)
+ */
+template<class T1, class E2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMVProduct<
+    MatrixConstReference<T1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+operator*(const Matrix<T1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs)
+ * \brief Compute the product of an XprMatrix with a Vector.
+ * \ingroup _binary_operator
+ * \sa prod(const XprMatrix<E, Rows, Cols>& lhs, const Vector<T, Cols>& rhs)
+ */
+template<class E1, class T2, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    VectorConstReference<T2, Cols>
+  >,
+  Rows
+>
+operator*(const XprMatrix<E1, Rows, Cols>& lhs, const Vector<T2, Cols>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Matrix<T1, Rows, Cols>, Matrix<T2, Rows, Cols>)
+ * operator(XprMatrix<E>, Matrix<T, Rows, Cols>)
+ * operator(Matrix<T, Rows, Cols>, XprMatrix<E>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)							\
+template<class T1, std::size_t Rows, std::size_t Cols,					\
+	 class T2>									\
+inline											\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME<T1, T2>,								\
+    MatrixConstReference<T1, Rows, Cols>,						\
+    MatrixConstReference<T2, Rows, Cols>						\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const Matrix<T1, Rows, Cols>& lhs,						\
+	     const Matrix<T2, Rows, Cols>& rhs) {					\
+  typedef XprBinOp <									\
+    Fcnl_##NAME<T1, T2>,								\
+    MatrixConstReference<T1, Rows, Cols>,						\
+    MatrixConstReference<T2, Rows, Cols>						\
+  >							expr_type;			\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(lhs.const_ref(), rhs.const_ref()));	\
+}											\
+											\
+template<class E,									\
+	 class T, std::size_t Rows, std::size_t Cols>					\
+inline											\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME<typename E::value_type, T>,						\
+    XprMatrix<E, Rows, Cols>,								\
+    MatrixConstReference<T, Rows, Cols>							\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, const Matrix<T, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, T>,						\
+    XprMatrix<E, Rows, Cols>,								\
+    MatrixConstReference<T, Rows, Cols>							\
+  > 							 expr_type;			\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(lhs, rhs.const_ref()));		\
+}											\
+											\
+template<class T, std::size_t Rows, std::size_t Cols,					\
+	 class E>									\
+inline											\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME<typename E::value_type, T>,						\
+    MatrixConstReference<T, Rows, Cols>,						\
+    XprMatrix<E, Rows, Cols>								\
+  >,											\
+  Rows, Cols										\
+>											\
+operator OP (const Matrix<T, Rows, Cols>& lhs, const XprMatrix<E, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<									\
+    Fcnl_##NAME<T, typename E::value_type>,						\
+    MatrixConstReference<T, Rows, Cols>,						\
+    XprMatrix<E, Rows, Cols>								\
+  >	 						 expr_type;			\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(lhs.const_ref(), rhs));		\
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^)
+  TVMET_IMPLEMENT_MACRO(bitand, &)
+  TVMET_IMPLEMENT_MACRO(bitor, |)
+  TVMET_IMPLEMENT_MACRO(shl, <<)
+  TVMET_IMPLEMENT_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Matrix<T, Rows, Cols>, complex<T>)
+ * operator(complex<T>, Matrix<T, Rows, Cols>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				     \
+template<class T, std::size_t Rows, std::size_t Cols>		     \
+inline								     \
+XprMatrix<							     \
+  XprBinOp<							     \
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		     \
+    MatrixConstReference< std::complex<T>, Rows, Cols>,		     \
+    XprLiteral<std::complex<T> >				     \
+  >,								     \
+  Rows, Cols							     \
+>								     \
+operator OP (const Matrix< std::complex<T>, Rows, Cols>& lhs,	     \
+	     const std::complex<T>& rhs) {			     \
+  typedef XprBinOp<						     \
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		     \
+    MatrixConstReference< std::complex<T>, Rows, Cols>,		     \
+    XprLiteral< std::complex<T> >				     \
+  >							expr_type;   \
+  return XprMatrix<expr_type, Rows, Cols>(			     \
+    expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs))); \
+}								     \
+								     \
+template<class T, std::size_t Rows, std::size_t Cols>		     \
+inline								     \
+XprMatrix<							     \
+  XprBinOp<							     \
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		     \
+    XprLiteral< std::complex<T> >,				     \
+    MatrixConstReference< std::complex<T>, Rows, Cols>		     \
+  >,								     \
+  Rows, Cols							     \
+>								     \
+operator OP (const std::complex<T>& lhs,			     \
+	     const Matrix< std::complex<T>, Rows, Cols>& rhs) {	     \
+  typedef XprBinOp<						     \
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,		     \
+    XprLiteral< std::complex<T> >,				     \
+    MatrixConstReference<T, Rows, Cols>				     \
+  >							expr_type;   \
+  return XprMatrix<expr_type, Rows, Cols>(			     \
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs.const_ref())); \
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(Matrix<T, Rows, Cols>, POD)
+ * operator(POD, Matrix<T, Rows, Cols>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, TP)			   \
+template<class T, std::size_t Rows, std::size_t Cols>		   \
+inline								   \
+XprMatrix<							   \
+  XprBinOp<							   \
+    Fcnl_##NAME<T, TP >,					   \
+    MatrixConstReference<T, Rows, Cols>,			   \
+    XprLiteral<TP >						   \
+  >,								   \
+  Rows, Cols							   \
+>								   \
+operator OP (const Matrix<T, Rows, Cols>& lhs, TP rhs) {	   \
+  typedef XprBinOp<						   \
+    Fcnl_##NAME<T, TP >,					   \
+    MatrixConstReference<T, Rows, Cols>,			   \
+    XprLiteral< TP >						   \
+  >							expr_type; \
+  return XprMatrix<expr_type, Rows, Cols>(			   \
+    expr_type(lhs.const_ref(), XprLiteral< TP >(rhs)));		   \
+}								   \
+								   \
+template<class T, std::size_t Rows, std::size_t Cols>		   \
+inline								   \
+XprMatrix<							   \
+  XprBinOp<							   \
+    Fcnl_##NAME< TP, T>,					   \
+    XprLiteral< TP >,						   \
+    MatrixConstReference<T, Rows, Cols>				   \
+  >,								   \
+  Rows, Cols							   \
+>								   \
+operator OP (TP lhs, const Matrix<T, Rows, Cols>& rhs) {	   \
+  typedef XprBinOp<						   \
+    Fcnl_##NAME< TP, T>,					   \
+    XprLiteral< TP >,						   \
+    MatrixConstReference<T, Rows, Cols>				   \
+  >							expr_type; \
+  return XprMatrix<expr_type, Rows, Cols>(			   \
+    expr_type(XprLiteral< TP >(lhs), rhs.const_ref()));		   \
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, int)
+TVMET_IMPLEMENT_MACRO(less, <, int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, int)
+TVMET_IMPLEMENT_MACRO(eq, ==, int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, int)
+TVMET_IMPLEMENT_MACRO(and, &&, int)
+TVMET_IMPLEMENT_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, long long int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, long long int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, long long int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, long long int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, long long int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long long int)
+TVMET_IMPLEMENT_MACRO(less, <, long long int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long long int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long long int)
+TVMET_IMPLEMENT_MACRO(eq, ==, long long int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long long int)
+TVMET_IMPLEMENT_MACRO(and, &&, long long int)
+TVMET_IMPLEMENT_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, float)
+TVMET_IMPLEMENT_MACRO(less, <, float)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, float)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, float)
+TVMET_IMPLEMENT_MACRO(eq, ==, float)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, float)
+TVMET_IMPLEMENT_MACRO(and, &&, float)
+TVMET_IMPLEMENT_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, double)
+TVMET_IMPLEMENT_MACRO(less, <, double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, double)
+TVMET_IMPLEMENT_MACRO(eq, ==, double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, double)
+TVMET_IMPLEMENT_MACRO(and, &&, double)
+TVMET_IMPLEMENT_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long double)
+TVMET_IMPLEMENT_MACRO(less, <, long double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long double)
+TVMET_IMPLEMENT_MACRO(eq, ==, long double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long double)
+TVMET_IMPLEMENT_MACRO(and, &&, long double)
+TVMET_IMPLEMENT_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(Matrix<T, Rows, Cols>)
+ * Note: per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				       \
+template <class T, std::size_t Rows, std::size_t Cols>		       \
+inline								       \
+XprMatrix<							       \
+  XprUnOp<							       \
+    Fcnl_##NAME<T>,						       \
+    MatrixConstReference<T, Rows, Cols>				       \
+  >,								       \
+  Rows, Cols							       \
+>								       \
+operator OP (const Matrix<T, Rows, Cols>& rhs) {		       \
+  typedef XprUnOp<						       \
+    Fcnl_##NAME<T>,						       \
+    MatrixConstReference<T, Rows, Cols>				       \
+  >  							 expr_type;    \
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(rhs.const_ref())); \
+}
+
+TVMET_IMPLEMENT_MACRO(not, !)
+TVMET_IMPLEMENT_MACRO(compl, ~)
+TVMET_IMPLEMENT_MACRO(neg, -)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_OPERATORS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MatrixUnaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,222 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixUnaryFunctions.h,v 1.13 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_MATRIX_UNARY_FUNCTIONS_H
+#define TVMET_MATRIX_UNARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * unary_function(Matrix<T, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)                \
+template<class T, std::size_t Rows, std::size_t Cols>        \
+inline                                \
+XprMatrix<                            \
+  XprUnOp<                            \
+    Fcnl_##NAME<T>,                        \
+    MatrixConstReference<T, Rows, Cols>                \
+  >,                                \
+  Rows, Cols                            \
+>                                \
+NAME(const Matrix<T, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(abs)
+TVMET_DECLARE_MACRO(cbrt)
+TVMET_DECLARE_MACRO(ceil)
+TVMET_DECLARE_MACRO(floor)
+TVMET_DECLARE_MACRO(rint)
+TVMET_DECLARE_MACRO(sin)
+TVMET_DECLARE_MACRO(cos)
+TVMET_DECLARE_MACRO(tan)
+TVMET_DECLARE_MACRO(sinh)
+TVMET_DECLARE_MACRO(cosh)
+TVMET_DECLARE_MACRO(tanh)
+TVMET_DECLARE_MACRO(asin)
+TVMET_DECLARE_MACRO(acos)
+TVMET_DECLARE_MACRO(atan)
+TVMET_DECLARE_MACRO(exp)
+TVMET_DECLARE_MACRO(log)
+TVMET_DECLARE_MACRO(log10)
+TVMET_DECLARE_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_DECLARE_MACRO(asinh)
+TVMET_DECLARE_MACRO(acosh)
+TVMET_DECLARE_MACRO(atanh)
+TVMET_DECLARE_MACRO(expm1)
+TVMET_DECLARE_MACRO(log1p)
+TVMET_DECLARE_MACRO(erf)
+TVMET_DECLARE_MACRO(erfc)
+TVMET_DECLARE_MACRO(j0)
+TVMET_DECLARE_MACRO(j1)
+TVMET_DECLARE_MACRO(y0)
+TVMET_DECLARE_MACRO(y1)
+TVMET_DECLARE_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_DECLARE_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * unary_function(Matrix<std::complex<T>, Rows, Cols>)
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+#define TVMET_DECLARE_MACRO(NAME)                        \
+template<class T, std::size_t Rows, std::size_t Cols>                \
+inline                                        \
+XprMatrix<                                    \
+  XprUnOp<                                    \
+    Fcnl_##NAME< std::complex<T> >,                        \
+    MatrixConstReference<std::complex<T>, Rows, Cols>                \
+  >,                                        \
+  Rows, Cols                                    \
+>                                        \
+NAME(const Matrix<std::complex<T>, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(real)
+TVMET_DECLARE_MACRO(imag)
+TVMET_DECLARE_MACRO(arg)
+TVMET_DECLARE_MACRO(norm)
+TVMET_DECLARE_MACRO(conj)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * unary_function(Matrix<T, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)                    \
+template<class T, std::size_t Rows, std::size_t Cols>            \
+inline                                    \
+XprMatrix<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME<T>,                            \
+    MatrixConstReference<T, Rows, Cols>                    \
+  >,                                    \
+  Rows, Cols                                \
+>                                    \
+NAME(const Matrix<T, Rows, Cols>& rhs) {                \
+  typedef XprUnOp<                            \
+    Fcnl_##NAME<T>,                            \
+    MatrixConstReference<T, Rows, Cols>                    \
+  >                             expr_type;    \
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(rhs.const_ref()));    \
+}
+
+TVMET_IMPLEMENT_MACRO(abs)
+TVMET_IMPLEMENT_MACRO(cbrt)
+TVMET_IMPLEMENT_MACRO(ceil)
+TVMET_IMPLEMENT_MACRO(floor)
+TVMET_IMPLEMENT_MACRO(rint)
+TVMET_IMPLEMENT_MACRO(sin)
+TVMET_IMPLEMENT_MACRO(cos)
+TVMET_IMPLEMENT_MACRO(tan)
+TVMET_IMPLEMENT_MACRO(sinh)
+TVMET_IMPLEMENT_MACRO(cosh)
+TVMET_IMPLEMENT_MACRO(tanh)
+TVMET_IMPLEMENT_MACRO(asin)
+TVMET_IMPLEMENT_MACRO(acos)
+TVMET_IMPLEMENT_MACRO(atan)
+TVMET_IMPLEMENT_MACRO(exp)
+TVMET_IMPLEMENT_MACRO(log)
+TVMET_IMPLEMENT_MACRO(log10)
+TVMET_IMPLEMENT_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_IMPLEMENT_MACRO(asinh)
+TVMET_IMPLEMENT_MACRO(acosh)
+TVMET_IMPLEMENT_MACRO(atanh)
+TVMET_IMPLEMENT_MACRO(expm1)
+TVMET_IMPLEMENT_MACRO(log1p)
+TVMET_IMPLEMENT_MACRO(erf)
+TVMET_IMPLEMENT_MACRO(erfc)
+TVMET_IMPLEMENT_MACRO(j0)
+TVMET_IMPLEMENT_MACRO(j1)
+TVMET_IMPLEMENT_MACRO(y0)
+TVMET_IMPLEMENT_MACRO(y1)
+TVMET_IMPLEMENT_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_IMPLEMENT_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * unary_function(Matrix<std::complex<T>, Rows, Cols>)
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+#define TVMET_IMPLEMENT_MACRO(NAME)                    \
+template<class T, std::size_t Rows, std::size_t Cols>            \
+inline                                    \
+XprMatrix<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME< std::complex<T> >,                    \
+    MatrixConstReference<std::complex<T>, Rows, Cols>            \
+  >,                                    \
+  Rows, Cols                                \
+>                                    \
+NAME(const Matrix<std::complex<T>, Rows, Cols>& rhs) {            \
+  typedef XprUnOp<                            \
+    Fcnl_##NAME< std::complex<T> >,                    \
+    MatrixConstReference<std::complex<T>, Rows, Cols>            \
+  >                             expr_type;    \
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(rhs.const_ref()));    \
+}
+
+TVMET_IMPLEMENT_MACRO(real)
+TVMET_IMPLEMENT_MACRO(imag)
+TVMET_IMPLEMENT_MACRO(arg)
+TVMET_IMPLEMENT_MACRO(norm)
+TVMET_IMPLEMENT_MACRO(conj)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_MATRIX_UNARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NumericTraits.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,1363 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: NumericTraits.h,v 1.16 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_NUMERIC_TRAITS_H
+#define TVMET_NUMERIC_TRAITS_H
+
+#if defined(TVMET_HAVE_COMPLEX)
+#  include <complex>
+#endif
+#include <cmath>
+#include <limits>
+
+#include <tvmet/CompileTimeError.h>
+
+
+namespace tvmet {
+
+
+/**
+ * \class NumericTraits NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits for integral types for operations.
+ *
+ * For each type we have to specialize this traits.
+ *
+ * \note Keep in mind that the long types long long and long double doesn't
+ *       have traits. This is due to the sum_type. We can't give a guarantee
+ *       that there is a type of holding the sum. Therefore using this traits
+ *       is only safe if you have long long resp. long double types by
+ *       working on long ints and doubles. Otherwise you will get not expected
+ *       result for some circumstances. Anyway, you can use big integer/float
+ *       libraries and specialize the traits by your own.
+ *
+ * \todo The abs function of complex<non_float_type> can have an
+ *       overrun due to numeric computation. Solve it (someone
+ *       using value_type=long here?)
+ */
+template<class T>
+struct NumericTraits {
+  typedef T					base_type;
+  typedef T					value_type;
+  typedef value_type				sum_type;
+  typedef value_type				diff_type;
+  typedef value_type				float_type;
+  typedef value_type				signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type x);
+
+  static inline
+  base_type imag(argument_type x);
+
+  static inline
+  value_type conj(argument_type x);
+
+  static inline
+  base_type abs(argument_type x);
+
+  static inline
+  value_type sqrt(argument_type x);
+
+  static inline
+  base_type norm_1(argument_type x) {
+    return NumericTraits<base_type>::abs(traits_type::real(x))
+         + NumericTraits<base_type>::abs(traits_type::imag(x));
+  }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(x)),
+		    NumericTraits<base_type>::abs(traits_type::imag(x)));
+   }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+};
+
+
+/*
+ * numeric traits for standard types
+ */
+
+
+/**
+ * \class NumericTraits<char> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for char.
+ */
+template<>
+struct NumericTraits<char> {
+  typedef char					value_type;
+  typedef value_type				base_type;
+  typedef long					sum_type;
+  typedef int					diff_type;
+  typedef float					float_type;
+  typedef char					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<unsigned char> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for unsigned char.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits<unsigned char> {
+  typedef unsigned char 			value_type;
+  typedef value_type				base_type;
+  typedef unsigned long	 			sum_type;
+  typedef int		 			diff_type;
+  typedef float		 			float_type;
+  typedef int					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<short int> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for short int.
+ */
+template<>
+struct NumericTraits<short int> {
+  typedef short int 				value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef long long		 		sum_type;
+#else
+  typedef long 					sum_type;
+#endif
+  typedef int			 		diff_type;
+  typedef float 				float_type;
+  typedef short int				signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<short unsigned int> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for short unsigned int.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits<short unsigned int> {
+  typedef short unsigned int			value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef unsigned long long			sum_type;
+#else
+  typedef unsigned long 			sum_type;
+#endif
+  typedef int 					diff_type;
+  typedef float 				float_type;
+  typedef int					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<int> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for int.
+ */
+template<>
+struct NumericTraits<int> {
+  typedef int 					value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef long long		 		sum_type;
+#else
+  typedef long 					sum_type;
+#endif
+  typedef int			 		diff_type;
+  typedef double			 	float_type;
+  typedef int					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<unsigned int> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for unsigned int.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits<unsigned int> {
+  typedef unsigned int 		 		value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef unsigned long long			sum_type;
+#else
+  typedef unsigned long 			sum_type;
+#endif
+  typedef int 			 		diff_type;
+  typedef double 				float_type;
+  typedef long			 		signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  base_type abs(argument_type x) { return x; }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<long> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for long.
+ */
+template<>
+struct NumericTraits<long> {
+  typedef long 			 		value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef long long		 		sum_type;
+#else
+  typedef long			  		sum_type;
+#endif
+  typedef long 		 			diff_type;
+  typedef double 				float_type;
+  typedef long		 	 		signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<unsigned long> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for unsigned long.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits<unsigned long> {
+  typedef unsigned long 			value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef unsigned long long 			sum_type;
+#else
+  typedef unsigned long 			sum_type;
+#endif
+  typedef unsigned long 			diff_type;
+  typedef double 				float_type;
+  typedef long					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  base_type abs(argument_type x) { return x; }
+
+  static inline
+  value_type sqrt(argument_type x) {
+    return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
+  }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<float> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for float.
+ */
+template<>
+struct NumericTraits<float> {
+  typedef float					value_type;
+  typedef value_type				base_type;
+  typedef double 				sum_type;
+  typedef float 				diff_type;
+  typedef float 				float_type;
+  typedef float					signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) { return std::sqrt(x); }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits<double> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for double.
+ */
+template<>
+struct NumericTraits<double> {
+  typedef double 				value_type;
+  typedef value_type				base_type;
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+  typedef long double		 		sum_type;
+#else
+  typedef double 				sum_type;
+#endif
+  typedef double				diff_type;
+  typedef double 				float_type;
+  typedef double				signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) { return std::sqrt(x); }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+/**
+ * \class NumericTraits<long double> NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for long double.
+ */
+template<>
+struct NumericTraits<long double> {
+  typedef long double 				value_type;
+  typedef value_type				base_type;
+  typedef long double		 		sum_type;
+  typedef long double				diff_type;
+  typedef long double 				float_type;
+  typedef long double				signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef value_type				argument_type;
+
+  static inline
+  base_type real(argument_type x) { return x; }
+
+  static inline
+  base_type imag(argument_type) { return 0; }
+
+  static inline
+  value_type conj(argument_type x) { return x; }
+
+  static inline
+  base_type abs(argument_type x) { return std::abs(x); }
+
+  static inline
+  value_type sqrt(argument_type x) { return std::sqrt(x); }
+
+  static inline
+  base_type norm_1(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_2(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  base_type norm_inf(argument_type x) { return traits_type::abs(x); }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = false };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 1,	/**< Complexity on plus/minus ops. */
+    ops_muls = 1	/**< Complexity on multiplications. */
+  };
+};
+#endif // TVMET_HAVE_LONG_DOUBLE
+
+
+/*
+ * numeric traits for complex types
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+
+/**
+ * \class NumericTraits< std::complex<int> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<int>.
+ */
+template<>
+struct NumericTraits< std::complex<int> > {
+  typedef int					base_type;
+  typedef std::complex<int>			value_type;
+  typedef std::complex<long> 			sum_type;
+  typedef std::complex<int>			diff_type;
+  typedef std::complex<float>			float_type;
+  typedef std::complex<int>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  value_type conj(argument_type z) { return std::conj(z); }
+
+  static inline
+  base_type abs(argument_type z) {
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    // XXX probably case of overrun; header complex uses scaling
+    return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
+  }
+
+  static /* inline */
+  value_type sqrt(argument_type z) {
+    // borrowed and adapted from header complex
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    if(x == base_type()) {
+	base_type t = NumericTraits<base_type>::sqrt(
+                        NumericTraits<base_type>::abs(y) / 2);
+	return value_type(t, y < base_type() ? -t : t);
+    }
+    else {
+      base_type t = NumericTraits<base_type>::sqrt(
+		      2 * (traits_type::abs(z)
+		            + NumericTraits<base_type>::abs(x)));
+      base_type u = t / 2;
+      return x > base_type()
+	? value_type(u, y / t)
+	: value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u);
+    }
+  }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+		    NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    return (traits_type::real(lhs) == traits_type::real(rhs))
+        && (traits_type::imag(lhs) == traits_type::imag(rhs));
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits< std::complex<unsigned int> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<unsigned int>.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits< std::complex<unsigned int> > {
+  typedef unsigned int				base_type;
+  typedef std::complex<unsigned int> 		value_type;
+  typedef std::complex<unsigned long> 		sum_type;
+  typedef std::complex<int>			diff_type;
+  typedef std::complex<float>			float_type;
+  typedef std::complex<int>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  base_type abs(argument_type z) {
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    // XXX probably case of overrun; header complex uses scaling
+    return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
+  }
+
+  static /* inline */
+  value_type sqrt(argument_type z) {
+    // borrowed and adapted from header complex
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    if(x == base_type()) {
+	base_type t = NumericTraits<base_type>::sqrt(
+                        NumericTraits<base_type>::abs(y) / 2);
+	return value_type(t, t);
+    }
+    else {
+      base_type t = NumericTraits<base_type>::sqrt(
+		      2 * (traits_type::abs(z)
+		            + NumericTraits<base_type>::abs(x)));
+      return value_type(t / 2, y / t);
+    }
+  }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+		    NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    return (traits_type::real(lhs) == traits_type::real(rhs))
+        && (traits_type::imag(lhs) == traits_type::imag(rhs));
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits< std::complex<long> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<long>.
+ */
+template<>
+struct NumericTraits< std::complex<long> > {
+  typedef long					base_type;
+  typedef std::complex<long>			value_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef std::complex<long long>		sum_type;
+#else
+  typedef std::complex<long>			sum_type;
+#endif
+  typedef std::complex<int>			diff_type;
+  typedef std::complex<float>			float_type;
+  typedef std::complex<int>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  value_type conj(argument_type z) { return std::conj(z); }
+
+  static inline
+  base_type abs(argument_type z) {
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    // XXX probably case of overrun; header complex uses scaling
+    return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
+  }
+
+  static /* inline */
+  value_type sqrt(argument_type z) {
+    // borrowed and adapted from header complex
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    if(x == base_type()) {
+	base_type t = NumericTraits<base_type>::sqrt(
+                        NumericTraits<base_type>::abs(y) / 2);
+	return value_type(t, y < base_type() ? -t : t);
+    }
+    else {
+      base_type t = NumericTraits<base_type>::sqrt(
+		      2 * (traits_type::abs(z)
+		            + NumericTraits<base_type>::abs(x)));
+      base_type u = t / 2;
+      return x > base_type()
+	? value_type(u, y / t)
+	: value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u);
+    }
+  }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+		    NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    return (traits_type::real(lhs) == traits_type::real(rhs))
+        && (traits_type::imag(lhs) == traits_type::imag(rhs));
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits< std::complex<unsigned long> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<unsigned long>.
+ *
+ * \note Normally it doesn't make sense to call <tt>conj</tt>
+ *       for an unsigned type! An unary minus operator
+ *       applied to unsigned type will result unsigned. Therefore
+ *       this function is missing here.
+ */
+template<>
+struct NumericTraits< std::complex<unsigned long> > {
+  typedef unsigned long				base_type;
+  typedef std::complex<unsigned long>		value_type;
+#if defined(TVMET_HAVE_LONG_LONG)
+  typedef std::complex<unsigned long long>	sum_type;
+#else
+  typedef std::complex<unsigned long>		sum_type;
+#endif
+  typedef std::complex<long>			diff_type;
+  typedef std::complex<float>			float_type;
+  typedef std::complex<long>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  base_type abs(argument_type z) {
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    // XXX probably case of overrun; header complex uses scaling
+    return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
+  }
+
+  static /* inline */
+  value_type sqrt(argument_type z) {
+    // borrowed and adapted from header complex
+    base_type x = z.real();
+    base_type y = z.imag();
+
+    if(x == base_type()) {
+	base_type t = NumericTraits<base_type>::sqrt(
+                        NumericTraits<base_type>::abs(y) / 2);
+	return value_type(t, t);
+    }
+    else {
+      base_type t = NumericTraits<base_type>::sqrt(
+		      2 * (traits_type::abs(z)
+		            + NumericTraits<base_type>::abs(x)));
+      return value_type(t / 2, y / t);
+    }
+  }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+		    NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    return (traits_type::real(lhs) == traits_type::real(rhs))
+        && (traits_type::imag(lhs) == traits_type::imag(rhs));
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity  on operations.*/
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits< std::complex<float> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<float>.
+ */
+template<>
+struct NumericTraits< std::complex<float> > {
+  typedef float					base_type;
+  typedef std::complex<float>			value_type;
+  typedef std::complex<double>			sum_type;
+  typedef std::complex<float>			diff_type;
+  typedef std::complex<float>			float_type;
+  typedef std::complex<float>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  value_type conj(argument_type z) { return std::conj(z); }
+
+  static inline
+  base_type abs(argument_type z) { return std::abs(z); }
+
+  static inline
+  value_type sqrt(argument_type z) { return std::sqrt(z); }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+	            NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+ static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+/**
+ * \class NumericTraits< std::complex<double> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<double>.
+ */
+template<>
+struct NumericTraits< std::complex<double> > {
+  typedef double				base_type;
+  typedef std::complex<double>			value_type;
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+  typedef std::complex<long double> 		sum_type;
+#else
+  typedef std::complex<double>			sum_type;
+#endif
+  typedef std::complex<double>			diff_type;
+  typedef std::complex<double>			float_type;
+  typedef std::complex<double>			signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  value_type conj(argument_type z) { return std::conj(z); }
+
+  static inline
+  base_type abs(argument_type z) { return std::abs(z); }
+
+  static inline
+  value_type sqrt(argument_type z) { return std::sqrt(z); }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+	            NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+ static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+/**
+ * \class NumericTraits< std::complex<long double> > NumericTraits.h "tvmet/NumericTraits.h"
+ * \brief Traits specialized for std::complex<double>.
+ */
+template<>
+struct NumericTraits< std::complex<long double> > {
+  typedef long double				base_type;
+  typedef std::complex<long double>		value_type;
+  typedef std::complex<long double> 		sum_type;
+  typedef std::complex<long double>		diff_type;
+  typedef std::complex<long double>		float_type;
+  typedef std::complex<long double>		signed_type;
+
+  typedef NumericTraits<value_type>		traits_type;
+  typedef const value_type&			argument_type;
+
+  static inline
+  base_type real(argument_type z) { return std::real(z); }
+
+  static inline
+  base_type imag(argument_type z) { return std::imag(z); }
+
+  static inline
+  value_type conj(argument_type z) { return std::conj(z); }
+
+  static inline
+  base_type abs(argument_type z) { return std::abs(z); }
+
+  static inline
+  value_type sqrt(argument_type z) { return std::sqrt(z); }
+
+  static inline
+  base_type norm_1(argument_type z) {
+    return NumericTraits<base_type>::abs((traits_type::real(z)))
+         + NumericTraits<base_type>::abs((traits_type::imag(z)));
+  }
+
+  static inline
+  base_type norm_2(argument_type z) { return traits_type::abs(z); }
+
+  static inline
+  base_type norm_inf(argument_type z) {
+    return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
+	            NumericTraits<base_type>::abs(traits_type::imag(z)));
+  }
+
+  static inline
+  bool equals(argument_type lhs, argument_type rhs) {
+    static base_type sqrt_epsilon(
+      NumericTraits<base_type>::sqrt(
+        std::numeric_limits<base_type>::epsilon()));
+
+    return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
+      std::max(std::max(traits_type::norm_inf(lhs),
+			traits_type::norm_inf(rhs)),
+	       std::numeric_limits<base_type>::min());
+  }
+
+  enum { is_complex = true };
+
+  /** Complexity on operations. */
+  enum {
+    ops_plus = 2,	/**< Complexity on plus/minus ops. */
+    ops_muls = 6	/**< Complexity on multiplications. */
+  };
+};
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+
+#endif //  TVMET_NUMERIC_TRAITS_H
+
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RunTimeError.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,66 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: RunTimeError.h,v 1.13 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_RUN_TIME_ERROR_H
+#define TVMET_RUN_TIME_ERROR_H
+
+#include <cassert>
+
+
+namespace tvmet {
+
+
+/**
+ * \def TVMET_RT_CONDITION(XPR, MSG)
+ * \brief If TVMET_DEBUG is defined it checks the condition XPR and prints
+ * an error message MSG at runtime.
+ */
+#if defined(TVMET_DEBUG)
+
+#define TVMET_RT_CONDITION(XPR, MSG) {					\
+  if(!(XPR)) {								\
+    std::cerr << "[tvmet] Precondition failure in " << __FILE__		\
+              << ", line " << __LINE__ << ": "				\
+              << MSG << std::endl;					\
+    std::cerr.flush();							\
+    assert(0);								\
+  }									\
+}
+
+#else
+
+#define TVMET_RT_CONDITION(XPR, MSG)
+
+#endif
+
+
+} // namespace tvmet
+
+
+#endif // TVMET_RUN_TIME_ERROR_H
+
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TvmetBase.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,112 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: TvmetBase.h,v 1.17 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_BASE_H
+#define TVMET_BASE_H
+
+#include <iostream>//<iosfwd>                // io streams forward declaration
+#include <typeinfo>                // rtti: used by Xpr.h level printing
+#include <cmath>                // unary and binary math
+#include <cstdlib>                // labs
+
+#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER == 1310)
+#include <string>                // operator<<(ostream) here defined
+#endif
+
+#if defined(__APPLE_CC__)
+// Mac OS X builds seems to miss these functions inside cmath
+extern "C" int isnan(double);
+extern "C" int isinf(double);
+#endif
+
+namespace tvmet {
+
+
+/**
+ * \class TvmetBase TvmetBase.h "tvmet/TvmetBase.h"
+ * \brief Base class
+ * Used for static polymorph call of print_xpr
+ */
+template<class E> class TvmetBase { };
+
+
+/**
+ * \class IndentLevel TvmetBase.h "tvmet/TvmetBase.h"
+ * \brief Prints the level indent.
+ */
+class IndentLevel : public TvmetBase< IndentLevel >
+{
+public:
+  IndentLevel(std::size_t level) : m_level(level) { }
+
+  std::ostream& print_xpr(std::ostream& os) const {
+    for(std::size_t i = 0; i != m_level; ++i) os << "   ";
+    return os;
+  }
+
+private:
+  std::size_t                     m_level;
+};
+
+
+/**
+ * \fn operator<<(std::ostream& os, const TvmetBase<E>& e)
+ * \brief overloaded ostream operator using static polymorphic.
+ * \ingroup _binary_operator
+ */
+template<class E>
+inline
+std::ostream& operator<<(std::ostream& os, const TvmetBase<E>& e) {
+  static_cast<const E&>(e).print_xpr(os);
+  return os;
+}
+
+
+/**
+ * \class dispatch TvmetBase.h "tvmet/TvmetBase.h"
+ * \brief Class helper to distuingish between e.g. meta
+ *        and loop strategy used.
+ */
+template<bool> struct dispatch;
+
+/**
+ * \class dispatch<true> TvmetBase.h "tvmet/TvmetBase.h"
+ * \brief specialized.
+ */
+template<> struct dispatch<true>  { };
+
+/**
+ * \class dispatch<false> TvmetBase.h "tvmet/TvmetBase.h"
+ * \brief specialized.
+ */
+template<> struct dispatch<false> { };
+
+
+} // namespace tvmet
+
+#endif // TVMET_BASE_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TypePromotion.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,232 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: TypePromotion.h,v 1.10 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_TYPE_PROMOTION_H
+#define TVMET_TYPE_PROMOTION_H
+
+namespace tvmet {
+
+
+/**
+ * \class PrecisionTraits TypePromotion.h "tvmet/TypePromotion.h"
+ * \brief Declaring ranks of types to avoid specializing
+ *
+ * All possible promoted types. For example, bool=1, int=2, float=3, double=4,
+ * etc. We can use a traits class to map from a type such as float onto its
+ * "precision rank". We will promote to whichever type has a higher
+ * "precision rank". f there is no "precision rank" for a type, we'll
+ * promote to whichever type requires more storage space
+ * (and hopefully more precision).
+ */
+template<class T>
+struct PrecisionTraits {
+  enum {
+    rank = 0,			/**< the rank of type. */
+    known = 0 			/**< true, if the rank is specialized = known. */
+  };
+};
+
+
+#define TVMET_PRECISION(T,R)      					\
+template<>                          					\
+struct PrecisionTraits< T > {        					\
+  enum {                          					\
+    rank = R,                   					\
+    known = 1                   					\
+  };                              					\
+};
+
+
+/*
+ * pod types
+ */
+TVMET_PRECISION(int, 100)
+TVMET_PRECISION(unsigned int, 200)
+TVMET_PRECISION(long, 300)
+TVMET_PRECISION(unsigned long, 400)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_PRECISION(long long, 500)
+TVMET_PRECISION(unsigned long long, 600)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_PRECISION(float, 700)
+TVMET_PRECISION(double, 800)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_PRECISION(long double, 900)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+
+/*
+ * complex types
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_PRECISION(std::complex<int>, 1000)
+TVMET_PRECISION(std::complex<unsigned int>, 1100)
+TVMET_PRECISION(std::complex<long>, 1200)
+TVMET_PRECISION(std::complex<unsigned long>, 1300)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_PRECISION(std::complex<long long>, 1400)
+TVMET_PRECISION(std::complex<unsigned long long>, 1500)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_PRECISION(std::complex<float>, 1600)
+TVMET_PRECISION(std::complex<double>, 1700)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_PRECISION(std::complex<long double>, 1800)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/** \class PrecisionTraits<int>				TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<unsigned int> 		TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<long>			TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<unsigned long> 		TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<long long>			TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<unsigned long long> 		TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<float>			TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<double>			TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits<long double>			TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<int> >		TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<unsigned int> > TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<long> >	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<unsigned long> > TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<long long> >	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<unsigned long long> > TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<float> >	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<double> >	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class PrecisionTraits< std::complex<long double> >	TypePromotion.h "tvmet/TypePromotion.h" */
+
+#undef TVMET_PRECISION
+
+
+/**
+ * \class AutopromoteTraits TypePromotion.h "tvmet/TypePromotion.h"
+ * \brief The promoted types traits.
+ */
+template<class T>
+struct AutopromoteTraits {
+  typedef T value_type;
+};
+
+
+/*
+ * Defines a macro for specializing/defining
+ * the promotion traits. bool, char, unsigned char, short int, etc. will
+ * be autopromote to int, as in C and C++.
+ */
+#define TVMET_AUTOPROMOTE(T1,T2)   					\
+template<>                          				 	\
+struct AutopromoteTraits<T1> {     					\
+  typedef T2 value_type;          					\
+};
+
+TVMET_AUTOPROMOTE(bool, int)
+TVMET_AUTOPROMOTE(char, int)
+TVMET_AUTOPROMOTE(unsigned char, int)
+TVMET_AUTOPROMOTE(short int, int)
+TVMET_AUTOPROMOTE(short unsigned int, unsigned int)
+
+/** \class AutopromoteTraits<bool>	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class AutopromoteTraits<char>	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class AutopromoteTraits<unsigned char> TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class AutopromoteTraits<short int>	TypePromotion.h "tvmet/TypePromotion.h" */
+/** \class AutopromoteTraits<short unsigned int> TypePromotion.h "tvmet/TypePromotion.h" */
+
+#undef TVMET_AUTOPROMOTE
+
+
+/**
+ * \class promoteTo TypePromotion.h "tvmet/TypePromotion.h"
+ * \brief Promote to T1.
+ */
+template<class T1, class T2, int promoteToT1>
+struct promoteTo {
+  typedef T1 value_type;
+};
+
+
+/**
+ * \class promoteTo<T1,T2,0> TypePromotion.h "tvmet/TypePromotion.h"
+ * \brief Promote to T2
+ */
+template<class T1, class T2>
+struct promoteTo<T1,T2,0> {
+  typedef T2 value_type;
+};
+
+
+/**
+ * \class PromoteTraits TypePromotion.h "tvmet/TypePromotion.h"
+ * \brief Promote type traits
+ */
+template<class T1org, class T2org>
+class PromoteTraits {
+  // Handle promotion of small integers to int/unsigned int
+  typedef typename AutopromoteTraits<T1org>::value_type T1;
+  typedef typename AutopromoteTraits<T2org>::value_type T2;
+
+  enum {
+    // True if T1 is higher ranked
+    T1IsBetter = int(PrecisionTraits<T1>::rank) > int(PrecisionTraits<T2>::rank),
+
+    // True if we know ranks for both T1 and T2
+    knowBothRanks = PrecisionTraits<T1>::known && PrecisionTraits<T2>::known,
+
+    // True if we know T1 but not T2
+    knowT1butNotT2 = PrecisionTraits<T1>::known && !(PrecisionTraits<T2>::known),
+
+    // True if we know T2 but not T1
+    knowT2butNotT1 =  PrecisionTraits<T2>::known && !(PrecisionTraits<T1>::known),
+
+    // True if T1 is bigger than T2
+    T1IsLarger = sizeof(T1) >= sizeof(T2),
+
+    // We know T1 but not T2: true
+    // We know T2 but not T1: false
+    // Otherwise, if T1 is bigger than T2: true
+    defaultPromotion = knowT1butNotT2 ? false : (knowT2butNotT1 ? true : T1IsLarger),
+
+    // If we have both ranks, then use them.
+    // If we have only one rank, then use the unknown type.
+    // If we have neither rank, then promote to the larger type.
+    promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion) ? 1 : 0
+  };
+
+ public:
+  typedef typename promoteTo<T1,T2,promoteToT1>::value_type value_type;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_TYPE_PROMOTION_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/UnaryFunctionals.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,349 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: UnaryFunctionals.h,v 1.24 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_UNARY_FUNCTIONAL_H
+#define TVMET_UNARY_FUNCTIONAL_H
+
+namespace tvmet {
+
+/** \class Fcnl_compl	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_neg	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_not	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class T>							\
+struct Fcnl_##NAME : public UnaryFunctional {				\
+  typedef T						value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(value_type rhs) {					\
+    return OP rhs;							\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(T).name() << ">,"					\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(compl, ~)
+TVMET_IMPLEMENT_MACRO(neg, -)
+TVMET_IMPLEMENT_MACRO(not, !)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_abs		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_ceil		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_floor		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" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T>							\
+struct Fcnl_##NAME : public UnaryFunctional {				\
+  typedef T						value_type;	\
+  									\
+  static inline 							\
+  value_type apply_on(value_type rhs) {					\
+    return TVMET_STD_SCOPE(NAME)(rhs);					\
+  }									\
+  									\
+ static 								\
+ void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(value_type).name() << ">,"				\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(abs)	// specialized later, see below
+TVMET_IMPLEMENT_MACRO(ceil)
+TVMET_IMPLEMENT_MACRO(floor)
+TVMET_IMPLEMENT_MACRO(sin)
+TVMET_IMPLEMENT_MACRO(cos)
+TVMET_IMPLEMENT_MACRO(tan)
+TVMET_IMPLEMENT_MACRO(sinh)
+TVMET_IMPLEMENT_MACRO(cosh)
+TVMET_IMPLEMENT_MACRO(tanh)
+TVMET_IMPLEMENT_MACRO(asin)
+TVMET_IMPLEMENT_MACRO(acos)
+TVMET_IMPLEMENT_MACRO(atan)
+TVMET_IMPLEMENT_MACRO(exp)
+TVMET_IMPLEMENT_MACRO(log)
+TVMET_IMPLEMENT_MACRO(log10)
+TVMET_IMPLEMENT_MACRO(sqrt)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/** \class Fcnl_cbrt		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_rint		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T>							\
+struct Fcnl_##NAME : public UnaryFunctional {				\
+  typedef T						value_type;	\
+									\
+  static inline								\
+  value_type apply_on(value_type rhs) {					\
+    return TVMET_GLOBAL_SCOPE(NAME)(rhs);				\
+  }									\
+									\
+ static									\
+ void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(value_type).name() << ">,"				\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(cbrt)
+TVMET_IMPLEMENT_MACRO(rint)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+
+/** \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" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T>							\
+struct Fcnl_##NAME : public UnaryFunctional {				\
+  typedef T						value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(value_type rhs) {					\
+    return TVMET_GLOBAL_SCOPE(NAME)(rhs);				\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(value_type).name() << ">,"				\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(asinh)
+TVMET_IMPLEMENT_MACRO(acosh)
+TVMET_IMPLEMENT_MACRO(atanh)
+TVMET_IMPLEMENT_MACRO(expm1)
+TVMET_IMPLEMENT_MACRO(log1p)
+TVMET_IMPLEMENT_MACRO(erf)
+TVMET_IMPLEMENT_MACRO(erfc)
+TVMET_IMPLEMENT_MACRO(j0)
+TVMET_IMPLEMENT_MACRO(j1)
+TVMET_IMPLEMENT_MACRO(y0)
+TVMET_IMPLEMENT_MACRO(y1)
+TVMET_IMPLEMENT_MACRO(lgamma)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+
+/** \class Fcnl_abs<long int>		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_abs<long long int>	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_abs<float>		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_abs<double>		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_abs<long double> 	UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template <class T> struct Fcnl_##NAME;					\
+template <>								\
+struct Fcnl_##NAME< POD > : public UnaryFunctional {			\
+  typedef POD						value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(value_type rhs) {					\
+    return TVMET_STD_SCOPE(NAME)(rhs);					\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(value_type).name() << ">,"				\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(labs, long int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(labs, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(fabs, float)
+TVMET_IMPLEMENT_MACRO(fabs, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(fabs, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * complex support
+ */
+
+#if defined(TVMET_HAVE_COMPLEX)
+/**
+ * \class Fcnl_abs< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h"
+ */
+template <class T>
+struct Fcnl_abs< std::complex<T> > : public UnaryFunctional {
+  typedef T						value_type;
+
+  static inline
+  value_type apply_on(const std::complex<T>& rhs) {
+    return std::abs(rhs);
+  }
+
+  static
+  void print_xpr(std::ostream& os, std::size_t l=0) {
+    os << IndentLevel(l) << "Fcnl_abs<T="
+       << typeid(std::complex<T>).name() << ">,"
+       << std::endl;
+  }
+};
+
+
+/**
+ * \class Fcnl_conj< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h"
+ * \brief %Functional for conj.
+ */
+template <class T> struct Fcnl_conj : public UnaryFunctional { };
+
+
+/** \class Fcnl_conj< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+template <class T>
+struct Fcnl_conj< std::complex<T> > : public UnaryFunctional {
+  typedef std::complex<T>                               value_type;
+
+  static inline
+  value_type apply_on(const std::complex<T>& rhs) {
+    return std::conj(rhs);
+  }
+
+  static
+  void print_xpr(std::ostream& os, std::size_t l=0) {
+    os << IndentLevel(l) << "Fcnl_conj<T="
+       << typeid(std::complex<T>).name() << ">,"
+       << std::endl;
+  }
+};
+
+
+/** \class Fcnl_real< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_imag< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_arg< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_norm< std::complex<T> > UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template <class T> struct Fcnl_##NAME;					\
+template <class T>							\
+struct Fcnl_##NAME< std::complex<T> > : public UnaryFunctional {	\
+  typedef T						value_type;	\
+									\
+  static inline 							\
+  value_type apply_on(const std::complex<T>& rhs) {			\
+    return TVMET_STD_SCOPE(NAME)(rhs);					\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(std::complex<T>).name() << ">,"			\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(real)
+TVMET_IMPLEMENT_MACRO(imag)
+TVMET_IMPLEMENT_MACRO(arg)
+TVMET_IMPLEMENT_MACRO(norm)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+
+/** \class Fcnl_isnan		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_isinf		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+/** \class Fcnl_finite		UnaryFunctionals.h "tvmet/UnaryFunctionals.h" */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template <class T>							\
+struct Fcnl_##NAME : public UnaryFunctional {				\
+  typedef T						value_type;	\
+									\
+  static inline 							\
+  POD apply_on(T rhs) {							\
+    return TVMET_GLOBAL_SCOPE(NAME)(rhs);				\
+  }									\
+  									\
+  static 								\
+  void print_xpr(std::ostream& os, std::size_t l=0) {			\
+    os << IndentLevel(l) << "Fcnl_" << #NAME << "<T="			\
+       << typeid(POD).name() << ">,"					\
+       << std::endl;							\
+  }									\
+};
+
+TVMET_IMPLEMENT_MACRO(isnan, int)
+TVMET_IMPLEMENT_MACRO(isinf, int)
+TVMET_IMPLEMENT_MACRO(finite, int)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif //  defined(TVMET_HAVE_IEEE_MATH)
+
+} // namespace tvmet
+
+#endif // TVMET_UNARY_FUNCTIONAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vector.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,563 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Vector.h,v 1.48 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_H
+#define TVMET_VECTOR_H
+
+#include <iterator>					// reverse_iterator
+
+#include <tvmet/tvmet.h>
+#include <tvmet/TypePromotion.h>
+#include <tvmet/CommaInitializer.h>
+#include <tvmet/RunTimeError.h>
+
+#include <tvmet/xpr/Vector.h>
+
+namespace tvmet {
+
+
+/* forwards */
+template<class T, std::size_t Sz> class Vector;
+
+
+/**
+ * \class VectorConstReference Vector.h "tvmet/Vector.h"
+ * \brief Const value iterator for ET
+ */
+template<class T, std::size_t Sz>
+class VectorConstReference
+  : public TvmetBase< VectorConstReference<T, Sz> >
+{
+public: // types
+  typedef T 						value_type;
+  typedef T*						pointer;
+  typedef const T*					const_pointer;
+
+public:
+  /** Dimensions. */
+  enum {
+    Size = Sz			/**< The size of the vector. */
+  };
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops        = Size
+  };
+
+private:
+  VectorConstReference();
+  VectorConstReference& operator=(const VectorConstReference&);
+
+public:
+  /** Constructor. */
+  explicit VectorConstReference(const Vector<T, Size>& rhs)
+    : m_data(rhs.data())
+  { }
+
+  /** Constructor by a given memory pointer. */
+  explicit VectorConstReference(const_pointer data)
+    : m_data(data)
+  { }
+
+public: // access operators
+  /** access by index. */
+  value_type operator()(std::size_t i) const {
+    TVMET_RT_CONDITION(i < Size, "VectorConstReference Bounce Violation")
+    return m_data[i];
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l)
+       << "VectorConstReference[O=" << ops << "]<"
+       << "T=" << typeid(T).name() << ">,"
+       << std::endl;
+  }
+
+private:
+  const_pointer _tvmet_restrict 			m_data;
+};
+
+
+/**
+ * \class Vector Vector.h "tvmet/Vector.h"
+ * \brief Compile time fixed length vector with evaluation on compile time.
+ */
+template<class T, std::size_t Sz>
+class Vector
+{
+public:
+  /** Data type of the tvmet::Vector. */
+  typedef T     					value_type;
+
+  /** Reference type of the tvmet::Vector data elements. */
+  typedef T&     					reference;
+
+  /** const reference type of the tvmet::Vector data elements. */
+  typedef const T&     					const_reference;
+
+  /** STL iterator interface. */
+  typedef T*     					iterator;
+
+  /** STL const_iterator interface. */
+  typedef const T*     					const_iterator;
+
+  /** STL reverse iterator interface. */
+  typedef std::reverse_iterator<iterator> 		reverse_iterator;
+
+  /** STL const reverse iterator interface. */
+  typedef std::reverse_iterator<const_iterator> 	const_reverse_iterator;
+
+public:
+  /** Dimensions. */
+  enum {
+    Size = Sz			/**< The size of the vector. */
+  };
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_assign = Size,
+    ops        = ops_assign,
+    use_meta   = ops < TVMET_COMPLEXITY_V_ASSIGN_TRIGGER ? true : false
+  };
+
+public: // STL  interface
+  /** STL iterator interface. */
+  iterator begin() { return m_data; }
+
+  /** STL iterator interface. */
+  iterator end() { return m_data + Size; }
+
+  /** STL const_iterator interface. */
+  const_iterator begin() const { return m_data; }
+
+  /** STL const_iterator interface. */
+  const_iterator end() const { return m_data + Size; }
+
+  /** STL reverse iterator interface reverse begin. */
+  reverse_iterator rbegin() { return reverse_iterator( end() ); }
+
+  /** STL const reverse iterator interface reverse begin. */
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator( end() );
+  }
+
+  /** STL reverse iterator interface reverse end. */
+  reverse_iterator rend() { return reverse_iterator( begin() ); }
+
+  /** STL const reverse iterator interface reverse end. */
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator( begin() );
+  }
+
+  /** STL vector front element. */
+  value_type front() { return m_data[0]; }
+
+  /** STL vector const front element. */
+  const_reference front() const { return m_data[0]; }
+
+  /** STL vector back element. */
+  value_type back() { return m_data[Size-1]; }
+
+  /** STL vector const back element. */
+  const_reference back() const { return m_data[Size-1]; }
+
+  /** STL vector empty() - returns allways false. */
+  static bool empty() { return false; }
+
+  /** The size of the vector. */
+  static std::size_t size() { return Size; }
+
+  /** STL vector max_size() - returns allways Size. */
+  static std::size_t max_size() { return Size; }
+
+public:
+  /** Default Destructor */
+  ~Vector() {
+#if defined(TVMET_DYNAMIC_MEMORY)
+    delete [] m_data;
+#endif
+  }
+
+  /** Default Constructor. The allocated memory region isn't cleared. If you want
+   a clean use the constructor argument zero. */
+  explicit Vector()
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  { }
+
+  /** Copy Constructor, not explicit! */
+  Vector(const Vector& rhs)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    *this = XprVector<ConstReference, Size>(rhs.const_ref());
+  }
+
+  /**
+   * Constructor with STL iterator interface. The data will be copied into the
+   * vector self, there isn't any stored reference to the array pointer.
+   */
+  template<class InputIterator>
+  explicit Vector(InputIterator first, InputIterator last)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_RT_CONDITION( static_cast<std::size_t>(std::distance(first, last)) <= Size,
+			"InputIterator doesn't fits in size" )
+    std::copy(first, last, m_data);
+  }
+
+  /**
+   * Constructor with STL iterator interface. The data will be copied into the
+   * vector self, there isn't any stored reference to the array pointer.
+   */
+  template<class InputIterator>
+  explicit Vector(InputIterator first, std::size_t sz)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_RT_CONDITION( sz <= Size, "InputIterator doesn't fits in size" )
+    std::copy(first, first + sz, m_data);
+  }
+
+  /** Constructor with initializer for all elements.  */
+  explicit Vector(value_type rhs)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    typedef XprLiteral<value_type> expr_type;
+    *this = XprVector<expr_type, Size>(expr_type(rhs));
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(2 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(3 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(4 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(5 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4, value_type x5)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(6 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+    m_data[5] = x5;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4, value_type x5, value_type x6)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(7 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+    m_data[5] = x5; m_data[6] = x6;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4, value_type x5, value_type x6, value_type x7)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(8 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+    m_data[5] = x5; m_data[6] = x6; m_data[7] = x7;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4, value_type x5, value_type x6, value_type x7,
+		  value_type x8)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(9 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+    m_data[5] = x5; m_data[6] = x6; m_data[7] = x7; m_data[8] = x8;
+  }
+
+  /** Default Constructor with initializer list. */
+  explicit Vector(value_type x0, value_type x1, value_type x2, value_type x3,
+		  value_type x4, value_type x5, value_type x6, value_type x7,
+		  value_type x8, value_type x9)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    TVMET_CT_CONDITION(10 <= Size, ArgumentList_is_too_long)
+    m_data[0] = x0; m_data[1] = x1; m_data[2] = x2; m_data[3] = x3; m_data[4] = x4;
+    m_data[5] = x5; m_data[6] = x6; m_data[7] = x7; m_data[8] = x8; m_data[9] = x9;
+  }
+
+  /** Construct a vector by expression. */
+  template <class E>
+  explicit Vector(const XprVector<E, Size>& e)
+#if defined(TVMET_DYNAMIC_MEMORY)
+    : m_data( new value_type[Size] )
+#endif
+  {
+    *this = e;
+  }
+
+  /** Assign a value_type on array, this can be used for a single value
+      or a comma separeted list of values. */
+  CommaInitializer<Vector, Size> operator=(value_type rhs) {
+    return CommaInitializer<Vector, Size>(*this, rhs);
+  }
+
+public: // access operators
+  value_type* _tvmet_restrict data() { return m_data; }
+  const value_type* _tvmet_restrict data() const { return m_data; }
+
+public: // index access operators
+  value_type& _tvmet_restrict operator()(std::size_t i) {
+    // Note: g++-2.95.3 does have problems on typedef reference
+    TVMET_RT_CONDITION(i < Size, "Vector Bounce Violation")
+    return m_data[i];
+  }
+
+  value_type operator()(std::size_t i) const {
+    TVMET_RT_CONDITION(i < Size, "Vector Bounce Violation")
+    return m_data[i];
+  }
+
+  value_type& _tvmet_restrict operator[](std::size_t i) {
+    // Note: g++-2.95.3 does have problems on typedef reference
+    return this->operator()(i);
+  }
+
+  value_type operator[](std::size_t i) const {
+    return this->operator()(i);
+  }
+
+public: // ET interface
+  typedef VectorConstReference<T, Size>    		ConstReference;
+
+  /** Return a const Reference of the internal data */
+  ConstReference const_ref() const { return ConstReference(*this); }
+
+  /** Return the vector as const expression. */
+  XprVector<ConstReference, Size> as_expr() const {
+    return XprVector<ConstReference, Size>(this->const_ref());
+  }
+
+private:
+  /** Wrapper for meta assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    meta::Vector<Size, 0>::assign(dest, src, assign_fn);
+  }
+
+  /** Wrapper for loop assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    loop::Vector<Size>::assign(dest, src, assign_fn);
+  }
+
+public:
+  /** assign this to a vector expression using the functional assign_fn. */
+  template<class T2, class Assign>
+  void assign_to(Vector<T2, Size>& dest, const Assign& assign_fn) const {
+    do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
+  }
+
+public:   // assign operations
+  /** assign a given Vector element wise to this vector.
+      The operator=(const Vector&) is compiler generated. */
+  template<class T2>
+  Vector& operator=(const Vector<T2, Size>& rhs) {
+    rhs.assign_to(*this, Fcnl_assign<value_type, T2>());
+    return *this;
+  }
+
+  /** assign a given XprVector element wise to this vector. */
+  template<class E>
+  Vector& operator=(const XprVector<E, Size>& rhs) {
+    rhs.assign_to(*this, Fcnl_assign<value_type, typename E::value_type>());
+    return *this;
+  }
+
+private:
+  template<class Obj, std::size_t LEN> friend class CommaInitializer;
+
+  /** This is a helper for assigning a comma separated initializer
+      list. It's equal to Vector& operator=(value_type) which does
+      replace it. */
+  Vector& assign_value(value_type rhs) {
+    typedef XprLiteral<value_type> 			expr_type;
+    *this = XprVector<expr_type, Size>(expr_type(rhs));
+    return *this;
+  }
+
+public: // math operators with scalars
+  // NOTE: this meaning is clear - element wise ops even if not in ns element_wise
+  Vector& operator+=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator-=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator*=(value_type) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator/=(value_type) TVMET_CXX_ALWAYS_INLINE;
+
+  Vector& operator%=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator^=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator&=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator|=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator<<=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+  Vector& operator>>=(std::size_t) TVMET_CXX_ALWAYS_INLINE;
+
+public: // math assign operators with vectors
+  // NOTE: access using the operators in ns element_wise, since that's what is does
+  template <class T2> Vector& M_add_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_sub_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_mul_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_div_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_mod_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_xor_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_and_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_or_eq (const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_shl_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& M_shr_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // math operators with expressions
+  // NOTE: access using the operators in ns element_wise, since that's what is does
+  template <class E> Vector& M_add_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_sub_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_mul_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_div_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_mod_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_xor_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_and_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_or_eq (const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_shl_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& M_shr_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // aliased math operators with expressions, used with proxy
+  template <class T2> Vector& alias_assign(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& alias_add_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& alias_sub_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& alias_mul_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class T2> Vector& alias_div_eq(const Vector<T2, Size>&) TVMET_CXX_ALWAYS_INLINE;
+
+  template <class E> Vector& alias_assign(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& alias_add_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& alias_sub_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& alias_mul_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+  template <class E> Vector& alias_div_eq(const XprVector<E, Size>&) TVMET_CXX_ALWAYS_INLINE;
+
+public: // io
+  /** Structure for info printing as Vector<T, Size>. */
+  struct Info : public TvmetBase<Info> {
+    std::ostream& print_xpr(std::ostream& os) const {
+      os << "Vector<T=" << typeid(value_type).name()
+	 << ", Sz=" << Size << ">";
+      return os;
+    }
+  };
+
+  /** Get an info object of this vector. */
+  static Info info() { return Info(); }
+
+  /** Member function for expression level printing. */
+  std::ostream& print_xpr(std::ostream& os, std::size_t l=0) const;
+
+  /** Member function for printing internal data. */
+  std::ostream& print_on(std::ostream& os) const;
+
+private:
+  /** The data of vector self. */
+
+#if defined(TVMET_DYNAMIC_MEMORY)
+  value_type*						m_data;
+#else
+  value_type 						m_data[Size];
+#endif
+};
+
+
+} // namespace tvmet
+
+#include <tvmet/VectorImpl.h>
+#include <tvmet/VectorFunctions.h>
+#include <tvmet/VectorBinaryFunctions.h>
+#include <tvmet/VectorUnaryFunctions.h>
+#include <tvmet/VectorOperators.h>
+#include <tvmet/VectorEval.h>
+#include <tvmet/AliasProxy.h>
+
+#endif // TVMET_VECTOR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorBinaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,531 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorBinaryFunctions.h,v 1.17 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_BINARY_FUNCTIONS_H
+#define TVMET_VECTOR_BINARY_FUNCTIONS_H
+
+#include <tvmet/NumericTraits.h>
+#include <tvmet/Extremum.h>
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * binary_function(Vector<T1, Sz>, Vector<T1, Sz>)
+ * binary_function(Vector<T, Sz>, XprVector<E>)
+ * binary_function(XprVector<E>, Vector<T, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)				\
+template<class T1, class T2, std::size_t Sz>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T1, T2>,					\
+    VectorConstReference<T1, Sz>,				\
+    VectorConstReference<T2, Sz>				\
+  >,								\
+  Sz								\
+>								\
+NAME(const Vector<T1, Sz>& lhs, 				\
+     const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+								\
+template<class E, class T, std::size_t Sz>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, T>,			\
+    VectorConstReference<T, Sz>,				\
+    XprVector<E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+NAME(const XprVector<E, Sz>& lhs, 				\
+     const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+								\
+template<class E, class T, std::size_t Sz>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T, typename E::value_type>,			\
+    VectorConstReference<T, Sz>,				\
+    XprVector<E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+NAME(const Vector<T, Sz>& lhs, 					\
+     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+TVMET_DECLARE_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_DECLARE_MACRO(polar)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * binary_function(Vector<T, Sz>, POD)
+ */
+#define TVMET_DECLARE_MACRO(NAME, TP)				\
+template<class T, std::size_t Sz>				\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T, TP >,					\
+    VectorConstReference<T, Sz>,				\
+    XprLiteral< TP >						\
+  >,								\
+  Sz								\
+>								\
+NAME(const Vector<T, Sz>& lhs, TP rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2, int)
+TVMET_DECLARE_MACRO(drem, int)
+TVMET_DECLARE_MACRO(fmod, int)
+TVMET_DECLARE_MACRO(hypot, int)
+TVMET_DECLARE_MACRO(jn, int)
+TVMET_DECLARE_MACRO(yn, int)
+TVMET_DECLARE_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(atan2, long long int)
+TVMET_DECLARE_MACRO(drem, long long int)
+TVMET_DECLARE_MACRO(fmod, long long int)
+TVMET_DECLARE_MACRO(hypot, long long int)
+TVMET_DECLARE_MACRO(jn, long long int)
+TVMET_DECLARE_MACRO(yn, long long int)
+TVMET_DECLARE_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(atan2, float)
+TVMET_DECLARE_MACRO(drem, float)
+TVMET_DECLARE_MACRO(fmod, float)
+TVMET_DECLARE_MACRO(hypot, float)
+TVMET_DECLARE_MACRO(jn, float)
+TVMET_DECLARE_MACRO(yn, float)
+TVMET_DECLARE_MACRO(pow, float)
+
+TVMET_DECLARE_MACRO(atan2, double)
+TVMET_DECLARE_MACRO(drem, double)
+TVMET_DECLARE_MACRO(fmod, double)
+TVMET_DECLARE_MACRO(hypot, double)
+TVMET_DECLARE_MACRO(jn, double)
+TVMET_DECLARE_MACRO(yn, double)
+TVMET_DECLARE_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(atan2, long double)
+TVMET_DECLARE_MACRO(drem, long double)
+TVMET_DECLARE_MACRO(fmod, long double)
+TVMET_DECLARE_MACRO(hypot, long double)
+TVMET_DECLARE_MACRO(jn, long double)
+TVMET_DECLARE_MACRO(yn, long double)
+TVMET_DECLARE_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * complex support
+ */
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    VectorConstReference<T, Sz>,
+    XprLiteral< std::complex<T> >
+  >,
+  Sz
+>
+pow(const Vector<T, Sz>& lhs,
+    const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, std::complex<T> >,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral< std::complex<T> >
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs,
+    const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<T>
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs,
+    const T& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<int>
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs,
+    int rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_polar<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral<T>
+  >,
+  Sz
+>
+polar(const Vector<T, Sz>& lhs, const T& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+// to be written (atan2)
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+/*
+ * binary_function(Vector<T1, Sz>, Vector<T1, Sz>)
+ * binary_function(Vector<T, Sz>, XprVector<E>)
+ * binary_function(XprVector<E>, Vector<T, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class T1, class T2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+NAME(const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {		\
+  typedef XprBinOp <							\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs.const_ref()));			\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME(const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  > 							 expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, rhs.const_ref()));					\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME(const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  > 						 	expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs));					\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+TVMET_IMPLEMENT_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_IMPLEMENT_MACRO(polar)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * binary_function(Vector<T, Sz>, POD)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, TP)					\
+template<class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, TP >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+NAME(const Vector<T, Sz>& lhs, TP rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, TP >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), XprLiteral< TP >(rhs)));			\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2, int)
+TVMET_IMPLEMENT_MACRO(drem, int)
+TVMET_IMPLEMENT_MACRO(fmod, int)
+TVMET_IMPLEMENT_MACRO(hypot, int)
+TVMET_IMPLEMENT_MACRO(jn, int)
+TVMET_IMPLEMENT_MACRO(yn, int)
+TVMET_IMPLEMENT_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(atan2, long long int)
+TVMET_IMPLEMENT_MACRO(drem, long long int)
+TVMET_IMPLEMENT_MACRO(fmod, long long int)
+TVMET_IMPLEMENT_MACRO(hypot, long long int)
+TVMET_IMPLEMENT_MACRO(jn, long long int)
+TVMET_IMPLEMENT_MACRO(yn, long long int)
+TVMET_IMPLEMENT_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(atan2, float)
+TVMET_IMPLEMENT_MACRO(drem, float)
+TVMET_IMPLEMENT_MACRO(fmod, float)
+TVMET_IMPLEMENT_MACRO(hypot, float)
+TVMET_IMPLEMENT_MACRO(jn, float)
+TVMET_IMPLEMENT_MACRO(yn, float)
+TVMET_IMPLEMENT_MACRO(pow, float)
+
+TVMET_IMPLEMENT_MACRO(atan2, double)
+TVMET_IMPLEMENT_MACRO(drem, double)
+TVMET_IMPLEMENT_MACRO(fmod, double)
+TVMET_IMPLEMENT_MACRO(hypot, double)
+TVMET_IMPLEMENT_MACRO(jn, double)
+TVMET_IMPLEMENT_MACRO(yn, double)
+TVMET_IMPLEMENT_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(atan2, long double)
+TVMET_IMPLEMENT_MACRO(drem, long double)
+TVMET_IMPLEMENT_MACRO(fmod, long double)
+TVMET_IMPLEMENT_MACRO(hypot, long double)
+TVMET_IMPLEMENT_MACRO(jn, long double)
+TVMET_IMPLEMENT_MACRO(yn, long double)
+TVMET_IMPLEMENT_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * complex support
+ */
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+/**
+ * \fn pow(const Vector<T, Sz>& lhs, const std::complex<T>& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    VectorConstReference<T, Sz>,
+    XprLiteral< std::complex<T> >
+  >,
+  Sz
+>
+pow(const Vector<T, Sz>& lhs, const std::complex<T>& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<T, std::complex<T> >,
+    VectorConstReference<T, Sz>,
+    XprLiteral< std::complex<T> >
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+      expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));
+}
+
+
+/**
+ * \fn pow(const Vector<std::complex<T>, Sz>& lhs, const std::complex<T>& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, std::complex<T> >,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral< std::complex<T> >
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs, const std::complex<T>& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<std::complex<T>, std::complex<T> >,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral< std::complex<T> >
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+      expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));
+}
+
+
+/**
+ * \fn pow(const Vector<std::complex<T>, Sz>& lhs, const T& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<T>
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs, const T& rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<std::complex<T>, T>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<T>
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+      expr_type(lhs.const_ref(), XprLiteral<T>(rhs)));
+}
+
+
+/**
+ * \fn pow(const Vector<std::complex<T>, Sz>& lhs, int rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<int>
+  >,
+  Sz
+>
+pow(const Vector<std::complex<T>, Sz>& lhs, int rhs) {
+  typedef XprBinOp<
+    Fcnl_pow<std::complex<T>, int>,
+    VectorConstReference<std::complex<T>, Sz>,
+    XprLiteral<int>
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+      expr_type(lhs.const_ref(), XprLiteral<int>(rhs)));
+}
+
+
+/**
+ * \fn polar(const Vector<T, Sz>& lhs, const T& rhs)
+ * \ingroup _binary_function
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_polar<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral<T>
+  >,
+  Sz
+>
+polar(const Vector<T, Sz>& lhs, const T& rhs) {
+  typedef XprBinOp<
+    Fcnl_polar<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral<T>
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+      expr_type(lhs.const_ref(), XprLiteral<T>(rhs)));
+}
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH1)
+
+#if defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+// to be written (atan2)
+#endif // defined(TVMET_HAVE_COMPLEX) && defined(TVMET_HAVE_COMPLEX_MATH2)
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_BINARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorEval.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,382 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorEval.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_EVAL_H
+#define TVMET_VECTOR_EVAL_H
+
+namespace tvmet {
+
+
+/********************************************************************
+ * functions all_elements/any_elements
+ ********************************************************************/
+
+
+/**
+ * \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
+ * \par Example:
+ * \code
+ * all_elements(vector > 0) {
+ *     // true branch
+ * } else {
+ *     // false branch
+ * }
+ * \endcode
+ * \sa \ref compare
+ */
+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
+ * \par Example:
+ * \code
+ * any_elements(vector > 0) {
+ *     // true branch
+ * } else {
+ *     // false branch
+ * }
+ * \endcode
+ * \sa \ref compare
+ */
+template<class E, std::size_t Sz>
+inline
+bool any_elements(const XprVector<E, Sz>& e) {
+  return meta::Vector<Sz>::any_elements(e);
+}
+
+
+/*
+ * trinary evaluation functions with vectors and xpr of
+ * 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(const XprVector<E1, Sz>& e1, const Vector<T2, Sz>& v2, 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 T2, class T3, std::size_t Sz>
+inline
+XprVector<
+  XprEval<
+    XprVector<E1, Sz>,
+    VectorConstReference<T2, Sz>,
+    VectorConstReference<T3, Sz>
+  >,
+  Sz
+>
+eval(const 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.const_ref(), v3.const_ref()));
+}
+
+
+/**
+ * eval(const XprVector<E1, Sz>& e1, const Vector<T2, Sz>& v2, const 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(const XprVector<E1, Sz>& e1, const Vector<T2, Sz>& v2, const 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.const_ref(), e3));
+}
+
+
+/**
+ * eval(const XprVector<E1, Sz>& e1, const 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(const XprVector<E1, Sz>& e1, const 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.const_ref()));
+}
+
+
+/**
+ * eval(const XprVector<E1, Sz>& e1, const XprVector<E2, Sz>& e2, const 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(const XprVector<E1, Sz>& e1, const XprVector<E2, Sz>& e2, const 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));
+}
+
+
+/*
+ * trinary evaluation functions with vectors, xpr of and POD
+ *
+ * XprVector<E, Sz> ? POD1 : POD2
+ * XprVector<E1, Sz> ? POD : XprVector<E3, Sz>
+ * XprVector<E1, Sz> ? XprVector<E2, Sz> : POD
+ */
+#define TVMET_IMPLEMENT_MACRO(POD)         				\
+template<class E, std::size_t Sz>      					\
+inline               							\
+XprVector<               						\
+  XprEval<               						\
+    XprVector<E, Sz>,               					\
+    XprLiteral< POD >,               					\
+    XprLiteral< POD >               					\
+  >,                							\
+  Sz									\
+>               							\
+eval(const 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(const XprVector<E1, Sz>& e1, POD x2, const 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(const XprVector<E1, Sz>& e1, const 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_IMPLEMENT_MACRO(int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(float)
+TVMET_IMPLEMENT_MACRO(double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * trinary evaluation functions with vectors, xpr of and 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
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+
+
+/**
+ * eval(const 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(const 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(const XprVector<E1, Sz>& e1, std::complex<T> z2, const 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(const XprVector<E1, Sz>& e1, std::complex<T> z2, const 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(const XprVector<E1, Sz>& e1, const 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(const XprVector<E1, Sz>& e1, const 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)));
+}
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_EVAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,883 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorFunctions.h,v 1.37 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_FUNCTIONS_H
+#define TVMET_VECTOR_FUNCTIONS_H
+
+#include <tvmet/Extremum.h>
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(Vector<T1, Sz>, Vector<T2, Sz>)
+ * function(Vector<T, Sz>, XprVector<E, Sz>)
+ * function(XprVector<E, Sz>, Vector<T, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)				\
+template<class T1, class T2, std::size_t Sz>			\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T1, T2>,					\
+    VectorConstReference<T1, Sz>,				\
+    VectorConstReference<T2, Sz>				\
+  >,								\
+  Sz								\
+>								\
+NAME (const Vector<T1, Sz>& lhs,				\
+      const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+								\
+template<class E, class T, std::size_t Sz>			\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, T>,			\
+    XprVector<E, Sz>,						\
+    VectorConstReference<T, Sz>					\
+  >,								\
+  Sz								\
+>								\
+NAME (const XprVector<E, Sz>& lhs,				\
+      const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+								\
+template<class E, class T, std::size_t Sz>			\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<T, typename E::value_type>,			\
+    VectorConstReference<T, Sz>,				\
+    XprVector<E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+NAME (const Vector<T, Sz>& lhs,					\
+      const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)		// per se element wise
+TVMET_DECLARE_MACRO(sub)		// per se element wise
+TVMET_DECLARE_MACRO(mul)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(div)		// not defined for vectors
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * function(Vector<T, Sz>, POD)
+ * function(POD, Vector<T, Sz>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, POD)				\
+template<class T, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< T, POD >,					\
+    VectorConstReference<T, Sz>,				\
+    XprLiteral< POD >						\
+  >,								\
+  Sz								\
+>								\
+NAME (const Vector<T, Sz>& lhs, 				\
+      POD rhs) TVMET_CXX_ALWAYS_INLINE;				\
+								\
+template<class T, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< POD, T>,					\
+    XprLiteral< POD >,						\
+    VectorConstReference<T, Sz>					\
+  >,								\
+  Sz								\
+>								\
+NAME (POD lhs, 							\
+      const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, int)
+TVMET_DECLARE_MACRO(sub, int)
+TVMET_DECLARE_MACRO(mul, int)
+TVMET_DECLARE_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, long long int)
+TVMET_DECLARE_MACRO(sub, long long int)
+TVMET_DECLARE_MACRO(mul, long long int)
+TVMET_DECLARE_MACRO(div, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, float)
+TVMET_DECLARE_MACRO(sub, float)
+TVMET_DECLARE_MACRO(mul, float)
+TVMET_DECLARE_MACRO(div, float)
+
+TVMET_DECLARE_MACRO(add, double)
+TVMET_DECLARE_MACRO(sub, double)
+TVMET_DECLARE_MACRO(mul, double)
+TVMET_DECLARE_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, long double)
+TVMET_DECLARE_MACRO(sub, long double)
+TVMET_DECLARE_MACRO(mul, long double)
+TVMET_DECLARE_MACRO(div, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * function(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class T, std::size_t Sz>					\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    VectorConstReference< std::complex<T>, Sz>,				\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+NAME (const Vector<std::complex<T>, Sz>& lhs,				\
+      const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+									\
+template<class T, std::size_t Sz>					\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,			\
+    XprLiteral< std::complex<T> >,					\
+    VectorConstReference< std::complex<T>, Sz>				\
+  >,									\
+  Sz									\
+>									\
+NAME (const std::complex<T>& lhs,					\
+      const Vector< std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)
+TVMET_DECLARE_MACRO(sub)
+TVMET_DECLARE_MACRO(mul)
+TVMET_DECLARE_MACRO(div)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * vector specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class T, std::size_t Sz>
+typename NumericTraits<T>::sum_type
+sum(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+typename NumericTraits<T>::sum_type
+product(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, class T2, std::size_t Sz>
+typename PromoteTraits<T1, T2>::value_type
+dot(const Vector<T1, Sz>& lhs,
+    const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T1, class T2>
+Vector<typename PromoteTraits<T1, T2>::value_type, 3>
+cross(const Vector<T1, 3>& lhs,
+      const Vector<T2, 3>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+typename NumericTraits<T>::sum_type
+norm1(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+typename NumericTraits<T>::sum_type
+norm2(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_div<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral< T >
+  >,
+  Sz
+>
+normalize(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * min/max unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+template<class E, std::size_t Sz>
+Extremum<typename E::value_type, std::size_t, vector_tag>
+maximum(const XprVector<E, Sz>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+Extremum<T, std::size_t, vector_tag>
+maximum(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+Extremum<typename E::value_type, std::size_t, vector_tag>
+minimum(const XprVector<E, Sz>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+Extremum<T, std::size_t, vector_tag>
+minimum(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename E::value_type
+max(const XprVector<E, Sz>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+T max(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename E::value_type
+min(const XprVector<E, Sz>& e); // NOT TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+T min(const Vector<T, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, std::size_t Sz>
+XprVector<
+  VectorConstReference<T, Sz>,
+  Sz
+>
+cvector_ref(const T* mem) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(Vector<T1, Sz>, Vector<T2, Sz>)
+ * function(Vector<T, Sz>, XprVector<E, Sz>)
+ * function(XprVector<E, Sz>, Vector<T, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class T1, class T2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+NAME (const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {		\
+  typedef XprBinOp <							\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs.const_ref()));			\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+NAME (const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) {		\
+  typedef XprBinOp<							\
+     Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  > 							 expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, rhs.const_ref()));					\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME (const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  > 						 	expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs));					\
+}
+
+TVMET_IMPLEMENT_MACRO(add)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(div)		// not defined for vectors
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * function(Vector<T, Sz>, POD)
+ * function(POD, Vector<T, Sz>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template<class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< T, POD >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< POD >							\
+  >,									\
+  Sz									\
+>									\
+NAME (const Vector<T, Sz>& lhs, POD rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, POD >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< POD >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), XprLiteral< POD >(rhs)));		\
+}									\
+									\
+template<class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+NAME (POD lhs, const Vector<T, Sz>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< POD, T>,						\
+    XprLiteral< POD >,							\
+    VectorConstReference<T, Sz>						\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< POD >(lhs), rhs.const_ref()));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add, int)
+TVMET_IMPLEMENT_MACRO(sub, int)
+TVMET_IMPLEMENT_MACRO(mul, int)
+TVMET_IMPLEMENT_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, long long int)
+TVMET_IMPLEMENT_MACRO(sub, long long int)
+TVMET_IMPLEMENT_MACRO(mul, long long int)
+TVMET_IMPLEMENT_MACRO(div, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, float)
+TVMET_IMPLEMENT_MACRO(sub, float)
+TVMET_IMPLEMENT_MACRO(mul, float)
+TVMET_IMPLEMENT_MACRO(div, float)
+
+TVMET_IMPLEMENT_MACRO(add, double)
+TVMET_IMPLEMENT_MACRO(sub, double)
+TVMET_IMPLEMENT_MACRO(mul, double)
+TVMET_IMPLEMENT_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, long double)
+TVMET_IMPLEMENT_MACRO(sub, long double)
+TVMET_IMPLEMENT_MACRO(mul, long double)
+TVMET_IMPLEMENT_MACRO(div, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * function(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)						\
+template<class T, std::size_t Sz>						\
+inline										\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    VectorConstReference< std::complex<T>, Sz>,					\
+    XprLiteral< std::complex<T> >						\
+  >,										\
+  Sz										\
+>										\
+NAME (const Vector<std::complex<T>, Sz>& lhs, const std::complex<T>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    VectorConstReference< std::complex<T>, Sz>,					\
+    XprLiteral< std::complex<T> >						\
+  >							expr_type;		\
+  return XprVector<expr_type, Sz>(						\
+    expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));		\
+}										\
+										\
+template<class T, std::size_t Sz>						\
+inline										\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    XprLiteral< std::complex<T> >,						\
+    VectorConstReference< std::complex<T>, Sz>					\
+  >,										\
+  Sz										\
+>										\
+NAME (const std::complex<T>& lhs, const Vector< std::complex<T>, Sz>& rhs) {	\
+  typedef XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    XprLiteral< std::complex<T> >,						\
+    VectorConstReference< std::complex<T>, Sz>					\
+  >							expr_type;		\
+  return XprVector<expr_type, Sz>(						\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs.const_ref()));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add)
+TVMET_IMPLEMENT_MACRO(sub)
+TVMET_IMPLEMENT_MACRO(mul)
+TVMET_IMPLEMENT_MACRO(div)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * vector specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn sum(const Vector<T, Sz>& v)
+ * \brief Compute the sum of the vector.
+ * \ingroup _unary_function
+ *
+ * Simply compute the sum of the given vector as:
+ * \f[
+ * \sum_{i = 0}^{Sz-1} v[i]
+ * \f]
+ */
+template<class T, std::size_t Sz>
+inline
+typename NumericTraits<T>::sum_type
+sum(const Vector<T, Sz>& v) {
+  return meta::Vector<Sz>::sum(v);
+}
+
+
+/**
+ * \fn product(const Vector<T, Sz>& v)
+ * \brief Compute the product of the vector elements.
+ * \ingroup _unary_function
+ *
+ * Simply computer the product of the given vector as:
+ * \f[
+ * \prod_{i = 0}^{Sz - 1} v[i]
+ * \f]
+ */
+template<class T, std::size_t Sz>
+inline
+typename NumericTraits<T>::sum_type
+product(const Vector<T, Sz>& v) {
+  return meta::Vector<Sz>::product(v);
+}
+
+
+/**
+ * \fn dot(const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs)
+ * \brief Compute the dot/inner product
+ * \ingroup _binary_function
+ *
+ * Compute the dot product as:
+ * \f[
+ * \sum_{i = 0}^{Sz - 1} ( lhs[i] * rhs[i] )
+ * \f]
+ * where lhs is a column vector and rhs is a row vector, both vectors
+ * have the same dimension.
+ */
+template<class T1, class T2, std::size_t Sz>
+inline
+typename PromoteTraits<T1, T2>::value_type
+dot(const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {
+  return meta::Vector<Sz>::dot(lhs, rhs);
+}
+
+
+/**
+ * \fn cross(const Vector<T1, 3>& lhs, const Vector<T2, 3>& rhs)
+ * \brief Compute the cross/outer product
+ * \ingroup _binary_function
+ * \note working only for vectors of size = 3
+ * \todo Implement vector outer product as ET and MT, returning a XprVector
+ */
+template<class T1, class T2>
+inline
+Vector<typename PromoteTraits<T1, T2>::value_type, 3>
+cross(const Vector<T1, 3>& lhs, const Vector<T2, 3>& rhs) {
+  typedef typename PromoteTraits<T1, T2>::value_type	value_type;
+  return Vector<value_type, 3>(lhs(1)*rhs(2) - rhs(1)*lhs(2),
+			       rhs(0)*lhs(2) - lhs(0)*rhs(2),
+			       lhs(0)*rhs(1) - rhs(0)*lhs(1));
+}
+
+
+/**
+ * \fn norm1(const Vector<T, Sz>& v)
+ * \brief The \f$l_1\f$ norm of a vector v.
+ * \ingroup _unary_function
+ * The norm of any vector is just the square root of the dot product of
+ * a vector with itself, or
+ *
+ * \f[
+ * |Vector<T, Sz> v| = |v| = \sum_{i=0}^{Sz-1}\,|v[i]|
+ * \f]
+ */
+template<class T, std::size_t Sz>
+inline
+typename NumericTraits<T>::sum_type
+norm1(const Vector<T, Sz>& v) {
+  return sum(abs(v));
+}
+
+
+/**
+ * \fn norm2(const Vector<T, Sz>& v)
+ * \brief The euklidian norm (or \f$l_2\f$ norm) of a vector v.
+ * \ingroup _unary_function
+ * The norm of any vector is just the square root of the dot product of
+ * a vector with itself, or
+ *
+ * \f[
+ * |Vector<T, Sz> v| = |v| = \sqrt{ \sum_{i=0}^{Sz-1}\,v[i]^2 }
+ * \f]
+ *
+ * \note The internal cast for Vector<int> avoids warnings on sqrt.
+ */
+template<class T, std::size_t Sz>
+inline
+typename NumericTraits<T>::sum_type
+norm2(const Vector<T, Sz>& v) {
+  return static_cast<T>( std::sqrt(static_cast<typename NumericTraits<T>::float_type>(dot(v, v))) );
+}
+
+
+/**
+ * \fn normalize(const Vector<T, Sz>& v)
+ * \brief Normalize the given vector.
+ * \ingroup _unary_function
+ * \sa norm2
+ *
+ * using the equation:
+ * \f[
+ * \frac{Vector<T, Sz> v}{\sqrt{ \sum_{i=0}^{Sz-1}\,v[i]^2 }}
+ * \f]
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_div<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral< T >
+  >,
+  Sz
+>
+normalize(const Vector<T, Sz>& v) {
+  typedef XprBinOp<
+    Fcnl_div<T, T>,
+    VectorConstReference<T, Sz>,
+    XprLiteral< T >
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+    expr_type(v.const_ref(), XprLiteral< T >(norm2(v))));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * min/max unary functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn maximum(const XprVector<E, Sz>& e)
+ * \brief Find the maximum of a vector expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Sz>
+inline
+Extremum<typename E::value_type, std::size_t, vector_tag>
+maximum(const XprVector<E, Sz>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						m_max(e(0));
+  std::size_t 						m_idx(0);
+
+  // this loop is faster than meta templates!
+  for(std::size_t i = 1; i != Sz; ++i) {
+    if(e(i) > m_max) {
+      m_max = e(i);
+      m_idx = i;
+    }
+  }
+
+  return Extremum<value_type, std::size_t, vector_tag>(m_max, m_idx);
+}
+
+
+/**
+ * \fn maximum(const Vector<T, Sz>& v)
+ * \brief Find the maximum of a vector
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Sz>
+inline
+Extremum<T, std::size_t, vector_tag>
+maximum(const Vector<T, Sz>& v) { return maximum(v.as_expr()); }
+
+
+/**
+ * \fn minimum(const XprVector<E, Sz>& e)
+ * \brief Find the minimum of a vector expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Sz>
+inline
+Extremum<typename E::value_type, std::size_t, vector_tag>
+minimum(const XprVector<E, Sz>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						m_min(e(0));
+  std::size_t 						m_idx(0);
+
+  // this loop is faster than meta templates!
+  for(std::size_t i = 1; i != Sz; ++i) {
+    if(e(i) < m_min) {
+      m_min = e(i);
+      m_idx = i;
+    }
+  }
+
+  return Extremum<value_type, std::size_t, vector_tag>(m_min, m_idx);
+}
+
+
+/**
+ * \fn minimum(const Vector<T, Sz>& v)
+ * \brief Find the minimum of a vector
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Sz>
+inline
+Extremum<T, std::size_t, vector_tag>
+minimum(const Vector<T, Sz>& v) { return minimum(v.as_expr()); }
+
+
+/**
+ * \fn max(const XprVector<E, Sz>& e)
+ * \brief Find the maximum of a vector expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Sz>
+inline
+typename E::value_type
+max(const XprVector<E, Sz>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						m_max(e(0));
+
+  // this loop is faster than meta templates!
+  for(std::size_t i = 1; i != Sz; ++i)
+    if(e(i) > m_max)
+      m_max = e(i);
+
+  return m_max;
+}
+
+
+/**
+ * \fn max(const Vector<T, Sz>& v)
+ * \brief Find the maximum of a vector
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Sz>
+inline
+T max(const Vector<T, Sz>& v) {
+  typedef T			 			value_type;
+  typedef typename Vector<T, Sz>::const_iterator	const_iterator;
+
+  const_iterator					iter(v.begin());
+  const_iterator					last(v.end());
+  value_type 						temp(*iter);
+
+  for( ; iter != last; ++iter)
+    if(*iter > temp)
+      temp = *iter;
+
+  return temp;
+}
+
+
+/**
+ * \fn min(const XprVector<E, Sz>& e)
+ * \brief Find the minimum of a vector expression
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Sz>
+inline
+typename E::value_type
+min(const XprVector<E, Sz>& e) {
+  typedef typename E::value_type 			value_type;
+
+  value_type 						m_min(e(0));
+
+  // this loop is faster than meta templates!
+  for(std::size_t i = 1; i != Sz; ++i)
+    if(e(i) < m_min)
+      m_min = e(i);
+
+  return m_min;
+}
+
+
+/**
+ * \fn min(const Vector<T, Sz>& v)
+ * \brief Find the minimum of a vector
+ * \ingroup _unary_function
+ */
+template<class T, std::size_t Sz>
+inline
+T min(const Vector<T, Sz>& v) {
+  typedef T			 			value_type;
+  typedef typename Vector<T, Sz>::const_iterator	const_iterator;
+
+  const_iterator					iter(v.begin());
+  const_iterator					last(v.end());
+  value_type 						temp(*iter);
+
+  for( ; iter != last; ++iter)
+    if(*iter < temp)
+      temp = *iter;
+
+  return temp;
+}
+
+
+/**
+ * \fn cvector_ref(const T* mem)
+ * \brief Creates an expression wrapper for a C like vector arrays.
+ * \ingroup _unary_function
+ *
+ * This is like creating a vector of external data, as described
+ * at \ref construct. With this function you wrap an expression
+ * around a C style vector array and you can operate directly with it
+ * as usual.
+ *
+ * \par Example:
+ * \code
+ * static float vertices[N][3] = {
+ *   {-1,  0,  1}, { 1,  0,  1}, ...
+ * };
+ * ...
+ * typedef Vector<float, 3>			vector_type;
+ * ...
+ * vector_type V( cross(cvector_ref<float, 3>(&vertices[0][0]),
+ *                      cvector_ref<float, 3>(&vertices[1][0])) );
+ * \endcode
+ *
+ * \since release 1.6.0
+ */
+template<class T, std::size_t Sz>
+inline
+XprVector<
+  VectorConstReference<T, Sz>,
+  Sz
+>
+cvector_ref(const T* mem) {
+  typedef VectorConstReference<T, Sz>		expr_type;
+
+  return XprVector<expr_type, Sz>(expr_type(mem));
+}
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorImpl.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,210 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorImpl.h,v 1.31 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_IMPL_H
+#define TVMET_VECTOR_IMPL_H
+
+#include <iomanip>			// setw
+
+#include <tvmet/Functional.h>
+#include <tvmet/Io.h>
+
+
+namespace tvmet {
+
+
+/*
+ * member operators for i/o
+ */
+template<class T, std::size_t Sz>
+std::ostream& Vector<T, Sz>::print_xpr(std::ostream& os, std::size_t l) const
+{
+  os << IndentLevel(l++) << "Vector[" << ops << "]<"
+     << typeid(T).name() << ", " << Size << ">,"
+     << IndentLevel(--l)
+     << std::endl;
+
+  return os;
+}
+
+
+template<class T, std::size_t Sz>
+std::ostream& Vector<T, Sz>::print_on(std::ostream& os) const
+{
+  enum {
+    complex_type = NumericTraits<value_type>::is_complex
+  };
+
+  std::streamsize w = IoPrintHelper<Vector>::width(dispatch<complex_type>(), *this);
+
+  os << std::setw(0) << "[\n  ";
+  for(std::size_t i = 0; i < (Size - 1); ++i) {
+    os << std::setw(w) << m_data[i] << ", ";
+  }
+  os << std::setw(w) << m_data[Size - 1] << "\n]";
+
+  return os;
+}
+
+
+/*
+ * member operators with scalars, per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class T, std::size_t Sz>					\
+inline									\
+Vector<T, Sz>& Vector<T, Sz>::operator OP (value_type rhs) {		\
+  typedef XprLiteral<value_type> 			expr_type;	\
+  this->M_##NAME(XprVector<expr_type, Size>(expr_type(rhs)));		\
+  return *this;								\
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq, +=)
+TVMET_IMPLEMENT_MACRO(sub_eq, -=)
+TVMET_IMPLEMENT_MACRO(mul_eq, *=)
+TVMET_IMPLEMENT_MACRO(div_eq, /=)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class T, std::size_t Sz>					\
+inline									\
+Vector<T, Sz>& Vector<T, Sz>::operator OP (std::size_t rhs) {		\
+  typedef XprLiteral<value_type> 			expr_type;	\
+  this->M_##NAME(XprVector<expr_type, Size>(expr_type(rhs)));		\
+  return *this;								\
+}
+
+TVMET_IMPLEMENT_MACRO(mod_eq, %=)
+TVMET_IMPLEMENT_MACRO(xor_eq,^=)
+TVMET_IMPLEMENT_MACRO(and_eq, &=)
+TVMET_IMPLEMENT_MACRO(or_eq, |=)
+TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
+TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * member functions (operators) with vectors, for use with +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)									\
+template<class T1, std::size_t Sz>									\
+template <class T2>											\
+inline Vector<T1, Sz>&											\
+Vector<T1, Sz>::M_##NAME (const Vector<T2, Size>& rhs) {						\
+  this->M_##NAME( XprVector<typename Vector<T2, Size>::ConstReference, Size>(rhs.const_ref()) );	\
+  return *this;												\
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+TVMET_IMPLEMENT_MACRO(mod_eq)
+TVMET_IMPLEMENT_MACRO(xor_eq)
+TVMET_IMPLEMENT_MACRO(and_eq)
+TVMET_IMPLEMENT_MACRO(or_eq)
+TVMET_IMPLEMENT_MACRO(shl_eq)
+TVMET_IMPLEMENT_MACRO(shr_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * member functions (operators) with expressions, for use width +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					   \
+template<class T, std::size_t Sz>					   \
+template <class E>							   \
+inline 									   \
+Vector<T, Sz>&								   \
+Vector<T, Sz>::M_##NAME (const XprVector<E, Size>& rhs) {		   \
+  rhs.assign_to(*this, Fcnl_##NAME<value_type, typename E::value_type>()); \
+  return *this;								   \
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+TVMET_IMPLEMENT_MACRO(mod_eq)
+TVMET_IMPLEMENT_MACRO(xor_eq)
+TVMET_IMPLEMENT_MACRO(and_eq)
+TVMET_IMPLEMENT_MACRO(or_eq)
+TVMET_IMPLEMENT_MACRO(shl_eq)
+TVMET_IMPLEMENT_MACRO(shr_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * aliased member functions (operators) with vectors,
+ * for use with +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)								     \
+template<class T1, std::size_t Sz>								     \
+template <class T2>										     \
+inline 												     \
+Vector<T1, Sz>&											     \
+Vector<T1, Sz>::alias_##NAME (const Vector<T2, Size>& rhs) {					     \
+  this->alias_##NAME( XprVector<typename Vector<T2, Size>::ConstReference, Size>(rhs.const_ref()) ); \
+  return *this;											     \
+}
+
+TVMET_IMPLEMENT_MACRO(assign)
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * aliased member functions (operators) with expressions,
+ * for use width +=,-= ... <<=
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)						      \
+template<class T, std::size_t Sz>						      \
+template <class E>								      \
+inline 										      \
+Vector<T, Sz>&									      \
+Vector<T, Sz>::alias_##NAME (const XprVector<E, Size>& rhs) {			      \
+  typedef Vector<T, Sz>					temp_type;		      \
+  temp_type(rhs).assign_to(*this, Fcnl_##NAME<value_type, typename E::value_type>()); \
+  return *this;									      \
+}
+
+TVMET_IMPLEMENT_MACRO(assign)
+TVMET_IMPLEMENT_MACRO(add_eq)
+TVMET_IMPLEMENT_MACRO(sub_eq)
+TVMET_IMPLEMENT_MACRO(mul_eq)
+TVMET_IMPLEMENT_MACRO(div_eq)
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_IMPL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorOperators.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,1055 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorOperators.h,v 1.18 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_OPERATORS_H
+#define TVMET_VECTOR_OPERATORS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+template<class T, std::size_t Sz>
+inline
+std::ostream& operator<<(std::ostream& os,
+			 const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Member operators (arithmetic and bit ops)
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * update_operator(Vector<T1, Sz>,  Vector<T2, Sz>)
+ * update_operator(Vector<T1, Sz>,  XprVector<E, Sz>)
+ * Note: per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class T1, class T2, std::size_t Sz>				\
+Vector<T1, Sz>&								\
+operator OP (Vector<T1, Sz>& lhs,					\
+	     const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class T, class E, std::size_t Sz>				\
+Vector<T, Sz>&								\
+operator OP (Vector<T, Sz>& lhs,					\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add_eq, +=)		// per se element wise
+TVMET_DECLARE_MACRO(sub_eq, -=)		// per se element wise
+TVMET_DECLARE_MACRO(mul_eq, *=)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(div_eq, /=)		// not defined for vectors
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod_eq, %=)
+  TVMET_DECLARE_MACRO(xor_eq, ^=)
+  TVMET_DECLARE_MACRO(and_eq, &=)
+  TVMET_DECLARE_MACRO(or_eq, |=)
+  TVMET_DECLARE_MACRO(shl_eq, <<=)
+  TVMET_DECLARE_MACRO(shr_eq, >>=)
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Vector<T1, Sz>, Vector<T2, Sz>)
+ * operator(Vector<T1, Sz>, XprVector<E, Sz>)
+ * operator(XprVector<E, Sz>, Vector<T1, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class T1, class T2, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T1, Sz>& lhs, 				\
+	     const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, class T, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs,				\
+	     const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+									\
+template<class E, class T, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, 					\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)		// per se element wise
+TVMET_DECLARE_MACRO(sub, -)		// per se element wise
+TVMET_DECLARE_MACRO(mul, *)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(div, /)		// not defined for vectors
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, POD)			\
+template<class T, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< T, POD >,					\
+    VectorConstReference<T, Sz>,				\
+    XprLiteral< POD >						\
+  >,								\
+  Sz								\
+>								\
+operator OP (const Vector<T, Sz>& lhs, 				\
+	     POD rhs) TVMET_CXX_ALWAYS_INLINE;			\
+								\
+template<class T, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< POD, T>,					\
+    XprLiteral< POD >,						\
+    VectorConstReference<T, Sz>					\
+  >,								\
+  Sz								\
+>								\
+operator OP (POD lhs, 						\
+	     const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +, int)
+TVMET_DECLARE_MACRO(sub, -, int)
+TVMET_DECLARE_MACRO(mul, *, int)
+TVMET_DECLARE_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, +, long long int)
+TVMET_DECLARE_MACRO(sub, -, long long int)
+TVMET_DECLARE_MACRO(mul, *, long long int)
+TVMET_DECLARE_MACRO(div, /, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, +, float)
+TVMET_DECLARE_MACRO(sub, -, float)
+TVMET_DECLARE_MACRO(mul, *, float)
+TVMET_DECLARE_MACRO(div, /, float)
+
+TVMET_DECLARE_MACRO(add, +, double)
+TVMET_DECLARE_MACRO(sub, -, double)
+TVMET_DECLARE_MACRO(mul, *, double)
+TVMET_DECLARE_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, +, long double)
+TVMET_DECLARE_MACRO(sub, -, long double)
+TVMET_DECLARE_MACRO(mul, *, long double)
+TVMET_DECLARE_MACRO(div, /, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class T, std::size_t Sz>						\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    VectorConstReference< std::complex<T>, Sz>,					\
+    XprLiteral< std::complex<T> >						\
+  >,										\
+  Sz										\
+>										\
+operator OP (const Vector<std::complex<T>, Sz>& lhs, 				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class T, std::size_t Sz>						\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    XprLiteral< std::complex<T> >,						\
+    VectorConstReference< std::complex<T>, Sz>					\
+  >,										\
+  Sz										\
+>										\
+operator OP (const std::complex<T>& lhs, 					\
+	     const Vector< std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)		// per se element wise
+TVMET_DECLARE_MACRO(sub, -)		// per se element wise
+TVMET_DECLARE_MACRO(mul, *)		// per se element wise
+TVMET_DECLARE_MACRO(div, /)		// per se element wise
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Vector<T1, Sz>, Vector<T2, Sz>)
+ * operator(XprVector<E, Sz>, Vector<T, Sz>)
+ * operator(Vector<T, Sz>, XprVector<E, Sz>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class T1, class T2, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T1, Sz>& lhs, 				\
+	     const Vector<T2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, class T, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, 				\
+	     const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+									\
+template<class E, class T, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, 					\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %)
+  TVMET_DECLARE_MACRO(bitxor, ^)
+  TVMET_DECLARE_MACRO(bitand, &)
+  TVMET_DECLARE_MACRO(bitor, |)
+  TVMET_DECLARE_MACRO(shl, <<)
+  TVMET_DECLARE_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class T, std::size_t Sz>						\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    VectorConstReference< std::complex<T>, Sz>,					\
+    XprLiteral< std::complex<T> >						\
+  >,										\
+  Sz										\
+>										\
+operator OP (const Vector<std::complex<T>, Sz>& lhs, 				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class T, std::size_t Sz>						\
+XprVector<									\
+  XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,				\
+    XprLiteral< std::complex<T> >,						\
+    VectorConstReference< std::complex<T>, Sz>					\
+  >,										\
+  Sz										\
+>										\
+operator OP (const std::complex<T>& lhs, 					\
+	     const Vector< std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations are per se element_wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, TP)				\
+template<class T, std::size_t Sz>					\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< T, TP >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, TP rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class T, std::size_t Sz>					\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< TP, T>,						\
+    XprLiteral< TP >,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (TP lhs, const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, int)
+  TVMET_DECLARE_MACRO(bitxor, ^, int)
+  TVMET_DECLARE_MACRO(bitand, &, int)
+  TVMET_DECLARE_MACRO(bitor, |, int)
+  TVMET_DECLARE_MACRO(shl, <<, int)
+  TVMET_DECLARE_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, int)
+TVMET_DECLARE_MACRO(less, <, int)
+TVMET_DECLARE_MACRO(greater_eq, >=, int)
+TVMET_DECLARE_MACRO(less_eq, <=, int)
+TVMET_DECLARE_MACRO(eq, ==, int)
+TVMET_DECLARE_MACRO(not_eq, !=, int)
+TVMET_DECLARE_MACRO(and, &&, int)
+TVMET_DECLARE_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, long long int)
+  TVMET_DECLARE_MACRO(bitxor, ^, long long int)
+  TVMET_DECLARE_MACRO(bitand, &, long long int)
+  TVMET_DECLARE_MACRO(bitor, |, long long int)
+  TVMET_DECLARE_MACRO(shl, <<, long long int)
+  TVMET_DECLARE_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long long int)
+TVMET_DECLARE_MACRO(less, <, long long int)
+TVMET_DECLARE_MACRO(greater_eq, >=, long long int)
+TVMET_DECLARE_MACRO(less_eq, <=, long long int)
+TVMET_DECLARE_MACRO(eq, ==, long long int)
+TVMET_DECLARE_MACRO(not_eq, !=, long long int)
+TVMET_DECLARE_MACRO(and, &&, long long int)
+TVMET_DECLARE_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, float)
+TVMET_DECLARE_MACRO(less, <, float)
+TVMET_DECLARE_MACRO(greater_eq, >=, float)
+TVMET_DECLARE_MACRO(less_eq, <=, float)
+TVMET_DECLARE_MACRO(eq, ==, float)
+TVMET_DECLARE_MACRO(not_eq, !=, float)
+TVMET_DECLARE_MACRO(and, &&, float)
+TVMET_DECLARE_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, double)
+TVMET_DECLARE_MACRO(less, <, double)
+TVMET_DECLARE_MACRO(greater_eq, >=, double)
+TVMET_DECLARE_MACRO(less_eq, <=, double)
+TVMET_DECLARE_MACRO(eq, ==, double)
+TVMET_DECLARE_MACRO(not_eq, !=, double)
+TVMET_DECLARE_MACRO(and, &&, double)
+TVMET_DECLARE_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long double)
+TVMET_DECLARE_MACRO(less, <, long double)
+TVMET_DECLARE_MACRO(greater_eq, >=, long double)
+TVMET_DECLARE_MACRO(less_eq, <=, long double)
+TVMET_DECLARE_MACRO(eq, ==, long double)
+TVMET_DECLARE_MACRO(not_eq, !=, long double)
+TVMET_DECLARE_MACRO(and, &&, long double)
+TVMET_DECLARE_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(Vector<T, Sz>)
+ * Note: per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)				\
+template <class T, std::size_t Sz>				\
+XprVector<							\
+  XprUnOp<							\
+    Fcnl_##NAME<T>,						\
+    VectorConstReference<T, Sz>					\
+  >,								\
+  Sz								\
+>								\
+operator OP (const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(not, !)
+TVMET_DECLARE_MACRO(compl, ~)
+TVMET_DECLARE_MACRO(neg, -)
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/**
+ * \fn operator<<(std::ostream& os, const Vector<T, Sz>& rhs)
+ * \brief Overload operator for i/o
+ * \ingroup _binary_operator
+ */
+template<class T, std::size_t Sz>
+inline
+std::ostream& operator<<(std::ostream& os, const Vector<T, Sz>& rhs) {
+  return rhs.print_on(os);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Member operators (arithmetic and bit ops)
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * update_operator(Vector<T1, Sz>,  Vector<T2, Sz>)
+ * update_operator(Vector<T1, Sz>,  XprVector<E, Sz>)
+ * Note: per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				\
+template<class T1, class T2, std::size_t Sz>			\
+inline Vector<T1, Sz>&						\
+operator OP (Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {	\
+  return lhs.M_##NAME(rhs);					\
+}								\
+								\
+template<class T, class E, std::size_t Sz>			\
+inline Vector<T, Sz>&						\
+operator OP (Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {	\
+  return lhs.M_##NAME(rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add_eq, +=)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub_eq, -=)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul_eq, *=)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(div_eq, /=)		// not defined for vectors
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod_eq, %=)
+  TVMET_IMPLEMENT_MACRO(xor_eq, ^=)
+  TVMET_IMPLEMENT_MACRO(and_eq, &=)
+  TVMET_IMPLEMENT_MACRO(or_eq, |=)
+  TVMET_IMPLEMENT_MACRO(shl_eq, <<=)
+  TVMET_IMPLEMENT_MACRO(shr_eq, >>=)
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Vector<T1, Sz>, Vector<T2, Sz>)
+ * operator(Vector<T1, Sz>, XprVector<E, Sz>)
+ * operator(XprVector<E, Sz>, Vector<T1, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class T1, class T2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {	\
+  return NAME (lhs, rhs);						\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) {	\
+  return NAME (lhs, rhs);						\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {	\
+  return NAME (lhs, rhs);						\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul, *)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(div, /)		// not defined for vectors
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, POD)		\
+template<class T, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME< T, POD >,				\
+    VectorConstReference<T, Sz>,			\
+    XprLiteral< POD >					\
+  >,							\
+  Sz							\
+>							\
+operator OP (const Vector<T, Sz>& lhs, POD rhs) {	\
+  return NAME (lhs, rhs);				\
+}							\
+							\
+template<class T, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME< POD, T>,				\
+    XprLiteral< POD >,					\
+    VectorConstReference<T, Sz>				\
+  >,							\
+  Sz							\
+>							\
+operator OP (POD lhs, const Vector<T, Sz>& rhs) {	\
+  return NAME (lhs, rhs);				\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +, int)
+TVMET_IMPLEMENT_MACRO(sub, -, int)
+TVMET_IMPLEMENT_MACRO(mul, *, int)
+TVMET_IMPLEMENT_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, +, long long int)
+TVMET_IMPLEMENT_MACRO(sub, -, long long int)
+TVMET_IMPLEMENT_MACRO(mul, *, long long int)
+TVMET_IMPLEMENT_MACRO(div, /, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, +, float)
+TVMET_IMPLEMENT_MACRO(sub, -, float)
+TVMET_IMPLEMENT_MACRO(mul, *, float)
+TVMET_IMPLEMENT_MACRO(div, /, float)
+
+TVMET_IMPLEMENT_MACRO(add, +, double)
+TVMET_IMPLEMENT_MACRO(sub, -, double)
+TVMET_IMPLEMENT_MACRO(mul, *, double)
+TVMET_IMPLEMENT_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, +, long double)
+TVMET_IMPLEMENT_MACRO(sub, -, long double)
+TVMET_IMPLEMENT_MACRO(mul, *, long double)
+TVMET_IMPLEMENT_MACRO(div, /, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)			\
+template<class T, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,	\
+    VectorConstReference< std::complex<T>, Sz>,		\
+    XprLiteral< std::complex<T> >			\
+  >,							\
+  Sz							\
+>							\
+operator OP (const Vector<std::complex<T>, Sz>& lhs, 	\
+	     const std::complex<T>& rhs) {		\
+  return NAME (lhs, rhs);				\
+}							\
+							\
+template<class T, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,	\
+    XprLiteral< std::complex<T> >,			\
+    VectorConstReference< std::complex<T>, Sz>		\
+  >,							\
+  Sz							\
+>							\
+operator OP (const std::complex<T>& lhs, 		\
+	     const Vector< std::complex<T>, Sz>& rhs) {	\
+  return NAME (lhs, rhs);				\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul, *)		// per se element wise
+TVMET_IMPLEMENT_MACRO(div, /)		// per se element wise
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(Vector<T1, Sz>, Vector<T2, Sz>)
+ * operator(XprVector<E, Sz>, Vector<T, Sz>)
+ * operator(Vector<T, Sz>, XprVector<E, Sz>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class T1, class T2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T1, Sz>& lhs, const Vector<T2, Sz>& rhs) {	\
+  typedef XprBinOp <							\
+    Fcnl_##NAME<T1, T2>,						\
+    VectorConstReference<T1, Sz>,					\
+    VectorConstReference<T2, Sz>					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs.const_ref()));			\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, T>,				\
+    XprVector<E, Sz>,							\
+    VectorConstReference<T, Sz>						\
+  > 							 expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, rhs.const_ref()));					\
+}									\
+									\
+template<class E, class T, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, typename E::value_type>,				\
+    VectorConstReference<T, Sz>,					\
+    XprVector<E, Sz>							\
+  > 						 	expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), rhs));					\
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^)
+  TVMET_IMPLEMENT_MACRO(bitand, &)
+  TVMET_IMPLEMENT_MACRO(bitor, |)
+  TVMET_IMPLEMENT_MACRO(shl, <<)
+  TVMET_IMPLEMENT_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)							\
+template<class T, std::size_t Sz>							\
+inline											\
+XprVector<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    VectorConstReference< std::complex<T>, Sz>,						\
+    XprLiteral< std::complex<T> >							\
+  >,											\
+  Sz											\
+>											\
+operator OP (const Vector<std::complex<T>, Sz>& lhs, const std::complex<T>& rhs) {	\
+  typedef XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    VectorConstReference< std::complex<T>, Sz>,						\
+    XprLiteral< std::complex<T> >							\
+  >							expr_type;			\
+  return XprVector<expr_type, Sz>(							\
+    expr_type(lhs.const_ref(), XprLiteral< std::complex<T> >(rhs)));			\
+}											\
+											\
+template<class T, std::size_t Sz>							\
+inline											\
+XprVector<										\
+  XprBinOp<										\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    XprLiteral< std::complex<T> >,							\
+    VectorConstReference< std::complex<T>, Sz>						\
+  >,											\
+  Sz											\
+>											\
+operator OP (const std::complex<T>& lhs, const Vector< std::complex<T>, Sz>& rhs) {	\
+  typedef XprBinOp<									\
+    Fcnl_##NAME< std::complex<T>, std::complex<T> >,					\
+    XprLiteral< std::complex<T> >,							\
+    VectorConstReference< std::complex<T>, Sz>						\
+  >							expr_type;			\
+  return XprVector<expr_type, Sz>(							\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs.const_ref()));			\
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations are per se element_wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, TP)				\
+template<class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< T, TP >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& lhs, TP rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<T, TP >,						\
+    VectorConstReference<T, Sz>,					\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs.const_ref(), XprLiteral< TP >(rhs)));			\
+}									\
+									\
+template<class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< TP, T>,						\
+    XprLiteral< TP >,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (TP lhs, const Vector<T, Sz>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< TP, T>,						\
+    XprLiteral< TP >,							\
+    VectorConstReference<T, Sz>						\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< TP >(lhs), rhs.const_ref()));			\
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, int)
+TVMET_IMPLEMENT_MACRO(less, <, int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, int)
+TVMET_IMPLEMENT_MACRO(eq, ==, int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, int)
+TVMET_IMPLEMENT_MACRO(and, &&, int)
+TVMET_IMPLEMENT_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, long long int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, long long int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, long long int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, long long int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, long long int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long long int)
+TVMET_IMPLEMENT_MACRO(less, <, long long int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long long int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long long int)
+TVMET_IMPLEMENT_MACRO(eq, ==, long long int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long long int)
+TVMET_IMPLEMENT_MACRO(and, &&, long long int)
+TVMET_IMPLEMENT_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, float)
+TVMET_IMPLEMENT_MACRO(less, <, float)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, float)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, float)
+TVMET_IMPLEMENT_MACRO(eq, ==, float)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, float)
+TVMET_IMPLEMENT_MACRO(and, &&, float)
+TVMET_IMPLEMENT_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, double)
+TVMET_IMPLEMENT_MACRO(less, <, double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, double)
+TVMET_IMPLEMENT_MACRO(eq, ==, double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, double)
+TVMET_IMPLEMENT_MACRO(and, &&, double)
+TVMET_IMPLEMENT_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long double)
+TVMET_IMPLEMENT_MACRO(less, <, long double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long double)
+TVMET_IMPLEMENT_MACRO(eq, ==, long double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long double)
+TVMET_IMPLEMENT_MACRO(and, &&, long double)
+TVMET_IMPLEMENT_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(Vector<T, Sz>)
+ * Note: per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class T, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprUnOp<								\
+    Fcnl_##NAME<T>,							\
+    VectorConstReference<T, Sz>						\
+  >,									\
+  Sz									\
+>									\
+operator OP (const Vector<T, Sz>& rhs) {				\
+  typedef XprUnOp<							\
+    Fcnl_##NAME<T>,							\
+    VectorConstReference<T, Sz>						\
+  >  							 expr_type;	\
+  return XprVector<expr_type, Sz>(expr_type(rhs.const_ref()));		\
+}
+
+TVMET_IMPLEMENT_MACRO(not, !)
+TVMET_IMPLEMENT_MACRO(compl, ~)
+TVMET_IMPLEMENT_MACRO(neg, -)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_OPERATORS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VectorUnaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,220 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorUnaryFunctions.h,v 1.13 2007-06-23 15:58:58 opetzold Exp $
+ */
+
+#ifndef TVMET_VECTOR_UNARY_FUNCTIONS_H
+#define TVMET_VECTOR_UNARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * unary_function(Vector<T, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)            \
+template<class T, std::size_t Sz>            \
+XprVector<                        \
+  XprUnOp<                        \
+    Fcnl_##NAME<T>,                    \
+    VectorConstReference<T, Sz>                \
+  >,                            \
+  Sz                            \
+>                            \
+NAME(const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(abs)
+TVMET_DECLARE_MACRO(cbrt)
+TVMET_DECLARE_MACRO(ceil)
+TVMET_DECLARE_MACRO(floor)
+TVMET_DECLARE_MACRO(rint)
+TVMET_DECLARE_MACRO(sin)
+TVMET_DECLARE_MACRO(cos)
+TVMET_DECLARE_MACRO(tan)
+TVMET_DECLARE_MACRO(sinh)
+TVMET_DECLARE_MACRO(cosh)
+TVMET_DECLARE_MACRO(tanh)
+TVMET_DECLARE_MACRO(asin)
+TVMET_DECLARE_MACRO(acos)
+TVMET_DECLARE_MACRO(atan)
+TVMET_DECLARE_MACRO(exp)
+TVMET_DECLARE_MACRO(log)
+TVMET_DECLARE_MACRO(log10)
+TVMET_DECLARE_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_DECLARE_MACRO(asinh)
+TVMET_DECLARE_MACRO(acosh)
+TVMET_DECLARE_MACRO(atanh)
+TVMET_DECLARE_MACRO(expm1)
+TVMET_DECLARE_MACRO(log1p)
+TVMET_DECLARE_MACRO(erf)
+TVMET_DECLARE_MACRO(erfc)
+TVMET_DECLARE_MACRO(j0)
+TVMET_DECLARE_MACRO(j1)
+TVMET_DECLARE_MACRO(y0)
+TVMET_DECLARE_MACRO(y1)
+TVMET_DECLARE_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_DECLARE_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * unary_function(Vector<std::complex<T>, Sz>)
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+#define TVMET_DECLARE_MACRO(NAME)                    \
+template<class T, std::size_t Sz>                    \
+XprVector<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME< std::complex<T> >,                    \
+    VectorConstReference<std::complex<T>, Sz>                \
+  >,                                    \
+  Sz                                    \
+>                                    \
+NAME(const Vector<std::complex<T>, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(real)
+TVMET_DECLARE_MACRO(imag)
+TVMET_DECLARE_MACRO(arg)
+TVMET_DECLARE_MACRO(norm)
+TVMET_DECLARE_MACRO(conj)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * unary_function(Vector<T, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)                    \
+template<class T, std::size_t Sz>                    \
+inline                                    \
+XprVector<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME<T>,                            \
+    VectorConstReference<T, Sz>                        \
+  >,                                    \
+  Sz                                    \
+>                                    \
+NAME(const Vector<T, Sz>& rhs) {                    \
+  typedef XprUnOp<                            \
+      Fcnl_##NAME<T>,                            \
+      VectorConstReference<T, Sz>                    \
+    >                             expr_type;    \
+    return XprVector<expr_type, Sz>(expr_type(rhs.const_ref()));    \
+}
+
+TVMET_IMPLEMENT_MACRO(abs)
+TVMET_IMPLEMENT_MACRO(cbrt)
+TVMET_IMPLEMENT_MACRO(ceil)
+TVMET_IMPLEMENT_MACRO(floor)
+TVMET_IMPLEMENT_MACRO(rint)
+TVMET_IMPLEMENT_MACRO(sin)
+TVMET_IMPLEMENT_MACRO(cos)
+TVMET_IMPLEMENT_MACRO(tan)
+TVMET_IMPLEMENT_MACRO(sinh)
+TVMET_IMPLEMENT_MACRO(cosh)
+TVMET_IMPLEMENT_MACRO(tanh)
+TVMET_IMPLEMENT_MACRO(asin)
+TVMET_IMPLEMENT_MACRO(acos)
+TVMET_IMPLEMENT_MACRO(atan)
+TVMET_IMPLEMENT_MACRO(exp)
+TVMET_IMPLEMENT_MACRO(log)
+TVMET_IMPLEMENT_MACRO(log10)
+TVMET_IMPLEMENT_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_IMPLEMENT_MACRO(asinh)
+TVMET_IMPLEMENT_MACRO(acosh)
+TVMET_IMPLEMENT_MACRO(atanh)
+TVMET_IMPLEMENT_MACRO(expm1)
+TVMET_IMPLEMENT_MACRO(log1p)
+TVMET_IMPLEMENT_MACRO(erf)
+TVMET_IMPLEMENT_MACRO(erfc)
+TVMET_IMPLEMENT_MACRO(j0)
+TVMET_IMPLEMENT_MACRO(j1)
+TVMET_IMPLEMENT_MACRO(y0)
+TVMET_IMPLEMENT_MACRO(y1)
+TVMET_IMPLEMENT_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_IMPLEMENT_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * unary_function(Vector<std::complex<T>, Sz>)
+ */
+#if defined(TVMET_HAVE_COMPLEX)
+#define TVMET_IMPLEMENT_MACRO(NAME)                    \
+template<class T, std::size_t Sz>                    \
+inline                                    \
+XprVector<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME< std::complex<T> >,                    \
+    VectorConstReference<std::complex<T>, Sz>                \
+  >,                                    \
+  Sz                                    \
+>                                    \
+NAME(const Vector<std::complex<T>, Sz>& rhs) {                \
+  typedef XprUnOp<                            \
+      Fcnl_##NAME< std::complex<T> >,                    \
+      VectorConstReference<std::complex<T>, Sz>                \
+    >                             expr_type;    \
+    return XprVector<expr_type, Sz>(expr_type(rhs.const_ref()));    \
+}
+
+TVMET_IMPLEMENT_MACRO(real)
+TVMET_IMPLEMENT_MACRO(imag)
+TVMET_IMPLEMENT_MACRO(arg)
+TVMET_IMPLEMENT_MACRO(norm)
+TVMET_IMPLEMENT_MACRO(conj)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_VECTOR_UNARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,206 @@
+#ifndef _INCLUDE_TVMET_CONFIG_H
+#define _INCLUDE_TVMET_CONFIG_H 1
+ 
+/* include/tvmet/config.h. Generated automatically at end of configure. */
+/* config/config.h.  Generated from config.h.in by configure.  */
+/* config/config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* define if the compiler has complex<T> */
+#ifndef TVMET_HAVE_COMPLEX 
+#define TVMET_HAVE_COMPLEX   
+#endif
+
+/* define if the compiler has complex math functions */
+#ifndef TVMET_HAVE_COMPLEX_MATH1 
+#define TVMET_HAVE_COMPLEX_MATH1   
+#endif
+
+/* define if the compiler has more complex math functions */
+/* #undef TVMET_HAVE_COMPLEX_MATH2 */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifndef TVMET_HAVE_DLFCN_H 
+#define TVMET_HAVE_DLFCN_H  1 
+#endif
+
+/* Define to 1 if you have the `floor' function. */
+#ifndef TVMET_HAVE_FLOOR 
+#define TVMET_HAVE_FLOOR  1 
+#endif
+
+/* Define if the compiler supports IEEE math library */
+#ifndef TVMET_HAVE_IEEE_MATH 
+#define TVMET_HAVE_IEEE_MATH   
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifndef TVMET_HAVE_INTTYPES_H 
+#define TVMET_HAVE_INTTYPES_H  1 
+#endif
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+#ifndef TVMET_HAVE_LIBDL 
+#define TVMET_HAVE_LIBDL  1 
+#endif
+
+/* Define to 1 if the type `long double' works and has more range or precision
+   than `double'. */
+#ifndef TVMET_HAVE_LONG_DOUBLE 
+#define TVMET_HAVE_LONG_DOUBLE  1 
+#endif
+
+/* Define to 1 if the type `long double' works and has more range or precision
+   than `double'. */
+#ifndef TVMET_HAVE_LONG_DOUBLE_WIDER 
+#define TVMET_HAVE_LONG_DOUBLE_WIDER  1 
+#endif
+
+/* Define if the compiler supports the long_long type */
+#ifndef TVMET_HAVE_LONG_LONG 
+#define TVMET_HAVE_LONG_LONG   
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef TVMET_HAVE_MEMORY_H 
+#define TVMET_HAVE_MEMORY_H  1 
+#endif
+
+/* Define if the compiler supports the mutable keyword */
+#ifndef TVMET_HAVE_MUTABLE 
+#define TVMET_HAVE_MUTABLE   
+#endif
+
+/* Define if the compiler implements namespaces */
+#ifndef TVMET_HAVE_NAMESPACES 
+#define TVMET_HAVE_NAMESPACES   
+#endif
+
+/* Define if the compiler supports partial specialization */
+#ifndef TVMET_HAVE_PARTIAL_SPECIALIZATION 
+#define TVMET_HAVE_PARTIAL_SPECIALIZATION   
+#endif
+
+/* Define to 1 if you have the `pow' function. */
+#ifndef TVMET_HAVE_POW 
+#define TVMET_HAVE_POW  1 
+#endif
+
+/* Define to 1 if you have the `rint' function. */
+#ifndef TVMET_HAVE_RINT 
+#define TVMET_HAVE_RINT  1 
+#endif
+
+/* Define to 1 if you have the `sqrt' function. */
+#ifndef TVMET_HAVE_SQRT 
+#define TVMET_HAVE_SQRT  1 
+#endif
+
+/* Define to 1 if stdbool.h conforms to C99. */
+#ifndef TVMET_HAVE_STDBOOL_H 
+#define TVMET_HAVE_STDBOOL_H  1 
+#endif
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#ifndef TVMET_HAVE_STDINT_H 
+#define TVMET_HAVE_STDINT_H  1 
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef TVMET_HAVE_STDLIB_H 
+#define TVMET_HAVE_STDLIB_H  1 
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifndef TVMET_HAVE_STRINGS_H 
+#define TVMET_HAVE_STRINGS_H  1 
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef TVMET_HAVE_STRING_H 
+#define TVMET_HAVE_STRING_H  1 
+#endif
+
+/* Define if the compiler supports SYSV math library */
+/* #undef TVMET_HAVE_SYSV_MATH */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifndef TVMET_HAVE_SYS_STAT_H 
+#define TVMET_HAVE_SYS_STAT_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#ifndef TVMET_HAVE_SYS_TIME_H 
+#define TVMET_HAVE_SYS_TIME_H  1 
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifndef TVMET_HAVE_SYS_TYPES_H 
+#define TVMET_HAVE_SYS_TYPES_H  1 
+#endif
+
+/* Define if the compiler recognizes typename */
+#ifndef TVMET_HAVE_TYPENAME 
+#define TVMET_HAVE_TYPENAME   
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifndef TVMET_HAVE_UNISTD_H 
+#define TVMET_HAVE_UNISTD_H  1 
+#endif
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef TVMET_HAVE__BOOL */
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef TVMET_PACKAGE_BUGREPORT 
+#define TVMET_PACKAGE_BUGREPORT  "opetzold@users.sourceforge.net" 
+#endif
+
+/* Define to the full name of this package. */
+#ifndef TVMET_PACKAGE_NAME 
+#define TVMET_PACKAGE_NAME  "tvmet" 
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef TVMET_PACKAGE_STRING 
+#define TVMET_PACKAGE_STRING  "tvmet 1.7.2" 
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef TVMET_PACKAGE_TARNAME 
+#define TVMET_PACKAGE_TARNAME  "tvmet" 
+#endif
+
+/* Define to the version of this package. */
+#ifndef TVMET_PACKAGE_VERSION 
+#define TVMET_PACKAGE_VERSION  "1.7.2" 
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef TVMET_STDC_HEADERS 
+#define TVMET_STDC_HEADERS  1 
+#endif
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TVMET_TM_IN_SYS_TIME */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef _tvmet_const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef _tvmet_inline */
+#endif
+
+/* Define to equivalent of C99 restrict keyword, or to nothing if this is not
+   supported. Do not define if restrict is supported directly. */
+#ifndef _tvmet_restrict 
+#define _tvmet_restrict  __restrict 
+#endif
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef _tvmet_size_t */
+ 
+/* _INCLUDE_TVMET_CONFIG_H */
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config-gcc.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,44 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: config-gcc.h,v 1.10 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_CONFIG_GCC_H
+#define TVMET_CONFIG_GCC_H
+
+#if defined(__GNUC__)
+
+   // force inline
+#  define TVMET_CXX_ALWAYS_INLINE __attribute__((always_inline))
+
+#else // !defined(__GNUC__)
+
+   // paranoia
+#  warning "config header for gnuc included without defined __GNUC__"
+
+#endif
+
+#endif // TVMET_CONFIG_GCC_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config-icc.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,69 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: config-icc.h,v 1.12 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_CONFIG_ICC_H
+#define TVMET_CONFIG_ICC_H
+
+#if defined(__INTEL_COMPILER)
+
+  /* isnan/isinf hack
+   *
+   * The problem is related intel's 8.0 macros isnan and isinf,
+   * they are expanded in this version and they are not compileable
+   * therefore. We use a small hack here - disabling. This is
+   * not an real solution, nor forever.
+   * For a list of all defined symbols use icpc -E -dM prog1.cpp
+   * or read /opt/intel/compiler80/doc/c_ug/index.htm.
+   */
+#  if (__INTEL_COMPILER == 800) || (__INTEL_COMPILER > 800)
+#    define TVMET_NO_IEEE_MATH_ISNAN
+#    define TVMET_NO_IEEE_MATH_ISINF
+#  endif
+
+
+   /*
+    * disable compiler warnings
+    */
+#  pragma warning(disable:981) // operands are evaluated in unspecified order
+
+
+   /*
+    * force inline using gcc's compatibility mode
+    */
+#  if (__INTEL_COMPILER == 800) || (__INTEL_COMPILER > 800)
+#    define TVMET_CXX_ALWAYS_INLINE __attribute__((always_inline))
+#  endif
+
+#else // !defined(__INTEL_COMPILER)
+
+   // paranoia
+#  warning "config header included without defined __INTEL_COMPILER"
+
+#endif
+
+#endif // TVMET_CONFIG_ICC_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config-kcc.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,41 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: config-kcc.h,v 1.9 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_CONFIG_KCC_H
+#define TVMET_CONFIG_KCC_H
+
+#if defined(__KCC)
+
+#else // !defined(__KCC)
+
+   // paranoia
+#  warning "config header included without defined __KCC"
+
+#endif
+
+#endif // TVMET_CONFIG_KCC_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config-pgi.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,48 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: config-pgi.h,v 1.10 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_CONFIG_PGI_H
+#define TVMET_CONFIG_PGI_H
+
+#if defined(__PGI)
+
+
+   // obviously does have pgCC 5.1 (trial) no long double on sqrt
+#  if defined(TVMET_HAVE_LONG_DOUBLE)
+#    undef TVMET_HAVE_LONG_DOUBLE
+#  endif
+
+
+#else // !defined(__PGI)
+
+   // paranoia
+#  warning "config header included without defined __PGI"
+
+#endif
+
+#endif // TVMET_CONFIG_PGI_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config/config-vc71.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,249 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2003 Olaf Petzold <opetzold@users.sourceforge.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: config-vc71.h.in,v 1.2 2004-11-04 16:47:12 opetzold Exp $
+ */
+
+#ifndef TVMET_CONFIG_VC71_H
+#define TVMET_CONFIG_VC71_H
+
+
+/*******************************************************************
+ * equivalent hand made header to configure.ac's autoheader.
+ ******************************************************************/
+
+
+/* define if the compiler has complex<T> */
+#ifndef TVMET_HAVE_COMPLEX
+#define TVMET_HAVE_COMPLEX 1
+#endif
+
+/* define if the compiler has complex math functions */
+#ifndef TVMET_HAVE_COMPLEX_MATH1
+#define TVMET_HAVE_COMPLEX_MATH1 1
+#endif
+
+/* define if the compiler has more complex math functions */
+/* #undef TVMET_HAVE_COMPLEX_MATH2 */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#ifdef TVMET_HAVE_DLFCN_H
+#undef TVMET_HAVE_DLFCN_H
+#endif
+
+/* Define to 1 if you have the `floor' function. */
+#ifndef TVMET_HAVE_FLOOR
+#define TVMET_HAVE_FLOOR  1
+#endif
+
+/* Define if the compiler supports IEEE math library */
+#ifndef TVMET_HAVE_IEEE_MATH
+#define TVMET_HAVE_IEEE_MATH 1
+#endif
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#ifdef TVMET_HAVE_INTTYPES_H
+#undef TVMET_HAVE_INTTYPES_H
+#endif
+
+/* Define to 1 if you have the `dl' library (-ldl). */
+#ifdef TVMET_HAVE_LIBDL
+#undef TVMET_HAVE_LIBDL
+#endif
+
+/* Define to 1 if long double works and has more range or precision than
+   double. */
+#ifndef TVMET_HAVE_LONG_DOUBLE
+#define TVMET_HAVE_LONG_DOUBLE  1
+#endif
+
+/* Define if the compiler supports the long_long type */
+// enable MS extension for long long
+#ifndef TVMET_HAVE_LONG_LONG
+#define TVMET_HAVE_LONG_LONG 1
+#endif
+
+/* Define to 1 if you have the <memory.h> header file. */
+#ifndef TVMET_HAVE_MEMORY_H
+#define TVMET_HAVE_MEMORY_H  1
+#endif
+
+/* Define if the compiler supports the mutable keyword */
+#ifndef TVMET_HAVE_MUTABLE
+#define TVMET_HAVE_MUTABLE 1
+#endif
+
+/* Define if the compiler implements namespaces */
+#ifndef TVMET_HAVE_NAMESPACES
+#define TVMET_HAVE_NAMESPACES 1
+#endif
+
+/* Define if the compiler supports partial specialization */
+#ifndef TVMET_HAVE_PARTIAL_SPECIALIZATION
+#define TVMET_HAVE_PARTIAL_SPECIALIZATION 1
+#endif
+
+/* Define to 1 if you have the `pow' function. */
+#ifndef TVMET_HAVE_POW
+#define TVMET_HAVE_POW  1
+#endif
+
+/* Define to 1 if you have the `rint' function. */
+
+#ifdef TVMET_HAVE_RINT
+#undef TVMET_HAVE_RINT
+#endif
+
+/* Define to 1 if you have the `sqrt' function. */
+#ifndef TVMET_HAVE_SQRT
+#define TVMET_HAVE_SQRT  1
+#endif
+
+/* Define to 1 if stdbool.h conforms to C99. */
+/* #undef TVMET_HAVE_STDBOOL_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#ifdef TVMET_HAVE_STDINT_H
+#undef TVMET_HAVE_STDINT_H
+#endif
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#ifndef TVMET_HAVE_STDLIB_H
+#define TVMET_HAVE_STDLIB_H  1
+#endif
+
+/* Define to 1 if you have the <strings.h> header file. */
+#ifdef TVMET_HAVE_STRINGS_H
+#undef TVMET_HAVE_STRINGS_H
+#endif
+
+/* Define to 1 if you have the <string.h> header file. */
+#ifndef TVMET_HAVE_STRING_H
+#define TVMET_HAVE_STRING_H  1
+#endif
+
+/* Define if the compiler supports SYSV math library */
+/* #undef TVMET_HAVE_SYSV_MATH */
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#ifdef TVMET_HAVE_SYS_STAT_H
+#undef TVMET_HAVE_SYS_STAT_H
+#endif
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#ifdef TVMET_HAVE_SYS_TIME_H
+#undef TVMET_HAVE_SYS_TIME_H
+#endif
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#ifdef TVMET_HAVE_SYS_TYPES_H
+#undef TVMET_HAVE_SYS_TYPES_H
+#endif
+
+/* Define if the compiler recognizes typename */
+#ifndef TVMET_HAVE_TYPENAME
+#define TVMET_HAVE_TYPENAME 1
+#endif
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#ifdef TVMET_HAVE_UNISTD_H
+#undef TVMET_HAVE_UNISTD_H
+#endif
+
+/* Define to 1 if the system has the type `_Bool'. */
+/* #undef TVMET_HAVE__BOOL */
+
+/* Define to the address where bug reports for this package should be sent. */
+#ifndef TVMET_PACKAGE_BUGREPORT
+#define TVMET_PACKAGE_BUGREPORT  "opetzold@users.sourceforge.net"
+#endif
+
+/* Define to the full name of this package. */
+#ifndef TVMET_PACKAGE_NAME
+#define TVMET_PACKAGE_NAME  "tvmet"
+#endif
+
+/* Define to the full name and version of this package. */
+#ifndef TVMET_PACKAGE_STRING
+#define TVMET_PACKAGE_STRING  "tvmet 1.7.2"
+#endif
+
+/* Define to the one symbol short name of this package. */
+#ifndef TVMET_PACKAGE_TARNAME
+#define TVMET_PACKAGE_TARNAME  "tvmet"
+#endif
+
+/* Define to the version of this package. */
+#ifndef TVMET_PACKAGE_VERSION
+#define TVMET_PACKAGE_VERSION  "1.7.2"
+#endif
+
+/* Define to 1 if you have the ANSI C header files. */
+#ifndef TVMET_STDC_HEADERS
+#define TVMET_STDC_HEADERS  1
+#endif
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TVMET_TM_IN_SYS_TIME */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef _tvmet_const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef _tvmet_inline */
+#endif
+
+/* Define to equivalent of C99 restrict keyword, or to nothing if this is not
+   supported. Do not define if restrict is supported directly. */
+// unfortunally, VC++ 7.1 doesn't have restrict.
+#ifndef _tvmet_restrict
+#define _tvmet_restrict
+#endif
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef _tvmet_size_t */
+
+
+
+/*******************************************************************
+ * tvmet's config for special handling on MS VC
+ ******************************************************************/
+
+
+#if defined(_MSC_VER)
+
+/* The undefined case of TVMET_CXX_ALWAYS_INLINE is handled inside
+ * tvmet.h, so there there is no need to do this here! */
+
+#else // !defined(_MSC_VER)
+
+   // paranoia
+#  warning "config header for MS VC 7.1 included without defined _MSC_VER"
+
+#endif
+
+#endif // TVMET_CONFIG_VC71_H
+
+// Local Variables:
+// mode:C++
+// End:
+//  LocalWords:  autoheader
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Gemm.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,115 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemm.h,v 1.12 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_GEMM_H
+#define TVMET_LOOP_GEMM_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class gemm Gemm.h "tvmet/loop/Gemm.h"
+ * \brief class for matrix-matrix product using loop unrolling.
+ *        using formula
+ *        \f[
+ *        M_1\,M_2
+ *        \f]
+ * \par Example:
+ * \code
+ * template<class T, std::size_t Rows1, std::size_t Cols1, std::size_t Cols2>
+ * inline
+ * void
+ * prod(const Matrix<T, Rows1, Cols1>& lhs, const Matrix<T, Cols1, Cols2>& rhs,
+ * 	Matrix<T, Rows1, Cols2>& dest)
+ * {
+ *   for (std::size_t i = 0; i != Rows1; ++i) {
+ *     for (std::size_t j = 0; j != Cols2; ++j) {
+ *       dest(i, j) = tvmet::loop::gemm<Rows1, Cols1, Cols2>().prod(lhs, rhs, i, j);
+ *     }
+ *   }
+ * }
+ * \endcode
+ * \note The number of rows of rhs matrix have to be equal to cols of lhs matrix.
+ *       The result is a (Rows1 x Cols2) matrix.
+ */
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2>
+class gemm
+{
+  gemm(const gemm&);
+  gemm& operator=(const gemm&);
+
+private:
+  enum {
+    count 	= Cols1,
+    N 		= (count+7)/8
+  };
+
+public:
+  gemm() { }
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+    >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    typename PromoteTraits<
+      typename E1::value_type,
+      typename E2::value_type
+    >::value_type  				sum(0);
+    std::size_t 				k(0);
+    std::size_t 				n(N);
+
+    // Duff's device
+    switch(count % 8) {
+    case 0: do { sum += lhs(i, k) * rhs(k, j); ++k;
+    case 7:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 6:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 5:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 4:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 3:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 2:      sum += lhs(i, k) * rhs(k, j); ++k;
+    case 1:      sum += lhs(i, k) * rhs(k, j); ++k;
+            } while(--n != 0);
+    }
+
+    return sum;
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_GEMM_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Gemmt.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,115 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemmt.h,v 1.9 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_GEMMT_H
+#define TVMET_LOOP_GEMMT_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class gemmt Gemmt.h "tvmet/loop/Gemmt.h"
+ * \brief class for for product matrix-transpose(matrix) operations.
+ *        using formula
+ *        \f[
+ *        M_1\,M_2^{T}
+ *        \f]
+ * \par Example:
+ * \code
+ * template<class T, std::size_t Rows1, std::size_t Cols1, std::size_t Cols2>
+ * inline
+ * void
+ * prod(const Matrix<T, Rows1, Cols1>& lhs, const Matrix<T, Rows2, Cols1>& rhs,
+ * 	Matrix<T, Rows1, Rows2>& dest)
+ * {
+ *   for (std::size_t i = 0; i != Rows1; ++i) {
+ *     for (std::size_t j = 0; j != Rows2; ++j) {
+ *       dest(i, j) = tvmet::loop::gemmt<Rows1, Cols1, Cols1>().prod(lhs, rhs, i, j);
+ *     }
+ *   }
+ * }
+ * \endcode
+ * \note The number of cols of rhs matrix have to be equal to cols of rhs matrix.
+ *       The result is a (Rows1 x Rows2) matrix.
+ */
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2 /* unused */>
+class gemmt
+{
+  gemmt(const gemmt&);
+  gemmt& operator=(const gemmt&);
+
+private:
+  enum {
+    count 	= Cols1,
+    N 		= (count+7)/8
+  };
+
+public:
+  gemmt() { }
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+    >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    typename PromoteTraits<
+      typename E1::value_type,
+      typename E2::value_type
+    >::value_type  				sum(0);
+    std::size_t 				k(0);
+    std::size_t 				n(N);
+
+    // Duff's device
+    switch(count % 8) {
+    case 0: do { sum += lhs(i, k) * rhs(j, k); ++k;
+    case 7:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 6:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 5:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 4:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 3:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 2:      sum += lhs(i, k) * rhs(j, k); ++k;
+    case 1:      sum += lhs(i, k) * rhs(j, k); ++k;
+            } while(--n != 0);
+    }
+
+    return sum;
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_GEMMT_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Gemtm.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,116 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemtm.h,v 1.9 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_GEMTM_H
+#define TVMET_LOOP_GEMTM_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class gemtm Gemtm.h "tvmet/loop/Gemtm.h"
+ * \brief class for matrix-matrix product using loop unrolling.
+ *        using formula
+ *        \f[
+ *        M_1^{T}\,M_2
+ *        \f]
+ * \par Example:
+ * \code
+ * template<class T, std::size_t Rows1, std::size_t Cols1, std::size_t Cols2>
+ * inline
+ * void
+ * prod(const Matrix<T, Rows1, Cols1>& lhs, const Matrix<T, Rows1, Cols2>& rhs,
+ * 	Matrix<T, Cols2, Cols1>& dest)
+ * {
+ *   for (std::size_t i = 0; i != Cols1; ++i) {
+ *     for (std::size_t j = 0; j != Cols2; ++j) {
+ *       dest(i, j) = tvmet::loop::gemtm<Rows1, Cols1, Cols2>::prod(lhs, rhs, i, j);
+ *     }
+ *   }
+ * }
+ * \endcode
+ * \note The number of rows of rhs matrix have to be equal rows of rhs matrix,
+ *       since lhs matrix 1 is transposed.
+ *       The result is a (Cols1 x Cols2) matrix.
+ */
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2>
+class gemtm
+{
+  gemtm(const gemtm&);
+  gemtm& operator=(const gemtm&);
+
+private:
+  enum {
+    count 	= Cols1,
+    N 		= (count+7)/8
+  };
+
+public:
+  gemtm() { }
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+    >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    typename PromoteTraits<
+      typename E1::value_type,
+      typename E2::value_type
+    >::value_type  				sum(0);
+    std::size_t 				k(0);
+    std::size_t 				n(N);
+
+    // Duff's device
+    switch(count % 8) {
+    case 0: do { sum += lhs(k, i) * rhs(k, j); ++k;
+    case 7:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 6:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 5:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 4:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 3:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 2:      sum += lhs(k, i) * rhs(k, j); ++k;
+    case 1:      sum += lhs(k, i) * rhs(k, j); ++k;
+            } while(--n != 0);
+    }
+
+    return sum;
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_GEMTM_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Gemtv.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,110 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemtv.h,v 1.7 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_GEMTV_H
+#define TVMET_LOOP_GEMTV_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class gemtv Gemtv.h "tvmet/loop/Gemtv.h"
+ * \brief class for transposed(matrix)-vector product using loop unrolling.
+ *        using formula
+ *        \f[
+ *        M^T\,v
+ *        \f]
+ * \par Example:
+ * \code
+ * template<class T, std::size_t Rows, std::size_t Cols>
+ * inline
+ * void
+ * prod(const Matrix<T, Rows, Cols>& lhs, const Vector<T, Rows>& rhs,
+ * 	Vector<T, Cols>& dest)
+ * {
+ *   for (std::size_t i = 0; i != Cols; ++i) {
+ *     dest(i) = tvmet::loop::gemtv<Rows, Cols>().prod(lhs, rhs, i);
+ *   }
+ * }
+ * \endcode
+ */
+template<std::size_t Rows, std::size_t Cols>
+class gemtv
+{
+  gemtv(const gemtv&);
+  gemtv& operator=(const gemtv&);
+
+private:
+  enum {
+    count 	= Rows,
+    N 		= (count+7)/8
+  };
+
+public:
+  gemtv() { }
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+    >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i) {
+    typename PromoteTraits<
+      typename E1::value_type,
+      typename E2::value_type
+    >::value_type  				sum(0);
+    std::size_t 				j(0);
+    std::size_t 				n(N);
+
+    // Duff's device
+    switch(count % 8) {
+    case 0: do { sum += lhs(j, i) * rhs(j); ++j;
+    case 7:      sum += lhs(j, i) * rhs(j); ++j;
+    case 6:      sum += lhs(j, i) * rhs(j); ++j;
+    case 5:      sum += lhs(j, i) * rhs(j); ++j;
+    case 4:      sum += lhs(j, i) * rhs(j); ++j;
+    case 3:      sum += lhs(j, i) * rhs(j); ++j;
+    case 2:      sum += lhs(j, i) * rhs(j); ++j;
+    case 1:      sum += lhs(j, i) * rhs(j); ++j;
+            } while(--n != 0);
+    }
+
+    return sum;
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_GEMTV_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Gemv.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,110 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemv.h,v 1.7 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_GEMV_H
+#define TVMET_LOOP_GEMV_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class gemv Gemv.h "tvmet/loop/Gemv.h"
+ * \brief class for matrix-vector product using loop unrolling.
+ *        using formula
+ *        \f[
+ *        M\,v
+ *        \f]
+ * \par Example:
+ * \code
+ * template<class T, std::size_t Rows, std::size_t Cols>
+ * inline
+ * void
+ * prod(const Matrix<T, Rows, Cols>& lhs, const Vector<T, Cols>& rhs,
+ * 	Vector<T, Rows>& dest)
+ * {
+ *   for (std::size_t i = 0; i != Rows; ++i) {
+ *     dest(i) = tvmet::loop::gemv<Rows, Cols>().prod(lhs, rhs, i);
+ *   }
+ * }
+ * \endcode
+ */
+template<std::size_t Rows, std::size_t Cols>
+class gemv
+{
+  gemv(const gemv&);
+  gemv& operator=(const gemv&);
+
+private:
+  enum {
+    count 	= Cols,
+    N 		= (count+7)/8
+  };
+
+public:
+  gemv() { }
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+    >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i) {
+    typename PromoteTraits<
+      typename E1::value_type,
+      typename E2::value_type
+    >::value_type  				sum(0);
+    std::size_t 				j(0);
+    std::size_t 				n(N);
+
+    // Duff's device
+    switch(count % 8) {
+    case 0: do { sum += lhs(i, j) * rhs(j); ++j;
+    case 7:      sum += lhs(i, j) * rhs(j); ++j;
+    case 6:      sum += lhs(i, j) * rhs(j); ++j;
+    case 5:      sum += lhs(i, j) * rhs(j); ++j;
+    case 4:      sum += lhs(i, j) * rhs(j); ++j;
+    case 3:      sum += lhs(i, j) * rhs(j); ++j;
+    case 2:      sum += lhs(i, j) * rhs(j); ++j;
+    case 1:      sum += lhs(i, j) * rhs(j); ++j;
+            } while(--n != 0);
+    }
+
+    return sum;
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_GEMV_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Matrix.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,66 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Matrix.h,v 1.11 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_MATRIX_H
+#define TVMET_LOOP_MATRIX_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class Matrix Matrix.h "tvmet/loop/Matrix.h"
+ * \brief Loop %Matrix class using expression and loop templates.
+ */
+template<std::size_t Rows, std::size_t Cols>
+class Matrix
+{
+  Matrix(const Matrix&);
+  Matrix& operator=(const Matrix&);
+
+public:
+  Matrix() { }
+
+public:
+  /** assign an expression on columns on given row using the functional fn. */
+  template<class E1, class E2, class Assign>
+  static inline
+  void assign(E1& lhs, const E2& rhs, const Assign& assign_fn) {
+    for(std::size_t i = 0; i != Rows; ++i)
+      for(std::size_t j = 0; j != Cols; ++j)
+	assign_fn.apply_on(lhs(i, j), rhs(i, j));
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_MATRIX_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/loop/Vector.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,65 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Vector.h,v 1.9 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_LOOP_VECTOR_H
+#define TVMET_LOOP_VECTOR_H
+
+namespace tvmet {
+
+namespace loop {
+
+
+/**
+ * \class Vector Vector.h "tvmet/loop/Vector.h"
+ * \brief Loop %Vector class using expression and loop templates.
+ */
+template<std::size_t Sz>
+class Vector
+{
+  Vector(const Vector&);
+  Vector& operator=(const Vector&);
+
+public:
+  Vector() { }
+
+public:
+  /** assign an expression on columns on given row using the functional fn. */
+  template<class E1, class E2, class Assign>
+  static inline
+  void assign(E1& lhs, const E2& rhs, const Assign& assign_fn) {
+    for(std::size_t i = 0; i != Sz; ++i)
+      assign_fn.apply_on(lhs(i), rhs(i));
+  }
+};
+
+
+} // namespace loop
+
+} // namespace tvmet
+
+#endif /* TVMET_LOOP_VECTOR_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Gemm.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,102 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemm.h,v 1.15 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_GEMM_H
+#define TVMET_META_GEMM_H
+
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class gemm Gemm.h "tvmet/meta/Gemm.h"
+ * \brief Meta class for matrix-matrix operations, like product
+ *        using formula
+ *        \f[
+ *        M_1\,M_2
+ *        \f]
+ * \note The rows of matrix 2 have to be equal to cols of matrix 1.
+ */
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2,
+	 std::size_t K>
+class gemm
+{
+  gemm();
+  gemm(const gemm&);
+  gemm& operator=(const gemm&);
+
+private:
+  enum {
+    doIt = (K != Cols1 - 1) 		/**< recursive counter */
+  };
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return lhs(i, K) * rhs(K, j)
+      + gemm<Rows1 * doIt, Cols1 * doIt,
+             Cols2 * doIt,
+             (K+1) * doIt>::prod(lhs, rhs, i, j);
+  }
+};
+
+
+/**
+ * \class gemm<0,0,0,0> Gemm.h "tvmet/meta/Gemm.h"
+ * \brief gemm Specialized for recursion.
+ */
+template<>
+class gemm<0,0,0,0>
+{
+  gemm();
+  gemm(const gemm&);
+  gemm& operator=(const gemm&);
+
+public:
+  template<class E1, class E2>
+  static inline
+  XprNull prod(const E1&, const E2&, std::size_t, std::size_t) {
+    return XprNull();
+  }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_GEMM_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Gemmt.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,103 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemmt.h,v 1.13 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_GEMMT_H
+#define TVMET_META_GEMMT_H
+
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class gemmt Gemmt.h "tvmet/meta/Gemmt.h"
+ * \brief Meta class for product matrix-transpose(matrix) operations.
+ *        using formula
+ *        \f[
+ *        M_1\,M_2^{T}
+ *        \f]
+ * \note The rows of matrix 2 have to be equal to cols of matrix 1. The result
+ *       is a rows1 * cols2 matrix.
+ */
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2,
+	 std::size_t K>
+class gemmt
+{
+  gemmt();
+  gemmt(const gemmt&);
+  gemmt& operator=(const gemmt&);
+
+private:
+  enum {
+    doIt = (K != Cols2 - 1) 		/**< recursive counter */
+  };
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return lhs(i, K) * rhs(j, K)
+      + gemmt<Rows1 * doIt, Cols1 * doIt,
+              Cols2 * doIt,
+              (K+1) * doIt>::prod(lhs, rhs, i, j);
+  }
+};
+
+
+/**
+ * \class gemmt<0,0,0,0> Gemmt.h "tvmet/meta/Gemmt.h"
+ * \brief gemmt Specialized for recursion.
+ */
+template<>
+class gemmt<0,0,0,0>
+{
+  gemmt();
+  gemmt(const gemmt&);
+  gemmt& operator=(const gemmt&);
+
+public:
+  template<class E1, class E2>
+  static inline
+  XprNull prod(const E1&, const E2&, std::size_t, std::size_t) {
+    return XprNull();
+  }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_GEMMT_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Gemtm.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,106 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemtm.h,v 1.12 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_GEMTM_H
+#define TVMET_META_GEMTM_H
+
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class gemtm Gemtm.h "tvmet/meta/Gemtm.h"
+ * \brief Meta class for trans(matrix)-matrix operations, like product.
+ *        using formula
+ *        \f[
+ *        M_1^{T}\,M_2
+ *        \f]
+ * \note The number of cols of matrix 2 have to be equal to number of rows of
+ *       matrix 1, since matrix 1 is transposed - the result is a (Cols1 x Cols2)
+ *       matrix.
+ */
+
+template<std::size_t Rows1, std::size_t Cols1,
+	 std::size_t Cols2,
+	 std::size_t K>
+class gemtm
+{
+private:
+  gemtm();
+  gemtm(const gemtm&);
+  gemtm& operator=(const gemtm&);
+
+private:
+  enum {
+    doIt = (K != Rows1 - 1) 		/**< recursive counter */
+  };
+
+public:
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return lhs(K, i) * rhs(K, j)
+      + gemtm<Rows1 * doIt, Cols1 * doIt,
+              Cols2 * doIt,
+              (K+1) * doIt>::prod(lhs, rhs, i, j);
+  }
+};
+
+
+/**
+ * \class gemtm<0,0,0,0> Gemtm.h "tvmet/meta/Gemtm.h"
+ * \brief gemtm Specialized for recursion.
+ */
+template<>
+class gemtm<0,0,0,0>
+{
+  gemtm();
+  gemtm(const gemtm&);
+  gemtm& operator=(const gemtm&);
+
+public:
+  template<class E1, class E2>
+  static inline
+  XprNull prod(const E1&, const E2&, std::size_t, std::size_t) {
+    return XprNull();
+  }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_GEMTM_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Gemtv.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,100 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemtv.h,v 1.8 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_GEMTV_H
+#define TVMET_META_GEMTV_H
+
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class gemtv Gemtv.h "tvmet/meta/Gemtv.h"
+ * \brief Meta class for matrix-transpose-vector operations.
+ *        using formula
+ *        \f[
+ *        M^T\,v
+ *        \f]
+ */
+template<std::size_t Rows, std::size_t Cols,
+	 std::size_t I>
+class gemtv
+{
+  gemtv();
+  gemtv(const gemtv&);
+  gemtv& operator=(const gemtv&);
+
+private:
+  enum {
+    doIt = I < (Rows-1)  		/**< recursive counter */
+  };
+
+public:
+  /** Meta template for %Matrix lhs %Vector rhs product. */
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t j) {
+    return lhs(I, j) * rhs(I)
+      + gemtv<Rows * doIt, Cols * doIt,
+              (I+1)* doIt>::prod(lhs, rhs, j);
+  }
+};
+
+
+/**
+ * \class gemtv<0,0,0> Gemtv.h "tvmet/meta/Gemtv.h"
+ * \brief gemtv Specialized for recursion
+ */
+template<>
+class gemtv<0,0,0>
+{
+  gemtv();
+  gemtv(const gemtv&);
+  gemtv& operator=(const gemtv&);
+
+public:
+  template<class E1, class E2>
+  static inline
+  XprNull prod(const E1&, const E2&, std::size_t) {
+    return XprNull();
+  }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_GEMTV_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Gemv.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,100 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Gemv.h,v 1.13 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_GEMV_H
+#define TVMET_META_GEMV_H
+
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class gemv Gemv.h "tvmet/meta/Gemv.h"
+ * \brief Meta class for matrix-vector operations.
+ *        using formula
+ *        \f[
+ *        M\,v
+ *        \f]
+ */
+template<std::size_t Rows, std::size_t Cols,
+	 std::size_t J>
+class gemv
+{
+  gemv();
+  gemv(const gemv&);
+  gemv& operator=(const gemv&);
+
+private:
+  enum {
+    doIt = J < (Cols-1)  		/**< recursive counter */
+  };
+
+public:
+  /** Meta template for %Matrix lhs %Vector rhs product. */
+  template<class E1, class E2>
+  static inline
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type
+  prod(const E1& lhs, const E2& rhs, std::size_t i) {
+    return lhs(i, J) * rhs(J)
+      + gemv<Rows * doIt, Cols * doIt,
+             (J+1)* doIt>::prod(lhs, rhs, i);
+  }
+};
+
+
+/**
+ * \class gemv<0,0,0> Gemv.h "tvmet/meta/Gemv.h"
+ * \brief gemv Specialized for recursion
+ */
+template<>
+class gemv<0,0,0>
+{
+  gemv();
+  gemv(const gemv&);
+  gemv& operator=(const gemv&);
+
+public:
+  template<class E1, class E2>
+  static inline
+  XprNull prod(const E1&, const E2&, std::size_t) {
+    return XprNull();
+  }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_GEMV_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Matrix.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,166 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Matrix.h,v 1.19 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_MATRIX_H
+#define TVMET_META_MATRIX_H
+
+#include <tvmet/NumericTraits.h>
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+namespace meta {
+
+
+/**
+ * \class Matrix Matrix.h "tvmet/meta/Matrix.h"
+ * \brief Meta %Matrix class using expression and meta templates.
+ */
+template<std::size_t Rows, std::size_t Cols,
+	 std::size_t M=0, std::size_t N=0>
+class Matrix
+{
+  Matrix();
+  Matrix(const Matrix&);
+  Matrix& operator=(const Matrix&);
+
+private:
+  enum {
+    doRows = (M < Rows - 1) ? 1 : 0,	/**< recursive counter Rows. */
+    doCols = (N < Cols - 1) ? 1 : 0	/**< recursive counter Cols. */
+  };
+
+public:
+  /** assign an expression on columns on given row using the functional assign_fn. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void assign2(Dest& lhs, const Src& rhs, const Assign& assign_fn) {
+    assign_fn.apply_on(lhs(M, N), rhs(M, N));
+    Matrix<Rows * doCols, Cols * doCols,
+           M * doCols, (N+1) * doCols>::assign2(lhs, rhs, assign_fn);
+  }
+
+  /** assign an expression on row-wise using the functional assign_fn. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void assign(Dest& lhs, const Src& rhs, const Assign& assign_fn) {
+    Matrix<Rows, Cols,
+           M, 0>::assign2(lhs, rhs, assign_fn);
+    Matrix<Rows * doRows, Cols * doRows,
+          (M+1) * doRows, 0>::assign(lhs, rhs, assign_fn);
+  }
+
+  /** evaluate a given matrix expression, column wise. */
+  template<class E>
+  static inline
+  bool all_elements2(const E& e) {
+    if(!e(M, N)) return false;
+    return Matrix<Rows * doCols, Cols * doCols,
+                  M * doCols, (N+1) * doCols>::all_elements2(e);
+  }
+
+  /** evaluate a given matrix expression, row wise. */
+  template<class E>
+  static inline
+  bool all_elements(const E& e) {
+    if(!Matrix<Rows, Cols, M, 0>::all_elements2(e) ) return false;
+    return Matrix<Rows * doRows, Cols * doRows,
+                 (M+1) * doRows, 0>::all_elements(e);
+  }
+
+  /** evaluate a given matrix expression, column wise. */
+  template<class E>
+  static inline
+  bool any_elements2(const E& e) {
+    if(e(M, N)) return true;
+    return Matrix<Rows * doCols, Cols * doCols,
+                  M * doCols, (N+1) * doCols>::any_elements2(e);
+  }
+
+  /** evaluate a given matrix expression, row wise. */
+  template<class E>
+  static inline
+  bool any_elements(const E& e) {
+    if(Matrix<Rows, Cols, M, 0>::any_elements2(e) ) return true;
+    return Matrix<Rows * doRows, Cols * doRows,
+                 (M+1) * doRows, 0>::any_elements(e);
+  }
+
+  /** trace a given matrix expression. */
+  template<class E>
+  static inline
+  typename E::value_type
+  trace(const E& e) {
+    return e(M, N)
+      + Matrix<Rows * doCols, Cols * doCols,
+              (M+1) * doCols, (N+1) * doCols>::trace(e);
+  }
+
+};
+
+
+/**
+ * \class Matrix<0, 0, 0, 0> Matrix.h "tvmet/meta/Matrix.h"
+ * \brief Meta %Matrix specialized for recursion.
+ */
+template<>
+class Matrix<0, 0, 0, 0>
+{
+  Matrix();
+  Matrix(const Matrix&);
+  Matrix& operator=(const Matrix&);
+
+public:
+  template<class Dest, class Src, class Assign>
+  static inline void assign2(Dest&, const Src&, const Assign&) { }
+
+  template<class Dest, class Src, class Assign>
+  static inline void assign(Dest&, const Src&, const Assign&) { }
+
+  template<class E>
+  static inline bool all_elements2(const E&) { return true; }
+
+  template<class E>
+  static inline bool all_elements(const E&) { return true; }
+
+  template<class E>
+  static inline bool any_elements2(const E&) { return false; }
+
+  template<class E>
+  static inline bool any_elements(const E&) { return false; }
+
+  template<class E>
+  static inline XprNull trace(const E&) { return XprNull(); }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_MATRIX_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/meta/Vector.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,155 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Vector.h,v 1.24 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_META_VECTOR_H
+#define TVMET_META_VECTOR_H
+
+#include <tvmet/NumericTraits.h>
+#include <tvmet/xpr/Null.h>
+
+namespace tvmet {
+
+/* forwards */
+template<class T, std::size_t Sz> class Vector;
+
+
+namespace meta {
+
+
+/**
+ * \class Vector Vector.h "tvmet/meta/Vector.h"
+ * \brief Meta %Vector class using expression templates
+ */
+template<std::size_t Sz, std::size_t K=0>
+class Vector
+{
+  Vector();
+  Vector(const Vector&);
+  Vector& operator=(const Vector&);
+
+private:
+  enum {
+    doIt = (K < (Sz-1)) ? 1 : 0		/**< recursive counter */
+  };
+
+public:
+  /** assign an expression expr using the functional assign_fn. */
+  template <class Dest, class Src, class Assign>
+  static inline
+  void assign(Dest& lhs, const Src& rhs, const Assign& assign_fn) {
+    assign_fn.apply_on(lhs(K), rhs(K));
+    meta::Vector<Sz * doIt, (K+1) * doIt>::assign(lhs, rhs, assign_fn);
+  }
+
+  /** build the sum of the vector. */
+  template<class E>
+  static inline
+  typename E::value_type
+  sum(const E& e) {
+    return e(K) + meta::Vector<Sz * doIt, (K+1) * doIt>::sum(e);
+  }
+
+  /** build the product of the vector. */
+  template<class E>
+  static inline
+  typename NumericTraits<
+    typename E::value_type
+  >::sum_type
+  product(const E& e) {
+    return e(K) * meta::Vector<Sz * doIt, (K+1) * doIt>::product(e);
+  }
+
+  /** build the dot product of the vector. */
+  template<class Dest, class Src>
+  static inline
+  typename PromoteTraits<
+    typename Dest::value_type,
+    typename Src::value_type
+  >::value_type
+  dot(const Dest& lhs, const Src& rhs) {
+    return lhs(K) * rhs(K)
+      + meta::Vector<Sz * doIt, (K+1) * doIt>::dot(lhs, rhs);
+  }
+
+  /** check for all elements */
+  template<class E>
+  static inline
+  bool
+  all_elements(const E& e) {
+    if(!e(K)) return false;
+    return meta::Vector<Sz * doIt, (K+1) * doIt>::all_elements(e);
+  }
+
+  /** check for any elements */
+  template<class E>
+  static inline
+  bool
+  any_elements(const E& e) {
+    if(e(K)) return true;
+    return meta::Vector<Sz * doIt, (K+1) * doIt>::any_elements(e);
+  }
+};
+
+
+/**
+ * \class Vector<0,0> Vector.h "tvmet/meta/Vector.h"
+ * \brief Meta %Vector Specialized for recursion
+ */
+template<>
+class Vector<0,0>
+{
+  Vector();
+  Vector(const Vector&);
+  Vector& operator=(const Vector&);
+
+public:
+  template <class Dest, class Src, class Assign>
+  static inline void assign(Dest&, const Src&, const Assign&) { }
+
+  template<class E>
+  static inline XprNull sum(const E&) { return XprNull(); }
+
+  template<class E>
+  static inline XprNull product(const E&) { return XprNull(); }
+
+  template<class Dest, class Src>
+  static inline XprNull dot(const Dest&, const Src&) { return XprNull(); }
+
+  template<class E>
+  static inline bool all_elements(const E&) { return true; }
+
+  template<class E>
+  static inline bool any_elements(const E&) { return false; }
+};
+
+
+} // namespace meta
+
+} // namespace tvmet
+
+#endif /* TVMET_META_VECTOR_H */
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tvmet.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,239 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: tvmet.h,v 1.21 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_H
+#define TVMET_H
+
+#include <tvmet/config.h>
+
+
+/***********************************************************************
+ * Compiler specifics
+ ***********************************************************************/
+#if defined(__GNUC__)
+#  include <tvmet/config/config-gcc.h>
+#endif
+
+#if defined(__ICC)
+#  include <tvmet/config/config-icc.h>
+#endif
+
+#if defined(__KCC)
+#  include <tvmet/config/config-kcc.h>
+#endif
+
+#if defined(__PGI)
+#  include <tvmet/config/config-pgi.h>
+#endif
+
+// vc7.1: 1310 and vc7.0 1300
+#if defined(_MSC_VER) && (_MSC_VER >= 1310)
+#  include <tvmet/config/config-vc71.h>
+#endif
+
+
+// give up for these cases
+#if !defined(TVMET_HAVE_MUTABLE)
+#  error "Your compiler doesn't support the mutable keyword! Giving up."
+#endif
+
+#if !defined(TVMET_HAVE_TYPENAME)
+#  error "Your compiler doesn't support the typename keyword! Giving up."
+#endif
+
+#if !defined(TVMET_HAVE_NAMESPACES)
+#  error "Your compiler doesn't support the namespace concept! Giving up."
+#endif
+
+#if !defined(TVMET_HAVE_PARTIAL_SPECIALIZATION)
+#  error "Your compiler doesn't support partial specialization! Giving up."
+#endif
+
+
+/*
+ * other compiler specific stuff
+ */
+
+/**
+ * \def TVMET_CXX_ALWAYS_INLINE
+ * \brief Compiler specific stuff to force inline code if supported.
+ *
+ * Mainly, this declares the functions using g++'s
+ * __attribute__((always_inline)). This features is enabled
+ * on defined TVMET_OPTIMIZE.
+ */
+#if !defined(TVMET_CXX_ALWAYS_INLINE)
+#define TVMET_CXX_ALWAYS_INLINE
+#endif
+
+
+/*
+ * Complexity triggers, compiler and architecture specific.
+ * If not defined, use defaults.
+ */
+
+/**
+ * \def TVMET_COMPLEXITY_DEFAULT_TRIGGER
+ * \brief Trigger for changing the matrix-product strategy.
+ */
+#if !defined(TVMET_COMPLEXITY_DEFAULT_TRIGGER)
+#  define TVMET_COMPLEXITY_DEFAULT_TRIGGER	1000
+#endif
+
+/**
+ * \def TVMET_COMPLEXITY_M_ASSIGN_TRIGGER
+ * \brief Trigger for changing the matrix assign strategy.
+ */
+#if !defined(TVMET_COMPLEXITY_M_ASSIGN_TRIGGER)
+#  define TVMET_COMPLEXITY_M_ASSIGN_TRIGGER	8*8
+#endif
+
+/**
+ * \def TVMET_COMPLEXITY_MM_TRIGGER
+ * \brief Trigger for changing the matrix-matrix-product strategy.
+ * One strategy to build the matrix-matrix-product is to use
+ * meta templates. The other to use looping.
+ */
+#if !defined(TVMET_COMPLEXITY_MM_TRIGGER)
+#  define TVMET_COMPLEXITY_MM_TRIGGER		8*8
+#endif
+
+/**
+ * \def TVMET_COMPLEXITY_V_ASSIGN_TRIGGER
+ * \brief Trigger for changing the vector assign strategy.
+ */
+#if !defined(TVMET_COMPLEXITY_V_ASSIGN_TRIGGER)
+#  define TVMET_COMPLEXITY_V_ASSIGN_TRIGGER	8
+#endif
+
+/**
+ * \def TVMET_COMPLEXITY_MV_TRIGGER
+ * \brief Trigger for changing the matrix-vector strategy.
+ * One strategy to build the matrix-vector-product is to use
+ * meta templates. The other to use looping.
+ */
+#if !defined(TVMET_COMPLEXITY_MV_TRIGGER)
+#  define TVMET_COMPLEXITY_MV_TRIGGER		8*8
+#endif
+
+
+/***********************************************************************
+ * other specials
+ ***********************************************************************/
+#if defined(TVMET_HAVE_IEEE_MATH)
+#  define _ALL_SOURCE
+#  if !defined(_XOPEN_SOURCE)
+#    define _XOPEN_SOURCE
+#  endif
+#  if !defined(_XOPEN_SOURCE_EXTENDED)
+#    define _XOPEN_SOURCE_EXTENDED
+#  endif
+#endif
+
+
+/**
+ * \def TVMET_DEBUG
+ * This is defined if <code>DEBUG</code> is defined. This enables runtime error
+ * bounds checking. If you compile %tvmet from another source directory
+ * which defines <code>DEBUG</code>, then <code>TVMET_DEBUG</code> will be
+ * <b>not</b> defined (This behavior differs from release less than 0.6.0).
+ */
+
+
+/**
+ * \def TVMET_OPTIMIZE
+ * If this is defined tvmet uses some compiler specific keywords.
+ *  Mainly, this declares the functions using gcc's
+ * <tt>__attribute__((always_inline))</tt>. This allows the
+ * compiler to produce high efficient code even on less
+ * optimization levels, like gcc's -O2 or even -O!
+ * This is known to work with gcc v3.3.3 (and higher).
+ * Using icc's v8 gnuc compatibility mode this may work, I've read
+ * that it's using as an hint, this means you can have static inline
+ * functions inside left.
+ */
+#if !defined(TVMET_OPTIMIZE)
+#  undef  TVMET_CXX_ALWAYS_INLINE
+#  define TVMET_CXX_ALWAYS_INLINE
+#endif
+
+
+/***********************************************************************
+ * Namespaces
+ ***********************************************************************/
+
+
+/**
+ * \namespace std
+ * \brief Imported ISO/IEC 14882:1998 functions from std namespace.
+ */
+
+/**
+ * \namespace tvmet
+ * \brief The namespace for the Tiny %Vector %Matrix using Expression Templates Libary.
+ */
+
+/**
+ * \namespace tvmet::meta
+ * \brief Meta stuff inside here.
+ */
+
+/**
+ * \namespace tvmet::loop
+ * \brief Loop stuff inside here.
+ */
+
+/**
+ * \namespace tvmet::element_wise
+ * \brief Operators inside this namespace does elementwise operations.
+ */
+
+/**
+ * \namespace tvmet::util
+ * \brief Miscellaneous utility functions used.
+ */
+
+
+/***********************************************************************
+ * forwards
+ ***********************************************************************/
+#if defined(TVMET_HAVE_COMPLEX)
+namespace std {
+  template<class T> class complex;
+}
+#endif
+
+
+/***********************************************************************
+ * other stuff
+ ***********************************************************************/
+#include <tvmet/TvmetBase.h>
+
+
+#endif // TVMET_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
+// LocalWords:  gnuc gcc's icc's std
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/General.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,126 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: General.h,v 1.13 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_UTIL_GENERAL_H
+#define TVMET_UTIL_GENERAL_H
+
+
+/** forward */
+namespace tvmet {
+template<class T, std::size_t Rows, std::size_t Cols> class Matrix;
+template<class T, std::size_t Sz> class Vector;
+}
+
+namespace tvmet {
+
+namespace util {
+
+/*
+ * \defgroup _util_function
+ * \brief Usefull utility functions
+ */
+
+/**
+ * \fn Gemm(const Matrix<T, Rows, Cols>& m1, const Matrix<T, Rows, Cols>& m2, Matrix<T, Rows, Cols>& m3)
+ * \brief General matrix matrix multiplication using loops.
+ * \ingroup _util_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+void
+Gemm(const Matrix<T, Rows, Cols>& m1, const Matrix<T, Rows, Cols>& m2,
+     Matrix<T, Rows, Cols>& m3)
+{
+  for (std::size_t i = 0; i < Rows; ++i) {
+    for (std::size_t j = 0; j < Cols; ++j) {
+      T sum(0);
+      for (std::size_t k = 0; k < Cols; ++k) {
+	sum += m1(i,k) * m2(k,j);
+      }
+      m3(i,j) = sum;
+    }
+  }
+}
+
+
+/**
+ * \fn Gemv(const Matrix<T, Rows, Cols>& m, const Vector<T, Cols>& v, Vector<T, Cols>& v2)
+ * \brief General matrix vector multiplication using loops.
+ * \ingroup _util_function
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+inline
+void
+Gemv(const Matrix<T, Rows, Cols>& m, const Vector<T, Cols>& v,
+     Vector<T, Cols>& v2)
+{
+  for (std::size_t i = 0; i < Rows; ++i){
+    v2(i) = T(0);	// clean up before use
+    for (std::size_t j = 0; j < Cols; ++j) {
+      v2(i) += m(i,j) * v(j);
+      }
+  }
+}
+
+
+/**
+ * \fn Gevvmul(const Vector<T, Sz>& v1, const Vector<T, Sz>& v2, Vector<T, Sz>& v3)
+ * \brief General vector vector elementwise multiplication using loop.
+ * \ingroup _util_function
+ */
+template<class T, std::size_t Sz>
+inline
+void
+Gevvmul(const Vector<T, Sz>& v1, const Vector<T, Sz>& v2,
+       Vector<T, Sz>& v3)
+{
+  for(std::size_t i = 0; i < Sz; ++i)
+    v3(i) = v1(i) * v2(i);
+}
+
+
+/**
+ * \fn Gevvadd(const Vector<T, Sz>& v1, const Vector<T, Sz>& v2, Vector<T, Sz>& v3)
+ * \brief General vector vector elementwise multiplication using loop.
+ * \ingroup _util_function
+ */
+template<class T, std::size_t Sz>
+inline
+void
+Gevvadd(const Vector<T, Sz>& v1, const Vector<T, Sz>& v2,
+	Vector<T, Sz>& v3)
+{
+  for(std::size_t i = 0; i < Sz; ++i)
+    v3(i) = v1(i) + v2(i);
+}
+
+} // namespace util
+
+} // namespace tvmet
+
+#endif // TVMET_UTIL_GENERAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/Incrementor.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,91 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Incrementor.h,v 1.7 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_UTIL_INCREMENTOR_H
+#define TVMET_UTIL_INCREMENTOR_H
+
+namespace tvmet {
+
+namespace util {
+
+
+/**
+ * \class Incrementor Incrementor.h "tvmet/util/Incrementor.h"
+ * \brief A simple incrementor class.
+ * The start value is given at construction time. After
+ * each access the class increments the internal counter.
+ * \ingroup _util_function
+ *
+ * \par Example:
+ * \code
+ * #include <algorithm>
+ *
+ * using namespace tvmet;
+ *
+ * ...
+ *
+ * std::generate(m1.begin(), m1.end(),
+ * util::Incrementor<typename matrix_type::value_type>());
+ * \endcode
+ */
+template<class T>
+struct Incrementor
+{
+  Incrementor(T start=0) : m_inc(start) { }
+  T operator()() { m_inc+=1; return m_inc; }
+
+private:
+  T 							m_inc;
+};
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/**
+ * \class Incrementor< std::complex<T> > Incrementor.h "tvmet/util/Incrementor.h"
+ * \brief Specialized Incrementor class.
+ * \ingroup _util_function
+ */
+template<class T>
+struct Incrementor< std::complex<T> > {
+  Incrementor(const std::complex<T>& start=0)
+    : m_inc(start) { }
+  std::complex<T> operator()() {
+    m_inc += std::complex<T>(1,1);
+    return m_inc;
+  }
+private:
+  std::complex<T>       				m_inc;
+};
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace util
+
+} // namespace tvmet
+
+#endif // TVMET_UTIL_INCREMENTOR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/Random.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,101 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Random.h,v 1.7 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_UTIL_RANDOM_H
+#define TVMET_UTIL_RANDOM_H
+
+#include <tvmet/CompileTimeError.h>
+
+namespace tvmet {
+
+namespace util {
+
+
+/**
+ * \class Random Random.h "tvmet/util/Random.h"
+ * \brief A simple random class.
+ * On each access this class returns a new random number using
+ * std::rand(). The range generated is templated by MIN and
+ * MAX.
+ * \ingroup _util_function
+ *
+ * \par Example:
+ * \code
+ * #include <algorithm>
+ *
+ * tvmet::Random<int, 0, 100>				random;
+ *
+ * std::generate(m1.begin(), m1.end(), random());
+ * \endcode
+ */
+template<class T, int MIN=0, int MAX=100>
+class Random {
+  static unsigned int				s_seed;
+public:
+  typedef T					value_type;
+  Random() { TVMET_CT_CONDITION(MIN<MAX, wrong_random_range) }
+  value_type operator()() {
+    s_seed += (unsigned)std::time(0);
+    std::srand(s_seed);
+    return MIN + int(double(MAX) * std::rand()/(double(RAND_MAX)+1.0));
+  }
+};
+// instance
+template<class T, int MIN, int MAX>
+unsigned int Random<T, MIN, MAX>::s_seed;
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/**
+ * \class Random< std::complex<T> > Random.h "tvmet/util/Random.h"
+ * \brief Specialized Random class.
+ * \ingroup _util_function
+ */
+template<class T, int MIN=0, int MAX=100>
+class Random {
+  static unsigned int				s_seed;
+public:
+  typedef std::complex<T>			value_type;
+  Random() { TVMET_CT_CONDITION(MIN<MAX, wrong_random_range) }
+  value_type operator()() {
+    s_seed += (unsigned)std::time(0);
+    std::srand(s_seed);
+    return MIN + int(double(MAX) * std::rand()/(double(RAND_MAX)+1.0));
+  }
+};
+// instance
+template<class T, int MIN, int MAX>
+unsigned int Random<std::complex<T>, MIN, MAX>::s_seed;
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace util
+
+} // namespace tvmet
+
+#endif // TVMET_UTIL_RANDOM_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/util/Timer.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,98 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Timer.h,v 1.9 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_UTIL_TIMER_H
+#define TVMET_UTIL_TIMER_H
+
+#if defined(TVMET_HAVE_SYS_TIME_H) && defined(TVMET_HAVE_UNISTD_H)
+#  include <sys/time.h>
+#  include <sys/resource.h>
+#  include <unistd.h>
+#else
+#  include <ctime>
+#endif
+
+namespace tvmet {
+
+namespace util {
+
+/**
+   \class Timer Timer.h "tvmet/util/Timer.h"
+   \brief A quick& dirty portable timer, measures elapsed time.
+
+   It is recommended that implementations measure wall clock rather than CPU
+   time since the intended use is performance measurement on systems where
+   total elapsed time is more important than just process or CPU time.
+
+   The accuracy of timings depends on the accuracy of timing information
+   provided by the underlying platform, and this varies from platform to
+   platform.
+*/
+
+class Timer
+{
+  Timer(const Timer&);
+  Timer& operator=(const Timer&);
+
+public: // types
+  typedef double					time_t;
+
+public:
+  /** starts the timer immediatly. */
+  Timer() { m_start_time = getTime(); }
+
+  /** restarts the timer */
+  void restart() { m_start_time = getTime(); }
+
+  /** return elapsed time in seconds */
+  time_t elapsed() const { return (getTime() - m_start_time); }
+
+private:
+  time_t getTime() const {
+#if defined(TVMET_HAVE_SYS_TIME_H) && defined(TVMET_HAVE_UNISTD_H)
+    getrusage(RUSAGE_SELF, &m_rusage);
+    time_t sec = m_rusage.ru_utime.tv_sec; // user, no system time
+    time_t usec  = m_rusage.ru_utime.tv_usec; // user, no system time
+    return sec + usec/1e6;
+#else
+    return static_cast<time_t>(std::clock()) / static_cast<time_t>(CLOCKS_PER_SEC);
+#endif
+  }
+
+private:
+#if defined(TVMET_HAVE_SYS_TIME_H) && defined(TVMET_HAVE_UNISTD_H)
+  mutable struct rusage 				m_rusage;
+#endif
+  time_t 						m_start_time;
+};
+
+} // namespace util
+
+} // namespace tvmet
+
+#endif // TVMET_UTIL_TIMER_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/BinOperator.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,105 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: BinOperator.h,v 1.19 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_BINOPERATOR_H
+#define TVMET_XPR_BINOPERATOR_H
+
+#include <tvmet/TypePromotion.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprBinOp BinOperator.h "tvmet/xpr/BinOperator.h"
+ * \brief Binary operators working on two sub expressions.
+ *
+ * On acessing using the index operator() the binary operation will be
+ * evaluated at compile time.
+ */
+template<class BinOp, class E1, class E2>
+class XprBinOp
+  : public TvmetBase< XprBinOp<BinOp, E1, E2> >
+{
+  XprBinOp();
+  XprBinOp& operator=(const XprBinOp&);
+
+public:
+  typedef typename BinOp::value_type			value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    ops       = 2 * (ops_lhs + ops_rhs) // lhs op rhs
+  };
+
+public:
+  /** Constructor for two expressions. */
+  explicit XprBinOp(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprBinOp(const XprBinOp& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+  /** Index operator, evaluates the expression inside. */
+  value_type operator()(std::size_t i) const {
+    return BinOp::apply_on(m_lhs(i), m_rhs(i));
+  }
+
+  /** Index operator for arrays/matrices */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    return BinOp::apply_on(m_lhs(i, j), m_rhs(i, j));
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprBinOp[O="<< ops << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    BinOp::print_xpr(os, l);
+    m_lhs.print_xpr(os, l);
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1						m_lhs;
+  const E2						m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_BINOPERATOR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Eval.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,116 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Eval.h,v 1.13 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_EVAL_H
+#define TVMET_XPR_EVAL_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprEval Eval.h "tvmet/xpr/Eval.h"
+ * \brief evaluate the expression
+ *
+ * Since we can't overwrite the ? operator we have to write a wrapper
+ * for expression like return v1>v2 ? true : false
+ */
+template<class E1, class E2, class E3>
+class XprEval
+  : public TvmetBase< XprEval<E1, E2, E3> >
+{
+public:
+  typedef E1 						expr1_type;
+  typedef E2 						expr2_type;
+  typedef E3 						expr3_type;
+
+  typedef typename expr2_type::value_type 		value2_type;
+  typedef typename expr3_type::value_type 		value3_type;
+
+  typedef typename
+  PromoteTraits<value2_type, value3_type>::value_type 	value_type;
+
+public:
+  /** Complexity Counter */
+  enum {
+    ops_expr1 = E1::ops,
+    ops_expr2 = E2::ops,
+    ops_expr3 = E3::ops,
+    ops = ops_expr1	// only (e1 op e2) are evaluated
+  };
+
+private:
+  XprEval();
+  XprEval& operator=(const XprEval<expr1_type, expr2_type, expr3_type>&);
+
+public:
+  /** Constructor */
+  explicit XprEval(const expr1_type& e1, const expr2_type& e2, const expr3_type& e3)
+    : m_expr1(e1), m_expr2(e2), m_expr3(e3)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprEval(const XprEval& rhs)
+    : m_expr1(rhs.m_expr1), m_expr2(rhs.m_expr2), m_expr3(rhs.m_expr3)
+  { }
+#endif
+
+public: //access
+  /** index operator for vectors. */
+  value_type operator()(std::size_t i) const {
+    return m_expr1(i) ? m_expr2(i) : m_expr3(i);
+  }
+
+  /** index operator for matrizes. */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    return m_expr1(i, j) ? m_expr2(i, j) : m_expr3(i, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprEval[" << ops << ", ("
+       << ops_expr1 << ", " << ops_expr2 << ", " << ops_expr3 << ")]<"
+       << std::endl;
+    m_expr1.print_xpr(os, l);
+    m_expr2.print_xpr(os, l);
+    m_expr3.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const expr1_type					m_expr1;
+  const expr2_type					m_expr2;
+  const expr3_type					m_expr3;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_EVAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Identity.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,68 @@
+/*
+ * $Id: Identity.h,v 1.4 2006-11-21 18:43:09 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_IDENTITY_H
+#define TVMET_XPR_IDENTITY_H
+
+
+namespace tvmet {
+
+
+/**
+ * \class XprIdentity Identity.h "tvmet/xpr/Identity.h"
+ * \brief Expression for the identity matrix.
+ *
+ * This expression doesn't hold any other expression, it
+ * simply returns 1 or 0 depends where the row and column
+ * element excess is done.
+ *
+ * \since release 1.6.0
+ * \sa identity
+ */
+template<class T, std::size_t Rows, std::size_t Cols>
+struct XprIdentity
+  : public TvmetBase< XprIdentity<T, Rows, Cols> >
+{
+  XprIdentity& operator=(const XprIdentity&);
+
+public:
+  typedef T				value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_assign = Rows * Cols,
+    ops        = ops_assign
+  };
+
+public:
+  /** access by index. */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    return i==j ? 1 : 0;
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprIdentity[O="<< ops << ")]<"
+       << std::endl;
+    os << IndentLevel(l)
+       << typeid(T).name() << ","
+       << "R=" << Rows << ", C=" << Cols << std::endl;
+    os << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+};
+
+
+} // namespace tvmet
+
+
+#endif // TVMET_XPR_IDENTITY_H
+
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Literal.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,90 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Literal.h,v 1.13 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_LITERAL_H
+#define TVMET_XPR_LITERAL_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprLiteral Literal.h "tvmet/xpr/Literal.h"
+ * \brief Specify literals like scalars into the expression.
+ *        This expression is used for vectors and matrices - the
+ *        decision is done by the access operator.
+ */
+template<class T>
+class XprLiteral
+  : public TvmetBase< XprLiteral<T> >
+{
+  XprLiteral();
+  XprLiteral& operator=(const XprLiteral&);
+
+public:
+  typedef T						value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops       = 1
+  };
+
+public:
+  /** Constructor by value for literals . */
+  explicit XprLiteral(value_type value)
+    : m_data(value)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprLiteral(const XprLiteral& e)
+    : m_data(e.m_data)
+  { }
+#endif
+
+  /** Index operator, gives the value for vectors. */
+  value_type operator()(std::size_t) const { return m_data; }
+
+  /** Index operator for arrays/matrices. */
+  value_type operator()(std::size_t, std::size_t) const { return m_data; }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++) << "XprLiteral[O=" << ops << "]<T="
+       << typeid(value_type).name()
+       << ">," << std::endl;
+  }
+
+private:
+  const value_type 					m_data;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_LITERAL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MMProduct.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,135 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MMProduct.h,v 1.24 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MMPRODUCT_H
+#define TVMET_XPR_MMPRODUCT_H
+
+#include <tvmet/meta/Gemm.h>
+#include <tvmet/loop/Gemm.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMMProduct MMProduct.h "tvmet/xpr/MMProduct.h"
+ * \brief Expression for matrix-matrix product.
+ *        Using formula:
+ *        \f[
+ *        M_1\,M_2
+ *        \f]
+ * \note The Rows2 has to be  equal to Cols1.
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+class XprMMProduct
+  : public TvmetBase< XprMMProduct<E1, Rows1, Cols1, E2, Cols2> >
+{
+private:
+  XprMMProduct();
+  XprMMProduct& operator=(const XprMMProduct&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    M         = Rows1 * Cols1 * Cols2,
+    N         = Rows1 * (Cols1 - 1) * Cols2,
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Rows1*Cols2 < TVMET_COMPLEXITY_MM_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMMProduct(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMMProduct(const XprMMProduct& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemm(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return meta::gemm<Rows1, Cols1,
+                      Cols2,
+                      0>::prod(lhs, rhs, i, j);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemm(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return loop::gemm<Rows1, Cols1, Cols2>::prod(lhs, rhs, i, j);
+  }
+
+public:
+  /** index operator for arrays/matrices */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Rows1) && (j < Cols2), "XprMMProduct Bounce Violation")
+    return do_gemm(dispatch<use_meta>(), m_lhs, m_rhs, i, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMMProduct["
+       << (use_meta ? "M" :  "L") << ", O=" << ops
+       << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R1=" << Rows1 << ", C1=" << Cols1 << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "C2=" << Cols2 << ",\n";
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1		 				m_lhs;
+  const E2		 				m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MMPRODUCT_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MMProductTransposed.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,137 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MMProductTransposed.h,v 1.20 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MMPRODUCT_TRANSPOSED_H
+#define TVMET_XPR_MMPRODUCT_TRANSPOSED_H
+
+#include <tvmet/meta/Gemm.h>
+#include <tvmet/loop/Gemm.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMMProductTransposed MMProductTransposed.h "tvmet/xpr/MMProductTransposed.h"
+ * \brief Expression for transpose(matrix-matrix product).
+ *        Using formula:
+ *        \f[
+ *        (M_1\,M_2)^T
+ *        \f]
+ * \note The Rows2 has to be  equal to Cols1.
+ *       The result is a (Cols2 x Rows1) matrix.
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+class XprMMProductTransposed
+  : public TvmetBase< XprMMProductTransposed<E1, Rows1, Cols1, E2, Cols2> >
+{
+private:
+  XprMMProductTransposed();
+  XprMMProductTransposed& operator=(const XprMMProductTransposed&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    M = Rows1 * Cols1 * Cols2,
+    N = Rows1 * (Cols1-1) * Cols2,
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Cols2*Rows1 < TVMET_COMPLEXITY_MM_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMMProductTransposed(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs) { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMMProductTransposed(const XprMMProductTransposed& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemm(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return meta::gemm<Rows1, Cols1,
+                      Cols2,
+                      0>::prod(lhs, rhs, i, j);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemm(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return loop::gemm<Rows1, Cols1, Cols2>::prod(lhs, rhs, i, j);
+  }
+
+public:
+  /** index operator for arrays/matrices */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Cols2) && (j < Rows1), "XprMMProductTransposed Bounce Violation")
+    return do_gemm(dispatch<use_meta>(), m_lhs, m_rhs, j, i);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMMProductTransposed["
+       << (use_meta ? "M" :  "L") << ", O=" << ops
+       << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R1=" << Rows1 << ", C1=" << Cols1 << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "C2=" << Cols2 << ",\n"
+       << IndentLevel(l)
+       << "\n"
+       << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1		 				m_lhs;
+  const E2						m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MMPRODUCT_TRANSPOSED_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MMtProduct.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,138 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MMtProduct.h,v 1.20 2007-06-23 15:58:59 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MMTPRODUCT_H
+#define TVMET_XPR_MMTPRODUCT_H
+
+#include <tvmet/meta/Gemmt.h>
+#include <tvmet/loop/Gemmt.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMMtProduct MMtProduct.h "tvmet/xpr/MMtProduct.h"
+ * \brief Expression for matrix-matrix product.
+ *        Using formula:
+ *        \f[
+ *        M_1\,M_2^T
+ *        \f]
+ * \note The number of cols of rhs matrix have to be equal to cols of rhs matrix.
+ *       The result is a (Rows1 x Rows2) matrix.
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+class XprMMtProduct
+  : public TvmetBase< XprMMtProduct<E1, Rows1, Cols1, E2, Cols2> >
+{
+private:
+  XprMMtProduct();
+  XprMMtProduct& operator=(const XprMMtProduct&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    Rows2 = Cols1,
+    M = Rows1 * Cols1 * Rows1,
+    N = Rows1 * (Cols1 - 1) * Rows2,
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Rows1*Rows2 < TVMET_COMPLEXITY_MM_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMMtProduct(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMMtProduct(const XprMMtProduct& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemmt(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return meta::gemmt<Rows1, Cols1,
+                       Cols2,
+                       0>::prod(lhs, rhs, i, j);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemmt(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return loop::gemmt<Rows1, Cols1, Cols1>::prod(lhs, rhs, i, j);
+  }
+
+public:
+  /** index operator for arrays/matrices */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Rows1) && (j < Rows2), "XprMMtProduct Bounce Violation")
+    return do_gemmt(dispatch<use_meta>(), m_lhs, m_rhs, i, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMMtProduct["
+       << (use_meta ? "M" :  "L") << ", O=" << ops
+       << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R1=" << Rows1 << ", C1=" << Cols1 << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "C2=" << Cols2 << ",\n"
+       << "\n"
+       << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1		 				m_lhs;
+  const E2 						m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MMTPRODUCT_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MVProduct.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,131 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MVProduct.h,v 1.21 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MVPRODUCT_H
+#define TVMET_XPR_MVPRODUCT_H
+
+#include <tvmet/meta/Gemv.h>
+#include <tvmet/loop/Gemv.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMVProduct MVProduct.h "tvmet/xpr/MVProduct.h"
+ * \brief Expression for matrix-vector product
+ *        using formula
+ *        \f[
+ *        M\,v
+ *        \f]
+ */
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+class XprMVProduct
+  : public TvmetBase< XprMVProduct<E1, Rows, Cols, E2> >
+{
+  XprMVProduct();
+  XprMVProduct& operator=(const XprMVProduct&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    M         = Rows * Cols,
+    N         = Rows * (Cols - 1),
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Rows*Cols < TVMET_COMPLEXITY_MV_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMVProduct(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMVProduct(const XprMVProduct& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemv(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t j) {
+    return meta::gemv<Rows, Cols,
+                      0>::prod(lhs, rhs, j);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemv(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t j) {
+    return loop::gemv<Rows, Cols>::prod(lhs, rhs, j);
+  }
+
+public:
+  /** index operator, returns the expression by index. This is the vector
+      style since a matrix*vector gives a vector. */
+  value_type operator()(std::size_t j) const {
+    TVMET_RT_CONDITION(j < Rows , "XprMVProduct Bounce Violation")
+    return do_gemv(dispatch<use_meta>(), m_lhs, m_rhs, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMVProduct["
+       << (use_meta ? "M" :  "L") << ", O=" << ops
+       << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R=" << Rows << ", C=" << Cols << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1							m_lhs;
+  const E2							m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MVPRODUCT_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Matrix.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,165 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Matrix.h,v 1.26 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_H
+#define TVMET_XPR_MATRIX_H
+
+#include <tvmet/meta/Matrix.h>
+#include <tvmet/loop/Matrix.h>
+
+namespace tvmet {
+
+
+/* forwards */
+template <class T, std::size_t Rows, std::size_t Cols> class Matrix;
+
+/**
+ * \class XprMatrix Matrix.h "tvmet/xpr/Matrix.h"
+ * \brief Represents the expression for vectors at any node in the parse tree.
+ *
+ * Specifically, XprMatrix is the class that wraps the expression, and the
+ * expression itself is represented by the template parameter E. The
+ * class XprMatrix is known as an anonymizing expression wrapper because
+ * it can hold any subexpression of arbitrary complexity, allowing
+ * clients to work with any expression by holding on to it via the
+ * wrapper, without having to know the name of the type object that
+ * actually implements the expression.
+ * \note leave the CCtors non-explicit to allow implicit type conversation.
+ */
+template<class E, std::size_t NRows, std::size_t NCols>
+class XprMatrix
+  : public TvmetBase< XprMatrix<E, NRows, NCols> >
+{
+  XprMatrix();
+  XprMatrix& operator=(const XprMatrix&);
+
+public:
+  /** Dimensions. */
+  enum {
+    Rows = NRows,			/**< Number of rows. */
+    Cols = NCols,			/**< Number of cols. */
+    Size = Rows * Cols			/**< Complete Size of Matrix. */
+  };
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_assign = Rows * Cols,
+    ops        = E::ops,
+    use_meta   = ops_assign < TVMET_COMPLEXITY_M_ASSIGN_TRIGGER ? true : false
+  };
+
+public:
+  typedef typename E::value_type			value_type;
+
+public:
+  /** Constructor. */
+  explicit XprMatrix(const E& e)
+    : m_expr(e)
+  { }
+
+ /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMatrix(const XprMatrix& rhs)
+    : m_expr(rhs.m_expr)
+  { }
+#endif
+
+  /** access by index. */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Rows) && (j < Cols), "XprMatrix Bounce Violation")
+    return m_expr(i, j);
+  }
+
+private:
+  /** Wrapper for meta assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    meta::Matrix<Rows, Cols, 0, 0>::assign(dest, src, assign_fn);
+  }
+
+  /** Wrapper for loop assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    loop::Matrix<Rows, Cols>::assign(dest, src, assign_fn);
+  }
+
+public:
+  /** assign this expression to Matrix dest. */
+  template<class Dest, class Assign>
+  void assign_to(Dest& dest, const Assign& assign_fn) const {
+    /* here is a way for caching, since each complex 'Node'
+       is of type XprMatrix. */
+    do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMatrix["
+       << (use_meta ? "M" :  "L") << ", O=" << ops << "]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R=" << Rows << ", C=" << Cols << std::endl;
+    os << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+
+private:
+  const E						m_expr;
+};
+
+
+} // namespace tvmet
+
+#include <tvmet/Functional.h>
+
+#include <tvmet/xpr/BinOperator.h>
+#include <tvmet/xpr/UnOperator.h>
+#include <tvmet/xpr/Literal.h>
+
+#include <tvmet/xpr/Identity.h>
+
+#include <tvmet/xpr/MMProduct.h>
+#include <tvmet/xpr/MMProductTransposed.h>
+#include <tvmet/xpr/MMtProduct.h>
+#include <tvmet/xpr/MtMProduct.h>
+#include <tvmet/xpr/MVProduct.h>
+#include <tvmet/xpr/MtVProduct.h>
+#include <tvmet/xpr/MatrixTranspose.h>
+
+#include <tvmet/xpr/MatrixFunctions.h>
+#include <tvmet/xpr/MatrixBinaryFunctions.h>
+#include <tvmet/xpr/MatrixUnaryFunctions.h>
+#include <tvmet/xpr/MatrixOperators.h>
+#include <tvmet/xpr/Eval.h>
+
+#endif // TVMET_XPR_MATRIX_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixBinaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,318 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixBinaryFunctions.h,v 1.12 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_BINARY_FUNCTIONS_H
+#define TVMET_XPR_MATRIX_BINARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * binary_function(XprMatrix<E1, Rows, Cols>, XprMatrix<E2, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class E1, std::size_t Rows, std::size_t Cols, class E2>	\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const XprMatrix<E1, Rows, Cols>& lhs, 				\
+     const XprMatrix<E2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+TVMET_DECLARE_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+  //TVMET_DECLARE_MACRO(polar)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * binary_function(XprMatrix<E, Rows, Cols>, POD)
+ */
+#define TVMET_DECLARE_MACRO(NAME, TP)			\
+template<class E, std::size_t Rows, std::size_t Cols>	\
+XprMatrix<						\
+  XprBinOp<						\
+    Fcnl_##NAME<typename E::value_type, TP >,		\
+    XprMatrix<E, Rows, Cols>,				\
+    XprLiteral< TP >					\
+  >,							\
+  Rows, Cols						\
+>							\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, 		\
+     TP rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2, int)
+TVMET_DECLARE_MACRO(drem, int)
+TVMET_DECLARE_MACRO(fmod, int)
+TVMET_DECLARE_MACRO(hypot, int)
+TVMET_DECLARE_MACRO(jn, int)
+TVMET_DECLARE_MACRO(yn, int)
+TVMET_DECLARE_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(atan2, long long int)
+TVMET_DECLARE_MACRO(drem, long long int)
+TVMET_DECLARE_MACRO(fmod, long long int)
+TVMET_DECLARE_MACRO(hypot, long long int)
+TVMET_DECLARE_MACRO(jn, long long int)
+TVMET_DECLARE_MACRO(yn,long long int)
+TVMET_DECLARE_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(atan2, float)
+TVMET_DECLARE_MACRO(drem, float)
+TVMET_DECLARE_MACRO(fmod, float)
+TVMET_DECLARE_MACRO(hypot, float)
+TVMET_DECLARE_MACRO(jn, float)
+TVMET_DECLARE_MACRO(yn, float)
+TVMET_DECLARE_MACRO(pow, float)
+
+TVMET_DECLARE_MACRO(atan2, double)
+TVMET_DECLARE_MACRO(drem, double)
+TVMET_DECLARE_MACRO(fmod, double)
+TVMET_DECLARE_MACRO(hypot,double)
+TVMET_DECLARE_MACRO(jn, double)
+TVMET_DECLARE_MACRO(yn, double)
+TVMET_DECLARE_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(atan2, long double)
+TVMET_DECLARE_MACRO(drem, long double)
+TVMET_DECLARE_MACRO(fmod, long double)
+TVMET_DECLARE_MACRO(hypot, long double)
+TVMET_DECLARE_MACRO(jn, long double)
+TVMET_DECLARE_MACRO(yn, long double)
+TVMET_DECLARE_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * binary_function(XprMatrix<E, Rows, Cols>, std::complex<>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)				\
+template<class E, std::size_t Rows, std::size_t Cols, class T>	\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,	\
+    XprMatrix<E, Rows, Cols>,					\
+    XprLiteral< std::complex<T> >				\
+  >,								\
+  Rows, Cols							\
+>								\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, 			\
+     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(pow)
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * binary_function(XprMatrix<E1, Rows, Cols>, XprMatrix<E2, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)							\
+template<class E1, std::size_t Rows, std::size_t Cols, class E2>			\
+inline											\
+XprMatrix<										\
+  XprBinOp<										\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,			\
+    XprMatrix<E1, Rows, Cols>,								\
+    XprMatrix<E2, Rows, Cols>								\
+  >,											\
+  Rows, Cols										\
+>											\
+NAME(const XprMatrix<E1, Rows, Cols>& lhs, const XprMatrix<E2, Rows, Cols>& rhs) {	\
+  typedef XprBinOp<									\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,			\
+    XprMatrix<E1, Rows, Cols>,								\
+    XprMatrix<E2, Rows, Cols>								\
+  >		    					expr_type;			\
+  return XprMatrix<expr_type, Rows, Cols>(						\
+    expr_type(lhs, rhs));								\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+TVMET_IMPLEMENT_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+  //TVMET_IMPLEMENT_MACRO(polar)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * binary_function(XprMatrix<E, Rows, Cols>, POD)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, TP)					\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< TP >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, TP rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< TP >(rhs)));				\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2, int)
+TVMET_IMPLEMENT_MACRO(drem, int)
+TVMET_IMPLEMENT_MACRO(fmod, int)
+TVMET_IMPLEMENT_MACRO(hypot, int)
+TVMET_IMPLEMENT_MACRO(jn, int)
+TVMET_IMPLEMENT_MACRO(yn, int)
+TVMET_IMPLEMENT_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(atan2, long long int)
+TVMET_IMPLEMENT_MACRO(drem, long long int)
+TVMET_IMPLEMENT_MACRO(fmod, long long int)
+TVMET_IMPLEMENT_MACRO(hypot, long long int)
+TVMET_IMPLEMENT_MACRO(jn, long long int)
+TVMET_IMPLEMENT_MACRO(yn,long long int)
+TVMET_IMPLEMENT_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(atan2, float)
+TVMET_IMPLEMENT_MACRO(drem, float)
+TVMET_IMPLEMENT_MACRO(fmod, float)
+TVMET_IMPLEMENT_MACRO(hypot, float)
+TVMET_IMPLEMENT_MACRO(jn, float)
+TVMET_IMPLEMENT_MACRO(yn, float)
+TVMET_IMPLEMENT_MACRO(pow, float)
+
+TVMET_IMPLEMENT_MACRO(atan2, double)
+TVMET_IMPLEMENT_MACRO(drem, double)
+TVMET_IMPLEMENT_MACRO(fmod, double)
+TVMET_IMPLEMENT_MACRO(hypot,double)
+TVMET_IMPLEMENT_MACRO(jn, double)
+TVMET_IMPLEMENT_MACRO(yn, double)
+TVMET_IMPLEMENT_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(atan2, long double)
+TVMET_IMPLEMENT_MACRO(drem, long double)
+TVMET_IMPLEMENT_MACRO(fmod, long double)
+TVMET_IMPLEMENT_MACRO(hypot, long double)
+TVMET_IMPLEMENT_MACRO(jn, long double)
+TVMET_IMPLEMENT_MACRO(yn, long double)
+TVMET_IMPLEMENT_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * binary_function(XprMatrix<E, Rows, Cols>, std::complex<>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E, std::size_t Rows, std::size_t Cols, class T>		\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME(const XprMatrix<E, Rows, Cols>& lhs, const std::complex<T>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}
+
+TVMET_IMPLEMENT_MACRO(pow)
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_BINARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixCol.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,96 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixCol.h,v 1.19 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_COL_H
+#define TVMET_XPR_MATRIX_COL_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprMatrixCol MatrixCol.h "tvmet/xpr/MatrixCol.h"
+ * \brief Expression on matrix used for access on the column vector.
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+class XprMatrixCol
+  : public TvmetBase< XprMatrixCol<E, Rows, Cols> >
+{
+  XprMatrixCol();
+  XprMatrixCol& operator=(const XprMatrixCol&);
+
+public:
+  typedef typename E::value_type			value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_expr  = E::ops,
+    ops       = ops_expr/Cols	// equal Row accesses
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMatrixCol(const E& e, std::size_t no)
+    : m_expr(e), m_col(no)
+  {
+    TVMET_RT_CONDITION(no < Cols, "XprMatrixCol Bounce Violation")
+  }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMatrixCol(const XprMatrixCol& e)
+    : m_expr(e.m_expr), m_col(e.m_col)
+  { }
+#endif
+
+  value_type operator()(std::size_t i) const {
+    TVMET_RT_CONDITION(i < Rows, "XprMatrixCol Bounce Violation")
+    return m_expr(i, m_col);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMatrixCol[O=" << ops << ", (O=" << ops_expr << ")]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R=" << Rows << ", C=" << Cols << std::endl
+       << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+
+private:
+  const E						m_expr;
+  const std::size_t					m_col;
+};
+
+
+}
+
+#endif // TVMET_XPR_MATRIX_COL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixDiag.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,94 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixDiag.h,v 1.17 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_DIAG_H
+#define TVMET_XPR_MATRIX_DIAG_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprMatrixDiag MatrixDiag.h "tvmet/xpr/MatrixDiag.h"
+ * \brief Expression on matrix used for access on the diagonal vector.
+ */
+template<class E, std::size_t Sz>
+class XprMatrixDiag
+  : public TvmetBase< XprMatrixDiag<E, Sz> >
+{
+  XprMatrixDiag();
+  XprMatrixDiag& operator=(const XprMatrixDiag<E, Sz>&);
+
+public:
+  typedef typename E::value_type			value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_expr  = E::ops,
+    ops       = ops_expr/Sz
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMatrixDiag(const E& e)
+    : m_expr(e)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMatrixDiag(const XprMatrixDiag& e)
+    : m_expr(e.m_expr)
+  { }
+#endif
+
+  /** index operator for arrays/matrizes */
+  value_type operator()(std::size_t i) const {
+    TVMET_RT_CONDITION(i < Sz, "XprMatrixDiag Bounce Violation")
+    return m_expr(i, i);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMatrixDiag[O=" << ops << ", (O=" << ops_expr << ")]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "Sz=" << Sz << std::endl
+       << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+
+private:
+  const E						m_expr;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_DIAG_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,761 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixFunctions.h,v 1.44 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_FUNCTIONS_H
+#define TVMET_XPR_MATRIX_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/* forwards */
+template<class T, std::size_t Rows, std::size_t Cols> class Matrix;
+template<class T, std::size_t Sz> class Vector;
+template<class E, std::size_t Sz> class XprVector;
+template<class E> class XprMatrixTranspose;
+template<class E, std::size_t Sz> class XprMatrixDiag;
+template<class E, std::size_t Rows, std::size_t Cols> class XprMatrixRow;
+template<class E, std::size_t Rows, std::size_t Cols> class XprMatrixCol;
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(XprMatrix<E1, Rows, Cols>, XprMatrix<E2, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Rows, std::size_t Cols>	\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E1, Rows, Cols>& lhs,				\
+      const XprMatrix<E2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)			// per se element wise
+TVMET_DECLARE_MACRO(sub)			// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mul)			// not defined for matrizes
+  TVMET_DECLARE_MACRO(div)			// not defined for matrizes
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * function(XprMatrix<E, Rows, Cols>, POD)
+ * function(POD, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, POD)					\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, POD >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< POD >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E, Rows, Cols>& lhs, 				\
+      POD rhs) TVMET_CXX_ALWAYS_INLINE;					\
+									\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, typename E::value_type>,				\
+    XprLiteral< POD >,							\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (POD lhs, 								\
+      const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, int)
+TVMET_DECLARE_MACRO(sub, int)
+TVMET_DECLARE_MACRO(mul, int)
+TVMET_DECLARE_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, long long int)
+TVMET_DECLARE_MACRO(sub, long long int)
+TVMET_DECLARE_MACRO(mul, long long int)
+TVMET_DECLARE_MACRO(div, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, float)
+TVMET_DECLARE_MACRO(sub, float)
+TVMET_DECLARE_MACRO(mul, float)
+TVMET_DECLARE_MACRO(div, float)
+
+TVMET_DECLARE_MACRO(add, double)
+TVMET_DECLARE_MACRO(sub, double)
+TVMET_DECLARE_MACRO(mul, double)
+TVMET_DECLARE_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, long double)
+TVMET_DECLARE_MACRO(sub, long double)
+TVMET_DECLARE_MACRO(mul, long double)
+TVMET_DECLARE_MACRO(div, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(XprMatrix<E, Rows, Cols>, complex<T>)
+ * function(complex<T>, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class E, class T, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E, Rows, Cols>& lhs,				\
+      const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+									\
+template<class T, class E, std::size_t Rows, std::size_t Cols>		\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const std::complex<T>& lhs,					\
+      const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)
+TVMET_DECLARE_MACRO(sub)
+TVMET_DECLARE_MACRO(mul)
+TVMET_DECLARE_MACRO(div)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2					// return Dim
+>
+prod(const XprMatrix<E1, Rows1, Cols1>& lhs,
+     const XprMatrix<E2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+XprMatrix<
+  XprMMProductTransposed<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Cols2, Rows1					// return Dim
+>
+trans_prod(const XprMatrix<E1, Rows1, Cols1>& lhs,
+	   const XprMatrix<E2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>	// Rows2 = Rows1
+XprMatrix<
+  XprMtMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Rows1, Cols2>, Cols2		// M2(Rows1, Cols2)
+  >,
+  Cols1, Cols2					// return Dim
+>
+MtM_prod(const XprMatrix<E1, Rows1, Cols1>& lhs,
+	 const XprMatrix<E2, Rows1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Rows2> 		// Cols2 = Cols1
+XprMatrix<
+  XprMMtProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Rows2, Cols1>, Cols1 		// M2(Rows2, Cols1)
+  >,
+  Rows1, Rows2					// return Dim
+>
+MMt_prod(const XprMatrix<E1, Rows1, Cols1>& lhs,
+	 const XprMatrix<E2, Rows2, Cols1>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+prod(const XprMatrix<E1, Rows, Cols>& lhs,
+     const XprVector<E2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+XprMatrix<
+  XprMatrixTranspose<
+    XprMatrix<E, Rows, Cols>
+  >,
+  Cols, Rows
+>
+trans(const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename NumericTraits<typename E::value_type>::sum_type
+trace(const XprMatrix<E, Sz, Sz>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMatrixRow<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >,
+  Cols
+>
+row(const XprMatrix<E, Rows, Cols>& m,
+    std::size_t no) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Rows, std::size_t Cols>
+XprVector<
+  XprMatrixCol<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >,
+  Rows
+>
+col(const XprMatrix<E, Rows, Cols>& m, std::size_t no) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+XprVector<
+  XprMatrixDiag<
+    XprMatrix<E, Sz, Sz>,
+    Sz
+  >,
+  Sz
+>
+diag(const XprMatrix<E, Sz, Sz>& m) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(XprMatrix<E1, Rows, Cols>, XprMatrix<E2, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Rows, std::size_t Cols>	\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E1, Rows, Cols>& lhs, 				\
+      const XprMatrix<E2, Rows, Cols>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  > 							 expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(lhs, rhs));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add)			// per se element wise
+TVMET_IMPLEMENT_MACRO(sub)			// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mul)			// not defined for matrizes
+  TVMET_IMPLEMENT_MACRO(div)			// not defined for matrizes
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * function(XprMatrix<E, Rows, Cols>, POD)
+ * function(POD, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, POD >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< POD >							\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E, Rows, Cols>& lhs, POD rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, POD >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< POD >							\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< POD >(rhs)));				\
+}									\
+									\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, typename E::value_type>,				\
+    XprLiteral< POD >,							\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (POD lhs, const XprMatrix<E, Rows, Cols>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< POD, typename E::value_type>,				\
+    XprLiteral< POD >,							\
+    XprMatrix<E, Rows, Cols>						\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< POD >(lhs), rhs));				\
+}
+
+TVMET_IMPLEMENT_MACRO(add, int)
+TVMET_IMPLEMENT_MACRO(sub, int)
+TVMET_IMPLEMENT_MACRO(mul, int)
+TVMET_IMPLEMENT_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, long long int)
+TVMET_IMPLEMENT_MACRO(sub, long long int)
+TVMET_IMPLEMENT_MACRO(mul, long long int)
+TVMET_IMPLEMENT_MACRO(div, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, float)
+TVMET_IMPLEMENT_MACRO(sub, float)
+TVMET_IMPLEMENT_MACRO(mul, float)
+TVMET_IMPLEMENT_MACRO(div, float)
+
+TVMET_IMPLEMENT_MACRO(add, double)
+TVMET_IMPLEMENT_MACRO(sub, double)
+TVMET_IMPLEMENT_MACRO(mul, double)
+TVMET_IMPLEMENT_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, long double)
+TVMET_IMPLEMENT_MACRO(sub, long double)
+TVMET_IMPLEMENT_MACRO(mul, long double)
+TVMET_IMPLEMENT_MACRO(div, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(XprMatrix<E, Rows, Cols>, complex<T>)
+ * function(complex<T>, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E, class T, std::size_t Rows, std::size_t Cols>		\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const XprMatrix<E, Rows, Cols>& lhs, 				\
+      const std::complex<T>& rhs) {					\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}									\
+									\
+template<class T, class E, std::size_t Rows, std::size_t Cols>		\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+NAME (const std::complex<T>& lhs, 					\
+      const XprMatrix<E, Rows, Cols>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprMatrix<E, Rows, Cols>						\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add)
+TVMET_IMPLEMENT_MACRO(sub)
+TVMET_IMPLEMENT_MACRO(mul)
+TVMET_IMPLEMENT_MACRO(div)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of two XprMatrix.
+ * Perform on given Matrix M1 and M2:
+ * \f[
+ * M_1\,M_2
+ * \f]
+ * \note The numer of Rows2 has to be equal to Cols1.
+ * \ingroup _binary_function
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >,
+  Rows1, Cols2					// return Dim
+>
+prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs) {
+  typedef XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Cols2>(expr_type(lhs, rhs));
+}
+
+
+/**
+ * \fn trans_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Function for the trans(matrix-matrix-product)
+ * Perform on given Matrix M1 and M2:
+ * \f[
+ * (M_1\,M_2)^T
+ * \f]
+ * \note The numer of Rows2 has to be equal to Cols1.
+ * \ingroup _binary_function
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProductTransposed<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Cols2, Rows1					// return Dim
+>
+trans_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs) {
+  typedef XprMMProductTransposed<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Cols1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Cols2, Rows1>(expr_type(lhs, rhs));
+}
+
+
+/**
+ * \fn MtM_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Rows1, Cols2>& rhs)
+ * \brief Function for the trans(matrix)-matrix-product.
+ *        using formula
+ *        \f[
+ *        M_1^{T}\,M_2
+ *        \f]
+ * \note The number of cols of matrix 2 have to be equal to number of rows of
+ *       matrix 1, since matrix 1 is trans - the result is a (Cols1 x Cols2)
+ *       matrix.
+ * \ingroup _binary_function
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>	// Rows2 = Rows1
+inline
+XprMatrix<
+  XprMtMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Rows1, Cols2>, Cols2		// M2(Rows1, Cols2)
+  >,
+  Cols1, Cols2					// return Dim
+>
+MtM_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Rows1, Cols2>& rhs) {
+  typedef XprMtMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Rows1, Cols2>, Cols2
+  >							expr_type;
+  return XprMatrix<expr_type, Cols1, Cols2>(expr_type(lhs, rhs));
+}
+
+
+/**
+ * \fn MMt_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Rows2, Cols1>& rhs)
+ * \brief Function for the matrix-trans(matrix)-product.
+ * \ingroup _binary_function
+ * \note The cols2 has to be equal to cols1.
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Rows2> // Cols2 = Cols1
+inline
+XprMatrix<
+  XprMMtProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Rows2, Cols1>, Cols1	 	// M2(Rows2, Cols1)
+  >,
+  Rows1, Rows2					// return Dim
+>
+MMt_prod(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Rows2, Cols1>& rhs) {
+  typedef XprMMtProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,
+    XprMatrix<E2, Rows2, Cols1>, Cols1
+  >							expr_type;
+  return XprMatrix<expr_type, Rows1, Rows2>(expr_type(lhs, rhs));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn prod(const XprMatrix<E1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs)
+ * \brief Evaluate the product of XprMatrix and XprVector.
+ * \ingroup _binary_function
+ */
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+inline
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+prod(const XprMatrix<E1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs) {
+  typedef XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >							expr_type;
+  return XprVector<expr_type, Rows>(expr_type(lhs, rhs));
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn trans(const XprMatrix<E, Rows, Cols>& rhs)
+ * \brief Transpose an expression matrix.
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+XprMatrix<
+  XprMatrixTranspose<
+    XprMatrix<E, Rows, Cols>
+  >,
+  Cols, Rows
+>
+trans(const XprMatrix<E, Rows, Cols>& rhs) {
+  typedef XprMatrixTranspose<
+    XprMatrix<E, Rows, Cols>
+  >							expr_type;
+  return XprMatrix<expr_type, Cols, Rows>(expr_type(rhs));
+}
+
+
+/*
+ * \fn trace(const XprMatrix<E, Sz, Sz>& m)
+ * \brief Compute the trace of a square matrix.
+ * \ingroup _unary_function
+ *
+ * Simply compute the trace of the given matrix expression as:
+ * \f[
+ *  \sum_{k = 0}^{Sz-1} m(k, k)
+ * \f]
+ */
+template<class E, std::size_t Sz>
+inline
+typename NumericTraits<typename E::value_type>::sum_type
+trace(const XprMatrix<E, Sz, Sz>& m) {
+  return meta::Matrix<Sz, Sz, 0, 0>::trace(m);
+}
+
+
+/**
+ * \fn row(const XprMatrix<E, Rows, Cols>& m, std::size_t no)
+ * \brief Returns a row vector of the given matrix.
+ * \ingroup _binary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMatrixRow<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >,
+  Cols
+>
+row(const XprMatrix<E, Rows, Cols>& m, std::size_t no) {
+  typedef XprMatrixRow<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >							expr_type;
+
+  return XprVector<expr_type, Cols>(expr_type(m, no));
+}
+
+
+/**
+ * \fn col(const XprMatrix<E, Rows, Cols>& m, std::size_t no)
+ * \brief Returns a column vector of the given matrix.
+ * \ingroup _binary_function
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+inline
+XprVector<
+  XprMatrixCol<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >,
+  Rows
+>
+col(const XprMatrix<E, Rows, Cols>& m, std::size_t no) {
+  typedef XprMatrixCol<
+    XprMatrix<E, Rows, Cols>,
+    Rows, Cols
+  >							expr_type;
+
+  return XprVector<expr_type, Cols>(expr_type(m, no));
+}
+
+
+/**
+ * \fn diag(const XprMatrix<E, Sz, Sz>& m)
+ * \brief Returns the diagonal vector of the given square matrix.
+ * \ingroup _unary_function
+ */
+template<class E, std::size_t Sz>
+inline
+XprVector<
+  XprMatrixDiag<
+    XprMatrix<E, Sz, Sz>,
+    Sz
+  >,
+  Sz
+>
+diag(const XprMatrix<E, Sz, Sz>& m) {
+  typedef XprMatrixDiag<
+    XprMatrix<E, Sz, Sz>,
+  Sz> 						expr_type;
+
+  return XprVector<expr_type, Sz>(expr_type(m));
+}
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixOperators.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,947 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixOperators.h,v 1.23 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_OPERATORS_H
+#define TVMET_XPR_MATRIX_OPERATORS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1,Cols2>& rhs)
+ *
+ * Note: operations +,-,*,/ are per se element wise. Further more,
+ * element wise operations make sense only for matrices of the same
+ * size [varg].
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class E1, std::size_t Rows1, std::size_t Cols1,			\
+         class E2>								\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,		\
+    XprMatrix<E1, Rows1, Cols1>,						\
+    XprMatrix<E2, Rows1, Cols1>							\
+  >,										\
+  Rows1, Cols1									\
+>										\
+operator OP (const XprMatrix<E1, Rows1, Cols1>& lhs,				\
+	     const XprMatrix<E2, Rows1, Cols1>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)		// per se element wise
+TVMET_DECLARE_MACRO(sub, -)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mul, *)		// see as prod()
+  TVMET_DECLARE_MACRO(div, /)		// not defined for matrizes, must be element_wise
+}
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * operator(XprMatrix<E, Rows, Cols>,  POD)
+ * operator(POD, XprMatrix<E, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, POD)					\
+template<class E, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, POD >,					\
+    XprMatrix<E, Rows, Cols>,							\
+    XprLiteral< POD >								\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 				\
+	     POD rhs) TVMET_CXX_ALWAYS_INLINE;					\
+										\
+template<class E,std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<POD, typename E::value_type>,					\
+    XprLiteral< POD >,								\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (POD lhs, 								\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +, int)
+TVMET_DECLARE_MACRO(sub, -, int)
+TVMET_DECLARE_MACRO(mul, *, int)
+TVMET_DECLARE_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, +, long long int)
+TVMET_DECLARE_MACRO(sub, -, long long int)
+TVMET_DECLARE_MACRO(mul, *, long long int)
+TVMET_DECLARE_MACRO(div, /, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(add, +, float)
+TVMET_DECLARE_MACRO(sub, -, float)
+TVMET_DECLARE_MACRO(mul, *, float)
+TVMET_DECLARE_MACRO(div, /, float)
+
+TVMET_DECLARE_MACRO(add, +, double)
+TVMET_DECLARE_MACRO(sub, -, double)
+TVMET_DECLARE_MACRO(mul, *, double)
+TVMET_DECLARE_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, +, long double)
+TVMET_DECLARE_MACRO(sub, -, long double)
+TVMET_DECLARE_MACRO(mul, *, long double)
+TVMET_DECLARE_MACRO(div, /, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprMatrix<E, Rows, Cols>, complex<>)
+ * operator(complex<>, XprMatrix<E, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class E, std::size_t Rows, std::size_t Cols, class T>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,			\
+    XprMatrix<E, Rows, Cols>,							\
+    XprLiteral< std::complex<T> >						\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs,				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class E, std::size_t Rows, std::size_t Cols, class T>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,			\
+    XprLiteral< std::complex<T> >,						\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const std::complex<T>& lhs,					\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)
+TVMET_DECLARE_MACRO(sub, -)
+TVMET_DECLARE_MACRO(mul, *)
+TVMET_DECLARE_MACRO(div, /)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific operator*() = prod() operations
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of two XprMatrix.
+ * \ingroup _binary_operator
+ * \sa prod(XprMatrix<E1, Rows1, Cols1> lhs, XprMatrix<E2, Cols1, Cols2> rhs)
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2
+>
+operator*(const XprMatrix<E1, Rows1, Cols1>& lhs,
+	  const XprMatrix<E2, Cols1, Cols2>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs)
+ * \brief Evaluate the product of XprMatrix and XprVector.
+ * \ingroup _binary_operator
+ * \sa prod(XprMatrix<E1, Rows, Cols> lhs, XprVector<E2, Cols> rhs)
+ */
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+operator*(const XprMatrix<E1, Rows, Cols>& lhs,
+	  const XprVector<E2, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprMatrix<>, XprMatrix<>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class E1, std::size_t Rows, std::size_t Cols,				\
+         class E2>								\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,		\
+    XprMatrix<E1, Rows, Cols>,							\
+    XprMatrix<E2, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E1, Rows, Cols>& lhs, 				\
+	     const XprMatrix<E2, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you will get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %)
+  TVMET_DECLARE_MACRO(bitxor, ^)
+  TVMET_DECLARE_MACRO(bitand, &)
+  TVMET_DECLARE_MACRO(bitor, |)
+  TVMET_DECLARE_MACRO(shl, <<)
+  TVMET_DECLARE_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprMatrix<E, Rows, Cols>, std::complex<>)
+ * operator(std::complex<>, XprMatrix<E, Rows, Cols>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template<class E, std::size_t Rows, std::size_t Cols, class T>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,			\
+    XprMatrix<E, Rows, Cols>,							\
+    XprLiteral< std::complex<T> >						\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;		\
+										\
+template<class E, std::size_t Rows, std::size_t Cols, class T>			\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,			\
+    XprLiteral< std::complex<T> >,						\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const std::complex<T>& lhs, 					\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(XprMatrix<E, Rows, Cols>, POD)
+ * operator(POD, XprMatrix<E, Rows, Cols>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, TP)					\
+template<class E, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<typename E::value_type, TP >,					\
+    XprMatrix<E, Rows, Cols>,							\
+    XprLiteral< TP >								\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 				\
+	     TP rhs) TVMET_CXX_ALWAYS_INLINE;					\
+										\
+template<class E, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprBinOp<									\
+    Fcnl_##NAME<TP, typename E::value_type>,					\
+    XprLiteral< TP >,								\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (TP lhs, 								\
+	     const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you will get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, int)
+  TVMET_DECLARE_MACRO(bitxor, ^, int)
+  TVMET_DECLARE_MACRO(bitand, &, int)
+  TVMET_DECLARE_MACRO(bitor, |, int)
+  TVMET_DECLARE_MACRO(shl, <<, int)
+  TVMET_DECLARE_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, int)
+TVMET_DECLARE_MACRO(less, <, int)
+TVMET_DECLARE_MACRO(greater_eq, >=, int)
+TVMET_DECLARE_MACRO(less_eq, <=, int)
+TVMET_DECLARE_MACRO(eq, ==, int)
+TVMET_DECLARE_MACRO(not_eq, !=, int)
+TVMET_DECLARE_MACRO(and, &&, int)
+TVMET_DECLARE_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, long long int)
+  TVMET_DECLARE_MACRO(bitxor, ^, long long int)
+  TVMET_DECLARE_MACRO(bitand, &, long long int)
+  TVMET_DECLARE_MACRO(bitor, |, long long int)
+  TVMET_DECLARE_MACRO(shl, <<, long long int)
+  TVMET_DECLARE_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long long int)
+TVMET_DECLARE_MACRO(less, <, long long int)
+TVMET_DECLARE_MACRO(greater_eq, >=, long long int)
+TVMET_DECLARE_MACRO(less_eq, <=, long long int)
+TVMET_DECLARE_MACRO(eq, ==, long long int)
+TVMET_DECLARE_MACRO(not_eq, !=, long long int)
+TVMET_DECLARE_MACRO(and, &&, long long int)
+TVMET_DECLARE_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, float)
+TVMET_DECLARE_MACRO(less, <, float)
+TVMET_DECLARE_MACRO(greater_eq, >=, float)
+TVMET_DECLARE_MACRO(less_eq, <=, float)
+TVMET_DECLARE_MACRO(eq, ==, float)
+TVMET_DECLARE_MACRO(not_eq, !=, float)
+TVMET_DECLARE_MACRO(and, &&, float)
+TVMET_DECLARE_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, double)
+TVMET_DECLARE_MACRO(less, <, double)
+TVMET_DECLARE_MACRO(greater_eq, >=, double)
+TVMET_DECLARE_MACRO(less_eq, <=, double)
+TVMET_DECLARE_MACRO(eq, ==, double)
+TVMET_DECLARE_MACRO(not_eq, !=, double)
+TVMET_DECLARE_MACRO(and, &&, double)
+TVMET_DECLARE_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long double)
+TVMET_DECLARE_MACRO(less, <, long double)
+TVMET_DECLARE_MACRO(greater_eq, >=, long double)
+TVMET_DECLARE_MACRO(less_eq, <=, long double)
+TVMET_DECLARE_MACRO(eq, ==, long double)
+TVMET_DECLARE_MACRO(not_eq, !=, long double)
+TVMET_DECLARE_MACRO(and, &&, long double)
+TVMET_DECLARE_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(const XprMatrix<E, Rows, Cols>& m)
+ * Note: per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)						\
+template <class E, std::size_t Rows, std::size_t Cols>				\
+XprMatrix<									\
+  XprUnOp<									\
+    Fcnl_##NAME<typename E::value_type>,					\
+    XprMatrix<E, Rows, Cols>							\
+  >,										\
+  Rows, Cols									\
+>										\
+operator OP (const XprMatrix<E, Rows, Cols>& m) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(not, !)
+TVMET_DECLARE_MACRO(compl, ~)
+TVMET_DECLARE_MACRO(neg, -)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1,Cols2>& rhs)
+ *
+ * Note: operations +,-,*,/ are per se element wise. Further more,
+ * element wise operations make sense only for matrices of the same
+ * size [varg].
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E1, std::size_t Rows1, std::size_t Cols1,		\
+         class E2>							\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows1, Cols1>,					\
+    XprMatrix<E2, Rows1, Cols1>						\
+  >,									\
+  Rows1, Cols1								\
+>									\
+operator OP (const XprMatrix<E1, Rows1, Cols1>& lhs, 			\
+	     const XprMatrix<E2, Rows1, Cols1>& rhs) {			\
+  return NAME (lhs, rhs);						\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mul, *)		// see as prod()
+  TVMET_IMPLEMENT_MACRO(div, /)		// not defined for matrizes, must be element_wise
+}
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * operator(XprMatrix<E, Rows, Cols>,  POD)
+ * operator(POD, XprMatrix<E, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, POD)			\
+template<class E, std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, POD >,			\
+    XprMatrix<E, Rows, Cols>,					\
+    XprLiteral< POD >						\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, POD rhs) {	\
+  return NAME (lhs, rhs);					\
+}								\
+								\
+template<class E,std::size_t Rows, std::size_t Cols>		\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<POD, typename E::value_type>,			\
+    XprLiteral< POD >,						\
+    XprMatrix<E, Rows, Cols>					\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (POD lhs, const XprMatrix<E, Rows, Cols>& rhs) {	\
+  return NAME (lhs, rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +, int)
+TVMET_IMPLEMENT_MACRO(sub, -, int)
+TVMET_IMPLEMENT_MACRO(mul, *, int)
+TVMET_IMPLEMENT_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, +, long long int)
+TVMET_IMPLEMENT_MACRO(sub, -, long long int)
+TVMET_IMPLEMENT_MACRO(mul, *, long long int)
+TVMET_IMPLEMENT_MACRO(div, /, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(add, +, float)
+TVMET_IMPLEMENT_MACRO(sub, -, float)
+TVMET_IMPLEMENT_MACRO(mul, *, float)
+TVMET_IMPLEMENT_MACRO(div, /, float)
+
+TVMET_IMPLEMENT_MACRO(add, +, double)
+TVMET_IMPLEMENT_MACRO(sub, -, double)
+TVMET_IMPLEMENT_MACRO(mul, *, double)
+TVMET_IMPLEMENT_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, +, long double)
+TVMET_IMPLEMENT_MACRO(sub, -, long double)
+TVMET_IMPLEMENT_MACRO(mul, *, long double)
+TVMET_IMPLEMENT_MACRO(div, /, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprMatrix<E, Rows, Cols>, complex<>)
+ * operator(complex<>, XprMatrix<E, Rows, Cols>)
+ * Note: operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				\
+template<class E, std::size_t Rows, std::size_t Cols, class T>	\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,	\
+    XprMatrix<E, Rows, Cols>,					\
+    XprLiteral< std::complex<T> >				\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs,		\
+	     const std::complex<T>& rhs) {			\
+  return NAME (lhs, rhs);					\
+}								\
+								\
+template<class E, std::size_t Rows, std::size_t Cols, class T>	\
+inline								\
+XprMatrix<							\
+  XprBinOp<							\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,	\
+    XprLiteral< std::complex<T> >,				\
+    XprMatrix<E, Rows, Cols>					\
+  >,								\
+  Rows, Cols							\
+>								\
+operator OP (const std::complex<T>& lhs,			\
+	     const XprMatrix<E, Rows, Cols>& rhs) {		\
+  return NAME (lhs, rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)
+TVMET_IMPLEMENT_MACRO(sub, -)
+TVMET_IMPLEMENT_MACRO(mul, *)
+TVMET_IMPLEMENT_MACRO(div, /)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix specific operator*() = prod() operations
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs)
+ * \brief Evaluate the product of two XprMatrix.
+ * \ingroup _binary_operator
+ * \sa prod(XprMatrix<E1, Rows1, Cols1> lhs, XprMatrix<E2, Cols1, Cols2> rhs)
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+inline
+XprMatrix<
+  XprMMProduct<
+    XprMatrix<E1, Rows1, Cols1>, Rows1, Cols1,	// M1(Rows1, Cols1)
+    XprMatrix<E2, Cols1, Cols2>, Cols2		// M2(Cols1, Cols2)
+  >,
+  Rows1, Cols2
+>
+operator*(const XprMatrix<E1, Rows1, Cols1>& lhs, const XprMatrix<E2, Cols1, Cols2>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * matrix-vector specific prod( ... ) operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn operator*(const XprMatrix<E1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs)
+ * \brief Evaluate the product of XprMatrix and XprVector.
+ * \ingroup _binary_operator
+ * \sa prod(XprMatrix<E1, Rows, Cols> lhs, XprVector<E2, Cols> rhs)
+ */
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+inline
+XprVector<
+  XprMVProduct<
+    XprMatrix<E1, Rows, Cols>, Rows, Cols,
+    XprVector<E2, Cols>
+  >,
+  Rows
+>
+operator*(const XprMatrix<E1, Rows, Cols>& lhs, const XprVector<E2, Cols>& rhs) {
+  return prod(lhs, rhs);
+}
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Matrix integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprMatrix<>, XprMatrix<>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E1, std::size_t Rows, std::size_t Cols,			\
+         class E2>							\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const XprMatrix<E1, Rows, Cols>& lhs, 			\
+	     const XprMatrix<E2, Rows, Cols>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprMatrix<E1, Rows, Cols>,						\
+    XprMatrix<E2, Rows, Cols>						\
+  >		    					expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(lhs, rhs));		\
+}
+
+// integer operators only, e.g used on double you will get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^)
+  TVMET_IMPLEMENT_MACRO(bitand, &)
+  TVMET_IMPLEMENT_MACRO(bitor, |)
+  TVMET_IMPLEMENT_MACRO(shl, <<)
+  TVMET_IMPLEMENT_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprMatrix<E, Rows, Cols>, std::complex<>)
+ * operator(std::complex<>, XprMatrix<E, Rows, Cols>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E, std::size_t Rows, std::size_t Cols, class T>		\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, 			\
+	     const std::complex<T>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}									\
+									\
+template<class E, std::size_t Rows, std::size_t Cols, class T>		\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const std::complex<T>& lhs, 				\
+	     const XprMatrix<E, Rows, Cols>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprMatrix<E, Rows, Cols>						\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs));		\
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*
+ * operator(XprMatrix<E, Rows, Cols>, POD)
+ * operator(POD, XprMatrix<E, Rows, Cols>)
+ * Note: operations are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, TP)				\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< TP >							\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const XprMatrix<E, Rows, Cols>& lhs, TP rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprMatrix<E, Rows, Cols>,						\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(lhs, XprLiteral< TP >(rhs)));				\
+}									\
+									\
+template<class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprBinOp<								\
+    Fcnl_##NAME<TP, typename E::value_type>,				\
+    XprLiteral< TP >,							\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (TP lhs, const XprMatrix<E, Rows, Cols>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< TP, typename E::value_type>,				\
+    XprLiteral< TP >,							\
+    XprMatrix<E, Rows, Cols>						\
+  >							expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(				\
+    expr_type(XprLiteral< TP >(lhs), rhs));				\
+}
+
+
+// integer operators only, e.g used on double you will get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, int)
+TVMET_IMPLEMENT_MACRO(less, <, int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, int)
+TVMET_IMPLEMENT_MACRO(eq, ==, int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, int)
+TVMET_IMPLEMENT_MACRO(and, &&, int)
+TVMET_IMPLEMENT_MACRO(or, ||, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, long long int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, long long int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, long long int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, long long int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, long long int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long long int)
+TVMET_IMPLEMENT_MACRO(less, <, long long int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long long int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long long int)
+TVMET_IMPLEMENT_MACRO(eq, ==, long long int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long long int)
+TVMET_IMPLEMENT_MACRO(and, &&, long long int)
+TVMET_IMPLEMENT_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, float)
+TVMET_IMPLEMENT_MACRO(less, <, float)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, float)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, float)
+TVMET_IMPLEMENT_MACRO(eq, ==, float)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, float)
+TVMET_IMPLEMENT_MACRO(and, &&, float)
+TVMET_IMPLEMENT_MACRO(or, ||, float)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, double)
+TVMET_IMPLEMENT_MACRO(less, <, double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, double)
+TVMET_IMPLEMENT_MACRO(eq, ==, double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, double)
+TVMET_IMPLEMENT_MACRO(and, &&, double)
+TVMET_IMPLEMENT_MACRO(or, ||, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long double)
+TVMET_IMPLEMENT_MACRO(less, <, long double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long double)
+TVMET_IMPLEMENT_MACRO(eq, ==, long double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long double)
+TVMET_IMPLEMENT_MACRO(and, &&, long double)
+TVMET_IMPLEMENT_MACRO(or, ||, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * unary_operator(const XprMatrix<E, Rows, Cols>& m)
+ * Note: per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class E, std::size_t Rows, std::size_t Cols>			\
+inline									\
+XprMatrix<								\
+  XprUnOp<								\
+    Fcnl_##NAME<typename E::value_type>,				\
+    XprMatrix<E, Rows, Cols>						\
+  >,									\
+  Rows, Cols								\
+>									\
+operator OP (const XprMatrix<E, Rows, Cols>& m) {			\
+  typedef XprUnOp<							\
+    Fcnl_##NAME<typename E::value_type>,				\
+    XprMatrix<E, Rows, Cols>						\
+  >  							 expr_type;	\
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(m));		\
+}
+
+TVMET_IMPLEMENT_MACRO(not, !)
+TVMET_IMPLEMENT_MACRO(compl, ~)
+TVMET_IMPLEMENT_MACRO(neg, -)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_OPERATORS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixRow.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,96 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixRow.h,v 1.18 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_ROW_H
+#define TVMET_XPR_MATRIX_ROW_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprMatrixRow MatrixRow.h "tvmet/xpr/MatrixRow.h"
+ * \brief Expression on matrix used for access on the row vector.
+ */
+template<class E, std::size_t Rows, std::size_t Cols>
+class XprMatrixRow
+  : public TvmetBase< XprMatrixRow<E, Rows, Cols> >
+{
+  XprMatrixRow();
+  XprMatrixRow& operator=(const XprMatrixRow&);
+
+public:
+  typedef typename E::value_type			value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_expr  = E::ops,
+    ops       = ops_expr/Rows	// equal Col accesses
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMatrixRow(const E& e, std::size_t no)
+    : m_expr(e), m_row(no)
+  {
+    TVMET_RT_CONDITION(no < Rows, "XprMatrixRow Bounce Violation")
+  }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMatrixRow(const XprMatrixRow& rhs)
+    : m_expr(rhs.m_expr), m_row(rhs.m_row)
+  { }
+#endif
+
+  value_type operator()(std::size_t j) const {
+    TVMET_RT_CONDITION(j < Cols, "XprMatrixRow Bounce Violation")
+    return m_expr(m_row, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMatrixRow[O=" << ops << ", (O=" << ops_expr << ")]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R=" << Rows << ", C=" << Cols << std::endl
+       << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+
+private:
+  const E		 				m_expr;
+  const std::size_t					m_row;
+};
+
+
+}
+
+#endif // TVMET_XPR_MATRIX_ROW_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixTranspose.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,89 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixTranspose.h,v 1.15 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_TRANSPOSE_H
+#define TVMET_XPR_MATRIX_TRANSPOSE_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprMatrixTranspose MatrixTranspose.h "tvmet/xpr/MatrixTranspose.h"
+ * \brief Expression for transpose matrix
+ */
+template<class E>
+class XprMatrixTranspose
+  : public TvmetBase< XprMatrixTranspose<E> >
+{
+  XprMatrixTranspose();
+  XprMatrixTranspose& operator=(const XprMatrixTranspose&);
+
+public:
+  typedef typename E::value_type			value_type;
+
+  /** Complexity counter. */
+  enum {
+    ops_expr  = E::ops,
+    ops       = 1 * ops_expr
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMatrixTranspose(const E& e)
+    : m_expr(e)
+  { }
+
+ /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMatrixTranspose(const XprMatrixTranspose& e)
+    : m_expr(e.m_expr)
+  { }
+#endif
+
+  /** index operator for arrays/matrices. This simple swap the index
+      access for transpose. */
+  value_type operator()(std::size_t i, std::size_t j) const { return m_expr(j, i); }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMatrixTranspose[O=" << ops << ", (O=" << ops_expr << ")]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E						m_expr;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_TRANSPOSE_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MatrixUnaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,163 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MatrixUnaryFunctions.h,v 1.11 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MATRIX_UNARY_FUNCTIONS_H
+#define TVMET_XPR_MATRIX_UNARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*
+ * unary_function(XprMatrix<E, Rows, Cols>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)                    \
+template<class E, std::size_t Rows, std::size_t Cols>            \
+inline                                    \
+XprMatrix<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME<typename E::value_type>,                \
+    XprMatrix<E, Rows, Cols>                        \
+  >,                                    \
+  Rows, Cols                                \
+>                                    \
+NAME(const XprMatrix<E, Rows, Cols>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(abs)
+TVMET_DECLARE_MACRO(cbrt)
+TVMET_DECLARE_MACRO(ceil)
+TVMET_DECLARE_MACRO(floor)
+TVMET_DECLARE_MACRO(rint)
+TVMET_DECLARE_MACRO(sin)
+TVMET_DECLARE_MACRO(cos)
+TVMET_DECLARE_MACRO(tan)
+TVMET_DECLARE_MACRO(sinh)
+TVMET_DECLARE_MACRO(cosh)
+TVMET_DECLARE_MACRO(tanh)
+TVMET_DECLARE_MACRO(asin)
+TVMET_DECLARE_MACRO(acos)
+TVMET_DECLARE_MACRO(atan)
+TVMET_DECLARE_MACRO(exp)
+TVMET_DECLARE_MACRO(log)
+TVMET_DECLARE_MACRO(log10)
+TVMET_DECLARE_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_DECLARE_MACRO(asinh)
+TVMET_DECLARE_MACRO(acosh)
+TVMET_DECLARE_MACRO(atanh)
+TVMET_DECLARE_MACRO(expm1)
+TVMET_DECLARE_MACRO(log1p)
+TVMET_DECLARE_MACRO(erf)
+TVMET_DECLARE_MACRO(erfc)
+TVMET_DECLARE_MACRO(j0)
+TVMET_DECLARE_MACRO(j1)
+TVMET_DECLARE_MACRO(y0)
+TVMET_DECLARE_MACRO(y1)
+TVMET_DECLARE_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_DECLARE_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * unary_function(XprMatrix<E, Rows, Cols>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)                   \
+template<class E, std::size_t Rows, std::size_t Cols>           \
+inline                                   \
+XprMatrix<                               \
+  XprUnOp<                               \
+    Fcnl_##NAME<typename E::value_type>,               \
+    XprMatrix<E, Rows, Cols>                       \
+  >,                                   \
+  Rows, Cols                               \
+>                                   \
+NAME(const XprMatrix<E, Rows, Cols>& rhs) {               \
+  typedef XprUnOp<                           \
+    Fcnl_##NAME<typename E::value_type>,               \
+    XprMatrix<E, Rows, Cols>                       \
+  >                             expr_type; \
+  return XprMatrix<expr_type, Rows, Cols>(expr_type(rhs));       \
+}
+
+TVMET_IMPLEMENT_MACRO(abs)
+TVMET_IMPLEMENT_MACRO(cbrt)
+TVMET_IMPLEMENT_MACRO(ceil)
+TVMET_IMPLEMENT_MACRO(floor)
+TVMET_IMPLEMENT_MACRO(rint)
+TVMET_IMPLEMENT_MACRO(sin)
+TVMET_IMPLEMENT_MACRO(cos)
+TVMET_IMPLEMENT_MACRO(tan)
+TVMET_IMPLEMENT_MACRO(sinh)
+TVMET_IMPLEMENT_MACRO(cosh)
+TVMET_IMPLEMENT_MACRO(tanh)
+TVMET_IMPLEMENT_MACRO(asin)
+TVMET_IMPLEMENT_MACRO(acos)
+TVMET_IMPLEMENT_MACRO(atan)
+TVMET_IMPLEMENT_MACRO(exp)
+TVMET_IMPLEMENT_MACRO(log)
+TVMET_IMPLEMENT_MACRO(log10)
+TVMET_IMPLEMENT_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_IMPLEMENT_MACRO(asinh)
+TVMET_IMPLEMENT_MACRO(acosh)
+TVMET_IMPLEMENT_MACRO(atanh)
+TVMET_IMPLEMENT_MACRO(expm1)
+TVMET_IMPLEMENT_MACRO(log1p)
+TVMET_IMPLEMENT_MACRO(erf)
+TVMET_IMPLEMENT_MACRO(erfc)
+TVMET_IMPLEMENT_MACRO(j0)
+TVMET_IMPLEMENT_MACRO(j1)
+TVMET_IMPLEMENT_MACRO(y0)
+TVMET_IMPLEMENT_MACRO(y1)
+TVMET_IMPLEMENT_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_IMPLEMENT_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MATRIX_UNARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MtMProduct.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,139 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MtMProduct.h,v 1.19 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MTMPRODUCT_H
+#define TVMET_XPR_MTMPRODUCT_H
+
+#include <tvmet/meta/Gemtm.h>
+#include <tvmet/loop/Gemtm.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMtMProduct MtMProduct.h "tvmet/xpr/MtMProduct.h"
+ * \brief Expression for product of transposed(matrix)-matrix product.
+ *        using formula
+ *        \f[
+ *        M_1^{T}\,M_2
+ *        \f]
+ * \note The number of rows of rhs matrix have to be equal rows of rhs matrix,
+ *       since lhs matrix 1 is transposed.
+ *       The result is a (Cols1 x Cols2) matrix.
+ */
+template<class E1, std::size_t Rows1, std::size_t Cols1,
+	 class E2, std::size_t Cols2>
+class XprMtMProduct
+  : public TvmetBase< XprMtMProduct<E1, Rows1, Cols1, E2, Cols2> >
+{
+private:
+  XprMtMProduct();
+  XprMtMProduct& operator=(const XprMtMProduct&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    M = Rows1 * Cols1 * Cols2,
+    N = (Rows1-1) * Cols1 * Cols2,
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Cols1*Cols2 < TVMET_COMPLEXITY_MM_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMtMProduct(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMtMProduct(const XprMtMProduct& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs) { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemtm(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return meta::gemtm<Rows1, Cols1,
+                       Cols2,
+                       0>::prod(lhs, rhs, i, j);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemtm(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t i, std::size_t j) {
+    return loop::gemtm<Rows1, Cols1,
+	               Cols2>::prod(lhs, rhs, i, j);
+  }
+
+public:
+  /** index operator for arrays/matrices */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    TVMET_RT_CONDITION((i < Cols1) && (j < Cols2), "XprMtMProduct Bounce Violation")
+    return do_gemtm(dispatch<use_meta>(), m_lhs, m_rhs, i, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMtMProduct["
+       << (use_meta ? "M" :  "L") << ", O=" << ops
+       << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R1=" << Rows1 << ", C1=" << Cols1 << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "C2=" << Cols2 << ",\n"
+       << IndentLevel(l)
+       << "\n"
+       << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1							m_lhs;
+  const E2							m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MTMPRODUCT_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/MtVProduct.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,128 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: MtVProduct.h,v 1.14 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_MTVPRODUCT_H
+#define TVMET_XPR_MTVPRODUCT_H
+
+#include <tvmet/meta/Gemtv.h>
+#include <tvmet/loop/Gemtv.h>
+
+namespace tvmet {
+
+
+/**
+ * \class XprMtVProduct MtVProduct.h "tvmet/xpr/MtVProduct.h"
+ * \brief Expression for matrix-transposed vector product
+ *        using formula
+ *        \f[
+ *        M^T\,v
+ *        \f]
+ */
+template<class E1, std::size_t Rows, std::size_t Cols,
+	 class E2>
+class XprMtVProduct
+  : public TvmetBase< XprMtVProduct<E1, Rows, Cols, E2> >
+{
+  XprMtVProduct();
+  XprMtVProduct& operator=(const XprMtVProduct&);
+
+public:
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type							value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_lhs   = E1::ops,
+    ops_rhs   = E2::ops,
+    M         = Cols * Rows,
+    N         = Cols * (Rows - 1),
+    ops_plus  = M * NumericTraits<value_type>::ops_plus,
+    ops_muls  = N * NumericTraits<value_type>::ops_muls,
+    ops       = ops_plus + ops_muls,
+    use_meta  = Rows*Cols < TVMET_COMPLEXITY_MV_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprMtVProduct(const E1& lhs, const E2& rhs)
+    : m_lhs(lhs), m_rhs(rhs)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprMtVProduct(const XprMtVProduct& e)
+    : m_lhs(e.m_lhs), m_rhs(e.m_rhs)
+  { }
+#endif
+
+private:
+  /** Wrapper for meta gemm. */
+  static inline
+  value_type do_gemtv(dispatch<true>, const E1& lhs, const E2& rhs, std::size_t i) {
+    return meta::gemtv<Rows, Cols, 0>::prod(lhs, rhs, i);
+  }
+
+  /** Wrapper for loop gemm. */
+  static inline
+  value_type do_gemtv(dispatch<false>, const E1& lhs, const E2& rhs, std::size_t i) {
+    return loop::gemtv<Rows, Cols>::prod(lhs, rhs, i);
+  }
+
+public:
+  /** index operator, returns the expression by index. This is the vector
+      style since a matrix*vector gives a vector. */
+  value_type operator()(std::size_t j) const {
+    TVMET_RT_CONDITION(j < Cols , "XprMtVProduct Bounce Violation")
+    return do_gemtv(dispatch<use_meta>(), m_lhs, m_rhs, j);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprMtVProduct[O=" << ops << ", (O1=" << ops_lhs << ", O2=" << ops_rhs << ")]<"
+       << std::endl;
+    m_lhs.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "R=" << Rows << ", C=" << Cols << ",\n";
+    m_rhs.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E1							m_lhs;
+  const E2							m_rhs;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_MTVPRODUCT_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Null.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,69 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Null.h,v 1.11 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_NULL_H
+#define TVMET_XPR_NULL_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprNull Null.h "tvmet/xpr/Null.h"
+ * \brief Null object design pattern
+ */
+class XprNull
+  : public TvmetBase< XprNull >
+{
+  XprNull& operator=(const XprNull&);
+
+public:
+  explicit XprNull() { }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l) << "XprNull[O=0]" << std::endl;
+  }
+};
+
+
+#define TVMET_BINARY_OPERATOR(OP)                   			\
+template< class T >                    					\
+inline                     						\
+T operator OP (const T& lhs, XprNull) { return lhs; }
+
+TVMET_BINARY_OPERATOR(+)
+TVMET_BINARY_OPERATOR(-)
+TVMET_BINARY_OPERATOR(*)
+TVMET_BINARY_OPERATOR(/)
+
+#undef TVMET_BINARY_OPERATOR
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_NULL_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/UnOperator.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,99 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: UnOperator.h,v 1.17 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_UNOPERATOR_H
+#define TVMET_XPR_UNOPERATOR_H
+
+namespace tvmet {
+
+
+/**
+ * \class XprUnOp UnOperator.h "tvmet/xpr/UnOperator.h"
+ * \brief Unary operator working on one subexpression.
+ *
+ * Using the access operator() the unary operation will be evaluated.
+ */
+template<class UnOp, class E>
+class XprUnOp
+  : public TvmetBase< XprUnOp<UnOp, E> >
+{
+  XprUnOp();
+  XprUnOp& operator=(const XprUnOp&);
+
+public:
+  typedef typename UnOp::value_type				value_type;
+
+public:
+  /** Complexity counter. */
+  enum {
+    ops_expr  = E::ops,
+    ops       = 1 * ops_expr
+  };
+
+public:
+  /** Constructor for an expressions. */
+  explicit XprUnOp(const E& e)
+    : m_expr(e)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprUnOp(const XprUnOp& e)
+    : m_expr(e.m_expr)
+  { }
+#endif
+
+  /** Index operator, evaluates the expression inside. */
+  value_type operator()(std::size_t i) const {
+    return UnOp::apply_on(m_expr(i));
+  }
+
+  /** index operator for arrays/matrices. */
+  value_type operator()(std::size_t i, std::size_t j) const {
+    return UnOp::apply_on(m_expr(i, j));
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprUnOp[O="<< ops << ", (O=" << ops_expr << ")]<"
+       << std::endl;
+    UnOp::print_xpr(os, l);
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(--l)
+       << ">," << std::endl;
+  }
+
+private:
+  const E							m_expr;
+};
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_UNOPERATOR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/Vector.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,157 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: Vector.h,v 1.28 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_VECTOR_H
+#define TVMET_XPR_VECTOR_H
+
+#include <tvmet/meta/Vector.h>
+#include <tvmet/loop/Vector.h>
+
+namespace tvmet {
+
+
+/* forwards */
+template <class T, std::size_t Sz> class Vector;
+
+/**
+ * \class XprVector Vector.h "tvmet/xpr/Vector.h"
+ * \brief Represents the expression for vectors at any node in the parse tree.
+ *
+ * Specifically, XprVector is the class that wraps the expression, and the
+ * expression itself is represented by the template parameter E. The
+ * class XprVector is known as an anonymizing expression wrapper because
+ * it can hold any subexpression of arbitrary complexity, allowing
+ * clients to work with any expression by holding on to it via the
+ * wrapper, without having to know the name of the type object that
+ * actually implements the expression.
+ * \note leave the Ctors non-explicit to allow implicit type conversation.
+ */
+template<class E, std::size_t Sz>
+class XprVector : public TvmetBase< XprVector<E, Sz> >
+{
+  XprVector();
+  XprVector& operator=(const XprVector&);
+
+public:
+  typedef typename E::value_type			value_type;
+
+public:
+  /** Dimensions. */
+  enum {
+    Size = Sz			/**< The size of the vector. */
+  };
+
+public:
+  /** Complexity counter */
+  enum {
+    ops_assign = Size,
+    ops        = E::ops,
+    use_meta   = ops_assign < TVMET_COMPLEXITY_V_ASSIGN_TRIGGER ? true : false
+  };
+
+public:
+  /** Constructor. */
+  explicit XprVector(const E& e)
+    : m_expr(e)
+  { }
+
+  /** Copy Constructor. Not explicit! */
+#if defined(TVMET_OPTIMIZE_XPR_MANUAL_CCTOR)
+  XprVector(const XprVector& e)
+    : m_expr(e.m_expr)
+  { }
+#endif
+
+ /** const index operator for vectors. */
+  value_type operator()(std::size_t i) const {
+    TVMET_RT_CONDITION(i < Size, "XprVector Bounce Violation")
+    return m_expr(i);
+  }
+
+  /** const index operator for vectors. */
+  value_type operator[](std::size_t i) const {
+    return this->operator()(i);
+  }
+
+private:
+  /** Wrapper for meta assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<true>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    meta::Vector<Size, 0>::assign(dest, src, assign_fn);
+  }
+
+  /** Wrapper for loop assign. */
+  template<class Dest, class Src, class Assign>
+  static inline
+  void do_assign(dispatch<false>, Dest& dest, const Src& src, const Assign& assign_fn) {
+    loop::Vector<Size>::assign(dest, src, assign_fn);
+  }
+
+public:
+  /** assign this expression to Vector dest. */
+  template<class Dest, class Assign>
+  void assign_to(Dest& dest, const Assign& assign_fn) const {
+    /* here is a way for caching, since each complex 'Node'
+       is of type XprVector. */
+    do_assign(dispatch<use_meta>(), dest, *this, assign_fn);
+  }
+
+public: // debugging Xpr parse tree
+  void print_xpr(std::ostream& os, std::size_t l=0) const {
+    os << IndentLevel(l++)
+       << "XprVector["
+       << (use_meta ? "M" :  "L") << ", O=" << ops << "]<"
+       << std::endl;
+    m_expr.print_xpr(os, l);
+    os << IndentLevel(l)
+       << "Sz=" << Size << std::endl;
+    os << IndentLevel(--l) << ">"
+       << ((l != 0) ? "," : "") << std::endl;
+  }
+
+private:
+  const E						m_expr;
+};
+
+
+} // namespace tvmet
+
+#include <tvmet/Functional.h>
+
+#include <tvmet/xpr/BinOperator.h>
+#include <tvmet/xpr/UnOperator.h>
+#include <tvmet/xpr/Literal.h>
+
+#include <tvmet/xpr/VectorFunctions.h>
+#include <tvmet/xpr/VectorBinaryFunctions.h>
+#include <tvmet/xpr/VectorUnaryFunctions.h>
+#include <tvmet/xpr/VectorOperators.h>
+#include <tvmet/xpr/Eval.h>
+
+#endif // TVMET_XPR_VECTOR_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/VectorBinaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,320 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorBinaryFunctions.h,v 1.12 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_VECTOR_BINARY_FUNCTIONS_H
+#define TVMET_XPR_VECTOR_BINARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*
+ * binary_function(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME(const XprVector<E1, Sz>& lhs, 					\
+     const XprVector<E2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+TVMET_DECLARE_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_DECLARE_MACRO(polar)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * binary_function(XprVector<E, Sz>, POD)
+ */
+#define TVMET_DECLARE_MACRO(NAME, TP)		\
+template<class E, std::size_t Sz>		\
+inline						\
+XprVector<					\
+  XprBinOp<					\
+    Fcnl_##NAME<typename E::value_type, TP >,	\
+    XprVector<E, Sz>,				\
+    XprLiteral< TP >				\
+  >,						\
+  Sz						\
+>						\
+NAME(const XprVector<E, Sz>& lhs, 		\
+     TP rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2, int)
+TVMET_DECLARE_MACRO(drem, int)
+TVMET_DECLARE_MACRO(fmod, int)
+TVMET_DECLARE_MACRO(hypot, int)
+TVMET_DECLARE_MACRO(jn, int)
+TVMET_DECLARE_MACRO(yn, int)
+TVMET_DECLARE_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(atan2, long long int)
+TVMET_DECLARE_MACRO(drem, long long int)
+TVMET_DECLARE_MACRO(fmod, long long int)
+TVMET_DECLARE_MACRO(hypot, long long int)
+TVMET_DECLARE_MACRO(jn, long long int)
+TVMET_DECLARE_MACRO(yn, long long int)
+TVMET_DECLARE_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_DECLARE_MACRO(atan2, float)
+TVMET_DECLARE_MACRO(drem, float)
+TVMET_DECLARE_MACRO(fmod, float)
+TVMET_DECLARE_MACRO(hypot, float)
+TVMET_DECLARE_MACRO(jn, float)
+TVMET_DECLARE_MACRO(yn, float)
+TVMET_DECLARE_MACRO(pow, float)
+
+TVMET_DECLARE_MACRO(atan2, double)
+TVMET_DECLARE_MACRO(drem, double)
+TVMET_DECLARE_MACRO(fmod, double)
+TVMET_DECLARE_MACRO(hypot, double)
+TVMET_DECLARE_MACRO(jn, double)
+TVMET_DECLARE_MACRO(yn, double)
+TVMET_DECLARE_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(atan2, long double)
+TVMET_DECLARE_MACRO(drem, long double)
+TVMET_DECLARE_MACRO(fmod, long double)
+TVMET_DECLARE_MACRO(hypot, long double)
+TVMET_DECLARE_MACRO(jn, long double)
+TVMET_DECLARE_MACRO(yn, long double)
+TVMET_DECLARE_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * binary_function(XprVector<E, Sz>, std::complex<>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)				\
+template<class E, std::size_t Sz, class T>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,	\
+    XprVector<E, Sz>,						\
+    XprLiteral< std::complex<T> >				\
+  >,								\
+  Sz								\
+>								\
+NAME(const XprVector<E, Sz>& lhs, 				\
+     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(atan2)
+TVMET_DECLARE_MACRO(drem)
+TVMET_DECLARE_MACRO(fmod)
+TVMET_DECLARE_MACRO(hypot)
+TVMET_DECLARE_MACRO(jn)
+TVMET_DECLARE_MACRO(yn)
+TVMET_DECLARE_MACRO(pow)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * binary_function(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME(const XprVector<E1, Sz>& lhs, const XprVector<E2, Sz>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >		    					expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, rhs));						\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+TVMET_IMPLEMENT_MACRO(pow)
+#if defined(TVMET_HAVE_COMPLEX)
+TVMET_IMPLEMENT_MACRO(polar)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * binary_function(XprVector<E, Sz>, POD)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, TP)					\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+NAME(const XprVector<E, Sz>& lhs, TP rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< TP >(rhs)));				\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2, int)
+TVMET_IMPLEMENT_MACRO(drem, int)
+TVMET_IMPLEMENT_MACRO(fmod, int)
+TVMET_IMPLEMENT_MACRO(hypot, int)
+TVMET_IMPLEMENT_MACRO(jn, int)
+TVMET_IMPLEMENT_MACRO(yn, int)
+TVMET_IMPLEMENT_MACRO(pow, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(atan2, long long int)
+TVMET_IMPLEMENT_MACRO(drem, long long int)
+TVMET_IMPLEMENT_MACRO(fmod, long long int)
+TVMET_IMPLEMENT_MACRO(hypot, long long int)
+TVMET_IMPLEMENT_MACRO(jn, long long int)
+TVMET_IMPLEMENT_MACRO(yn, long long int)
+TVMET_IMPLEMENT_MACRO(pow, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+TVMET_IMPLEMENT_MACRO(atan2, float)
+TVMET_IMPLEMENT_MACRO(drem, float)
+TVMET_IMPLEMENT_MACRO(fmod, float)
+TVMET_IMPLEMENT_MACRO(hypot, float)
+TVMET_IMPLEMENT_MACRO(jn, float)
+TVMET_IMPLEMENT_MACRO(yn, float)
+TVMET_IMPLEMENT_MACRO(pow, float)
+
+TVMET_IMPLEMENT_MACRO(atan2, double)
+TVMET_IMPLEMENT_MACRO(drem, double)
+TVMET_IMPLEMENT_MACRO(fmod, double)
+TVMET_IMPLEMENT_MACRO(hypot, double)
+TVMET_IMPLEMENT_MACRO(jn, double)
+TVMET_IMPLEMENT_MACRO(yn, double)
+TVMET_IMPLEMENT_MACRO(pow, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(atan2, long double)
+TVMET_IMPLEMENT_MACRO(drem, long double)
+TVMET_IMPLEMENT_MACRO(fmod, long double)
+TVMET_IMPLEMENT_MACRO(hypot, long double)
+TVMET_IMPLEMENT_MACRO(jn, long double)
+TVMET_IMPLEMENT_MACRO(yn, long double)
+TVMET_IMPLEMENT_MACRO(pow, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * binary_function(XprVector<E, Sz>, std::complex<>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+NAME(const XprVector<E, Sz>& lhs, const std::complex<T>& rhs) {		\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}
+
+TVMET_IMPLEMENT_MACRO(atan2)
+TVMET_IMPLEMENT_MACRO(drem)
+TVMET_IMPLEMENT_MACRO(fmod)
+TVMET_IMPLEMENT_MACRO(hypot)
+TVMET_IMPLEMENT_MACRO(jn)
+TVMET_IMPLEMENT_MACRO(yn)
+TVMET_IMPLEMENT_MACRO(pow)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_VECTOR_BINARY_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/VectorFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,684 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorFunctions.h,v 1.21 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_VECTOR_FUNCTIONS_H
+#define TVMET_XPR_VECTOR_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/* forwards */
+template<class T, std::size_t Sz> class Vector;
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic functions add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * function(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Sz>				\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME (const XprVector<E1, Sz>& lhs,					\
+      const XprVector<E2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)		// per se element wise
+TVMET_DECLARE_MACRO(sub)		// per se element wise
+TVMET_DECLARE_MACRO(mul)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(div)		// not defined for vectors
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * function(XprVector<E, Sz>, POD)
+ * function(POD, XprVector<E, Sz>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, POD)				\
+template<class E, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< typename E::value_type, POD >,			\
+    XprVector<E, Sz>,						\
+    XprLiteral< POD >						\
+  >,								\
+  Sz								\
+>								\
+NAME (const XprVector<E, Sz>& lhs, 				\
+      POD rhs) TVMET_CXX_ALWAYS_INLINE;				\
+								\
+template<class E, std::size_t Sz>				\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< POD, typename E::value_type>,			\
+    XprLiteral< POD >,						\
+    XprVector<E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+NAME (POD lhs, 							\
+      const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, int)
+TVMET_DECLARE_MACRO(sub, int)
+TVMET_DECLARE_MACRO(mul, int)
+TVMET_DECLARE_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, long long int)
+TVMET_DECLARE_MACRO(sub, long long int)
+TVMET_DECLARE_MACRO(mul, long long int)
+TVMET_DECLARE_MACRO(div, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, float)
+TVMET_DECLARE_MACRO(sub, float)
+TVMET_DECLARE_MACRO(mul, float)
+TVMET_DECLARE_MACRO(div, float)
+
+TVMET_DECLARE_MACRO(add, double)
+TVMET_DECLARE_MACRO(sub, double)
+TVMET_DECLARE_MACRO(mul, double)
+TVMET_DECLARE_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, long double)
+TVMET_DECLARE_MACRO(sub, long double)
+TVMET_DECLARE_MACRO(mul, long double)
+TVMET_DECLARE_MACRO(div, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(XprMatrix<E, Rows, Cols>, complex<T>)
+ * function(complex<T>, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME)				\
+template<class E, std::size_t Sz, class T>			\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< typename E::value_type, std::complex<T> >,	\
+    XprVector<E, Sz>,						\
+    XprLiteral< std::complex<T> >				\
+  >,								\
+  Sz								\
+>								\
+NAME (const XprVector<E, Sz>& lhs,				\
+      const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+								\
+template<class E, std::size_t Sz, class T>			\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,	\
+    XprLiteral< std::complex<T> >,				\
+    XprVector<E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+NAME (const std::complex<T>& lhs, 				\
+      const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add)
+TVMET_DECLARE_MACRO(sub)
+TVMET_DECLARE_MACRO(mul)
+TVMET_DECLARE_MACRO(div)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * vector specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+template<class E, std::size_t Sz>
+typename NumericTraits<typename E::value_type>::sum_type
+sum(const XprVector<E, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename NumericTraits<typename E::value_type>::sum_type
+product(const XprVector<E, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, class E2, std::size_t Sz>
+typename PromoteTraits<
+  typename E1::value_type,
+  typename E2::value_type
+>::value_type
+dot(const XprVector<E1, Sz>& lhs,
+    const XprVector<E2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, class E, std::size_t Sz>
+typename PromoteTraits<T, typename E::value_type>::value_type
+dot(const Vector<T, Sz>& lhs,
+    const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, class T, std::size_t Sz>
+typename PromoteTraits<T, typename E::value_type>::value_type
+dot(const XprVector<E, Sz>& lhs,
+    const Vector<T, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E1, class E2>
+Vector<
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type,
+  3
+>
+cross(const XprVector<E1, 3>& lhs,
+      const XprVector<E2, 3>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class T, class E>
+Vector<
+  typename PromoteTraits<T, typename E::value_type>::value_type, 3>
+cross(const Vector<T, 3>& lhs,
+      const XprVector<E, 3>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, class T>
+Vector<
+  typename PromoteTraits<T, typename E::value_type>::value_type, 3>
+cross(const XprVector<E, 3>& lhs,
+      const Vector<T, 3>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename NumericTraits<typename E::value_type>::sum_type
+norm1(const XprVector<E, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+typename NumericTraits<typename E::value_type>::sum_type
+norm2(const XprVector<E, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+template<class E, std::size_t Sz>
+XprVector<
+  XprBinOp<
+    Fcnl_div<typename E::value_type, typename E::value_type>,
+    XprVector<E, Sz>,
+    XprLiteral<typename E::value_type>
+  >,
+  Sz
+>
+normalize(const XprVector<E, Sz>& v) TVMET_CXX_ALWAYS_INLINE;
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * function(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME (const XprVector<E1, Sz>& lhs, const XprVector<E2, Sz>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  > 							 expr_type;	\
+  return XprVector<expr_type, Sz>(expr_type(lhs, rhs));			\
+}
+
+TVMET_IMPLEMENT_MACRO(add)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(div)		// not defined for vectors
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * function(XprVector<E, Sz>, POD)
+ * function(POD, XprVector<E, Sz>)
+ * Note: - operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, POD)				\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< typename E::value_type, POD >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< POD >							\
+  >,									\
+  Sz									\
+>									\
+NAME (const XprVector<E, Sz>& lhs, POD rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< typename E::value_type, POD >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< POD >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< POD >(rhs)));				\
+}									\
+									\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, typename E::value_type>,				\
+    XprLiteral< POD >,							\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME (POD lhs, const XprVector<E, Sz>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< POD, typename E::value_type>,				\
+    XprLiteral< POD >,							\
+    XprVector<E, Sz>							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< POD >(lhs), rhs));				\
+}
+
+TVMET_IMPLEMENT_MACRO(add, int)
+TVMET_IMPLEMENT_MACRO(sub, int)
+TVMET_IMPLEMENT_MACRO(mul, int)
+TVMET_IMPLEMENT_MACRO(div, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, long long int)
+TVMET_IMPLEMENT_MACRO(sub, long long int)
+TVMET_IMPLEMENT_MACRO(mul, long long int)
+TVMET_IMPLEMENT_MACRO(div, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, float)
+TVMET_IMPLEMENT_MACRO(sub, float)
+TVMET_IMPLEMENT_MACRO(mul, float)
+TVMET_IMPLEMENT_MACRO(div, float)
+
+TVMET_IMPLEMENT_MACRO(add, double)
+TVMET_IMPLEMENT_MACRO(sub, double)
+TVMET_IMPLEMENT_MACRO(mul, double)
+TVMET_IMPLEMENT_MACRO(div, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, long double)
+TVMET_IMPLEMENT_MACRO(sub, long double)
+TVMET_IMPLEMENT_MACRO(mul, long double)
+TVMET_IMPLEMENT_MACRO(div, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * function(XprMatrix<E, Rows, Cols>, complex<T>)
+ * function(complex<T>, XprMatrix<E, Rows, Cols>)
+ * Note: - operations +,-,*,/ are per se element wise
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)				   \
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+NAME (const XprVector<E, Sz>& lhs, const std::complex<T>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}									\
+									\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+NAME (const std::complex<T>& lhs, const XprVector<E, Sz>& rhs) {	\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector<E, Sz>							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs));		\
+}
+
+TVMET_IMPLEMENT_MACRO(add)
+TVMET_IMPLEMENT_MACRO(sub)
+TVMET_IMPLEMENT_MACRO(mul)
+TVMET_IMPLEMENT_MACRO(div)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * vector specific functions
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/**
+ * \fn sum(const XprVector<E, Sz>& v)
+ * \brief Compute the sum of the vector expression.
+ * \ingroup _unary_function
+ *
+ * Simply compute the sum of the given vector as:
+ * \f[
+ * \sum_{i = 0}^{Sz-1} v[i]
+ * \f]
+ */
+template<class E, std::size_t Sz>
+inline
+typename NumericTraits<typename E::value_type>::sum_type
+sum(const XprVector<E, Sz>& v) {
+  return meta::Vector<Sz>::sum(v);
+}
+
+
+/**
+ * \fn product(const XprVector<E, Sz>& v)
+ * \brief Compute the product of the vector elements.
+ * \ingroup _unary_function
+ *
+ * Simply computer the product of the given vector expression as:
+ * \f[
+ * \prod_{i = 0}^{Sz - 1} v[i]
+ * \f]
+ */
+template<class E, std::size_t Sz>
+inline
+typename NumericTraits<typename E::value_type>::sum_type
+product(const XprVector<E, Sz>& v) {
+  return meta::Vector<Sz>::product(v);
+}
+
+
+/**
+ * \fn dot(const XprVector<E1, Sz>& lhs, const XprVector<E2, Sz>& rhs)
+ * \brief Compute the dot/inner product
+ * \ingroup _binary_function
+ *
+ * Compute the dot product as:
+ * \f[
+ * \sum_{i = 0}^{Sz - 1} ( lhs[i] * rhs[i] )
+ * \f]
+ * where lhs is a column vector and rhs is a row vector, both vectors
+ * have the same dimension.
+ */
+template<class E1, class E2, std::size_t Sz>
+inline
+typename PromoteTraits<
+  typename E1::value_type,
+  typename E2::value_type
+>::value_type
+dot(const XprVector<E1, Sz>& lhs, const XprVector<E2, Sz>& rhs) {
+  return meta::Vector<Sz>::dot(lhs, rhs);
+}
+
+
+/**
+ * \fn dot(const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs)
+ * \brief Compute the dot/inner product
+ * \ingroup _binary_function
+ *
+ * Compute the dot product as:
+ * \f[
+ * \sum_{i = 0}^{Sz - 1} ( lhs[i] * rhs[i] )
+ * \f]
+ * where lhs is a column vector and rhs is a row vector, both vectors
+ * have the same dimension.
+ */
+template<class T, class E, std::size_t Sz>
+inline
+typename PromoteTraits<T, typename E::value_type>::value_type
+dot(const Vector<T, Sz>& lhs, const XprVector<E, Sz>& rhs) {
+  return meta::Vector<Sz>::dot(lhs, rhs);
+}
+
+
+/**
+ * \fn dot(const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs)
+ * \brief Compute the dot/inner product
+ * \ingroup _binary_function
+ *
+ * Compute the dot product as:
+ * \f[
+ * \sum_{i = 0}^{Sz - 1} ( lhs[i] * rhs[i] )
+ * \f]
+ * where lhs is a column vector and rhs is a row vector, both vectors
+ * have the same dimension.
+ */
+template<class E, class T, std::size_t Sz>
+inline
+typename PromoteTraits<T, typename E::value_type>::value_type
+dot(const XprVector<E, Sz>& lhs, const Vector<T, Sz>& rhs) {
+  return meta::Vector<Sz>::dot(lhs, rhs);
+}
+
+
+/**
+ * \fn cross(const XprVector<E1, 3>& lhs, const XprVector<E2, 3>& rhs)
+ * \brief Compute the cross/outer product
+ * \ingroup _binary_function
+ * \note working only for vectors of size = 3
+ * \todo Implement vector outer product as ET and MT, returning a XprVector
+ */
+template<class E1, class E2>
+inline
+Vector<
+  typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type,
+  3
+>
+cross(const XprVector<E1, 3>& lhs, const XprVector<E2, 3>& rhs) {
+  typedef typename PromoteTraits<
+    typename E1::value_type,
+    typename E2::value_type
+  >::value_type						value_type;
+  return Vector<value_type, 3>(lhs(1)*rhs(2) - rhs(1)*lhs(2),
+			       rhs(0)*lhs(2) - lhs(0)*rhs(2),
+			       lhs(0)*rhs(1) - rhs(0)*lhs(1));
+}
+
+
+/**
+ * \fn cross(const XprVector<E, 3>& lhs, const Vector<T, 3>& rhs)
+ * \brief Compute the cross/outer product
+ * \ingroup _binary_function
+ * \note working only for vectors of size = 3
+ * \todo Implement vector outer product as ET and MT, returning a XprVector
+ */
+template<class E, class T>
+inline
+Vector<
+  typename PromoteTraits<T, typename E::value_type>::value_type, 3>
+cross(const XprVector<E, 3>& lhs, const Vector<T, 3>& rhs) {
+  typedef typename PromoteTraits<
+    typename E::value_type, T>::value_type 		value_type;
+  return Vector<value_type, 3>(lhs(1)*rhs(2) - rhs(1)*lhs(2),
+			       rhs(0)*lhs(2) - lhs(0)*rhs(2),
+			       lhs(0)*rhs(1) - rhs(0)*lhs(1));
+}
+
+
+/**
+ * \fn cross(const Vector<T, 3>& lhs, const XprVector<E, 3>& rhs)
+ * \brief Compute the cross/outer product
+ * \ingroup _binary_function
+ * \note working only for vectors of size = 3
+ * \todo Implement vector outer product as ET and MT, returning a XprVector
+ */
+template<class T1, class E2>
+inline
+Vector<
+  typename PromoteTraits<T1, typename E2::value_type>::value_type, 3>
+cross(const Vector<T1, 3>& lhs, const XprVector<E2, 3>& rhs) {
+  typedef typename PromoteTraits<
+    typename E2::value_type, T1>::value_type 		value_type;
+  return Vector<value_type, 3>(lhs(1)*rhs(2) - rhs(1)*lhs(2),
+			       rhs(0)*lhs(2) - lhs(0)*rhs(2),
+			       lhs(0)*rhs(1) - rhs(0)*lhs(1));
+}
+
+
+/**
+ * \fn norm1(const XprVector<E, Sz>& v)
+ * \brief The \f$l_1\f$ norm of a vector expression.
+ * \ingroup _unary_function
+ * The norm of any vector is just the square root of the dot product of
+ * a vector with itself, or
+ *
+ * \f[
+ * |Vector<T, Sz> v| = |v| = \sum_{i=0}^{Sz-1}\,|v[i]|
+ * \f]
+ */
+template<class E, std::size_t Sz>
+inline
+typename NumericTraits<typename E::value_type>::sum_type
+norm1(const XprVector<E, Sz>& v) {
+  return sum(abs(v));
+}
+
+
+/**
+ * \fn norm2(const XprVector<E, Sz>& v)
+ * \brief The euklidian norm (or \f$l_2\f$ norm) of a vector expression.
+ * \ingroup _unary_function
+ * The norm of any vector is just the square root of the dot product of
+ * a vector with itself, or
+ *
+ * \f[
+ * |Vector<T, Sz> v| = |v| = \sqrt{ \sum_{i=0}^{Sz-1}\,v[i]^2 }
+ * \f]
+ *
+ * \note The internal cast for Vector<int> avoids warnings on sqrt.
+ */
+template<class E, std::size_t Sz>
+inline
+typename NumericTraits<typename E::value_type>::sum_type
+norm2(const XprVector<E, Sz>& v) {
+  typedef typename E::value_type			value_type;
+  return static_cast<value_type>( std::sqrt(static_cast<value_type>(dot(v, v))) );
+}
+
+
+/**
+ * \fn normalize(const XprVector<E, Sz>& v)
+ * \brief Normalize the given vector expression.
+ * \ingroup _unary_function
+ * \sa norm2
+ *
+ * using the equation:
+ * \f[
+ * \frac{Vector<T, Sz> v}{\sqrt{ \sum_{i=0}^{Sz-1}\,v[i]^2 }}
+ * \f]
+ */
+template<class E, std::size_t Sz>
+inline
+XprVector<
+  XprBinOp<
+    Fcnl_div<typename E::value_type, typename E::value_type>,
+    XprVector<E, Sz>,
+    XprLiteral<typename E::value_type>
+  >,
+  Sz
+>
+normalize(const XprVector<E, Sz>& v) {
+  typedef typename E::value_type			value_type;
+  typedef XprBinOp<
+    Fcnl_div<value_type, value_type>,
+    XprVector<E, Sz>,
+    XprLiteral<value_type>
+  >							expr_type;
+  return XprVector<expr_type, Sz>(
+    expr_type(v, XprLiteral< value_type >(norm2(v))));
+}
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_VECTOR_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/VectorOperators.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,830 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorOperators.h,v 1.17 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_VECTOR_OPERATORS_H
+#define TVMET_XPR_VECTOR_OPERATORS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E1, Sz>& lhs, 				\
+	     const XprVector<E2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)		// per se element wise
+TVMET_DECLARE_MACRO(sub, -)		// per se element wise
+TVMET_DECLARE_MACRO(mul, *)		// per se element wise
+namespace element_wise {
+  TVMET_DECLARE_MACRO(div, /)		// not defined for vectors
+}
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * operator(XprVector<E, Sz>, POD)
+ * operator(POD, XprVector<E, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, POD)				\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, POD >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< POD >							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, 				\
+	     POD rhs) TVMET_CXX_ALWAYS_INLINE;				\
+									\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< POD, typename E::value_type >,				\
+    XprLiteral< POD >,							\
+    XprVector< E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (POD lhs, 							\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +, int)
+TVMET_DECLARE_MACRO(sub, -, int)
+TVMET_DECLARE_MACRO(mul, *, int)
+TVMET_DECLARE_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_DECLARE_MACRO(add, +, long long int)
+TVMET_DECLARE_MACRO(sub, -, long long int)
+TVMET_DECLARE_MACRO(mul, *, long long int)
+TVMET_DECLARE_MACRO(div, /, long long int)
+#endif
+
+TVMET_DECLARE_MACRO(add, +, float)
+TVMET_DECLARE_MACRO(sub, -, float)
+TVMET_DECLARE_MACRO(mul, *, float)
+TVMET_DECLARE_MACRO(div, /, float)
+
+TVMET_DECLARE_MACRO(add, +, double)
+TVMET_DECLARE_MACRO(sub, -, double)
+TVMET_DECLARE_MACRO(mul, *, double)
+TVMET_DECLARE_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_DECLARE_MACRO(add, +, long double)
+TVMET_DECLARE_MACRO(sub, -, long double)
+TVMET_DECLARE_MACRO(mul, *, long double)
+TVMET_DECLARE_MACRO(div, /, long double)
+#endif
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprVector<E, Sz>, complex<T>)
+ * operator(complex<T>, XprVector<E, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs,				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type >,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector< E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const std::complex<T>& lhs,				\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(add, +)		// per se element wise
+TVMET_DECLARE_MACRO(sub, -)		// per se element wise
+TVMET_DECLARE_MACRO(mul, *)		// per se element wise
+TVMET_DECLARE_MACRO(div, /)		// per se element wise
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprVector, XprVector)
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E1, Sz>& lhs,				\
+	     const XprVector<E2, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %)
+  TVMET_DECLARE_MACRO(bitxor, ^)
+  TVMET_DECLARE_MACRO(bitand, &)
+  TVMET_DECLARE_MACRO(bitor, |)
+  TVMET_DECLARE_MACRO(shl, <<)
+  TVMET_DECLARE_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations are per se element_wise
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP, TP)				\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, 				\
+	     TP rhs) TVMET_CXX_ALWAYS_INLINE;				\
+									\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<TP, typename E::value_type>,				\
+    XprLiteral< TP >,							\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (TP lhs, 							\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, int)
+  TVMET_DECLARE_MACRO(bitxor, ^, int)
+  TVMET_DECLARE_MACRO(bitand, &, int)
+  TVMET_DECLARE_MACRO(bitor, |, int)
+  TVMET_DECLARE_MACRO(shl, <<, int)
+  TVMET_DECLARE_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, int)
+TVMET_DECLARE_MACRO(less, <, int)
+TVMET_DECLARE_MACRO(greater_eq, >=, int)
+TVMET_DECLARE_MACRO(less_eq, <=, int)
+TVMET_DECLARE_MACRO(eq, ==, int)
+TVMET_DECLARE_MACRO(not_eq, !=, int)
+TVMET_DECLARE_MACRO(and, &&, int)
+TVMET_DECLARE_MACRO(or, ||, int)
+
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_DECLARE_MACRO(mod, %, long long int)
+  TVMET_DECLARE_MACRO(bitxor, ^, long long int)
+  TVMET_DECLARE_MACRO(bitand, &, long long int)
+  TVMET_DECLARE_MACRO(bitor, |, long long int)
+  TVMET_DECLARE_MACRO(shl, <<, long long int)
+  TVMET_DECLARE_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long long int)
+TVMET_DECLARE_MACRO(less, <, long long int)
+TVMET_DECLARE_MACRO(greater_eq, >=, long long int)
+TVMET_DECLARE_MACRO(less_eq, <=, long long int)
+TVMET_DECLARE_MACRO(eq, ==, long long int)
+TVMET_DECLARE_MACRO(not_eq, !=, long long int)
+TVMET_DECLARE_MACRO(and, &&, long long int)
+TVMET_DECLARE_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, float)
+TVMET_DECLARE_MACRO(less, <, float)
+TVMET_DECLARE_MACRO(greater_eq, >=, float)
+TVMET_DECLARE_MACRO(less_eq, <=, float)
+TVMET_DECLARE_MACRO(eq, ==, float)
+TVMET_DECLARE_MACRO(not_eq, !=, float)
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, double)
+TVMET_DECLARE_MACRO(less, <, double)
+TVMET_DECLARE_MACRO(greater_eq, >=, double)
+TVMET_DECLARE_MACRO(less_eq, <=, double)
+TVMET_DECLARE_MACRO(eq, ==, double)
+TVMET_DECLARE_MACRO(not_eq, !=, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >, long double)
+TVMET_DECLARE_MACRO(less, <, long double)
+TVMET_DECLARE_MACRO(greater_eq, >=, long double)
+TVMET_DECLARE_MACRO(less_eq, <=, long double)
+TVMET_DECLARE_MACRO(eq, ==, long double)
+TVMET_DECLARE_MACRO(not_eq, !=, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_DECLARE_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs,				\
+	     const std::complex<T>& rhs) TVMET_CXX_ALWAYS_INLINE;	\
+									\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const std::complex<T>& lhs,				\
+	     const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+// necessary operators for eval functions
+TVMET_DECLARE_MACRO(greater, >)
+TVMET_DECLARE_MACRO(less, <)
+TVMET_DECLARE_MACRO(greater_eq, >=)
+TVMET_DECLARE_MACRO(less_eq, <=)
+TVMET_DECLARE_MACRO(eq, ==)
+TVMET_DECLARE_MACRO(not_eq, !=)
+TVMET_DECLARE_MACRO(and, &&)
+TVMET_DECLARE_MACRO(or, ||)
+
+#undef TVMET_DECLARE_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * Unary Operator on XprVector<E, Sz>
+ */
+#define TVMET_DECLARE_MACRO(NAME, OP)					\
+template <class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprUnOp<								\
+    Fcnl_##NAME<typename E::value_type>,				\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(not, !)
+TVMET_DECLARE_MACRO(compl, ~)
+TVMET_DECLARE_MACRO(neg, -)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector arithmetic operators implemented by functions
+ * add, sub, mul and div
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprVector<E1, Sz>, XprVector<E2, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E1, Sz>& lhs, 				\
+	     const XprVector<E2, Sz>& rhs) {				\
+  return NAME (lhs, rhs);						\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul, *)		// per se element wise
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(div, /)		// not defined for vectors
+}
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * operator(XprVector<E, Sz>, POD)
+ * operator(POD, XprVector<E, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, POD)		\
+template<class E, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME<typename E::value_type, POD >,		\
+    XprVector<E, Sz>,					\
+    XprLiteral< POD >					\
+  >,							\
+  Sz							\
+>							\
+operator OP (const XprVector<E, Sz>& lhs, POD rhs) {	\
+  return NAME (lhs, rhs);				\
+}							\
+							\
+template<class E, std::size_t Sz>			\
+inline							\
+XprVector<						\
+  XprBinOp<						\
+    Fcnl_##NAME< POD, typename E::value_type >,		\
+    XprLiteral< POD >,					\
+    XprVector< E, Sz>					\
+  >,							\
+  Sz							\
+>							\
+operator OP (POD lhs, const XprVector<E, Sz>& rhs) {	\
+  return NAME (lhs, rhs);				\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +, int)
+TVMET_IMPLEMENT_MACRO(sub, -, int)
+TVMET_IMPLEMENT_MACRO(mul, *, int)
+TVMET_IMPLEMENT_MACRO(div, /, int)
+
+#if defined(TVMET_HAVE_LONG_LONG)
+TVMET_IMPLEMENT_MACRO(add, +, long long int)
+TVMET_IMPLEMENT_MACRO(sub, -, long long int)
+TVMET_IMPLEMENT_MACRO(mul, *, long long int)
+TVMET_IMPLEMENT_MACRO(div, /, long long int)
+#endif
+
+TVMET_IMPLEMENT_MACRO(add, +, float)
+TVMET_IMPLEMENT_MACRO(sub, -, float)
+TVMET_IMPLEMENT_MACRO(mul, *, float)
+TVMET_IMPLEMENT_MACRO(div, /, float)
+
+TVMET_IMPLEMENT_MACRO(add, +, double)
+TVMET_IMPLEMENT_MACRO(sub, -, double)
+TVMET_IMPLEMENT_MACRO(mul, *, double)
+TVMET_IMPLEMENT_MACRO(div, /, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+TVMET_IMPLEMENT_MACRO(add, +, long double)
+TVMET_IMPLEMENT_MACRO(sub, -, long double)
+TVMET_IMPLEMENT_MACRO(mul, *, long double)
+TVMET_IMPLEMENT_MACRO(div, /, long double)
+#endif
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(XprVector<E, Sz>, complex<T>)
+ * operator(complex<T>, XprVector<E, Sz>)
+ * Note: operations +,-,*,/ are per se element wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)				\
+template<class E, std::size_t Sz, class T>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,	\
+    XprVector<E, Sz>,						\
+    XprLiteral< std::complex<T> >				\
+  >,								\
+  Sz								\
+>								\
+operator OP (const XprVector<E, Sz>& lhs,			\
+	     const std::complex<T>& rhs) {			\
+  return NAME (lhs, rhs);					\
+}								\
+								\
+template<class E, std::size_t Sz, class T>			\
+inline								\
+XprVector<							\
+  XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type >,	\
+    XprLiteral< std::complex<T> >,				\
+    XprVector< E, Sz>						\
+  >,								\
+  Sz								\
+>								\
+operator OP (const std::complex<T>& lhs,			\
+	     const XprVector<E, Sz>& rhs) {			\
+  return NAME (lhs, rhs);					\
+}
+
+TVMET_IMPLEMENT_MACRO(add, +)		// per se element wise
+TVMET_IMPLEMENT_MACRO(sub, -)		// per se element wise
+TVMET_IMPLEMENT_MACRO(mul, *)		// per se element wise
+TVMET_IMPLEMENT_MACRO(div, /)		// per se element wise
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * Vector integer and compare operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * operator(XprVector, XprVector)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E1, class E2, std::size_t Sz>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E1, Sz>& lhs,				\
+	     const XprVector<E2, Sz>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E1::value_type, typename E2::value_type>,	\
+    XprVector<E1, Sz>,							\
+    XprVector<E2, Sz>							\
+  >		    					expr_type;	\
+  return XprVector<expr_type, Sz>(expr_type(lhs, rhs));			\
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^)
+  TVMET_IMPLEMENT_MACRO(bitand, &)
+  TVMET_IMPLEMENT_MACRO(bitor, |)
+  TVMET_IMPLEMENT_MACRO(shl, <<)
+  TVMET_IMPLEMENT_MACRO(shr, >>)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+/*
+ * operator(Vector<T, Sz>, POD)
+ * operator(POD, Vector<T, Sz>)
+ * Note: operations are per se element_wise
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP, TP)				\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< TP >							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs, TP rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, TP >,				\
+    XprVector<E, Sz>,							\
+    XprLiteral< TP >							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< TP >(rhs)));				\
+}									\
+									\
+template<class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<TP, typename E::value_type>,				\
+    XprLiteral< TP >,							\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (TP lhs, const XprVector<E, Sz>& rhs) {			\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< TP, typename E::value_type>,				\
+    XprLiteral< TP >,							\
+    XprVector<E, Sz>							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< TP >(lhs), rhs));				\
+}
+
+// integer operators only, e.g used on double you wil get an error
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, int)
+TVMET_IMPLEMENT_MACRO(less, <, int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, int)
+TVMET_IMPLEMENT_MACRO(eq, ==, int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, int)
+TVMET_IMPLEMENT_MACRO(and, &&, int)
+TVMET_IMPLEMENT_MACRO(or, ||, int)
+
+
+#if defined(TVMET_HAVE_LONG_LONG)
+// integer operators only
+namespace element_wise {
+  TVMET_IMPLEMENT_MACRO(mod, %, long long int)
+  TVMET_IMPLEMENT_MACRO(bitxor, ^, long long int)
+  TVMET_IMPLEMENT_MACRO(bitand, &, long long int)
+  TVMET_IMPLEMENT_MACRO(bitor, |, long long int)
+  TVMET_IMPLEMENT_MACRO(shl, <<, long long int)
+  TVMET_IMPLEMENT_MACRO(shr, >>, long long int)
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long long int)
+TVMET_IMPLEMENT_MACRO(less, <, long long int)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long long int)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long long int)
+TVMET_IMPLEMENT_MACRO(eq, ==, long long int)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long long int)
+TVMET_IMPLEMENT_MACRO(and, &&, long long int)
+TVMET_IMPLEMENT_MACRO(or, ||, long long int)
+#endif // defined(TVMET_HAVE_LONG_LONG)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, float)
+TVMET_IMPLEMENT_MACRO(less, <, float)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, float)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, float)
+TVMET_IMPLEMENT_MACRO(eq, ==, float)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, float)
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, double)
+TVMET_IMPLEMENT_MACRO(less, <, double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, double)
+TVMET_IMPLEMENT_MACRO(eq, ==, double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, double)
+
+#if defined(TVMET_HAVE_LONG_DOUBLE)
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >, long double)
+TVMET_IMPLEMENT_MACRO(less, <, long double)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=, long double)
+TVMET_IMPLEMENT_MACRO(less_eq, <=, long double)
+TVMET_IMPLEMENT_MACRO(eq, ==, long double)
+TVMET_IMPLEMENT_MACRO(not_eq, !=, long double)
+#endif // defined(TVMET_HAVE_LONG_DOUBLE)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+#if defined(TVMET_HAVE_COMPLEX)
+/*
+ * operator(Vector<std::complex<T>, Sz>, std::complex<T>)
+ * operator(std::complex<T>, Vector<std::complex<T>, Sz>)
+ * Note: - per se element wise
+ *       - bit ops on complex<int> doesn't make sense, stay away
+ * \todo type promotion
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& lhs,				\
+	     const std::complex<T>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME<typename E::value_type, std::complex<T> >,		\
+    XprVector<E, Sz>,							\
+    XprLiteral< std::complex<T> >					\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(lhs, XprLiteral< std::complex<T> >(rhs)));		\
+}									\
+									\
+template<class E, std::size_t Sz, class T>				\
+inline									\
+XprVector<								\
+  XprBinOp<								\
+    Fcnl_##NAME<std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const std::complex<T>& lhs,				\
+	     const XprVector<E, Sz>& rhs) {				\
+  typedef XprBinOp<							\
+    Fcnl_##NAME< std::complex<T>, typename E::value_type>,		\
+    XprLiteral< std::complex<T> >,					\
+    XprVector<E, Sz>							\
+  >							expr_type;	\
+  return XprVector<expr_type, Sz>(					\
+    expr_type(XprLiteral< std::complex<T> >(lhs), rhs));		\
+}
+
+// necessary operators for eval functions
+TVMET_IMPLEMENT_MACRO(greater, >)
+TVMET_IMPLEMENT_MACRO(less, <)
+TVMET_IMPLEMENT_MACRO(greater_eq, >=)
+TVMET_IMPLEMENT_MACRO(less_eq, <=)
+TVMET_IMPLEMENT_MACRO(eq, ==)
+TVMET_IMPLEMENT_MACRO(not_eq, !=)
+TVMET_IMPLEMENT_MACRO(and, &&)
+TVMET_IMPLEMENT_MACRO(or, ||)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+#endif // defined(TVMET_HAVE_COMPLEX)
+
+
+/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * global unary operators
+ *+++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
+
+
+/*
+ * Unary Operator on XprVector<E, Sz>
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME, OP)					\
+template <class E, std::size_t Sz>					\
+inline									\
+XprVector<								\
+  XprUnOp<								\
+    Fcnl_##NAME<typename E::value_type>,				\
+    XprVector<E, Sz>							\
+  >,									\
+  Sz									\
+>									\
+operator OP (const XprVector<E, Sz>& rhs) {				\
+  typedef XprUnOp<							\
+    Fcnl_##NAME<typename E::value_type>,				\
+    XprVector<E, Sz>							\
+  >  							 expr_type;	\
+  return XprVector<expr_type, Sz>(expr_type(rhs));			\
+}
+
+TVMET_IMPLEMENT_MACRO(not, !)
+TVMET_IMPLEMENT_MACRO(compl, ~)
+TVMET_IMPLEMENT_MACRO(neg, -)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_VECTOR_OPERATORS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/xpr/VectorUnaryFunctions.h	Wed Mar 28 15:53:45 2012 +0000
@@ -0,0 +1,163 @@
+/*
+ * Tiny Vector Matrix Library
+ * Dense Vector Matrix Libary of Tiny size using Expression Templates
+ *
+ * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.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: VectorUnaryFunctions.h,v 1.11 2007-06-23 15:59:00 opetzold Exp $
+ */
+
+#ifndef TVMET_XPR_VECTOR_UNARY_FUNCTIONS_H
+#define TVMET_XPR_VECTOR_UNARY_FUNCTIONS_H
+
+namespace tvmet {
+
+
+/*********************************************************
+ * PART I: DECLARATION
+ *********************************************************/
+
+/*
+ * unary_function(XprVector<E, Sz>)
+ */
+#define TVMET_DECLARE_MACRO(NAME)                \
+template<class E, std::size_t Sz>                \
+inline                                \
+XprVector<                            \
+  XprUnOp<                            \
+    Fcnl_##NAME<typename E::value_type>,            \
+    XprVector<E, Sz>                        \
+  >,                                \
+  Sz                                \
+>                                \
+NAME(const XprVector<E, Sz>& rhs) TVMET_CXX_ALWAYS_INLINE;
+
+TVMET_DECLARE_MACRO(abs)
+TVMET_DECLARE_MACRO(cbrt)
+TVMET_DECLARE_MACRO(ceil)
+TVMET_DECLARE_MACRO(floor)
+TVMET_DECLARE_MACRO(rint)
+TVMET_DECLARE_MACRO(sin)
+TVMET_DECLARE_MACRO(cos)
+TVMET_DECLARE_MACRO(tan)
+TVMET_DECLARE_MACRO(sinh)
+TVMET_DECLARE_MACRO(cosh)
+TVMET_DECLARE_MACRO(tanh)
+TVMET_DECLARE_MACRO(asin)
+TVMET_DECLARE_MACRO(acos)
+TVMET_DECLARE_MACRO(atan)
+TVMET_DECLARE_MACRO(exp)
+TVMET_DECLARE_MACRO(log)
+TVMET_DECLARE_MACRO(log10)
+TVMET_DECLARE_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_DECLARE_MACRO(asinh)
+TVMET_DECLARE_MACRO(acosh)
+TVMET_DECLARE_MACRO(atanh)
+TVMET_DECLARE_MACRO(expm1)
+TVMET_DECLARE_MACRO(log1p)
+TVMET_DECLARE_MACRO(erf)
+TVMET_DECLARE_MACRO(erfc)
+TVMET_DECLARE_MACRO(j0)
+TVMET_DECLARE_MACRO(j1)
+TVMET_DECLARE_MACRO(y0)
+TVMET_DECLARE_MACRO(y1)
+TVMET_DECLARE_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_DECLARE_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_DECLARE_MACRO
+
+
+/*********************************************************
+ * PART II: IMPLEMENTATION
+ *********************************************************/
+
+
+/*
+ * unary_function(XprVector<E, Sz>)
+ */
+#define TVMET_IMPLEMENT_MACRO(NAME)                    \
+template<class E, std::size_t Sz>                    \
+inline                                    \
+XprVector<                                \
+  XprUnOp<                                \
+    Fcnl_##NAME<typename E::value_type>,                \
+    XprVector<E, Sz>                            \
+  >,                                    \
+  Sz                                    \
+>                                    \
+NAME(const XprVector<E, Sz>& rhs) {                    \
+  typedef XprUnOp<                            \
+    Fcnl_##NAME<typename E::value_type>,                \
+    XprVector<E, Sz>                            \
+  >                             expr_type;    \
+  return XprVector<expr_type, Sz>(expr_type(rhs));            \
+}
+
+TVMET_IMPLEMENT_MACRO(abs)
+TVMET_IMPLEMENT_MACRO(cbrt)
+TVMET_IMPLEMENT_MACRO(ceil)
+TVMET_IMPLEMENT_MACRO(floor)
+TVMET_IMPLEMENT_MACRO(rint)
+TVMET_IMPLEMENT_MACRO(sin)
+TVMET_IMPLEMENT_MACRO(cos)
+TVMET_IMPLEMENT_MACRO(tan)
+TVMET_IMPLEMENT_MACRO(sinh)
+TVMET_IMPLEMENT_MACRO(cosh)
+TVMET_IMPLEMENT_MACRO(tanh)
+TVMET_IMPLEMENT_MACRO(asin)
+TVMET_IMPLEMENT_MACRO(acos)
+TVMET_IMPLEMENT_MACRO(atan)
+TVMET_IMPLEMENT_MACRO(exp)
+TVMET_IMPLEMENT_MACRO(log)
+TVMET_IMPLEMENT_MACRO(log10)
+TVMET_IMPLEMENT_MACRO(sqrt)
+
+#if defined(TVMET_HAVE_IEEE_MATH)
+TVMET_IMPLEMENT_MACRO(asinh)
+TVMET_IMPLEMENT_MACRO(acosh)
+TVMET_IMPLEMENT_MACRO(atanh)
+TVMET_IMPLEMENT_MACRO(expm1)
+TVMET_IMPLEMENT_MACRO(log1p)
+TVMET_IMPLEMENT_MACRO(erf)
+TVMET_IMPLEMENT_MACRO(erfc)
+TVMET_IMPLEMENT_MACRO(j0)
+TVMET_IMPLEMENT_MACRO(j1)
+TVMET_IMPLEMENT_MACRO(y0)
+TVMET_IMPLEMENT_MACRO(y1)
+TVMET_IMPLEMENT_MACRO(lgamma)
+/** \todo isnan etc. - default return is only an int! */
+
+TVMET_IMPLEMENT_MACRO(finite)
+#endif // defined(TVMET_HAVE_IEEE_MATH)
+
+#undef TVMET_IMPLEMENT_MACRO
+
+
+
+} // namespace tvmet
+
+#endif // TVMET_XPR_VECTOR_FUNCTIONS_H
+
+// Local Variables:
+// mode:C++
+// tab-width:8
+// End: