00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00261
00262 #ifndef VL_MATHOP_INSTANTIATING
00263
00264 #include "mathop.h"
00265 #include "mathop_sse2.h"
00266 #include "mathop_avx.h"
00267 #include <math.h>
00268
00269 #undef FLT
00270 #define FLT VL_TYPE_FLOAT
00271 #define VL_MATHOP_INSTANTIATING
00272 #include "mathop.c"
00273
00274 #undef FLT
00275 #define FLT VL_TYPE_DOUBLE
00276 #define VL_MATHOP_INSTANTIATING
00277 #include "mathop.c"
00278 #endif
00279
00280
00281 #ifdef VL_MATHOP_INSTANTIATING
00282 #include "float.th"
00283
00284 #undef COMPARISONFUNCTION_TYPE
00285 #undef COMPARISONFUNCTION3_TYPE
00286 #if (FLT == VL_TYPE_FLOAT)
00287 # define COMPARISONFUNCTION_TYPE VlFloatVectorComparisonFunction
00288 # define COMPARISONFUNCTION3_TYPE VlFloatVector3ComparisonFunction
00289 #else
00290 # define COMPARISONFUNCTION_TYPE VlDoubleVectorComparisonFunction
00291 # define COMPARISONFUNCTION3_TYPE VlDoubleVector3ComparisonFunction
00292 #endif
00293
00294
00295
00296 VL_EXPORT T
00297 VL_XCAT(_vl_distance_l2_, SFX)
00298 (vl_size dimension, T const * X, T const * Y)
00299 {
00300 T const * X_end = X + dimension ;
00301 T acc = 0.0 ;
00302 while (X < X_end) {
00303 T d = *X++ - *Y++ ;
00304 acc += d * d ;
00305 }
00306 return acc ;
00307 }
00308
00309 VL_EXPORT T
00310 VL_XCAT(_vl_distance_l1_, SFX)
00311 (vl_size dimension, T const * X, T const * Y)
00312 {
00313 T const * X_end = X + dimension ;
00314 T acc = 0.0 ;
00315 while (X < X_end) {
00316 T d = *X++ - *Y++ ;
00317 acc += VL_MAX(d, -d) ;
00318 }
00319 return acc ;
00320 }
00321
00322 VL_EXPORT T
00323 VL_XCAT(_vl_distance_chi2_, SFX)
00324 (vl_size dimension, T const * X, T const * Y)
00325 {
00326 T const * X_end = X + dimension ;
00327 T acc = 0.0 ;
00328 while (X < X_end) {
00329 T a = *X++ ;
00330 T b = *Y++ ;
00331 T delta = a - b ;
00332 T denom = (a + b) ;
00333 T numer = delta * delta ;
00334 if (denom) {
00335 T ratio = numer / denom ;
00336 acc += ratio ;
00337 }
00338 }
00339 return acc ;
00340 }
00341
00342 VL_EXPORT T
00343 VL_XCAT(_vl_distance_hellinger_, SFX)
00344 (vl_size dimension, T const * X, T const * Y)
00345 {
00346 T const * X_end = X + dimension ;
00347 T acc = 0.0 ;
00348 while (X < X_end) {
00349 T a = *X++ ;
00350 T b = *Y++ ;
00351 #if (FLT == VL_TYPE_FLOAT)
00352 acc += a + b - 2.0 * sqrtf (a*b) ;
00353 #else
00354 acc += a + b - 2.0 * sqrt (a*b) ;
00355 #endif
00356 }
00357 return acc ;
00358 }
00359
00360 VL_EXPORT T
00361 VL_XCAT(_vl_distance_js_, SFX)
00362 (vl_size dimension, T const * X, T const * Y)
00363 {
00364 T const * X_end = X + dimension ;
00365 T acc = 0.0 ;
00366 while (X < X_end) {
00367 T x = *X++ ;
00368 T y = *Y++ ;
00369 if (x) acc += x - x * VL_XCAT(vl_log2_,SFX)(1 + y/x) ;
00370 if (y) acc += y - y * VL_XCAT(vl_log2_,SFX)(1 + x/y) ;
00371 }
00372 return acc ;
00373 }
00374
00375 VL_EXPORT T
00376 VL_XCAT(_vl_kernel_l2_, SFX)
00377 (vl_size dimension, T const * X, T const * Y)
00378 {
00379 T const * X_end = X + dimension ;
00380 T acc = 0.0 ;
00381 while (X < X_end) {
00382 T a = *X++ ;
00383 T b = *Y++ ;
00384 acc += a * b ;
00385 }
00386 return acc ;
00387 }
00388
00389 VL_EXPORT T
00390 VL_XCAT(_vl_kernel_l1_, SFX)
00391 (vl_size dimension, T const * X, T const * Y)
00392 {
00393 T const * X_end = X + dimension ;
00394 T acc = 0.0 ;
00395 while (X < X_end) {
00396 T a = *X++ ;
00397 T b = *Y++ ;
00398 T a_ = VL_XCAT(vl_abs_, SFX) (a) ;
00399 T b_ = VL_XCAT(vl_abs_, SFX) (b) ;
00400 acc += a_ + b_ - VL_XCAT(vl_abs_, SFX) (a - b) ;
00401 }
00402 return acc / ((T)2) ;
00403 }
00404
00405 VL_EXPORT T
00406 VL_XCAT(_vl_kernel_chi2_, SFX)
00407 (vl_size dimension, T const * X, T const * Y)
00408 {
00409 T const * X_end = X + dimension ;
00410 T acc = 0.0 ;
00411 while (X < X_end) {
00412 T a = *X++ ;
00413 T b = *Y++ ;
00414 T denom = (a + b) ;
00415 if (denom) {
00416 T numer = 2 * a * b ;
00417 T ratio = numer / denom ;
00418 acc += ratio ;
00419 }
00420 }
00421 return acc ;
00422 }
00423
00424 VL_EXPORT T
00425 VL_XCAT(_vl_kernel_hellinger_, SFX)
00426 (vl_size dimension, T const * X, T const * Y)
00427 {
00428 T const * X_end = X + dimension ;
00429 T acc = 0.0 ;
00430 while (X < X_end) {
00431 T a = *X++ ;
00432 T b = *Y++ ;
00433 #if (FLT == VL_TYPE_FLOAT)
00434 acc += sqrtf (a*b) ;
00435 #else
00436 acc += sqrt (a*b) ;
00437 #endif
00438 }
00439 return acc ;
00440 }
00441
00442 VL_EXPORT T
00443 VL_XCAT(_vl_kernel_js_, SFX)
00444 (vl_size dimension, T const * X, T const * Y)
00445 {
00446 T const * X_end = X + dimension ;
00447 T acc = 0.0 ;
00448 while (X < X_end) {
00449 T x = *X++ ;
00450 T y = *Y++ ;
00451 if (x) acc += x * VL_XCAT(vl_log2_,SFX)(1 + y/x) ;
00452 if (y) acc += y * VL_XCAT(vl_log2_,SFX)(1 + x/y) ;
00453 }
00454 return (T)0.5 * acc ;
00455 }
00456
00457 VL_EXPORT T
00458 VL_XCAT(_vl_distance_mahalanobis_sq_, SFX)
00459 (vl_size dimension, T const * X, T const * MU, T const * S)
00460 {
00461 T const * X_end = X + dimension ;
00462 T acc = 0.0 ;
00463 while (X < X_end) {
00464 T d = *X++ - *MU++ ;
00465 acc += d * d * (*S++) ;
00466 }
00467 return acc ;
00468 }
00469
00470
00471
00472 VL_EXPORT COMPARISONFUNCTION_TYPE
00473 VL_XCAT(vl_get_vector_comparison_function_, SFX)(VlVectorComparisonType type)
00474 {
00475 COMPARISONFUNCTION_TYPE function = 0 ;
00476 switch (type) {
00477 case VlDistanceL2 : function = VL_XCAT(_vl_distance_l2_, SFX) ; break ;
00478 case VlDistanceL1 : function = VL_XCAT(_vl_distance_l1_, SFX) ; break ;
00479 case VlDistanceChi2 : function = VL_XCAT(_vl_distance_chi2_, SFX) ; break ;
00480 case VlDistanceHellinger : function = VL_XCAT(_vl_distance_hellinger_, SFX) ; break ;
00481 case VlDistanceJS : function = VL_XCAT(_vl_distance_js_, SFX) ; break ;
00482 case VlKernelL2 : function = VL_XCAT(_vl_kernel_l2_, SFX) ; break ;
00483 case VlKernelL1 : function = VL_XCAT(_vl_kernel_l1_, SFX) ; break ;
00484 case VlKernelChi2 : function = VL_XCAT(_vl_kernel_chi2_, SFX) ; break ;
00485 case VlKernelHellinger : function = VL_XCAT(_vl_kernel_hellinger_, SFX) ; break ;
00486 case VlKernelJS : function = VL_XCAT(_vl_kernel_js_, SFX) ; break ;
00487 default: abort() ;
00488 }
00489
00490 #ifndef VL_DISABLE_SSE2
00491
00492 if (vl_cpu_has_sse2() && vl_get_simd_enabled()) {
00493 switch (type) {
00494 case VlDistanceL2 : function = VL_XCAT(_vl_distance_l2_sse2_, SFX) ; break ;
00495 case VlDistanceL1 : function = VL_XCAT(_vl_distance_l1_sse2_, SFX) ; break ;
00496 case VlDistanceChi2 : function = VL_XCAT(_vl_distance_chi2_sse2_, SFX) ; break ;
00497 case VlKernelL2 : function = VL_XCAT(_vl_kernel_l2_sse2_, SFX) ; break ;
00498 case VlKernelL1 : function = VL_XCAT(_vl_kernel_l1_sse2_, SFX) ; break ;
00499 case VlKernelChi2 : function = VL_XCAT(_vl_kernel_chi2_sse2_, SFX) ; break ;
00500 default: break ;
00501 }
00502 }
00503 #endif
00504
00505 #ifndef VL_DISABLE_AVX
00506
00507 if (vl_cpu_has_avx() && vl_get_simd_enabled()) {
00508 switch (type) {
00509 case VlDistanceL2 : function = VL_XCAT(_vl_distance_l2_avx_, SFX) ; break ;
00510 default: break ;
00511 }
00512 }
00513 #endif
00514
00515 return function ;
00516 }
00517
00518
00519
00520 VL_EXPORT COMPARISONFUNCTION3_TYPE
00521 VL_XCAT(vl_get_vector_3_comparison_function_, SFX)(VlVectorComparisonType type)
00522 {
00523 COMPARISONFUNCTION3_TYPE function = 0 ;
00524 switch (type) {
00525 case VlDistanceMahalanobis : function = VL_XCAT(_vl_distance_mahalanobis_sq_, SFX) ; break ;
00526 default: abort() ;
00527 }
00528
00529 #ifndef VL_DISABLE_SSE2
00530
00531 if (vl_cpu_has_sse2() && vl_get_simd_enabled()) {
00532 switch (type) {
00533 case VlDistanceMahalanobis : function = VL_XCAT(_vl_distance_mahalanobis_sq_sse2_, SFX) ; break ;
00534 default: break ;
00535 }
00536 }
00537 #endif
00538
00539 #ifndef VL_DISABLE_AVX
00540
00541 if (vl_cpu_has_avx() && vl_get_simd_enabled()) {
00542 switch (type) {
00543 case VlDistanceMahalanobis : function = VL_XCAT(_vl_distance_mahalanobis_sq_avx_, SFX) ; break ;
00544 default: break ;
00545 }
00546 }
00547 #endif
00548
00549 return function ;
00550 }
00551
00552
00553
00554 VL_EXPORT void
00555 VL_XCAT(vl_eval_vector_comparison_on_all_pairs_, SFX)
00556 (T * result, vl_size dimension,
00557 T const * X, vl_size numDataX,
00558 T const * Y, vl_size numDataY,
00559 COMPARISONFUNCTION_TYPE function)
00560 {
00561 vl_uindex xi ;
00562 vl_uindex yi ;
00563
00564 if (dimension == 0) return ;
00565 if (numDataX == 0) return ;
00566 assert (X) ;
00567
00568 if (Y) {
00569 if (numDataY == 0) return ;
00570 for (yi = 0 ; yi < numDataY ; ++ yi) {
00571 for (xi = 0 ; xi < numDataX ; ++ xi) {
00572 *result++ = (*function)(dimension, X, Y) ;
00573 X += dimension ;
00574 }
00575 X -= dimension * numDataX ;
00576 Y += dimension ;
00577 }
00578 } else {
00579 T * resultTransp = result ;
00580 Y = X ;
00581 for (yi = 0 ; yi < numDataX ; ++ yi) {
00582 for (xi = 0 ; xi <= yi ; ++ xi) {
00583 T z = (*function)(dimension, X, Y) ;
00584 X += dimension ;
00585 *result = z ;
00586 *resultTransp = z ;
00587 result += 1 ;
00588 resultTransp += numDataX ;
00589 }
00590 X -= dimension * (yi + 1) ;
00591 Y += dimension ;
00592 result += numDataX - (yi + 1) ;
00593 resultTransp += 1 - (yi + 1) * numDataX ;
00594 }
00595 }
00596 }
00597
00598
00599 #endif
00600
00601
00602
00603
00604
00605
00606 #ifndef VL_MATHOP_INSTANTIATING
00607
00640 void
00641 vl_svd2 (double* S, double *U, double *V, double const *M)
00642 {
00643 double m11 = M[0] ;
00644 double m21 = M[1] ;
00645 double m12 = M[2] ;
00646 double m22 = M[3] ;
00647 double cu1 = m11 ;
00648 double su1 = m21 ;
00649 double norm = sqrt(cu1*cu1 + su1*su1) ;
00650 double cu2, su2, cv2, sv2 ;
00651 double f, g, h ;
00652 double smin, smax ;
00653 cu1 /= norm ;
00654 su1 /= norm ;
00655
00656 f = cu1 * m11 + su1 * m21 ;
00657 g = cu1 * m12 + su1 * m22 ;
00658 h = - su1 * m12 + cu1 * m22 ;
00659
00660 vl_lapack_dlasv2 (&smin, &smax,
00661 &sv2, &cv2,
00662 &su2, &cu2,
00663 f, g, h) ;
00664
00665 assert(S) ;
00666 S[0] = smax ;
00667 S[1] = 0 ;
00668 S[2] = 0 ;
00669 S[3] = smin ;
00670
00671 if (U) {
00672 U[0] = cu2*cu1 - su2*su1 ;
00673 U[1] = su2*cu1 + cu2*su1 ;
00674 U[2] = - cu2*su1 - su2*cu1 ;
00675 U[3] = - su2*su1 + cu2*cu1 ;
00676 }
00677 if (V) {
00678 V[0] = cv2 ;
00679 V[1] = sv2 ;
00680 V[2] = - sv2 ;
00681 V[3] = cv2 ;
00682 }
00683 }
00684
00709 #define isign(i) ((i)<0 ? (-1) : (+1))
00710 #define sign(x) ((x)<0.0 ? (-1) : (+1))
00711
00712 void
00713 vl_lapack_dlasv2 (double *smin,
00714 double *smax,
00715 double *sv,
00716 double *cv,
00717 double *su,
00718 double *cu,
00719 double f,
00720 double g,
00721 double h)
00722 {
00723 double svt, cvt, sut, cut;
00724 double ft = f, gt = g, ht = h;
00725 double fa = fabs(f), ga = fabs(g), ha = fabs(h);
00726 int pmax = 1 ;
00727 int swap = 0 ;
00728 int glarge = 0 ;
00729 int tsign ;
00730 double fmh ;
00731 double d ;
00732 double dd ;
00733 double q ;
00734 double qq ;
00735 double s ;
00736 double ss ;
00737 double spq ;
00738 double dpq ;
00739 double a ;
00740 double tmp ;
00741 double tt;
00742
00743
00744 if (fa < ha) {
00745 pmax = 3 ;
00746 tmp =ft ; ft = ht ; ht = tmp ;
00747 tmp =fa ; fa = ha ; ha = tmp ;
00748 swap = 1 ;
00749 }
00750
00751 if (ga == 0.0) {
00752 *smin = ha ;
00753 *smax = fa ;
00754
00755 cut = 1.0 ; sut = 0.0 ;
00756 cvt = 1.0 ; svt = 0.0 ;
00757 }
00758 else {
00759 if (ga > fa) {
00760 pmax = 2 ;
00761 if ((fa / ga) < VL_EPSILON_D) {
00762 glarge = 1 ;
00763 *smax = ga ;
00764 if (ha > 1.0) {
00765 *smin = fa / (ga / ha) ;
00766 } else {
00767 *smin = (fa / ga) * ha ;
00768 }
00769 cut = 1.0 ; sut = ht / gt ;
00770 cvt = 1.0 ; svt = ft / gt ;
00771 }
00772 }
00773
00774 if (glarge == 0) {
00775 fmh = fa - ha ;
00776 if (fmh == fa) {
00777 d = 1.0 ;
00778 } else {
00779 d = fmh / fa ;
00780 }
00781 q = gt / ft ;
00782 s = 2.0 - d ;
00783 dd = d*d ;
00784 qq = q*q ;
00785 ss = s*s ;
00786 spq = sqrt(ss + qq) ;
00787 if (d == 0.0) {
00788 dpq = fabs(q) ;
00789 } else {
00790 dpq = sqrt(dd + qq) ;
00791 }
00792 a = 0.5 * (spq + dpq) ;
00793 *smin = ha / a;
00794 *smax = fa * a;
00795 if (qq==0.0) {
00796 if (d==0.0) {
00797 tmp = sign(ft)*2*sign(gt);
00798 }
00799 else {
00800 tmp = gt/(sign(ft)*fmh) + q/s;
00801 }
00802 } else {
00803 tmp = (q/(spq + s) + q/(dpq + d))*(1.0 + a);
00804 }
00805
00806 tt = sqrt(tmp*tmp + 4.0) ;
00807 cvt = 2.0 / tt ;
00808 svt = tmp / tt ;
00809 cut = (cvt + svt*q) / a ;
00810 sut = (ht / ft) * svt / a ;
00811 }
00812 }
00813 if (swap == 1) {
00814 *cu = svt ; *su = cvt ;
00815 *cv = sut ; *sv = cut ;
00816 } else {
00817 *cu = cut ; *su = sut ;
00818 *cv = cvt ; *sv = svt ;
00819 }
00820
00821 if (pmax==1) { tsign = sign(*cv) * sign(*cu) * sign(f) ; }
00822 if (pmax==2) { tsign = sign(*sv) * sign(*cu) * sign(g) ; }
00823 if (pmax==3) { tsign = sign(*sv) * sign(*su) * sign(h) ; }
00824 *smax = isign(tsign) * (*smax);
00825 *smin = isign(tsign * sign(f) * sign(h)) * (*smin) ;
00826 }
00827
00828
00838 VL_EXPORT int
00839 vl_solve_linear_system_3 (double * x, double const * A, double const *b)
00840 {
00841 int err ;
00842 double M[3*4] ;
00843 M[0] = A[0] ;
00844 M[1] = A[1] ;
00845 M[2] = A[2] ;
00846 M[3] = A[3] ;
00847 M[4] = A[4] ;
00848 M[5] = A[5] ;
00849 M[6] = A[6] ;
00850 M[7] = A[7] ;
00851 M[8] = A[8] ;
00852 M[9] = b[0] ;
00853 M[10] = b[1] ;
00854 M[11] = b[2] ;
00855 err = vl_gaussian_elimination(M,3,4) ;
00856 x[0] = M[9] ;
00857 x[1] = M[10] ;
00858 x[2] = M[11] ;
00859 return err ;
00860 }
00861
00871 VL_EXPORT int
00872 vl_solve_linear_system_2 (double * x, double const * A, double const *b)
00873 {
00874 int err ;
00875 double M[2*3] ;
00876 M[0] = A[0] ;
00877 M[1] = A[1] ;
00878 M[2] = A[2] ;
00879 M[3] = A[3] ;
00880 M[4] = b[0];
00881 M[5] = b[1] ;
00882 err = vl_gaussian_elimination(M,2,3) ;
00883 x[0] = M[4] ;
00884 x[1] = M[5] ;
00885 return err ;
00886 }
00887
00905 VL_EXPORT vl_bool
00906 vl_gaussian_elimination (double * A, vl_size numRows, vl_size numColumns)
00907 {
00908 vl_index i, j, ii, jj ;
00909 assert(A) ;
00910 assert(numRows <= numColumns) ;
00911
00912 #define Aat(i,j) A[(i) + (j)*numRows]
00913
00914
00915 for(j = 0 ; j < (signed)numRows ; ++j) {
00916 double maxa = 0 ;
00917 double maxabsa = 0 ;
00918 vl_index maxi = -1 ;
00919 double tmp ;
00920
00921 #if 0
00922 {
00923 vl_index iii, jjj ;
00924 for (iii = 0 ; iii < 2 ; ++iii) {
00925 for (jjj = 0 ; jjj < 3 ; ++jjj) {
00926 VL_PRINTF("%5.2g ", Aat(iii,jjj)) ;
00927
00928 }
00929 VL_PRINTF("\n") ;
00930 }
00931 VL_PRINTF("\n") ;
00932 }
00933 #endif
00934
00935
00936 for (i = j ; i < (signed)numRows ; ++i) {
00937 double a = Aat(i,j) ;
00938 double absa = vl_abs_d (a) ;
00939 if (absa > maxabsa) {
00940 maxa = a ;
00941 maxabsa = absa ;
00942 maxi = i ;
00943 }
00944 }
00945 i = maxi ;
00946
00947
00948 if (maxabsa < 1e-10) return VL_ERR_OVERFLOW ;
00949
00950
00951 for(jj = j ; jj < (signed)numColumns ; ++jj) {
00952 tmp = Aat(i,jj) ; Aat(i,jj) = Aat(j,jj) ; Aat(j,jj) = tmp ;
00953 Aat(j,jj) /= maxa ;
00954 }
00955
00956 #if 0
00957 {
00958 vl_index iii, jjj ;
00959 VL_PRINTF("after swap %d %d\n", j, i);
00960 for (iii = 0 ; iii < 2 ; ++iii) {
00961 for (jjj = 0 ; jjj < 3 ; ++jjj) {
00962 VL_PRINTF("%5.2g ", Aat(iii,jjj)) ;
00963
00964 }
00965 VL_PRINTF("\n") ;
00966 }
00967 VL_PRINTF("\n") ;
00968 }
00969 #endif
00970
00971
00972 for (ii = j+1 ; ii < (signed)numRows ; ++ii) {
00973 double x = Aat(ii,j) ;
00974 for (jj = j ; jj < (signed)numColumns ; ++jj) {
00975 Aat(ii,jj) -= x * Aat(j,jj) ;
00976 }
00977 }
00978
00979 #if 0
00980 {
00981 VL_PRINTF("after elimination\n");
00982
00983 vl_index iii, jjj ;
00984 for (iii = 0 ; iii < 2 ; ++iii) {
00985 for (jjj = 0 ; jjj < 3 ; ++jjj) {
00986 VL_PRINTF("%5.2g ", Aat(iii,jjj)) ;
00987
00988 }
00989 VL_PRINTF("\n") ;
00990 }
00991 VL_PRINTF("\n") ;
00992 }
00993 #endif
00994
00995 }
00996
00997
00998 for (i = numRows - 1 ; i > 0 ; --i) {
00999
01000 for (ii = i - 1 ; ii >= 0 ; --ii) {
01001 double x = Aat(ii,i) ;
01002
01003 for (j = numRows ; j < (signed)numColumns ; ++j) {
01004 Aat(ii,j) -= x * Aat(i,j) ;
01005 }
01006 }
01007 }
01008
01009 #if 0
01010 {
01011 VL_PRINTF("after substitution\n");
01012
01013 vl_index iii, jjj ;
01014 for (iii = 0 ; iii < 2 ; ++iii) {
01015 for (jjj = 0 ; jjj < 3 ; ++jjj) {
01016 VL_PRINTF("%5.2g ", Aat(iii,jjj)) ;
01017
01018 }
01019 VL_PRINTF("\n") ;
01020 }
01021 VL_PRINTF("\n") ;
01022 }
01023 #endif
01024
01025
01026 return VL_ERR_OK ;
01027 }
01028
01029
01030 #endif
01031
01032 #undef VL_MATHOP_INSTANTIATING