1984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian/*
2984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * Copyright (C) 2011 The Android Open Source Project
3984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian *
4984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License");
5984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * you may not use this file except in compliance with the License.
6984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * You may obtain a copy of the License at
7984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian *
8984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian *      http://www.apache.org/licenses/LICENSE-2.0
9984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian *
10984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * Unless required by applicable law or agreed to in writing, software
11984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS,
12984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * See the License for the specific language governing permissions and
14984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian * limitations under the License.
15984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian */
16984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
17984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian#ifndef ANDROID_MAT_H
18984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian#define ANDROID_MAT_H
19984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
20984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian#include "vec.h"
21984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian#include "traits.h"
22984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
23984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
24984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
25984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiannamespace android {
26984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
27984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
28984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianclass mat;
29984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
30984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiannamespace helpers {
31984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
32984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
33984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, C, R>& doAssign(
34984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        mat<TYPE, C, R>& lhs,
35984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        typename TypeTraits<TYPE>::ParameterType rhs) {
36984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t i=0 ; i<C ; i++)
37984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t j=0 ; j<R ; j++)
38984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            lhs[i][j] = (i==j) ? rhs : 0;
39984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return lhs;
40984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
41984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
42984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R, size_t D>
43984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, C, R> PURE doMul(
44984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, D, R>& lhs,
45984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, C, D>& rhs)
46984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian{
47984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, C, R> res;
48984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t c=0 ; c<C ; c++) {
49984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t r=0 ; r<R ; r++) {
50984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            TYPE v(0);
51984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            for (size_t k=0 ; k<D ; k++) {
52984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                v += lhs[k][r] * rhs[c][k];
53984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            }
54984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            res[c][r] = v;
55984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
56984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
57984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return res;
58984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
59984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
60984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t R, size_t D>
61984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianvec<TYPE, R> PURE doMul(
62984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, D, R>& lhs,
63984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const vec<TYPE, D>& rhs)
64984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian{
65984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    vec<TYPE, R> res;
66984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t r=0 ; r<R ; r++) {
67984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        TYPE v(0);
68984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t k=0 ; k<D ; k++) {
69984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            v += lhs[k][r] * rhs[k];
70984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
71984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        res[r] = v;
72984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
73984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return res;
74984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
75984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
76984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
77984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, C, R> PURE doMul(
78984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const vec<TYPE, R>& lhs,
79984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, C, 1>& rhs)
80984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian{
81984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, C, R> res;
82984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t c=0 ; c<C ; c++) {
83984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t r=0 ; r<R ; r++) {
84984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            res[c][r] = lhs[r] * rhs[c][0];
85984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
86984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
87984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return res;
88984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
89984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
90984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
91984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, C, R> PURE doMul(
92984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, C, R>& rhs,
93984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        typename TypeTraits<TYPE>::ParameterType v)
94984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian{
95984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, C, R> res;
96984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t c=0 ; c<C ; c++) {
97984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t r=0 ; r<R ; r++) {
98984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            res[c][r] = rhs[c][r] * v;
99984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
100984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
101984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return res;
102984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
103984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
104984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
105984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, C, R> PURE doMul(
106984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        typename TypeTraits<TYPE>::ParameterType v,
107984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        const mat<TYPE, C, R>& rhs)
108984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian{
109984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, C, R> res;
110984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t c=0 ; c<C ; c++) {
111984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t r=0 ; r<R ; r++) {
112984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            res[c][r] = v * rhs[c][r];
113984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
114984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
115984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return res;
116984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
117984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
118984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
119984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}; // namespace helpers
120984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
121984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
122984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
123984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
124984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianclass mat : public vec< vec<TYPE, R>, C > {
125984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef typename TypeTraits<TYPE>::ParameterType pTYPE;
126984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef vec< vec<TYPE, R>, C > base;
127984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianpublic:
128984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // STL-like interface.
129984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE value_type;
130984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE& reference;
131984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE const& const_reference;
132984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef size_t size_type;
133984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    size_type size() const { return R*C; }
134984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    enum { ROWS = R, COLS = C };
135984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
136984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
137984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // -----------------------------------------------------------------------
138984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // default constructors
139984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
140984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat() { }
141984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(const mat& rhs)  : base(rhs) { }
142984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(const base& rhs) : base(rhs) { }
143984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
144984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // -----------------------------------------------------------------------
145984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // conversion constructors
146984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
147984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // sets the diagonal to the value, off-diagonal to zero
148984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(pTYPE rhs) {
149984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        helpers::doAssign(*this, rhs);
150984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
151984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
152984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // -----------------------------------------------------------------------
153984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // Assignment
154984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
155984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(const mat& rhs) {
156984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        base::operator=(rhs);
157984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return *this;
158984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
159984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
160984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(const base& rhs) {
161984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        base::operator=(rhs);
162984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return *this;
163984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
164984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
165984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(pTYPE rhs) {
166984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doAssign(*this, rhs);
167984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
168984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
169984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // -----------------------------------------------------------------------
170984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // non-member function declaration and definition
171984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
172984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend inline mat PURE operator + (const mat& lhs, const mat& rhs) {
173984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doAdd(
174984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                static_cast<const base&>(lhs),
175984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                static_cast<const base&>(rhs));
176984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
177984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend inline mat PURE operator - (const mat& lhs, const mat& rhs) {
178984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doSub(
179984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                static_cast<const base&>(lhs),
180984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                static_cast<const base&>(rhs));
181984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
182984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
183984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // matrix*matrix
184984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    template <size_t D>
185984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend mat PURE operator * (
186984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const mat<TYPE, D, R>& lhs,
187984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const mat<TYPE, C, D>& rhs) {
188984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doMul(lhs, rhs);
189984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
190984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
191984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // matrix*vector
192984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend vec<TYPE, R> PURE operator * (
193984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const mat& lhs, const vec<TYPE, C>& rhs) {
194984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doMul(lhs, rhs);
195984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
196984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
197984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // vector*matrix
198984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend mat PURE operator * (
199984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const vec<TYPE, R>& lhs, const mat<TYPE, C, 1>& rhs) {
200984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doMul(lhs, rhs);
201984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
202984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
203984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // matrix*scalar
204984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend inline mat PURE operator * (const mat& lhs, pTYPE v) {
205984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doMul(lhs, v);
206984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
207984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
208984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // scalar*matrix
209984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend inline mat PURE operator * (pTYPE v, const mat& rhs) {
210984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return helpers::doMul(v, rhs);
211984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
212984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
213984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // -----------------------------------------------------------------------
214984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // streaming operator to set the columns of the matrix:
215984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // example:
216984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    //    mat33_t m;
217984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    //    m << v0 << v1 << v2;
218984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
219984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // column_builder<> stores the matrix and knows which column to set
220984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    template<size_t PREV_COLUMN>
221984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    struct column_builder {
222984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        mat& matrix;
223984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        column_builder(mat& matrix) : matrix(matrix) { }
224984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    };
225984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
226984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // operator << is not a method of column_builder<> so we can
227984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // overload it for unauthorized values (partial specialization
228984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // not allowed in class-scope).
229984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // we just set the column and return the next column_builder<>
230984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    template<size_t PREV_COLUMN>
231984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend column_builder<PREV_COLUMN+1> operator << (
232984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const column_builder<PREV_COLUMN>& lhs,
233984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const vec<TYPE, R>& rhs) {
234984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        lhs.matrix[PREV_COLUMN+1] = rhs;
235984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return column_builder<PREV_COLUMN+1>(lhs.matrix);
236984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
237984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
238984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // we return void here so we get a compile-time error if the
239984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // user tries to set too many columns
240984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    friend void operator << (
241984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const column_builder<C-2>& lhs,
242984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            const vec<TYPE, R>& rhs) {
243984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        lhs.matrix[C-1] = rhs;
244984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
245984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
246984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // this is where the process starts. we set the first columns and
247984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // return the next column_builder<>
248984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    column_builder<0> operator << (const vec<TYPE, R>& rhs) {
249984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        (*this)[0] = rhs;
250984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        return column_builder<0>(*this);
251984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
252984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian};
253984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
254984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// Specialize column matrix so they're exactly equivalent to a vector
255984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t R>
256984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianclass mat<TYPE, 1, R> : public vec<TYPE, R> {
257984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef vec<TYPE, R> base;
258984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianpublic:
259984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // STL-like interface.
260984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE value_type;
261984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE& reference;
262984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef TYPE const& const_reference;
263984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typedef size_t size_type;
264984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    size_type size() const { return R; }
265984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    enum { ROWS = R, COLS = 1 };
266984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
267984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat() { }
268984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(const base& rhs) : base(rhs) { }
269984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(const mat& rhs) : base(rhs) { }
270984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat(const TYPE& rhs) { helpers::doAssign(*this, rhs); }
271984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(const mat& rhs) { base::operator=(rhs); return *this; }
272984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(const base& rhs) { base::operator=(rhs); return *this; }
273984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat& operator=(const TYPE& rhs) { return helpers::doAssign(*this, rhs); }
274984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    // we only have one column, so ignore the index
275984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    const base& operator[](size_t) const { return *this; }
276984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    base& operator[](size_t) { return *this; }
277984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    void operator << (const vec<TYPE, R>& rhs) { base::operator[](0) = rhs; }
278984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian};
279984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
280984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
281984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// matrix functions
282984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
283984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// transpose. this handles matrices of matrices
284984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianinline int     PURE transpose(int v)    { return v; }
285984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianinline float   PURE transpose(float v)  { return v; }
286984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianinline double  PURE transpose(double v) { return v; }
287984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
288984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// Transpose a matrix
289984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <typename TYPE, size_t C, size_t R>
290984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, R, C> PURE transpose(const mat<TYPE, C, R>& m) {
291984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, R, C> r;
292984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t i=0 ; i<R ; i++)
293984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t j=0 ; j<C ; j++)
294984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            r[i][j] = transpose(m[j][i]);
295984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return r;
296984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
297984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
298a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun// Calculate the trace of a matrix
299a01b4e237d57b74689576a3d486a2b2b903e74f4Max Brauntemplate <typename TYPE, size_t C> static TYPE trace(const mat<TYPE, C, C>& m) {
300a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    TYPE t;
301a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    for (size_t i=0 ; i<C ; i++)
302a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun        t += m[i][i];
303a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    return t;
304a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun}
305a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun
306a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun// Test positive-semidefiniteness of a matrix
307a01b4e237d57b74689576a3d486a2b2b903e74f4Max Brauntemplate <typename TYPE, size_t C>
308a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braunstatic bool isPositiveSemidefinite(const mat<TYPE, C, C>& m, TYPE tolerance) {
309a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    for (size_t i=0 ; i<C ; i++)
310a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun        if (m[i][i] < 0)
311a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun            return false;
312a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun
313a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    for (size_t i=0 ; i<C ; i++)
314a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun      for (size_t j=i+1 ; j<C ; j++)
315a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun          if (fabs(m[i][j] - m[j][i]) > tolerance)
316a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun              return false;
317a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun
318a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun    return true;
319a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun}
320a01b4e237d57b74689576a3d486a2b2b903e74f4Max Braun
321984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// Transpose a vector
322984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate <
323984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    template<typename T, size_t S> class VEC,
324984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    typename TYPE,
325984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    size_t SIZE
326984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian>
327984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<TYPE, SIZE, 1> PURE transpose(const VEC<TYPE, SIZE>& v) {
328984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<TYPE, SIZE, 1> r;
329984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t i=0 ; i<SIZE ; i++)
330984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        r[i][0] = transpose(v[i]);
331984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return r;
332984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
333984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
334984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
335984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// "dumb" matrix inversion
336984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantemplate<typename T, size_t N>
337984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopianmat<T, N, N> PURE invert(const mat<T, N, N>& src) {
338984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    T t;
339984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    size_t swap;
340984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<T, N, N> tmp(src);
341984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    mat<T, N, N> inverse(1);
342984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
343984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    for (size_t i=0 ; i<N ; i++) {
344984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        // look for largest element in column
345984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        swap = i;
346984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t j=i+1 ; j<N ; j++) {
347984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            if (fabs(tmp[j][i]) > fabs(tmp[i][i])) {
348984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                swap = j;
349984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            }
350984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
351984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
352984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        if (swap != i) {
353984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            /* swap rows. */
354984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            for (size_t k=0 ; k<N ; k++) {
355984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                t = tmp[i][k];
356984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                tmp[i][k] = tmp[swap][k];
357984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                tmp[swap][k] = t;
358984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
359984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                t = inverse[i][k];
360984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                inverse[i][k] = inverse[swap][k];
361984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                inverse[swap][k] = t;
362984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            }
363984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
364984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
365984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        t = 1 / tmp[i][i];
366984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t k=0 ; k<N ; k++) {
367984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            tmp[i][k] *= t;
368984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            inverse[i][k] *= t;
369984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
370984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        for (size_t j=0 ; j<N ; j++) {
371984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            if (j != i) {
372984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                t = tmp[j][i];
373984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                for (size_t k=0 ; k<N ; k++) {
374984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                    tmp[j][k] -= tmp[i][k] * t;
375984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                    inverse[j][k] -= inverse[i][k] * t;
376984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian                }
377984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian            }
378984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian        }
379984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    }
380984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian    return inverse;
381984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}
382984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
383984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
384984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
385984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantypedef mat<float, 2, 2> mat22_t;
386984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantypedef mat<float, 3, 3> mat33_t;
387984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopiantypedef mat<float, 4, 4> mat44_t;
388984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
389984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian// -----------------------------------------------------------------------
390984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
391984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian}; // namespace android
392984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian
393984826cc158193e61e3a00359ef4f6699c7d748aMathias Agopian#endif /* ANDROID_MAT_H */
394