Simbody
3.4 (development)
|
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_