From 744f892252bd08ec06c3d04ad8c15cda2b5a5417 Mon Sep 17 00:00:00 2001
From: Francois Henrotte <francois.henrotte@ulg.ac.be>
Date: Fri, 15 Feb 2013 14:51:04 +0000
Subject: [PATCH] quaternions library

---
 Mesh/stat_coordsys.h | 377 ++++++++++++++++++++++++++++++++
 Mesh/stat_cwmtx.h    |  56 +++++
 Mesh/stat_matrix.h   | 507 +++++++++++++++++++++++++++++++++++++++++++
 Mesh/stat_quatern.h  | 418 +++++++++++++++++++++++++++++++++++
 Mesh/stat_smatrix.h  | 467 +++++++++++++++++++++++++++++++++++++++
 Mesh/stat_svector.h  | 247 +++++++++++++++++++++
 Mesh/stat_vector.h   | 243 +++++++++++++++++++++
 7 files changed, 2315 insertions(+)
 create mode 100755 Mesh/stat_coordsys.h
 create mode 100755 Mesh/stat_cwmtx.h
 create mode 100755 Mesh/stat_matrix.h
 create mode 100755 Mesh/stat_quatern.h
 create mode 100755 Mesh/stat_smatrix.h
 create mode 100755 Mesh/stat_svector.h
 create mode 100755 Mesh/stat_vector.h

diff --git a/Mesh/stat_coordsys.h b/Mesh/stat_coordsys.h
new file mode 100755
index 0000000000..df818398cb
--- /dev/null
+++ b/Mesh/stat_coordsys.h
@@ -0,0 +1,377 @@
+// -*-c++-*-
+#ifndef IG_STAT_COORDSYS_H
+#define IG_STAT_COORDSYS_H
+
+// $Id: stat_coordsys.h,v 1.1.2.6 2005/05/30 09:14:25 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+#ifndef IG_STAT_SMATRIX_H
+#include "stat_smatrix.h"
+#endif
+
+#ifndef IG_STAT_QUATERNION_H
+#include "stat_quatern.h"
+#endif
+
+#ifndef IG_STAT_SVECTOR_H
+#include "stat_svector.h"
+#endif
+
+// CWTSSquareMatrix utilities for use in coordinate systems
+
+namespace CwMtx
+{
+
+  // NOTE: These template functions only work with floating point
+  // template arguments due to the use of sin(3), cos(3), tan(3), etc.
+
+  // PLEASE, READ THIS!!!
+
+  // Function smatFromEuler321(sclrAbout3, sclrAbout2, sclrAbout1)
+  // returns a transformation matrix which transforms coordinates from
+  // the reference axis system to coordinates in an axis system with
+  // Euler angles: sclrAbout3, sclrAbout2, sclrAbout1 relative to that
+  // reference axis system DO NOT CHANGE THIS DEFINITION!!!
+
+  // rotation about axis 3 (yaw angle), axis 2 (pitch angle) axis 1
+  // (roll angle)
+  template <class T>
+  CWTSSquareMatrix<3, T>
+  smatFromEuler321Angles(T sclrAbout3,
+			 T sclrAbout2,
+			 T sclrAbout1)
+  {
+    CWTSSquareMatrix<3, T> smat;
+
+    // to reduce the number of calls to CPU expensive sin(..) and
+    // cos(..) functions
+    T sin3 = sin(sclrAbout3);
+    T sin2 = sin(sclrAbout2);
+    T sin1 = sin(sclrAbout1);
+
+    T cos3 = cos(sclrAbout3);
+    T cos2 = cos(sclrAbout2);
+    T cos1 = cos(sclrAbout1);
+
+    // first row
+    smat[0][0] =  cos3*cos2;
+    smat[0][1] =  sin3*cos2;
+    smat[0][2] = -sin2;
+
+    // second row
+    smat[1][0] = -sin3*cos1 + cos3*sin2*sin1;
+    smat[1][1] =  cos3*cos1 + sin3*sin2*sin1;
+    smat[1][2] =  cos2*sin1;
+
+    // third row
+    smat[2][0] =  sin3*sin1 + cos3*sin2*cos1;
+    smat[2][1] = -cos3*sin1 + sin3*sin2*cos1;
+    smat[2][2] =  cos2*cos1;
+
+    return smat;
+  }
+
+  // Next three functions calculate Euler angles from a transformation matrix
+  // WARNING!!! They suffer from the ubiquitos singularities at 0, pi, 2*pi,
+  // etc.
+
+  // yaw angle, rotation angle about Z-axis
+  template <class T>
+  T
+  euler321Angle3FromSmat(const CWTSSquareMatrix<3, T> &smat)
+  {
+    return atan2(smat[0][1], smat[0][0]);
+  }
+
+  // pitch angle, rotation angle about Y-axis
+  template <class T>
+  T
+  euler321Angle2FromSmat(const CWTSSquareMatrix<3, T> &smat)
+  {
+    return asin(-smat[0][2]);
+  }
+
+  // roll angle, rotation angle about X-axis
+  template <class T>
+  T
+  euler321Angle1FromSmat(const CWTSSquareMatrix<3, T> &smat)
+  {
+    return atan2(smat[1][2], smat[2][2]);
+  }
+
+  // CWTSQuaternion utilities for use in coordinate systems
+
+  // PLEASE, READ THIS!!!
+
+  // next three functions calculate Euler angles from a quaternion
+  // that represents a rigid body's attitude WARNING!!! They do suffer
+  // from the ubiquitos singularities around 0, pi and 2*pi.
+
+  // yaw angle, rotation angle about Z-axis
+  template <class T>
+  T
+  euler321Angle3FromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    // to reduce the number of calls to the subscript operator
+    T qtn0 = qtn[0];
+    T qtn1 = qtn[1];
+    T qtn2 = qtn[2];
+    T qtn3 = qtn[3];
+
+    // NOTE: Speed tip from Jeffrey T Duncan: use the identity: 1 =
+    // q0^2 + q1^2 + q2^2 + q3^2 which simplifies: q0^2 - q1^2 -
+    // q2^2 + q3^2 down to: 2*(q0^2 + q3^2) - 1
+    return atan2(2*(qtn0*qtn1 + qtn2*qtn3),
+		 2*(qtn0*qtn0 + qtn3*qtn3) - 1);
+  }
+
+  // pitch angle, rotation angle about Y-axis
+  template <class T>
+  T
+  euler321Angle2FromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    return asin(-2*(qtn[0]*qtn[2] - qtn[1]*qtn[3]));
+  }
+
+  // roll angle, rotation angle about X-axis
+  template <class T>
+  T
+  euler321Angle1FromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    // to reduce the number of calls to the subscript operator
+    T qtn0 = qtn[0];
+    T qtn1 = qtn[1];
+    T qtn2 = qtn[2];
+    T qtn3 = qtn[3];
+
+    return atan2(2*(qtn1*qtn2 + qtn0*qtn3),
+		 2*(qtn2*qtn2 + qtn3*qtn3) - 1);
+  }
+
+  // Function QtnFromEulerAxisAndAngle returns a quaternion
+  // representing a rigid body's attitude from its Euler axis and
+  // angle. NOTE: Argument vector svecEulerAxis MUST be a unit vector.
+  template <class T>
+  CWTSQuaternion<T>
+  qtnFromEulerAxisAndAngle(const CWTSSpaceVector<T> &svecEulerAxis,
+			   const T &sclrEulerAngle)
+  {
+    return CWTSQuaternion<T>(1, svecEulerAxis, 0.5*sclrEulerAngle);
+  }
+
+  // returns Euler axis
+  template <class T>
+  CWTSSpaceVector<T>
+  eulerAxisFromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    T sclrTmp = sqrt(1 - qtn[3]*qtn[3]);
+
+    return CWTSSpaceVector<T>(qtn[0]/sclrTmp,
+			      qtn[1]/sclrTmp,
+			      qtn[2]/sclrTmp);
+  }
+
+  // returns Euler angle
+  template <class T>
+  T
+  eulerAngleFromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    return 2*acos(qtn[3]);
+  }
+
+  // Function QtnFromEuler321 returns a quaternion representing a
+  // rigid body's attitude. The quaternion elements correspond to the
+  // Euler symmetric parameters of the body. The body's attitude must
+  // be entered in Euler angle representation with rotation order
+  // 3-2-1, i.e. first about Z-axis next about Y-axis and finally
+  // about X-axis.
+
+  // rotation about axis 3 (yaw angle), axis 2 (pitch angle) axis 1
+  // (roll angle)
+  template <class T>
+  CWTSQuaternion<T>
+  qtnFromEuler321Angles(T sclrAbout3,
+			T sclrAbout2,
+			T sclrAbout1)
+  {
+    return
+      CWTSQuaternion<T>(1, CWTSSpaceVector<T>(0, 0, 1), 0.5*sclrAbout3)
+      *CWTSQuaternion<T>(1, CWTSSpaceVector<T>(0, 1, 0), 0.5*sclrAbout2)
+      *CWTSQuaternion<T>(1, CWTSSpaceVector<T>(1, 0, 0), 0.5*sclrAbout1);
+  }
+
+  // SmatFromQtn returns the transformation matrix corresponding to a
+  // quaternion
+  template <class T>
+  CWTSSquareMatrix<3, T>
+  smatFromQtn(const CWTSQuaternion<T> &qtn)
+  {
+    CWTSSquareMatrix<3, T> smat;
+
+    // to reduce the number of calls to the subscript operator
+    T qtn0 = qtn[0];
+    T qtn1 = qtn[1];
+    T qtn2 = qtn[2];
+    T qtn3 = qtn[3];
+
+    smat[0][0] = 1 - 2*(qtn1*qtn1 + qtn2*qtn2);
+    smat[0][1] = 2*(qtn0*qtn1 + qtn2*qtn3);
+    smat[0][2] = 2*(qtn0*qtn2 - qtn1*qtn3);
+
+    smat[1][0] = 2*(qtn0*qtn1 - qtn2*qtn3);
+    smat[1][1] = 1 - 2*(qtn0*qtn0 + qtn2*qtn2);
+    smat[1][2] = 2*(qtn1*qtn2 + qtn0*qtn3);
+
+    smat[2][0] = 2*(qtn0*qtn2 + qtn1*qtn3);
+    smat[2][1] = 2*(qtn1*qtn2 - qtn0*qtn3);
+    smat[2][2] = 1 - 2*(qtn0*qtn0 + qtn1*qtn1);
+
+    return smat;
+  }
+
+  // QtnFromSmat returns the quaternion corresponding to a
+  // transformation matrix
+  template <class T>
+  CWTSQuaternion<T>
+  qtnFromSmat(const CWTSSquareMatrix<3, T> &smat)
+  {
+    // Check trace to prevent loss of accuracy
+    T sclrTmp = tr(smat);
+    CWTSQuaternion<T> qtn;
+
+    if(sclrTmp > 0)
+      {
+	// No trouble, we can use standard expression
+	sclrTmp = 0.5*sqrt(1 + sclrTmp);
+	qtn[0] = 0.25*(smat[1][2] - smat[2][1])/sclrTmp;
+	qtn[1] = 0.25*(smat[2][0] - smat[0][2])/sclrTmp;
+	qtn[2] = 0.25*(smat[0][1] - smat[1][0])/sclrTmp;
+	qtn[3] = sclrTmp;
+      }
+    else
+      {
+	// We could be in trouble, so we have to take
+	// precautions. NOTE: Parts of this piece of code were taken
+	// from the example in the article "Rotating Objects Using
+	// Quaternions" in Game Developer Magazine written by Nick
+	// Bobick, july 3, 1998, vol. 2, issue 26.
+	int i = 0;
+	if (smat[1][1] > smat[0][0]) i = 1;
+	if (smat[2][2] > smat[i][i]) i = 2;
+
+	switch (i)
+	  {
+	  case 0:
+	    sclrTmp = 0.5*sqrt(1 + smat[0][0] - smat[1][1] - smat[2][2]);
+	    qtn[0] = sclrTmp;
+	    qtn[1] = 0.25*(smat[0][1] + smat[1][0])/sclrTmp;
+	    qtn[2] = 0.25*(smat[0][2] + smat[2][0])/sclrTmp;
+	    qtn[3] = 0.25*(smat[1][2] - smat[2][1])/sclrTmp;
+	    break;
+
+	  case 1:
+	    sclrTmp = 0.5*sqrt(1 - smat[0][0] + smat[1][1] - smat[2][2]);
+	    qtn[0] = 0.25*(smat[1][0] + smat[0][1])/sclrTmp;
+	    qtn[1] = sclrTmp;
+	    qtn[2] = 0.25*(smat[1][2] + smat[2][1])/sclrTmp;
+	    qtn[3] = 0.25*(smat[2][0] - smat[0][2])/sclrTmp;
+	    break;
+
+	  case 2:
+	    sclrTmp = 0.5*sqrt(1 - smat[0][0] - smat[1][1] + smat[2][2]);
+	    qtn[0] = 0.25*(smat[2][0] + smat[0][2])/sclrTmp;
+	    qtn[1] = 0.25*(smat[2][1] + smat[1][2])/sclrTmp;
+	    qtn[2] = sclrTmp;
+	    qtn[3] = 0.25*(smat[0][1] - smat[1][0])/sclrTmp;
+
+	    break;
+	  }
+      }
+
+    return qtn;
+  }
+
+  // NOTE: This function duplicates eulerAxisFromQtn(qtn) it only has
+  // a different return type.
+  template <class T>
+  CWTSVector<3, T>
+  axisAngleFromQtn( const CWTSQuaternion<T> &qtn )
+  {
+    return eulerAxisFromQtn(qtn);
+  }
+
+  // NOTE: This function duplicates qtnFromEulerAxisAndAngle(..) it
+  // only has a different function profile.
+  template <class T>
+  CWTSQuaternion<T>
+  qtnFromAxisAndAngle(const CWTSVector<3, T> &vAxis,
+                      const T sAngle)
+  {
+    return qtnFromEulerAxisAndAngle(vAxis, sAngle);
+  }
+
+  template <class T>
+  CWTSSquareMatrix<3, T>
+  changeOfBasis(CWTSSpaceVector< CWTSSpaceVector<T> >&from, 
+		CWTSSpaceVector< CWTSSpaceVector<T> >&to)
+  {
+    CWTSSquareMatrix<3, T> A;
+
+    // This is a "change of basis" from the "from" frame to the "to"
+    // frame.  the "to" frame is typically the "Standard basis"
+    // frame.  The "from" is a frame that represents the current
+    // orientation of the object in the shape of an orthonormal
+    // tripod.
+
+    enum { x , y , z };
+
+    // _X,_Y,_Z is typically the standard basis frame.
+
+    //  | x^_X , y^_X , z^_X |
+    //  | x^_Y , y^_Y , z^_Y |
+    //  | x^_Z , y^_Z , z^_Z |
+	
+    A[0][0] = from[x]*to[x];
+    A[0][1] = from[y]*to[x];
+    A[0][2] = from[z]*to[x];
+
+    A[1][0] = from[x]*to[y];
+    A[1][1] = from[y]*to[y];
+    A[1][2] = from[z]*to[y];
+
+    A[2][0] = from[x]*to[z];
+    A[2][1] = from[y]*to[z];
+    A[2][2] = from[z]*to[z];
+	
+    // This is simply the transpose done manually which would save
+    // and inverse call.
+    //	| x ^ _X , x ^ _Y , x ^ _Z |
+    //	| y ^ _X , y ^ _Y , y ^ _Z |
+    //	| z ^ _X , z ^ _Y , z ^ _Z |
+	
+    // And finally we return the matrix that takes the "from" frame
+    // to the "to"/"Standard basis" frame.
+    return A;
+  }
+
+}
+
+#endif   // IG_STAT_COORDSYS_H
diff --git a/Mesh/stat_cwmtx.h b/Mesh/stat_cwmtx.h
new file mode 100755
index 0000000000..fc4cc35e51
--- /dev/null
+++ b/Mesh/stat_cwmtx.h
@@ -0,0 +1,56 @@
+// -*-c++-*-
+#ifndef IG_STAT_CWMTX_H
+#define IG_STAT_CWMTX_H
+
+// $Id: stat_cwmtx.h,v 1.1.2.1 2002/01/15 01:25:21 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+//---------------------------------------------------------------------------
+//
+// Master include file for CWTSMatrix and CWTSVector classes
+//
+//---------------------------------------------------------------------------
+
+#ifndef IG_STAT_MATRIX_H
+#include "stat_matrix.h"
+#endif
+
+#ifndef IG_STAT_SMATRIX_H
+#include "stat_smatrix.h"
+#endif
+
+#ifndef IG_STAT_VECTOR_H
+#include "stat_vector.h"
+#endif
+
+#ifndef IG_STAT_SVECTOR_H
+#include "stat_svector.h"
+#endif
+
+#ifndef IG_STAT_QUATERN_H
+#include "stat_quatern.h"
+#endif
+
+#ifndef IG_STAT_COORDSYS_H
+#include "stat_coordsys.h"
+#endif
+
+#endif   // IG_STAT_CWMTX_H
diff --git a/Mesh/stat_matrix.h b/Mesh/stat_matrix.h
new file mode 100755
index 0000000000..16526ff74f
--- /dev/null
+++ b/Mesh/stat_matrix.h
@@ -0,0 +1,507 @@
+// -*-c++-*-
+#ifndef IG_STAT_MATRIX_H
+#define IG_STAT_MATRIX_H
+
+// $Id: stat_matrix.h,v 1.1.2.12 2005/07/02 15:41:46 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+#include <iostream>
+
+// CWMatrix class
+
+// This library was designed to mirror as closely as possible the
+// notation used in mathematical writing. A matrix is indexed:
+// matMatrixName[row][col].
+
+// CAUTION!!!
+
+// This matrix library was implemented with emphasis on
+// speed. Consequently no attempts were made to trap and report
+// errors. It is left entirely to the user to write code that does not
+// cause errors within the matrix routines.
+
+namespace CwMtx
+{
+  using std::ostream;
+  
+  // forward declarations
+
+  template <unsigned r, unsigned c, class T>
+  class CWTSMatrix;
+
+  template <unsigned r, class T>
+  class CWTSSquareMatrix;
+
+  template <unsigned r, class T>
+  class CWTSVector;
+
+  template <class T>
+  class CWTSSpaceVector;
+
+  template <class T>
+  class CWTSQuaternion;
+
+  // Template classes that create zero "objects".
+
+  template <class T>
+  class CWTSZero
+  {
+  public:
+    operator T() { return 0; }
+  };
+
+  template <unsigned r, unsigned c, class T>
+  class CWTSZero< CWTSMatrix<r, c, T> >:
+    public CWTSMatrix<r, c, T>
+  {
+  public:
+    CWTSZero() { fill(CWTSZero<T>()); }
+  };
+
+  template <unsigned r, class T>
+  class CWTSZero< CWTSSquareMatrix<r, T> >:
+    public CWTSSquareMatrix<r, T>
+  {
+  public:
+    CWTSZero() { fill(CWTSZero<T>()); }
+  };
+
+  template <unsigned r, class T>
+  class CWTSZero< CWTSVector<r, T> >:
+    public CWTSVector<r, T>
+  {
+  public:
+    CWTSZero() { fill(CWTSZero<T>()); }
+  };
+
+  template <class T>
+  class CWTSZero< CWTSSpaceVector<T> >:
+    public CWTSSpaceVector<T>
+  {
+  public:
+    CWTSZero() { fill(CWTSZero<T>()); }
+  };
+
+  template <class T>
+  class CWTSZero< CWTSQuaternion<T> >:
+    public CWTSQuaternion<T>
+  {
+  public:
+    CWTSZero() { fill(CWTSZero<T>()); }
+  };
+
+  // Template classes that create unity "objects".
+
+  template <class T>
+  class CWTSUnity
+  {
+  public:
+    operator T() { return 1; }
+  };
+
+  // NOTE: Only a matrix with an equal number of rows and columns can
+  // be a unity matrix.
+  template <unsigned r, class T>
+  class CWTSUnity< CWTSMatrix<r, r, T> >:
+    public CWTSSquareMatrix<r, T>
+  {
+  public:
+    CWTSUnity() { this->makeUnity(); }
+  };
+
+  template <unsigned r, class T>
+  class CWTSUnity< CWTSSquareMatrix<r, T> >:
+    public CWTSSquareMatrix<r, T>
+  {
+  public:
+    CWTSUnity() { this->makeUnity(); }
+  };
+
+  template <class T>
+  class CWTSUnity< CWTSQuaternion<T> >:
+    public CWTSQuaternion<T>
+  {
+  public:
+    CWTSUnity()
+    {
+      (*this)[0] = (*this)[1] = (*this)[2] = CWTSZero<T>();
+      (*this)[3] = CWTSUnity<T>();
+    }
+  };
+
+  // This template defaults to double. Most of the time this template
+  // will be working with math functions that only work with
+  // doubles. For example, the transcendental function sin(x) takes
+  // and returns a double which would force the compiler to convert
+  // back and forth from some other data type to a double.
+
+  // prefix mat
+  template <unsigned r, unsigned c, class T = double>
+  class CWTSMatrix
+  {
+  public:
+    typedef T element;
+
+    CWTSMatrix() {}
+    CWTSMatrix(const CWTSMatrix &);
+
+    ~CWTSMatrix() {}
+
+    unsigned getRows() const { return r; }
+    unsigned getCols() const { return c; }
+
+    // basic matrix operations
+
+    // returns a row of modifyable elements
+    T* operator [](unsigned irow) { return m_rgrow[irow]; }
+    // returns a row of non-modifyable elements
+    const T* operator [](unsigned irow) const { return m_rgrow[irow]; }
+
+    CWTSMatrix operator +(const CWTSMatrix &) const;
+    CWTSMatrix operator -(const CWTSMatrix &) const;
+    CWTSMatrix operator -() const;
+    CWTSMatrix operator *(const T &) const;
+    CWTSMatrix operator /(const T &value) const;
+
+    // not inherited
+    CWTSMatrix & operator =(const CWTSMatrix &);
+    CWTSMatrix & operator +=(const CWTSMatrix &);
+    CWTSMatrix & operator -=(const CWTSMatrix &);
+    CWTSMatrix & operator *=(const T &);
+    CWTSMatrix & operator /=(const T &value);
+
+    bool operator ==(const CWTSMatrix &) const;
+    bool operator !=(const CWTSMatrix &mat) const;
+
+    void interchangeRows(unsigned, unsigned);
+    void addRowToRow(unsigned, unsigned, const T & = CWTSUnity<T>());
+    void multiplyRow(unsigned, const T &);
+
+    // fills the whole array with a value.
+    void fill(const T &);
+    // stores matrix + matrix in this
+    void storeSum(const CWTSMatrix &, const CWTSMatrix &);
+    // stores CWMatrix at indicated position in this
+    template <unsigned r2, unsigned c2>
+    void storeAtPosition(unsigned, unsigned, const CWTSMatrix<r2, c2, T> &);
+
+  private:
+    // an array of rows
+    T m_rgrow[r][c];
+  };
+
+  template <unsigned r, unsigned c, class T >
+  inline CWTSMatrix<r, c, T>::CWTSMatrix(const CWTSMatrix<r, c, T> &mat)
+  {
+    // copy contents of input matrix
+    (*this) = mat;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> 
+  CWTSMatrix<r, c, T>::operator +(const CWTSMatrix<r, c, T> &mat) const
+  {
+    // copy this and add argument
+    return CWTSMatrix(*this) += mat;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> 
+  CWTSMatrix<r, c, T>::operator -(const CWTSMatrix<r, c, T> &mat) const
+  {
+    // copy this and subtract argument
+    return CWTSMatrix(*this) -= mat;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T>
+  CWTSMatrix<r, c, T>::operator -() const
+  {
+    return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T>
+  CWTSMatrix<r, c, T>::operator *(const T &value) const
+  {
+    // copy this and multiply by argument
+    return CWTSMatrix(*this) *= value;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  inline CWTSMatrix<r, c, T>
+  CWTSMatrix<r, c, T>::operator /(const T &value) const
+  {
+    return (*this)*(CWTSUnity<T>()/value);
+  }
+
+  // assignment operator
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> & 
+  CWTSMatrix<r, c, T>::operator =(const CWTSMatrix<r, c, T> &mat)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] = mat.m_rgrow[irow][icol];
+	  }
+      }
+
+    return (*this);
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> & 
+  CWTSMatrix<r, c, T>::operator +=(const CWTSMatrix<r, c, T> &mat)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] += mat.m_rgrow[irow][icol];
+	  }
+      }
+
+    return (*this);
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> & 
+  CWTSMatrix<r, c, T>::operator -=(const CWTSMatrix<r, c, T> &mat)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] -= mat.m_rgrow[irow][icol];
+	  }
+      }
+
+    return (*this);
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T> &
+  CWTSMatrix<r, c, T>::operator *=(const T &value)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] *= value;
+	  }
+      }
+
+    return (*this);
+  }
+
+  template <unsigned r, unsigned c, class T>
+  inline CWTSMatrix<r, c, T> &
+  CWTSMatrix<r, c, T>::operator /=(const T &value)
+  {
+    return (*this) *= CWTSUnity<T>()/value;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  bool
+  CWTSMatrix<r, c, T>::operator ==(const CWTSMatrix<r, c, T> &mat) const
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    if (m_rgrow[irow][icol] != mat.m_rgrow[irow][icol])
+	      {
+		return false;
+	      }
+	  }
+      }
+
+    return true;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  inline bool
+  CWTSMatrix<r, c, T>::operator !=(const CWTSMatrix &mat) const
+  {
+    return !( (*this) == mat );
+  }
+
+  template <unsigned r, unsigned c, class T>
+  void
+  CWTSMatrix<r, c, T>::fill(const T &elemFill)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] = elemFill;
+	  }
+      }
+  }
+
+  // stores mat1 + mat2 in this
+  template <unsigned r, unsigned c, class T>
+  void
+  CWTSMatrix<r, c, T>::storeSum(const CWTSMatrix<r, c, T> &mat1,
+				const CWTSMatrix<r, c, T> &mat2)
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    m_rgrow[irow][icol] = 
+	      mat1.m_rgrow[irow][icol] + mat2.m_rgrow[irow][icol];
+	  }
+      }
+  }
+
+  template <unsigned r, unsigned c, class T>
+  template <unsigned r2, unsigned c2>
+  void
+  CWTSMatrix<r, c, T>::storeAtPosition(unsigned irowStart,
+				       unsigned icolStart,
+				       const CWTSMatrix<r2, c2, T> &mat)
+  {
+    for (unsigned irow = 0; irow < r2; ++irow)
+      {
+	for (unsigned icol = 0; icol < c2; ++icol)
+	  {
+	    m_rgrow[irow + irowStart][icol + icolStart] = mat[irow][icol];
+	  }
+      }
+  }
+
+  template <unsigned r, unsigned c, class T>
+  void
+  CWTSMatrix<r, c, T>::interchangeRows(unsigned irow1, unsigned irow2)
+  {
+    T elemTmp;
+
+    for (unsigned icol = 0; icol < c; ++icol)
+      {
+	elemTmp = m_rgrow[irow1][icol];
+	m_rgrow[irow1][icol] = m_rgrow[irow2][icol];
+	m_rgrow[irow2][icol] = elemTmp;
+      }
+  }
+
+  template <unsigned r, unsigned c, class T>
+  void
+  CWTSMatrix<r, c, T>::multiplyRow(unsigned irow, const T &value)
+  {
+    for (unsigned icol = 0; icol < c; ++icol)
+      {
+	m_rgrow[irow][icol] *= value;
+      }
+  }
+
+  template <unsigned r, unsigned c, class T>
+  void
+  CWTSMatrix<r, c, T>::addRowToRow(unsigned irowSrc,
+				   unsigned irowDest,
+				   const T &value)
+  {
+    for (unsigned icol = 0; icol < c; ++icol)
+      {
+	m_rgrow[irowDest][icol] += m_rgrow[irowSrc][icol]*value;
+      }
+  }
+
+  // template functions designed to work with the base matrix class
+
+  template <unsigned r, unsigned c, class T>
+  inline CWTSMatrix<r, c, T>
+  operator *(const T &value, const CWTSMatrix<r, c, T> &mat)
+  {
+    return (mat*value);
+  }
+
+  template <unsigned r, unsigned c, unsigned c2, class T>
+  CWTSMatrix<r, c2, T>
+  operator *(CWTSMatrix<r, c, T> mat1, const CWTSMatrix<c, c2, T> &mat2)
+  {
+    CWTSMatrix<r, c2, T> matResult;
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c2; ++icol)
+	  {
+	    matResult[irow][icol] = CWTSZero<T>();
+
+	    for (unsigned icol2 = 0; icol2 < c; ++icol2)
+	      {
+		matResult[irow][icol] += mat1[irow][icol2]*mat2[icol2][icol];
+	      }
+	  }
+      }
+
+    return matResult;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  CWTSMatrix<r, c, T>
+  transpose(const CWTSMatrix<c, r, T> &mat)
+  {
+    CWTSMatrix<r, c, T> matTranspose;
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    matTranspose[irow][icol] = mat[icol][irow];
+	  }
+      }
+
+    return matTranspose;
+  }
+
+  template <unsigned r, unsigned c, class T>
+  ostream &
+  operator <<(ostream &os, const CWTSMatrix<r, c, T> &mtx)
+  {
+    os << "[" ;
+
+    for (unsigned i = 0; i < r; i++)
+      {
+	if (i > 0)
+	  {
+	    os << "; ";
+	  }
+
+        os << mtx[i][0];
+
+	for (unsigned j = 1; j < c; j++)
+	  {
+	    os << ", " << mtx[i][j];
+	  }
+      }
+
+    os << "]";
+
+    return os;
+  }
+
+}
+
+#endif // IG_STAT_MATRIX_H
+
diff --git a/Mesh/stat_quatern.h b/Mesh/stat_quatern.h
new file mode 100755
index 0000000000..1d4538e169
--- /dev/null
+++ b/Mesh/stat_quatern.h
@@ -0,0 +1,418 @@
+// -*-c++-*-
+#ifndef IG_STAT_QUATERN_H
+#define IG_STAT_QUATERN_H
+
+// $Id: stat_quatern.h,v 1.1.2.8 2005/07/02 15:41:46 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+// Copyright (C) 2000  Jiri Ecer (constructor from exponential form)
+
+// 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 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
+
+#ifndef IG_STAT_SVECTOR_H
+#include "stat_svector.h"
+#endif
+
+namespace CwMtx
+{
+  using std::exp;
+  using std::log;
+
+  // prefix qtn
+  template <class T = double>
+  class CWTSQuaternion : public CWTSVector<4, T>
+  {
+  public:
+    CWTSQuaternion(): CWTSVector<4, T>() {}
+    CWTSQuaternion(const CWTSMatrix<4, 1, T> &mat): CWTSVector<4, T>(mat) {}
+    // assumption: vec has four elements
+    CWTSQuaternion(const CWTSVector<4, T> &vec): CWTSVector<4, T>(vec) {}
+    CWTSQuaternion(const CWTSQuaternion &qtn): CWTSVector<4, T>(qtn) {}
+    // the space vector will become the quaternion's imaginary part, T
+    // will become its real part
+    CWTSQuaternion(const CWTSSpaceVector<T> &, const T & = CWTSZero<T>());
+    // creates a quaternion, index runs from left to right
+    CWTSQuaternion(const T &, const T &, const T &, const T &);
+    // creates a quaternion from a scalar
+    CWTSQuaternion(const T &);
+
+    // constructor from exponential form: q = r*exp(svec*angle), svec
+    // should be a unity vector, angle is in radians
+    CWTSQuaternion(const T &r, const CWTSSpaceVector<T> &svec, const T &angle);
+
+    ~CWTSQuaternion() {}
+
+    CWTSQuaternion operator +(const CWTSQuaternion &) const;
+    CWTSQuaternion operator -(const CWTSQuaternion &) const;
+    CWTSQuaternion operator -() const;
+    CWTSQuaternion operator *(const T &) const;
+    CWTSQuaternion operator *(const CWTSQuaternion &) const;
+    CWTSQuaternion operator /(const T &value) const;
+    CWTSQuaternion operator /(const CWTSQuaternion &) const;
+
+    // not inherited
+    CWTSQuaternion & operator =(const CWTSQuaternion &);
+    CWTSQuaternion & operator +=(const CWTSQuaternion &);
+    CWTSQuaternion & operator -=(const CWTSQuaternion &);
+    CWTSQuaternion & operator *=(const T &);
+    CWTSQuaternion & operator *=(const CWTSQuaternion &);
+    CWTSQuaternion & operator /=(const T &);
+    CWTSQuaternion & operator /=(const CWTSQuaternion &);
+
+    // stores product of qtn*qtn in this
+    void storeProduct(const CWTSQuaternion &, const CWTSQuaternion &);
+    // stores conjugate of argument in this
+    void storeConjugate(const CWTSQuaternion &);
+    // makes this its own conjugate
+    void makeConjugate();
+
+    // returns a unit quaternion with same direction as this
+    CWTSQuaternion unit() const { return (*this)/(this->norm()); }
+  };
+
+  template <class T>
+  inline CWTSQuaternion<T>::CWTSQuaternion(const T &elemIm0,
+					   const T &elemIm1,
+					   const T &elemIm2,
+					   const T &elemReal)
+    :
+    CWTSVector<4, T>()
+  {
+    (*this)[0] = elemIm0;
+    (*this)[1] = elemIm1;
+    (*this)[2] = elemIm2;
+    (*this)[3] = elemReal;
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T>::CWTSQuaternion(const T &elemReal)
+  {
+    (*this)[0] = CWTSZero<T>();
+    (*this)[1] = CWTSZero<T>();
+    (*this)[2] = CWTSZero<T>();
+    (*this)[3] = elemReal;
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T>::CWTSQuaternion(const CWTSSpaceVector<T> &svecIm,
+					   const T &elemReal)
+    :
+    CWTSVector<4, T>()
+  {
+    (*this)[0] = svecIm[0];
+    (*this)[1] = svecIm[1];
+    (*this)[2] = svecIm[2];
+    (*this)[3] = elemReal;
+  }
+
+  // NOTE: This only works with template arguments that can be
+  // converted to floating point types due to the use of sin(3) and
+  // cos(3).
+  template <class T>
+  CWTSQuaternion<T>::CWTSQuaternion(const T &r,
+				    const CWTSSpaceVector<T> &svec,
+				    const T &angle)
+    :
+    CWTSVector<4, T>()
+  {
+    T rsina = r*sin(angle);
+
+    (*this)[0] = svec[0]*rsina;
+    (*this)[1] = svec[1]*rsina;
+    (*this)[2] = svec[2]*rsina;
+    (*this)[3] = r*cos(angle);
+  }
+
+  // not inherited
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator =(const CWTSQuaternion<T> &qtn)
+  {
+    return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator=(qtn));
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator +=(const CWTSQuaternion<T> &qtn)
+  {
+    return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator+=(qtn));
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator -=(const CWTSQuaternion<T> &qtn)
+  {
+    return static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator-=(qtn));
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator *=(const T &value)
+  {
+    return
+      static_cast<CWTSQuaternion &>(CWTSMatrix<4, 1, T>::operator*=(value));
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator *=(const CWTSQuaternion<T> &qtn)
+  {
+    return (*this) = (*this)*qtn;
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator /=(const T &value)
+  {
+    return (*this) *= CWTSUnity<T>()/value;
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T> &
+  CWTSQuaternion<T>::operator /=(const CWTSQuaternion<T> &qtn)
+  {
+    return (*this) = (*this)/qtn;
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator +(const CWTSQuaternion<T> &qtn) const
+  {
+    return CWTSQuaternion(*this) += qtn;
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator -(const CWTSQuaternion<T> &qtn) const
+  {
+    return CWTSQuaternion(*this) -= qtn;
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator -() const
+  {
+    return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator *(const T &value) const
+  {
+    return CWTSQuaternion(*this) *= value;
+  }
+
+  template <class T>
+  inline CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator /(const T &value) const
+  {
+    return (*this)*(CWTSUnity<T>()/value);
+  }
+
+  template <class T>
+  void
+  CWTSQuaternion<T>::storeProduct(const CWTSQuaternion<T> &qtnLeft,
+				  const CWTSQuaternion<T> &qtnRight)
+  {
+    // to reduce the number of calls to the subscript operator
+    T qtnLeft0 = qtnLeft[0];
+    T qtnLeft1 = qtnLeft[1];
+    T qtnLeft2 = qtnLeft[2];
+    T qtnLeft3 = qtnLeft[3];
+
+    T qtnRight0 = qtnRight[0];
+    T qtnRight1 = qtnRight[1];
+    T qtnRight2 = qtnRight[2];
+    T qtnRight3 = qtnRight[3];
+
+    (*this)[0] =
+      qtnLeft0*qtnRight3 + qtnLeft1*qtnRight2
+      - qtnLeft2*qtnRight1 + qtnLeft3*qtnRight0;
+
+    (*this)[1] =
+      -qtnLeft0*qtnRight2 + qtnLeft1*qtnRight3
+      + qtnLeft2*qtnRight0 + qtnLeft3*qtnRight1;
+
+    (*this)[2] =
+      qtnLeft0*qtnRight1 - qtnLeft1*qtnRight0
+      + qtnLeft2*qtnRight3 + qtnLeft3*qtnRight2;
+
+    (*this)[3] =
+      -qtnLeft0*qtnRight0 - qtnLeft1*qtnRight1
+      - qtnLeft2*qtnRight2 + qtnLeft3*qtnRight3;
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator *(const CWTSQuaternion<T> &qtn) const
+  {
+    CWTSQuaternion qtnResult;
+    qtnResult.storeProduct(*this, qtn);
+    return qtnResult;
+  }
+
+  template <class T>
+  CWTSQuaternion<T>
+  CWTSQuaternion<T>::operator /(const CWTSQuaternion<T> &qtn) const
+  {
+    return (*this)*inv(qtn);
+  }
+
+  // stores conjugate of argument in this
+  template <class T>
+  void
+  CWTSQuaternion<T>::storeConjugate(const CWTSQuaternion<T> &qtn)
+  {
+    // copy argument into this
+    (*this) = qtn;
+    makeConjugate();
+  }
+
+  template <class T>
+  void
+  CWTSQuaternion<T>::makeConjugate()
+  {
+    T tmp = CWTSZero<T>() - CWTSUnity<T>();
+
+    (*this)[0] *= tmp;
+    (*this)[1] *= tmp;
+    (*this)[2] *= tmp;
+  }
+
+  // template functions designed work with the Quaternion class.
+
+  template <class T>
+  inline CWTSQuaternion<T>
+  operator *(const T &value, const CWTSQuaternion<T> &qtn)
+  {
+    return qtn*value;
+  }
+
+  // return real part of a quaternion
+  template <class T>
+  inline T
+  re(const CWTSQuaternion<T> &qtn)
+  {
+    return qtn[3];
+  }
+
+  // returns imaginary (vector) part of a quaternion
+  template <class T>
+  CWTSSpaceVector<T>
+  im(const CWTSQuaternion<T> &qtn)
+  {
+    return CWTSSpaceVector<T>(qtn[0], qtn[1], qtn[2]);
+  }
+
+  // the conjugate
+  template <class T>
+  CWTSQuaternion<T>
+  conj(const CWTSQuaternion<T> &qtn)
+  {
+    // copy input quaternion
+    CWTSQuaternion<T> qtnResult(qtn);
+    qtnResult.makeConjugate();
+    return qtnResult;
+  }
+
+  // the inverse
+  template <class T>
+  CWTSQuaternion<T>
+  inv(const CWTSQuaternion<T> &qtn)
+  {
+    T qtn0 = qtn[0];
+    T qtn1 = qtn[1];
+    T qtn2 = qtn[2];
+    T qtn3 = qtn[3];
+
+    return conj(qtn)/static_cast<const T &>(qtn0*qtn0
+                                            + qtn1*qtn1
+                                            + qtn2*qtn2
+                                            + qtn3*qtn3);
+  }
+
+  // the sign of a quaternion is a unit quaternion with the same
+  // direction
+  template <class T>
+  inline CWTSQuaternion<T>
+  sgn(const CWTSQuaternion<T> &qtn)
+  {
+    return qtn.unit();
+  }
+
+  // the argument of a quaternion is the angle between it and the
+  // scalar number 1 (analogous to the argument of a complex number)
+  template <class T>
+  inline T
+  arg(const CWTSQuaternion<T> &qtn)
+  {
+    return atan2(norm(im(qtn)), re(qtn));
+  }
+
+  // quaternion exponentiation
+  template <class T>
+  CWTSQuaternion<T>
+  exp(const CWTSQuaternion<T> &qtn)
+  {
+    CWTSSpaceVector<T> svec = im(qtn);
+    T len = norm(svec);
+
+    if (len == CWTSZero<T>())
+      {
+        return exp(re(qtn))*CWTSQuaternion<T>(CWTSZero<T>(),
+                                              CWTSZero<T>(),
+                                              CWTSZero<T>(),
+                                              cos(len));
+      }
+    else
+      {
+        return exp(re(qtn))*CWTSQuaternion<T>(sgn(svec)*sin(len), cos(len));
+      }
+  }
+
+  // quaternion logarithm (with base e)
+  template <class T>
+  CWTSQuaternion<T>
+  log(const CWTSQuaternion<T> &qtn)
+  {
+    CWTSSpaceVector<T> svec = im(qtn);
+    T len = norm(svec);
+
+    if (len == CWTSZero<T>())
+      {
+        return CWTSQuaternion<T>(CWTSZero<T>(),
+                                 CWTSZero<T>(),
+                                 CWTSZero<T>(),
+                                 log(norm(qtn)));
+      }
+    else
+      {
+        return CWTSQuaternion<T>(sgn(svec)*arg(qtn), log(norm(qtn)));
+      }
+  }
+
+  // quaternion power! raise qtn1 to the power qtn2
+  template <class T>
+  inline CWTSQuaternion<T>
+  pow(const CWTSQuaternion<T> &qtn1, const CWTSQuaternion<T> &qtn2)
+  {
+    return exp(qtn2*log(qtn1));
+  }
+}
+
+#endif // IG_STAT_QUATERN_H
diff --git a/Mesh/stat_smatrix.h b/Mesh/stat_smatrix.h
new file mode 100755
index 0000000000..e25106b2d5
--- /dev/null
+++ b/Mesh/stat_smatrix.h
@@ -0,0 +1,467 @@
+// -*-c++-*-
+#ifndef IG_STAT_SMATRIX_H
+#define IG_STAT_SMATRIX_H
+
+// $Id: stat_smatrix.h,v 1.1.2.7 2005/07/02 15:41:46 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+#ifndef IG_STAT_MATRIX_H
+#include "stat_matrix.h"
+#endif
+
+namespace CwMtx
+{
+  // prefix smat
+  template <unsigned r, class T = double>
+  class CWTSSquareMatrix : public CWTSMatrix<r, r, T>
+  {
+  public:
+    CWTSSquareMatrix(): CWTSMatrix<r, r, T>() {}
+    CWTSSquareMatrix(const CWTSMatrix<r, r, T> &mat):
+      CWTSMatrix<r, r, T>(mat) {}
+    CWTSSquareMatrix(const CWTSSquareMatrix &smat):
+      CWTSMatrix<r, r, T>(smat) {}
+
+    ~CWTSSquareMatrix() {}
+
+    CWTSSquareMatrix operator +(const CWTSSquareMatrix &) const;
+    CWTSSquareMatrix operator -(const CWTSSquareMatrix &) const;
+    CWTSSquareMatrix operator -() const;
+    CWTSSquareMatrix operator *(const T &) const;
+    CWTSSquareMatrix operator *(const CWTSSquareMatrix &) const;
+    CWTSSquareMatrix operator /(const T &value) const;
+    CWTSSquareMatrix operator /(const CWTSSquareMatrix &) const;
+
+    // not inherited
+    CWTSSquareMatrix & operator =(const CWTSSquareMatrix &smat);
+    CWTSSquareMatrix & operator +=(const CWTSSquareMatrix &smat);
+    CWTSSquareMatrix & operator -=(const CWTSSquareMatrix &smat);
+    CWTSSquareMatrix & operator *=(const T &value);
+    CWTSSquareMatrix & operator *=(const CWTSSquareMatrix &);
+    CWTSSquareMatrix & operator /=(const T &value);
+    CWTSSquareMatrix & operator /=(const CWTSSquareMatrix &);
+
+    // stores the adjoint of argument in this
+    void storeAdjoint(const CWTSSquareMatrix &);
+    // stores the inverse of argument in this
+    void storeInverse(const CWTSSquareMatrix &);
+    // makes this its own adjoint
+    void makeAdjoint();
+    // makes this its own inverse
+    void makeInverse();
+    // makes this a unity matrix
+    void makeUnity();
+  };
+
+  // not inherited
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator =(const CWTSSquareMatrix<r, T> &smat)
+  {
+    return
+      static_cast<CWTSSquareMatrix<r, T> &>(CWTSMatrix<r, r, T>::
+					    operator=(smat));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator +=(const CWTSSquareMatrix<r, T> &smat)
+  {
+    return
+      static_cast<CWTSSquareMatrix<r, T> &>(CWTSMatrix<r, r, T>::
+					    operator+=(smat));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator -=(const CWTSSquareMatrix &smat)
+  {
+    return
+      static_cast<CWTSSquareMatrix<r, T> &>(CWTSMatrix<r, r, T>::
+					    operator-=(smat));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator *=(const T &value)
+  {
+    return
+      static_cast<CWTSSquareMatrix<r, T> &>(CWTSMatrix<r, r, T>::
+					    operator*=(value));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator *=(const CWTSSquareMatrix<r, T> &smat)
+  {
+    return (*this) = (*this)*smat;
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator /=(const T &value)
+  {
+    return (*this) *= CWTSUnity<T>()/value;
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T> &
+  CWTSSquareMatrix<r, T>::operator /=(const CWTSSquareMatrix<r, T> &smat)
+  {
+    return (*this) = (*this)/smat;
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator +(const CWTSSquareMatrix<r, T> &smat) const
+  {
+    return CWTSSquareMatrix(*this) += smat;
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator -(const CWTSSquareMatrix<r, T> &smat) const
+  {
+    return CWTSSquareMatrix(*this) -= smat;
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T> CWTSSquareMatrix<r, T>::operator -() const
+  {
+    return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator *(const T &value) const
+  {
+    return CWTSSquareMatrix(*this) *= value;
+  }
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator /(const T &value) const
+  {
+    return (*this)*(CWTSUnity<T>()/value);
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator *(const CWTSSquareMatrix<r, T> &smat) const
+  {
+    CWTSSquareMatrix<r, T> smatResult;
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < r; ++icol)
+	  {
+	    smatResult[irow][icol] = CWTSZero<T>();
+
+	    for (unsigned icol2 = 0; icol2 < r; ++icol2)
+	      {
+		smatResult[irow][icol] +=
+		  (*this)[irow][icol2]*smat[icol2][icol];
+	      }
+	  }
+      }
+
+    return smatResult;
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  CWTSSquareMatrix<r, T>::operator /(const CWTSSquareMatrix<r, T> &smat) const
+  {
+    return (*this)*inv(smat);
+  }
+
+  // stores inverse of argument in this
+  template <unsigned r, class T>
+  void
+  CWTSSquareMatrix<r, T>::storeInverse(const CWTSSquareMatrix<r, T> &smat)
+  {
+    // copy input matrix in this
+    (*this) = smat;
+    makeInverse();
+  }
+
+  // makes this a unity matrix
+  template <unsigned r, class T>
+  void
+  CWTSSquareMatrix<r, T>::makeUnity()
+  {
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < r; ++icol)
+	  {
+	    if (irow == icol)
+	      {
+		(*this)[irow][icol] = CWTSUnity<T>();
+	      }
+	    else
+	      {
+		(*this)[irow][icol] = CWTSZero<T>();
+	      }
+	  }
+      }
+  }
+
+  // makes this its own adjoint
+  template <unsigned r, class T>
+  void
+  CWTSSquareMatrix<r, T>::makeAdjoint()
+  {
+    // we need a copy of this
+    CWTSSquareMatrix<r, T> smatCopy(*this);
+    T elemTmp;
+    // will eventually contain det(smatCopy)
+    T elemDet = CWTSUnity<T>();
+
+    // make this a unity matrix
+    makeUnity();
+
+    // start row reduction
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	// if element [irow][irow] is zero, add a row with non-zero
+	// element at column irow
+	if (smatCopy[irow][irow] == CWTSZero<T>())
+	  {
+	    for (unsigned irowTmp = irow; irowTmp < r; ++irowTmp)
+	      {
+		if (smatCopy[irowTmp][irow] != CWTSZero<T>())
+		  {
+		    // has no effect on adj(smat)
+		    smatCopy.addRowToRow(irowTmp, irow);
+		    // repeat action on this
+		    this->addRowToRow(irowTmp, irow);
+		    break;
+		  }
+	      }
+	  }
+
+	elemTmp = smatCopy[irow][irow];
+        T tTmp = CWTSUnity<T>();
+        tTmp /= elemTmp;
+	smatCopy.multiplyRow(irow, tTmp);
+	// repeat action on this
+	multiplyRow(irow, tTmp);
+	elemDet *= elemTmp;
+
+	for (unsigned irowToAddTo = 0; irowToAddTo < r; ++irowToAddTo)
+	  {
+	    if (irowToAddTo != irow)
+	      {
+		elemTmp = -smatCopy[irowToAddTo][irow];
+		smatCopy.addRowToRow(irow, irowToAddTo, elemTmp);
+		// repeat action on this
+		addRowToRow(irow, irowToAddTo, elemTmp);
+	      }
+	  }
+      }
+
+    // this now contains its adjoint
+    (*this) *= elemDet;
+  }
+
+  // stores adjoint of input matrix in this
+  template <unsigned r, class T>
+  void
+  CWTSSquareMatrix<r, T>::storeAdjoint(const CWTSSquareMatrix<r, T> &smat)
+  {
+    // copy input matrix in this
+    (*this) = smat;
+    makeAdjoint();
+  }
+
+  // makes this its own inverse
+  template <unsigned r, class T>
+  void
+  CWTSSquareMatrix<r, T>::makeInverse()
+  {
+    // we need a copy of this
+    CWTSSquareMatrix<r, T> smatCopy(*this);
+    T elemTmp;
+
+    // make this a unity matrix
+    makeUnity();
+
+    // start row reduction
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	// if element [irow][irow] is zero, add a row with non-zero
+	// element at column irow
+	if (smatCopy[irow][irow] == CWTSZero<T>())
+	  {
+	    for (unsigned irowTmp = irow; irowTmp < r; ++irowTmp)
+	      {
+		// has no effect on inv(smat)
+		if (smatCopy[irowTmp][irow] != CWTSZero<T>())
+		  {
+		    smatCopy.addRowToRow(irowTmp, irow);
+		    // repeat action on this
+		    this->addRowToRow(irowTmp, irow);
+		    break;
+		  }
+	      }
+	  }
+
+	elemTmp = smatCopy[irow][irow];
+        T tTmp = CWTSUnity<T>();
+        tTmp /= elemTmp;
+	smatCopy.multiplyRow(irow, tTmp);
+	multiplyRow(irow, tTmp);
+
+	for (unsigned irowToAddTo = 0; irowToAddTo < r; ++irowToAddTo)
+	  {
+	    if (irowToAddTo != irow)
+	      {
+		elemTmp = -smatCopy[irowToAddTo][irow];
+		smatCopy.addRowToRow(irow, irowToAddTo, elemTmp);
+		// repeat action on this
+		addRowToRow(irow, irowToAddTo, elemTmp);
+	      }
+	  }
+      }
+
+    // this now contains its inverse
+  }
+
+  // template functions designed work with the Square Matrix class.
+
+  template <unsigned r, class T>
+  inline CWTSSquareMatrix<r, T>
+  operator *(const T &value, const CWTSSquareMatrix<r, T> &smat)
+  {
+    return smat*value;
+  }
+
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  transpose(const CWTSSquareMatrix<r, T> &smat)
+  {
+    CWTSSquareMatrix<r, T> smatTranspose;
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	for (unsigned icol = 0; icol < r; ++icol)
+	  {
+	    smatTranspose[irow][icol] = smat[icol][irow];
+	  }
+      }
+
+    return smatTranspose;
+  }
+
+  // returns the adjoint of a square matrix
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  adj(const CWTSSquareMatrix<r, T> &smat)
+  {
+    CWTSSquareMatrix<r, T> smatResult(smat);   // copy input matrix
+    smatResult.makeAdjoint();
+    return smatResult;
+  }
+
+  // calculates the inverse of a square matrix
+  template <unsigned r, class T>
+  CWTSSquareMatrix<r, T>
+  inv(const CWTSSquareMatrix<r, T> &smat)
+  {
+    // copy input matrix
+    CWTSSquareMatrix<r, T> smatResult(smat);
+    smatResult.makeInverse();
+    return smatResult;
+  }
+
+  // calculates the determinant of a square matrix
+  template <unsigned r, class T>
+  T
+  det(const CWTSSquareMatrix<r, T> &smat)
+  {
+    // a copy of the input matrix
+    CWTSSquareMatrix<r, T> smatCopy(smat);
+
+    // start row reduction
+    T elemTmp;
+    // will eventually contain det(smatCopy)
+    T elemDet = CWTSUnity<T>();
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	// if element [irow][irow] is zero, add a row with non-zero
+	// element at column irow
+	if (smatCopy[irow][irow] == CWTSZero<T>())
+	  {
+	    for (unsigned irowTmp = irow; irowTmp < r; ++irowTmp)
+	      {
+		// has no effect on inv(smat)
+		if (smatCopy[irowTmp][irow] != CWTSZero<T>())
+		  {
+		    smatCopy.addRowToRow(irowTmp, irow);
+		    break;
+		  }
+	      }
+	  }
+
+	elemTmp = smatCopy[irow][irow];
+	elemDet *= elemTmp;
+
+	if (elemDet == CWTSZero<T>())
+	  {
+	    // once elemDet is zero it will stay zero
+	    return elemDet;
+	  }
+
+	smatCopy.multiplyRow(irow, CWTSUnity<T>()/elemTmp);
+
+	for (unsigned irowToAddTo = 0; irowToAddTo < r; ++irowToAddTo)
+	  {
+	    if (irowToAddTo != irow)
+	      {
+		smatCopy.addRowToRow(irow,
+				     irowToAddTo,
+				     -smatCopy[irowToAddTo][irow]);
+	      }
+	  }
+      }
+
+    return elemDet;
+  }
+
+  // trace
+  template <unsigned r, class T>
+  T
+  tr(const CWTSSquareMatrix<r, T> &smat)
+  {
+    T elemTmp = CWTSZero<T>();
+
+    for (unsigned c = 0; c < r; c++)
+      {
+	elemTmp += smat[c][c];
+      }
+
+    return elemTmp;
+  }
+
+}
+
+#endif // IG_STAT_SMATRIX_H
diff --git a/Mesh/stat_svector.h b/Mesh/stat_svector.h
new file mode 100755
index 0000000000..f9099aec27
--- /dev/null
+++ b/Mesh/stat_svector.h
@@ -0,0 +1,247 @@
+// -*-c++-*-
+#ifndef IG_STAT_SVECTOR_H
+#define IG_STAT_SVECTOR_H
+
+// $Id: stat_svector.h,v 1.1.2.7 2005/07/02 15:41:46 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+#ifndef IG_STAT_VECTOR_H
+#include "stat_vector.h"
+#endif
+
+#ifndef IG_STAT_SMATRIX_H
+#include "stat_smatrix.h"
+#endif
+
+namespace CwMtx
+{
+
+  // prefix svec
+  template <class T = double>
+  class CWTSSpaceVector: public CWTSVector<3, T>
+  {
+  public:
+    CWTSSpaceVector(): CWTSVector<3, T>() {}
+    CWTSSpaceVector(const CWTSMatrix<3, 1, T> &mat): CWTSVector<3, T>(mat) {}
+    CWTSSpaceVector(const CWTSVector<3, T> &vec): CWTSVector<3, T>(vec) {}
+    CWTSSpaceVector(const CWTSSpaceVector &svec): CWTSVector<3, T>(svec) {}
+    // construct from 3 elements
+    CWTSSpaceVector(const T &, const T &, const T &);
+
+    ~CWTSSpaceVector() {}
+
+    CWTSSpaceVector operator +(const CWTSSpaceVector &) const;
+    CWTSSpaceVector operator -(const CWTSSpaceVector &) const;
+    CWTSSpaceVector operator -() const;
+    CWTSSpaceVector operator *(const T &) const;
+    // inner product
+    T operator *(const CWTSSpaceVector &) const;
+    // outer product
+    CWTSSpaceVector operator %(const CWTSSpaceVector &) const;
+    CWTSSpaceVector operator /(const T &value) const;
+
+    // not inherited
+    CWTSSpaceVector & operator =(const CWTSSpaceVector &);
+    CWTSSpaceVector & operator +=(const CWTSSpaceVector &);
+    CWTSSpaceVector & operator -=(const CWTSSpaceVector &);
+    CWTSSpaceVector & operator *=(const T &);
+    // outer product
+    CWTSSpaceVector & operator %=(const CWTSSpaceVector &);
+    CWTSSpaceVector & operator /=(const T &value);
+
+    void storeOuterProduct(const CWTSSpaceVector &, const CWTSSpaceVector &);
+
+    // returns a unit vector with same direction as this
+    CWTSSpaceVector unit() const { return (*this)/(this->norm()); }
+  };
+
+  template <class T>
+  inline CWTSSpaceVector<T>::CWTSSpaceVector(const T &elem1,
+					     const T &elem2,
+					     const T &elem3)
+    :
+    CWTSVector<3, T>()
+  {
+    (*this)[0] = elem1;
+    (*this)[1] = elem2;
+    (*this)[2] = elem3;
+  }
+
+  template <class T>
+  inline CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator /(const T &value) const
+  {
+    return (*this)*(CWTSUnity<T>()/value);
+  }
+
+  // not inherited
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator =(const CWTSSpaceVector<T> &svec)
+  {
+    return
+      static_cast<CWTSSpaceVector &>(CWTSMatrix<3, 1, T>::operator=(svec));
+  }
+
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator +=(const CWTSSpaceVector<T> &svec)
+  {
+    return
+      static_cast<CWTSSpaceVector &>(CWTSMatrix<3, 1, T>::operator+=(svec));
+  }
+
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator -=(const CWTSSpaceVector<T> &svec)
+  {
+    return
+      static_cast<CWTSSpaceVector &>(CWTSMatrix<3, 1, T>::operator-=(svec));
+  }
+
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator *=(const T &value)
+  {
+    return
+      static_cast<CWTSSpaceVector &>(
+				     CWTSMatrix<3, 1, T>::operator*=(value));
+  }
+
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator /=(const T &value)
+  {
+    return (*this) *= CWTSUnity<T>()/value;
+  }
+
+  // outer product
+  template <class T>
+  inline CWTSSpaceVector<T> &
+  CWTSSpaceVector<T>::operator %=(const CWTSSpaceVector<T> &vec)
+  {
+    return (*this) = (*this)%vec;
+  }
+
+  template <class T>
+  CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator +(const CWTSSpaceVector<T> &svec) const
+  {
+    return CWTSSpaceVector(*this) += svec;
+  }
+
+  template <class T>
+  CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator -(const CWTSSpaceVector<T> &svec) const
+  {
+    return CWTSSpaceVector(*this) -= svec;
+  }
+
+  template <class T>
+  CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator -() const
+  {
+    return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
+  }
+
+  template <class T>
+  CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator *(const T &value) const
+  {
+    return CWTSSpaceVector(*this) *= value;
+  }
+
+  // inner product
+  template <class T>
+  T
+  CWTSSpaceVector<T>::operator *(const CWTSSpaceVector<T> &vec) const
+  {
+    return CWTSVector<3, T>::operator*(vec);
+  }
+
+  template <class T>
+  void
+  CWTSSpaceVector<T>::storeOuterProduct(const CWTSSpaceVector<T> &svecLeft,
+					const CWTSSpaceVector<T> &svecRight)
+  {
+    // to reduce the number of calls to the subscript operator
+    T svecLeft0 = svecLeft[0];
+    T svecLeft1 = svecLeft[1];
+    T svecLeft2 = svecLeft[2];
+
+    T svecRight0 = svecRight[0];
+    T svecRight1 = svecRight[1];
+    T svecRight2 = svecRight[2];
+
+    (*this)[0] = svecLeft1*svecRight2 - svecLeft2*svecRight1;
+    (*this)[1] = svecLeft2*svecRight0 - svecLeft0*svecRight2;
+    (*this)[2] = svecLeft0*svecRight1 - svecLeft1*svecRight0;
+  }
+
+  template <class T>
+  CWTSSpaceVector<T>
+  CWTSSpaceVector<T>::operator %(const CWTSSpaceVector<T> &svec) const
+  {
+    CWTSSpaceVector<T> svecResult;
+    svecResult.storeOuterProduct(*this, svec);
+    return svecResult;
+  }
+
+  // template functions designed work with the base matrix class.
+
+  template <class T>
+  inline CWTSSpaceVector<T>
+  operator *(const T &value, const CWTSSpaceVector<T> &svec)
+  {
+    return svec*value;
+  }
+
+  // (square matrix)*(space vector) must yield a space vector
+  template <class T>
+  CWTSSpaceVector<T>
+  operator *(const CWTSSquareMatrix<3, T> &smat,
+	     const CWTSSpaceVector<T> &svec)
+  {
+    CWTSSpaceVector<T> svecResult;
+
+    for (unsigned irow = 0; irow < 3; ++irow)
+      {
+	svecResult[irow] = CWTSZero<T>();
+
+	for (unsigned icol = 0; icol < 3; ++icol)
+	  {
+	    svecResult[irow] += smat[irow][icol]*svec[icol];
+	  }
+      }
+
+    return svecResult;
+  }
+
+  // the sign of a vector is a unit vector with the same direction
+  template <class T>
+  inline CWTSSpaceVector<T>
+  sgn(const CWTSSpaceVector<T> &svec)
+  {
+    return svec.unit();
+  }
+}
+
+#endif // IG_STAT_SVECTOR_H
diff --git a/Mesh/stat_vector.h b/Mesh/stat_vector.h
new file mode 100755
index 0000000000..089ba93454
--- /dev/null
+++ b/Mesh/stat_vector.h
@@ -0,0 +1,243 @@
+// -*-c++-*-
+#ifndef IG_STAT_VECTOR_H
+#define IG_STAT_VECTOR_H
+
+// $Id: stat_vector.h,v 1.1.2.6 2005/05/30 09:14:25 hkuiper Exp $
+
+// CwMtx matrix and vector math library
+// Copyright (C) 1999-2001  Harry Kuiper
+// Copyright (C) 2000  Will DeVore (template conversion)
+
+// 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 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
+
+#include <cmath>
+
+#ifndef IG_STAT_MATRIX_H
+#include "stat_matrix.h"
+#endif
+
+namespace CwMtx
+{
+
+  template <unsigned r, class T = double>
+  class CWTSVector : public CWTSMatrix<r, 1, T>
+  {
+  public:
+    CWTSVector(): CWTSMatrix<r, 1, T>() {}
+    CWTSVector(const CWTSMatrix<r, 1, T>& mat): CWTSMatrix<r, 1, T>(mat) {}
+    CWTSVector(const CWTSVector& vec): CWTSMatrix<r, 1, T>(vec) {}
+
+    ~CWTSVector() {}
+
+    T & operator [](unsigned irow);
+    const T & operator [](unsigned irow) const;
+
+    CWTSVector operator +(const CWTSVector &) const;
+    CWTSVector operator -(const CWTSVector &) const;
+    CWTSVector operator -() const;
+    CWTSVector operator *(const T &) const;
+    CWTSVector operator /(const T &value) const;
+    // CWTSVector*CWTSVector, inner product
+    T operator *(const CWTSVector &) const;
+
+    // not inherited
+    CWTSVector & operator =(const CWTSVector &vec);
+    CWTSVector & operator +=(const CWTSVector &vec);
+    CWTSVector & operator -=(const CWTSVector &vec);
+    CWTSVector & operator *=(const T &value);
+    CWTSVector & operator /=(const T &value);
+
+    // CWTSVector norm
+    T operator !() const { return (*this).norm(); }
+    // returns vector norm (length)
+    T norm() const;
+    // returns a unit vector with same direction as this
+    CWTSVector unit() const { return (*this)/norm(); }
+
+    // make this a unit vector
+    void makeUnit() { (*this) /= norm(); }
+
+    template <unsigned r2>
+    void storeAtRow(unsigned, const CWTSVector<r2, T> &);
+  };
+
+  template <unsigned r, class T>
+  inline T &
+  CWTSVector<r, T>::operator [](unsigned irow)
+  {
+    return this->CWTSMatrix<r, 1, T>::operator[](irow)[0];
+  }
+
+  template <unsigned r, class T>
+  inline const T &
+  CWTSVector<r, T>::operator [](unsigned irow) const
+  {
+    return this->CWTSMatrix<r, 1, T>::operator[](irow)[0];
+  }
+
+  // not inherited
+  template <unsigned r, class T>
+  inline CWTSVector<r, T> &
+  CWTSVector<r, T>::operator =(const CWTSVector<r, T> &vec)
+  {
+    return static_cast<CWTSVector &>(CWTSMatrix<r, 1, T>::operator=(vec));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSVector<r, T> &
+  CWTSVector<r, T>::operator +=(const CWTSVector<r, T> &vec)
+  {
+    return static_cast<CWTSVector &>(CWTSMatrix<r, 1, T>::operator+=(vec));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSVector<r, T> &
+  CWTSVector<r, T>::operator -=(const CWTSVector<r, T> &vec)
+  {
+    return static_cast<CWTSVector &>(CWTSMatrix<r, 1, T>::operator-=(vec));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSVector<r, T> &
+  CWTSVector<r, T>::operator *=(const T &value)
+  {
+    return static_cast<CWTSVector &>(CWTSMatrix<r, 1, T>::operator*=(value));
+  }
+
+  template <unsigned r, class T>
+  inline CWTSVector<r, T> &
+  CWTSVector<r, T>::operator /=(const T &value)
+  {
+    return (*this) *= CWTSUnity<T>()/value;
+  }
+
+  template <unsigned r, class T>
+  CWTSVector<r, T>
+  CWTSVector<r, T>::operator +(const CWTSVector<r, T> &vec) const
+  {
+    return CWTSVector<r, T>(*this) += vec;
+  }
+
+  template <unsigned r, class T>
+  CWTSVector<r, T>
+  CWTSVector<r, T>::operator -(const CWTSVector<r, T> &vec) const
+  {
+    return CWTSVector<r, T>(*this) -= vec;
+  }
+
+  template <unsigned r, class T>
+  CWTSVector<r, T>
+  CWTSVector<r, T>::operator -() const
+  {
+    return (*this)*(CWTSZero<T>() - CWTSUnity<T>());
+  }
+
+  template <unsigned r, class T>
+  CWTSVector<r, T>
+  CWTSVector<r, T>::operator *(const T &value) const
+  {
+    return CWTSVector<r, T>(*this) *= value;
+  }
+
+  template <unsigned r, class T>
+  CWTSVector<r, T>
+  CWTSVector<r, T>::operator /(const T &value) const
+  {
+    return (*this)*(CWTSUnity<T>()/value);
+  }
+
+  template <unsigned r, class T>
+  T
+  CWTSVector<r, T>::operator *(const CWTSVector<r, T> &vec) const
+  {
+    T elemResult = CWTSZero<T>();
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	elemResult += (*this)[irow]*vec[irow];
+      }
+
+    return elemResult;
+  }
+
+  // length of vector
+  template <unsigned r, class T>
+  T
+  CWTSVector<r, T>::norm() const
+  {
+    T elemResult = CWTSZero<T>();
+
+    elemResult = (*this)*(*this);
+
+    return sqrt(elemResult);
+  }
+
+  template <unsigned r, class T>
+  template <unsigned r2>
+  inline void
+  CWTSVector<r, T>::storeAtRow(unsigned irowStart,
+			       const CWTSVector<r2, T> &vec)
+  {
+    CWTSMatrix<r, 1, T>::storeAtPosition(irowStart, 0, vec);
+  }
+
+  // template functions designed work with the vector class.
+
+  template <unsigned r, class T>
+  inline CWTSVector<r, T>
+  operator *(const T &value, const CWTSVector<r, T> &vec)
+  {
+    return vec*value;
+  }
+
+  // matrix*vector must yield a vector
+  template <unsigned r, unsigned c, class T>
+  CWTSVector<r, T>
+  operator *(const CWTSMatrix<r, c, T> &mat, const CWTSVector<r, T> &vec)
+  {
+    CWTSVector<r, T> vecResult;
+
+    for (unsigned irow = 0; irow < r; ++irow)
+      {
+	vecResult[irow] = CWTSZero<T>();
+
+	for (unsigned icol = 0; icol < c; ++icol)
+	  {
+	    vecResult[irow] += mat[irow][icol]*vec[icol];
+	  }
+      }
+
+    return vecResult;
+  }
+
+  // norm computation as a function
+  template <unsigned r, class T>
+  inline T
+  norm(const CWTSVector<r, T> &vec)
+  {
+    return vec.norm();
+  }
+
+  // the sign of a vector is a unit vector with the same direction
+  template <unsigned r, class T>
+  inline CWTSVector<r, T>
+  sgn(const CWTSVector<r, T> &vec)
+  {
+    return vec.unit();
+  }
+}
+
+#endif // IG_STAT_VECTOR_H
-- 
GitLab