Simple Vector Library 1.5 http://www.cs.cmu.edu/~ajw/doc/svl.html

Files at this revision

API Documentation at this revision

Comitter:
BartJanssens
Date:
Mon Jan 04 15:19:10 2016 +0000
Child:
1:e25ff4b06ed2
Commit message:
svl-1.5

Changed in this revision

Basics.cpp Show annotated file Show diff for this revision Revisions of this file
Basics.h Show annotated file Show diff for this revision Revisions of this file
Constants.h Show annotated file Show diff for this revision Revisions of this file
Mat.cpp Show annotated file Show diff for this revision Revisions of this file
Mat.h Show annotated file Show diff for this revision Revisions of this file
Mat2.cpp Show annotated file Show diff for this revision Revisions of this file
Mat2.h Show annotated file Show diff for this revision Revisions of this file
Mat3.cpp Show annotated file Show diff for this revision Revisions of this file
Mat3.h Show annotated file Show diff for this revision Revisions of this file
Mat4.cpp Show annotated file Show diff for this revision Revisions of this file
Mat4.h Show annotated file Show diff for this revision Revisions of this file
Quat.cpp Show annotated file Show diff for this revision Revisions of this file
Quat.h Show annotated file Show diff for this revision Revisions of this file
SVL.h Show annotated file Show diff for this revision Revisions of this file
Transform.h Show annotated file Show diff for this revision Revisions of this file
Utils.h Show annotated file Show diff for this revision Revisions of this file
Vec.cpp Show annotated file Show diff for this revision Revisions of this file
Vec.h Show annotated file Show diff for this revision Revisions of this file
Vec2.cpp Show annotated file Show diff for this revision Revisions of this file
Vec2.h Show annotated file Show diff for this revision Revisions of this file
Vec3.cpp Show annotated file Show diff for this revision Revisions of this file
Vec3.h Show annotated file Show diff for this revision Revisions of this file
Vec4.cpp Show annotated file Show diff for this revision Revisions of this file
Vec4.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Basics.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,78 @@
+/*
+    File:           Basics.cpp
+
+    Function:       Implements Basics.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+    Notes:          
+
+*/
+
+#include "Basics.h"
+//#include <cstdio>
+//#include <cstdlib>
+//#include <iostream>
+
+
+//using namespace std;
+
+
+// --- Error functions for range and routine checking -------------------------
+
+
+static Void DebuggerBreak()
+{
+    abort();
+}
+
+Void _Assert(Int condition, const Char *errorMessage, const Char *file, Int line)
+{
+    if (!condition)
+    {
+        //Char reply;
+        
+        //cerr << "\n*** Assert failed (line " << line << " in " << 
+        //    file << "): " << errorMessage << endl;
+        printf("\r\n*** Assert failed (line \"%d \" in \" %s \"): \"%s", line, file, errorMessage);
+        //cerr << "    Continue? [y/n] ";
+        //cin >> reply;
+        
+        //if (reply != 'y')
+        //{
+            DebuggerBreak();
+            exit(1);
+        //}
+    }
+}
+
+Void _Expect(Int condition, const Char *warningMessage, const Char *file, Int line)
+{
+    if (!condition)
+        //cerr << "\n*** Warning (line " << line << " in " << file << "): " <<
+        //    warningMessage << endl;
+        printf("\r\n*** Warning (line \"%d \" in \" %s \"): \"%s", line, file, warningMessage);
+}
+
+Void _CheckRange(Int i, Int lowerBound, Int upperBound, 
+                 const Char *rangeMessage, const Char *file, Int line)
+{
+    if (i < lowerBound || i >= upperBound)
+    {
+        //Char reply;
+        
+        //cerr << "\n*** Range Error (line " << line << " in " << file <<
+        //    "): " << rangeMessage << endl;  
+        printf("\r\n*** Range Error (line \"%d \" in \" %s \"): \"%s", line, file, rangeMessage);
+        //cerr << "    Continue? [y/n] ";
+        //cin >> reply;
+        
+        //if (reply != 'y')
+        //{
+            DebuggerBreak();
+            exit(1);
+        //}
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Basics.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,162 @@
+/*
+    File:           Basics.h
+
+    Function:       Basic definitions for all files. Contains type
+                    definitions, assertion and debugging facilities, and
+                    miscellaneous useful template functions.
+
+                    This is a cut-down version for SVL.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+    Notes:          This header is affected by the following defines:
+
+                    VL_CHECKING     - Include code for assertions,
+                                      range errors and warnings.
+                    VL_FLOAT        - Use floats for real numbers. (Doubles
+                                      are the default.)
+                    VL_NO_BOOL      - There is no bool type.
+                    VL_NO_TF        - true and false are not predefined.
+*/
+
+#ifndef __Basics__
+#define __Basics__
+
+#include "mbed.h"
+//#include <iostream>
+//#include <cmath>
+
+
+// --- Basic types -------------------------------------------------------------
+
+typedef void            Void;
+typedef float           Float;
+typedef double          Double;
+typedef char            Char;
+typedef int             Short;
+typedef int             Int;
+typedef long            Long;
+typedef unsigned char   Byte;
+typedef unsigned int    UInt;
+
+#ifndef VL_FLOAT
+typedef Double          Real;
+#else
+typedef Float           Real;
+#endif
+
+#define SELF (*this)    // A syntactic convenience.
+
+
+// --- Boolean type ------------------------------------------------------------
+
+// X11 #defines 'Bool' -- typical.
+
+#ifdef Bool
+#undef Bool
+#endif
+
+#ifndef VL_NO_BOOL
+// if the compiler implements the bool type...
+typedef bool Bool;
+#else
+// if not, make up our own.
+class Bool
+{
+public:
+
+    Bool() : val(0) {};
+    Bool(Int b) : val(b) {};
+
+    operator Int() { return val; };
+
+private:
+    Int val;
+};
+#ifdef VL_NO_TF
+enum {false, true};
+#endif
+#endif
+
+
+// --- Assertions and Range checking -------------------------------------------
+
+#define _Error(e)               _Assert(false, e, __FILE__, __LINE__)
+#define _Warning(w)             _Expect(false, w, __FILE__, __LINE__)
+
+#if defined(VL_CHECKING)
+#define Assert(b, e)            _Assert(b, e, __FILE__, __LINE__)
+    // Assert that b is true. e is an error message to be printed if b
+    // is false.
+#define Expect(b, w)            _Expect(b, w, __FILE__, __LINE__)
+    // Prints warning w if b is false
+#define CheckRange(i, l, u, r)  _CheckRange(i, l, u, r, __FILE__, __LINE__)
+    // Checks whether i is in the range [lowerBound, upperBound).
+#else
+#define Assert(b, e)
+#define Expect(b, w)
+#define CheckRange(a, l, u, r)
+#endif
+
+Void _Assert(Int condition, const Char *errorMessage, const Char *file, Int line);
+Void _Expect(Int condition, const Char *warningMessage, const Char *file, Int line);
+Void _CheckRange(Int i, Int lowerBound, Int upperBound, const Char *rangeMessage,
+        const Char *file, Int line);
+
+
+// --- Inlines -----------------------------------------------------------------
+
+template<class Value>
+    inline Value Min(Value x, Value y)
+    {
+        if (x <= y)
+            return(x);
+        else
+            return(y);
+    };
+
+template<class Value>
+    inline Value Max(Value x, Value y)
+    {
+        if (x >= y)
+            return(x);
+        else
+            return(y);
+    };
+
+template<class Value>
+    inline Void Swap(Value &x, Value &y)
+    {
+        Value t;
+
+        t = x;
+        x = y;
+        y = t;
+    };
+
+template<class Value>
+    inline Value Mix(Value x, Value y, Real s)
+    {
+        return(x + (y - x) * s);
+    };
+
+template<class Value>
+    inline Value Clip(Value x, Value min, Value max)
+    {
+        if (x < min)
+            return(min);
+        else if (x > max)
+            return(max);
+        else
+            return(x);
+    };
+
+template<class Value>
+    inline Value sqr(Value x)
+    {
+        return(x * x);
+    };
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Constants.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,44 @@
+/*
+    File:       Constants.h
+
+    Function:   Contains various constants for VL.
+
+    Author:     Andrew Willmott
+
+    Copyright:  (c) 1999-2001, Andrew Willmott
+*/
+
+#ifndef __VLConstants__
+#define __VLConstants__
+
+#include <cmath>
+#include "Basics.h"
+
+
+// --- Mathematical constants -------------------------------------------------
+
+
+#ifdef M_PI
+const double          vl_pi = M_PI;
+const double          vl_halfPi = M_PI_2;
+#elif defined(_PI)
+const double          vl_pi = _PI;
+const double          vl_halfPi = vl_pi / 2.0;
+#else
+const double          vl_pi = 3.14159265358979323846;
+const double          vl_halfPi = vl_pi / 2.0;
+#endif
+
+#ifdef HUGE_VAL
+const double        vl_inf = HUGE_VAL;
+#endif
+
+enum    ZeroOrOne   { vl_zero = 0, vl_0 = 0, vl_one = 1, vl_I = 1, vl_1 = 1 };
+enum    Block       { vl_Z = 0, vl_B = 1, vl_block = 1 };
+enum    Axis        { vl_x, vl_y, vl_z, vl_w };
+typedef Axis        vl_axis;
+
+const UInt          VL_REF_FLAG = UInt(1) << (sizeof(UInt) * 8 - 1);
+const UInt          VL_REF_MASK = (~VL_REF_FLAG);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,676 @@
+/*
+    File:           Mat.cpp
+
+    Function:       Implements Mat.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+#include "Mat.h"
+
+//#include <cctype>
+//#include <cstring>
+//#include <cstdarg>
+//#include <iomanip>
+
+
+
+// --- Mat Constructors & Destructors -----------------------------------------
+
+
+Mat::Mat(Int rows, Int cols, ZeroOrOne k) : rows(rows), cols(cols)
+{
+    Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
+
+    data = new Real[rows * cols];
+
+    MakeDiag(k);
+}
+
+Mat::Mat(Int rows, Int cols, Block k) : rows(rows), cols(cols)
+{
+    Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
+
+    data = new Real[rows * cols];
+
+    MakeBlock(k);
+}
+
+Mat::Mat(Int rows, Int cols, double elt0, ...) : rows(rows), cols(cols)
+// The double is hardwired here because it is the only type that will work
+// with var args and C++ real numbers.
+{
+    Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
+
+    va_list ap;
+    Int     i, j;
+
+    data = new Real[rows * cols];
+    va_start(ap, elt0);
+
+    SetReal(data[0], elt0);
+
+    for (i = 1; i < cols; i++)
+        SetReal(Elt(0, i), va_arg(ap, double));
+
+    for (i = 1; i < rows; i++)
+        for (j = 0; j < cols; j++)
+            SetReal(Elt(i, j), va_arg(ap, double));
+
+    va_end(ap);
+}
+
+Mat::Mat(const Mat &m) : cols(m.cols)
+{
+    Assert(m.data != 0, "(Mat) Can't construct from null matrix");
+    rows = m.Rows();
+
+    UInt    elts = rows * cols;
+
+    data = new Real[elts];
+#ifdef VL_USE_MEMCPY
+    memcpy(data, m.data, elts * sizeof(Real));
+#else
+    for (UInt i = 0; i < elts; i++)
+        data[i] = m.data[i];
+#endif
+}
+
+Mat::Mat(const Mat2 &m) : data(m.Ref()), rows(2 | VL_REF_FLAG), cols(2)
+{
+}
+
+Mat::Mat(const Mat3 &m) : data(m.Ref()), rows(3 | VL_REF_FLAG), cols(3)
+{
+}
+
+Mat::Mat(const Mat4 &m) : data(m.Ref()), rows(4 | VL_REF_FLAG), cols(4)
+{
+}
+
+
+// --- Mat Assignment Operators -----------------------------------------------
+
+
+Mat &Mat::operator = (const Mat &m)
+{
+    if (!IsRef())
+        SetSize(m.Rows(), m.Cols());
+    else
+        Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
+    for (Int i = 0; i < Rows(); i++)
+        SELF[i] = m[i];
+
+    return(SELF);
+}
+
+Mat &Mat::operator = (const Mat2 &m)
+{
+    if (!IsRef())
+        SetSize(m.Rows(), m.Cols());
+    else
+        Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
+    for (Int i = 0; i < Rows(); i++)
+        SELF[i] = m[i];
+
+    return(SELF);
+}
+
+Mat &Mat::operator = (const Mat3 &m)
+{
+    if (!IsRef())
+        SetSize(m.Rows(), m.Cols());
+    else
+        Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
+    for (Int i = 0; i < Rows(); i++)
+        SELF[i] = m[i];
+
+    return(SELF);
+}
+
+Mat &Mat::operator = (const Mat4 &m)
+{
+    if (!IsRef())
+        SetSize(m.Rows(), m.Cols());
+    else
+        Assert(Rows() == m.Rows(), "(Mat::=) Matrix rows don't match");
+
+    for (Int i = 0; i < Rows(); i++)
+        SELF[i] = m[i];
+
+    return(SELF);
+}
+
+Void Mat::SetSize(Int nrows, Int ncols)
+{
+    UInt    elts = nrows * ncols;
+    Assert(nrows > 0 && ncols > 0, "(Mat::SetSize) Illegal matrix size.");
+    UInt    oldElts = Rows() * Cols();
+
+    if (IsRef())
+    {
+        // Abort! We don't allow this operation on references.
+        _Error("(Mat::SetSize) Trying to resize a matrix reference");
+    }
+
+    rows = nrows;
+    cols = ncols;
+
+    // Don't reallocate if we already have enough storage
+    if (elts <= oldElts)
+        return;
+
+    // Otherwise, delete old storage and reallocate
+    delete[] data;
+    data = 0;
+    data = new Real[elts]; // may throw an exception
+}
+
+Void Mat::SetSize(const Mat &m)
+{
+    SetSize(m.Rows(), m.Cols());
+}
+
+Void Mat::MakeZero()
+{
+#ifdef VL_USE_MEMCPY
+    memset(data, 0, sizeof(Real) * Rows() * Cols());
+#else
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] = vl_zero;
+#endif
+}
+
+Void Mat::MakeDiag(Real k)
+{
+    Int     i, j;
+
+    for (i = 0; i < Rows(); i++)
+        for (j = 0; j < Cols(); j++)
+            if (i == j)
+                Elt(i,j) = k;
+            else
+                Elt(i,j) = vl_zero;
+}
+
+Void Mat::MakeDiag()
+{
+    Int     i, j;
+
+    for (i = 0; i < Rows(); i++)
+        for (j = 0; j < Cols(); j++)
+            Elt(i,j) = (i == j) ? vl_one : vl_zero;
+}
+
+Void Mat::MakeBlock(Real k)
+{
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i].MakeBlock(k);
+}
+
+Void Mat::MakeBlock()
+{
+    Int     i, j;
+
+    for (i = 0; i < Rows(); i++)
+        for (j = 0; j < Cols(); j++)
+            Elt(i,j) = vl_one;
+}
+
+
+// --- Mat Assignment Operators -----------------------------------------------
+
+
+Mat &Mat::operator += (const Mat &m)
+{
+    Assert(Rows() == m.Rows(), "(Mat::+=) matrix rows don't match");
+
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] += m[i];
+
+    return(SELF);
+}
+
+Mat &Mat::operator -= (const Mat &m)
+{
+    Assert(Rows() == m.Rows(), "(Mat::-=) matrix rows don't match");
+
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] -= m[i];
+
+    return(SELF);
+}
+
+Mat &Mat::operator *= (const Mat &m)
+{
+    Assert(Cols() == m.Cols(), "(Mat::*=) matrix columns don't match");
+
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] = SELF[i] * m;
+
+    return(SELF);
+}
+
+Mat &Mat::operator *= (Real s)
+{
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] *= s;
+
+    return(SELF);
+}
+
+Mat &Mat::operator /= (Real s)
+{
+    Int     i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i] /= s;
+
+    return(SELF);
+}
+
+
+// --- Mat Comparison Operators -----------------------------------------------
+
+
+Bool operator == (const Mat &m, const Mat &n)
+{
+    Assert(n.Rows() == m.Rows(), "(Mat::==) matrix rows don't match");
+
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        if (m[i] != n[i])
+            return(0);
+
+    return(1);
+}
+
+Bool operator != (const Mat &m, const Mat &n)
+{
+    Assert(n.Rows() == m.Rows(), "(Mat::!=) matrix rows don't match");
+
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        if (m[i] != n[i])
+            return(1);
+
+    return(0);
+}
+
+
+// --- Mat Arithmetic Operators -----------------------------------------------
+
+
+Mat operator + (const Mat &m, const Mat &n)
+{
+    Assert(n.Rows() == m.Rows(), "(Mat::+) matrix rows don't match");
+
+    Mat result(m.Rows(), m.Cols());
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = m[i] + n[i];
+
+    return(result);
+}
+
+Mat operator - (const Mat &m, const Mat &n)
+{
+    Assert(n.Rows() == m.Rows(), "(Mat::-) matrix rows don't match");
+
+    Mat result(m.Rows(), m.Cols());
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = m[i] - n[i];
+
+    return(result);
+}
+
+Mat operator - (const Mat &m)
+{
+    Mat result(m.Rows(), m.Cols());
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = -m[i];
+
+    return(result);
+}
+
+Mat operator * (const Mat &m, const Mat &n)
+{
+    Assert(m.Cols() == n.Rows(), "(Mat::*m) matrix cols don't match");
+
+    Mat result(m.Rows(), n.Cols());
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = m[i] * n;
+
+    return(result);
+}
+
+Vec operator * (const Mat &m, const Vec &v)
+{
+    Assert(m.Cols() == v.Elts(), "(Mat::*v) matrix and vector sizes don't match");
+
+    Int     i;
+    Vec result(m.Rows());
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = dot(v, m[i]);
+
+    return(result);
+}
+
+Mat operator * (const Mat &m, Real s)
+{
+    Int     i;
+    Mat result(m.Rows(), m.Cols());
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = m[i] * s;
+
+    return(result);
+}
+
+Mat operator / (const Mat &m, Real s)
+{
+    Int     i;
+    Mat result(m.Rows(), m.Cols());
+
+    for (i = 0; i < m.Rows(); i++)
+        result[i] = m[i] / s;
+
+    return(result);
+}
+
+
+// --- Mat Mat-Vec Functions --------------------------------------------------
+
+
+Vec operator * (const Vec &v, const Mat &m)         // v * m
+{
+    Assert(v.Elts() == m.Rows(), "(Mat::v*m) vector/matrix sizes don't match");
+
+    Vec     result(m.Cols(), vl_zero);
+    Int     i;
+
+    for (i = 0; i < m.Rows(); i++)
+        result += m[i] * v[i];
+
+    return(result);
+}
+
+
+// --- Mat Special Functions --------------------------------------------------
+
+
+Mat trans(const Mat &m)
+{
+    Int     i,j;
+    Mat result(m.Cols(), m.Rows());
+
+    for (i = 0; i < m.Rows(); i++)
+        for (j = 0; j < m.Cols(); j++)
+            result.Elt(j,i) = m.Elt(i,j);
+
+    return(result);
+}
+
+Real trace(const Mat &m)
+{
+    Int     i;
+    Real    result = vl_0;
+
+    for (i = 0; i < m.Rows(); i++)
+        result += m.Elt(i,i);
+
+    return(result);
+}
+
+Mat &Mat::Clamp(Real fuzz)
+//  clamps all values of the matrix with a magnitude
+//  smaller than fuzz to zero.
+{
+    Int i;
+
+    for (i = 0; i < Rows(); i++)
+        SELF[i].Clamp(fuzz);
+
+    return(SELF);
+}
+
+Mat &Mat::Clamp()
+{
+    return(Clamp(1e-7));
+}
+
+Mat clamped(const Mat &m, Real fuzz)
+//  clamps all values of the matrix with a magnitude
+//  smaller than fuzz to zero.
+{
+    Mat result(m);
+
+    return(result.Clamp(fuzz));
+}
+
+Mat clamped(const Mat &m)
+{
+    return(clamped(m, 1e-7));
+}
+
+Mat oprod(const Vec &a, const Vec &b)
+// returns outerproduct of a and b:  a * trans(b)
+{
+    Mat result;
+    Int     i;
+
+    result.SetSize(a.Elts(), b.Elts());
+    for (i = 0; i < a.Elts(); i++)
+        result[i] = a[i] * b;
+
+    return(result);
+}
+
+
+// --- Mat Input & Output -----------------------------------------------------
+
+void printMat(const Mat &m)
+{
+    Int i;
+    
+    printf("[");
+    for (i = 0; i < m.Rows() - 1; i++){
+        printVec(m[i]);
+        printf("\r\n");
+    }
+    printVec(m[i]);
+    printf("]\r\n");
+}
+    
+/*
+ostream &operator << (ostream &s, const Mat &m)
+{
+    Int i, w = s.width();
+
+    s << '[';
+    for (i = 0; i < m.Rows() - 1; i++)
+        s << setw(w) << m[i] << "\r\n";
+    s << setw(w) << m[i] << ']' << "\r\n";
+    return(s);
+}
+*/
+
+inline Void CopyPartialMat(const Mat &m, Mat &n, Int numRows)
+{
+    for (Int i = 0; i < numRows; i++)
+        n[i] = m[i];
+}
+
+/*
+istream &operator >> (istream &s, Mat &m)
+{
+    Int     size = 1;
+    Char    c;
+    Mat     inMat;
+
+    //  Expected format: [row0 row1 row2 ...]
+
+    while (isspace(s.peek()))           //  chomp white space
+        s.get(c);
+
+    if (s.peek() == '[')
+    {
+        Vec     row;
+
+        s.get(c);
+
+        s >> row;
+        inMat.SetSize(2 * row.Elts(), row.Elts());
+        inMat[0] = row;
+
+        while (isspace(s.peek()))       //  chomp white space
+            s.get(c);
+
+        while (s.peek() != ']')         //  resize if needed
+        {
+            if (size == inMat.Rows())
+            {
+                Mat     holdMat(inMat);
+
+                inMat.SetSize(size * 2, inMat.Cols());
+                CopyPartialMat(holdMat, inMat, size);
+            }
+
+            s >> row;           //  read a row
+            inMat[size++] = row;
+
+            if (!s)
+            {
+                _Warning("Couldn't read matrix row");
+                return(s);
+            }
+
+            while (isspace(s.peek()))   //  chomp white space
+                s.get(c);
+        }
+        s.get(c);
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        _Warning("Error: Expected '[' while reading matrix");
+        return(s);
+    }
+
+    m.SetSize(size, inMat.Cols());
+    CopyPartialMat(inMat, m, size);
+
+    return(s);
+}
+*/
+
+// --- Matrix Inversion -------------------------------------------------------
+
+#if !defined(CL_CHECKING) && !defined(VL_CHECKING)
+// we #define away pAssertEps if it is not used, to avoid
+// compiler warnings.
+#define pAssertEps
+#endif
+
+Mat inv(const Mat &m, Real *determinant, Real pAssertEps)
+// matrix inversion using Gaussian pivoting
+{
+    Assert(m.IsSquare(), "(inv) Matrix not square");
+
+    Int             i, j, k;
+    Int             n = m.Rows();
+    Real            t, pivot, det;
+    Real            max;
+    Mat         A(m);
+    Mat         B(n, n, vl_I);
+
+    // ---------- Forward elimination ---------- ------------------------------
+
+    det = vl_1;
+
+    for (i = 0; i < n; i++)             // Eliminate in column i, below diag
+    {
+        max = -1.0;
+
+        for (k = i; k < n; k++)         // Find a pivot for column i
+            if (len(A[k][i]) > max)
+            {
+                max = len(A[k][i]);
+                j = k;
+            }
+
+        Assert(max > pAssertEps, "(inv) Matrix not invertible");
+
+        if (j != i)                     // Swap rows i and j
+        {
+            for (k = i; k < n; k++)
+                Swap(A.Elt(i, k), A.Elt(j, k));
+            for (k = 0; k < n; k++)
+                Swap(B.Elt(i, k), B.Elt(j, k));
+
+            det = -det;
+        }
+
+        pivot = A.Elt(i, i);
+        Assert(abs(pivot) > pAssertEps, "(inv) Matrix not invertible");
+        det *= pivot;
+
+        for (k = i + 1; k < n; k++)     // Only do elements to the right of the pivot
+            A.Elt(i, k) /= pivot;
+
+        for (k = 0; k < n; k++)
+            B.Elt(i, k) /= pivot;
+
+        // We know that A(i, i) will be set to 1, so don't bother to do it
+
+        for (j = i + 1; j < n; j++)
+        {                               // Eliminate in rows below i
+            t = A.Elt(j, i);            // We're gonna zero this guy
+            for (k = i + 1; k < n; k++) // Subtract scaled row i from row j
+                A.Elt(j, k) -= A.Elt(i, k) * t; // (Ignore k <= i, we know they're 0)
+            for (k = 0; k < n; k++)
+                B.Elt(j, k) -= B.Elt(i, k) * t;
+        }
+    }
+
+    // ---------- Backward elimination ---------- -----------------------------
+
+    for (i = n - 1; i > 0; i--)         // Eliminate in column i, above diag
+    {
+        for (j = 0; j < i; j++)         // Eliminate in rows above i
+        {
+            t = A.Elt(j, i);            // We're gonna zero this guy
+            for (k = 0; k < n; k++)     // Subtract scaled row i from row j
+                B.Elt(j, k) -= B.Elt(i, k) * t;
+        }
+    }
+    if (determinant)
+        *determinant = det;
+    return(B);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,218 @@
+/*
+    File:           Mat.h
+
+    Function:       Defines a generic resizeable matrix.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Mat__
+#define __Mat__
+
+#include "Vec.h"
+#include "Mat2.h"
+#include "Mat3.h"
+#include "Mat4.h"
+
+class Mat2;
+class Mat3;
+class Mat4;
+
+
+// --- Mat Class --------------------------------------------------------------
+
+class Mat
+{
+public:
+
+    // Constructors
+
+                Mat();                          // Null matrix
+                Mat(Int rows, Int cols);        // Uninitialised matrix
+                Mat(Int rows, Int cols, Double elt0 ...);   // Mat(2, 2, 1.0, 2.0, 3.0, 4.0)
+                Mat(Int nrows, Int ncols, Real *ndata);     // Create reference matrix
+                Mat(const Mat &m);              // Copy constructor
+                Mat(const Mat2 &m);             // reference to a Mat2
+                Mat(const Mat3 &m);             // reference to a Mat3
+                Mat(const Mat4 &m);             // reference to a Mat4
+                Mat(Int rows, Int cols, ZeroOrOne k); // I * k
+                Mat(Int rows, Int cols, Block k); // block matrix (m[i][j] = k)
+
+                ~Mat();
+
+    // Accessor methods
+
+    Int         Rows() const { return(rows & VL_REF_MASK); };
+    Int         Cols() const { return(cols); };
+
+    Vec         operator [] (Int i);            // Indexing by row
+    Vec         operator [] (Int i) const;      // Indexing by row
+
+    Real        &Elt(Int i, Int j);             // Indexing by elt
+    Real        Elt(Int i, Int j) const;
+
+    Void        SetSize(Int nrows, Int ncols);
+    Void        SetSize(const Mat &m);
+    Bool        IsSquare() const
+                { return((rows & VL_REF_MASK) == cols); };
+
+    Real        *Ref() const;                   // Return pointer to data
+
+    // Assignment operators
+
+    Mat         &operator =  (const Mat &m);    // Assignment of a matrix
+    Mat         &operator =  (ZeroOrOne k);     // Set to k * I...
+    Mat         &operator =  (Block k);         // Set to a block matrix...
+    Mat         &operator =  (const Mat2 &m);
+    Mat         &operator =  (const Mat3 &m);
+    Mat         &operator =  (const Mat4 &m);
+
+    // In-Place Operators
+
+    Mat         &operator += (const Mat &m);
+    Mat         &operator -= (const Mat &m);
+    Mat         &operator *= (const Mat &m);
+    Mat         &operator *= (Real s);
+    Mat         &operator /= (Real s);
+
+    //  Matrix initialisers
+
+    Void        MakeZero();
+    Void        MakeDiag(Real k);
+    Void        MakeDiag();
+    Void        MakeBlock(Real k);
+    Void        MakeBlock();
+
+    Mat         &Clamp(Real fuzz);
+    Mat         &Clamp();
+
+    // Private...
+
+protected:
+
+    Real        *data;
+    UInt        rows;
+    UInt        cols;
+
+    Bool        IsRef() { return((rows & VL_REF_FLAG) != 0); };
+};
+
+
+// --- Mat Comparison Operators -----------------------------------------------
+
+Bool            operator == (const Mat &m, const Mat &n);
+Bool            operator != (const Mat &m, const Mat &n);
+
+
+// --- Mat Arithmetic Operators -----------------------------------------------
+
+Mat             operator + (const Mat &m, const Mat &n);
+Mat             operator - (const Mat &m, const Mat &n);
+Mat             operator - (const Mat &m);
+Mat             operator * (const Mat &m, const Mat &n);
+Mat             operator * (const Mat &m, Real s);
+inline Mat      operator * (Real s, const Mat &m);
+Mat             operator / (const Mat &m, Real s);
+
+Vec             operator * (const Mat &m, const Vec &v);
+Vec             operator * (const Vec &v, const Mat &m);
+
+Mat             trans(const Mat &m);                // Transpose
+Real            trace(const Mat &m);                // Trace
+Mat             inv(const Mat &m, Real *determinant = 0, Real pEps = 1e-20);
+                                                    // Inverse
+Mat             oprod(const Vec &a, const Vec &b);  // Outer product
+
+Mat             clamped(const Mat &m, Real fuzz);
+Mat             clamped(const Mat &m);
+
+
+// --- Mat Input & Output -----------------------------------------------------
+
+//std::ostream         &operator << (std::ostream &s, const Mat &m);
+//std::istream         &operator >> (std::istream &s, Mat &m);
+
+void printMat(const Mat &m);
+
+
+// --- Mat Inlines ------------------------------------------------------------
+
+inline Mat::Mat() : data(0), rows(0), cols(0)
+{
+}
+
+inline Mat::Mat(Int rows, Int cols) : rows(rows), cols(cols)
+{
+    Assert(rows > 0 && cols > 0, "(Mat) illegal matrix size");
+
+    data = new Real[rows * cols];
+}
+
+inline Mat::Mat(Int nrows, Int ncols, Real *ndata) :
+    data(ndata), rows(nrows | VL_REF_FLAG), cols(ncols)
+{
+}
+
+inline Vec Mat::operator [] (Int i)
+{
+    CheckRange(i, 0, Rows(), "(Mat::[i]) i index out of range");
+
+    return(Vec(cols, data + i * cols));
+}
+
+inline Vec Mat::operator [] (Int i) const
+{
+    CheckRange(i, 0, Rows(), "(Mat::[i]) i index out of range");
+
+    return(Vec(cols, data + i * cols));
+}
+
+inline Real &Mat::Elt(Int i, Int j)
+{
+    CheckRange(i, 0, Rows(), "(Mat::e(i,j)) i index out of range");
+    CheckRange(j, 0, Cols(), "(Mat::e(i,j)) j index out of range");
+
+    return(data[i * cols + j]);
+}
+
+inline Real Mat::Elt(Int i, Int j) const
+{
+    CheckRange(i, 0, Rows(), "(Mat::e(i,j)) i index out of range");
+    CheckRange(j, 0, Cols(), "(Mat::e(i,j)) j index out of range");
+
+    return(data[i * cols + j]);
+}
+
+inline Real *Mat::Ref() const
+{
+    return(data);
+}
+
+inline Mat operator * (Real s, const Mat &m)
+{
+    return(m * s);
+}
+
+inline Mat &Mat::operator = (ZeroOrOne k)
+{
+    MakeDiag(k);
+
+    return(SELF);
+}
+
+inline Mat &Mat::operator = (Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+
+    return(SELF);
+}
+
+inline Mat::~Mat()
+{
+    if (!IsRef())
+        delete[] data;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat2.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,146 @@
+/*
+    File:           Mat2.cpp
+
+    Function:       Implements Mat2.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+#include "Mat2.h"
+//#include <cctype>
+//#include <iomanip>
+#include "Utils.h"
+
+
+Bool Mat2::operator == (const Mat2 &m) const
+{
+    return(row[0] == m[0] && row[1] == m[1]);
+}
+
+Bool Mat2::operator != (const Mat2 &m) const
+{
+    return(row[0] != m[0] || row[1] != m[1]);
+}
+
+
+Real det(const Mat2 &m)
+{
+    return(dot(m[0], cross(m[1])));
+}
+
+Mat2 inv(const Mat2 &m)
+{
+    Real            mDet;
+    Mat2            result;
+
+    result[0][0] =  m[1][1]; result[0][1] = -m[0][1];
+    result[1][0] = -m[1][0]; result[1][1] =  m[0][0];
+
+    mDet = m[0][0] * result[0][0] + m[0][1] * result[1][0];
+    Assert(mDet != 0.0, "(Mat2::inv) matrix is non-singular");
+    result /= mDet;
+
+    return(result);
+}
+
+Mat2 oprod(const Vec2 &a, const Vec2 &b)
+// returns outerproduct of a and b:  a * trans(b)
+{
+    Mat2    result;
+
+    result[0] = a[0] * b;
+    result[1] = a[1] * b;
+
+    return(result);
+}
+
+void printMat2(const Mat2 &m)
+{
+    printf("[");
+    printVec2(m[0]);
+    printf("\r\n");
+    printVec2(m[1]);
+    printf("]\r\n");
+}
+
+/*
+ostream &operator << (ostream &s, const Mat2 &m)
+{
+    Int w = s.width();
+
+    return(s << '[' << m[0] << "\r\n" << setw(w) << m[1] << ']' << "\r\n");
+}
+
+istream &operator >> (istream &s, Mat2 &m)
+{
+    Mat2    result;
+    Char    c;
+
+    // Expected format: [[1 2] [3 4]]
+    // Each vector is a row of the row matrix.
+
+    while (s >> c && isspace(c))        // ignore leading white space
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1];
+
+        if (!s)
+        {
+            cerr << "Expected number while reading matrix\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Expected ']' while reading matrix\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Expected '[' while reading matrix\n";
+        return(s);
+    }
+
+    m = result;
+    return(s);
+}
+*/
+
+
+Mat2 &Mat2::MakeRot(Real theta)
+{
+    Real    c, s;
+
+    SetReal(s, sin(theta));
+    SetReal(c, cos(theta));
+
+#ifdef VL_ROW_ORIENT
+    row[0][0] =  c; row[0][1] = s;
+    row[1][0] = -s; row[1][1] = c;
+#else
+    row[0][0] = c; row[0][1] = -s;
+    row[1][0] = s; row[1][1] =  c;
+#endif
+
+    return(SELF);
+}
+
+Mat2 &Mat2::MakeScale(const Vec2 &s)
+{
+    row[0][0] = s[0]; row[0][1] = vl_0;
+    row[1][0] = vl_0; row[1][1] = s[1];
+
+    return(SELF);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat2.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,381 @@
+/*
+    File:           Mat2.h
+
+    Function:       Defines a 2 x 2 matrix.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Mat2__
+#define __Mat2__
+
+#include "Vec2.h"
+
+
+// --- Mat2 Class -------------------------------------------------------------
+
+class Mat2
+{
+public:
+
+    // Constructors
+
+                Mat2();
+                Mat2(Real a, Real b, Real c, Real d);   // Create from rows
+                Mat2(const Mat2 &m);                    // Copy constructor
+                Mat2(ZeroOrOne k);
+                Mat2(Block k);
+
+    // Accessor functions
+
+    Int         Rows() const { return(2); };
+    Int         Cols() const { return(2); };
+
+    Vec2        &operator [] (Int i);
+    const Vec2  &operator [] (Int i) const;
+
+    Real        *Ref() const;               // Return pointer to data
+
+    // Assignment operators
+
+    Mat2        &operator =  (const Mat2 &m);
+    Mat2        &operator =  (ZeroOrOne k);
+    Mat2        &operator =  (Block k);
+    Mat2        &operator += (const Mat2 &m);
+    Mat2        &operator -= (const Mat2 &m);
+    Mat2        &operator *= (const Mat2 &m);
+    Mat2        &operator *= (Real s);
+    Mat2        &operator /= (Real s);
+
+    // Comparison operators
+
+    Bool        operator == (const Mat2 &m) const;  // M == N?
+    Bool        operator != (const Mat2 &m) const;  // M != N?
+
+    // Arithmetic operators
+
+    Mat2        operator + (const Mat2 &m) const;   // M + N
+    Mat2        operator - (const Mat2 &m) const;   // M - N
+    Mat2        operator - () const;                // -M
+    Mat2        operator * (const Mat2 &m) const;   // M * N
+    Mat2        operator * (Real s) const;          // M * s
+    Mat2        operator / (Real s) const;          // M / s
+
+    // Initialisers
+
+    Void        MakeZero();                         // Zero matrix
+    Void        MakeDiag(Real k = vl_one);          // I
+    Void        MakeBlock(Real k = vl_one);         // all elts=k
+
+    // Vector Transformations
+
+    Mat2&       MakeRot(Real theta);
+    Mat2&       MakeScale(const Vec2 &s);
+
+    // Private...
+
+protected:
+
+    Vec2        row[2];     // Rows of the matrix
+};
+
+
+// --- Matrix operators -------------------------------------------------------
+
+inline Vec2     &operator *= (Vec2 &v, const Mat2 &m);      // v *= m
+inline Vec2     operator * (const Mat2 &m, const Vec2 &v);  // m * v
+inline Vec2     operator * (const Vec2 &v, const Mat2 &m);  // v * m
+inline Mat2     operator * (Real s, const Mat2 &m);         // s * m
+
+inline Mat2     trans(const Mat2 &m);               // Transpose
+inline Real     trace(const Mat2 &m);               // Trace
+inline Mat2     adj(const Mat2 &m);                 // Adjoint
+Real            det(const Mat2 &m);                 // Determinant
+Mat2            inv(const Mat2 &m);                 // Inverse
+Mat2            oprod(const Vec2 &a, const Vec2 &b);
+                                                    // Outer product
+
+// The xform functions help avoid dependence on whether row or column
+// vectors are used to represent points and vectors.
+inline Vec2     xform(const Mat2 &m, const Vec2 &v); // Transform of v by m
+inline Mat2     xform(const Mat2 &m, const Mat2 &n); // xform v -> m(n(v))
+
+//std::ostream         &operator << (std::ostream &s, const Mat2 &m);
+//std::istream         &operator >> (std::istream &s, Mat2 &m);
+
+void printMat2(const Mat2 &m);
+
+
+// --- Inlines ----------------------------------------------------------------
+
+inline Vec2 &Mat2::operator [] (Int i)
+{
+    CheckRange(i, 0, 2, "(Mat2::[i]) index out of range");
+    return(row[i]);
+}
+
+inline const Vec2 &Mat2::operator [] (Int i) const
+{
+    CheckRange(i, 0, 2, "(Mat2::[i]) index out of range");
+    return(row[i]);
+}
+
+inline Real *Mat2::Ref() const
+{
+    return((Real*) row);
+}
+
+inline Mat2::Mat2()
+{
+}
+
+inline Mat2::Mat2(Real a, Real b, Real c, Real d)
+{
+    row[0][0] = a;  row[0][1] = b;
+    row[1][0] = c;  row[1][1] = d;
+}
+
+inline Mat2::Mat2(const Mat2 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+}
+
+
+inline Void Mat2::MakeZero()
+{
+    row[0][0] = vl_zero; row[0][1] = vl_zero;
+    row[1][0] = vl_zero; row[1][1] = vl_zero;
+}
+
+inline Void Mat2::MakeDiag(Real k)
+{
+    row[0][0] = k;          row[0][1] = vl_zero;
+    row[1][0] = vl_zero;    row[1][1] = k;
+}
+
+inline Void Mat2::MakeBlock(Real k)
+{
+    row[0][0] = k; row[0][1] = k;
+    row[1][0] = k; row[1][1] = k;
+}
+
+inline Mat2::Mat2(ZeroOrOne k)
+{
+    MakeDiag(k);
+}
+
+inline Mat2::Mat2(Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+}
+
+inline Mat2 &Mat2::operator = (ZeroOrOne k)
+{
+    MakeDiag(k);
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator = (Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator = (const Mat2 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator += (const Mat2 &m)
+{
+    row[0] += m[0];
+    row[1] += m[1];
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator -= (const Mat2 &m)
+{
+    row[0] -= m[0];
+    row[1] -= m[1];
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator *= (const Mat2 &m)
+{
+    SELF = SELF * m;
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator *= (Real s)
+{
+    row[0] *= s;
+    row[1] *= s;
+
+    return(SELF);
+}
+
+inline Mat2 &Mat2::operator /= (Real s)
+{
+    row[0] /= s;
+    row[1] /= s;
+
+    return(SELF);
+}
+
+
+inline Mat2 Mat2::operator + (const Mat2 &m) const
+{
+    Mat2 result;
+
+    result[0] = row[0] + m[0];
+    result[1] = row[1] + m[1];
+
+    return(result);
+}
+
+inline Mat2 Mat2::operator - (const Mat2 &m) const
+{
+    Mat2 result;
+
+    result[0] = row[0] - m[0];
+    result[1] = row[1] - m[1];
+
+    return(result);
+}
+
+inline Mat2 Mat2::operator - () const
+{
+    Mat2 result;
+
+    result[0] = -row[0];
+    result[1] = -row[1];
+
+    return(result);
+}
+
+inline Mat2 Mat2::operator * (const Mat2 &m) const
+{
+#define N(x,y) row[x][y]
+#define M(x,y) m.row[x][y]
+#define R(x,y) result[x][y]
+
+    Mat2 result;
+
+    R(0,0) = N(0,0) * M(0,0) + N(0,1) * M(1,0);
+    R(0,1) = N(0,0) * M(0,1) + N(0,1) * M(1,1);
+    R(1,0) = N(1,0) * M(0,0) + N(1,1) * M(1,0);
+    R(1,1) = N(1,0) * M(0,1) + N(1,1) * M(1,1);
+
+    return(result);
+
+#undef N
+#undef M
+#undef R
+}
+
+inline Mat2 Mat2::operator * (Real s) const
+{
+    Mat2 result;
+
+    result[0] = row[0] * s;
+    result[1] = row[1] * s;
+
+    return(result);
+}
+
+inline Mat2 Mat2::operator / (Real s) const
+{
+    Mat2 result;
+
+    result[0] = row[0] / s;
+    result[1] = row[1] / s;
+
+    return(result);
+}
+
+inline Mat2  operator *  (Real s, const Mat2 &m)
+{
+    return(m * s);
+}
+
+inline Vec2 operator * (const Mat2 &m, const Vec2 &v)
+{
+    Vec2 result;
+
+    result[0] = m[0][0] * v[0] + m[0][1] * v[1];
+    result[1] = m[1][0] * v[0] + m[1][1] * v[1];
+
+    return(result);
+}
+
+inline Vec2 operator * (const Vec2 &v, const Mat2 &m)
+{
+    Vec2 result;
+
+    result[0] = v[0] * m[0][0] + v[1] * m[1][0];
+    result[1] = v[0] * m[0][1] + v[1] * m[1][1];
+
+    return(result);
+}
+
+inline Vec2 &operator *= (Vec2 &v, const Mat2 &m)
+{
+    Real t;
+
+    t    = v[0] * m[0][0] + v[1] * m[1][0];
+    v[1] = v[0] * m[0][1] + v[1] * m[1][1];
+    v[0] = t;
+
+    return(v);
+}
+
+
+inline Mat2 trans(const Mat2 &m)
+{
+    Mat2 result;
+
+    result[0][0] = m[0][0]; result[0][1] = m[1][0];
+    result[1][0] = m[0][1]; result[1][1] = m[1][1];
+
+    return(result);
+}
+
+inline Real trace(const Mat2 &m)
+{
+    return(m[0][0] + m[1][1]);
+}
+
+inline Mat2 adj(const Mat2 &m)
+{
+    Mat2 result;
+
+    result[0] =  cross(m[1]);
+    result[1] = -cross(m[0]);
+
+    return(result);
+}
+
+#ifdef VL_ROW_ORIENT
+inline Vec2 xform(const Mat2 &m, const Vec2 &v)
+{ return(v * m); }
+inline Mat2 xform(const Mat2 &m, const Mat2 &n)
+{ return(n * m); }
+#else
+inline Vec2 xform(const Mat2 &m, const Vec2 &v)
+{ return(m * v); }
+inline Mat2 xform(const Mat2 &m, const Mat2 &n)
+{ return(m * n); }
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat3.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,442 @@
+/*
+    File:           Mat3.cpp
+
+    Function:       Implements Mat3.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+#include "Mat3.h"
+#include "Vec4.h"
+//#include <cctype>
+//#include <iomanip>
+
+
+Mat3::Mat3(Real a, Real b, Real c,
+           Real d, Real e, Real f,
+           Real g, Real h, Real i)
+{
+    row[0][0] = a;  row[0][1] = b;  row[0][2] = c;
+    row[1][0] = d;  row[1][1] = e;  row[1][2] = f;
+    row[2][0] = g;  row[2][1] = h;  row[2][2] = i;
+}
+
+Mat3::Mat3(const Mat3 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+    row[2] = m[2];
+}
+
+Mat3 &Mat3::operator = (const Mat3 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+    row[2] = m[2];
+
+    return(SELF);
+}
+
+Mat3 &Mat3::operator += (const Mat3 &m)
+{
+    row[0] += m[0];
+    row[1] += m[1];
+    row[2] += m[2];
+
+    return(SELF);
+}
+
+Mat3 &Mat3::operator -= (const Mat3 &m)
+{
+    row[0] -= m[0];
+    row[1] -= m[1];
+    row[2] -= m[2];
+
+    return(SELF);
+}
+
+Mat3 &Mat3::operator *= (const Mat3 &m)
+{
+    SELF = SELF * m;
+
+    return(SELF);
+}
+
+Mat3 &Mat3::operator *= (Real s)
+{
+    row[0] *= s;
+    row[1] *= s;
+    row[2] *= s;
+
+    return(SELF);
+}
+
+Mat3 &Mat3::operator /= (Real s)
+{
+    row[0] /= s;
+    row[1] /= s;
+    row[2] /= s;
+
+    return(SELF);
+}
+
+
+Bool Mat3::operator == (const Mat3 &m) const
+{
+    return(row[0] == m[0] && row[1] == m[1] && row[2] == m[2]);
+}
+
+Bool Mat3::operator != (const Mat3 &m) const
+{
+    return(row[0] != m[0] || row[1] != m[1] || row[2] != m[2]);
+}
+
+
+Mat3 Mat3::operator + (const Mat3 &m) const
+{
+    Mat3 result;
+
+    result[0] = row[0] + m[0];
+    result[1] = row[1] + m[1];
+    result[2] = row[2] + m[2];
+
+    return(result);
+}
+
+Mat3 Mat3::operator - (const Mat3 &m) const
+{
+    Mat3 result;
+
+    result[0] = row[0] - m[0];
+    result[1] = row[1] - m[1];
+    result[2] = row[2] - m[2];
+
+    return(result);
+}
+
+Mat3 Mat3::operator - () const
+{
+    Mat3 result;
+
+    result[0] = -row[0];
+    result[1] = -row[1];
+    result[2] = -row[2];
+
+    return(result);
+}
+
+Mat3 Mat3::operator * (const Mat3 &m) const
+{
+#define N(x,y) row[x][y]
+#define M(x,y) m[x][y]
+#define R(x,y) result[x][y]
+
+    Mat3 result;
+
+    R(0,0) = N(0,0) * M(0,0) + N(0,1) * M(1,0) + N(0,2) * M(2,0);
+    R(0,1) = N(0,0) * M(0,1) + N(0,1) * M(1,1) + N(0,2) * M(2,1);
+    R(0,2) = N(0,0) * M(0,2) + N(0,1) * M(1,2) + N(0,2) * M(2,2);
+
+    R(1,0) = N(1,0) * M(0,0) + N(1,1) * M(1,0) + N(1,2) * M(2,0);
+    R(1,1) = N(1,0) * M(0,1) + N(1,1) * M(1,1) + N(1,2) * M(2,1);
+    R(1,2) = N(1,0) * M(0,2) + N(1,1) * M(1,2) + N(1,2) * M(2,2);
+
+    R(2,0) = N(2,0) * M(0,0) + N(2,1) * M(1,0) + N(2,2) * M(2,0);
+    R(2,1) = N(2,0) * M(0,1) + N(2,1) * M(1,1) + N(2,2) * M(2,1);
+    R(2,2) = N(2,0) * M(0,2) + N(2,1) * M(1,2) + N(2,2) * M(2,2);
+
+    return(result);
+
+#undef N
+#undef M
+#undef R
+}
+
+Mat3 Mat3::operator * (Real s) const
+{
+    Mat3 result;
+
+    result[0] = row[0] * s;
+    result[1] = row[1] * s;
+    result[2] = row[2] * s;
+
+    return(result);
+}
+
+Mat3 Mat3::operator / (Real s) const
+{
+    Mat3 result;
+
+    result[0] = row[0] / s;
+    result[1] = row[1] / s;
+    result[2] = row[2] / s;
+
+    return(result);
+}
+
+Mat3 trans(const Mat3 &m)
+{
+#define M(x,y) m[x][y]
+#define R(x,y) result[x][y]
+
+    Mat3 result;
+
+    R(0,0) = M(0,0); R(0,1) = M(1,0); R(0,2) = M(2,0);
+    R(1,0) = M(0,1); R(1,1) = M(1,1); R(1,2) = M(2,1);
+    R(2,0) = M(0,2); R(2,1) = M(1,2); R(2,2) = M(2,2);
+
+    return(result);
+
+#undef M
+#undef R
+}
+
+Mat3 adj(const Mat3 &m)
+{
+    Mat3    result;
+
+    result[0] = cross(m[1], m[2]);
+    result[1] = cross(m[2], m[0]);
+    result[2] = cross(m[0], m[1]);
+
+    return(result);
+}
+
+
+Real trace(const Mat3 &m)
+{
+    return(m[0][0] + m[1][1] + m[2][2]);
+}
+
+Real det(const Mat3 &m)
+{
+    return(dot(m[0], cross(m[1], m[2])));
+}
+
+Mat3 inv(const Mat3 &m)
+{
+    Real    mDet;
+    Mat3    adjoint;
+    Mat3    result;
+
+    adjoint = adj(m);
+    mDet = dot(adjoint[0], m[0]);
+
+    Assert(mDet != 0, "(Mat3::inv) matrix is non-singular");
+
+    result = trans(adjoint);
+    result /= mDet;
+
+    return(result);
+}
+
+Mat3 oprod(const Vec3 &a, const Vec3 &b)
+// returns outerproduct of a and b:  a * trans(b)
+{
+    Mat3    result;
+
+    result[0] = a[0] * b;
+    result[1] = a[1] * b;
+    result[2] = a[2] * b;
+
+    return(result);
+}
+
+Void Mat3::MakeZero()
+{
+    Int     i;
+
+    for (i = 0; i < 9; i++)
+        ((Real*) row)[i] = vl_zero;
+}
+
+Void Mat3::MakeDiag(Real k)
+{
+    Int     i, j;
+
+    for (i = 0; i < 3; i++)
+        for (j = 0; j < 3; j++)
+            if (i == j)
+                row[i][j] = k;
+            else
+                row[i][j] = vl_zero;
+}
+
+Void Mat3::MakeBlock(Real k)
+{
+    Int     i;
+
+    for (i = 0; i < 9; i++)
+        ((Real *) row)[i] = k;
+}
+
+void printMat3(const Mat3 &m)
+{
+    printf("[");
+    printVec3(m[0]);
+    printf("\r\n");
+    printVec3(m[1]);
+    printf("\r\n");
+    printVec3(m[2]);
+    printf("]\r\n");
+}
+
+/*
+ostream &operator << (ostream &s, const Mat3 &m)
+{
+    Int     w = s.width();
+
+    return(s << '[' << m[0] << "\r\n" << setw(w) << m[1] << "\r\n" << setw(w)
+           << m[2] << ']' << "\r\n");
+}
+
+istream &operator >> (istream &s, Mat3 &m)
+{
+    Mat3    result;
+    Char    c;
+
+    // Expected format: [[1 2 3] [4 5 6] [7 8 9]]
+    // Each vector is a column of the matrix.
+
+    while (s >> c && isspace(c))        // ignore leading white space
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1] >> result[2];
+
+        if (!s)
+        {
+            cerr << "Expected number while reading matrix\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Expected ']' while reading matrix\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Expected '[' while reading matrix\n";
+        return(s);
+    }
+
+    m = result;
+    return(s);
+}
+*/
+
+
+Mat3 &Mat3::MakeRot(const Vec4 &q)
+// modify to the new quat format [q0, (q1,q2,q3)]
+{
+    Real    i2 =  2 * q[1],
+            j2 =  2 * q[2],
+            k2 =  2 * q[3],
+            ij = i2 * q[2],
+            ik = i2 * q[3],
+            jk = j2 * q[3],
+            ri = i2 * q[0],
+            rj = j2 * q[0],
+            rk = k2 * q[0];
+
+    i2 *= q[1];
+    j2 *= q[2];
+    k2 *= q[3];
+
+#if VL_ROW_ORIENT // off by default
+    row[0][0] = 1 - j2 - k2;  row[0][1] = ij + rk    ;  row[0][2] = ik - rj;
+    row[1][0] = ij - rk    ;  row[1][1] = 1 - i2 - k2;  row[1][2] = jk + ri;
+    row[2][0] = ik + rj    ;  row[2][1] = jk - ri    ;  row[2][2] = 1 - i2 - j2;
+#else
+    row[0][0] = 1 - j2 - k2;  row[0][1] = ij - rk    ;  row[0][2] = ik + rj;
+    row[1][0] = ij + rk    ;  row[1][1] = 1 - i2 - k2;  row[1][2] = jk - ri;
+    row[2][0] = ik - rj    ;  row[2][1] = jk + ri    ;  row[2][2] = 1 - i2 - j2;
+#endif
+
+    return(SELF);
+}
+
+Mat3 &Mat3::MakeRot(const Vec3 &axis, Real theta)
+// modify to the new quat format [q0,(q1,q2,q3)]
+{
+    Real            s;
+    Vec4            q;
+
+    theta /= 2.0;
+    s = sin(theta);
+
+    q[1] = s * axis[0];
+    q[2] = s * axis[1];
+    q[3] = s * axis[2];
+    q[0] = cos(theta);
+
+    MakeRot(q);
+
+    return(SELF);
+}
+
+Mat3 &Mat3::MakeScale(const Vec3 &s)
+{
+    MakeZero();
+
+    row[0][0] = s[0];
+    row[1][1] = s[1];
+    row[2][2] = s[2];
+
+    return(SELF);
+}
+
+Mat3 &Mat3::MakeHRot(Real theta)
+{
+    Real    c, s;
+
+    MakeDiag();
+
+    s = sin(theta);
+    c = cos(theta);
+
+#ifdef VL_ROW_ORIENT
+    row[0][0] =  c; row[0][1] =  s;
+    row[1][0] = -s; row[1][1] =  c;
+#else
+    row[0][0] =  c; row[0][1] = -s;
+    row[1][0] =  s; row[1][1] =  c;
+#endif
+
+    return(SELF);
+}
+
+Mat3 &Mat3::MakeHScale(const Vec2 &s)
+{
+    MakeDiag();
+
+    row[0][0] = s[0];
+    row[1][1] = s[1];
+
+    return(SELF);
+}
+
+Mat3 &Mat3::MakeHTrans(const Vec2 &t)
+{
+    MakeDiag();
+
+#ifdef VL_ROW_ORIENT
+    row[2][0] = t[0];
+    row[2][1] = t[1];
+#else
+    row[0][2] = t[0];
+    row[1][2] = t[1];
+#endif
+
+    return(SELF);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat3.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,226 @@
+/*
+    File:           Mat3.h
+
+    Function:       Defines a 3 x 3 matrix.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+*/
+
+#ifndef __Mat3__
+#define __Mat3__
+
+#include "Vec3.h"
+
+
+// --- Mat3 Class -------------------------------------------------------------
+
+
+class Vec4;
+
+class Mat3
+{
+public:
+
+    // Constructors
+
+                Mat3();
+                Mat3(Real a, Real b, Real c,
+                     Real d, Real e, Real f,
+                     Real g, Real h, Real i);
+                Mat3(const Mat3 &m);
+                Mat3(ZeroOrOne k);
+                Mat3(Block k);
+
+    // Accessor functions
+
+    Int         Rows() const { return(3); };
+    Int         Cols() const { return(3); };
+
+    Vec3        &operator [] (Int i);
+    const Vec3  &operator [] (Int i) const;
+
+    Real        *Ref() const;               // Return pointer to data
+
+    // Assignment operators
+
+    Mat3        &operator =  (const Mat3 &m);
+    Mat3        &operator =  (ZeroOrOne k);
+    Mat3        &operator =  (Block k);
+    Mat3        &operator += (const Mat3 &m);
+    Mat3        &operator -= (const Mat3 &m);
+    Mat3        &operator *= (const Mat3 &m);
+    Mat3        &operator *= (Real s);
+    Mat3        &operator /= (Real s);
+
+    // Comparison operators
+
+    Bool        operator == (const Mat3 &m) const;  // M == N?
+    Bool        operator != (const Mat3 &m) const;  // M != N?
+
+    // Arithmetic operators
+
+    Mat3        operator + (const Mat3 &m) const;   // M + N
+    Mat3        operator - (const Mat3 &m) const;   // M - N
+    Mat3        operator - () const;                // -M
+    Mat3        operator * (const Mat3 &m) const;   // M * N
+    Mat3        operator * (Real s) const;          // M * s
+    Mat3        operator / (Real s) const;          // M / s
+
+    // Initialisers
+
+    Void        MakeZero();                 // Zero matrix
+    Void        MakeDiag(Real k = vl_one);  // I
+    Void        MakeBlock(Real k = vl_one); // all elts = k
+
+    // Vector Transforms
+
+    Mat3&       MakeRot(const Vec3 &axis, Real theta);
+    Mat3&       MakeRot(const Vec4 &q);     // Rotate by quaternion
+    Mat3&       MakeScale(const Vec3 &s);
+
+    // Homogeneous Transforms
+
+    Mat3&       MakeHRot(Real theta);       // Rotate by theta rads
+    Mat3&       MakeHScale(const Vec2 &s);  // Scale by s
+    Mat3&       MakeHTrans(const Vec2 &t);  // Translation by t
+
+    // Private...
+
+protected:
+
+    Vec3        row[3];
+};
+
+
+// --- Matrix operators -------------------------------------------------------
+
+inline Vec3     &operator *= (Vec3 &v, const Mat3 &m);      // v *= m
+inline Vec3     operator * (const Mat3 &m, const Vec3 &v);  // m * v
+inline Vec3     operator * (const Vec3 &v, const Mat3 &m);  // v * m
+inline Mat3     operator * (const Real s, const Mat3 &m);   // s * m
+
+Mat3            trans(const Mat3 &m);                   // Transpose
+Real            trace(const Mat3 &m);                   // Trace
+Mat3            adj(const Mat3 &m);                     // Adjoint
+Real            det(const Mat3 &m);                     // Determinant
+Mat3            inv(const Mat3 &m);                     // Inverse
+Mat3            oprod(const Vec3 &a, const Vec3 &b);    // Outer product
+
+// The xform functions help avoid dependence on whether row or column
+// vectors are used to represent points and vectors.
+inline Vec3     xform(const Mat3 &m, const Vec3 &v); // Transform of v by m
+inline Vec2     xform(const Mat3 &m, const Vec2 &v); // Hom. xform of v by m
+inline Mat3     xform(const Mat3 &m, const Mat3 &n); // Xform v -> m(n(v))
+
+//std::ostream         &operator << (std::ostream &s, const Mat3 &m);
+//std::istream         &operator >> (std::istream &s, Mat3 &m);
+
+void printMat3(const Mat3 &m);
+
+
+// --- Inlines ----------------------------------------------------------------
+
+inline Mat3::Mat3()
+{
+}
+
+inline Vec3 &Mat3::operator [] (Int i)
+{
+    CheckRange(i, 0, 3, "(Mat3::[i]) index out of range");
+    return(row[i]);
+}
+
+inline const Vec3 &Mat3::operator [] (Int i) const
+{
+    CheckRange(i, 0, 3, "(Mat3::[i]) index out of range");
+    return(row[i]);
+}
+
+inline Real *Mat3::Ref() const
+{
+    return((Real *) row);
+}
+
+inline Mat3::Mat3(ZeroOrOne k)
+{
+    MakeDiag(k);
+}
+
+inline Mat3::Mat3(Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+}
+
+inline Mat3 &Mat3::operator = (ZeroOrOne k)
+{
+    MakeDiag(k);
+
+    return(SELF);
+}
+
+inline Mat3 &Mat3::operator = (Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+
+    return(SELF);
+}
+
+inline Mat3 operator *  (const Real s, const Mat3 &m)
+{
+    return(m * s);
+}
+
+inline Vec3 operator * (const Mat3 &m, const Vec3 &v)
+{
+    Vec3 result;
+
+    result[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2];
+    result[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2];
+    result[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2];
+
+    return(result);
+}
+
+inline Vec3 operator * (const Vec3 &v, const Mat3 &m)
+{
+    Vec3 result;
+
+    result[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0];
+    result[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1];
+    result[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2];
+
+    return(result);
+}
+
+inline Vec3 &operator *= (Vec3 &v, const Mat3 &m)
+{
+    Real t0, t1;
+
+    t0   = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0];
+    t1   = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1];
+    v[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2];
+    v[0] = t0;
+    v[1] = t1;
+
+    return(v);
+}
+
+#ifdef VL_ROW_ORIENT
+inline Vec2 xform(const Mat3 &m, const Vec2 &v)
+{ return(proj(Vec3(v, 1.0) * m)); }
+inline Vec3 xform(const Mat3 &m, const Vec3 &v)
+{ return(v * m); }
+inline Mat3 xform(const Mat3 &m, const Mat3 &n)
+{ return(n * m); }
+#else
+inline Vec2 xform(const Mat3 &m, const Vec2 &v)
+{ return(proj(m * Vec3(v, 1.0))); }
+inline Vec3 xform(const Mat3 &m, const Vec3 &v)
+{ return(m * v); }
+inline Mat3 xform(const Mat3 &m, const Mat3 &n)
+{ return(m * n); }
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat4.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,507 @@
+/*
+    File:           Mat4.cpp
+
+    Function:       Implements Mat4.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+#include "Mat4.h"
+//#include <cctype>
+//#include <iomanip>
+
+
+Mat4::Mat4(Real a, Real b, Real c, Real d,
+           Real e, Real f, Real g, Real h,
+           Real i, Real j, Real k, Real l,
+           Real m, Real n, Real o, Real p)
+{
+    row[0][0] = a;  row[0][1] = b;  row[0][2] = c;  row[0][3] = d;
+    row[1][0] = e;  row[1][1] = f;  row[1][2] = g;  row[1][3] = h;
+    row[2][0] = i;  row[2][1] = j;  row[2][2] = k;  row[2][3] = l;
+    row[3][0] = m;  row[3][1] = n;  row[3][2] = o;  row[3][3] = p;
+}
+
+Mat4::Mat4(const Mat4 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+    row[2] = m[2];
+    row[3] = m[3];
+}
+
+
+Mat4 &Mat4::operator = (const Mat4 &m)
+{
+    row[0] = m[0];
+    row[1] = m[1];
+    row[2] = m[2];
+    row[3] = m[3];
+
+    return(SELF);
+}
+
+Mat4 &Mat4::operator += (const Mat4 &m)
+{
+    row[0] += m[0];
+    row[1] += m[1];
+    row[2] += m[2];
+    row[3] += m[3];
+
+    return(SELF);
+}
+
+Mat4 &Mat4::operator -= (const Mat4 &m)
+{
+    row[0] -= m[0];
+    row[1] -= m[1];
+    row[2] -= m[2];
+    row[3] -= m[3];
+
+    return(SELF);
+}
+
+Mat4 &Mat4::operator *= (const Mat4 &m)
+{
+    SELF = SELF * m;
+
+    return(SELF);
+}
+
+Mat4 &Mat4::operator *= (Real s)
+{
+    row[0] *= s;
+    row[1] *= s;
+    row[2] *= s;
+    row[3] *= s;
+
+    return(SELF);
+}
+
+Mat4 &Mat4::operator /= (Real s)
+{
+    row[0] /= s;
+    row[1] /= s;
+    row[2] /= s;
+    row[3] /= s;
+
+    return(SELF);
+}
+
+
+Bool Mat4::operator == (const Mat4 &m) const
+{
+    return(row[0] == m[0] && row[1] == m[1] && row[2] == m[2] && row[3] == m[3]);
+}
+
+Bool Mat4::operator != (const Mat4 &m) const
+{
+    return(row[0] != m[0] || row[1] != m[1] || row[2] != m[2] || row[3] != m[3]);
+}
+
+
+Mat4 Mat4::operator + (const Mat4 &m) const
+{
+    Mat4 result;
+
+    result[0] = row[0] + m[0];
+    result[1] = row[1] + m[1];
+    result[2] = row[2] + m[2];
+    result[3] = row[3] + m[3];
+
+    return(result);
+}
+
+Mat4 Mat4::operator - (const Mat4 &m) const
+{
+    Mat4 result;
+
+    result[0] = row[0] - m[0];
+    result[1] = row[1] - m[1];
+    result[2] = row[2] - m[2];
+    result[3] = row[3] - m[3];
+
+    return(result);
+}
+
+Mat4 Mat4::operator - () const
+{
+    Mat4 result;
+
+    result[0] = -row[0];
+    result[1] = -row[1];
+    result[2] = -row[2];
+    result[3] = -row[3];
+
+    return(result);
+}
+
+Mat4 Mat4::operator * (const Mat4 &m) const
+{
+#define N(x,y) row[x][y]
+#define M(x,y) m[x][y]
+#define R(x,y) result[x][y]
+
+    Mat4 result;
+
+    R(0,0) = N(0,0) * M(0,0) + N(0,1) * M(1,0) + N(0,2) * M(2,0) + N(0,3) * M(3,0);
+    R(0,1) = N(0,0) * M(0,1) + N(0,1) * M(1,1) + N(0,2) * M(2,1) + N(0,3) * M(3,1);
+    R(0,2) = N(0,0) * M(0,2) + N(0,1) * M(1,2) + N(0,2) * M(2,2) + N(0,3) * M(3,2);
+    R(0,3) = N(0,0) * M(0,3) + N(0,1) * M(1,3) + N(0,2) * M(2,3) + N(0,3) * M(3,3);
+
+    R(1,0) = N(1,0) * M(0,0) + N(1,1) * M(1,0) + N(1,2) * M(2,0) + N(1,3) * M(3,0);
+    R(1,1) = N(1,0) * M(0,1) + N(1,1) * M(1,1) + N(1,2) * M(2,1) + N(1,3) * M(3,1);
+    R(1,2) = N(1,0) * M(0,2) + N(1,1) * M(1,2) + N(1,2) * M(2,2) + N(1,3) * M(3,2);
+    R(1,3) = N(1,0) * M(0,3) + N(1,1) * M(1,3) + N(1,2) * M(2,3) + N(1,3) * M(3,3);
+
+    R(2,0) = N(2,0) * M(0,0) + N(2,1) * M(1,0) + N(2,2) * M(2,0) + N(2,3) * M(3,0);
+    R(2,1) = N(2,0) * M(0,1) + N(2,1) * M(1,1) + N(2,2) * M(2,1) + N(2,3) * M(3,1);
+    R(2,2) = N(2,0) * M(0,2) + N(2,1) * M(1,2) + N(2,2) * M(2,2) + N(2,3) * M(3,2);
+    R(2,3) = N(2,0) * M(0,3) + N(2,1) * M(1,3) + N(2,2) * M(2,3) + N(2,3) * M(3,3);
+
+    R(3,0) = N(3,0) * M(0,0) + N(3,1) * M(1,0) + N(3,2) * M(2,0) + N(3,3) * M(3,0);
+    R(3,1) = N(3,0) * M(0,1) + N(3,1) * M(1,1) + N(3,2) * M(2,1) + N(3,3) * M(3,1);
+    R(3,2) = N(3,0) * M(0,2) + N(3,1) * M(1,2) + N(3,2) * M(2,2) + N(3,3) * M(3,2);
+    R(3,3) = N(3,0) * M(0,3) + N(3,1) * M(1,3) + N(3,2) * M(2,3) + N(3,3) * M(3,3);
+
+    return(result);
+
+#undef N
+#undef M
+#undef R
+}
+
+Mat4 Mat4::operator * (Real s) const
+{
+    Mat4 result;
+
+    result[0] = row[0] * s;
+    result[1] = row[1] * s;
+    result[2] = row[2] * s;
+    result[3] = row[3] * s;
+
+    return(result);
+}
+
+Mat4 Mat4::operator / (Real s) const
+{
+    Mat4 result;
+
+    result[0] = row[0] / s;
+    result[1] = row[1] / s;
+    result[2] = row[2] / s;
+    result[3] = row[3] / s;
+
+    return(result);
+}
+
+Vec4 operator * (const Mat4 &m, const Vec4 &v)          // m * v
+{
+    Vec4 result;
+
+    result[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + v[3] * m[0][3];
+    result[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + v[3] * m[1][3];
+    result[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + v[3] * m[2][3];
+    result[3] = v[0] * m[3][0] + v[1] * m[3][1] + v[2] * m[3][2] + v[3] * m[3][3];
+
+    return(result);
+}
+
+Vec4 operator * (const Vec4 &v, const Mat4 &m)          // v * m
+{
+    Vec4 result;
+
+    result[0] = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0];
+    result[1] = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1];
+    result[2] = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2];
+    result[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3];
+
+    return(result);
+}
+
+Vec4 &operator *= (Vec4 &v, const Mat4 &m)              // v *= m
+{
+    Real    t0, t1, t2;
+
+    t0   = v[0] * m[0][0] + v[1] * m[1][0] + v[2] * m[2][0] + v[3] * m[3][0];
+    t1   = v[0] * m[0][1] + v[1] * m[1][1] + v[2] * m[2][1] + v[3] * m[3][1];
+    t2   = v[0] * m[0][2] + v[1] * m[1][2] + v[2] * m[2][2] + v[3] * m[3][2];
+    v[3] = v[0] * m[0][3] + v[1] * m[1][3] + v[2] * m[2][3] + v[3] * m[3][3];
+    v[0] = t0;
+    v[1] = t1;
+    v[2] = t2;
+
+    return(v);
+}
+
+Mat4 trans(const Mat4 &m)
+{
+#define M(x,y) m[x][y]
+#define R(x,y) result[x][y]
+
+    Mat4 result;
+
+    R(0,0) = M(0,0); R(0,1) = M(1,0); R(0,2) = M(2,0); R(0,3) = M(3,0);
+    R(1,0) = M(0,1); R(1,1) = M(1,1); R(1,2) = M(2,1); R(1,3) = M(3,1);
+    R(2,0) = M(0,2); R(2,1) = M(1,2); R(2,2) = M(2,2); R(2,3) = M(3,2);
+    R(3,0) = M(0,3); R(3,1) = M(1,3); R(3,2) = M(2,3); R(3,3) = M(3,3);
+
+    return(result);
+
+#undef M
+#undef R
+}
+
+Mat4 adj(const Mat4 &m)
+{
+    Mat4    result;
+
+    result[0] =  cross(m[1], m[2], m[3]);
+    result[1] = -cross(m[0], m[2], m[3]);
+    result[2] =  cross(m[0], m[1], m[3]);
+    result[3] = -cross(m[0], m[1], m[2]);
+
+    return(result);
+}
+
+Real trace(const Mat4 &m)
+{
+    return(m[0][0] + m[1][1] + m[2][2] + m[3][3]);
+}
+
+Real det(const Mat4 &m)
+{
+    return(dot(m[0], cross(m[1], m[2], m[3])));
+}
+
+Mat4 inv(const Mat4 &m)
+{
+    Real    mDet;
+    Mat4    adjoint;
+    Mat4    result;
+
+    adjoint = adj(m);               // Find the adjoint
+    mDet = dot(adjoint[0], m[0]);
+
+    Assert(mDet != 0, "(Mat4::inv) matrix is non-singular");
+
+    result = trans(adjoint);
+    result /= mDet;
+
+    return(result);
+}
+
+Mat4 oprod(const Vec4 &a, const Vec4 &b)
+// returns outerproduct of a and b:  a * trans(b)
+{
+    Mat4    result;
+
+    result[0] = a[0] * b;
+    result[1] = a[1] * b;
+    result[2] = a[2] * b;
+    result[3] = a[3] * b;
+
+    return(result);
+}
+
+Void Mat4::MakeZero()
+{
+    Int     i;
+
+    for (i = 0; i < 16; i++)
+        ((Real *) row)[i] = vl_zero;
+}
+
+Void Mat4::MakeDiag(Real k)
+// default argument is vl_one
+{
+    Int     i, j;
+
+    for (i = 0; i < 4; i++)
+        for (j = 0; j < 4; j++)
+            if (i == j)
+                row[i][j] = k;
+            else
+                row[i][j] = vl_zero;
+}
+
+Void Mat4::MakeBlock(Real k)
+{
+    Int     i;
+
+    for (i = 0; i < 16; i++) {
+        //printf("i = %d k = %f\r\n",i,k);
+        ((Real *) row)[i] = k;
+    }    
+}
+
+void printMat4(const Mat4 &m)
+{
+    printf("[");
+    printVec4(m[0]);
+    printf("\r\n");
+    printVec4(m[1]);
+    printf("\r\n");
+    printVec4(m[2]);
+    printf("\r\n");
+    printVec4(m[3]);
+    printf("]\r\n");
+}
+
+/*
+ostream &operator << (ostream &s, const Mat4 &m)
+{
+    Int w = s.width();
+
+    return(s << '[' << m[0] << "\r\n" << setw(w) << m[1] << "\r\n"
+         << setw(w) << m[2] << "\r\n" << setw(w) << m[3] << ']' << "\r\n");
+}
+
+istream &operator >> (istream &s, Mat4 &m)
+{
+    Mat4    result;
+    Char    c;
+
+    // Expected format: [[1 2 3] [4 5 6] [7 8 9]]
+    // Each vector is a column of the matrix.
+
+    while (s >> c && isspace(c))        // ignore leading white space
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1] >> result[2] >> result[3];
+
+        if (!s)
+        {
+            cerr << "Expected number while reading matrix\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Expected ']' while reading matrix\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Expected '[' while reading matrix\n";
+        return(s);
+    }
+
+    m = result;
+    return(s);
+}
+*/
+
+
+Mat4& Mat4::MakeHRot(const Vec4 &q)
+{
+    Real    i2 =  2 * q[1],
+            j2 =  2 * q[2],
+            k2 =  2 * q[3],
+            ij = i2 * q[2],
+            ik = i2 * q[3],
+            jk = j2 * q[3],
+            ri = i2 * q[0],
+            rj = j2 * q[0],
+            rk = k2 * q[0];
+
+    MakeDiag();
+
+    i2 *= q[1];
+    j2 *= q[2];
+    k2 *= q[3];
+
+#if VL_ROW_ORIENT
+    row[0][0] = 1 - j2 - k2;  row[0][1] = ij + rk   ;  row[0][2] = ik - rj;
+    row[1][0] = ij - rk    ;  row[1][1] = 1 - i2- k2;  row[1][2] = jk + ri;
+    row[2][0] = ik + rj    ;  row[2][1] = jk - ri   ;  row[2][2] = 1 - i2 - j2;
+#else
+    row[0][0] = 1 - j2 - k2;  row[0][1] = ij - rk   ;  row[0][2] = ik + rj;
+    row[1][0] = ij + rk    ;  row[1][1] = 1 - i2- k2;  row[1][2] = jk - ri;
+    row[2][0] = ik - rj    ;  row[2][1] = jk + ri   ;  row[2][2] = 1 - i2 - j2;
+#endif
+
+    return(SELF);
+}
+
+Mat4& Mat4::MakeHRot(const Vec3 &axis, Real theta)
+{
+    Real        s;
+    Vec4        q;
+
+    theta /= 2.0;
+    s = sin(theta);
+
+    q[1] = s * axis[0];
+    q[2] = s * axis[1];
+    q[3] = s * axis[2];
+    q[0] = cos(theta);
+
+    MakeHRot(q);
+
+    return(SELF);
+}
+
+Mat4& Mat4::MakeHScale(const Vec3 &s)
+{
+    MakeDiag();
+
+    row[0][0] = s[0];
+    row[1][1] = s[1];
+    row[2][2] = s[2];
+
+    return(SELF);
+}
+
+Mat4& Mat4::MakeHTrans(const Vec3 &t)
+{
+    MakeDiag();
+
+#ifdef VL_ROW_ORIENT
+    row[3][0] = t[0];
+    row[3][1] = t[1];
+    row[3][2] = t[2];
+#else
+    row[0][3] = t[0];
+    row[1][3] = t[1];
+    row[2][3] = t[2];
+#endif
+
+    return(SELF);
+}
+
+Mat4& Mat4::Transpose()
+{
+    row[0][1] = row[1][0]; row[0][2] = row[2][0]; row[0][3] = row[3][0];
+    row[1][0] = row[0][1]; row[1][2] = row[2][1]; row[1][3] = row[3][1];
+    row[2][0] = row[0][2]; row[2][1] = row[1][2]; row[2][3] = row[3][2];
+    row[3][0] = row[0][3]; row[3][1] = row[1][3]; row[3][2] = row[2][3];
+
+    return(SELF);
+}
+
+Mat4& Mat4::AddShift(const Vec3 &t)
+{
+#ifdef VL_ROW_ORIENT
+    row[3][0] += t[0];
+    row[3][1] += t[1];
+    row[3][2] += t[2];
+#else
+    row[0][3] += t[0];
+    row[1][3] += t[1];
+    row[2][3] += t[2];
+#endif
+
+    return(SELF);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Mat4.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,190 @@
+/*
+    File:           Mat4.h
+
+    Function:       Defines a 4 x 4 matrix.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Mat4__
+#define __Mat4__
+
+#include "Vec3.h"
+#include "Vec4.h"
+
+
+// --- Mat4 Class -------------------------------------------------------------
+
+class Mat4
+{
+public:
+
+    // Constructors
+
+                Mat4();
+                Mat4(Real a, Real b, Real c, Real d,
+                     Real e, Real f, Real g, Real h,
+                     Real i, Real j, Real k, Real l,
+                     Real m, Real n, Real o, Real p);
+                Mat4(const Mat4 &m);
+                Mat4(ZeroOrOne k);
+                Mat4(Block k);
+
+    // Accessor functions
+
+    Int          Rows() const { return(4); };
+    Int          Cols() const { return(4); };
+
+    Vec4        &operator [] (Int i);
+    const Vec4  &operator [] (Int i) const;
+
+    Real        *Ref() const;
+
+    // Assignment operators
+
+    Mat4        &operator =  (const Mat4 &m);
+    Mat4        &operator =  (ZeroOrOne k);
+    Mat4        &operator =  (Block k);
+    Mat4        &operator += (const Mat4 &m);
+    Mat4        &operator -= (const Mat4 &m);
+    Mat4        &operator *= (const Mat4 &m);
+    Mat4        &operator *= (Real s);
+    Mat4        &operator /= (Real s);
+
+    // Comparison operators
+
+    Bool        operator == (const Mat4 &m) const;  // M == N?
+    Bool        operator != (const Mat4 &m) const;  // M != N?
+
+    // Arithmetic operators
+
+    Mat4        operator + (const Mat4 &m) const;   // M + N
+    Mat4        operator - (const Mat4 &m) const;   // M - N
+    Mat4        operator - () const;                // -M
+    Mat4        operator * (const Mat4 &m) const;   // M * N
+    Mat4        operator * (Real s) const;          // M * s
+    Mat4        operator / (Real s) const;          // M / s
+
+    // Initialisers
+
+    Void        MakeZero();                         // Zero matrix
+    Void        MakeDiag(Real k = vl_one);          // I
+    Void        MakeBlock(Real k = vl_one);         // all elts = k
+
+    // Homogeneous Transforms
+
+    Mat4&       MakeHRot(const Vec3 &axis, Real theta);
+                                    // Rotate by theta radians about axis
+    Mat4&       MakeHRot(const Vec4 &q);    // Rotate by quaternion
+    Mat4&       MakeHScale(const Vec3 &s);  // Scale by components of s
+
+    Mat4&       MakeHTrans(const Vec3 &t);  // Translation by t
+
+    Mat4&       Transpose();                // transpose in place
+    Mat4&       AddShift(const Vec3 &t);    // Concatenate shift
+
+    // Private...
+
+protected:
+
+    Vec4        row[4];
+};
+
+
+// --- Matrix operators -------------------------------------------------------
+
+Vec4            operator * (const Mat4 &m, const Vec4 &v);  // m * v
+Vec4            operator * (const Vec4 &v, const Mat4 &m);  // v * m
+Vec4            &operator *= (Vec4 &a, const Mat4 &m);      // v *= m
+inline Mat4     operator * (Real s, const Mat4 &m);         // s * m
+
+Mat4            trans(const Mat4 &m);               // Transpose
+Real            trace(const Mat4 &m);               // Trace
+Mat4            adj(const Mat4 &m);                 // Adjoint
+Real            det(const Mat4 &m);                 // Determinant
+Mat4            inv(const Mat4 &m);                 // Inverse
+Mat4            oprod(const Vec4 &a, const Vec4 &b);
+                                                    // Outer product
+
+// The xform functions help avoid dependence on whether row or column
+// vectors are used to represent points and vectors.
+inline Vec4     xform(const Mat4 &m, const Vec4 &v); // Transform of v by m
+inline Vec3     xform(const Mat4 &m, const Vec3 &v); // Hom. xform of v by m
+inline Mat4     xform(const Mat4 &m, const Mat4 &n); // Xform v -> m(n(v))
+
+//std::ostream         &operator << (std::ostream &s, const Mat4 &m);
+//std::istream         &operator >> (std::istream &s, Mat4 &m);
+
+void printMat4(const Mat4 &m);
+
+// --- Inlines ----------------------------------------------------------------
+
+inline Mat4::Mat4()
+{
+}
+
+inline Vec4 &Mat4::operator [] (Int i)
+{
+    CheckRange(i, 0, 4, "(Mat4::[i]) index out of range");
+    return(row[i]);
+}
+
+inline const Vec4 &Mat4::operator [] (Int i) const
+{
+    CheckRange(i, 0, 4, "(Mat4::[i]) index out of range");
+    return(row[i]);
+}
+
+inline Real *Mat4::Ref() const
+{
+    return((Real *) row);
+}
+
+inline Mat4::Mat4(ZeroOrOne k)
+{
+    MakeDiag(k);
+}
+
+inline Mat4::Mat4(Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+}
+
+inline Mat4 &Mat4::operator = (ZeroOrOne k)
+{
+    MakeDiag(k);
+
+    return(SELF);
+}
+
+inline Mat4 &Mat4::operator = (Block k)
+{
+    MakeBlock((ZeroOrOne) k);
+
+    return(SELF);
+}
+
+inline Mat4 operator * (Real s, const Mat4 &m)
+{
+    return(m * s);
+}
+
+#ifdef VL_ROW_ORIENT
+inline Vec3 xform(const Mat4 &m, const Vec3 &v)
+{ return(proj(Vec4(v, 1.0) * m)); }
+inline Vec4 xform(const Mat4 &m, const Vec4 &v)
+{ return(v * m); }
+inline Mat4 xform(const Mat4 &m, const Mat4 &n)
+{ return(n * m); }
+#else
+inline Vec3 xform(const Mat4 &m, const Vec3 &v)
+{ return(proj(m * Vec4(v, 1.0))); }
+inline Vec4 xform(const Mat4 &m, const Vec4 &v)
+{ return(m * v); }
+inline Mat4 xform(const Mat4 &m, const Mat4 &n)
+{ return(m * n); }
+#endif
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Quat.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,146 @@
+#include "Quat.h"
+//#include "svl/Mat3.h"
+#include <cctype>
+#include <iomanip>
+
+//
+// Quat in SVL: [(q0,q1,q2),q3]
+// update: 
+// Modify to conform with most literature:
+// Quat in SVL [q0, (q1,q2,q3)]
+// (may need to modify other SVL files relating to quat!!!
+//
+// implement:
+//
+// Quaterion multiplication
+// 3x3 -> mQuat; 
+// mQuat->3x3 (NY) .... already available 
+// slerp
+//
+// find application that demonstrate the needs ...
+//
+
+Mat3 Rot3 (const Quat &q)
+{
+    Mat3 result; 
+    Vec4 v(q[0],q[1],q[2],q[3]);
+    result.MakeRot(v); 
+    return(result); 
+}
+
+Mat4 HRot4 (const Quat &q)
+{
+    Mat4 result; 
+    Vec4 v(q[0],q[1],q[2],q[3]);
+    result.MakeHRot(v);
+    return(result); 
+}
+
+Quat::Quat(const Mat3 & m)
+{   
+    Real compare[4], max;
+    compare[0] = 1 + m[0][0] + m[1][1] + m[2][2];
+    compare[1] = 1 + m[0][0] - m[1][1] - m[2][2];
+    compare[2] = 1 - m[0][0] + m[1][1] - m[2][2];
+    compare[3] = 1 - m[0][0] - m[1][1] + m[2][2];
+
+    int i, which;
+    for (i = 0, which = -1, max = 0; i < 4; i++)
+    if (fabs(compare[i]) > max)
+        which = i, max = fabs(compare[i]);
+
+    Real q0,q1,q2,q3;
+    switch (which) {
+      case 0:
+        q0 = 0.5*sqrt (compare[which]);
+        q1 = 0.25*(m[2][1] - m[1][2])/q0;
+        q2 = 0.25*(m[0][2] - m[2][0])/q0;
+        q3 = 0.25*(m[1][0] - m[0][1])/q0;
+        break;
+
+      case 1:
+        q1 = 0.5*sqrt (compare[which]);
+        q0 = 0.25*(m[2][1] - m[1][2])/q1;
+        q2 = 0.25*(m[0][1] + m[1][0])/q1;
+        q3 = 0.25*(m[0][2] + m[2][0])/q1;
+        break;
+
+      case 2:
+        q2 = 0.5*sqrt (compare[which]);
+        q0 = 0.25*(m[0][2] - m[2][0])/q2;
+        q1 = 0.25*(m[0][1] + m[1][0])/q2;
+        q3 = 0.25*(m[1][2] + m[2][1])/q2;
+        break;
+
+      case 3:
+        q3 = 0.5*sqrt (compare[which]);
+        q0 = 0.25*(m[1][0] - m[0][1])/q3;
+        q1 = 0.25*(m[0][2] + m[2][0])/q3;
+        q2 = 0.25*(m[1][2] + m[2][1])/q3;
+        break;
+    }
+    elt[1] = q1, elt[2] = q2, elt[3] = q3, elt[0] = q0;
+}
+
+void printQuat(const Quat &v)
+{
+    Int i;
+    
+    printf("[");
+    for (i = 0; i < 3; i++){
+        printf("%f", v[i]);
+        printf(" ");
+    }
+    printf("%f ]/r/n", v[3]);
+}
+
+/*
+ostream &operator << (ostream &s, const Quat &v)
+{
+    Int w = s.width();
+
+    return(s << '[' << v[0] << ' ' << setw(w) << v[1] << ' '
+        << setw(w) << v[2] << ' ' << setw(w) << v[3] << ']');
+}
+
+istream &operator >> (istream &s, Quat &v)
+{
+    Quat    result;
+    Char    c;
+
+    // Expected format: [1 2 3 4]
+
+    while (s >> c && isspace(c))
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1] >> result[2] >> result[3];
+
+        if (!s)
+        {
+            cerr << "Error: Expected number while reading vector\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Error: Expected ']' while reading vector\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Error: Expected '[' while reading vector\n";
+        return(s);
+    }
+
+    v = result;
+    return(s);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Quat.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,296 @@
+#ifndef __Quat__
+#define __Quat__
+#include "Vec3.h"
+#include "Mat3.h"
+#include "Vec4.h"
+#include "Mat4.h"
+
+class Quat 
+{
+public:
+    // constructors
+    Quat();
+    Quat(Real q0, Real q1, Real q2, Real q3); // [q0,(q1,q2,q3)]
+    Quat (const Vec3 &axis, Real angle);
+    Quat (const Mat3 &m);
+    
+    Int Elts() const { return (4); };
+    
+    Real        &operator [] (Int i);
+    const Real  &operator [] (Int i) const;
+    
+    // Assignment operators
+
+    Quat        &operator =  (const Quat &a);
+    Quat        &operator += (const Quat &a);
+    Quat        &operator -= (const Quat &a);
+    Quat        &operator *= (const Quat &a);
+    Quat        &operator *= (Real s);
+    Quat        &operator /= (Real s);
+
+    // Arithmetic operators
+
+    Quat        operator + (const Quat &a) const;   // v + a
+    Quat        operator - (const Quat &a) const;   // v - a
+    Quat        operator - () const;                // -v
+    Quat        operator * (const Quat &a) const;   // v * a (vx * ax, ...)
+    Quat        operator * (Real s) const;          // v * s
+    Quat        operator / (Real s) const;          // v / s
+
+
+    Quat        &Normalise();                       // normalise vector
+
+protected:
+    Real elt[4];
+};
+
+inline Quat     operator * (Real s, const Quat &v); // Left mult. by s
+inline Real     dot(const Quat &a, const Quat &b);  // v . a
+inline Real     len(const Quat &v);                 // || v ||
+inline Real     sqrlen(const Quat &v);              // v . v
+inline Quat     norm(const Quat &v);                // v / || v ||
+inline Void     normalise(Quat &v);                 // v = norm(v)
+inline Quat     slerp(const Quat &q1, const Quat &q2, Real t);
+inline Quat     conjugate(const Quat &q);
+
+Mat3     Rot3(const Quat &q);
+Mat4     HRot4(const Quat &q);
+
+            
+//std::ostream &operator << (std::ostream &s, const Quat &v);
+//std::istream &operator >> (std::istream &s, Quat &v);
+
+void printQuat(const Quat &v);
+
+inline Real &Quat::operator [] (Int i)
+{
+    CheckRange(i, 0, 4, "(Quat::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline const Real &Quat::operator [] (Int i) const
+{
+    CheckRange(i, 0, 4, "(Quat::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline Quat::Quat()
+{
+}
+
+inline Quat::Quat(Real q0, Real q1, Real q2, Real q3)
+{
+    elt[0] = q0;
+    elt[1] = q1;
+    elt[2] = q2;
+    elt[3] = q3;
+}
+
+inline Quat::Quat(const Vec3 &axis, Real angle)
+{
+    Vec3 n = norm(axis);
+    Real sinhalf = sin(angle/2);
+    elt[1] = sinhalf*n[0];
+    elt[2] = sinhalf*n[1];
+    elt[3] = sinhalf*n[2];
+
+    elt[0] = cos(angle/2);
+}
+
+
+inline Quat &Quat::operator = (const Quat &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+    elt[3] = v[3];
+
+    return(SELF);
+}
+
+inline Quat &Quat::operator += (const Quat &v)
+{
+    elt[0] += v[0];
+    elt[1] += v[1];
+    elt[2] += v[2];
+    elt[3] += v[3];
+
+    return(SELF);
+}
+
+inline Quat &Quat::operator -= (const Quat &v)
+{
+    elt[0] -= v[0];
+    elt[1] -= v[1];
+    elt[2] -= v[2];
+    elt[3] -= v[3];
+
+    return(SELF);
+}
+
+inline Quat &Quat::operator *= (const Quat &v)
+{
+    Quat tmp(elt[0],elt[1],elt[2],elt[3]);
+    tmp = tmp * v;
+
+    elt[0] = tmp[0];
+    elt[1] = tmp[1];
+    elt[2] = tmp[2];
+    elt[3] = tmp[3];
+    
+    return(SELF);
+}
+
+inline Quat &Quat::operator *= (Real s)
+{
+    elt[0] *= s;
+    elt[1] *= s;
+    elt[2] *= s;
+    elt[3] *= s;
+
+    return(SELF);
+}
+
+inline Quat &Quat::operator /= (Real s)
+{
+    elt[0] /= s;
+    elt[1] /= s;
+    elt[2] /= s;
+    elt[3] /= s;
+
+    return(SELF);
+}
+
+
+inline Quat Quat::operator + (const Quat &a) const
+{
+    Quat result;
+
+    result[0] = elt[0] + a[0];
+    result[1] = elt[1] + a[1];
+    result[2] = elt[2] + a[2];
+    result[3] = elt[3] + a[3];
+
+    return(result);
+}
+
+inline Quat Quat::operator - (const Quat &a) const
+{
+    Quat result;
+
+    result[0] = elt[0] - a[0];
+    result[1] = elt[1] - a[1];
+    result[2] = elt[2] - a[2];
+    result[3] = elt[3] - a[3];
+
+    return(result);
+}
+
+inline Quat Quat::operator - () const
+{
+    Quat result;
+
+    result[0] = -elt[0];
+    result[1] = -elt[1];
+    result[2] = -elt[2];
+    result[3] = -elt[3];
+
+    return(result);
+}
+
+inline Quat Quat::operator * (const Quat &a) const
+{
+    Quat result;
+
+    Vec3 qv(elt[1],elt[2],elt[3]); Real qs = elt[0];
+    Vec3 av(a[1],a[2],a[3]); Real as = a[0];
+
+    Vec3 rv = qs*av + as*qv + cross(qv,av);
+    Real rs = qs*as - dot(qv,av);
+
+    result[1] = rv[0];
+    result[2] = rv[1];
+    result[3] = rv[2];
+    result[0] = rs;
+
+    return(result);
+}
+
+inline Quat Quat::operator * (Real s) const
+{
+    Quat result;
+
+    result[0] = elt[0] * s;
+    result[1] = elt[1] * s;
+    result[2] = elt[2] * s;
+    result[3] = elt[3] * s;
+
+    return(result);
+}
+
+inline Quat Quat::operator / (Real s) const
+{
+    Quat result;
+
+    result[0] = elt[0] / s;
+    result[1] = elt[1] / s;
+    result[2] = elt[2] / s;
+    result[3] = elt[3] / s;
+
+    return(result);
+}
+
+inline Quat operator * (Real s, const Quat &v)
+{
+    return(v * s);
+}
+
+// for convenience. Quat has no dot operation.
+inline Real dot(const Quat &a, const Quat &b)
+{
+    return(a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]);
+}
+
+inline Real len(const Quat &v)
+{
+    return(sqrt(dot(v, v)));
+}
+
+inline Real sqrlen(const Quat &v)
+{
+    return(dot(v, v));
+}
+
+inline Quat norm(const Quat &v)
+{
+    Assert(sqrlen(v) > 0.0, "normalising length-zero vector");
+    return(v / len(v));
+}
+
+inline Void normalise(Quat &v)
+{
+    v /= len(v);
+}
+
+inline Quat slerp (const Quat& q1, const Quat& q2, Real t)
+{
+    Quat result;
+    Quat qq = q1;
+
+    if (dot(qq,q2) < 0)
+        qq = -q1;
+
+    Real phi = acos(dot (qq, q2));
+    Real denom = sin(phi);
+    
+    result = sin(phi*(1-t))/denom * qq + sin(phi*t)/denom * q2;
+
+    return result;
+}
+
+inline Quat conjugate(const Quat &q)
+{
+    return Quat (q[0], -q[1], -q[2], -q[3]);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SVL.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,53 @@
+/*
+    File:           SVL.h
+
+    Function:       Master header for a simple version of the VL library.
+                    The various classes are named Vec2, Mat3, Vec, etc.
+                    Link with -lsvl, or define the symbol VL_DEBUG and
+                    link with -lsvl.dbg for the debugging version.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+ // http://www.cs.cmu.edu/~ajw/doc/svl.html
+#ifndef __SVL__
+#define __SVL__
+
+#define SVL_VERSION "1.5"
+#define SVL_VER_NUM 10500
+
+//#pragma comment (lib, "svl-dbg.lib")
+
+
+
+
+#ifdef VL_DEBUG
+#define VL_CHECKING
+#endif
+
+//#include <iostream>
+//namespace svl {
+#include "Basics.h"
+#include "Constants.h"
+#include "Utils.h"
+
+#include "Vec2.h"
+#include "Vec3.h"
+#include "Vec4.h"
+#include "Vec.h"
+
+#include "Mat2.h"
+#include "Mat3.h"
+#include "Mat4.h"
+#include "Mat.h"
+
+#include "Transform.h"
+
+#include "Quat.h"
+
+//}
+//using namespace svl;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Transform.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,41 @@
+/*
+    File:           Transform.h
+
+    Function:       Provides transformation constructors.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+*/
+
+#ifndef __SVL_TRANSFORM__
+#define __SVL_TRANSFORM__
+
+inline Mat2 Rot2(Real theta)
+            { Mat2 result; result.MakeRot(theta); return(result); }
+inline Mat2 Scale2(const Vec2 &s)
+            { Mat2 result; result.MakeScale(s); return(result); }
+
+inline Mat3 Rot3(const Vec3 &axis, Real theta)
+            { Mat3 result; result.MakeRot(axis, theta); return(result); }
+inline Mat3 Rot3(const Vec4 &q)
+            { Mat3 result; result.MakeRot(q); return(result); }
+inline Mat3 Scale3(const Vec3 &s)
+            { Mat3 result; result.MakeScale(s); return(result); }
+inline Mat3 HRot3(Real theta)
+            { Mat3 result; result.MakeHRot(theta); return(result); }
+inline Mat3 HScale3(const Vec2 &s)
+            { Mat3 result; result.MakeHScale(s); return(result); }
+inline Mat3 HTrans3(const Vec2 &t)
+            { Mat3 result; result.MakeHTrans(t); return(result); }
+
+inline Mat4 HRot4(const Vec3 &axis, Real theta)
+            { Mat4 result; result.MakeHRot(axis, theta); return(result); }
+inline Mat4 HRot4(const Vec4 &q)
+            { Mat4 result; result.MakeHRot(q); return(result); }
+inline Mat4 HScale4(const Vec3 &s)
+            { Mat4 result; result.MakeHScale(s); return(result); }
+inline Mat4 HTrans4(const Vec3 &t)
+            { Mat4 result; result.MakeHTrans(t); return(result); }
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Utils.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,86 @@
+/*
+    File:           Utils.h
+
+    Function:       Various math definitions for VL
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __VL_MATH__
+#define __VL_MATH__
+
+//#include <cstdlib>
+
+// --- Inlines ----------------------------------------------------------------
+
+// additions to arithmetic functions
+
+#ifdef VL_HAS_IEEEFP
+#include <ieeefp.h>
+#define vl_is_finite(X) finite(X)
+#elif defined (__GNUC__) && defined(__USE_MISC)
+#define vl_is_finite(X) finite(X)
+#else
+#define vl_is_finite(X) (1)
+#endif
+
+#ifdef VL_HAS_DRAND
+inline Double vl_rand()
+{ return(drand48()); }
+#else
+#ifndef RAND_MAX
+// we're on something totally sucky, like SunOS
+#define RAND_MAX (Double(1 << 30) * 4.0 - 1.0)
+#endif
+inline Double vl_rand()
+{ return(rand() / (RAND_MAX + 1.0)); }
+#endif
+
+#ifndef __CMATH__
+// GNU's complex.h defines its own abs(double)
+#ifdef VL_HAS_ABSF
+inline Float abs(Float x)
+{ return (fabsf(x)); }
+#endif
+// jmc ......... 7/19
+//inline Double abs(Double x)
+//{ return (fabs(x)); }
+#endif
+#ifdef VL_HAS_ABSF
+inline Float len(Float x)
+{ return (fabsf(x)); }
+#endif
+inline Double len(Double x)
+{ return (fabs(x)); }
+
+inline Float sqrlen(Float r)
+{ return(sqr(r)); }
+inline Double sqrlen(Double r)
+{ return(sqr(r)); }
+
+inline Float mix(Float a, Float b, Float s)
+{ return((1.0f - s) * a + s * b); }
+inline Double mix(Double a, Double b, Double s)
+{ return((1.0 - s) * a + s * b); }
+
+inline Double sign(Double d)
+{
+    if (d < 0)
+        return(-1.0);
+    else
+        return(1.0);
+}
+
+// useful routines
+
+inline Bool IsPowerOfTwo(Int a)
+{ return((a & -a) == a); };
+
+inline Void SetReal(Float &a, Double b)
+{ a = Float(b); }
+inline Void SetReal(Double &a, Double b)
+{ a = b; }
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,548 @@
+/*
+    File:           Vec.cpp
+
+    Function:       Implements Vec.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+
+#include "Vec.h"
+
+//#include <cctype>
+//#include <cstring>
+//#include <cstdarg>
+//#include <iomanip>
+#include "Vec2.h"
+#include "Vec3.h"
+#include "Vec4.h"
+
+// --- Vec Constructors -------------------------------------------------------
+
+
+Vec::Vec(Int n, ZeroOrOne k) : elts(n)
+{
+    Assert(n > 0,"(Vec) illegal vector size");
+
+    data = new Real[n];
+
+    MakeBlock(k);
+}
+
+Vec::Vec(Int n, Axis a) : elts(n)
+{
+    Assert(n > 0,"(Vec) illegal vector size");
+
+    data = new Real[n];
+
+    MakeUnit(a);
+}
+
+Vec::Vec(const Vec &v)
+{
+    Assert(v.data != 0, "(Vec) Can't construct from a null vector");
+
+    elts = v.Elts();
+    data = new Real[elts];
+
+#ifdef VL_USE_MEMCPY
+    memcpy(data, v.Ref(), sizeof(Real) * Elts());
+#else
+    for (Int i = 0; i < Elts(); i++)
+        data[i] = v[i];
+#endif
+}
+
+Vec::Vec(const Vec2 &v) : data(v.Ref()), elts(v.Elts() | VL_REF_FLAG)
+{
+}
+
+Vec::Vec(const Vec3 &v) : data(v.Ref()), elts(v.Elts() | VL_REF_FLAG)
+{
+}
+
+Vec::Vec(const Vec4 &v) : data(v.Ref()), elts(v.Elts() | VL_REF_FLAG)
+{
+}
+
+Vec::Vec(Int n, double elt0, ...) : elts(n)
+{
+    Assert(n > 0,"(Vec) illegal vector size");
+
+    va_list ap;
+    Int     i = 1;
+
+    data = new Real[n];
+    va_start(ap, elt0);
+
+    SetReal(data[0], elt0);
+
+    while (--n)
+        SetReal(data[i++], va_arg(ap, double));
+
+    va_end(ap);
+}
+
+Vec::~Vec()
+{
+    Assert(elts != 0,"(Vec) illegal vector size");
+
+    if (!IsRef())
+        delete[] data;
+}
+
+
+// --- Vec Assignment Operators -----------------------------------------------
+
+
+Vec &Vec::operator = (const Vec &v)
+{
+    if (!IsRef())
+        SetSize(v.Elts());
+    else
+        Assert(Elts() == v.Elts(), "(Vec::=) Vector sizes don't match");
+
+#ifdef VL_USE_MEMCPY
+    memcpy(data, v.data, sizeof(Real) * Elts());
+#else
+    for (Int i = 0; i < Elts(); i++)
+        data[i] = v[i];
+#endif
+
+    return(SELF);
+}
+
+Vec &Vec::operator = (const Vec2 &v)
+{
+    if (!IsRef())
+        SetSize(v.Elts());
+    else
+        Assert(Elts() == v.Elts(), "(Vec::=) Vector sizes don't match");
+
+    data[0] = v[0];
+    data[1] = v[1];
+
+    return(SELF);
+}
+
+Vec &Vec::operator = (const Vec3 &v)
+{
+    if (!IsRef())
+        SetSize(v.Elts());
+    else
+        Assert(Elts() == v.Elts(), "(Vec::=) Vector sizes don't match");
+
+    data[0] = v[0];
+    data[1] = v[1];
+    data[2] = v[2];
+
+    return(SELF);
+}
+
+Vec &Vec::operator = (const Vec4 &v)
+{
+    if (!IsRef())
+        SetSize(v.Elts());
+    else
+        Assert(Elts() == v.Elts(), "(Vec::=) Vector sizes don't match");
+
+    data[0] = v[0];
+    data[1] = v[1];
+    data[2] = v[2];
+    data[3] = v[3];
+
+    return(SELF);
+}
+
+Void Vec::SetSize(Int ni)
+{
+    Assert(ni > 0, "(Vec::SetSize) Illegal vector size");
+    UInt    n = UInt(ni);
+    
+    if (!IsRef())
+    {
+        // Don't reallocate if we already have enough storage
+
+        if (n <= elts)
+        {
+            elts = n;
+            return;
+        }
+
+        // Otherwise, delete old storage
+
+        delete[] data;
+
+        elts = n;
+        data = new Real[elts];
+    }
+    else
+        Assert(false, "(Vec::SetSize) Can't resize a vector reference");
+}
+
+Vec &Vec::MakeZero()
+{
+#ifdef VL_USE_MEMCPY
+    memset(data, 0, sizeof(Real) * Elts());
+#else
+    Int j;
+
+    for (j = 0; j < Elts(); j++)
+        data[j] = vl_zero;
+#endif
+
+    return(SELF);
+}
+
+Vec &Vec::MakeUnit(Int i, Real k)
+{
+    MakeZero();
+    data[i] = k;
+
+    return(SELF);
+}
+
+Vec &Vec::MakeBlock(Real k)
+{
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] = k;
+
+    return(SELF);
+}
+
+
+// --- Vec In-Place operators -------------------------------------------------
+
+
+Vec &Vec::operator += (const Vec &b)
+{
+    Assert(Elts() == b.Elts(), "(Vec::+=) vector sizes don't match");
+
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] += b[i];
+
+    return(SELF);
+}
+
+Vec &Vec::operator -= (const Vec &b)
+{
+    Assert(Elts() == b.Elts(), "(Vec::-=) vector sizes don't match");
+
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] -= b[i];
+
+    return(SELF);
+}
+
+Vec &Vec::operator *= (const Vec &b)
+{
+    Assert(Elts() == b.Elts(), "(Vec::*=) Vec sizes don't match");
+
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] *= b[i];
+
+    return(SELF);
+}
+
+Vec &Vec::operator *= (Real s)
+{
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] *= s;
+
+    return(SELF);
+}
+
+Vec &Vec::operator /= (const Vec &b)
+{
+    Assert(Elts() == b.Elts(), "(Vec::/=) Vec sizes don't match");
+
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] /= b[i];
+
+    return(SELF);
+}
+
+Vec &Vec::operator /= (Real s)
+{
+    Int     i;
+
+    for (i = 0; i < Elts(); i++)
+        data[i] /= s;
+
+    return(SELF);
+}
+
+
+// --- Vec Comparison Operators -----------------------------------------------
+
+
+Bool operator == (const Vec &a, const Vec &b)
+{
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        if (a[i] != b[i])
+            return(0);
+
+    return(1);
+}
+
+Bool operator != (const Vec &a, const Vec &b)
+{
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        if (a[i] != b[i])
+            return(1);
+
+    return(0);
+}
+
+
+// --- Vec Arithmetic Operators -----------------------------------------------
+
+
+Vec operator + (const Vec &a, const Vec &b)
+{
+    Assert(a.Elts() == b.Elts(), "(Vec::+) Vec sizes don't match");
+
+    Vec     result(a.Elts());
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        result[i] = a[i] + b[i];
+
+    return(result);
+}
+
+Vec operator - (const Vec &a, const Vec &b)
+{
+    Assert(a.Elts() == b.Elts(), "(Vec::-) Vec sizes don't match");
+
+    Vec     result(a.Elts());
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        result[i] = a[i] - b[i];
+
+    return(result);
+}
+
+Vec operator - (const Vec &v)
+{
+    Vec     result(v.Elts());
+    Int     i;
+
+    for (i = 0; i < v.Elts(); i++)
+        result[i] = - v[i];
+
+    return(result);
+}
+
+Vec operator * (const Vec &a, const Vec &b)
+{
+    Assert(a.Elts() == b.Elts(), "(Vec::*) Vec sizes don't match");
+
+    Vec     result(a.Elts());
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        result[i] = a[i] * b[i];
+
+    return(result);
+}
+
+Vec operator * (const Vec &v, Real s)
+{
+    Vec     result(v.Elts());
+    Int     i;
+
+    for (i = 0; i < v.Elts(); i++)
+        result[i] = v[i] * s;
+
+    return(result);
+}
+
+Vec operator / (const Vec &a, const Vec &b)
+{
+    Assert(a.Elts() == b.Elts(), "(Vec::/) Vec sizes don't match");
+
+    Vec     result(a.Elts());
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        result[i] = a[i] / b[i];
+
+    return(result);
+}
+
+Vec operator / (const Vec &v, Real s)
+{
+    Vec     result(v.Elts());
+    Int     i;
+
+    for (i = 0; i < v.Elts(); i++)
+        result[i] = v[i] / s;
+
+    return(result);
+}
+
+Real dot(const Vec &a, const Vec &b)
+{
+    Assert(a.Elts() == b.Elts(), "(Vec::dot) Vec sizes don't match");
+
+    Real    sum = vl_zero;
+    Int     i;
+
+    for (i = 0; i < a.Elts(); i++)
+        sum += a[i] * b[i];
+
+    return(sum);
+}
+
+Vec operator * (Real s, const Vec &v)
+{
+    Vec     result(v.Elts());
+    Int     i;
+
+    for (i = 0; i < v.Elts(); i++)
+        result[i] = v[i] * s;
+
+    return(result);
+}
+
+Vec &Vec::Clamp(Real fuzz)
+//  clamps all values of the matrix with a magnitude
+//  smaller than fuzz to zero.
+{
+    Int i;
+
+    for (i = 0; i < Elts(); i++)
+        if (len(SELF[i]) < fuzz)
+            SELF[i] = vl_zero;
+
+    return(SELF);
+}
+
+Vec &Vec::Clamp()
+{
+    return(Clamp(1e-7));
+}
+
+Vec clamped(const Vec &v, Real fuzz)
+//  clamps all values of the matrix with a magnitude
+//  smaller than fuzz to zero.
+{
+    Vec result(v);
+
+    return(result.Clamp(fuzz));
+}
+
+Vec clamped(const Vec &v)
+{
+    return(clamped(v, 1e-7));
+}
+
+
+// --- Vec Input & Output -----------------------------------------------------
+
+
+/*
+ostream &operator << (ostream &s, const Vec &v)
+{
+    Int i, w;
+
+    s << '[';
+
+    if (v.Elts() > 0)
+    {
+        w = s.width();
+        s << v[0];
+
+        for (i = 1; i < v.Elts(); i++)
+            s << ' ' << setw(w) << v[i];
+    }
+
+    s << ']';
+
+    return(s);
+}
+*/
+
+inline Void CopyPartialVec(const Vec &u, Vec &v, Int numElts)
+{
+    for (Int i = 0; i < numElts; i++)
+        v[i] = u[i];
+}
+
+/*
+istream &operator >> (istream &s, Vec &v)
+{
+    Int     size = 0;
+    Vec     inVec(16);
+    Char    c;
+
+    //  Expected format: [a b c d ...]
+
+    while (isspace(s.peek()))           //  chomp white space
+        s.get(c);
+
+    if (s.peek() == '[')
+    {
+        s.get(c);
+
+
+        while (isspace(s.peek()))       //  chomp white space
+            s.get(c);
+
+        while (s.peek() != ']')         //  resize if needed
+        {
+            if (size == inVec.Elts())
+            {
+                Vec     holdVec(inVec);
+
+                inVec.SetSize(size * 2);
+                CopyPartialVec(holdVec, inVec, size);
+            }
+
+            s >> inVec[size++];         //  read an item
+
+            if (!s)
+            {
+                _Warning("Couldn't read vector element");
+                return(s);
+            }
+
+            while (isspace(s.peek()))   //  chomp white space
+                s.get(c);
+        }
+        s.get(c);
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        _Warning("Error: Expected '[' while reading vector");
+        return(s);
+    }
+
+    v.SetSize(size);
+    CopyPartialVec(inVec, v, size);
+
+    return(s);
+}
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,255 @@
+/*
+    File:           Vec.h
+
+    Function:       Defines a generic resizeable vector.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Vec__
+#define __Vec__
+#include "Basics.h"
+#include "Constants.h"
+#include "Utils.h"
+
+class Vec2;
+class Vec3;
+class Vec4;
+
+
+// --- Vec Class --------------------------------------------------------------
+
+class Vec
+{
+public:
+
+    // Constructors
+
+                Vec();                          // Null vector
+    explicit    Vec(Int n);                     // n-element vector
+                Vec(Int n, double elt0, ...);   // e.g. Vec(3, 1.1, 2.0, 3.4)
+                Vec(Int n, Real *data);         // Vector reference
+                Vec(const Vec &v);              // Copy constructor
+                Vec(const Vec2 &v);             // reference to a Vec2
+                Vec(const Vec3 &v);             // reference to a Vec3
+                Vec(const Vec4 &v);             // reference to a Vec4
+                Vec(Int n, ZeroOrOne);          // Zero or all-ones vector
+                Vec(Int n, Axis a);             // Unit vector
+               ~Vec();                          // Destructor
+
+    // Accessor functions
+
+    Int         Elts() const;
+
+    Real        &operator [] (Int i);
+    Real        operator [] (Int i) const;
+
+    Void        SetSize(Int n);                 // Resize the vector
+    Real        *Ref() const;                   // Return pointer to data
+
+    // Assignment operators
+
+    Vec         &operator =  (const Vec &v);    // v = a etc.
+    Vec         &operator =  (ZeroOrOne k);
+    Vec         &operator =  (Axis a);
+    Vec         &operator =  (const Vec2 &v);
+    Vec         &operator =  (const Vec3 &v);
+    Vec         &operator =  (const Vec4 &v);
+
+    // In-Place operators
+
+    Vec         &operator += (const Vec &v);
+    Vec         &operator -= (const Vec &v);
+    Vec         &operator *= (const Vec &v);
+    Vec         &operator *= (Real s);
+    Vec         &operator /= (const Vec &v);
+    Vec         &operator /= (Real s);
+
+    //  Vector initialisers
+
+    Vec         &MakeZero();
+    Vec         &MakeUnit(Int i, Real k = vl_one);
+    Vec         &MakeBlock(Real k = vl_one);
+
+    Vec         &Normalise();                   // Normalise vector
+    Vec         &Clamp(Real fuzz);
+    Vec         &Clamp();
+
+    Bool        IsRef() const { return((elts & VL_REF_FLAG) != 0); };
+
+    // Private...
+
+protected:
+
+    Real        *data;
+    UInt        elts;
+};
+
+
+// --- Vec Comparison Operators -----------------------------------------------
+
+Bool            operator == (const Vec &a, const Vec &b);
+Bool            operator != (const Vec &a, const Vec &b);
+
+
+// --- Vec Arithmetic Operators -----------------------------------------------
+
+Vec             operator + (const Vec &a, const Vec &b);
+Vec             operator - (const Vec &a, const Vec &b);
+Vec             operator - (const Vec &v);
+Vec             operator * (const Vec &a, const Vec &b);
+Vec             operator * (const Vec &v, Real s);
+Vec             operator / (const Vec &a, const Vec &b);
+Vec             operator / (const Vec &v, Real s);
+Vec             operator * (Real s, const Vec &v);
+
+Real            dot(const Vec &a, const Vec &b);// v . a
+inline Real     len(const Vec &v);              // || v ||
+inline Real     sqrlen(const Vec &v);           // v . v
+inline Vec      norm(const Vec &v);             // v / || v ||
+inline Void     normalise(Vec &v);              // v = norm(v)
+
+Vec             clamped(const Vec &v, Real fuzz);
+Vec             clamped(const Vec &v);
+
+
+// --- Vec Input & Output -----------------------------------------------------
+
+//std::ostream         &operator << (std::ostream &s, const Vec &v);
+//std::istream         &operator >> (std::istream &s, Vec &v);
+
+inline void printVec(const Vec &v);
+
+// --- Sub-vector functions ---------------------------------------------------
+
+inline Vec      sub(const Vec &v, Int start, Int length);
+inline Vec      first(const Vec &v, Int length);
+inline Vec      last(const Vec &v, Int length);
+
+
+// --- Vec inlines ------------------------------------------------------------
+
+inline Vec::Vec() : data(0), elts(0)
+{
+}
+
+inline Vec::Vec(Int n) : elts(n)
+{
+    Assert(n > 0,"(Vec) illegal vector size");
+
+    data = new Real[n];
+}
+
+inline Vec::Vec(Int n, Real *data) : data(data), elts(n | VL_REF_FLAG)
+{
+}
+
+inline Int Vec::Elts() const
+{
+    return(elts & VL_REF_MASK);
+}
+
+inline Real &Vec::operator [] (Int i)
+{
+    CheckRange(i, 0, Elts(), "Vec::[i]");
+
+    return(data[i]);
+}
+
+inline Real Vec::operator [] (Int i) const
+{
+    CheckRange(i, 0, Elts(), "Vec::[i]");
+
+    return(data[i]);
+}
+
+inline Real *Vec::Ref() const
+{
+    return(data);
+}
+
+inline Vec &Vec::operator = (ZeroOrOne k)
+{
+    MakeBlock(k);
+
+    return(SELF);
+}
+
+inline Vec &Vec::operator = (Axis a)
+{
+    MakeUnit(a);
+
+    return(SELF);
+}
+
+inline Real len(const Vec &v)
+{
+    return(sqrt(dot(v, v)));
+}
+
+inline Real sqrlen(const Vec &v)
+{
+    return(dot(v, v));
+}
+
+inline Vec norm(const Vec &v)
+{
+    Assert(sqrlen(v) > 0.0, "normalising length-zero vector");
+    return(v / len(v));
+}
+
+inline Void normalise(Vec &v)
+{
+    v /= len(v);
+}
+
+inline Vec sub(const Vec &v, Int start, Int length)
+{
+    Assert(start >= 0 && length > 0 && start + length <= v.Elts(),
+        "(sub(Vec)) illegal subset of vector");
+
+    return(Vec(length, v.Ref() + start));
+}
+
+inline Vec first(const Vec &v, Int length)
+{
+    Assert(length > 0 && length <= v.Elts(),
+        "(first(Vec)) illegal subset of vector");
+
+    return(Vec(length, v.Ref()));
+}
+
+inline Vec last(const Vec &v, Int length)
+{
+    Assert(length > 0 && length <= v.Elts(),
+        "(last(Vec)) illegal subset of vector");
+
+    return(Vec(length, v.Ref() + v.Elts() - length));
+}
+
+inline Vec &Vec::Normalise()
+{
+    Assert(sqrlen(SELF) > 0.0, "normalising length-zero vector");
+    SELF /= len(SELF);
+    return(SELF);
+}
+
+inline void printVec(const Vec &v)
+{    
+    Int i;
+    printf("[");
+    if (v.Elts() > 0)
+    {
+        printf("%10f",v[0]);
+        
+        for (i = 1; i < v.Elts(); i++)
+            printf(" %10f", v[i]);
+    }
+    printf("]");
+}
+
+
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec2.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,66 @@
+/*
+    File:           Vec2.cpp
+
+    Function:       Implements Vec2.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+
+#include "Vec2.h"
+//#include <cctype>
+//#include <iomanip>
+
+
+/*
+ostream &operator << (ostream &s, const Vec2 &v)
+{
+    uint16_t w = s.width();
+
+    return(s << '[' << v[0] << ' ' << setw(w) << v[1] << ']');
+}
+
+istream &operator >> (istream &s, Vec2 &v)
+{
+    Vec2    result;
+    Char    c;
+
+    // Expected format: [1 2]
+
+    while (s >> c && isspace(c))
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1];
+
+        if (!s)
+        {
+            cerr << "Error: Expected number while reading vector\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Error: Expected ']' while reading vector\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Error: Expected '[' while reading vector\n";
+        return(s);
+    }
+
+    v = result;
+    return(s);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec2.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,373 @@
+/*
+    File:           Vec2.h
+
+    Function:       Defines a length-2 vector.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Vec2__
+#define __Vec2__
+#include "Constants.h"
+#include "Basics.h"
+
+// --- Vec2 Class -------------------------------------------------------------
+
+
+class Vec2
+{
+public:
+
+    // Constructors
+
+                Vec2();
+                Vec2(double x, double y);       // (x, y)
+                Vec2(const Vec2 &v);        // Copy constructor
+                Vec2(ZeroOrOne k);          // v[i] = vl_zero
+                Vec2(Axis k);               // v[k] = 1
+
+    // Accessor functions
+
+    double        &operator [] (Int i);
+    const double  &operator [] (Int i) const;
+
+    Int         Elts() const { return(2); };
+    double        *Ref() const;                       // Return ptr to data
+
+    // Assignment operators
+
+    Vec2        &operator =  (const Vec2 &a);
+    Vec2        &operator =  (ZeroOrOne k);
+    Vec2        &operator =  (Axis k);
+
+    Vec2        &operator += (const Vec2 &a);
+    Vec2        &operator -= (const Vec2 &a);
+    Vec2        &operator *= (const Vec2 &a);
+    Vec2        &operator *= (double s);
+    Vec2        &operator /= (const Vec2 &a);
+    Vec2        &operator /= (double s);
+
+    // Comparison operators
+
+    bool        operator == (const Vec2 &a) const;  // v == a?
+    bool        operator != (const Vec2 &a) const;  // v != a?
+
+    // Arithmetic operators
+
+    Vec2        operator + (const Vec2 &a) const;   // v + a
+    Vec2        operator - (const Vec2 &a) const;   // v - a
+    Vec2        operator - () const;                // -v
+    Vec2        operator * (const Vec2 &a) const;   // v * a (vx * ax, ...)
+    Vec2        operator * (double s) const;          // v * s
+    Vec2        operator / (const Vec2 &a) const;   // v / a (vx / ax, ...)
+    Vec2        operator / (double s) const;          // v / s
+
+    // Initialisers
+
+    Vec2        &MakeZero();                        // Zero vector
+    Vec2        &MakeUnit(Int i, double k = vl_one);  // I[i]
+    Vec2        &MakeBlock(double k = vl_one);        // All-k vector
+
+    Vec2        &Normalise();                       // normalise vector
+
+    // Private...
+
+protected:
+
+    double            elt[2];
+};
+
+
+// --- Vec operators ----------------------------------------------------------
+
+inline Vec2     operator * (double s, const Vec2 &v); // s * v
+inline double     dot(const Vec2 &a, const Vec2 &b);  // v . a
+inline double     len(const Vec2 &v);                 // || v ||
+inline double     sqrlen(const Vec2 &v);              // v . v
+inline Vec2     norm(const Vec2 &v);                // v / || v ||
+inline void     normalise(Vec2 &v);                 // v = norm(v)
+inline Vec2     cross(const Vec2 &v);               // cross prod.
+
+//std::ostream &operator << (std::ostream &s, const Vec2 &v);
+//std::istream &operator >> (std::istream &s, Vec2 &v);
+
+inline void printVec2(const Vec2 &v);
+
+
+// --- Inlines ----------------------------------------------------------------
+
+inline double &Vec2::operator [] (Int i)
+{
+    CheckRange(i, 0, 2, "(Vec2::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline const double &Vec2::operator [] (Int i) const
+{
+    CheckRange(i, 0, 2, "(Vec2::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline Vec2::Vec2()
+{
+}
+
+inline Vec2::Vec2(double x, double y)
+{
+    elt[0] = x;
+    elt[1] = y;
+}
+
+inline Vec2::Vec2(const Vec2 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+}
+
+inline double *Vec2::Ref() const
+{
+    return((double *) elt);
+}
+
+inline Vec2 &Vec2::operator = (const Vec2 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator += (const Vec2 &v)
+{
+    elt[0] += v[0];
+    elt[1] += v[1];
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator -= (const Vec2 &v)
+{
+    elt[0] -= v[0];
+    elt[1] -= v[1];
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator *= (const Vec2 &v)
+{
+    elt[0] *= v[0];
+    elt[1] *= v[1];
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator *= (double s)
+{
+    elt[0] *= s;
+    elt[1] *= s;
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator /= (const Vec2 &v)
+{
+    elt[0] /= v[0];
+    elt[1] /= v[1];
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator /= (double s)
+{
+    elt[0] /= s;
+    elt[1] /= s;
+
+    return(SELF);
+}
+
+inline Vec2 Vec2::operator + (const Vec2 &a) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] + a[0];
+    result[1] = elt[1] + a[1];
+
+    return(result);
+}
+
+inline Vec2 Vec2::operator - (const Vec2 &a) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] - a[0];
+    result[1] = elt[1] - a[1];
+
+    return(result);
+}
+
+inline Vec2 Vec2::operator - () const
+{
+    Vec2 result;
+
+    result[0] = -elt[0];
+    result[1] = -elt[1];
+
+    return(result);
+}
+
+inline Vec2 Vec2::operator * (const Vec2 &a) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] * a[0];
+    result[1] = elt[1] * a[1];
+
+    return(result);
+}
+
+inline Vec2 Vec2::operator * (double s) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] * s;
+    result[1] = elt[1] * s;
+
+    return(result);
+}
+
+inline Vec2 operator * (double s, const Vec2 &v)
+{
+    return(v * s);
+}
+
+inline Vec2 Vec2::operator / (const Vec2 &a) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] / a[0];
+    result[1] = elt[1] / a[1];
+
+    return(result);
+}
+
+inline Vec2 Vec2::operator / (double s) const
+{
+    Vec2 result;
+
+    result[0] = elt[0] / s;
+    result[1] = elt[1] / s;
+
+    return(result);
+}
+
+inline double dot(const Vec2 &a, const Vec2 &b)
+{
+    return(a[0] * b[0] + a[1] * b[1]);
+}
+
+inline Vec2 cross(const Vec2 &a)
+{
+    Vec2 result;
+
+    result[0] =  a[1];
+    result[1] = -a[0];
+
+    return(result);
+}
+
+inline double len(const Vec2 &v)
+{
+    return(sqrt(dot(v, v)));
+}
+
+inline double sqrlen(const Vec2 &v)
+{
+    return(dot(v, v));
+}
+
+inline Vec2 norm(const Vec2 &v)
+{
+    Assert(sqrlen(v) > 0.0, "normalising length-zero vector");
+    return(v / len(v));
+}
+
+inline void normalise(Vec2 &v)
+{
+    v /= len(v);
+}
+
+inline Vec2 &Vec2::MakeUnit(Int i, double k)
+{
+    if (i == 0)
+    { elt[0] = k; elt[1] = vl_zero; }
+    else if (i == 1)
+    { elt[0] = vl_zero; elt[1] = k; }
+    else
+        _Error("(Vec2::Unit) illegal unit vector");
+    return(SELF);
+}
+
+inline Vec2 &Vec2::MakeZero()
+{
+    elt[0] = vl_zero; elt[1] = vl_zero;
+    return(SELF);
+}
+
+inline Vec2 &Vec2::MakeBlock(double k)
+{
+    elt[0] = k; elt[1] = k;
+    return(SELF);
+}
+
+inline Vec2 &Vec2::Normalise()
+{
+    Assert(sqrlen(SELF) > 0.0, "normalising length-zero vector");
+    SELF /= len(SELF);
+    return(SELF);
+}
+
+
+inline Vec2::Vec2(ZeroOrOne k)
+{
+    elt[0] = k;
+    elt[1] = k;
+}
+
+inline Vec2::Vec2(Axis k)
+{
+    MakeUnit(k, vl_one);
+}
+
+inline Vec2 &Vec2::operator = (ZeroOrOne k)
+{
+    elt[0] = k; elt[1] = k;
+
+    return(SELF);
+}
+
+inline Vec2 &Vec2::operator = (Axis k)
+{
+    MakeUnit(k, vl_1);
+
+    return(SELF);
+}
+
+inline bool Vec2::operator == (const Vec2 &a) const
+{
+    return(elt[0] == a[0] && elt[1] == a[1]);
+}
+
+inline bool Vec2::operator != (const Vec2 &a) const
+{
+    return(elt[0] != a[0] || elt[1] != a[1]);
+}
+
+inline void printVec2(const Vec2 &v)
+{    
+    printf("[%10f %10f]",v[0],v[1]);
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec3.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,65 @@
+/*
+    File:           Vec3.cpp
+
+    Function:       Implements Vec3.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+
+#include "Vec3.h"
+//#include <cctype>
+//#include <iomanip>
+
+/*
+ostream &operator << (ostream &s, const Vec3 &v)
+{
+    Int w = s.width();
+
+    return(s << '[' << v[0] << ' ' << setw(w) << v[1] << ' ' << setw(w) << v[2] << ']');
+}
+
+istream &operator >> (istream &s, Vec3 &v)
+{
+    Vec3    result;
+    Char    c;
+
+    // Expected format: [1 2 3]
+
+    while (s >> c && isspace(c))
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1] >> result[2];
+
+        if (!s)
+        {
+            cerr << "Error: Expected number while reading vector\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Error: Expected ']' while reading vector\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Error: Expected '[' while reading vector\n";
+        return(s);
+    }
+
+    v = result;
+    return(s);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec3.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,421 @@
+/*
+    File:           Vec3.h
+
+    Function:       Defines a length-3 vector.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Vec3__
+#define __Vec3__
+
+#include "Vec2.h"
+
+
+// --- Vec3 Class -------------------------------------------------------------
+
+class Vec3
+{
+public:
+
+    // Constructors
+
+                Vec3();
+                Vec3(double x, double y, double z);   // [x, y, z]
+                Vec3(const Vec3 &v);            // Copy constructor
+                Vec3(const Vec2 &v, double w);    // Hom. 2D vector
+                Vec3(ZeroOrOne k);
+                Vec3(Axis a);
+
+    // Accessor functions
+
+    Int         Elts() const { return(3); };
+
+    double        &operator [] (Int i);
+    const double  &operator [] (Int i) const;
+
+    double        *Ref() const;                   // Return pointer to data
+
+    // Assignment operators
+
+    Vec3        &operator =  (const Vec3 &a);
+    Vec3        &operator =  (ZeroOrOne k);
+    Vec3        &operator += (const Vec3 &a);
+    Vec3        &operator -= (const Vec3 &a);
+    Vec3        &operator *= (const Vec3 &a);
+    Vec3        &operator *= (double s);
+    Vec3        &operator /= (const Vec3 &a);
+    Vec3        &operator /= (double s);
+
+    // Comparison operators
+
+    Bool        operator == (const Vec3 &a) const;  // v == a?
+    Bool        operator != (const Vec3 &a) const;  // v != a?
+    Bool        operator <  (const Vec3 &a) const; // v <  a?
+    Bool        operator >= (const Vec3 &a) const; // v >= a?
+
+    // Arithmetic operators
+
+    Vec3        operator + (const Vec3 &a) const;   // v + a
+    Vec3        operator - (const Vec3 &a) const;   // v - a
+    Vec3        operator - () const;                // -v
+    Vec3        operator * (const Vec3 &a) const;   // v * a (vx * ax, ...)
+    Vec3        operator * (double s) const;          // v * s
+    Vec3        operator / (const Vec3 &a) const;   // v / a (vx / ax, ...)
+    Vec3        operator / (double s) const;          // v / s
+
+    // Initialisers
+
+    Vec3        &MakeZero();                        // Zero vector
+    Vec3        &MakeUnit(Int i, double k = vl_one);  // I[i]
+    Vec3        &MakeBlock(double k = vl_one);        // All-k vector
+
+    Vec3        &Normalise();                       // normalise vector
+
+    // Private...
+
+protected:
+
+    double elt[3];
+};
+
+
+// --- Vec operators ----------------------------------------------------------
+
+inline Vec3     operator * (double s, const Vec3 &v); // s * v
+inline double     dot(const Vec3 &a, const Vec3 &b);  // v . a
+inline double     len(const Vec3 &v);                 // || v ||
+inline double     sqrlen(const Vec3 &v);              // v . v
+inline Vec3     norm(const Vec3 &v);                // v / || v ||
+inline Void     normalise(Vec3 &v);                 // v = norm(v)
+inline Vec3     cross(const Vec3 &a, const Vec3 &b);// a x b
+inline Vec2     proj(const Vec3 &v);                // hom. projection
+
+//std::ostream &operator << (std::ostream &s, const Vec3 &v);
+//std::istream &operator >> (std::istream &s, Vec3 &v);
+
+inline void printVec3(const Vec3 &v);
+
+
+// --- Inlines ----------------------------------------------------------------
+
+inline double &Vec3::operator [] (Int i)
+{
+    CheckRange(i, 0, 3, "(Vec3::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline const double &Vec3::operator [] (Int i) const
+{
+    CheckRange(i, 0, 3, "(Vec3::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline Vec3::Vec3()
+{
+}
+
+inline Vec3::Vec3(double x, double y, double z)
+{
+    elt[0] = x;
+    elt[1] = y;
+    elt[2] = z;
+}
+
+inline Vec3::Vec3(const Vec3 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+}
+
+inline Vec3::Vec3(const Vec2 &v, double w)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = w;
+}
+
+inline double *Vec3::Ref() const
+{
+    return((double *) elt);
+}
+
+inline Vec3 &Vec3::operator = (const Vec3 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator += (const Vec3 &v)
+{
+    elt[0] += v[0];
+    elt[1] += v[1];
+    elt[2] += v[2];
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator -= (const Vec3 &v)
+{
+    elt[0] -= v[0];
+    elt[1] -= v[1];
+    elt[2] -= v[2];
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator *= (const Vec3 &a)
+{
+    elt[0] *= a[0];
+    elt[1] *= a[1];
+    elt[2] *= a[2];
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator *= (double s)
+{
+    elt[0] *= s;
+    elt[1] *= s;
+    elt[2] *= s;
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator /= (const Vec3 &a)
+{
+    elt[0] /= a[0];
+    elt[1] /= a[1];
+    elt[2] /= a[2];
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::operator /= (double s)
+{
+    elt[0] /= s;
+    elt[1] /= s;
+    elt[2] /= s;
+
+    return(SELF);
+}
+
+inline Vec3 Vec3::operator + (const Vec3 &a) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] + a[0];
+    result[1] = elt[1] + a[1];
+    result[2] = elt[2] + a[2];
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator - (const Vec3 &a) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] - a[0];
+    result[1] = elt[1] - a[1];
+    result[2] = elt[2] - a[2];
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator - () const
+{
+    Vec3 result;
+
+    result[0] = -elt[0];
+    result[1] = -elt[1];
+    result[2] = -elt[2];
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator * (const Vec3 &a) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] * a[0];
+    result[1] = elt[1] * a[1];
+    result[2] = elt[2] * a[2];
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator * (double s) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] * s;
+    result[1] = elt[1] * s;
+    result[2] = elt[2] * s;
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator / (const Vec3 &a) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] / a[0];
+    result[1] = elt[1] / a[1];
+    result[2] = elt[2] / a[2];
+
+    return(result);
+}
+
+inline Vec3 Vec3::operator / (double s) const
+{
+    Vec3 result;
+
+    result[0] = elt[0] / s;
+    result[1] = elt[1] / s;
+    result[2] = elt[2] / s;
+
+    return(result);
+}
+
+inline Vec3 operator * (double s, const Vec3 &v)
+{
+    return(v * s);
+}
+
+inline Vec3 &Vec3::MakeUnit(Int n, double k)
+{
+    if (n == 0)
+    { elt[0] = k; elt[1] = vl_zero; elt[2] = vl_zero; }
+    else if (n == 1)
+    { elt[0] = vl_zero; elt[1] = k; elt[2] = vl_zero; }
+    else if (n == 2)
+    { elt[0] = vl_zero; elt[1] = vl_zero; elt[2] = k; }
+    else
+        _Error("(Vec3::Unit) illegal unit vector");
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::MakeZero()
+{
+    elt[0] = vl_zero; elt[1] = vl_zero; elt[2] = vl_zero;
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::MakeBlock(double k)
+{
+    elt[0] = k; elt[1] = k; elt[2] = k;
+
+    return(SELF);
+}
+
+inline Vec3 &Vec3::Normalise()
+{
+    Assert(sqrlen(SELF) > 0.0, "normalising length-zero vector");
+    SELF /= len(SELF);
+
+    return(SELF);
+}
+
+
+inline Vec3::Vec3(ZeroOrOne k)
+{
+    elt[0] = k; elt[1] = k; elt[2] = k;
+}
+
+inline Vec3 &Vec3::operator = (ZeroOrOne k)
+{
+    elt[0] = k; elt[1] = k; elt[2] = k;
+
+    return(SELF);
+}
+
+inline Vec3::Vec3(Axis a)
+{
+    MakeUnit(a, vl_one);
+}
+
+
+inline Bool Vec3::operator == (const Vec3 &a) const
+{
+    return(elt[0] == a[0] && elt[1] == a[1] && elt[2] == a[2]);
+}
+
+inline Bool Vec3::operator != (const Vec3 &a) const
+{
+    return(elt[0] != a[0] || elt[1] != a[1] || elt[2] != a[2]);
+}
+
+inline Bool Vec3::operator < (const Vec3 &a) const
+{
+    return(elt[0] < a[0] && elt[1] < a[1] && elt[2] < a[2]);
+}
+
+inline Bool Vec3::operator >= (const Vec3 &a) const
+{
+    return(elt[0] >= a[0] && elt[1] >= a[1] && elt[2] >= a[2]);
+}
+
+
+inline double dot(const Vec3 &a, const Vec3 &b)
+{
+    return(a[0] * b[0] + a[1] * b[1] + a[2] * b[2]);
+}
+
+inline double len(const Vec3 &v)
+{
+    return(sqrt(dot(v, v)));
+}
+
+inline double sqrlen(const Vec3 &v)
+{
+    return(dot(v, v));
+}
+
+inline Vec3 norm(const Vec3 &v)
+{
+    Assert(sqrlen(v) > 0.0, "normalising length-zero vector");
+    return(v / len(v));
+}
+
+inline Void normalise(Vec3 &v)
+{
+    v /= len(v);
+}
+
+inline Vec3 cross(const Vec3 &a, const Vec3 &b)
+{
+    Vec3 result;
+
+    result[0] = a[1] * b[2] - a[2] * b[1];
+    result[1] = a[2] * b[0] - a[0] * b[2];
+    result[2] = a[0] * b[1] - a[1] * b[0];
+
+    return(result);
+}
+
+inline Vec2 proj(const Vec3 &v)
+{
+    Vec2 result;
+
+    Assert(v[2] != 0, "(Vec3/proj) last elt. is zero");
+
+    result[0] = v[0] / v[2];
+    result[1] = v[1] / v[2];
+
+    return(result);
+}
+
+inline void printVec3(const Vec3 &v)
+{    
+    printf("[%10f %10f %10f]",v[0],v[1],v[2]);
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec4.cpp	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,124 @@
+/*
+    File:           Vec4.cpp
+
+    Function:       Implements Vec4.h
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+
+*/
+
+
+#include "Vec4.h"
+//#include <cctype>
+//#include <iomanip>
+
+
+Vec4 &Vec4::MakeUnit(Int n, Real k)
+{
+    if (n == 0)
+    { elt[0] = k; elt[1] = vl_zero; elt[2] = vl_zero; elt[3] = vl_zero; }
+    else if (n == 1)
+    { elt[0] = vl_zero; elt[1] = k; elt[2] = vl_zero; elt[3] = vl_zero; }
+    else if (n == 2)
+    { elt[0] = vl_zero; elt[1] = vl_zero; elt[2] = k; elt[3] = vl_zero; }
+    else if (n == 3)
+    { elt[0] = vl_zero; elt[1] = vl_zero; elt[2] = vl_zero; elt[3] = k; }
+    else
+        _Error("(Vec4::MakeUnit) illegal unit vector");
+
+    return(SELF);
+}
+
+bool Vec4::operator == (const Vec4 &a) const
+{
+    return(elt[0] == a[0] && elt[1] == a[1] && elt[2] == a[2] && elt[3] == a[3]);
+}
+
+bool Vec4::operator != (const Vec4 &a) const
+{
+    return(elt[0] != a[0] || elt[1] != a[1] || elt[2] != a[2] || elt[3] != a[3]);
+}
+
+Vec4 cross(const Vec4 &a, const Vec4 &b, const Vec4 &c)
+{
+    Vec4 result;
+    // XXX can this be improved? Look at assembly.
+#define ROW(i)       a[i], b[i], c[i]
+#define DET(i,j,k)   dot(Vec3(ROW(i)), cross(Vec3(ROW(j)), Vec3(ROW(k))))
+
+    result[0] =  DET(1,2,3);
+    result[1] = -DET(0,2,3);
+    result[2] =  DET(0,1,3);
+    result[3] = -DET(0,1,2);
+
+    return(result);
+
+#undef ROW
+#undef DET
+}
+
+Vec3 proj(const Vec4 &v)
+{
+    Vec3 result;
+
+    Assert(v[3] != 0, "(Vec4/proj) last elt. is zero");
+
+    result[0] = v[0] / v[3];
+    result[1] = v[1] / v[3];
+    result[2] = v[2] / v[3];
+
+    return(result);
+}
+
+/*
+ostream &operator << (ostream &s, const Vec4 &v)
+{
+    Int w = s.width();
+
+    return(s << '[' << v[0] << ' ' << setw(w) << v[1] << ' '
+        << setw(w) << v[2] << ' ' << setw(w) << v[3] << ']');
+}
+
+istream &operator >> (istream &s, Vec4 &v)
+{
+    Vec4    result;
+    Char    c;
+
+    // Expected format: [1 2 3 4]
+
+    while (s >> c && isspace(c))
+        ;
+
+    if (c == '[')
+    {
+        s >> result[0] >> result[1] >> result[2] >> result[3];
+
+        if (!s)
+        {
+            cerr << "Error: Expected number while reading vector\n";
+            return(s);
+        }
+
+        while (s >> c && isspace(c))
+            ;
+
+        if (c != ']')
+        {
+            s.clear(ios::failbit);
+            cerr << "Error: Expected ']' while reading vector\n";
+            return(s);
+        }
+    }
+    else
+    {
+        s.clear(ios::failbit);
+        cerr << "Error: Expected '[' while reading vector\n";
+        return(s);
+    }
+
+    v = result;
+    return(s);
+}
+*/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Vec4.h	Mon Jan 04 15:19:10 2016 +0000
@@ -0,0 +1,386 @@
+/*
+    File:           Vec4.h
+
+    Function:       Defines a length-4 vector.
+
+    Author(s):      Andrew Willmott
+
+    Copyright:      (c) 1995-2001, Andrew Willmott
+ */
+
+#ifndef __Vec4__
+#define __Vec4__
+
+#include "Vec3.h"
+
+
+// --- Vec4 Class -------------------------------------------------------------
+
+class Vec4
+{
+public:
+
+    // Constructors
+
+                Vec4();
+                Vec4(Real x, Real y, Real z, Real w);   // [x, y, z, w]
+                Vec4(const Vec4 &v);                    // Copy constructor
+                Vec4(const Vec3 &v, Real w);            // Hom. 3D vector
+                Vec4(ZeroOrOne k);
+                Vec4(Axis k);
+
+    // Accessor functions
+
+    Int         Elts() const { return(4); };
+
+    Real        &operator [] (Int i);
+    const Real  &operator [] (Int i) const;
+
+    Real        *Ref() const;                   // Return pointer to data
+
+    // Assignment operators
+
+    Vec4        &operator =  (const Vec4 &a);
+    Vec4        &operator =  (ZeroOrOne k);
+    Vec4        &operator =  (Axis k);
+    Vec4        &operator += (const Vec4 &a);
+    Vec4        &operator -= (const Vec4 &a);
+    Vec4        &operator *= (const Vec4 &a);
+    Vec4        &operator *= (Real s);
+    Vec4        &operator /= (const Vec4 &a);
+    Vec4        &operator /= (Real s);
+
+    // Comparison operators
+
+    Bool        operator == (const Vec4 &a) const;  // v == a ?
+    Bool        operator != (const Vec4 &a) const;  // v != a ?
+
+    // Arithmetic operators
+
+    Vec4        operator + (const Vec4 &a) const;   // v + a
+    Vec4        operator - (const Vec4 &a) const;   // v - a
+    Vec4        operator - () const;                // -v
+    Vec4        operator * (const Vec4 &a) const;   // v * a (vx * ax, ...)
+    Vec4        operator * (Real s) const;          // v * s
+    Vec4        operator / (const Vec4 &a) const;   // v / a (vx / ax, ...)
+    Vec4        operator / (Real s) const;          // v / s
+
+
+    // Initialisers
+
+    Vec4        &MakeZero();                        // Zero vector
+    Vec4        &MakeUnit(Int i, Real k = vl_one);  // kI[i]
+    Vec4        &MakeBlock(Real k = vl_one);        // All-k vector
+
+    Vec4        &Normalise();                       // normalise vector
+
+    // Private...
+
+protected:
+
+    Real        elt[4];
+};
+
+
+// --- Vec operators ----------------------------------------------------------
+
+inline Vec4     operator * (Real s, const Vec4 &v); // Left mult. by s
+inline Real     dot(const Vec4 &a, const Vec4 &b);  // v . a
+inline Real     len(const Vec4 &v);                 // || v ||
+inline Real     sqrlen(const Vec4 &v);              // v . v
+inline Vec4     norm(const Vec4 &v);                // v / || v ||
+inline Void     normalise(Vec4 &v);                 // v = norm(v)
+Vec4            cross(const Vec4 &a, const Vec4 &b, const Vec4 &c);
+                                                    // 4D cross prod.
+Vec3            proj(const Vec4 &v);                // hom. projection
+
+//std::ostream &operator << (std::ostream &s, const Vec4 &v);
+//std::istream &operator >> (std::istream &s, Vec4 &v);
+
+inline void printVec4(const Vec4 &v);
+
+
+// --- Inlines ----------------------------------------------------------------
+
+inline Real &Vec4::operator [] (Int i)
+{
+    CheckRange(i, 0, 4, "(Vec4::[i]) index out of range");
+    return(elt[i]);
+}
+
+inline const Real &Vec4::operator [] (Int i) const
+{
+    CheckRange(i, 0, 4, "(Vec4::[i]) index out of range");
+    return(elt[i]);
+}
+
+
+inline Vec4::Vec4()
+{
+}
+
+inline Vec4::Vec4(Real x, Real y, Real z, Real w)
+{
+    elt[0] = x;
+    elt[1] = y;
+    elt[2] = z;
+    elt[3] = w;
+}
+
+inline Vec4::Vec4(const Vec4 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+    elt[3] = v[3];
+}
+
+inline Vec4::Vec4(const Vec3 &v, Real w)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+    elt[3] = w;
+}
+
+inline Real *Vec4::Ref() const
+{
+    return((Real *) elt);
+}
+
+inline Vec4 &Vec4::operator = (const Vec4 &v)
+{
+    elt[0] = v[0];
+    elt[1] = v[1];
+    elt[2] = v[2];
+    elt[3] = v[3];
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator += (const Vec4 &v)
+{
+    elt[0] += v[0];
+    elt[1] += v[1];
+    elt[2] += v[2];
+    elt[3] += v[3];
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator -= (const Vec4 &v)
+{
+    elt[0] -= v[0];
+    elt[1] -= v[1];
+    elt[2] -= v[2];
+    elt[3] -= v[3];
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator *= (const Vec4 &v)
+{
+    elt[0] *= v[0];
+    elt[1] *= v[1];
+    elt[2] *= v[2];
+    elt[3] *= v[3];
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator *= (Real s)
+{
+    elt[0] *= s;
+    elt[1] *= s;
+    elt[2] *= s;
+    elt[3] *= s;
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator /= (const Vec4 &v)
+{
+    elt[0] /= v[0];
+    elt[1] /= v[1];
+    elt[2] /= v[2];
+    elt[3] /= v[3];
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator /= (Real s)
+{
+    elt[0] /= s;
+    elt[1] /= s;
+    elt[2] /= s;
+    elt[3] /= s;
+
+    return(SELF);
+}
+
+
+inline Vec4 Vec4::operator + (const Vec4 &a) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] + a[0];
+    result[1] = elt[1] + a[1];
+    result[2] = elt[2] + a[2];
+    result[3] = elt[3] + a[3];
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator - (const Vec4 &a) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] - a[0];
+    result[1] = elt[1] - a[1];
+    result[2] = elt[2] - a[2];
+    result[3] = elt[3] - a[3];
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator - () const
+{
+    Vec4 result;
+
+    result[0] = -elt[0];
+    result[1] = -elt[1];
+    result[2] = -elt[2];
+    result[3] = -elt[3];
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator * (const Vec4 &a) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] * a[0];
+    result[1] = elt[1] * a[1];
+    result[2] = elt[2] * a[2];
+    result[3] = elt[3] * a[3];
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator * (Real s) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] * s;
+    result[1] = elt[1] * s;
+    result[2] = elt[2] * s;
+    result[3] = elt[3] * s;
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator / (const Vec4 &a) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] / a[0];
+    result[1] = elt[1] / a[1];
+    result[2] = elt[2] / a[2];
+    result[3] = elt[3] / a[3];
+
+    return(result);
+}
+
+inline Vec4 Vec4::operator / (Real s) const
+{
+    Vec4 result;
+
+    result[0] = elt[0] / s;
+    result[1] = elt[1] / s;
+    result[2] = elt[2] / s;
+    result[3] = elt[3] / s;
+
+    return(result);
+}
+
+inline Vec4 operator * (Real s, const Vec4 &v)
+{
+    return(v * s);
+}
+
+inline Vec4 &Vec4::MakeZero()
+{
+    elt[0] = vl_zero; elt[1] = vl_zero; elt[2] = vl_zero; elt[3] = vl_zero;
+    return(SELF);
+}
+
+inline Vec4 &Vec4::MakeBlock(Real k)
+{
+    elt[0] = k; elt[1] = k; elt[2] = k; elt[3] = k;
+    return(SELF);
+}
+
+inline Vec4 &Vec4::Normalise()
+{
+    Assert(sqrlen(SELF) > 0.0, "normalising length-zero vector");
+    SELF /= len(SELF);
+    return(SELF);
+}
+
+inline Vec4::Vec4(ZeroOrOne k)
+{
+    MakeBlock(k);
+}
+
+inline Vec4::Vec4(Axis k)
+{
+    MakeUnit(k, vl_1);
+}
+
+inline Vec4 &Vec4::operator = (ZeroOrOne k)
+{
+    MakeBlock(k);
+
+    return(SELF);
+}
+
+inline Vec4 &Vec4::operator = (Axis k)
+{
+    MakeUnit(k, vl_1);
+
+    return(SELF);
+}
+
+
+inline Real dot(const Vec4 &a, const Vec4 &b)
+{
+    return(a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]);
+}
+
+inline Real len(const Vec4 &v)
+{
+    return(sqrt(dot(v, v)));
+}
+
+inline Real sqrlen(const Vec4 &v)
+{
+    return(dot(v, v));
+}
+
+inline Vec4 norm(const Vec4 &v)
+{
+    Assert(sqrlen(v) > 0.0, "normalising length-zero vector");
+    return(v / len(v));
+}
+
+inline Void normalise(Vec4 &v)
+{
+    v /= len(v);
+}
+
+inline void printVec4(const Vec4 &v)
+{    
+    printf("[%10f %10f %10f %10f]",v[0],v[1],v[2],v[3]);
+}
+
+#endif