SmallMatrixMixed.h

Go to the documentation of this file.
00001 #ifndef SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_
00002 #define SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTK Simmatrix(tm)                       *
00006  * -------------------------------------------------------------------------- *
00007  * This is part of the SimTK Core biosimulation toolkit originating from      *
00008  * Simbios, the NIH National Center for Physics-Based Simulation of           *
00009  * Biological Structures at Stanford, funded under the NIH Roadmap for        *
00010  * Medical Research, grant U54 GM072970. See https://simtk.org.               *
00011  *                                                                            *
00012  * Portions copyright (c) 2005-7 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 
00040 namespace SimTK {
00041 
00042     // DOT PRODUCT
00043 
00044 // Dot product and corresponding infix operator*(). Note that
00045 // the '*' operator is just a matrix multiply so is strictly 
00046 // row*column to produce a scalar (1x1) result.
00047 //
00048 // In keeping with Matlab precedent, however, the explicit dot()
00049 // function is defined on two column vectors
00050 // v and w such that dot(v,w)= ~v * w. That means we use the
00051 // Hermitian transpose of the elements of v, and the elements of
00052 // w unchanged. If v and/or w are rows, we first convert them
00053 // to vectors via *positional* transpose. So no matter what shape
00054 // these have on the way in it is always the Hermitian transpose
00055 // (or complex conjugate for scalars) of the first item times
00056 // the unchanged elements of the second item.
00057 
00058 
00059 template <int M, class E1, int S1, class E2, int S2> inline
00060 typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul 
00061 dot(const Vec<M,E1,S1>& r, const Vec<M,E2,S2>& v) {
00062     typename CNT<typename CNT<E1>::THerm>::template Result<E2>::Mul sum(0);
00063     for (int i=0; i<M; ++i)
00064         sum += CNT<E1>::transpose(r[i])*v[i];
00065     return sum;
00066 }
00067 
00068 // dot product (row * conforming vec)
00069 template <int N, class E1, int S1, class E2, int S2> inline
00070 typename CNT<E1>::template Result<E2>::Mul 
00071 operator*(const Row<N,E1,S1>& r, const Vec<N,E2,S2>& v) {
00072     typename CNT<E1>::template Result<E2>::Mul sum(0);
00073     for (int i=0; i<N; ++i)
00074         sum += r[i]*v[i];
00075     return sum;
00076 }
00077 
00078 // Alternate acceptable forms for dot().
00079 template <int N, class E1, int S1, class E2, int S2> inline
00080 typename CNT<E1>::template Result<E2>::Mul 
00081 dot(const Row<N,E1,S1>& r, const Vec<N,E2,S2>& v) {
00082     return dot(r.positionalTranspose(),v);
00083 }
00084 template <int M, class E1, int S1, class E2, int S2> inline
00085 typename CNT<E1>::template Result<E2>::Mul 
00086 dot(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00087     return dot(v,r.positionalTranspose());
00088 }
00089 template <int N, class E1, int S1, class E2, int S2> inline
00090 typename CNT<E1>::template Result<E2>::Mul 
00091 dot(const Row<N,E1,S1>& r, const Row<N,E2,S2>& s) {
00092     return dot(r.positionalTranspose(),s.positionalTranspose());
00093 }
00094 
00095     // OUTER PRODUCT
00096 
00097 // Outer product and corresponding infix operator*(). Note that
00098 // the '*' operator is just a matrix multiply so is strictly 
00099 // column_mX1 * row_1Xm to produce an mXm matrix result.
00100 //
00101 // Although Matlab doesn't provide outer(), to be consistent
00102 // we'll treat it as discussed for dot() above. That is, outer
00103 // is defined on two column vectors
00104 // v and w such that outer(v,w)= v * ~w. That means we use the
00105 // elements of v unchanged but use the Hermitian transpose of
00106 // the elements of w. If v and/or w are rows, we first convert them
00107 // to vectors via *positional* transpose. So no matter what shape
00108 // these have on the way in it is always the unchanged elements of
00109 // the first item times the Hermitian transpose (or complex
00110 // conjugate for scalars) of the elements of the second item.
00111 
00112 template <int M, class E1, int S1, class E2, int S2> inline
00113 Mat<M,M, typename CNT<E1>::template Result<typename CNT<E2>::THerm>::Mul>
00114 outer(const Vec<M,E1,S1>& v, const Vec<M,E2,S2>& w) {
00115     Mat<M,M, typename CNT<E1>::template Result<typename CNT<E2>::THerm>::Mul> m;
00116     for (int i=0; i<M; ++i)
00117         m[i] = v[i] * ~w;
00118     return m;
00119 }
00120 
00121 // This is the general conforming case of Vec*Row (outer product)
00122 template <int M, class E1, int S1, class E2, int S2> inline
00123 typename Vec<M,E1,S1>::template Result<Row<M,E2,S2> >::Mul
00124 operator*(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00125     return Vec<M,E1,S1>::template Result<Row<M,E2,S2> >::MulOp::perform(v,r);
00126 }
00127 
00128 
00129 // Alternate acceptable forms for outer().
00130 template <int M, class E1, int S1, class E2, int S2> inline
00131 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00132 outer(const Vec<M,E1,S1>& v, const Row<M,E2,S2>& r) {
00133     return outer(v,r.positionalTranspose());
00134 }
00135 template <int M, class E1, int S1, class E2, int S2> inline
00136 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00137 outer(const Row<M,E1,S1>& r, const Vec<M,E2,S2>& v) {
00138     return outer(r.positionalTranspose(),v);
00139 }
00140 template <int M, class E1, int S1, class E2, int S2> inline
00141 Mat<M,M, typename CNT<E1>::template Result<E2>::Mul>
00142 outer(const Row<M,E1,S1>& r, const Row<M,E2,S2>& s) {
00143     return outer(r.positionalTranspose(),s.positionalTranspose());
00144 }
00145 
00146     // MAT*VEC, ROW*MAT (conforming)
00147 
00148 // vec = mat * vec (conforming)
00149 template <int M, int N, class ME, int CS, int RS, class E, int S> inline
00150 typename Mat<M,N,ME,CS,RS>::template Result<Vec<N,E,S> >::Mul
00151 operator*(const Mat<M,N,ME,CS,RS>& m,const Vec<N,E,S>& v) {
00152     typename Mat<M,N,ME,CS,RS>::template Result<Vec<N,E,S> >::Mul result;
00153     for (int i=0; i<M; ++i)
00154         result[i] = m[i]*v;
00155     return result;
00156 }
00157 
00158 // row = row * mat (conforming)
00159 template <int M, class E, int S, int N, class ME, int CS, int RS> inline
00160 typename Row<M,E,S>::template Result<Mat<M,N,ME,CS,RS> >::Mul
00161 operator*(const Row<M,E,S>& r, const Mat<M,N,ME,CS,RS>& m) {
00162     typename Row<M,E,S>::template Result<Mat<M,N,ME,CS,RS> >::Mul result;
00163     for (int i=0; i<N; ++i)
00164         result[i] = r*m(i);
00165     return result;
00166 }
00167 
00168     // NONCONFORMING MULTIPLY
00169 
00170     // Nonconforming: Vec on left: v*r v*m v*sym v*v
00171     // Result has the shape of the "most composite" (deepest) argument.
00172 
00173 // elementwise multiply (vec * nonconforming row)
00174 template <int M, class E1, int S1, int N, class E2, int S2> inline
00175 typename Vec<M,E1,S1>::template Result<Row<N,E2,S2> >::MulNon
00176 operator*(const Vec<M,E1,S1>& v, const Row<N,E2,S2>& r) {
00177     return Vec<M,E1,S1>::template Result<Row<N,E2,S2> >::MulOpNonConforming::perform(v,r);
00178 }
00179 // elementwise multiply (vec * nonconforming mat)
00180 template <int M, class E1, int S1, int MM, int NN, class E2, int CS2, int RS2> inline
00181 typename Vec<M,E1,S1>::template Result<Mat<MM,NN,E2,CS2,RS2> >::MulNon
00182 operator*(const Vec<M,E1,S1>& v, const Mat<MM,NN,E2,CS2,RS2>& m) {
00183     return Vec<M,E1,S1>::template Result<Mat<MM,NN,E2,CS2,RS2> >
00184                 ::MulOpNonConforming::perform(v,m);
00185 }
00186 // elementwise multiply (vec * nonconforming symmat)
00187 template <int M, class E1, int S1, int MM, class E2, int RS2> inline
00188 typename Vec<M,E1,S1>::template Result<SymMat<MM,E2,RS2> >::MulNon
00189 operator*(const Vec<M,E1,S1>& v, const SymMat<MM,E2,RS2>& m) {
00190     return Vec<M,E1,S1>::template Result<SymMat<MM,E2,RS2> >
00191                 ::MulOpNonConforming::perform(v,m);
00192 }
00193 // elementwise multiply (vec * nonconforming vec)
00194 template <int M, class E1, int S1, int MM, class E2, int S2> inline
00195 typename Vec<M,E1,S1>::template Result<Vec<MM,E2,S2> >::MulNon
00196 operator*(const Vec<M,E1,S1>& v1, const Vec<MM,E2,S2>& v2) {
00197     return Vec<M,E1,S1>::template Result<Vec<MM,E2,S2> >
00198                 ::MulOpNonConforming::perform(v1,v2);
00199 }
00200 
00201     // Nonconforming: Row on left -- r*v r*r r*m r*sym
00202 
00203 
00204 // (row or mat) = row * mat (nonconforming)
00205 template <int M, class E, int S, int MM, int NN, class ME, int CS, int RS> inline
00206 typename Row<M,E,S>::template Result<Mat<MM,NN,ME,CS,RS> >::MulNon
00207 operator*(const Row<M,E,S>& r, const Mat<MM,NN,ME,CS,RS>& m) {
00208     return Row<M,E,S>::template Result<Mat<MM,NN,ME,CS,RS> >
00209         ::MulOpNonConforming::perform(r,m);
00210 }
00211 // (row or vec) = row * vec (nonconforming)
00212 template <int N, class E1, int S1, int M, class E2, int S2> inline
00213 typename Row<N,E1,S1>::template Result<Vec<M,E2,S2> >::MulNon
00214 operator*(const Row<N,E1,S1>& r, const Vec<M,E2,S2>& v) {
00215     return Row<N,E1,S1>::template Result<Vec<M,E2,S2> >
00216         ::MulOpNonConforming::perform(r,v);
00217 }
00218 // (row1 or row2) = row1 * row2(nonconforming)
00219 template <int N1, class E1, int S1, int N2, class E2, int S2> inline
00220 typename Row<N1,E1,S1>::template Result<Row<N2,E2,S2> >::MulNon
00221 operator*(const Row<N1,E1,S1>& r1, const Row<N2,E2,S2>& r2) {
00222     return Row<N1,E1,S1>::template Result<Row<N2,E2,S2> >
00223         ::MulOpNonConforming::perform(r1,r2);
00224 }
00225 
00226     // Nonconforming: Mat on left -- m*v m*r m*sym
00227 
00228 // (mat or vec) = mat * vec (nonconforming)
00229 template <int M, int N, class ME, int CS, int RS, int MM, class E, int S> inline
00230 typename Mat<M,N,ME,CS,RS>::template Result<Vec<MM,E,S> >::MulNon
00231 operator*(const Mat<M,N,ME,CS,RS>& m,const Vec<MM,E,S>& v) {
00232     return Mat<M,N,ME,CS,RS>::template Result<Vec<MM,E,S> >
00233         ::MulOpNonConforming::perform(m,v);
00234 }
00235 // (mat or row) = mat * row (nonconforming)
00236 template <int M, int N, class ME, int CS, int RS, int NN, class E, int S> inline
00237 typename Mat<M,N,ME,CS,RS>::template Result<Row<NN,E,S> >::MulNon
00238 operator*(const Mat<M,N,ME,CS,RS>& m,const Row<NN,E,S>& r) {
00239     return Mat<M,N,ME,CS,RS>::template Result<Row<NN,E,S> >
00240         ::MulOpNonConforming::perform(m,r);
00241 }
00242 
00243 // (mat or sym) = mat * sym (nonconforming)
00244 template <int M, int N, class ME, int CS, int RS, int Dim, class E, int S> inline
00245 typename Mat<M,N,ME,CS,RS>::template Result<SymMat<Dim,E,S> >::MulNon
00246 operator*(const Mat<M,N,ME,CS,RS>& m,const SymMat<Dim,E,S>& sy) {
00247     return Mat<M,N,ME,CS,RS>::template Result<SymMat<Dim,E,S> >
00248         ::MulOpNonConforming::perform(m,sy);
00249 }
00250 
00251     // CROSS PRODUCT
00252 
00253 // Cross product and corresponding operator%, but only for 2- and 3-Vecs
00254 // and Rows. It is OK to mix same-length Vecs & Rows; cross product is
00255 // defined elementwise and never transposes the individual elements.
00256 //
00257 // We also define crossMat(v) below which produces a 2x2 or 3x3
00258 // matrix M such that M*w = v % w for w the same length vector (or row) as v.
00259 // TODO: the 3d crossMat is skew symmetric but currently there is no
00260 // SkewMat class defined so we have to return a full 3x3.
00261 
00262 // For 3d cross product, we'll follow Matlab and make the return type a
00263 // Row if either or both arguments are Rows, although I'm not sure that's
00264 // a good idea! Note that the definition of crossMat means crossMat(r)*v
00265 // will yield a column, while r%v is a Row.
00266 
00267 template <class E1, int S1, class E2, int S2> inline
00268 Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00269 cross(const Vec<3,E1,S1>& a, const Vec<3,E2,S2>& b) {
00270     return Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00271         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00272 }
00273 template <class E1, int S1, class E2, int S2> inline
00274 Vec<3,typename CNT<E1>::template Result<E2>::Mul>
00275 operator%(const Vec<3,E1,S1>& a, const Vec<3,E2,S2>& b) {return cross(a,b);}
00276 
00277 template <class E1, int S1, class E2, int S2> inline
00278 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00279 cross(const Vec<3,E1,S1>& a, const Row<3,E2,S2>& b) {
00280     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00281         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00282 }
00283 template <class E1, int S1, class E2, int S2> inline
00284 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00285 operator%(const Vec<3,E1,S1>& a, const Row<3,E2,S2>& b) {return cross(a,b);}
00286 
00287 template <class E1, int S1, class E2, int S2> inline
00288 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00289 cross(const Row<3,E1,S1>& a, const Vec<3,E2,S2>& b) {
00290     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00291         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00292 }
00293 template <class E1, int S1, class E2, int S2> inline
00294 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00295 operator%(const Row<3,E1,S1>& a, const Vec<3,E2,S2>& b) {return cross(a,b);}
00296 
00297 template <class E1, int S1, class E2, int S2> inline
00298 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00299 cross(const Row<3,E1,S1>& a, const Row<3,E2,S2>& b) {
00300     return Row<3,typename CNT<E1>::template Result<E2>::Mul>
00301         (a[1]*b[2]-a[2]*b[1], a[2]*b[0]-a[0]*b[2], a[0]*b[1]-a[1]*b[0]);
00302 }
00303 template <class E1, int S1, class E2, int S2> inline
00304 Row<3,typename CNT<E1>::template Result<E2>::Mul>
00305 operator%(const Row<3,E1,S1>& a, const Row<3,E2,S2>& b) {return cross(a,b);}
00306 
00307 // 2d cross product just returns a scalar. This is the z-value you
00308 // would get if the arguments were treated as 3-vectors with 0
00309 // z components.
00310 
00311 template <class E1, int S1, class E2, int S2> inline
00312 typename CNT<E1>::template Result<E2>::Mul
00313 cross(const Vec<2,E1,S1>& a, const Vec<2,E2,S2>& b) {
00314     return a[0]*b[1]-a[1]*b[0];
00315 }
00316 template <class E1, int S1, class E2, int S2> inline
00317 typename CNT<E1>::template Result<E2>::Mul
00318 operator%(const Vec<2,E1,S1>& a, const Vec<2,E2,S2>& b) {return cross(a,b);}
00319 
00320 template <class E1, int S1, class E2, int S2> inline
00321 typename CNT<E1>::template Result<E2>::Mul
00322 cross(const Row<2,E1,S1>& a, const Vec<2,E2,S2>& b) {
00323     return a[0]*b[1]-a[1]*b[0];
00324 }
00325 template <class E1, int S1, class E2, int S2> inline
00326 typename CNT<E1>::template Result<E2>::Mul
00327 operator%(const Row<2,E1,S1>& a, const Vec<2,E2,S2>& b) {return cross(a,b);}
00328 
00329 template <class E1, int S1, class E2, int S2> inline
00330 typename CNT<E1>::template Result<E2>::Mul
00331 cross(const Vec<2,E1,S1>& a, const Row<2,E2,S2>& b) {
00332     return a[0]*b[1]-a[1]*b[0];
00333 }
00334 template <class E1, int S1, class E2, int S2> inline
00335 typename CNT<E1>::template Result<E2>::Mul
00336 operator%(const Vec<2,E1,S1>& a, const Row<2,E2,S2>& b) {return cross(a,b);}
00337 
00338 template <class E1, int S1, class E2, int S2> inline
00339 typename CNT<E1>::template Result<E2>::Mul
00340 cross(const Row<2,E1,S1>& a, const Row<2,E2,S2>& b) {
00341     return a[0]*b[1]-a[1]*b[0];
00342 }
00343 template <class E1, int S1, class E2, int S2> inline
00344 typename CNT<E1>::template Result<E2>::Mul
00345 operator%(const Row<2,E1,S1>& a, const Row<2,E2,S2>& b) {return cross(a,b);}
00346 
00347     // CROSS MAT
00348 
00349 // Calculate matrix M(v) such that M(v)*w = v % w. We produce the
00350 // same M regardless of whether v is a column or row.
00351 template <class E, int S> inline
00352 Mat<3,3,E>
00353 crossMat(const Vec<3,E,S>& v) {
00354     return Mat<3,3,E>(Row<3,E>( E(0), -v[2],  v[1]),
00355                       Row<3,E>( v[2],  E(0), -v[0]),
00356                       Row<3,E>(-v[1],  v[0],  E(0)));
00357 }
00358 template <class E, int S> inline
00359 Mat<3,3,E> crossMat(const Row<3,E,S>& r) {return crossMat(r.positionalTranspose());}
00360 
00361 // Calculate M(v) such that M(v)*w = v0*w1-v1*w0 = v % w (a scalar). Whether v is column
00362 // or row we create the same M, which must be a row.
00363 template <class E, int S> inline
00364 Row<2,E>
00365 crossMat(const Vec<2,E,S>& v) {
00366     return Row<2,E>(-v[1], v[0]);
00367 }
00368 template <class E, int S> inline
00369 Row<2,E> crossMat(const Row<2,E,S>& r) {return crossMat(r.positionalTranspose());}
00370 
00371 } //namespace SimTK
00372 
00373 
00374 #endif //SimTK_SIMMATRIX_SMALLMATRIX_MIXED_H_

Generated on Thu Feb 28 01:34:32 2008 for SimTKcommon by  doxygen 1.4.7