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