Colour sensors calibrated

Dependencies:   mbed-rtos mbed Servo QEI

Fork of ICRSEurobot13 by Thomas Branch

Files at this revision

API Documentation at this revision

Comitter:
madcowswe
Date:
Sat Apr 06 20:57:54 2013 +0000
Parent:
14:c638d4b9ee94
Child:
16:52250d8d8fce
Child:
18:10adf96f5416
Commit message:
Encoders fairly tuned, still has random noise in it

Changed in this revision

Processes/Printing/Printing.cpp Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
tvmet/AliasProxy.h Show annotated file Show diff for this revision Revisions of this file
tvmet/BinaryFunctionals.h Show annotated file Show diff for this revision Revisions of this file
tvmet/CommaInitializer.h Show annotated file Show diff for this revision Revisions of this file
tvmet/CompileTimeError.h Show annotated file Show diff for this revision Revisions of this file
tvmet/Extremum.h Show annotated file Show diff for this revision Revisions of this file
tvmet/Functional.h Show annotated file Show diff for this revision Revisions of this file
tvmet/Io.h Show annotated file Show diff for this revision Revisions of this file
tvmet/Matrix.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixEval.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixImpl.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixOperators.h Show annotated file Show diff for this revision Revisions of this file
tvmet/MatrixUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/NumericTraits.h Show annotated file Show diff for this revision Revisions of this file
tvmet/RunTimeError.h Show annotated file Show diff for this revision Revisions of this file
tvmet/TvmetBase.h Show annotated file Show diff for this revision Revisions of this file
tvmet/TypePromotion.h Show annotated file Show diff for this revision Revisions of this file
tvmet/UnaryFunctionals.h Show annotated file Show diff for this revision Revisions of this file
tvmet/Vector.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorEval.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorImpl.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorOperators.h Show annotated file Show diff for this revision Revisions of this file
tvmet/VectorUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config/config-gcc.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config/config-icc.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config/config-kcc.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config/config-pgi.h Show annotated file Show diff for this revision Revisions of this file
tvmet/config/config-vc71.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Gemm.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Gemmt.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Gemtm.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Gemtv.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Gemv.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Matrix.h Show annotated file Show diff for this revision Revisions of this file
tvmet/loop/Vector.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Gemm.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Gemmt.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Gemtm.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Gemtv.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Gemv.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Matrix.h Show annotated file Show diff for this revision Revisions of this file
tvmet/meta/Vector.h Show annotated file Show diff for this revision Revisions of this file
tvmet/tvmet.h Show annotated file Show diff for this revision Revisions of this file
tvmet/util/General.h Show annotated file Show diff for this revision Revisions of this file
tvmet/util/Incrementor.h Show annotated file Show diff for this revision Revisions of this file
tvmet/util/Random.h Show annotated file Show diff for this revision Revisions of this file
tvmet/util/Timer.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/BinOperator.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Eval.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Identity.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Literal.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MMProduct.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MMProductTransposed.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MMtProduct.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MVProduct.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Matrix.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixCol.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixDiag.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixOperators.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixRow.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixTranspose.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MatrixUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MtMProduct.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/MtVProduct.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Null.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/UnOperator.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/Vector.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/VectorBinaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/VectorFunctions.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/VectorOperators.h Show annotated file Show diff for this revision Revisions of this file
tvmet/xpr/VectorUnaryFunctions.h Show annotated file Show diff for this revision Revisions of this file
--- a/Processes/Printing/Printing.cpp	Sat Apr 06 15:43:47 2013 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-#include "Printing.h"
-#ifdef PRINTINGOFF
-void printingThread(void const*){Thread::wait(osWaitForever);}
-bool registerID(char, size_t){return true;}
-bool unregisterID(char) {return true;}
-bool updateval(char, float*, size_t){return true;}
-bool updateval(char id, float value){return true;}
-#else
-#include <iostream>
-using namespace std;
-
-size_t idlist[NUMIDS]; // Stores length of buffer 0 => unassigned
-float* buffarr[NUMIDS];
-volatile unsigned int newdataflags;
-
-bool registerID(char id, size_t length) {   
-    if (id < NUMIDS && !idlist[id]) {//check if the id is already taken
-        idlist[id] = length;
-        buffarr[id] = new float[length];
-        return true;
-    } else
-        return false;
-}
-bool unregisterID(char id) {
-    if (id < NUMIDS) {
-        idlist[id] = 0;
-        if (buffarr[id])
-            delete buffarr[id];
-        return true;
-    } else
-        return false;
-}
-
-bool updateval(char id, float* buffer, size_t length) {
-    //check if the id is registered, and has buffer of correct length
-    if (id < NUMIDS && idlist[id] == length && buffarr[id] && !(newdataflags & (1<<id))) {
-        for (size_t i = 0; i < length; i++)
-            buffarr[id][i] = buffer[i];
-        newdataflags |= (1<<id);
-        return true;
-    } else
-        return false;
-}
-
-bool updateval(char id, float value){
-    //check if the id is registered, and the old value has been written
-    if (id < NUMIDS && idlist[id] == 1 && buffarr[id] && !(newdataflags & (1<<id))) {
-        buffarr[id][0] = value;
-        newdataflags |= (1<<id);
-        return true;
-    } else
-        return false;
-}
-
-void printingThread(void const*){
-    newdataflags = 0;
-    for (int i = 0; i < NUMIDS; i++) {
-        idlist[i] = 0;
-        buffarr[i] = 0;
-    }
-
-
-    Thread::wait(3500);
-    while(true){   
-        // Send number of packets
-        char numtosend = 0;
-        for (unsigned int v = newdataflags; v; numtosend++){v &= v - 1;}        
-        cout.put(numtosend);
-
-        // Send packets
-        for (char id = 0; id < NUMIDS; id++) {
-            if (newdataflags & (1<<id)) {
-                cout.put(id);
-                cout.write((char*)buffarr[id], idlist[id] * sizeof(float));
-                newdataflags &= ~(1<<id);
-            }
-        }
-        cout << endl;
-        Thread::wait(200);
-    }
-}
-#endif
-
-
- 
\ No newline at end of file
--- a/main.cpp	Sat Apr 06 15:43:47 2013 +0000
+++ b/main.cpp	Sat Apr 06 20:57:54 2013 +0000
@@ -102,13 +102,16 @@
     //ledphototransistortest();
     //colourtest(); // Red SnR too low
     //cakesensortest();
-    //feedbacktest();
+    feedbacktest();
+    
+    /*
     DigitalOut l1(LED1);
     Thread p(printingThread,        NULL,   osPriorityNormal,   2048);
     l1=1;
     Thread a(printingtestthread,    NULL,   osPriorityNormal,   1024);
     Thread b(printingtestthread2,   NULL,   osPriorityNormal,   1024);
     Thread::wait(osWaitForever);
+    */
 }
 
 #include <cstdlib>
@@ -145,14 +148,14 @@
     Encoder Eright(P_ENC_RIGHT_A, P_ENC_RIGHT_B), Eleft(P_ENC_LEFT_A, P_ENC_LEFT_B);
     MainMotor mright(P_MOT_RIGHT_A, P_MOT_RIGHT_B), mleft(P_MOT_LEFT_A, P_MOT_LEFT_B);
     
-    float Pgain = -0.002;
-    float fwdspeed = -200/3.0f;
+    float Pgain = -0.005;
+    float fwdspeed = -400/3.0f;
     Timer timer;
     timer.start();
     
     while(true){
         float expecdist = fwdspeed * timer.read();
-        float errleft = Eleft.getPoint() - (expecdist*1.07f);
+        float errleft = Eleft.getPoint() - (expecdist*1.05);
         float errright = Eright.getPoint() - expecdist;
         
         mleft(max(min(errleft*Pgain, 0.4f), -0.4f));
@@ -350,12 +353,12 @@
 }
 
 void encodertest(){
-    Encoder E1(p28, p27);
-    Encoder E2(p29, p30);
+    Encoder E1(P_ENC_LEFT_A, P_ENC_LEFT_B);
+    //Encoder E2(P_ENC_RIGHT_A, P_ENC_RIGHT_B);
     Serial pc(USBTX, USBRX);
     while(true){
         wait(0.1);
-        pc.printf("Position is: %i \t %i \n\r", E1.getPoint(), E2.getPoint());
+        pc.printf("Position is: %i \t %i \n\r", E1.getPoint(), 0);//E2.getPoint());
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tvmet/AliasProxy.h	Sat Apr 06 20:57:54 2013 +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/tvmet/BinaryFunctionals.h	Sat Apr 06 20:57:54 2013 +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/tvmet/CommaInitializer.h	Sat Apr 06 20:57:54 2013 +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/tvmet/CompileTimeError.h	Sat Apr 06 20:57:54 2013 +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/tvmet/Extremum.h	Sat Apr 06 20:57:54 2013 +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/tvmet/Functional.h	Sat Apr 06 20:57:54 2013 +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/tvmet/Io.h	Sat Apr 06 20:57:54 2013 +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/tvmet/Matrix.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixBinaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixEval.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixImpl.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixOperators.h	Sat Apr 06 20:57:54 2013 +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/tvmet/MatrixUnaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/NumericTraits.h	Sat Apr 06 20:57:54 2013 +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/tvmet/RunTimeError.h	Sat Apr 06 20:57:54 2013 +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/tvmet/TvmetBase.h	Sat Apr 06 20:57:54 2013 +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/tvmet/TypePromotion.h	Sat Apr 06 20:57:54 2013 +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/tvmet/UnaryFunctionals.h	Sat Apr 06 20:57:54 2013 +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/tvmet/Vector.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorBinaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorEval.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorImpl.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorOperators.h	Sat Apr 06 20:57:54 2013 +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/tvmet/VectorUnaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config/config-gcc.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config/config-icc.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config/config-kcc.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config/config-pgi.h	Sat Apr 06 20:57:54 2013 +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/tvmet/config/config-vc71.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Gemm.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Gemmt.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Gemtm.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Gemtv.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Gemv.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Matrix.h	Sat Apr 06 20:57:54 2013 +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/tvmet/loop/Vector.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Gemm.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Gemmt.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Gemtm.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Gemtv.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Gemv.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Matrix.h	Sat Apr 06 20:57:54 2013 +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/tvmet/meta/Vector.h	Sat Apr 06 20:57:54 2013 +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/tvmet.h	Sat Apr 06 20:57:54 2013 +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/tvmet/util/General.h	Sat Apr 06 20:57:54 2013 +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/tvmet/util/Incrementor.h	Sat Apr 06 20:57:54 2013 +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/tvmet/util/Random.h	Sat Apr 06 20:57:54 2013 +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/tvmet/util/Timer.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/BinOperator.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Eval.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Identity.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Literal.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MMProduct.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MMProductTransposed.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MMtProduct.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MVProduct.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Matrix.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixBinaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixCol.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixDiag.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixOperators.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixRow.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixTranspose.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MatrixUnaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MtMProduct.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/MtVProduct.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Null.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/UnOperator.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/Vector.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/VectorBinaryFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/VectorFunctions.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/VectorOperators.h	Sat Apr 06 20:57:54 2013 +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/tvmet/xpr/VectorUnaryFunctions.h	Sat Apr 06 20:57:54 2013 +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: