include/opencv2/flann/dist.h
Go to the documentation of this file.
00001 /***********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  * Copyright 2008-2009  Marius Muja (mariusm@cs.ubc.ca). All rights reserved.
00005  * Copyright 2008-2009  David G. Lowe (lowe@cs.ubc.ca). All rights reserved.
00006  *
00007  * THE BSD LICENSE
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted provided that the following conditions
00011  * are met:
00012  *
00013  * 1. Redistributions of source code must retain the above copyright
00014  *    notice, this list of conditions and the following disclaimer.
00015  * 2. Redistributions in binary form must reproduce the above copyright
00016  *    notice, this list of conditions and the following disclaimer in the
00017  *    documentation and/or other materials provided with the distribution.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00020  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00021  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00022  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00024  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00025  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00026  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00028  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *************************************************************************/
00030 
00031 #ifndef OPENCV_FLANN_DIST_H_
00032 #define OPENCV_FLANN_DIST_H_
00033 
00034 #include <cmath>
00035 #include <cstdlib>
00036 #include <string.h>
00037 #ifdef _MSC_VER
00038 typedef unsigned __int32 uint32_t;
00039 typedef unsigned __int64 uint64_t;
00040 #else
00041 #include <stdint.h>
00042 #endif
00043 
00044 #include "defines.h"
00045 
00046 #ifdef __ARM_NEON__
00047 #include "arm_neon.h"
00048 #endif
00049 
00050 namespace cvflann
00051 {
00052 
00053 template<typename T>
00054 inline T abs(T x) { return (x<0) ? -x : x; }
00055 
00056 template<>
00057 inline int abs<int>(int x) { return ::abs(x); }
00058 
00059 template<>
00060 inline float abs<float>(float x) { return fabsf(x); }
00061 
00062 template<>
00063 inline double abs<double>(double x) { return fabs(x); }
00064 
00065 template<typename T>
00066 struct Accumulator { typedef T Type; };
00067 template<>
00068 struct Accumulator<unsigned char>  { typedef float Type; };
00069 template<>
00070 struct Accumulator<unsigned short> { typedef float Type; };
00071 template<>
00072 struct Accumulator<unsigned int> { typedef float Type; };
00073 template<>
00074 struct Accumulator<char>   { typedef float Type; };
00075 template<>
00076 struct Accumulator<short>  { typedef float Type; };
00077 template<>
00078 struct Accumulator<int> { typedef float Type; };
00079 
00080 #undef True
00081 #undef False
00082 
00083 class True
00084 {
00085 };
00086 
00087 class False
00088 {
00089 };
00090 
00091 
00098 template<class T>
00099 struct L2_Simple
00100 {
00101     typedef True is_kdtree_distance;
00102     typedef True is_vector_space_distance;
00103 
00104     typedef T ElementType;
00105     typedef typename Accumulator<T>::Type ResultType;
00106 
00107     template <typename Iterator1, typename Iterator2>
00108     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
00109     {
00110         ResultType result = ResultType();
00111         ResultType diff;
00112         for(size_t i = 0; i < size; ++i ) {
00113             diff = *a++ - *b++;
00114             result += diff*diff;
00115         }
00116         return result;
00117     }
00118 
00119     template <typename U, typename V>
00120     inline ResultType accum_dist(const U& a, const V& b, int) const
00121     {
00122         return (a-b)*(a-b);
00123     }
00124 };
00125 
00126 
00127 
00131 template<class T>
00132 struct L2
00133 {
00134     typedef True is_kdtree_distance;
00135     typedef True is_vector_space_distance;
00136 
00137     typedef T ElementType;
00138     typedef typename Accumulator<T>::Type ResultType;
00139 
00149     template <typename Iterator1, typename Iterator2>
00150     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00151     {
00152         ResultType result = ResultType();
00153         ResultType diff0, diff1, diff2, diff3;
00154         Iterator1 last = a + size;
00155         Iterator1 lastgroup = last - 3;
00156 
00157         /* Process 4 items with each loop for efficiency. */
00158         while (a < lastgroup) {
00159             diff0 = (ResultType)(a[0] - b[0]);
00160             diff1 = (ResultType)(a[1] - b[1]);
00161             diff2 = (ResultType)(a[2] - b[2]);
00162             diff3 = (ResultType)(a[3] - b[3]);
00163             result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00164             a += 4;
00165             b += 4;
00166 
00167             if ((worst_dist>0)&&(result>worst_dist)) {
00168                 return result;
00169             }
00170         }
00171         /* Process last 0-3 pixels.  Not needed for standard vector lengths. */
00172         while (a < last) {
00173             diff0 = (ResultType)(*a++ - *b++);
00174             result += diff0 * diff0;
00175         }
00176         return result;
00177     }
00178 
00185     template <typename U, typename V>
00186     inline ResultType accum_dist(const U& a, const V& b, int) const
00187     {
00188         return (a-b)*(a-b);
00189     }
00190 };
00191 
00192 
00193 /*
00194  * Manhattan distance functor, optimized version
00195  */
00196 template<class T>
00197 struct L1
00198 {
00199     typedef True is_kdtree_distance;
00200     typedef True is_vector_space_distance;
00201 
00202     typedef T ElementType;
00203     typedef typename Accumulator<T>::Type ResultType;
00204 
00211     template <typename Iterator1, typename Iterator2>
00212     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00213     {
00214         ResultType result = ResultType();
00215         ResultType diff0, diff1, diff2, diff3;
00216         Iterator1 last = a + size;
00217         Iterator1 lastgroup = last - 3;
00218 
00219         /* Process 4 items with each loop for efficiency. */
00220         while (a < lastgroup) {
00221             diff0 = (ResultType)abs(a[0] - b[0]);
00222             diff1 = (ResultType)abs(a[1] - b[1]);
00223             diff2 = (ResultType)abs(a[2] - b[2]);
00224             diff3 = (ResultType)abs(a[3] - b[3]);
00225             result += diff0 + diff1 + diff2 + diff3;
00226             a += 4;
00227             b += 4;
00228 
00229             if ((worst_dist>0)&&(result>worst_dist)) {
00230                 return result;
00231             }
00232         }
00233         /* Process last 0-3 pixels.  Not needed for standard vector lengths. */
00234         while (a < last) {
00235             diff0 = (ResultType)abs(*a++ - *b++);
00236             result += diff0;
00237         }
00238         return result;
00239     }
00240 
00244     template <typename U, typename V>
00245     inline ResultType accum_dist(const U& a, const V& b, int) const
00246     {
00247         return abs(a-b);
00248     }
00249 };
00250 
00251 
00252 
00253 template<class T>
00254 struct MinkowskiDistance
00255 {
00256     typedef True is_kdtree_distance;
00257     typedef True is_vector_space_distance;
00258 
00259     typedef T ElementType;
00260     typedef typename Accumulator<T>::Type ResultType;
00261 
00262     int order;
00263 
00264     MinkowskiDistance(int order_) : order(order_) {}
00265 
00275     template <typename Iterator1, typename Iterator2>
00276     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00277     {
00278         ResultType result = ResultType();
00279         ResultType diff0, diff1, diff2, diff3;
00280         Iterator1 last = a + size;
00281         Iterator1 lastgroup = last - 3;
00282 
00283         /* Process 4 items with each loop for efficiency. */
00284         while (a < lastgroup) {
00285             diff0 = (ResultType)abs(a[0] - b[0]);
00286             diff1 = (ResultType)abs(a[1] - b[1]);
00287             diff2 = (ResultType)abs(a[2] - b[2]);
00288             diff3 = (ResultType)abs(a[3] - b[3]);
00289             result += pow(diff0,order) + pow(diff1,order) + pow(diff2,order) + pow(diff3,order);
00290             a += 4;
00291             b += 4;
00292 
00293             if ((worst_dist>0)&&(result>worst_dist)) {
00294                 return result;
00295             }
00296         }
00297         /* Process last 0-3 pixels.  Not needed for standard vector lengths. */
00298         while (a < last) {
00299             diff0 = (ResultType)abs(*a++ - *b++);
00300             result += pow(diff0,order);
00301         }
00302         return result;
00303     }
00304 
00308     template <typename U, typename V>
00309     inline ResultType accum_dist(const U& a, const V& b, int) const
00310     {
00311         return pow(static_cast<ResultType>(abs(a-b)),order);
00312     }
00313 };
00314 
00315 
00316 
00317 template<class T>
00318 struct MaxDistance
00319 {
00320     typedef False is_kdtree_distance;
00321     typedef True is_vector_space_distance;
00322 
00323     typedef T ElementType;
00324     typedef typename Accumulator<T>::Type ResultType;
00325 
00331     template <typename Iterator1, typename Iterator2>
00332     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00333     {
00334         ResultType result = ResultType();
00335         ResultType diff0, diff1, diff2, diff3;
00336         Iterator1 last = a + size;
00337         Iterator1 lastgroup = last - 3;
00338 
00339         /* Process 4 items with each loop for efficiency. */
00340         while (a < lastgroup) {
00341             diff0 = abs(a[0] - b[0]);
00342             diff1 = abs(a[1] - b[1]);
00343             diff2 = abs(a[2] - b[2]);
00344             diff3 = abs(a[3] - b[3]);
00345             if (diff0>result) {result = diff0; }
00346             if (diff1>result) {result = diff1; }
00347             if (diff2>result) {result = diff2; }
00348             if (diff3>result) {result = diff3; }
00349             a += 4;
00350             b += 4;
00351 
00352             if ((worst_dist>0)&&(result>worst_dist)) {
00353                 return result;
00354             }
00355         }
00356         /* Process last 0-3 pixels.  Not needed for standard vector lengths. */
00357         while (a < last) {
00358             diff0 = abs(*a++ - *b++);
00359             result = (diff0>result) ? diff0 : result;
00360         }
00361         return result;
00362     }
00363 
00364     /* This distance functor is not dimension-wise additive, which
00365      * makes it an invalid kd-tree distance, not implementing the accum_dist method */
00366 
00367 };
00368 
00370 
00375 struct HammingLUT
00376 {
00377     typedef False is_kdtree_distance;
00378     typedef False is_vector_space_distance;
00379 
00380     typedef unsigned char ElementType;
00381     typedef int ResultType;
00382 
00385     ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const
00386     {
00387         static const uchar popCountTable[] =
00388         {
00389             0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00390             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00391             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00392             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00393             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00394             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00395             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00396             3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
00397         };
00398         ResultType result = 0;
00399         for (int i = 0; i < size; i++) {
00400             result += popCountTable[a[i] ^ b[i]];
00401         }
00402         return result;
00403     }
00404 };
00405 
00410 struct HammingLUT2
00411 {
00412     typedef False is_kdtree_distance;
00413     typedef False is_vector_space_distance;
00414 
00415     typedef unsigned char ElementType;
00416     typedef int ResultType;
00417 
00420     ResultType operator()(const unsigned char* a, const unsigned char* b, size_t size) const
00421     {
00422         static const uchar popCountTable[] =
00423         {
00424             0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
00425             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00426             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00427             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00428             1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
00429             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00430             2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
00431             3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
00432         };
00433         ResultType result = 0;
00434         for (size_t i = 0; i < size; i++) {
00435             result += popCountTable[a[i] ^ b[i]];
00436         }
00437         return result;
00438     }
00439 };
00440 
00445 template<class T>
00446 struct Hamming
00447 {
00448     typedef False is_kdtree_distance;
00449     typedef False is_vector_space_distance;
00450 
00451 
00452     typedef T ElementType;
00453     typedef int ResultType;
00454 
00455     template<typename Iterator1, typename Iterator2>
00456     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
00457     {
00458         ResultType result = 0;
00459 #ifdef __GNUC__
00460 #ifdef __ARM_NEON__
00461         {
00462             uint32x4_t bits = vmovq_n_u32(0);
00463             for (size_t i = 0; i < size; i += 16) {
00464                 uint8x16_t A_vec = vld1q_u8 (a + i);
00465                 uint8x16_t B_vec = vld1q_u8 (b + i);
00466                 uint8x16_t AxorB = veorq_u8 (A_vec, B_vec);
00467                 uint8x16_t bitsSet = vcntq_u8 (AxorB);
00468                 uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
00469                 uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
00470                 bits = vaddq_u32(bits, bitSet4);
00471             }
00472             uint64x2_t bitSet2 = vpaddlq_u32 (bits);
00473             result = vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),0);
00474             result += vgetq_lane_s32 (vreinterpretq_s32_u64(bitSet2),2);
00475         }
00476 #else
00477         {
00478             //for portability just use unsigned long -- and use the __builtin_popcountll (see docs for __builtin_popcountll)
00479             typedef unsigned long long pop_t;
00480             const size_t modulo = size % sizeof(pop_t);
00481             const pop_t* a2 = reinterpret_cast<const pop_t*> (a);
00482             const pop_t* b2 = reinterpret_cast<const pop_t*> (b);
00483             const pop_t* a2_end = a2 + (size / sizeof(pop_t));
00484 
00485             for (; a2 != a2_end; ++a2, ++b2) result += __builtin_popcountll((*a2) ^ (*b2));
00486 
00487             if (modulo) {
00488                 //in the case where size is not dividable by sizeof(size_t)
00489                 //need to mask off the bits at the end
00490                 pop_t a_final = 0, b_final = 0;
00491                 memcpy(&a_final, a2, modulo);
00492                 memcpy(&b_final, b2, modulo);
00493                 result += __builtin_popcountll(a_final ^ b_final);
00494             }
00495         }
00496 #endif //NEON
00497 #else
00498         HammingLUT lut;
00499         result = lut(reinterpret_cast<const unsigned char*> (a),
00500                      reinterpret_cast<const unsigned char*> (b), size * sizeof(pop_t));
00501 #endif
00502         return result;
00503     }
00504 };
00505 
00506 template<typename T>
00507 struct Hamming2
00508 {
00509     typedef False is_kdtree_distance;
00510     typedef False is_vector_space_distance;
00511 
00512     typedef T ElementType;
00513     typedef int ResultType;
00514 
00517     unsigned int popcnt32(uint32_t n) const
00518     {
00519         n -= ((n >> 1) & 0x55555555);
00520         n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
00521         return (((n + (n >> 4))& 0xF0F0F0F)* 0x1010101) >> 24;
00522     }
00523 
00524 #ifdef FLANN_PLATFORM_64_BIT
00525     unsigned int popcnt64(uint64_t n) const
00526     {
00527         n -= ((n >> 1) & 0x5555555555555555);
00528         n = (n & 0x3333333333333333) + ((n >> 2) & 0x3333333333333333);
00529         return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0f)* 0x0101010101010101) >> 56;
00530     }
00531 #endif
00532 
00533     template <typename Iterator1, typename Iterator2>
00534     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
00535     {
00536 #ifdef FLANN_PLATFORM_64_BIT
00537         const uint64_t* pa = reinterpret_cast<const uint64_t*>(a);
00538         const uint64_t* pb = reinterpret_cast<const uint64_t*>(b);
00539         ResultType result = 0;
00540         size /= (sizeof(uint64_t)/sizeof(unsigned char));
00541         for(size_t i = 0; i < size; ++i ) {
00542             result += popcnt64(*pa ^ *pb);
00543             ++pa;
00544             ++pb;
00545         }
00546 #else
00547         const uint32_t* pa = reinterpret_cast<const uint32_t*>(a);
00548         const uint32_t* pb = reinterpret_cast<const uint32_t*>(b);
00549         ResultType result = 0;
00550         size /= (sizeof(uint32_t)/sizeof(unsigned char));
00551         for(size_t i = 0; i < size; ++i ) {
00552             result += popcnt32(*pa ^ *pb);
00553             ++pa;
00554             ++pb;
00555         }
00556 #endif
00557         return result;
00558     }
00559 };
00560 
00561 
00562 
00564 
00565 template<class T>
00566 struct HistIntersectionDistance
00567 {
00568     typedef True is_kdtree_distance;
00569     typedef True is_vector_space_distance;
00570 
00571     typedef T ElementType;
00572     typedef typename Accumulator<T>::Type ResultType;
00573 
00577     template <typename Iterator1, typename Iterator2>
00578     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00579     {
00580         ResultType result = ResultType();
00581         ResultType min0, min1, min2, min3;
00582         Iterator1 last = a + size;
00583         Iterator1 lastgroup = last - 3;
00584 
00585         /* Process 4 items with each loop for efficiency. */
00586         while (a < lastgroup) {
00587             min0 = (ResultType)(a[0] < b[0] ? a[0] : b[0]);
00588             min1 = (ResultType)(a[1] < b[1] ? a[1] : b[1]);
00589             min2 = (ResultType)(a[2] < b[2] ? a[2] : b[2]);
00590             min3 = (ResultType)(a[3] < b[3] ? a[3] : b[3]);
00591             result += min0 + min1 + min2 + min3;
00592             a += 4;
00593             b += 4;
00594             if ((worst_dist>0)&&(result>worst_dist)) {
00595                 return result;
00596             }
00597         }
00598         /* Process last 0-3 pixels.  Not needed for standard vector lengths. */
00599         while (a < last) {
00600             min0 = (ResultType)(*a < *b ? *a : *b);
00601             result += min0;
00602             ++a;
00603             ++b;
00604         }
00605         return result;
00606     }
00607 
00611     template <typename U, typename V>
00612     inline ResultType accum_dist(const U& a, const V& b, int) const
00613     {
00614         return a<b ? a : b;
00615     }
00616 };
00617 
00618 
00619 
00620 template<class T>
00621 struct HellingerDistance
00622 {
00623     typedef True is_kdtree_distance;
00624     typedef True is_vector_space_distance;
00625 
00626     typedef T ElementType;
00627     typedef typename Accumulator<T>::Type ResultType;
00628 
00632     template <typename Iterator1, typename Iterator2>
00633     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType /*worst_dist*/ = -1) const
00634     {
00635         ResultType result = ResultType();
00636         ResultType diff0, diff1, diff2, diff3;
00637         Iterator1 last = a + size;
00638         Iterator1 lastgroup = last - 3;
00639 
00640         /* Process 4 items with each loop for efficiency. */
00641         while (a < lastgroup) {
00642             diff0 = sqrt(static_cast<ResultType>(a[0])) - sqrt(static_cast<ResultType>(b[0]));
00643             diff1 = sqrt(static_cast<ResultType>(a[1])) - sqrt(static_cast<ResultType>(b[1]));
00644             diff2 = sqrt(static_cast<ResultType>(a[2])) - sqrt(static_cast<ResultType>(b[2]));
00645             diff3 = sqrt(static_cast<ResultType>(a[3])) - sqrt(static_cast<ResultType>(b[3]));
00646             result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00647             a += 4;
00648             b += 4;
00649         }
00650         while (a < last) {
00651             diff0 = sqrt(static_cast<ResultType>(*a++)) - sqrt(static_cast<ResultType>(*b++));
00652             result += diff0 * diff0;
00653         }
00654         return result;
00655     }
00656 
00660     template <typename U, typename V>
00661     inline ResultType accum_dist(const U& a, const V& b, int) const
00662     {
00663         return sqrt(static_cast<ResultType>(a)) - sqrt(static_cast<ResultType>(b));
00664     }
00665 };
00666 
00667 
00668 template<class T>
00669 struct ChiSquareDistance
00670 {
00671     typedef True is_kdtree_distance;
00672     typedef True is_vector_space_distance;
00673 
00674     typedef T ElementType;
00675     typedef typename Accumulator<T>::Type ResultType;
00676 
00680     template <typename Iterator1, typename Iterator2>
00681     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00682     {
00683         ResultType result = ResultType();
00684         ResultType sum, diff;
00685         Iterator1 last = a + size;
00686 
00687         while (a < last) {
00688             sum = (ResultType)(*a + *b);
00689             if (sum>0) {
00690                 diff = (ResultType)(*a - *b);
00691                 result += diff*diff/sum;
00692             }
00693             ++a;
00694             ++b;
00695 
00696             if ((worst_dist>0)&&(result>worst_dist)) {
00697                 return result;
00698             }
00699         }
00700         return result;
00701     }
00702 
00706     template <typename U, typename V>
00707     inline ResultType accum_dist(const U& a, const V& b, int) const
00708     {
00709         ResultType result = ResultType();
00710         ResultType sum, diff;
00711 
00712         sum = (ResultType)(a+b);
00713         if (sum>0) {
00714             diff = (ResultType)(a-b);
00715             result = diff*diff/sum;
00716         }
00717         return result;
00718     }
00719 };
00720 
00721 
00722 template<class T>
00723 struct KL_Divergence
00724 {
00725     typedef True is_kdtree_distance;
00726     typedef True is_vector_space_distance;
00727 
00728     typedef T ElementType;
00729     typedef typename Accumulator<T>::Type ResultType;
00730 
00734     template <typename Iterator1, typename Iterator2>
00735     ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00736     {
00737         ResultType result = ResultType();
00738         Iterator1 last = a + size;
00739 
00740         while (a < last) {
00741             if (* a != 0) {
00742                 ResultType ratio = (ResultType)(*a / *b);
00743                 if (ratio>0) {
00744                     result += *a * log(ratio);
00745                 }
00746             }
00747             ++a;
00748             ++b;
00749 
00750             if ((worst_dist>0)&&(result>worst_dist)) {
00751                 return result;
00752             }
00753         }
00754         return result;
00755     }
00756 
00760     template <typename U, typename V>
00761     inline ResultType accum_dist(const U& a, const V& b, int) const
00762     {
00763         ResultType result = ResultType();
00764         ResultType ratio = (ResultType)(a / b);
00765         if (ratio>0) {
00766             result = a * log(ratio);
00767         }
00768         return result;
00769     }
00770 };
00771 
00772 
00773 
00774 /*
00775  * This is a "zero iterator". It basically behaves like a zero filled
00776  * array to all algorithms that use arrays as iterators (STL style).
00777  * It's useful when there's a need to compute the distance between feature
00778  * and origin it and allows for better compiler optimisation than using a
00779  * zero-filled array.
00780  */
00781 template <typename T>
00782 struct ZeroIterator
00783 {
00784 
00785     T operator*()
00786     {
00787         return 0;
00788     }
00789 
00790     T operator[](int)
00791     {
00792         return 0;
00793     }
00794 
00795     const ZeroIterator<T>& operator ++()
00796     {
00797         return *this;
00798     }
00799 
00800     ZeroIterator<T> operator ++(int)
00801     {
00802         return *this;
00803     }
00804 
00805     ZeroIterator<T>& operator+=(int)
00806     {
00807         return *this;
00808     }
00809 
00810 };
00811 
00812 }
00813 
00814 #endif //OPENCV_FLANN_DIST_H_