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

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