Simbody
|
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_