UtiLite  0.3.1
A lite utilities library
include/utilite/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 "utilite/UtiLiteExp.h" // DLL export/import defines
00028 
00029 #include <cmath>
00030 #include <list>
00031 #include <vector>
00032 
00033 #ifdef APPLE
00034         #define ISNAN(value) std::isnan(value)
00035 #elif _MSC_VER
00036         #define ISNAN(value) _isnan(value)
00037         #undef min  
00038         #undef max 
00039 #else
00040         #define ISNAN(value) isnan(value)
00041 #endif
00042 
00050 template<class T>
00051 inline T uMax(const T * v, unsigned int size, unsigned int & index)
00052 {
00053         T max = 0;
00054         index = 0;
00055         if(!v || size == 0)
00056         {
00057                 return max;
00058         }
00059         max = v[0];
00060         for(unsigned int i=1; i<size; ++i)
00061         {
00062                 if(ISNAN(max) || (max < v[i] && !ISNAN(v[i])))
00063                 {
00064                         max = v[i];
00065                         index = i;
00066                 }
00067         }
00068 
00069         return max;
00070 }
00071 
00078 template<class T>
00079 inline T uMax(const std::vector<T> & v, unsigned int & index)
00080 {
00081         return uMax(v.data(), v->size(), index);
00082 }
00083 
00090 template<class T>
00091 inline T uMax(const T * v, unsigned int size)
00092 {
00093         unsigned int index;
00094         return uMax(v, size, index);
00095 }
00096 
00102 template<class T>
00103 inline T uMax(const std::vector<T> & v)
00104 {
00105         return uMax(v.data(), v.size());
00106 }
00107 
00115 template<class T>
00116 inline T uMin(const T * v, unsigned int size, unsigned int & index)
00117 {
00118         T min = 0;
00119         index = 0;
00120         if(!v || size == 0)
00121         {
00122                 return min;
00123         }
00124         min = v[0];
00125         for(unsigned int i=1; i<size; ++i)
00126         {
00127                 if(ISNAN(min) || (min > v[i] && !ISNAN(v[i])))
00128                 {
00129                         min = v[i];
00130                         index = i;
00131                 }
00132         }
00133 
00134         return min;
00135 }
00136 
00143 template<class T>
00144 inline T uMin(const std::vector<T> & v, unsigned int & index)
00145 {
00146         return uMin(v.data(), v.size(), index);
00147 }
00148 
00155 template<class T>
00156 inline T uMin(const T * v, unsigned int size)
00157 {
00158         unsigned int index;
00159         return uMin(v, size, index);
00160 }
00161 
00167 template<class T>
00168 inline T uMin(const std::vector<T> & v)
00169 {
00170         return uMin(v.data(), v.size());
00171 }
00172 
00182 template<class T>
00183 inline void uMinMax(const T * v, unsigned int size, T & min, T & max, unsigned int & indexMin, unsigned int & indexMax)
00184 {
00185         min = 0;
00186         max = 0;
00187         indexMin = 0;
00188         indexMax = 0;
00189         if(!v || size == 0)
00190         {
00191                 return;
00192         }
00193         min = v[0];
00194         max = v[0];
00195 
00196         for(unsigned int i=1; i<size; ++i)
00197         {
00198                 if(ISNAN(min) || (min > v[i] && !ISNAN(v[i])))
00199                 {
00200                         min = v[i];
00201                         indexMin = i;
00202                 }
00203 
00204                 if(ISNAN(max) || (max < v[i] && !ISNAN(v[i])))
00205                 {
00206                         max = v[i];
00207                         indexMax = i;
00208                 }
00209         }
00210 }
00211 
00220 template<class T>
00221 inline void uMinMax(const std::vector<T> & v, T & min, T & max, unsigned int & indexMin, unsigned int & indexMax)
00222 {
00223         uMinMax(v.data(), v.size(), min, max, indexMin, indexMax);
00224 }
00225 
00233 template<class T>
00234 inline void uMinMax(const T * v, unsigned int size, T & min, T & max)
00235 {
00236         unsigned int indexMin;
00237         unsigned int indexMax;
00238         uMinMax(v, size, min, max, indexMin, indexMax);
00239 }
00240 
00247 template<class T>
00248 inline void uMinMax(const std::vector<T> & v, T & min, T & max)
00249 {
00250         uMinMax(v.data(), v.size(), min, max);
00251 }
00252 
00258 template<class T>
00259 inline int uSign(const T & v)
00260 {
00261         if(v < 0)
00262         {
00263                 return -1;
00264         }
00265         else
00266         {
00267                 return 1;
00268         }
00269 }
00270 
00276 template<class T>
00277 inline T uSum(const std::list<T> & list)
00278 {
00279         T sum = 0;
00280         for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00281         {
00282                 sum += *i;
00283         }
00284         return sum;
00285 }
00286 
00293 template<class T>
00294 inline T uSum(const T * v, unsigned int size)
00295 {
00296         T sum = 0;
00297         if(v && size)
00298         {
00299                 for(unsigned int i=0; i<size; ++i)
00300                 {
00301                         sum += v[i];
00302                 }
00303         }
00304         return sum;
00305 }
00306 
00312 template<class T>
00313 inline T uSum(const std::vector<T> & v)
00314 {
00315         return uSum(v.data(), v.size());
00316 }
00317 
00325 template<class T>
00326 inline T uSumSquared(const T * v, unsigned int size, T subtract = T())
00327 {
00328         T sum = 0;
00329         if(v && size)
00330         {
00331                 for(unsigned int i=0; i<size; ++i)
00332                 {
00333                         sum += (v[i]-subtract)*(v[i]-subtract);
00334                 }
00335         }
00336         return sum;
00337 }
00338 
00345 template<class T>
00346 inline T uSumSquared(const std::vector<T> & v, T subtract = T())
00347 {
00348         return uSumSquared(v.data(), v.size(), subtract);
00349 }
00350 
00357 template<class T>
00358 inline T uMean(const T * v, unsigned int size)
00359 {
00360         T buf = 0;
00361         if(v && size)
00362         {
00363                 for(unsigned int i=0; i<size; ++i)
00364                 {
00365                         buf += v[i];
00366                 }
00367                 buf /= size;
00368         }
00369         return buf;
00370 }
00371 
00377 template<class T>
00378 inline T uMean(const std::list<T> & list)
00379 {
00380         T m = 0;
00381         if(list.size())
00382         {
00383                 for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00384                 {
00385                         m += *i;
00386                 }
00387                 m /= list.size();
00388         }
00389         return m;
00390 }
00391 
00397 template<class T>
00398 inline T uMean(const std::vector<T> & v)
00399 {
00400         return uMean(v.data(), v.size());
00401 }
00402 
00411 template<class T>
00412 inline T uMeanSquaredError(const T * x, unsigned int sizeX, const T * y, unsigned int sizeY)
00413 {
00414         T sum = 0;
00415         if(x && y && sizeX == sizeY)
00416         {
00417                 for(unsigned int i=0; i<sizeX; ++i)
00418                 {
00419                         T diff = x[i]-y[i];
00420                         sum += diff*diff;
00421                 }
00422                 return sum/(T)sizeX;
00423         }
00424         return (T)-1;
00425 }
00426 
00433 template<class T>
00434 inline T uMeanSquaredError(const std::vector<T> & x, const std::vector<T> & y)
00435 {
00436         return uMeanSquaredError(x.data(), x.size(), y.data(), y.size());
00437 }
00438 
00447 template<class T>
00448 inline T uStdDev(const T * v, unsigned int size, T meanV)
00449 {
00450         T buf = 0;
00451         if(v && size>1)
00452         {
00453                 float sum = 0;
00454                 for(unsigned int i=0; i<size; ++i)
00455                 {
00456                         sum += (v[i]-meanV)*(v[i]-meanV);
00457                 }
00458                 buf = sqrt(sum/(size-1));
00459         }
00460         return buf;
00461 }
00462 
00470 template<class T>
00471 inline T uStdDev(const std::list<T> & list, const T & m)
00472 {
00473         T buf = 0;
00474         if(list.size()>1)
00475         {
00476                 float sum = 0;
00477                 for(typename std::list<T>::const_iterator i=list.begin(); i!=list.end(); ++i)
00478                 {
00479                         sum += (*i-m)*(*i-m);
00480                 }
00481                 buf = sqrt(sum/(list.size()-1));
00482         }
00483         return buf;
00484 }
00485 
00492 template<class T>
00493 inline T uStdDev(const T * v, unsigned int size)
00494 {
00495         T m = uMean(v, size);
00496         return uStdDev(v, size, m);
00497 }
00498 
00506 template<class T>
00507 inline T uStdDev(const std::vector<T> & v, const T & m)
00508 {
00509         return uStdDev(v.data(), v.size(), m);
00510 }
00511 
00516 template<class T>
00517 inline T uNorm(const std::vector<T> & v)
00518 {
00519         float sum = 0.0f;
00520         for(unsigned int i=0; i<v.size(); ++i)
00521         {
00522                 sum += v[i]*v[i];
00523         }
00524         return std::sqrt(sum);
00525 }
00526 
00531 template<class T>
00532 inline std::vector<T> uNormalize(const std::vector<T> & v)
00533 {
00534         float norm = uNorm(v);
00535         if(norm == 0)
00536         {
00537                 return v;
00538         }
00539         else
00540         {
00541                 std::vector<T> r(v.size());
00542                 for(unsigned int i=0; i<v.size(); ++i)
00543                 {
00544                         r[i] = v[i]/norm;
00545                 }
00546                 return r;
00547         }
00548 }
00549 
00553 template<class T>
00554 inline std::list<unsigned int> uLocalMaxima(const T * v, unsigned int size)
00555 {
00556         std::list<unsigned int> maxima;
00557         if(size)
00558         {
00559                 for(unsigned int i=0; i<size; ++i)
00560                 {
00561                         if(i == 0)
00562                         {
00563                                 // first item
00564                                 if((i+1 < size && v[i] > v[i+1]) ||
00565                                         i+1 >= size)
00566                                 {
00567                                         maxima.push_back(i);
00568                                 }
00569                         }
00570                         else if(i == size - 1)
00571                         {
00572                                 //last item
00573                                 if((i >= 1 && v[i] > v[i-1]) ||
00574                                         i == 0)
00575                                 {
00576                                         maxima.push_back(i);
00577                                 }
00578                         }
00579                         else
00580                         {
00581                                 //all others, check previous and next
00582                                 if(v[i] > v[i-1] && v[i] > v[i+1])
00583                                 {
00584                                         maxima.push_back(i);
00585                                 }
00586                         }
00587                 }
00588         }
00589         return maxima;
00590 }
00591 
00595 template<class T>
00596 inline std::list<unsigned int> uLocalMaxima(const std::vector<T> & v)
00597 {
00598         return uLocalMaxima(v.data(), v.size());
00599 }
00600 
00605 enum UXMatchMethod{UXCorrRaw, UXCorrBiased, UXCorrUnbiased, UXCorrCoeff, UXCovRaw, UXCovBiased, UXCovUnbiased, UXCovCoeff};
00606 
00616 template<class T>
00617 inline std::vector<T> uXMatch(const T * vA, const T * vB, unsigned int sizeA, unsigned int sizeB, UXMatchMethod method)
00618 {
00619         if(!vA || !vB || sizeA == 0 || sizeB == 0)
00620         {
00621                 return std::vector<T>();
00622         }
00623 
00624         std::vector<T> result(sizeA + sizeB - 1);
00625 
00626         T meanA = 0;
00627         T meanB = 0;
00628         if(method > UXCorrCoeff)
00629         {
00630                 meanA = uMean(vA, sizeA);
00631                 meanB = uMean(vB, sizeB);
00632         }
00633 
00634         T den = 1;
00635         if(method == UXCorrCoeff || method == UXCovCoeff)
00636         {
00637                 den = std::sqrt(uSumSquared(vA, sizeA, meanA) * uSumSquared(vB, sizeB, meanB));
00638         }
00639         else if(method == UXCorrBiased || method == UXCovBiased)
00640         {
00641                 den = (T)std::max(sizeA, sizeB);
00642         }
00643 
00644         if(sizeA == sizeB)
00645         {
00646                 T resultA;
00647                 T resultB;
00648 
00649                 int posA;
00650                 int posB;
00651                 unsigned int j;
00652 
00653                 // Optimization, filling two results at once
00654                 for(unsigned int i=0; i<sizeA; ++i)
00655                 {
00656                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00657                         {
00658                                 den = 0;
00659                         }
00660 
00661                         posA = sizeA - i - 1;
00662                         posB = sizeB - i - 1;
00663                         resultA = 0;
00664                         resultB = 0;
00665                         for(j=0; (j + posB) < sizeB && (j + posA) < sizeA; ++j)
00666                         {
00667                                 resultA += (vA[j] - meanA) * (vB[j + posB] - meanB);
00668                                 resultB += (vA[j + posA] - meanA) * (vB[j] - meanB);
00669                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00670                                 {
00671                                         ++den;
00672                                 }
00673                         }
00674 
00675                         result[i] = resultA / den;
00676                         result[result.size()-1 -i] = resultB / den;
00677                 }
00678         }
00679         else
00680         {
00681                 for(unsigned int i=0; i<result.size(); ++i)
00682                 {
00683                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00684                         {
00685                                 den = 0;
00686                         }
00687 
00688                         int posB = sizeB - i - 1;
00689                         T r = 0;
00690                         if(posB >= 0)
00691                         {
00692                                 for(unsigned int j=0; (j + posB) < sizeB && j < sizeA; ++j)
00693                                 {
00694                                         r += (vA[j] - meanA) * (vB[j + posB] - meanB);
00695                                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00696                                         {
00697                                                 ++den;
00698                                         }
00699                                 }
00700                         }
00701                         else
00702                         {
00703                                 int posA = posB*-1;
00704                                 for(unsigned int i=0; (i+posA) < sizeA && i < sizeB; ++i)
00705                                 {
00706                                         r += (vA[i+posA] - meanA) * (vB[i] - meanB);
00707                                         if(method == UXCorrUnbiased || method == UXCovUnbiased)
00708                                         {
00709                                                 ++den;
00710                                         }
00711                                 }
00712                         }
00713 
00714                         result[i] = r / den;
00715                 }
00716         }
00717 
00718         return result;
00719 }
00720 
00728 template<class T>
00729 inline std::vector<T> uXMatch(const std::vector<T> & vA, const std::vector<T> & vB, UXMatchMethod method)
00730 {
00731         return uXMatch(vA.data(), vB.data(), vA.size(), vB.size(), method);
00732 }
00733 
00744 template<class T>
00745 inline T uXMatch(const T * vA, const T * vB, unsigned int sizeA, unsigned int sizeB, unsigned int index, UXMatchMethod method)
00746 {
00747         T result = 0;
00748         if(!vA || !vB || sizeA == 0 || sizeB == 0)
00749         {
00750                 return result;
00751         }
00752 
00753         T meanA = 0;
00754         T meanB = 0;
00755         if(method > UXCorrCoeff)
00756         {
00757                 meanA = uMean(vA, sizeA);
00758                 meanB = uMean(vB, sizeB);
00759         }
00760         unsigned int size = sizeA + sizeB - 1;
00761 
00762         T den = 1;
00763         if(method == UXCorrCoeff || method == UXCovCoeff)
00764         {
00765                 den = std::sqrt(uSumSquared(vA, sizeA, meanA) * uSumSquared(vB, sizeB, meanB));
00766         }
00767         else if(method == UXCorrBiased || method == UXCovBiased)
00768         {
00769                 den = (T)std::max(sizeA, sizeB);
00770         }
00771         else if(method == UXCorrUnbiased || method == UXCovUnbiased)
00772         {
00773                 den = 0;
00774         }
00775 
00776         if(index < size)
00777         {
00778                 int posB = sizeB - index - 1;
00779                 unsigned int i;
00780                 if(posB >= 0)
00781                 {
00782                         for(i=0; (i + posB) < sizeB && i < sizeA; ++i)
00783                         {
00784                                 result += (vA[i] - meanA) * (vB[i + posB] - meanB);
00785                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00786                                 {
00787                                         ++den;
00788                                 }
00789                         }
00790                 }
00791                 else
00792                 {
00793                         int posA = posB*-1;
00794                         for(i=0; (i+posA) < sizeA && i < sizeB; ++i)
00795                         {
00796                                 result += (vA[i+posA] - meanA) * (vB[i] - meanB);
00797                                 if(method == UXCorrUnbiased || method == UXCovUnbiased)
00798                                 {
00799                                         ++den;
00800                                 }
00801                         }
00802                 }
00803         }
00804         return result / den;
00805 }
00806 
00817 template<class T>
00818 inline T uXMatch(const std::vector<T> & vA, const std::vector<T> & vB, unsigned int index, UXMatchMethod method)
00819 {
00820         return uXMatch(vA.data(), vB.data(), vA.size(), vB.size(), index, method);
00821 }
00822 
00828 inline std::vector<float> uHamming(unsigned int L)
00829 {
00830         std::vector<float> w(L);
00831         unsigned int N = L-1;
00832         float pi = 3.14159265f;
00833         for(unsigned int n=0; n<N; ++n)
00834         {
00835                 w[n] = 0.54f-0.46f*std::cos(2.0f*pi*float(n)/float(N));
00836         }
00837         return w;
00838 }
00839 
00840 #endif // UMATH_H
 All Classes Files Functions Variables Enumerations Friends Defines