UtiLite
0.3.1
A lite utilities library
|
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