00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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 = -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
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
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
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
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
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
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
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
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
00357 while (a < last) {
00358 diff0 = abs(*a++ - *b++);
00359 result = (diff0>result) ? diff0 : result;
00360 }
00361 return result;
00362 }
00363
00364
00365
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 = -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
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
00489
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 = -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
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
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 = -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
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
00776
00777
00778
00779
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_