Simbody

SmallMatrixMixed.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-9 Stanford University and the Authors.         *
00013  * Authors: Michael Sherman                                                   *
00014  * Contributors:                                                              *
00015  *                                                                            *
00016  * Permission is hereby granted, free of charge, to any person obtaining a    *
00017  * copy of this software and associated documentation files (the "Software"), *
00018  * to deal in the Software without restriction, including without limitation  *
00019  * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
00020  * and/or sell copies of the Software, and to permit persons to whom the      *
00021  * Software is furnished to do so, subject to the following conditions:       *
00022  *                                                                            *
00023  * The above copyright notice and this permission notice shall be included in *
00024  * all copies or substantial portions of the Software.                        *
00025  *                                                                            *
00026  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
00027  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
00028  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
00029  * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,    *
00030  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR      *
00031  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE  *
00032  * USE OR OTHER DEALINGS IN THE SOFTWARE.                                     *
00033  * -------------------------------------------------------------------------- */
00034 
00041 namespace SimTK {
00042 
00043     // COMPARISON
00044 
00045 // m==s
00046 template <int M, class EL, int CSL, int RSL, class ER, int RSR> inline
00047 bool operator==(const Mat<M,M,EL,CSL,RSL>& l, const SymMat<M,ER,RSR>& r) {
00048     for (int i=0; i<M; ++i) {
00049         if (l(i,i) != r.getDiag()[i]) return false;
00050         for (int j=0; j<i; ++j)
00051             if (l(i,j) != r.getEltLower(i,j)) return false;
00052         for (int j=i+1; j<M; ++j)
00053             if (l(i,j) != r.getEltUpper(i,j)) return false;
00054     }
00055      
00056     return true;
00057 }
00058 // m!=s
00059 template <int M, class EL, int CSL, int RSL, class ER, int RSR> inline
00060 bool operator!=(const Mat<M,M,EL,CSL,RSL>& l, const SymMat<M,ER,RSR>& r) {
00061     return !(l==r);
00062 }
00063 
00064 // s==m
00065 template <int M, class EL, int RSL, class ER, int CSR, int RSR> inline
00066 bool operator==(const SymMat<M,EL,RSL>& l, const Mat<M,M,ER,CSR,RSR>& r) {
00067     return r==l;
00068 }
00069 // s!=m
00070 template <int M, class EL, int RSL, class ER, int CSR, int RSR> inline
00071 bool operator!=(const SymMat<M,EL,RSL>& l, const Mat<M,M,ER,CSR,RSR>& r) {
00072     return !(r==l);
00073 }
00074 
00075     // DOT PRODUCT
00076 
00077 // Dot product and corresponding infix operator*(). Note that
00078 // the '*' operator is just a matrix multiply so is strictly 
00079 // row*column to produce a scalar (1x1) result.
00080 //
00081 // In keeping with Matlab precedent, however, the explicit dot()
00082 // function is defined on two column vectors
00083 // v and w such that dot(v,w)= ~v * w. That means we use the
00084 // Hermitian transpose of the elements of v, and the elements of
00085 // w unchanged. If v and/or w are rows, we first convert them
00086 // to vectors via *positional* transpose. So no matter what shape
00087 // these have on the way in it is always the Hermitian transpose
00088 // (or complex conjugate for scalars) of the first item times
00089 // the unchanged elements of the second item.
00090 
00091 
00092 template <int M, class E1, int S1, class E2, int S2> inline
00093 typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul 
00094 dot(const Vec<M,E1,S1>& r, const Vec<M,E2,S2>& v) {
00095     typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul sum(dot(reinterpret_cast<const Vec<M-1,E1,S1>&>(r), reinterpret_cast<const Vec<M-1,E2,S2>&>(v)) + CNT<E1>::transpose(r[M-1])*v[M-1]);
00096     return sum;
00097 }
00098 template <class E1, int S1, class E2, int S2> inline
00099 typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul 
00100 dot(const Vec<1,E1,S1>& r, const Vec<1,E2,S2>& v) {
00101     typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul sum(CNT<E1>::transpose(r[0])*v[0]);
00102     return sum;
00103 }
00104 
00105 // dot product (row * conforming vec)
00106 template <int N, class E1, int S1, class E2, int S2> inline
00107 typename CNT<E1>::template Result<E2>::Mul 
00108 operator*(const Row<N,E1,S1>& r, const Vec<N,E2,S2>& v) {
00109     typename CNT<E1>::template Result<E2>::Mul sum(reinterpret_cast<const Row<N-1,E1,S1>&>(r)*reinterpret_cast<const Vec<N-1,E2,S2>&>(v) + r[N-1]*v[N-1]);
00110     return sum;
00111 }
00112 template <class E1, int S1, class E2, int S2> inline
00113 typename CNT<E1>::template Result<E2>::Mul 
00114 operator*(const Row<1,E1,S1>& r, const Vec<1,E2,S2>& v) {
00115     typename CNT<E1>::template Result<E2>::Mul sum(r[0]*v[0]);
00116     return sum;
00117 }
00118 
00119 // Alternate acceptable forms for dot().
00120 template <int N, class E1, int S1, class E2, int S2> inline
00121 typename CNT<E1>::template Result<E2>::Mul 
00122 dot(const Row<N,E1,S1>& r, const Vec<N,E2,S2>& v) {
00123     return dot(r.positionalTranspose(),v);
00124 }
00125 template <int M, class E1, int S1, class E2, int S2> inline
00126 typename CNT<E1>::template Result<E2>::Mul 
00127 dot(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00128     return dot(v,r.positionalTranspose());
00129 }
00130 template <int N, class E1, int S1, class E2, int S2> inline
00131 typename CNT<E1>::template Result<E2>::Mul 
00132 dot(const Row<N,E1,S1>& r, const Row<N,E2,S2>& s) {
00133     return dot(r.positionalTranspose(),s.positionalTranspose());
00134 }
00135 
00136     // OUTER PRODUCT
00137 
00138 // Outer product and corresponding infix operator*(). Note that
00139 // the '*' operator is just a matrix multiply so is strictly 
00140 // column_mX1 * row_1Xm to produce an mXm matrix result.
00141 //
00142 // Although Matlab doesn't provide outer(), to be consistent
00143 // we'll treat it as discussed for dot() above. That is, outer
00144 // is defined on two column vectors
00145 // v and w such that outer(v,w)= v * ~w. That means we use the
00146 // elements of v unchanged but use the Hermitian transpose of
00147 // the elements of w. If v and/or w are rows, we first convert them
00148 // to vectors via *positional* transpose. So no matter what shape
00149 // these have on the way in it is always the unchanged elements of
00150 // the first item times the Hermitian transpose (or complex
00151 // conjugate for scalars) of the elements of the second item.
00152 
00153 template <int M, class E1, int S1, class E2, int S2> inline
00154 Mat<M,M, typename CNT<E1>::template Result<typename CNT<E2>::THerm>::Mul>
00155 outer(const Vec<M,E1,S1>& v, const Vec<M,E2,S2>& w) {
00156     Mat<M,M, typename CNT<E1>::template Result<typename CNT<E2>::THerm>::Mul> m;
00157     for (int i=0; i<M; ++i)
00158         m[i] = v[i] * ~w;
00159     return m;
00160 }
00161 
00162 // This is the general conforming case of Vec*Row (outer product)
00163 template <int M, class E1, int S1, class E2, int S2> inline
00164 typename Vec<M,E1,S1>::template Result<Row<M,E2,S2> >::Mul
00165 operator*(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00166     return Vec<M,E1,S1>::template Result<Row<M,E2,S2> >::MulOp::perform(v,r);
00167 }
00168 
00169 
00170 // Alternate acceptable forms for outer().
00171 template <int M, class E1, int S1, class E2, int S2> inline
00172 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00173 outer(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00174     return outer(v,r.positionalTranspose());
00175 }
00176 template <int M, class E1, int S1, class E2, int S2> inline
00177 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00178 outer(const Row<M,E1,S1>& r, const Vec<M,E2,S2>& v) {
00179     return outer(r.positionalTranspose(),v);
00180 }
00181 template <int M, class E1, int S1, class E2, int S2> inline
00182 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00183 outer(const Row<M,E1,S1>& r, const Row<M,E2,S2>& s) {
00184     return outer(r.positionalTranspose(),s.positionalTranspose());
00185 }
00186 
00187     // MAT*VEC, ROW*MAT (conforming)
00188 
00189 // vec = mat * vec (conforming)
00190 template <int M, int N, class ME, int CS, int RS, class E, int S> inline
00191 typename Mat<M,N,ME,CS,RS>::template Result<Vec<N,E,S> >::Mul
00192 operator*(const Mat<M,N,ME,CS,RS>& m,const Vec<N,E,S>& v) {
00193     typename Mat<M,N,ME,CS,RS>::template Result<Vec<N,E,S> >::Mul result;
00194     for (int i=0; i<M; ++i)
00195         result[i] = m[i]*v;
00196     return result;
00197 }
00198 
00199 // row = row * mat (conforming)
00200 template <int M, class E, int S, int N, class ME, int CS, int RS> inline
00201 typename Row<M,E,S>::template Result<Mat<M,N,ME,CS,RS> >::Mul
00202 operator*(const Row<M,E,S>& r, const Mat<M,N,ME,CS,RS>& m) {
00203     typename Row<M,E,S>::template Result<Mat<M,N,ME,CS,RS> >::Mul result;
00204     for (int i=0; i<N; ++i)
00205         result[i] = r*m(i);
00206     return result;
00207 }
00208 
00209     // SYMMAT*VEC, ROW*SYMMAT (conforming)
00210 
00211 // vec = sym * vec (conforming)
00212 template <int N, class ME, int RS, class E, int S> inline
00213 typename SymMat<N,ME,RS>::template Result<Vec<N,E,S> >::Mul
00214 operator*(const SymMat<N,ME,RS>& m,const Vec<N,E,S>& v) {
00215     typename SymMat<N,ME,RS>::template Result<Vec<N,E,S> >::Mul result;
00216     for (int i=0; i<N; ++i) {
00217         result[i] = m.getDiag()[i]*v[i];
00218         for (int j=0; j<i; ++j)
00219             result[i] += m.getEltLower(i,j)*v[j];
00220         for (int j=i+1; j<N; ++j)
00221             result[i] += m.getEltUpper(i,j)*v[j];
00222     }
00223     return result;
00224 }
00225 
00226 // Unroll loops for small cases.
00227 
00228 // 1 flop.
00229 template <class ME, int RS, class E, int S> inline
00230 typename SymMat<1,ME,RS>::template Result<Vec<1,E,S> >::Mul
00231 operator*(const SymMat<1,ME,RS>& m,const Vec<1,E,S>& v) {
00232     typename SymMat<1,ME,RS>::template Result<Vec<1,E,S> >::Mul result;
00233     result[0] = m.getDiag()[0]*v[0];
00234     return result;
00235 }
00236 
00237 // 6 flops.
00238 template <class ME, int RS, class E, int S> inline
00239 typename SymMat<2,ME,RS>::template Result<Vec<2,E,S> >::Mul
00240 operator*(const SymMat<2,ME,RS>& m,const Vec<2,E,S>& v) {
00241     typename SymMat<2,ME,RS>::template Result<Vec<2,E,S> >::Mul result;
00242     result[0] = m.getDiag()[0]    *v[0] + m.getEltUpper(0,1)*v[1];
00243     result[1] = m.getEltLower(1,0)*v[0] + m.getDiag()[1]    *v[1];
00244     return result;
00245 }
00246 
00247 // 15 flops.
00248 template <class ME, int RS, class E, int S> inline
00249 typename SymMat<3,ME,RS>::template Result<Vec<3,E,S> >::Mul
00250 operator*(const SymMat<3,ME,RS>& m,const Vec<3,E,S>& v) {
00251     typename SymMat<3,ME,RS>::template Result<Vec<3,E,S> >::Mul result;
00252     result[0] = m.getDiag()[0]    *v[0] + m.getEltUpper(0,1)*v[1] + m.getEltUpper(0,2)*v[2];
00253     result[1] = m.getEltLower(1,0)*v[0] + m.getDiag()[1]    *v[1] + m.getEltUpper(1,2)*v[2];
00254     result[2] = m.getEltLower(2,0)*v[0] + m.getEltLower(2,1)*v[1] + m.getDiag()[2]    *v[2];
00255     return result;
00256 }
00257 
00258 // row = row * sym (conforming)
00259 template <int M, class E, int S, class ME, int RS> inline
00260 typename Row<M,E,S>::template Result<SymMat<M,ME,RS> >::Mul
00261 operator*(const Row<M,E,S>& r, const SymMat<M,ME,RS>& m) {
00262     typename Row<M,E,S>::template Result<SymMat<M,ME,RS> >::Mul result;
00263     for (int j=0; j<M; ++j) {
00264         result[j] = r[j]*m.getDiag()[j];
00265         for (int i=0; i<j; ++i)
00266             result[j] += r[i]*m.getEltUpper(i,j);
00267         for (int i=j+1; i<M; ++i)
00268             result[j] += r[i]*m.getEltLower(i,j);
00269     }
00270     return result;
00271 }
00272 
00273 // Unroll loops for small cases.
00274 
00275 // 1 flop.
00276 template <class E, int S, class ME, int RS> inline
00277 typename Row<1,E,S>::template Result<SymMat<1,ME,RS> >::Mul
00278 operator*(const Row<1,E,S>& r, const SymMat<1,ME,RS>& m) {
00279     typename Row<1,E,S>::template Result<SymMat<1,ME,RS> >::Mul result;
00280     result[0] = r[0]*m.getDiag()[0];
00281     return result;
00282 }
00283 
00284 // 6 flops.
00285 template <class E, int S, class ME, int RS> inline
00286 typename Row<2,E,S>::template Result<SymMat<2,ME,RS> >::Mul
00287 operator*(const Row<2,E,S>& r, const SymMat<2,ME,RS>& m) {
00288     typename Row<2,E,S>::template Result<SymMat<2,ME,RS> >::Mul result;
00289     result[0] = r[0]*m.getDiag()[0]     + r[1]*m.getEltLower(1,0);
00290     result[1] = r[0]*m.getEltUpper(0,1) + r[1]*m.getDiag()[1];
00291     return result;
00292 }
00293 
00294 // 15 flops.
00295 template <class E, int S, class ME, int RS> inline
00296 typename Row<3,E,S>::template Result<SymMat<3,ME,RS> >::Mul
00297 operator*(const Row<3,E,S>& r, const SymMat<3,ME,RS>& m) {
00298     typename Row<3,E,S>::template Result<SymMat<3,ME,RS> >::Mul result;
00299     result[0] = r[0]*m.getDiag()[0]     + r[1]*m.getEltLower(1,0) + r[2]*m.getEltLower(2,0);
00300     result[1] = r[0]*m.getEltUpper(0,1) + r[1]*m.getDiag()[1]     + r[2]*m.getEltLower(2,1);
00301     result[2] = r[0]*m.getEltUpper(0,2) + r[1]*m.getEltUpper(1,2) + r[2]*m.getDiag()[2];
00302     return result;
00303 }
00304 
00305     // NONCONFORMING MULTIPLY
00306 
00307     // Nonconforming: Vec on left: v*r v*m v*sym v*v
00308     // Result has the shape of the "most composite" (deepest) argument.
00309 
00310 // elementwise multiply (vec * nonconforming row)
00311 template <int M, class E1, int S1, int N, class E2, int S2> inline
00312 typename Vec<M,E1,S1>::template Result<Row<N,E2,S2> >::MulNon
00313 operator*(const Vec<M,E1,S1>& v, const Row<N,E2,S2>& r) {
00314     return Vec<M,E1,S1>::template Result<Row<N,E2,S2> >::MulOpNonConforming::perform(v,r);
00315 }
00316 // elementwise multiply (vec * nonconforming mat)
00317 template <int M, class E1, int S1, int MM, int NN, class E2, int CS2, int RS2> inline
00318 typename Vec<M,E1,S1>::template Result<Mat<MM,NN,E2,CS2,RS2> >::MulNon
00319 operator*(const Vec<M,E1,S1>& v, const Mat<MM,NN,E2,CS2,RS2>& m) {
00320     return Vec<M,E1,S1>::template Result<Mat<MM,NN,E2,CS2,RS2> >
00321                 ::MulOpNonConforming::perform(v,m);
00322 }
00323 // elementwise multiply (vec * nonconforming symmat)
00324 template <int M, class E1, int S1, int MM, class E2, int RS2> inline
00325 typename Vec<M,E1,S1>::template Result<SymMat<MM,E2,RS2> >::MulNon
00326 operator*(const Vec<M,E1,S1>& v, const SymMat<MM,E2,RS2>& m) {
00327     return Vec<M,E1,S1>::template Result<SymMat<MM,E2,RS2> >
00328                 ::MulOpNonConforming::perform(v,m);
00329 }
00330 // elementwise multiply (vec * nonconforming vec)
00331 template <int M, class E1, int S1, int MM, class E2, int S2> inline
00332 typename Vec<M,E1,S1>::template Result<Vec<MM,E2,S2> >::MulNon
00333 operator*(const Vec<M,E1,S1>& v1, const Vec<MM,E2,S2>& v2) {
00334     return Vec<M,E1,S1>::template Result<Vec<MM,E2,S2> >
00335                 ::MulOpNonConforming::perform(v1,v2);
00336 }
00337 
00338     // Nonconforming: Row on left -- r*v r*r r*m r*sym
00339 
00340 
00341 // (row or mat) = row * mat (nonconforming)
00342 template <int M, class E, int S, int MM, int NN, class ME, int CS, int RS> inline
00343 typename Row<M,E,S>::template Result<Mat<MM,NN,ME,CS,RS> >::MulNon
00344 operator*(const Row<M,E,S>& r, const Mat<MM,NN,ME,CS,RS>& m) {
00345     return Row<M,E,S>::template Result<Mat<MM,NN,ME,CS,RS> >
00346         ::MulOpNonConforming::perform(r,m);
00347 }
00348 // (row or vec) = row * vec (nonconforming)
00349 template <int N, class E1, int S1, int M, class E2, int S2> inline
00350 typename Row<N,E1,S1>::template Result<Vec<M,E2,S2> >::MulNon
00351 operator*(const Row<N,E1,S1>& r, const Vec<M,E2,S2>& v) {
00352     return Row<N,E1,S1>::template Result<Vec<M,E2,S2> >
00353         ::MulOpNonConforming::perform(r,v);
00354 }
00355 // (row1 or row2) = row1 * row2(nonconforming)
00356 template <int N1, class E1, int S1, int N2, class E2, int S2> inline
00357 typename Row<N1,E1,S1>::template Result<Row<N2,E2,S2> >::MulNon
00358 operator*(const Row<N1,E1,S1>& r1, const Row<N2,E2,S2>& r2) {
00359     return Row<N1,E1,S1>::template Result<Row<N2,E2,S2> >
00360         ::MulOpNonConforming::perform(r1,r2);
00361 }
00362 
00363     // Nonconforming: Mat on left -- m*v m*r m*sym
00364 
00365 // (mat or vec) = mat * vec (nonconforming)
00366 template <int M, int N, class ME, int CS, int RS, int MM, class E, int S> inline
00367 typename Mat<M,N,ME,CS,RS>::template Result<Vec<MM,E,S> >::MulNon
00368 operator*(const Mat<M,N,ME,CS,RS>& m,const Vec<MM,E,S>& v) {
00369     return Mat<M,N,ME,CS,RS>::template Result<Vec<MM,E,S> >
00370         ::MulOpNonConforming::perform(m,v);
00371 }
00372 // (mat or row) = mat * row (nonconforming)
00373 template <int M, int N, class ME, int CS, int RS, int NN, class E, int S> inline
00374 typename Mat<M,N,ME,CS,RS>::template Result<Row<NN,E,S> >::MulNon
00375 operator*(const Mat<M,N,ME,CS,RS>& m,const Row<NN,E,S>& r) {
00376     return Mat<M,N,ME,CS,RS>::template Result<Row<NN,E,S> >
00377         ::MulOpNonConforming::perform(m,r);
00378 }
00379 
00380 // (mat or sym) = mat * sym (nonconforming)
00381 template <int M, int N, class ME, int CS, int RS, int Dim, class E, int S> inline
00382 typename Mat<M,N,ME,CS,RS>::template Result<SymMat<Dim,E,S> >::MulNon
00383 operator*(const Mat<M,N,ME,CS,RS>& m,const SymMat<Dim,E,S>& sy) {
00384     return Mat<M,N,ME,CS,RS>::template Result<SymMat<Dim,E,S> >
00385         ::MulOpNonConforming::perform(m,sy);
00386 }
00387 
00388     // CROSS PRODUCT
00389 
00390 // Cross product and corresponding operator%, but only for 2- and 3-Vecs
00391 // and Rows. It is OK to mix same-length Vecs & Rows; cross product is
00392 // defined elementwise and never transposes the individual elements.
00393 //
00394 // We also define crossMat(v) below which produces a 2x2 or 3x3
00395 // matrix M such that M*w = v % w for w the same length vector (or row) as v.
00396 // TODO: the 3d crossMat is skew symmetric but currently there is no
00397 // SkewMat class defined so we have to return a full 3x3.
00398 
00399 // For 3d cross product, we'll follow Matlab and make the return type a
00400 // Row if either or both arguments are Rows, although I'm not sure that's
00401 // a good idea! Note that the definition of crossMat means crossMat(r)*v
00402 // will yield a column, while r%v is a Row.
00403 
00404 // We define v % m where v is a 3-vector and m is a 3xN matrix.
00405 // This returns a matrix c of the same dimensions as m where
00406 // column c(i) = v % m(i), that is, each column of c is the cross
00407 // product of v and the corresponding column of m. This definition means that
00408 //      v % m == crossMat(v)*m
00409 // which seems like a good idea. (But note that v%m takes 9*N flops while
00410 // crossMat(v)*m takes 15*N flops.) If we have a row vector r instead,
00411 // we define r % m == v % m so again r%m==crossMat(r)*m. We also
00412 // define the cross product operator with an Mx3 matrix on the left,
00413 // defined so that c[i] = m[i]%v, that is, the rows of c are the
00414 // cross products of the corresonding rows of m and vector v. Again,
00415 // we allow v to be a row without any change to the results or return type.
00416 // This definition means m % v = m * crossMat(v), but again it is faster.
00417 
00418 // v = v % v
00419 template <class E1, int S1, class E2, int S2> inline
00420 Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00421 cross(const Vec<3,E1,S1>& a, const Vec<3,E2,S2>& b) {
00422     return Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00423         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00424 }
00425 template <class E1, int S1, class E2, int S2> inline
00426 Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00427 operator%(const Vec<3,E1,S1>& a, const Vec<3,E2,S2>& b) {return cross(a,b);}
00428 
00429 // r = v % r
00430 template <class E1, int S1, class E2, int S2> inline
00431 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00432 cross(const Vec<3,E1,S1>& a, const Row<3,E2,S2>& b) {
00433     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00434         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00435 }
00436 template <class E1, int S1, class E2, int S2> inline
00437 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00438 operator%(const Vec<3,E1,S1>& a, const Row<3,E2,S2>& b) {return cross(a,b);}
00439 
00440 // r = r % v
00441 template <class E1, int S1, class E2, int S2> inline
00442 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00443 cross(const Row<3,E1,S1>& a, const Vec<3,E2,S2>& b) {
00444     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00445         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00446 }
00447 template <class E1, int S1, class E2, int S2> inline
00448 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00449 operator%(const Row<3,E1,S1>& a, const Vec<3,E2,S2>& b) {return cross(a,b);}
00450 
00451 // r = r % r 
00452 template <class E1, int S1, class E2, int S2> inline
00453 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00454 cross(const Row<3,E1,S1>& a, const Row<3,E2,S2>& b) {
00455     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00456         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00457 }
00458 template <class E1, int S1, class E2, int S2> inline
00459 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00460 operator%(const Row<3,E1,S1>& a, const Row<3,E2,S2>& b) {return cross(a,b);}
00461 
00462 
00463     // Cross a vector with a matrix. The meaning is given by substituting
00464     // the vector's cross product matrix and performing a matrix multiply.
00465     // We implement v % m(3,N) for a full matrix m, and v % s(3,3) for
00466     // a 3x3 symmetric matrix (producing a 3x3 full result). Variants are
00467     // provided with the vector on the right and for when the vector is
00468     // supplied as a row (which doesn't change the result). See above
00469     // for more details.
00470 
00471 // m = v % m
00472 // Cost is 9*N flops.
00473 template <class E1, int S1, int N, class E2, int CS, int RS> inline
00474 Mat<3,N,typename CNT<E1>::template Result<E2>::Mul> // packed
00475 cross(const Vec<3,E1,S1>& v, const Mat<3,N,E2,CS,RS>& m) {
00476     Mat<3,N,typename CNT<E1>::template Result<E2>::Mul> result;
00477     for (int j=0; j < N; ++j)
00478         result(j) = v % m(j);
00479     return result;
00480 }
00481 template <class E1, int S1, int N, class E2, int CS, int RS> inline
00482 Mat<3,N,typename CNT<E1>::template Result<E2>::Mul>
00483 operator%(const Vec<3,E1,S1>& v, const Mat<3,N,E2,CS,RS>& m) {return cross(v,m);}
00484 
00485 // m = v % s
00486 // By writing this out elementwise for the symmetric case we can do this 
00487 // in 24 flops, a small savings over doing three cross products of 9 flops each.
00488 template<class EV, int SV, class EM, int RS> inline
00489 Mat<3,3,typename CNT<EV>::template Result<EM>::Mul> // packed
00490 cross(const Vec<3,EV,SV>& v, const SymMat<3,EM,RS>& s) {
00491     const EV& x=v[0]; const EV& y=v[1]; const EV& z=v[2];
00492     const EM& a=s(0,0);
00493     const EM& b=s(1,0); const EM& d=s(1,1);
00494     const EM& c=s(2,0); const EM& e=s(2,1); const EM& f=s(2,2);
00495 
00496     typedef typename CNT<EV>::template Result<EM>::Mul EResult;
00497     const EResult xe=x*e, yc=y*c, zb=z*b;
00498     return Mat<3,3,EResult>
00499       (  yc-zb,  y*e-z*d, y*f-z*e,
00500         z*a-x*c,  zb-xe,  z*c-x*f,
00501         x*b-y*a, x*d-y*b,  xe-yc );
00502 }
00503 template <class EV, int SV, class EM, int RS> inline
00504 Mat<3,3,typename CNT<EV>::template Result<EM>::Mul>
00505 operator%(const Vec<3,EV,SV>& v, const SymMat<3,EM,RS>& s) {return cross(v,s);}
00506 
00507 // m = r % m
00508 template <class E1, int S1, int N, class E2, int CS, int RS> inline
00509 Mat<3,N,typename CNT<E1>::template Result<E2>::Mul> // packed
00510 cross(const Row<3,E1,S1>& r, const Mat<3,N,E2,CS,RS>& m) {
00511     return cross(r.positionalTranspose(), m);
00512 }
00513 template <class E1, int S1, int N, class E2, int CS, int RS> inline
00514 Mat<3,N,typename CNT<E1>::template Result<E2>::Mul>
00515 operator%(const Row<3,E1,S1>& r, const Mat<3,N,E2,CS,RS>& m) {return cross(r,m);}
00516 
00517 // m = r % s
00518 template<class EV, int SV, class EM, int RS> inline
00519 Mat<3,3,typename CNT<EV>::template Result<EM>::Mul> // packed
00520 cross(const Row<3,EV,SV>& r, const SymMat<3,EM,RS>& s) {
00521     return cross(r.positionalTranspose(), s);
00522 }
00523 template<class EV, int SV, class EM, int RS> inline
00524 Mat<3,3,typename CNT<EV>::template Result<EM>::Mul> // packed
00525 operator%(const Row<3,EV,SV>& r, const SymMat<3,EM,RS>& s) {return cross(r,s);}
00526 
00527 // m = m % v
00528 template <int M, class EM, int CS, int RS, class EV, int S> inline
00529 Mat<M,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00530 cross(const Mat<M,3,EM,CS,RS>& m, const Vec<3,EV,S>& v) {
00531     Mat<M,3,typename CNT<EM>::template Result<EV>::Mul> result;
00532     for (int i=0; i < M; ++i)
00533         result[i] = m[i] % v;
00534     return result;
00535 }
00536 template <int M, class EM, int CS, int RS, class EV, int S> inline
00537 Mat<M,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00538 operator%(const Mat<M,3,EM,CS,RS>& m, const Vec<3,EV,S>& v) {return cross(m,v);}
00539 
00540 // m = s % v
00541 // By writing this out elementwise for the symmetric case we can do this 
00542 // in 24 flops, a small savings over doing three cross products of 9 flops each.
00543 template<class EM, int RS, class EV, int SV> inline
00544 Mat<3,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00545 cross(const SymMat<3,EM,RS>& s, const Vec<3,EV,SV>& v) {
00546     const EV& x=v[0]; const EV& y=v[1]; const EV& z=v[2];
00547     const EM& a=s(0,0);
00548     const EM& b=s(1,0); const EM& d=s(1,1);
00549     const EM& c=s(2,0); const EM& e=s(2,1); const EM& f=s(2,2);
00550 
00551     typedef typename CNT<EV>::template Result<EM>::Mul EResult;
00552     const EResult xe=x*e, yc=y*c, zb=z*b;
00553     return Mat<3,3,EResult>
00554       (  zb-yc,  x*c-z*a, y*a-x*b,
00555         z*d-y*e,  xe-zb,  y*b-x*d,
00556         z*e-y*f, x*f-z*c,  yc-xe );
00557 }
00558 template<class EM, int RS, class EV, int SV> inline
00559 Mat<3,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00560 operator%(const SymMat<3,EM,RS>& s, const Vec<3,EV,SV>& v) {return cross(s,v);}
00561 
00562 // m = m % r
00563 template <int M, class EM, int CS, int RS, class ER, int S> inline
00564 Mat<M,3,typename CNT<EM>::template Result<ER>::Mul> // packed
00565 cross(const Mat<M,3,EM,CS,RS>& m, const Row<3,ER,S>& r) {
00566     return cross(m,r.positionalTranspose());
00567 }
00568 template <int M, class EM, int CS, int RS, class ER, int S> inline
00569 Mat<M,3,typename CNT<EM>::template Result<ER>::Mul> // packed
00570 operator%(const Mat<M,3,EM,CS,RS>& m, const Row<3,ER,S>& r) {return cross(m,r);}
00571 
00572 // m = s % r
00573 template<class EM, int RS, class EV, int SV> inline
00574 Mat<3,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00575 cross(const SymMat<3,EM,RS>& s, const Row<3,EV,SV>& r) {
00576     return cross(s,r.positionalTranspose());
00577 }
00578 template<class EM, int RS, class EV, int SV> inline
00579 Mat<3,3,typename CNT<EM>::template Result<EV>::Mul> // packed
00580 operator%(const SymMat<3,EM,RS>& s, const Row<3,EV,SV>& r) {return cross(s,r);}
00581 
00582 // 2d cross product just returns a scalar. This is the z-value you
00583 // would get if the arguments were treated as 3-vectors with 0
00584 // z components.
00585 
00586 template <class E1, int S1, class E2, int S2> inline
00587 typename CNT<E1>::template Result<E2>::Mul
00588 cross(const Vec<2,E1,S1>& a, const Vec<2,E2,S2>& b) {
00589     return a[0]*b[1]-a[1]*b[0];
00590 }
00591 template <class E1, int S1, class E2, int S2> inline
00592 typename CNT<E1>::template Result<E2>::Mul
00593 operator%(const Vec<2,E1,S1>& a, const Vec<2,E2,S2>& b) {return cross(a,b);}
00594 
00595 template <class E1, int S1, class E2, int S2> inline
00596 typename CNT<E1>::template Result<E2>::Mul
00597 cross(const Row<2,E1,S1>& a, const Vec<2,E2,S2>& b) {
00598     return a[0]*b[1]-a[1]*b[0];
00599 }
00600 template <class E1, int S1, class E2, int S2> inline
00601 typename CNT<E1>::template Result<E2>::Mul
00602 operator%(const Row<2,E1,S1>& a, const Vec<2,E2,S2>& b) {return cross(a,b);}
00603 
00604 template <class E1, int S1, class E2, int S2> inline
00605 typename CNT<E1>::template Result<E2>::Mul
00606 cross(const Vec<2,E1,S1>& a, const Row<2,E2,S2>& b) {
00607     return a[0]*b[1]-a[1]*b[0];
00608 }
00609 template <class E1, int S1, class E2, int S2> inline
00610 typename CNT<E1>::template Result<E2>::Mul
00611 operator%(const Vec<2,E1,S1>& a, const Row<2,E2,S2>& b) {return cross(a,b);}
00612 
00613 template <class E1, int S1, class E2, int S2> inline
00614 typename CNT<E1>::template Result<E2>::Mul
00615 cross(const Row<2,E1,S1>& a, const Row<2,E2,S2>& b) {
00616     return a[0]*b[1]-a[1]*b[0];
00617 }
00618 template <class E1, int S1, class E2, int S2> inline
00619 typename CNT<E1>::template Result<E2>::Mul
00620 operator%(const Row<2,E1,S1>& a, const Row<2,E2,S2>& b) {return cross(a,b);}
00621 
00622     // CROSS MAT
00623 
00627 template <class E, int S> inline
00628 Mat<3,3,E>
00629 crossMat(const Vec<3,E,S>& v) {
00630     return Mat<3,3,E>(Row<3,E>( E(0), -v[2],  v[1]),
00631                       Row<3,E>( v[2],  E(0), -v[0]),
00632                       Row<3,E>(-v[1],  v[0],  E(0)));
00633 }
00636 template <class E, int S> inline
00637 Mat<3,3,E>
00638 crossMat(const Vec<3,negator<E>,S>& v) {
00639     // Here the "-" operators are just recasts, but the casts
00640     // to type E have to perform floating point negations.
00641     return Mat<3,3,E>(Row<3,E>( E(0),   -v[2],    E(v[1])),
00642                       Row<3,E>( E(v[2]), E(0),   -v[0]),
00643                       Row<3,E>(-v[1],    E(v[0]), E(0)));
00644 }
00645 
00647 template <class E, int S> inline
00648 Mat<3,3,E> crossMat(const Row<3,E,S>& r) {return crossMat(r.positionalTranspose());}
00650 template <class E, int S> inline
00651 Mat<3,3,E> crossMat(const Row<3,negator<E>,S>& r) {return crossMat(r.positionalTranspose());}
00652 
00656 template <class E, int S> inline
00657 Row<2,E> crossMat(const Vec<2,E,S>& v) {
00658     return Row<2,E>(-v[1], v[0]);
00659 }
00661 template <class E, int S> inline
00662 Row<2,E> crossMat(const Vec<2,negator<E>,S>& v) {
00663     return Row<2,E>(-v[1], E(v[0]));
00664 }
00665 
00667 template <class E, int S> inline
00668 Row<2,E> crossMat(const Row<2,E,S>& r) {return crossMat(r.positionalTranspose());}
00670 template <class E, int S> inline
00671 Row<2,E> crossMat(const Row<2,negator<E>,S>& r) {return crossMat(r.positionalTranspose());}
00672 
00673     // CROSS MAT SQ
00674 
00694 template <class E, int S> inline
00695 SymMat<3,E>
00696 crossMatSq(const Vec<3,E,S>& v) {
00697     const E xx = square(v[0]);
00698     const E yy = square(v[1]);
00699     const E zz = square(v[2]);
00700     const E nx = -v[0];
00701     const E ny = -v[1];
00702     return SymMat<3,E>( yy+zz,
00703                         nx*v[1], xx+zz,
00704                         nx*v[2], ny*v[2], xx+yy );
00705 }
00706 // Specialize above for negated types. Returned matrix loses negator.
00707 // The total number of flops here is the same as above: 11 flops.
00708 template <class E, int S> inline
00709 SymMat<3,E>
00710 crossMatSq(const Vec<3,negator<E>,S>& v) {
00711     const E xx = square(v[0]);
00712     const E yy = square(v[1]);
00713     const E zz = square(v[2]);
00714     const E y = v[1]; // requires a negation to convert to E
00715     const E z = v[2];
00716     // The negations in the arguments below are not floating point
00717     // operations because the element type is already negated.
00718     return SymMat<3,E>( yy+zz,
00719                         -v[0]*y,  xx+zz,
00720                         -v[0]*z, -v[1]*z, xx+yy );
00721 }
00722 
00723 template <class E, int S> inline
00724 SymMat<3,E> crossMatSq(const Row<3,E,S>& r) {return crossMatSq(r.positionalTranspose());}
00725 template <class E, int S> inline
00726 SymMat<3,E> crossMatSq(const Row<3,negator<E>,S>& r) {return crossMatSq(r.positionalTranspose());}
00727 
00728 
00729     // DETERMINANT
00730 
00732 template <class E, int CS, int RS> inline
00733 E det(const Mat<1,1,E,CS,RS>& m) {
00734     return m(0,0);
00735 }
00736 
00738 template <class E, int RS> inline
00739 E det(const SymMat<1,E,RS>& s) {
00740     return s.diag()[0]; // s(0,0) is trouble for a 1x1 symmetric
00741 }
00742 
00744 template <class E, int CS, int RS> inline
00745 E det(const Mat<2,2,E,CS,RS>& m) {
00746     // Constant element indices here allow the compiler to select
00747     // exactly the right element at compile time.
00748     return E(m(0,0)*m(1,1) - m(0,1)*m(1,0));
00749 }
00750 
00752 template <class E, int RS> inline
00753 E det(const SymMat<2,E,RS>& s) {
00754     // For Hermitian matrix (i.e., E is complex or conjugate), s(0,1) 
00755     // and s(1,0) are complex conjugates of one another. Because of the
00756     // constant indices here, the SymMat goes right to the correct
00757     // element, so everything gets done inline here with no conditionals.
00758     return E(s.getEltDiag(0)*s.getEltDiag(1) - s.getEltUpper(0,1)*s.getEltLower(1,0));
00759 }
00760 
00762 template <class E, int CS, int RS> inline
00763 E det(const Mat<3,3,E,CS,RS>& m) {
00764     return E(  m(0,0)*(m(1,1)*m(2,2)-m(1,2)*m(2,1))
00765              - m(0,1)*(m(1,0)*m(2,2)-m(1,2)*m(2,0))
00766              + m(0,2)*(m(1,0)*m(2,1)-m(1,1)*m(2,0)));
00767 }
00768 
00770 template <class E, int RS> inline
00771 E det(const SymMat<3,E,RS>& s) {
00772     return E(  s.getEltDiag(0)*
00773                 (s.getEltDiag(1)*s.getEltDiag(2)-s.getEltUpper(1,2)*s.getEltLower(2,1))
00774              - s.getEltUpper(0,1)*
00775                 (s.getEltLower(1,0)*s.getEltDiag(2)-s.getEltUpper(1,2)*s.getEltLower(2,0))
00776              + s.getEltUpper(0,2)*
00777                 (s.getEltLower(1,0)*s.getEltLower(2,1)-s.getEltDiag(1)*s.getEltLower(2,0)));
00778 }
00779 
00793 template <int M, class E, int CS, int RS> inline
00794 E det(const Mat<M,M,E,CS,RS>& m) {
00795     typename CNT<E>::StdNumber sign(1);
00796     E                          result(0);
00797     // We're always going to drop the first row.
00798     const Mat<M-1,M,E,CS,RS>& m2 = m.template getSubMat<M-1,M>(1,0);
00799     for (int j=0; j < M; ++j) {
00800         // det() here is recursive but terminates at 3x3 above.
00801         result += sign*m(0,j)*det(m2.dropCol(j));
00802         sign = -sign;
00803     }
00804     return result;
00805 }
00806 
00812 template <int M, class E, int RS> inline
00813 E det(const SymMat<M,E,RS>& s) {
00814     return det(Mat<M,M,E>(s));
00815 }
00816 
00817 
00818     // INVERSE
00819 
00821 template <class E, int CS, int RS> inline
00822 typename Mat<1,1,E,CS,RS>::TInvert lapackInverse(const Mat<1,1,E,CS,RS>& m) {
00823     typedef typename Mat<1,1,E,CS,RS>::TInvert MInv;
00824     return MInv( E(typename CNT<E>::StdNumber(1)/m(0,0)) );
00825 }
00826 
00837 template <int M, class E, int CS, int RS> inline
00838 typename Mat<M,M,E,CS,RS>::TInvert lapackInverse(const Mat<M,M,E,CS,RS>& m) {
00839     // Copy the source matrix, which has arbitrary row and column spacing,
00840     // into the type for its inverse, which must be dense, columnwise
00841     // storage. That means its column spacing will be M and row spacing
00842     // will be 1, as Lapack expects for a Full matrix.
00843     typename Mat<M,M,E,CS,RS>::TInvert inv = m; // dense, columnwise storage
00844 
00845     // We'll perform the inversion ignoring negation and conjugation altogether, 
00846     // but the TInvert Mat type negates or conjugates the result. And because 
00847     // of the famous Sherman-Eastman theorem, we know that 
00848     // conj(inv(m))==inv(conj(m)), and of course -inv(m)==inv(-m).
00849     typedef typename CNT<E>::StdNumber Raw;   // Raw is E without negator or conjugate.
00850     Raw* rawData = reinterpret_cast<Raw*>(&inv(0,0));
00851     int ipiv[M], info;
00852 
00853     // This replaces "inv" with its LU facorization and pivot matrix P, such that
00854     // P*L*U = m (ignoring negation and conjugation).
00855     Lapack::getrf<Raw>(M,M,rawData,M,&ipiv[0],info);
00856     SimTK_ASSERT1(info>=0, "Argument %d to Lapack getrf routine was bad", -info);
00857     SimTK_ERRCHK1_ALWAYS(info==0, "lapackInverse(Mat<>)",
00858         "Matrix is singular so can't be inverted (Lapack getrf info=%d).", info);
00859 
00860     // The workspace size must be at least M. For larger matrices, Lapack wants
00861     // to do factorization in blocks of size NB in which case the workspace should
00862     // be M*NB. However, we will assume that this matrix is small (in the sense
00863     // that it fits entirely in cache) so the minimum workspace size is fine and
00864     // we don't need an extra getri call to find the workspace size nor any heap
00865     // allocation.
00866 
00867     Raw work[M];
00868     Lapack::getri<Raw>(M,rawData,M,&ipiv[0],&work[0],M,info);
00869     SimTK_ASSERT1(info>=0, "Argument %d to Lapack getri routine was bad", -info);
00870     SimTK_ERRCHK1_ALWAYS(info==0, "lapackInverse(Mat<>)",
00871         "Matrix is singular so can't be inverted (Lapack getri info=%d).", info);
00872     return inv;
00873 }
00874 
00875 
00877 template <class E, int CS, int RS> inline
00878 typename Mat<1,1,E,CS,RS>::TInvert inverse(const Mat<1,1,E,CS,RS>& m) {
00879     typedef typename Mat<1,1,E,CS,RS>::TInvert MInv;
00880     return MInv( E(typename CNT<E>::StdNumber(1)/m(0,0)) );
00881 }
00882 
00884 template <class E, int RS> inline
00885 typename SymMat<1,E,RS>::TInvert inverse(const SymMat<1,E,RS>& s) {
00886     typedef typename SymMat<1,E,RS>::TInvert SInv;
00887     return SInv( E(typename CNT<E>::StdNumber(1)/s.diag()[0]) );
00888 }
00889 
00891 template <class E, int CS, int RS> inline
00892 typename Mat<2,2,E,CS,RS>::TInvert inverse(const Mat<2,2,E,CS,RS>& m) {
00893     const E               d  ( det(m) );
00894     const typename CNT<E>::TInvert ood( typename CNT<E>::StdNumber(1)/d );
00895     return typename Mat<2,2,E,CS,RS>::TInvert( E( ood*m(1,1)), E(-ood*m(0,1)),
00896                                                E(-ood*m(1,0)), E( ood*m(0,0)));
00897 }
00898 
00900 template <class E, int RS> inline
00901 typename SymMat<2,E,RS>::TInvert inverse(const SymMat<2,E,RS>& s) {
00902     const E               d  ( det(s) );
00903     const typename CNT<E>::TInvert ood( typename CNT<E>::StdNumber(1)/d );
00904     return typename SymMat<2,E,RS>::TInvert( E( ood*s(1,1)),
00905                                              E(-ood*s(1,0)), E(ood*s(0,0)));
00906 }
00907 
00912 template <class E, int CS, int RS> inline
00913 typename Mat<3,3,E,CS,RS>::TInvert inverse(const Mat<3,3,E,CS,RS>& m) {
00914     // Calculate determinants for each 2x2 submatrix with first row removed.
00915     // (See the specialized 3x3 determinant routine above.) We're calculating
00916     // this explicitly here because we can re-use the intermediate terms.
00917     const E d00 (m(1,1)*m(2,2)-m(1,2)*m(2,1)),
00918             nd01(m(1,2)*m(2,0)-m(1,0)*m(2,2)),   // -d01
00919             d02 (m(1,0)*m(2,1)-m(1,1)*m(2,0));
00920 
00921     // This is the 3x3 determinant and its inverse.
00922     const E d  (m(0,0)*d00 + m(0,1)*nd01 + m(0,2)*d02);
00923     const typename CNT<E>::TInvert 
00924             ood(typename CNT<E>::StdNumber(1)/d);
00925 
00926     // The other six 2x2 determinants we can't re-use, but we can still
00927     // avoid some copying by calculating them explicitly here.
00928     const E nd10(m(0,2)*m(2,1)-m(0,1)*m(2,2)),  // -d10
00929             d11 (m(0,0)*m(2,2)-m(0,2)*m(2,0)),
00930             nd12(m(0,1)*m(2,0)-m(0,0)*m(2,1)),  // -d12
00931             d20 (m(0,1)*m(1,2)-m(0,2)*m(1,1)),
00932             nd21(m(0,2)*m(1,0)-m(0,0)*m(1,2)),  // -d21
00933             d22 (m(0,0)*m(1,1)-m(0,1)*m(1,0));
00934 
00935     return typename Mat<3,3,E,CS,RS>::TInvert
00936        ( E(ood* d00), E(ood*nd10), E(ood* d20),
00937          E(ood*nd01), E(ood* d11), E(ood*nd21),
00938          E(ood* d02), E(ood*nd12), E(ood* d22) ); 
00939 }
00940 
00946 template <class E, int RS> inline
00947 typename SymMat<3,E,RS>::TInvert inverse(const SymMat<3,E,RS>& s) {
00948     // Calculate determinants for each 2x2 submatrix with first row removed.
00949     // (See the specialized 3x3 determinant routine above.) We're calculating
00950     // this explicitly here because we can re-use the intermediate terms.
00951     const E d00 (s(1,1)*s(2,2)-s(1,2)*s(2,1)),
00952             nd01(s(1,2)*s(2,0)-s(1,0)*s(2,2)),   // -d01
00953             d02 (s(1,0)*s(2,1)-s(1,1)*s(2,0));
00954 
00955     // This is the 3x3 determinant and its inverse.
00956     const E d  (s(0,0)*d00 + s(0,1)*nd01 + s(0,2)*d02);
00957     const typename CNT<E>::TInvert 
00958             ood(typename CNT<E>::StdNumber(1)/d);
00959 
00960     // The other six 2x2 determinants we can't re-use, but we can still
00961     // avoid some copying by calculating them explicitly here.
00962     const E d11 (s(0,0)*s(2,2)-s(0,2)*s(2,0)),
00963             nd12(s(0,1)*s(2,0)-s(0,0)*s(2,1)),  // -d12
00964             d22 (s(0,0)*s(1,1)-s(0,1)*s(1,0));
00965 
00966     return typename SymMat<3,E,RS>::TInvert
00967        ( E(ood* d00), 
00968          E(ood*nd01), E(ood* d11), 
00969          E(ood* d02), E(ood*nd12), E(ood* d22) ); 
00970 }
00971 
00974 template <int M, class E, int CS, int RS> inline
00975 typename Mat<M,M,E,CS,RS>::TInvert inverse(const Mat<M,M,E,CS,RS>& m) {
00976     return lapackInverse(m);
00977 }
00978 
00979 // Implement the Mat<>::invert() method using the above specialized 
00980 // inverse functions. This will only compile if M==N.
00981 template <int M, int N, class ELT, int CS, int RS> inline
00982 typename Mat<M,N,ELT,CS,RS>::TInvert 
00983 Mat<M,N,ELT,CS,RS>::invert() const {
00984     return SimTK::inverse(*this);
00985 }
00986 
00987 } //namespace SimTK
00988 
00989 
00990 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines