UMath.h
Go to the documentation of this file.
00001 /*
00002 *  utilite is a cross-platform library with
00003 *  useful utilities for fast and small developing.
00004 *  Copyright (C) 2010  Mathieu Labbe
00005 *
00006 *  utilite is free library: you can redistribute it and/or modify
00007 *  it under the terms of the GNU Lesser General Public License as published by
00008 *  the Free Software Foundation, either version 3 of the License, or
00009 *  (at your option) any later version.
00010 *
00011 *  utilite is distributed in the hope that it will be useful,
00012 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *  GNU Lesser General Public License for more details.
00015 *
00016 *  You should have received a copy of the GNU Lesser General Public License
00017 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 
00020 #ifndef UMATH_H
00021 #define UMATH_H
00022 
00027 #include "rtabmap/utilite/UtiLiteExp.h" // DLL export/import defines
00028 
00029 #include <cmath>
00030 #include <list>
00031 #include <vector>
00032 
00033 #if _MSC_VER
00034         #undef min
00035         #undef max
00036 #endif
00037 
00041 template<class T>
00042 inline bool uIsNan(const T & value)
00043 {
00044 #ifdef __APPLE__
00045         return std::isnan(value);
00046 #elif _MSC_VER
00047         return _isnan(value) != 0;
00048 #else
00049         return isnan(value);
00050 #endif
00051 }
00052 
00056 template<class T>
00057 inline bool uIsFinite(const T & value)
00058 {
00059 #if _MSC_VER
00060         return _finite(value) != 0;
00061 #else
00062         return std::isfinite(value);
00063 #endif
00064 }
00065 
00073 template<class T>
00074 inline T uMax(const T * v, unsigned int size, unsigned int & index)
00075 {
00076         T max = 0;
00077         index = 0;
00078         if(!v || size == 0)
00079         {
00080                 return max;
00081         }
00082         max = v[0];
00083         for(unsigned int i=1; i<size; ++i)
00084         {
00085                 if(uIsNan(max) || (max < v[i] && !uIsNan(v[i])))
00086                 {
00087                         max = v[i];
00088                         index = i;
00089                 }
00090         }
00091 
00092         return max;
00093 }
00094 
00101 template<class T>
00102 inline T uMax(const std::vector<T> & v, unsigned int & index)
00103 {
00104         return uMax(v.data(), v->size(), index);
00105 }
00106 
00113 template<class T>
00114 inline T uMax(const T * v, unsigned int size)
00115 {
00116         unsigned int index;
00117         return uMax(v, size, index);
00118 }
00119 
00125 template<class T>
00126 inline T uMax(const std::vector<T> & v)
00127 {
00128         return uMax(v.data(), v.size());
00129 }
00130 
00138 template<class T>
00139 inline T uMin(const T * v, unsigned int size, unsigned int & index)
00140 {
00141         T min = 0;
00142         index = 0;
00143         if(!v || size == 0)
00144         {
00145                 return min;
00146         }
00147         min = v[0];
00148         for(unsigned int i=1; i<size; ++i)
00149         {
00150                 if(uIsNan(min) || (min > v[i] && !uIsNan(v[i])))
00151                 {
00152                         min = v[i];
00153                         index = i;
00154                 }
00155         }
00156 
00157         return min;
00158 }
00159 
00166 template<class T>
00167 inline T uMin(const std::vector<T> & v, unsigned int & index)
00168 {
00169         return uMin(v.data(), v.size(), index);
00170 }
00171 
00178 template<class T>
00179 inline T uMin(const T * v, unsigned int size)
00180 {
00181         unsigned int index;
00182         return uMin(v, size, index);
00183 }
00184 
00190 template<class T>
00191 inline T uMin(const std::vector<T> & v)
00192 {
00193         return uMin(v.data(), v.size());
00194 }
00195 
00205 template<class T>
00206 inline void uMinMax(const T * v, unsigned int size, T & min, T & max, unsigned int & indexMin, unsigned int & indexMax)
00207 {
00208         min = 0;
00209         max = 0;
00210         indexMin = 0;
00211         indexMax = 0;
00212         if(!v || size == 0)
00213         {
00214                 return;
00215         }
00216         min = v[0];
00217         max = v[0];
00218 
00219         for(unsigned int i=1; i<size; ++i)
00220         {
00221                 if(uIsNan(min) || (min > v[i] && !uIsNan(v[i])))
00222                 {
00223                         min = v[i];
00224                         indexMin = i;
00225                 }
00226 
00227                 if(uIsNan(max) || (max < v[i] && !uIsNan(v[i])))
00228                 {
00229                         max = v[i];
00230                         indexMax = i;
00231                 }
00232         }
00233 }
00234 
00243 template<class T>
00244 inline void uMinMax(const std::vector<T> & v, T & min, T & max, unsigned int & indexMin, unsigned int & indexMax)
00245 {
00246         uMinMax(v.data(), v.size(), min, max, indexMin, indexMax);
00247 }
00248 
00256 template<class T>
00257 inline void uMinMax(const T * v, unsigned int size, T & min, T & max)
00258 {
00259         unsigned int indexMin;
00260         unsigned int indexMax;
00261         uMinMax(v, size, min, max, indexMin, indexMax);
00262 }
00263 
00270 template<class T>
00271 inline void uMinMax(const std::vector<T> & v, T & min, T & max)
00272 {
00273         uMinMax(v.data(), v.size(), min, max);
00274 }
00275 
00281 template<class T>
00282 inline int uSign(const T & v)
00283 {
00284         if(v < 0)
00285         {
00286                 return -1;
00287         }
00288         else
00289         {
00290                 return 1;
00291         }
00292 }
00293 
00299 template<class T>
00300 inline T uSum(const std::list<T> & list)
00301 {
00302         T sum = 0;
00303         for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00304         {
00305                 sum += *i;
00306         }
00307         return sum;
00308 }
00309 
00316 template<class T>
00317 inline T uSum(const T * v, unsigned int size)
00318 {
00319         T sum = 0;
00320         if(v && size)
00321         {
00322                 for(unsigned int i=0; i<size; ++i)
00323                 {
00324                         sum += v[i];
00325                 }
00326         }
00327         return sum;
00328 }
00329 
00335 template<class T>
00336 inline T uSum(const std::vector<T> & v)
00337 {
00338         return uSum(v.data(), (int)v.size());
00339 }
00340 
00348 template<class T>
00349 inline T uSumSquared(const T * v, unsigned int size, T subtract = T())
00350 {
00351         T sum = 0;
00352         if(v && size)
00353         {
00354                 for(unsigned int i=0; i<size; ++i)
00355                 {
00356                         sum += (v[i]-subtract)*(v[i]-subtract);
00357                 }
00358         }
00359         return sum;
00360 }
00361 
00368 template<class T>
00369 inline T uSumSquared(const std::vector<T> & v, T subtract = T())
00370 {
00371         return uSumSquared(v.data(), v.size(), subtract);
00372 }
00373 
00380 template<class T>
00381 inline T uMean(const T * v, unsigned int size)
00382 {
00383         T buf = 0;
00384         if(v && size)
00385         {
00386                 for(unsigned int i=0; i<size; ++i)
00387                 {
00388                         buf += v[i];
00389                 }
00390                 buf /= size;
00391         }
00392         return buf;
00393 }
00394 
00400 template<class T>
00401 inline T uMean(const std::list<T> & list)
00402 {
00403         T m = 0;
00404         if(list.size())
00405         {
00406                 for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00407                 {
00408                         m += *i;
00409                 }
00410                 m /= list.size();
00411         }
00412         return m;
00413 }
00414 
00420 template<class T>
00421 inline T uMean(const std::vector<T> & v)
00422 {
00423         return uMean(v.data(), v.size());
00424 }
00425 
00434 template<class T>
00435 inline T uMeanSquaredError(const T * x, unsigned int sizeX, const T * y, unsigned int sizeY)
00436 {
00437         T sum = 0;
00438         if(x && y && sizeX == sizeY)
00439         {
00440                 for(unsigned int i=0; i<sizeX; ++i)
00441                 {
00442                         T diff = x[i]-y[i];
00443                         sum += diff*diff;
00444                 }
00445                 return sum/(T)sizeX;
00446         }
00447         return (T)-1;
00448 }
00449 
00456 template<class T>
00457 inline T uMeanSquaredError(const std::vector<T> & x, const std::vector<T> & y)
00458 {
00459         return uMeanSquaredError(x.data(), x.size(), y.data(), y.size());
00460 }
00461 
00470 template<class T>
00471 inline T uVariance(const T * v, unsigned int size, T meanV)
00472 {
00473         T buf = 0;
00474         if(v && size>1)
00475         {
00476                 float sum = 0;
00477                 for(unsigned int i=0; i<size; ++i)
00478                 {
00479                         sum += (v[i]-meanV)*(v[i]-meanV);
00480                 }
00481                 buf = sum/(size-1);
00482         }
00483         return buf;
00484 }
00485 
00493 template<class T>
00494 inline T uVariance(const std::list<T> & list, const T & m)
00495 {
00496         T buf = 0;
00497         if(list.size()>1)
00498         {
00499                 float sum = 0;
00500                 for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00501                 {
00502                         sum += (*i-m)*(*i-m);
00503                 }
00504                 buf = sum/(list.size()-1);
00505         }
00506         return buf;
00507 }
00508 
00515 template<class T>
00516 inline T uVariance(const T * v, unsigned int size)
00517 {
00518         T m = uMean(v, size);
00519         return uVariance(v, size, m);
00520 }
00521 
00529 template<class T>
00530 inline T uVariance(const std::vector<T> & v, const T & m)
00531 {
00532         return uVariance(v.data(), v.size(), m);
00533 }
00534 
00539 template<class T>
00540 inline T uNormSquared(const std::vector<T> & v)
00541 {
00542         float sum = 0.0f;
00543         for(unsigned int i=0; i<v.size(); ++i)
00544         {
00545                 sum += v[i]*v[i];
00546         }
00547         return sum;
00548 }
00549 
00554 template<class T>
00555 inline T uNorm(const std::vector<T> & v)
00556 {
00557         return std::sqrt(uNormSquared(v));
00558 }
00559 
00564 template<class T>
00565 inline T uNormSquared(const T & x1, const T & x2)
00566 {
00567         return x1*x1 + x2*x2;
00568 }
00569 
00574 template<class T>
00575 inline T uNorm(const T & x1, const T & x2)
00576 {
00577         return std::sqrt(uNormSquared(x1, x2));
00578 }
00579 
00584 template<class T>
00585 inline T uNormSquared(const T & x1, const T & x2, const T & x3)
00586 {
00587         return x1*x1 + x2*x2 + x3*x3;
00588 }
00589 
00594 template<class T>
00595 inline T uNorm(const T & x1, const T & x2, const T & x3)
00596 {
00597         return std::sqrt(uNormSquared(x1, x2, x3));
00598 }
00599 
00604 template<class T>
00605 inline std::vector<T> uNormalize(const std::vector<T> & v)
00606 {
00607         float norm = uNorm(v);
00608         if(norm == 0)
00609         {
00610                 return v;
00611         }
00612         else
00613         {
00614                 std::vector<T> r(v.size());
00615                 for(unsigned int i=0; i<v.size(); ++i)
00616                 {
00617                         r[i] = v[i]/norm;
00618                 }
00619                 return r;
00620         }
00621 }
00622 
00626 template<class T>
00627 inline std::list<unsigned int> uLocalMaxima(const T * v, unsigned int size)
00628 {
00629         std::list<unsigned int> maxima;
00630         if(size)
00631         {
00632                 for(unsigned int i=0; i<size; ++i)
00633                 {
00634                         if(i == 0)
00635                         {
00636                                 // first item
00637                                 if((i+1 < size && v[i] > v[i+1]) ||
00638                                         i+1 >= size)
00639                                 {
00640                                         maxima.push_back(i);
00641                                 }
00642                         }
00643                         else if(i == size - 1)
00644                         {
00645                                 //last item
00646                                 if((i >= 1 && v[i] > v[i-1]) ||
00647                                         i == 0)
00648                                 {
00649                                         maxima.push_back(i);
00650                                 }
00651                         }
00652                         else
00653                         {
00654                                 //all others, check previous and next
00655                                 if(v[i] > v[i-1] && v[i] > v[i+1])
00656                                 {
00657                                         maxima.push_back(i);
00658                                 }
00659                         }
00660                 }
00661         }
00662         return maxima;
00663 }
00664 
00668 template<class T>
00669 inline std::list<unsigned int> uLocalMaxima(const std::vector<T> & v)
00670 {
00671         return uLocalMaxima(v.data(), v.size());
00672 }
00673 
00678 enum UXMatchMethod{UXCorrRaw, UXCorrBiased, UXCorrUnbiased, UXCorrCoeff, UXCovRaw, UXCovBiased, UXCovUnbiased, UXCovCoeff};
00679 
00689 template<class T>
00690 inline std::vector<T> uXMatch(const T * vA, const T * vB, unsigned int sizeA, unsigned int sizeB, UXMatchMethod method)
00691 {
00692         if(!vA || !vB || sizeA == 0 || sizeB == 0)
00693         {
00694                 return std::vector<T>();
00695         }
00696 
00697         std::vector<T> result(sizeA + sizeB - 1);
00698 
00699         T meanA = 0;
00700         T meanB = 0;
00701         if(method > UXCorrCoeff)
00702         {
00703                 meanA = uMean(vA, sizeA);
00704                 meanB = uMean(vB, sizeB);
00705         }
00706 
00707         T den = 1;
00708         if(method == UXCorrCoeff || method == UXCovCoeff)
00709         {
00710                 den = std::sqrt(uSumSquared(vA, sizeA, meanA) * uSumSquared(vB, sizeB, meanB));
00711         }
00712         else if(method == UXCorrBiased || method == UXCovBiased)
00713         {
00714                 den = (T)std::max(sizeA, sizeB);
00715         }
00716 
00717         if(sizeA == sizeB)
00718         {
00719                 T resultA;
00720                 T resultB;
00721 
00722                 int posA;
00723                 int posB;
00724                 unsigned int j;
00725 
00726                 // Optimization, filling two results at once
00727                 for(unsigned int i=0; i<sizeA; ++i)
00728                 {
00729                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00730                         {
00731                                 den = 0;
00732                         }
00733 
00734                         posA = sizeA - i - 1;
00735                         posB = sizeB - i - 1;
00736                         resultA = 0;
00737                         resultB = 0;
00738                         for(j=0; (j + posB) < sizeB && (j + posA) < sizeA; ++j)
00739                         {
00740                                 resultA += (vA[j] - meanA) * (vB[j + posB] - meanB);
00741                                 resultB += (vA[j + posA] - meanA) * (vB[j] - meanB);
00742                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00743                                 {
00744                                         ++den;
00745                                 }
00746                         }
00747 
00748                         result[i] = resultA / den;
00749                         result[result.size()-1 -i] = resultB / den;
00750                 }
00751         }
00752         else
00753         {
00754                 for(unsigned int i=0; i<result.size(); ++i)
00755                 {
00756                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00757                         {
00758                                 den = 0;
00759                         }
00760 
00761                         int posB = sizeB - i - 1;
00762                         T r = 0;
00763                         if(posB >= 0)
00764                         {
00765                                 for(unsigned int j=0; (j + posB) < sizeB && j < sizeA; ++j)
00766                                 {
00767                                         r += (vA[j] - meanA) * (vB[j + posB] - meanB);
00768                                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00769                                         {
00770                                                 ++den;
00771                                         }
00772                                 }
00773                         }
00774                         else
00775                         {
00776                                 int posA = posB*-1;
00777                                 for(unsigned int i=0; (i+posA) < sizeA && i < sizeB; ++i)
00778                                 {
00779                                         r += (vA[i+posA] - meanA) * (vB[i] - meanB);
00780                                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00781                                         {
00782                                                 ++den;
00783                                         }
00784                                 }
00785                         }
00786 
00787                         result[i] = r / den;
00788                 }
00789         }
00790 
00791         return result;
00792 }
00793 
00801 template<class T>
00802 inline std::vector<T> uXMatch(const std::vector<T> & vA, const std::vector<T> & vB, UXMatchMethod method)
00803 {
00804         return uXMatch(vA.data(), vB.data(), vA.size(), vB.size(), method);
00805 }
00806 
00817 template<class T>
00818 inline T uXMatch(const T * vA, const T * vB, unsigned int sizeA, unsigned int sizeB, unsigned int index, UXMatchMethod method)
00819 {
00820         T result = 0;
00821         if(!vA || !vB || sizeA == 0 || sizeB == 0)
00822         {
00823                 return result;
00824         }
00825 
00826         T meanA = 0;
00827         T meanB = 0;
00828         if(method > UXCorrCoeff)
00829         {
00830                 meanA = uMean(vA, sizeA);
00831                 meanB = uMean(vB, sizeB);
00832         }
00833         unsigned int size = sizeA + sizeB - 1;
00834 
00835         T den = 1;
00836         if(method == UXCorrCoeff || method == UXCovCoeff)
00837         {
00838                 den = std::sqrt(uSumSquared(vA, sizeA, meanA) * uSumSquared(vB, sizeB, meanB));
00839         }
00840         else if(method == UXCorrBiased || method == UXCovBiased)
00841         {
00842                 den = (T)std::max(sizeA, sizeB);
00843         }
00844         else if(method == UXCorrUnbiased || method == UXCovUnbiased)
00845         {
00846                 den = 0;
00847         }
00848 
00849         if(index < size)
00850         {
00851                 int posB = sizeB - index - 1;
00852                 unsigned int i;
00853                 if(posB >= 0)
00854                 {
00855                         for(i=0; (i + posB) < sizeB && i < sizeA; ++i)
00856                         {
00857                                 result += (vA[i] - meanA) * (vB[i + posB] - meanB);
00858                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00859                                 {
00860                                         ++den;
00861                                 }
00862                         }
00863                 }
00864                 else
00865                 {
00866                         int posA = posB*-1;
00867                         for(i=0; (i+posA) < sizeA && i < sizeB; ++i)
00868                         {
00869                                 result += (vA[i+posA] - meanA) * (vB[i] - meanB);
00870                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00871                                 {
00872                                         ++den;
00873                                 }
00874                         }
00875                 }
00876         }
00877         return result / den;
00878 }
00879 
00890 template<class T>
00891 inline T uXMatch(const std::vector<T> & vA, const std::vector<T> & vB, unsigned int index, UXMatchMethod method)
00892 {
00893         return uXMatch(vA.data(), vB.data(), vA.size(), vB.size(), index, method);
00894 }
00895 
00901 inline std::vector<float> uHamming(unsigned int L)
00902 {
00903         std::vector<float> w(L);
00904         unsigned int N = L-1;
00905         float pi = 3.14159265f;
00906         for(unsigned int n=0; n<N; ++n)
00907         {
00908                 w[n] = 0.54f-0.46f*std::cos(2.0f*pi*float(n)/float(N));
00909         }
00910         return w;
00911 }
00912 
00913 template <typename T>
00914 bool uIsInBounds(const T& value, const T& low, const T& high)
00915 {
00916         return !(value < low) && !(value >= high);
00917 }
00918 
00919 #endif // UMATH_H


rtabmap
Author(s): Mathieu Labbe
autogenerated on Fri Aug 28 2015 12:51:42