vector and matrix classes for graphics use

- this implements vec2, vec3, vec4, which are float vectors
of size 2, 3 and 4 respectively.

the code allows easy instantiation of vectors of a different
type via the tvec{2|3|4}<T> template classes.

- this also implements mat4 which is a float 4x4 matrix. the
tmat44<T> template class allows easy instantiation of a
4x4 matrix of a different value_type.

The vector types have some minimal support for the
glsl style swizzled access; for instance:

  vec4 u;
  vec3 v = u.xyz;

only .x, .xy, .xyz and their .stpq / .rgba equivalent are
supported.

most operators are supported on both vector and matrices:
arithmetic, unary, compound assignment and comparison
(bit-wise operators NOT supported).

- operations available on vectors include:
dot, length, distance, normalize and cross

- operations available on matrices include:
transpose, inverse, trace

- and a few utilities to create matrices:
ortho, frustum, lookAt

Change-Id: I64add89ae90fa78d3f2f59985b63495575378635
diff --git a/include/ui/TMatHelpers.h b/include/ui/TMatHelpers.h
new file mode 100644
index 0000000..b778af0
--- /dev/null
+++ b/include/ui/TMatHelpers.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TMAT_IMPLEMENTATION
+#error "Don't include TMatHelpers.h directly. use ui/mat*.h instead"
+#else
+#undef TMAT_IMPLEMENTATION
+#endif
+
+
+#ifndef UI_TMAT_HELPERS_H
+#define UI_TMAT_HELPERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <utils/Debug.h>
+#include <utils/String8.h>
+
+#define PURE __attribute__((pure))
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+/*
+ * No user serviceable parts here.
+ *
+ * Don't use this file directly, instead include ui/mat*.h
+ */
+
+
+/*
+ * Matrix utilities
+ */
+
+namespace matrix {
+
+inline int     PURE transpose(int v)    { return v; }
+inline float   PURE transpose(float v)  { return v; }
+inline double  PURE transpose(double v) { return v; }
+
+inline int     PURE trace(int v)    { return v; }
+inline float   PURE trace(float v)  { return v; }
+inline double  PURE trace(double v) { return v; }
+
+template<typename MATRIX>
+MATRIX PURE inverse(const MATRIX& src) {
+
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::COL_SIZE == MATRIX::ROW_SIZE );
+
+    typename MATRIX::value_type t;
+    const size_t N = MATRIX::col_size();
+    size_t swap;
+    MATRIX tmp(src);
+    MATRIX inverse(1);
+
+    for (size_t i=0 ; i<N ; i++) {
+        // look for largest element in column
+        swap = i;
+        for (size_t j=i+1 ; j<N ; j++) {
+            if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
+                swap = j;
+            }
+        }
+
+        if (swap != i) {
+            /* swap rows. */
+            for (size_t k=0 ; k<N ; k++) {
+                t = tmp[i][k];
+                tmp[i][k] = tmp[swap][k];
+                tmp[swap][k] = t;
+
+                t = inverse[i][k];
+                inverse[i][k] = inverse[swap][k];
+                inverse[swap][k] = t;
+            }
+        }
+
+        t = 1 / tmp[i][i];
+        for (size_t k=0 ; k<N ; k++) {
+            tmp[i][k] *= t;
+            inverse[i][k] *= t;
+        }
+        for (size_t j=0 ; j<N ; j++) {
+            if (j != i) {
+                t = tmp[j][i];
+                for (size_t k=0 ; k<N ; k++) {
+                    tmp[j][k] -= tmp[i][k] * t;
+                    inverse[j][k] -= inverse[i][k] * t;
+                }
+            }
+        }
+    }
+    return inverse;
+}
+
+template<typename MATRIX_R, typename MATRIX_A, typename MATRIX_B>
+MATRIX_R PURE multiply(const MATRIX_A& lhs, const MATRIX_B& rhs) {
+    // pre-requisite:
+    //  lhs : D columns, R rows
+    //  rhs : C columns, D rows
+    //  res : C columns, R rows
+
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_A::ROW_SIZE == MATRIX_B::COL_SIZE );
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::ROW_SIZE == MATRIX_B::ROW_SIZE );
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX_R::COL_SIZE == MATRIX_A::COL_SIZE );
+
+    MATRIX_R res(MATRIX_R::NO_INIT);
+    for (size_t r=0 ; r<MATRIX_R::row_size() ; r++) {
+        res[r] = lhs * rhs[r];
+    }
+    return res;
+}
+
+// transpose. this handles matrices of matrices
+template <typename MATRIX>
+MATRIX PURE transpose(const MATRIX& m) {
+    // for now we only handle square matrix transpose
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
+    MATRIX result(MATRIX::NO_INIT);
+    for (size_t r=0 ; r<MATRIX::row_size() ; r++)
+        for (size_t c=0 ; c<MATRIX::col_size() ; c++)
+            result[c][r] = transpose(m[r][c]);
+    return result;
+}
+
+// trace. this handles matrices of matrices
+template <typename MATRIX>
+typename MATRIX::value_type PURE trace(const MATRIX& m) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
+    typename MATRIX::value_type result(0);
+    for (size_t r=0 ; r<MATRIX::row_size() ; r++)
+        result += trace(m[r][r]);
+    return result;
+}
+
+// trace. this handles matrices of matrices
+template <typename MATRIX>
+typename MATRIX::col_type PURE diag(const MATRIX& m) {
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE( MATRIX::ROW_SIZE == MATRIX::COL_SIZE );
+    typename MATRIX::col_type result(MATRIX::col_type::NO_INIT);
+    for (size_t r=0 ; r<MATRIX::row_size() ; r++)
+        result[r] = m[r][r];
+    return result;
+}
+
+template <typename MATRIX>
+String8 asString(const MATRIX& m) {
+    String8 s;
+    for (size_t c=0 ; c<MATRIX::col_size() ; c++) {
+        s.append("|  ");
+        for (size_t r=0 ; r<MATRIX::row_size() ; r++) {
+            s.appendFormat("%7.2f  ", m[r][c]);
+        }
+        s.append("|\n");
+    }
+    return s;
+}
+
+}; // namespace matrix
+
+// -------------------------------------------------------------------------------------
+}; // namespace android
+
+#undef PURE
+
+#endif /* UI_TMAT_HELPERS_H */
diff --git a/include/ui/TVecHelpers.h b/include/ui/TVecHelpers.h
new file mode 100644
index 0000000..081c69c
--- /dev/null
+++ b/include/ui/TVecHelpers.h
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TVEC_IMPLEMENTATION
+#error "Don't include TVecHelpers.h directly. use ui/vec*.h instead"
+#else
+#undef TVEC_IMPLEMENTATION
+#endif
+
+
+#ifndef UI_TVEC_HELPERS_H
+#define UI_TVEC_HELPERS_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#define PURE __attribute__((pure))
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+/*
+ * No user serviceable parts here.
+ *
+ * Don't use this file directly, instead include ui/vec{2|3|4}.h
+ */
+
+/*
+ * This class casts itself into anything and assign itself from anything!
+ * Use with caution!
+ */
+template <typename TYPE>
+struct Impersonator {
+    Impersonator& operator = (const TYPE& rhs) {
+        reinterpret_cast<TYPE&>(*this) = rhs;
+        return *this;
+    }
+    operator TYPE& () {
+        return reinterpret_cast<TYPE&>(*this);
+    }
+    operator TYPE const& () const {
+        return reinterpret_cast<TYPE const&>(*this);
+    }
+};
+
+/*
+ * TVecArithmeticOperators implements basic arithmetic and basic compound assignments
+ * operators on a vector of type BASE<T>.
+ *
+ * BASE only needs to implement operator[] and size().
+ * By simply inheriting from TVecArithmeticOperators<BASE, T> BASE will automatically
+ * get all the functionality here.
+ */
+
+template <template<typename T> class BASE, typename T>
+class TVecArithmeticOperators {
+public:
+    /* compound assignment from a another vector of the same size but different
+     * element type.
+     */
+    template <typename OTHER>
+    BASE<T>& operator += (const BASE<OTHER>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] += v[i];
+        }
+        return rhs;
+    }
+    template <typename OTHER>
+    BASE<T>& operator -= (const BASE<OTHER>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] -= v[i];
+        }
+        return rhs;
+    }
+    template <typename OTHER>
+    BASE<T>& operator *= (const BASE<OTHER>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] *= v[i];
+        }
+        return rhs;
+    }
+    template <typename OTHER>
+    BASE<T>& operator /= (const BASE<OTHER>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] /= v[i];
+        }
+        return rhs;
+    }
+
+    /* compound assignment from a another vector of the same type.
+     * These operators can be used for implicit conversion and  handle operations
+     * like "vector *= scalar" by letting the compiler implicitly convert a scalar
+     * to a vector (assuming the BASE<T> allows it).
+     */
+    BASE<T>& operator += (const BASE<T>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] += v[i];
+        }
+        return rhs;
+    }
+    BASE<T>& operator -= (const BASE<T>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] -= v[i];
+        }
+        return rhs;
+    }
+    BASE<T>& operator *= (const BASE<T>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] *= v[i];
+        }
+        return rhs;
+    }
+    BASE<T>& operator /= (const BASE<T>& v) {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            rhs[i] /= v[i];
+        }
+        return rhs;
+    }
+
+    /*
+     * NOTE: the functions below ARE NOT member methods. They are friend functions
+     * with they definition inlined with their declaration. This makes these
+     * template functions available to the compiler when (and only when) this class
+     * is instantiated, at which point they're only templated on the 2nd parameter
+     * (the first one, BASE<T> being known).
+     */
+
+    /* The operators below handle operation between vectors of the same side
+     * but of a different element type.
+     */
+    template<typename RT>
+    friend inline
+    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<RT>& rv) {
+        return BASE<T>(lv) += rv;
+    }
+    template<typename RT>
+    friend inline
+    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<RT>& rv) {
+        return BASE<T>(lv) -= rv;
+    }
+    template<typename RT>
+    friend inline
+    BASE<T> PURE operator *(const BASE<T>& lv, const BASE<RT>& rv) {
+        return BASE<T>(lv) *= rv;
+    }
+    template<typename RT>
+    friend inline
+    BASE<T> PURE operator /(const BASE<T>& lv, const BASE<RT>& rv) {
+        return BASE<T>(lv) /= rv;
+    }
+
+    /* The operators below (which are not templates once this class is instanced,
+     * i.e.: BASE<T> is known) can be used for implicit conversion on both sides.
+     * These handle operations like "vector * scalar" and "scalar * vector" by
+     * letting the compiler implicitly convert a scalar to a vector (assuming
+     * the BASE<T> allows it).
+     */
+    friend inline
+    BASE<T> PURE operator +(const BASE<T>& lv, const BASE<T>& rv) {
+        return BASE<T>(lv) += rv;
+    }
+    friend inline
+    BASE<T> PURE operator -(const BASE<T>& lv, const BASE<T>& rv) {
+        return BASE<T>(lv) -= rv;
+    }
+    friend inline
+    BASE<T> PURE operator *(const BASE<T>& lv, const BASE<T>& rv) {
+        return BASE<T>(lv) *= rv;
+    }
+    friend inline
+    BASE<T> PURE operator /(const BASE<T>& lv, const BASE<T>& rv) {
+        return BASE<T>(lv) /= rv;
+    }
+};
+
+/*
+ * TVecUnaryOperators implements unary operators on a vector of type BASE<T>.
+ *
+ * BASE only needs to implement operator[] and size().
+ * By simply inheriting from TVecUnaryOperators<BASE, T> BASE will automatically
+ * get all the functionality here.
+ *
+ * These operators are implemented as friend functions of TVecUnaryOperators<BASE, T>
+ */
+template <template<typename T> class BASE, typename T>
+class TVecUnaryOperators {
+public:
+    BASE<T>& operator ++ () {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            ++rhs[i];
+        }
+        return rhs;
+    }
+    BASE<T>& operator -- () {
+        BASE<T>& rhs = static_cast<BASE<T>&>(*this);
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            --rhs[i];
+        }
+        return rhs;
+    }
+    BASE<T> operator - () const {
+        BASE<T> r(BASE<T>::NO_INIT);
+        BASE<T> const& rv(static_cast<BASE<T> const&>(*this));
+        for (size_t i=0 ; i<BASE<T>::size() ; i++) {
+            r[i] = -rv[i];
+        }
+        return r;
+    }
+};
+
+
+/*
+ * TVecComparisonOperators implements relational/comparison operators
+ * on a vector of type BASE<T>.
+ *
+ * BASE only needs to implement operator[] and size().
+ * By simply inheriting from TVecComparisonOperators<BASE, T> BASE will automatically
+ * get all the functionality here.
+ */
+template <template<typename T> class BASE, typename T>
+class TVecComparisonOperators {
+public:
+    /*
+     * NOTE: the functions below ARE NOT member methods. They are friend functions
+     * with they definition inlined with their declaration. This makes these
+     * template functions available to the compiler when (and only when) this class
+     * is instantiated, at which point they're only templated on the 2nd parameter
+     * (the first one, BASE<T> being known).
+     */
+    template<typename RT>
+    friend inline
+    bool PURE operator ==(const BASE<T>& lv, const BASE<RT>& rv) {
+        for (size_t i = 0; i < BASE<T>::size(); i++)
+            if (lv[i] != rv[i])
+                return false;
+        return true;
+    }
+
+    template<typename RT>
+    friend inline
+    bool PURE operator !=(const BASE<T>& lv, const BASE<RT>& rv) {
+        return !operator ==(lv, rv);
+    }
+
+    template<typename RT>
+    friend inline
+    bool PURE operator >(const BASE<T>& lv, const BASE<RT>& rv) {
+        for (size_t i = 0; i < BASE<T>::size(); i++)
+            if (lv[i] <= rv[i])
+                return false;
+        return true;
+    }
+
+    template<typename RT>
+    friend inline
+    bool PURE operator <=(const BASE<T>& lv, const BASE<RT>& rv) {
+        return !(lv > rv);
+    }
+
+    template<typename RT>
+    friend inline
+    bool PURE operator <(const BASE<T>& lv, const BASE<RT>& rv) {
+        for (size_t i = 0; i < BASE<T>::size(); i++)
+            if (lv[i] >= rv[i])
+                return false;
+        return true;
+    }
+
+    template<typename RT>
+    friend inline
+    bool PURE operator >=(const BASE<T>& lv, const BASE<RT>& rv) {
+        return !(lv < rv);
+    }
+};
+
+
+/*
+ * TVecFunctions implements functions on a vector of type BASE<T>.
+ *
+ * BASE only needs to implement operator[] and size().
+ * By simply inheriting from TVecFunctions<BASE, T> BASE will automatically
+ * get all the functionality here.
+ */
+template <template<typename T> class BASE, typename T>
+class TVecFunctions {
+public:
+    /*
+     * NOTE: the functions below ARE NOT member methods. They are friend functions
+     * with they definition inlined with their declaration. This makes these
+     * template functions available to the compiler when (and only when) this class
+     * is instantiated, at which point they're only templated on the 2nd parameter
+     * (the first one, BASE<T> being known).
+     */
+    template<typename RT>
+    friend inline
+    T PURE dot(const BASE<T>& lv, const BASE<RT>& rv) {
+        T r(0);
+        for (size_t i = 0; i < BASE<T>::size(); i++)
+            r += lv[i]*rv[i];
+        return r;
+    }
+
+    friend inline
+    T PURE length(const BASE<T>& lv) {
+        return sqrt( dot(lv, lv) );
+    }
+
+    template<typename RT>
+    friend inline
+    T PURE distance(const BASE<T>& lv, const BASE<RT>& rv) {
+        return length(rv - lv);
+    }
+
+    friend inline
+    BASE<T> PURE normalize(const BASE<T>& lv) {
+        return lv * (1 / length(lv));
+    }
+};
+
+#undef PURE
+
+// -------------------------------------------------------------------------------------
+}; // namespace android
+
+
+#endif /* UI_TVEC_HELPERS_H */
diff --git a/include/ui/mat4.h b/include/ui/mat4.h
new file mode 100644
index 0000000..08a67c7
--- /dev/null
+++ b/include/ui/mat4.h
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_MAT4_H
+#define UI_MAT4_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/vec4.h>
+#include <utils/String8.h>
+
+#define TMAT_IMPLEMENTATION
+#include <ui/TMatHelpers.h>
+
+#define PURE __attribute__((pure))
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+template <typename T>
+class tmat44 :  public TVecUnaryOperators<tmat44, T>,
+                public TVecComparisonOperators<tmat44, T>
+{
+public:
+    enum no_init { NO_INIT };
+    typedef T value_type;
+    typedef T& reference;
+    typedef T const& const_reference;
+    typedef size_t size_type;
+    typedef tvec4<T> col_type;
+    typedef tvec4<T> row_type;
+
+    // size of a column (i.e.: number of rows)
+    enum { COL_SIZE = col_type::SIZE };
+    static inline size_t col_size() { return COL_SIZE; }
+
+    // size of a row (i.e.: number of columns)
+    enum { ROW_SIZE = row_type::SIZE };
+    static inline size_t row_size() { return ROW_SIZE; }
+    static inline size_t size()     { return row_size(); }  // for TVec*<>
+
+private:
+
+    /*
+     *  <--  N columns  -->
+     *
+     *  a00 a10 a20 ... aN0    ^
+     *  a01 a11 a21 ... aN1    |
+     *  a02 a12 a22 ... aN2  M rows
+     *  ...                    |
+     *  a0M a1M a2M ... aNM    v
+     *
+     *  COL_SIZE = M
+     *  ROW_SIZE = N
+     *  m[0] = [a00 a01 a02 ... a01M]
+     */
+
+    col_type mValue[ROW_SIZE];
+
+public:
+    // array access
+    inline col_type const& operator [] (size_t i) const { return mValue[i]; }
+    inline col_type&       operator [] (size_t i)       { return mValue[i]; }
+
+    T const* asArray() const { return &mValue[0][0]; }
+
+    // -----------------------------------------------------------------------
+    // we don't provide copy-ctor and operator= on purpose
+    // because we want the compiler generated versions
+
+    /*
+     *  constructors
+     */
+
+    // leaves object uninitialized. use with caution.
+    explicit tmat44(no_init) { }
+
+    // initialize to identity
+    tmat44();
+
+    // initialize to Identity*scalar.
+    template<typename U>
+    explicit tmat44(U v);
+
+    // sets the diagonal to the passed vector
+    template <typename U>
+    explicit tmat44(const tvec4<U>& rhs);
+
+    // construct from another matrix of the same size
+    template <typename U>
+    explicit tmat44(const tmat44<U>& rhs);
+
+    // construct from 4 column vectors
+    template <typename A, typename B, typename C, typename D>
+    tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3);
+
+    // construct from a C array
+    template <typename U>
+    explicit tmat44(U const* rawArray);
+
+    /*
+     *  helpers
+     */
+
+    static tmat44 ortho(T left, T right, T bottom, T top, T near, T far);
+
+    static tmat44 frustum(T left, T right, T bottom, T top, T near, T far);
+
+    template <typename A, typename B, typename C>
+    static tmat44 lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up);
+
+    template <typename A>
+    static tmat44 translate(const tvec4<A>& t);
+
+    template <typename A>
+    static tmat44 scale(const tvec4<A>& s);
+
+    template <typename A, typename B>
+    static tmat44 rotate(A radian, const tvec3<B>& about);
+
+
+    /*
+     * Compound assignment arithmetic operators
+     */
+
+    // add another matrix of the same size
+    template <typename U>
+    tmat44& operator += (const tmat44<U>& v);
+
+    // subtract another matrix of the same size
+    template <typename U>
+    tmat44& operator -= (const tmat44<U>& v);
+
+    // multiply by a scalar
+    template <typename U>
+    tmat44& operator *= (U v);
+
+    // divide by a scalar
+    template <typename U>
+    tmat44& operator /= (U v);
+
+    /*
+     * debugging
+     */
+
+    String8 asString() const;
+};
+
+// ----------------------------------------------------------------------------------------
+// Constructors
+// ----------------------------------------------------------------------------------------
+
+/*
+ * Since the matrix code could become pretty big quickly, we don't inline most
+ * operations.
+ */
+
+template <typename T>
+tmat44<T>::tmat44() {
+    mValue[0] = col_type(1,0,0,0);
+    mValue[1] = col_type(0,1,0,0);
+    mValue[2] = col_type(0,0,1,0);
+    mValue[3] = col_type(0,0,0,1);
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>::tmat44(U v) {
+    mValue[0] = col_type(v,0,0,0);
+    mValue[1] = col_type(0,v,0,0);
+    mValue[2] = col_type(0,0,v,0);
+    mValue[3] = col_type(0,0,0,v);
+}
+
+template<typename T>
+template<typename U>
+tmat44<T>::tmat44(const tvec4<U>& v) {
+    mValue[0] = col_type(v.x,0,0,0);
+    mValue[1] = col_type(0,v.y,0,0);
+    mValue[2] = col_type(0,0,v.z,0);
+    mValue[3] = col_type(0,0,0,v.w);
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>::tmat44(const tmat44<U>& rhs) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        mValue[r] = rhs[r];
+}
+
+template <typename T>
+template <typename A, typename B, typename C, typename D>
+tmat44<T>::tmat44(const tvec4<A>& v0, const tvec4<B>& v1, const tvec4<C>& v2, const tvec4<D>& v3) {
+    mValue[0] = v0;
+    mValue[1] = v1;
+    mValue[2] = v2;
+    mValue[3] = v3;
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>::tmat44(U const* rawArray) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        for (size_t c=0 ; c<col_size() ; c++)
+            mValue[r][c] = *rawArray++;
+}
+
+// ----------------------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------------------
+
+template <typename T>
+tmat44<T> tmat44<T>::ortho(T left, T right, T bottom, T top, T near, T far) {
+    tmat44<T> m;
+    m[0][0] =  2 / (right - left);
+    m[1][1] =  2 / (top   - bottom);
+    m[2][2] = -2 / (far   - near);
+    m[3][0] = -(right + left)   / (right - left);
+    m[3][1] = -(top   + bottom) / (top   - bottom);
+    m[3][2] = -(far   + near)   / (far   - near);
+    return m;
+}
+
+template <typename T>
+tmat44<T> tmat44<T>::frustum(T left, T right, T bottom, T top, T near, T far) {
+    tmat44<T> m;
+    T A = (right + left)   / (right - left);
+    T B = (top   + bottom) / (top   - bottom);
+    T C = (far   + near)   / (far   - near);
+    T D = (2 * far * near) / (far   - near);
+    m[0][0] = (2 * near) / (right - left);
+    m[1][1] = (2 * near) / (top   - bottom);
+    m[2][0] = A;
+    m[2][1] = B;
+    m[2][2] = C;
+    m[2][3] =-1;
+    m[3][2] = D;
+    m[3][3] = 0;
+    return m;
+}
+
+template <typename T>
+template <typename A, typename B, typename C>
+tmat44<T> tmat44<T>::lookAt(const tvec3<A>& eye, const tvec3<B>& center, const tvec3<C>& up) {
+    tvec3<T> L(normalize(center - eye));
+    tvec3<T> S(normalize( cross(L, up) ));
+    tvec3<T> U(cross(S, L));
+    return tmat44<T>(
+            tvec4<T>( S, 0),
+            tvec4<T>( U, 0),
+            tvec4<T>(-L, 0),
+            tvec4<T>(-eye, 1));
+}
+
+template <typename T>
+template <typename A>
+tmat44<T> tmat44<T>::translate(const tvec4<A>& t) {
+    tmat44<T> r;
+    r[3] = t;
+    return r;
+}
+
+template <typename T>
+template <typename A>
+tmat44<T> tmat44<T>::scale(const tvec4<A>& s) {
+    tmat44<T> r;
+    r[0][0] = s[0];
+    r[1][1] = s[1];
+    r[2][2] = s[2];
+    r[3][3] = s[3];
+    return r;
+}
+
+template <typename T>
+template <typename A, typename B>
+tmat44<T> tmat44<T>::rotate(A radian, const tvec3<B>& about) {
+    tmat44<T> rotation;
+    T* r = const_cast<T*>(rotation.asArray());
+    T c = cos(radian);
+    T s = sin(radian);
+    if (about.x==1 && about.y==0 && about.z==0) {
+        r[5] = c;   r[10]= c;
+        r[6] = s;   r[9] = -s;
+    } else if (about.x==0 && about.y==1 && about.z==0) {
+        r[0] = c;   r[10]= c;
+        r[8] = s;   r[2] = -s;
+    } else if (about.x==0 && about.y==0 && about.z==1) {
+        r[0] = c;   r[5] = c;
+        r[1] = s;   r[4] = -s;
+    } else {
+        tvec3<B> nabout = normalize(about);
+        B x = nabout.x;
+        B y = nabout.y;
+        B z = nabout.z;
+        T nc = 1 - c;
+        T xy = x * y;
+        T yz = y * z;
+        T zx = z * x;
+        T xs = x * s;
+        T ys = y * s;
+        T zs = z * s;
+        r[ 0] = x*x*nc +  c;    r[ 4] =  xy*nc - zs;    r[ 8] =  zx*nc + ys;
+        r[ 1] =  xy*nc + zs;    r[ 5] = y*y*nc +  c;    r[ 9] =  yz*nc - xs;
+        r[ 2] =  zx*nc - ys;    r[ 6] =  yz*nc + xs;    r[10] = z*z*nc +  c;
+    }
+}
+
+// ----------------------------------------------------------------------------------------
+// Compound assignment arithmetic operators
+// ----------------------------------------------------------------------------------------
+
+template <typename T>
+template <typename U>
+tmat44<T>& tmat44<T>::operator += (const tmat44<U>& v) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        mValue[r] += v[r];
+    return *this;
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>& tmat44<T>::operator -= (const tmat44<U>& v) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        mValue[r] -= v[r];
+    return *this;
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>& tmat44<T>::operator *= (U v) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        mValue[r] *= v;
+    return *this;
+}
+
+template <typename T>
+template <typename U>
+tmat44<T>& tmat44<T>::operator /= (U v) {
+    for (size_t r=0 ; r<row_size() ; r++)
+        mValue[r] /= v;
+    return *this;
+}
+
+// ----------------------------------------------------------------------------------------
+// Arithmetic operators outside of class
+// ----------------------------------------------------------------------------------------
+
+/* We use non-friend functions here to prevent the compiler from using
+ * implicit conversions, for instance of a scalar to a vector. The result would
+ * not be what the caller expects.
+ *
+ * Also note that the order of the arguments in the inner loop is important since
+ * it determines the output type (only relevant when T != U).
+ */
+
+// matrix + matrix, result is a matrix of the same type than the lhs matrix
+template <typename T, typename U>
+tmat44<T> PURE operator +(const tmat44<T>& lhs, const tmat44<U>& rhs) {
+    tmat44<T> result(tmat44<T>::NO_INIT);
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result[r] = lhs[r] + rhs[r];
+    return result;
+}
+
+// matrix - matrix, result is a matrix of the same type than the lhs matrix
+template <typename T, typename U>
+tmat44<T> PURE operator -(const tmat44<T>& lhs, const tmat44<U>& rhs) {
+    tmat44<T> result(tmat44<T>::NO_INIT);
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result[r] = lhs[r] - rhs[r];
+    return result;
+}
+
+// matrix * vector, result is a vector of the same type than the input vector
+template <typename T, typename U>
+typename tmat44<U>::col_type PURE operator *(const tmat44<T>& lv, const tvec4<U>& rv) {
+    typename tmat44<U>::col_type result;
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result += rv[r]*lv[r];
+    return result;
+}
+
+// vector * matrix, result is a vector of the same type than the input vector
+template <typename T, typename U>
+typename tmat44<U>::row_type PURE operator *(const tvec4<U>& rv, const tmat44<T>& lv) {
+    typename tmat44<U>::row_type result(tmat44<U>::row_type::NO_INIT);
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result[r] = dot(rv, lv[r]);
+    return result;
+}
+
+// matrix * scalar, result is a matrix of the same type than the input matrix
+template <typename T, typename U>
+tmat44<T> PURE operator *(const tmat44<T>& lv, U rv) {
+    tmat44<T> result(tmat44<T>::NO_INIT);
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result[r] = lv[r]*rv;
+    return result;
+}
+
+// scalar * matrix, result is a matrix of the same type than the input matrix
+template <typename T, typename U>
+tmat44<T> PURE operator *(U rv, const tmat44<T>& lv) {
+    tmat44<T> result(tmat44<T>::NO_INIT);
+    for (size_t r=0 ; r<tmat44<T>::row_size() ; r++)
+        result[r] = lv[r]*rv;
+    return result;
+}
+
+// matrix * matrix, result is a matrix of the same type than the lhs matrix
+template <typename T, typename U>
+tmat44<T> PURE operator *(const tmat44<T>& lhs, const tmat44<U>& rhs) {
+    return matrix::multiply< tmat44<T> >(lhs, rhs);
+}
+
+// ----------------------------------------------------------------------------------------
+// Functions
+// ----------------------------------------------------------------------------------------
+
+// inverse a matrix
+template <typename T>
+tmat44<T> PURE inverse(const tmat44<T>& m) {
+    return matrix::inverse(m);
+}
+
+template <typename T>
+tmat44<T> PURE transpose(const tmat44<T>& m) {
+    return matrix::transpose(m);
+}
+
+template <typename T>
+T PURE trace(const tmat44<T>& m) {
+    return matrix::trace(m);
+}
+
+template <typename T>
+tvec4<T> PURE diag(const tmat44<T>& m) {
+    return matrix::diag(m);
+}
+
+// ----------------------------------------------------------------------------------------
+// Debugging
+// ----------------------------------------------------------------------------------------
+
+template <typename T>
+String8 tmat44<T>::asString() const {
+    return matrix::asString(*this);
+}
+
+// ----------------------------------------------------------------------------------------
+
+typedef tmat44<float> mat4;
+
+// ----------------------------------------------------------------------------------------
+}; // namespace android
+
+#undef PURE
+
+#endif /* UI_MAT4_H */
diff --git a/include/ui/vec2.h b/include/ui/vec2.h
new file mode 100644
index 0000000..b4edfc6
--- /dev/null
+++ b/include/ui/vec2.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_VEC2_H
+#define UI_VEC2_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#define TVEC_IMPLEMENTATION
+#include <ui/TVecHelpers.h>
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+template <typename T>
+class tvec2 :   public TVecArithmeticOperators<tvec2, T>,
+                public TVecUnaryOperators<tvec2, T>,
+                public TVecComparisonOperators<tvec2, T>,
+                public TVecFunctions<tvec2, T>
+{
+public:
+    enum no_init { NO_INIT };
+    typedef T value_type;
+    typedef T& reference;
+    typedef T const& const_reference;
+    typedef size_t size_type;
+
+    union {
+        struct { T x, y; };
+        struct { T s, t; };
+        struct { T r, g; };
+    };
+
+    enum { SIZE = 2 };
+    inline static size_type size() { return SIZE; }
+
+    // array access
+    inline T const& operator [] (size_t i) const { return (&x)[i]; }
+    inline T&       operator [] (size_t i)       { return (&x)[i]; }
+
+    // -----------------------------------------------------------------------
+    // we don't provide copy-ctor and operator= on purpose
+    // because we want the compiler generated versions
+
+    // constructors
+
+    // leaves object uninitialized. use with caution.
+    explicit tvec2(no_init) { }
+
+    // default constructor
+    tvec2() : x(0), y(0) { }
+
+    // handles implicit conversion to a tvec4. must not be explicit.
+    template<typename A>
+    tvec2(A v) : x(v), y(v) { }
+
+    template<typename A, typename B>
+    tvec2(A x, B y) : x(x), y(y) { }
+
+    template<typename A>
+    explicit tvec2(const tvec2<A>& v) : x(v.x), y(v.y) { }
+};
+
+// ----------------------------------------------------------------------------------------
+
+typedef tvec2<float> vec2;
+
+// ----------------------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* UI_VEC4_H */
diff --git a/include/ui/vec3.h b/include/ui/vec3.h
new file mode 100644
index 0000000..591b8b2
--- /dev/null
+++ b/include/ui/vec3.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_VEC3_H
+#define UI_VEC3_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/vec2.h>
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+template <typename T>
+class tvec3 :   public TVecArithmeticOperators<tvec3, T>,
+                public TVecUnaryOperators<tvec3, T>,
+                public TVecComparisonOperators<tvec3, T>,
+                public TVecFunctions<tvec3, T>
+{
+public:
+    enum no_init { NO_INIT };
+    typedef T value_type;
+    typedef T& reference;
+    typedef T const& const_reference;
+    typedef size_t size_type;
+
+    union {
+        struct { T x, y, z; };
+        struct { T s, t, p; };
+        struct { T r, g, b; };
+        Impersonator< tvec2<T> > xy;
+        Impersonator< tvec2<T> > st;
+        Impersonator< tvec2<T> > rg;
+    };
+
+    enum { SIZE = 3 };
+    inline static size_type size() { return SIZE; }
+
+    // array access
+    inline T const& operator [] (size_t i) const { return (&x)[i]; }
+    inline T&       operator [] (size_t i)       { return (&x)[i]; }
+
+    // -----------------------------------------------------------------------
+    // we don't provide copy-ctor and operator= on purpose
+    // because we want the compiler generated versions
+
+    // constructors
+    // leaves object uninitialized. use with caution.
+    explicit tvec3(no_init) { }
+
+    // default constructor
+    tvec3() : x(0), y(0), z(0) { }
+
+    // handles implicit conversion to a tvec4. must not be explicit.
+    template<typename A>
+    tvec3(A v) : x(v), y(v), z(v) { }
+
+    template<typename A, typename B, typename C>
+    tvec3(A x, B y, C z) : x(x), y(y), z(z) { }
+
+    template<typename A, typename B>
+    tvec3(const tvec2<A>& v, B z) : x(v.x), y(v.y), z(z) { }
+
+    template<typename A>
+    explicit tvec3(const tvec3<A>& v) : x(v.x), y(v.y), z(v.z) { }
+
+    template<typename A, typename B>
+    tvec3(const Impersonator< tvec2<A> >& v, B z)
+        : x(((const tvec2<A>&)v).x),
+          y(((const tvec2<A>&)v).y),
+          z(z) { }
+
+    // cross product works only on vectors of size 3
+    template <typename RT>
+    friend inline
+    tvec3 __attribute__((pure)) cross(const tvec3& u, const tvec3<RT>& v) {
+        return tvec3(
+                u.y*v.z - u.z*v.y,
+                u.z*v.x - u.x*v.z,
+                u.x*v.y - u.y*v.x);
+    }
+};
+
+
+// ----------------------------------------------------------------------------------------
+
+typedef tvec3<float> vec3;
+
+// ----------------------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* UI_VEC4_H */
diff --git a/include/ui/vec4.h b/include/ui/vec4.h
new file mode 100644
index 0000000..798382d
--- /dev/null
+++ b/include/ui/vec4.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_VEC4_H
+#define UI_VEC4_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <ui/vec3.h>
+
+namespace android {
+// -------------------------------------------------------------------------------------
+
+template <typename T>
+class tvec4 :   public TVecArithmeticOperators<tvec4, T>,
+                public TVecUnaryOperators<tvec4, T>,
+                public TVecComparisonOperators<tvec4, T>,
+                public TVecFunctions<tvec4, T>
+{
+public:
+    enum no_init { NO_INIT };
+    typedef T value_type;
+    typedef T& reference;
+    typedef T const& const_reference;
+    typedef size_t size_type;
+
+    union {
+        struct { T x, y, z, w; };
+        struct { T s, t, p, q; };
+        struct { T r, g, b, a; };
+        Impersonator< tvec2<T> > xy;
+        Impersonator< tvec2<T> > st;
+        Impersonator< tvec2<T> > rg;
+        Impersonator< tvec3<T> > xyz;
+        Impersonator< tvec3<T> > stp;
+        Impersonator< tvec3<T> > rgb;
+    };
+
+    enum { SIZE = 4 };
+    inline static size_type size() { return SIZE; }
+
+    // array access
+    inline T const& operator [] (size_t i) const { return (&x)[i]; }
+    inline T&       operator [] (size_t i)       { return (&x)[i]; }
+
+    // -----------------------------------------------------------------------
+    // we don't provide copy-ctor and operator= on purpose
+    // because we want the compiler generated versions
+
+    // constructors
+
+    // leaves object uninitialized. use with caution.
+    explicit tvec4(no_init) { }
+
+    // default constructor
+    tvec4() : x(0), y(0), z(0), w(0) { }
+
+    // handles implicit conversion to a tvec4. must not be explicit.
+    template<typename A>
+    tvec4(A v) : x(v), y(v), z(v), w(v) { }
+
+    template<typename A, typename B, typename C, typename D>
+    tvec4(A x, B y, C z, D w) : x(x), y(y), z(z), w(w) { }
+
+    template<typename A, typename B, typename C>
+    tvec4(const tvec2<A>& v, B z, C w) : x(v.x), y(v.y), z(z), w(w) { }
+
+    template<typename A, typename B>
+    tvec4(const tvec3<A>& v, B w) : x(v.x), y(v.y), z(v.z), w(w) { }
+
+    template<typename A>
+    explicit tvec4(const tvec4<A>& v) : x(v.x), y(v.y), z(v.z), w(v.w) { }
+
+    template<typename A, typename B>
+    tvec4(const Impersonator< tvec3<A> >& v, B w)
+        : x(((const tvec3<A>&)v).x),
+          y(((const tvec3<A>&)v).y),
+          z(((const tvec3<A>&)v).z),
+          w(w) { }
+
+    template<typename A, typename B, typename C>
+    tvec4(const Impersonator< tvec2<A> >& v, B z, C w)
+        : x(((const tvec2<A>&)v).x),
+          y(((const tvec2<A>&)v).y),
+          z(z),
+          w(w) { }
+};
+
+// ----------------------------------------------------------------------------------------
+
+typedef tvec4<float> vec4;
+
+// ----------------------------------------------------------------------------------------
+}; // namespace android
+
+#endif /* UI_VEC4_H */