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