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
00046 namespace SimTK {
00047
00048
00049
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
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
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
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
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
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
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
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
00414
00415
00416
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 }
00471
00472 #endif // SimTK_SimTKCOMMON_VECTOR_MATH_H_