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

Generated on Fri Sep 26 07:44:17 2008 for SimTKcore by  doxygen 1.5.6