00001 #ifndef SimTK_SimTKCOMMON_VECTOR_MATH_H_
00002 #define SimTK_SimTKCOMMON_VECTOR_MATH_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "SimTKcommon/basics.h"
00036 #include "SimTKcommon/Simmatrix.h"
00037
00038 #include <cmath>
00039 #include <algorithm>
00040
00047 namespace SimTK {
00048
00049
00050
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
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
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
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
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
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
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
00407
00408 template <class ELEM, class RandomAccessIterator>
00409 ELEM median(RandomAccessIterator start, RandomAccessIterator end) {
00410 int size = 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
00415
00416
00417
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 }
00472
00473 #endif // SimTK_SimTKCOMMON_VECTOR_MATH_H_