Simbody
3.4 (development)
|
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_