Simbody

VectorMath.h

Go to the documentation of this file.
00001 #ifndef SimTK_SimTKCOMMON_VECTOR_MATH_H_
00002 #define SimTK_SimTKCOMMON_VECTOR_MATH_H_
00003 
00004 /* -------------------------------------------------------------------------- *
00005  *                      SimTK Core: SimTKcommon                               *
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) 2008 Stanford University and the Authors.           *
00013  * Authors: Peter Eastman                                                     *
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 
00035 #include "SimTKcommon/basics.h"
00036 #include "SimTKcommon/Simmatrix.h"
00037 
00038 #include <cmath>     // for std:sin, sqrt, etc.
00039 #include <algorithm> // for std:sort, nth_element, etc.
00040 
00047 namespace SimTK {
00048 
00049 // We can use a single definition for a number of functions that simply call a function
00050 // on each element, returning a value of the same type.
00051 
00052 #define SimTK_ELEMENTWISE_FUNCTION(func)               \
00053 template <class ELEM>                                  \
00054 VectorBase<ELEM> func(const VectorBase<ELEM> v) {      \
00055     const int size = v.size();                         \
00056     Vector_<ELEM> temp(size);                          \
00057     for (int i = 0; i < size; ++i)                     \
00058         temp[i] = std::func(v[i]);                     \
00059     return temp;                                       \
00060 }                                                      \
00061 template <class ELEM>                                  \
00062 RowVectorBase<ELEM> func(const RowVectorBase<ELEM> v) {\
00063     const int size = v.size();                         \
00064     RowVector_<ELEM> temp(size);                       \
00065     for (int i = 0; i < size; ++i)                     \
00066         temp[i] = std::func(v[i]);                     \
00067     return temp;                                       \
00068 }                                                      \
00069 template <class ELEM>                                  \
00070 MatrixBase<ELEM> func(const MatrixBase<ELEM> v) {      \
00071     const int rows = v.nrow(), cols = v.ncol();        \
00072     Matrix_<ELEM> temp(rows, cols);                    \
00073     for (int i = 0; i < rows; ++i)                     \
00074         for (int j = 0; j < cols; ++j)                 \
00075             temp(i, j) = std::func(v(i, j));           \
00076     return temp;                                       \
00077 }                                                      \
00078 template <int N, class ELEM>                           \
00079 Vec<N, ELEM> func(Vec<N, ELEM> v) {                    \
00080     for (int i = 0; i < N; ++i)                        \
00081         v[i] = std::func(v[i]);                        \
00082     return v;                                          \
00083 }                                                      \
00084 template <int N, class ELEM>                           \
00085 Row<N, ELEM> func(Row<N, ELEM> v) {                    \
00086     for (int i = 0; i < N; ++i)                        \
00087         v[i] = std::func(v[i]);                        \
00088     return v;                                          \
00089 }                                                      \
00090 template <int M, int N, class ELEM>                    \
00091 Mat<M, N, ELEM> func(Mat<M, N, ELEM> v) {              \
00092     for (int i = 0; i < M; ++i)                        \
00093         for (int j = 0; j < N; ++j)                    \
00094             v(i, j) = std::func(v(i, j));              \
00095     return v;                                          \
00096 }                                                      \
00097 template <int N, class ELEM>                           \
00098 SymMat<N, ELEM> func(SymMat<N, ELEM> v) {              \
00099     for (int i = 0; i < N; ++i)                        \
00100         for (int j = 0; j <= i; ++j)                   \
00101             v(i, j) = std::func(v(i, j));              \
00102     return v;                                          \
00103 }                                                      \
00104 
00105 SimTK_ELEMENTWISE_FUNCTION(exp)
00106 SimTK_ELEMENTWISE_FUNCTION(log)
00107 SimTK_ELEMENTWISE_FUNCTION(sqrt)
00108 SimTK_ELEMENTWISE_FUNCTION(sin)
00109 SimTK_ELEMENTWISE_FUNCTION(cos)
00110 SimTK_ELEMENTWISE_FUNCTION(tan)
00111 SimTK_ELEMENTWISE_FUNCTION(asin)
00112 SimTK_ELEMENTWISE_FUNCTION(acos)
00113 SimTK_ELEMENTWISE_FUNCTION(atan)
00114 SimTK_ELEMENTWISE_FUNCTION(sinh)
00115 SimTK_ELEMENTWISE_FUNCTION(cosh)
00116 SimTK_ELEMENTWISE_FUNCTION(tanh)
00117 
00118 #undef SimTK_ELEMENTWISE_FUNCTION
00119 
00120 // The abs() function.
00121 
00122 template <class ELEM>
00123 VectorBase<typename CNT<ELEM>::TAbs> abs(const VectorBase<ELEM> v) {
00124     return v.abs();
00125 }
00126 template <class ELEM>
00127 RowVectorBase<typename CNT<ELEM>::TAbs> abs(const RowVectorBase<ELEM> v) {
00128     return v.abs();
00129 }
00130 template <class ELEM>
00131 MatrixBase<typename CNT<ELEM>::TAbs> abs(const MatrixBase<ELEM> v) {
00132     return v.abs();
00133 }
00134 template <int N, class ELEM>
00135 Vec<N, typename CNT<ELEM>::TAbs> abs(const Vec<N, ELEM> v) {
00136     return v.abs();
00137 }
00138 template <int N, class ELEM>
00139 Row<N, typename CNT<ELEM>::TAbs> abs(const Row<N, ELEM> v) {
00140     return v.abs();
00141 }
00142 template <int M, int N, class ELEM>
00143 Mat<M, N, typename CNT<ELEM>::TAbs> abs(const Mat<M, N, ELEM> v) {
00144     return v.abs();
00145 }
00146 template <int N, class ELEM>
00147 SymMat<N, typename CNT<ELEM>::TAbs> abs(const SymMat<N, ELEM> v) {
00148     return v.abs();
00149 }
00150 
00151 // The sum() function.
00152 
00153 template <class ELEM>
00154 ELEM sum(const VectorBase<ELEM> v) {
00155     return v.sum();
00156 }
00157 template <class ELEM>
00158 ELEM sum(const RowVectorBase<ELEM> v) {
00159     return v.sum();
00160 }
00161 template <class ELEM>
00162 RowVectorBase<ELEM> sum(const MatrixBase<ELEM> v) {
00163     return v.sum();
00164 }
00165 template <int N, class ELEM>
00166 ELEM sum(const Vec<N, ELEM> v) {
00167     return v.sum();
00168 }
00169 template <int N, class ELEM>
00170 ELEM sum(const Row<N, ELEM> v) {
00171     return v.sum();
00172 }
00173 template <int M, int N, class ELEM>
00174 Row<N, ELEM> sum(const Mat<M, N, ELEM> v) {
00175     return v.sum();
00176 }
00177 template <int N, class ELEM>
00178 Row<N, ELEM> sum(const SymMat<N, ELEM> v) {
00179     return v.sum();
00180 }
00181 
00182 // The min() function.
00183 
00184 template <class ELEM>
00185 ELEM min(const VectorBase<ELEM> v) {
00186     const int size = v.size();
00187     ELEM min = NTraits<ELEM>::getMostPositive();
00188     for (int i = 0; i < size; ++i) {
00189         ELEM val = v[i];
00190         if (val < min)
00191             min = val;
00192     }
00193     return min;
00194 }
00195 template <class ELEM>
00196 ELEM min(const RowVectorBase<ELEM> v) {
00197     const int size = v.size();
00198     ELEM min = NTraits<ELEM>::getMostPositive();
00199     for (int i = 0; i < size; ++i) {
00200         ELEM val = v[i];
00201         if (val < min)
00202             min = val;
00203     }
00204     return min;
00205 }
00206 template <class ELEM>
00207 RowVectorBase<ELEM> min(const MatrixBase<ELEM> v) {
00208     int cols = v.ncol();
00209     RowVectorBase<ELEM> temp(cols);
00210     for (int i = 0; i < cols; ++i)
00211         temp[i] = min(v(i));
00212     return temp;
00213 }
00214 template <int N, class ELEM>
00215 ELEM min(const Vec<N, ELEM> v) {
00216     ELEM min = NTraits<ELEM>::getMostPositive();
00217     for (int i = 0; i < N; ++i) {
00218         ELEM val = v[i];
00219         if (val < min)
00220             min = val;
00221     }
00222     return min;
00223 }
00224 template <int N, class ELEM>
00225 ELEM min(Row<N, ELEM> v) {
00226     ELEM min = NTraits<ELEM>::getMostPositive();
00227     for (int i = 0; i < N; ++i) {
00228         ELEM val = v[i];
00229         if (val < min)
00230             min = val;
00231     }
00232     return min;
00233 }
00234 template <int M, int N, class ELEM>
00235 Row<N, ELEM> min(const Mat<M, N, ELEM> v) {
00236     Row<N, ELEM> temp;
00237     for (int i = 0; i < N; ++i)
00238         temp[i] = min(v(i));
00239     return temp;
00240 }
00241 template <int N, class ELEM>
00242 Row<N, ELEM> min(SymMat<N, ELEM> v) {
00243     Row<N, ELEM> temp(~v.getDiag());
00244     for (int i = 1; i < N; ++i)
00245         for (int j = 0; j < i; ++j) {
00246             ELEM value = v.getEltLower(i, j);
00247             if (value < temp[i])
00248                 temp[i] = value;
00249             if (value < temp[j])
00250                 temp[j] = value;
00251         }
00252     return temp;
00253 }
00254 
00255 // The max() function.
00256 
00257 template <class ELEM>
00258 ELEM max(const VectorBase<ELEM> v) {
00259     const int size = v.size();
00260     ELEM max = NTraits<ELEM>::getMostNegative();
00261     for (int i = 0; i < size; ++i) {
00262         ELEM val = v[i];
00263         if (val > max)
00264             max = val;
00265     }
00266     return max;
00267 }
00268 template <class ELEM>
00269 ELEM max(const RowVectorBase<ELEM> v) {
00270     const int size = v.size();
00271     ELEM max = NTraits<ELEM>::getMostNegative();
00272     for (int i = 0; i < size; ++i) {
00273         ELEM val = v[i];
00274         if (val > max)
00275             max = val;
00276     }
00277     return max;
00278 }
00279 template <class ELEM>
00280 RowVectorBase<ELEM> max(const MatrixBase<ELEM> v) {
00281     int cols = v.ncol();
00282     RowVectorBase<ELEM> temp(cols);
00283     for (int i = 0; i < cols; ++i)
00284         temp[i] = max(v(i));
00285     return temp;
00286 }
00287 template <int N, class ELEM>
00288 ELEM max(Vec<N, ELEM> v) {
00289     ELEM max = NTraits<ELEM>::getMostNegative();
00290     for (int i = 0; i < N; ++i) {
00291         ELEM val = v[i];
00292         if (val > max)
00293             max = val;
00294     }
00295     return max;
00296 }
00297 template <int N, class ELEM>
00298 ELEM max(const Row<N, ELEM> v) {
00299     ELEM max = NTraits<ELEM>::getMostNegative();
00300     for (int i = 0; i < N; ++i) {
00301         ELEM val = v[i];
00302         if (val > max)
00303             max = val;
00304     }
00305     return max;
00306 }
00307 template <int M, int N, class ELEM>
00308 Row<N, ELEM> max(const Mat<M, N, ELEM> v) {
00309     Row<N, ELEM> temp;
00310     for (int i = 0; i < N; ++i)
00311         temp[i] = max(v(i));
00312     return temp;
00313 }
00314 template <int N, class ELEM>
00315 Row<N, ELEM> max(const SymMat<N, ELEM> v) {
00316     Row<N, ELEM> temp(~v.getDiag());
00317     for (int i = 1; i < N; ++i)
00318         for (int j = 0; j < i; ++j) {
00319             ELEM value = v.getEltLower(i, j);
00320             if (value > temp[i])
00321                 temp[i] = value;
00322             if (value > temp[j])
00323                 temp[j] = value;
00324         }
00325     return temp;
00326 }
00327 
00328 // The mean() function.
00329 
00330 template <class ELEM>
00331 ELEM mean(const VectorBase<ELEM> v) {
00332     return sum(v)/v.size();
00333 }
00334 template <class ELEM>
00335 ELEM mean(const RowVectorBase<ELEM> v) {
00336     return sum(v)/v.size();
00337 }
00338 template <class ELEM>
00339 RowVectorBase<ELEM> mean(const MatrixBase<ELEM> v) {
00340     return sum(v)/v.nrow();
00341 }
00342 template <int N, class ELEM>
00343 ELEM mean(const Vec<N, ELEM> v) {
00344     return sum(v)/N;
00345 }
00346 template <int N, class ELEM>
00347 ELEM mean(const Row<N, ELEM> v) {
00348     return sum(v)/N;
00349 }
00350 template <int M, int N, class ELEM>
00351 Row<N, ELEM> mean(const Mat<M, N, ELEM> v) {
00352     return sum(v)/M;
00353 }
00354 template <int N, class ELEM>
00355 Row<N, ELEM> mean(const SymMat<N, ELEM> v) {
00356     return sum(v)/N;
00357 }
00358 
00359 // The sort() function.
00360 
00361 template <class ELEM>
00362 VectorBase<ELEM> sort(const VectorBase<ELEM> v) {
00363     const int size = v.size();
00364     VectorBase<ELEM> temp(v);
00365     std::sort(temp.begin(), temp.end());
00366     return temp;
00367 }
00368 template <class ELEM>
00369 RowVectorBase<ELEM> sort(const RowVectorBase<ELEM> v) {
00370     const int size = v.size();
00371     RowVectorBase<ELEM> temp(v);
00372     std::sort(temp.begin(), temp.end());
00373     return temp;
00374 }
00375 template <class ELEM>
00376 MatrixBase<ELEM> sort(const MatrixBase<ELEM> v) {
00377     const int rows = v.nrow(), cols = v.ncol();
00378     MatrixBase<ELEM> temp(v);
00379     for (int i = 0; i < cols; ++i)
00380         temp.updCol(i) = sort(temp.col(i));
00381     return temp;
00382 }
00383 template <int N, class ELEM>
00384 Vec<N, ELEM> sort(Vec<N, ELEM> v) {
00385     ELEM* pointer = reinterpret_cast<ELEM*>(&v);
00386     std::sort(pointer, pointer+N);
00387     return v;
00388 }
00389 template <int N, class ELEM>
00390 Row<N, ELEM> sort(Row<N, ELEM> v) {
00391     ELEM* pointer = reinterpret_cast<ELEM*>(&v);
00392     std::sort(pointer, pointer+N);
00393     return v;
00394 }
00395 template <int M, int N, class ELEM>
00396 Mat<M, N, ELEM> sort(Mat<M, N, ELEM> v) {
00397     for (int i = 0; i < N; ++i)
00398         v.col(i) = sort(v.col(i));
00399     return v;
00400 }
00401 template <int N, class ELEM>
00402 Mat<N, N, ELEM> sort(const SymMat<N, ELEM> v) {
00403     return sort(Mat<N, N, ELEM>(v));
00404 }
00405 
00406 // The median() function.
00407 
00408 template <class ELEM, class RandomAccessIterator>
00409 ELEM median(RandomAccessIterator start, RandomAccessIterator end) {
00410     const int size = (int)(end-start);
00411     RandomAccessIterator mid = start+(size-1)/2;
00412     std::nth_element(start, mid, end);
00413     if (size%2 == 0 && mid+1 < end) {
00414         // An even number of element.  The median is the mean of the two middle elements.
00415         // nth_element has given us the first of them and partially sorted the list.
00416         // We need to scan through the rest of the list and find the next element in
00417         // sorted order.
00418         
00419         RandomAccessIterator min = mid+1;
00420         for (RandomAccessIterator iter = mid+1; iter < end; iter++) {
00421             if (*iter < *min)
00422                 min = iter;
00423         }
00424         return (*mid+*min)/2;
00425     }
00426     return *mid;
00427 }
00428 template <class ELEM>
00429 ELEM median(const VectorBase<ELEM> v) {
00430     VectorBase<ELEM> temp(v);
00431     return median<ELEM>(temp.begin(), temp.end());
00432 }
00433 template <class ELEM>
00434 ELEM median(const RowVectorBase<ELEM> v) {
00435     RowVectorBase<ELEM> temp(v);
00436     return median<ELEM>(temp.begin(), temp.end());
00437 }
00438 template <class ELEM>
00439 RowVectorBase<ELEM> median(const MatrixBase<ELEM> v) {
00440     int cols = v.ncol(), rows = v.nrow();
00441     RowVectorBase<ELEM> temp(cols);
00442     VectorBase<ELEM> column(rows);
00443     for (int i = 0; i < cols; ++i) {
00444         column = v.col(i);
00445         temp[i] = median<ELEM>(column);
00446     }
00447     return temp;
00448 }
00449 template <int N, class ELEM>
00450 ELEM median(Vec<N, ELEM> v) {
00451     ELEM* pointer = reinterpret_cast<ELEM*>(&v);
00452     return  median<ELEM>(pointer, pointer+N);
00453 }
00454 template <int N, class ELEM>
00455 ELEM median(Row<N, ELEM> v) {
00456     ELEM* pointer = reinterpret_cast<ELEM*>(&v);
00457     return  median<ELEM>(pointer, pointer+N);
00458 }
00459 template <int M, int N, class ELEM>
00460 Row<N, ELEM> median(const Mat<M, N, ELEM> v) {
00461     Row<N, ELEM> temp;
00462     for (int i = 0; i < N; ++i)
00463         temp[i] = median(v(i));
00464     return temp;
00465 }
00466 template <int N, class ELEM>
00467 Row<N, ELEM> median(const SymMat<N, ELEM> v) {
00468     return median(Mat<N, N, ELEM>(v));
00469 }
00470 
00471 } // namespace SimTK
00472 
00473 #endif // SimTK_SimTKCOMMON_VECTOR_MATH_H_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines