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 RTABMAP_FLANN_DIST_H_
00032 #define RTABMAP_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 "rtflann/defines.h"
00045
00046
00047 namespace rtflann
00048 {
00049
00050 template<typename T>
00051 struct Accumulator { typedef T Type; };
00052 template<>
00053 struct Accumulator<unsigned char> { typedef float Type; };
00054 template<>
00055 struct Accumulator<unsigned short> { typedef float Type; };
00056 template<>
00057 struct Accumulator<unsigned int> { typedef float Type; };
00058 template<>
00059 struct Accumulator<char> { typedef float Type; };
00060 template<>
00061 struct Accumulator<short> { typedef float Type; };
00062 template<>
00063 struct Accumulator<int> { typedef float Type; };
00064
00065
00066
00073 template<class T>
00074 struct L2_Simple
00075 {
00076 typedef bool is_kdtree_distance;
00077
00078 typedef T ElementType;
00079 typedef typename Accumulator<T>::Type ResultType;
00080
00081 template <typename Iterator1, typename Iterator2>
00082 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType = -1) const
00083 {
00084 ResultType result = ResultType();
00085 ResultType diff;
00086 for(size_t i = 0; i < size; ++i ) {
00087 diff = *a++ - *b++;
00088 result += diff*diff;
00089 }
00090 return result;
00091 }
00092
00093 template <typename U, typename V>
00094 inline ResultType accum_dist(const U& a, const V& b, int) const
00095 {
00096 return (a-b)*(a-b);
00097 }
00098 };
00099
00100 template<class T>
00101 struct L2_3D
00102 {
00103 typedef bool is_kdtree_distance;
00104
00105 typedef T ElementType;
00106 typedef typename Accumulator<T>::Type ResultType;
00107
00108 template <typename Iterator1, typename Iterator2>
00109 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType = -1) const
00110 {
00111 ResultType result = ResultType();
00112 ResultType diff;
00113 diff = *a++ - *b++;
00114 result += diff*diff;
00115 diff = *a++ - *b++;
00116 result += diff*diff;
00117 diff = *a++ - *b++;
00118 result += diff*diff;
00119 return result;
00120 }
00121
00122 template <typename U, typename V>
00123 inline ResultType accum_dist(const U& a, const V& b, int) const
00124 {
00125 return (a-b)*(a-b);
00126 }
00127 };
00128
00132 template<class T>
00133 struct L2
00134 {
00135 typedef bool is_kdtree_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 bool is_kdtree_distance;
00200
00201 typedef T ElementType;
00202 typedef typename Accumulator<T>::Type ResultType;
00203
00210 template <typename Iterator1, typename Iterator2>
00211 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00212 {
00213 ResultType result = ResultType();
00214 ResultType diff0, diff1, diff2, diff3;
00215 Iterator1 last = a + size;
00216 Iterator1 lastgroup = last - 3;
00217
00218
00219 while (a < lastgroup) {
00220 diff0 = (ResultType)std::abs(a[0] - b[0]);
00221 diff1 = (ResultType)std::abs(a[1] - b[1]);
00222 diff2 = (ResultType)std::abs(a[2] - b[2]);
00223 diff3 = (ResultType)std::abs(a[3] - b[3]);
00224 result += diff0 + diff1 + diff2 + diff3;
00225 a += 4;
00226 b += 4;
00227
00228 if ((worst_dist>0)&&(result>worst_dist)) {
00229 return result;
00230 }
00231 }
00232
00233 while (a < last) {
00234 diff0 = (ResultType)std::abs(*a++ - *b++);
00235 result += diff0;
00236 }
00237 return result;
00238 }
00239
00243 template <typename U, typename V>
00244 inline ResultType accum_dist(const U& a, const V& b, int) const
00245 {
00246 return std::abs(a-b);
00247 }
00248 };
00249
00250
00251
00252 template<class T>
00253 struct MinkowskiDistance
00254 {
00255 typedef bool is_kdtree_distance;
00256
00257 typedef T ElementType;
00258 typedef typename Accumulator<T>::Type ResultType;
00259
00260 int order;
00261
00262 MinkowskiDistance(int order_) : order(order_) {}
00263
00273 template <typename Iterator1, typename Iterator2>
00274 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00275 {
00276 ResultType result = ResultType();
00277 ResultType diff0, diff1, diff2, diff3;
00278 Iterator1 last = a + size;
00279 Iterator1 lastgroup = last - 3;
00280
00281
00282 while (a < lastgroup) {
00283 diff0 = (ResultType)std::abs(a[0] - b[0]);
00284 diff1 = (ResultType)std::abs(a[1] - b[1]);
00285 diff2 = (ResultType)std::abs(a[2] - b[2]);
00286 diff3 = (ResultType)std::abs(a[3] - b[3]);
00287 result += pow(diff0,order) + pow(diff1,order) + pow(diff2,order) + pow(diff3,order);
00288 a += 4;
00289 b += 4;
00290
00291 if ((worst_dist>0)&&(result>worst_dist)) {
00292 return result;
00293 }
00294 }
00295
00296 while (a < last) {
00297 diff0 = (ResultType)std::abs(*a++ - *b++);
00298 result += pow(diff0,order);
00299 }
00300 return result;
00301 }
00302
00306 template <typename U, typename V>
00307 inline ResultType accum_dist(const U& a, const V& b, int) const
00308 {
00309 return pow(static_cast<ResultType>(std::abs(a-b)),order);
00310 }
00311 };
00312
00313
00314
00315 template<class T>
00316 struct MaxDistance
00317 {
00318 typedef bool is_vector_space_distance;
00319
00320 typedef T ElementType;
00321 typedef typename Accumulator<T>::Type ResultType;
00322
00328 template <typename Iterator1, typename Iterator2>
00329 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00330 {
00331 ResultType result = ResultType();
00332 ResultType diff0, diff1, diff2, diff3;
00333 Iterator1 last = a + size;
00334 Iterator1 lastgroup = last - 3;
00335
00336
00337 while (a < lastgroup) {
00338 diff0 = std::abs(a[0] - b[0]);
00339 diff1 = std::abs(a[1] - b[1]);
00340 diff2 = std::abs(a[2] - b[2]);
00341 diff3 = std::abs(a[3] - b[3]);
00342 if (diff0>result) {result = diff0; }
00343 if (diff1>result) {result = diff1; }
00344 if (diff2>result) {result = diff2; }
00345 if (diff3>result) {result = diff3; }
00346 a += 4;
00347 b += 4;
00348
00349 if ((worst_dist>0)&&(result>worst_dist)) {
00350 return result;
00351 }
00352 }
00353
00354 while (a < last) {
00355 diff0 = std::abs(*a++ - *b++);
00356 result = (diff0>result) ? diff0 : result;
00357 }
00358 return result;
00359 }
00360
00361
00362
00363
00364 };
00365
00367
00372 struct HammingLUT
00373 {
00374 typedef unsigned char ElementType;
00375 typedef int ResultType;
00376
00379 ResultType operator()(const unsigned char* a, const unsigned char* b, int size) const
00380 {
00381 ResultType result = 0;
00382 for (int i = 0; i < size; i++) {
00383 result += byteBitsLookUp(a[i] ^ b[i]);
00384 }
00385 return result;
00386 }
00387
00388
00394 static unsigned char byteBitsLookUp(unsigned char b)
00395 {
00396 static const unsigned char table[256] = {
00397 0, 1, 1, 2,
00398 1, 2, 2, 3,
00399 1, 2, 2, 3,
00400 2, 3, 3, 4,
00401 1, 2, 2, 3,
00402 2, 3, 3, 4,
00403 2, 3, 3, 4,
00404 3, 4, 4, 5,
00405 1, 2, 2, 3,
00406 2, 3, 3, 4,
00407 2, 3, 3, 4,
00408 3, 4, 4, 5,
00409 2, 3, 3, 4,
00410 3, 4, 4, 5,
00411 3, 4, 4, 5,
00412 4, 5, 5, 6,
00413 1, 2, 2, 3,
00414 2, 3, 3, 4,
00415 2, 3, 3, 4,
00416 3, 4, 4, 5,
00417 2, 3, 3, 4,
00418 3, 4, 4, 5,
00419 3, 4, 4, 5,
00420 4, 5, 5, 6,
00421 2, 3, 3, 4,
00422 3, 4, 4, 5,
00423 3, 4, 4, 5,
00424 4, 5, 5, 6,
00425 3, 4, 4, 5,
00426 4, 5, 5, 6,
00427 4, 5, 5, 6,
00428 5, 6, 6, 7,
00429 1, 2, 2, 3,
00430 2, 3, 3, 4,
00431 2, 3, 3, 4,
00432 3, 4, 4, 5,
00433 2, 3, 3, 4,
00434 3, 4, 4, 5,
00435 3, 4, 4, 5,
00436 4, 5, 5, 6,
00437 2, 3, 3, 4,
00438 3, 4, 4, 5,
00439 3, 4, 4, 5,
00440 4, 5, 5, 6,
00441 3, 4, 4, 5,
00442 4, 5, 5, 6,
00443 4, 5, 5, 6,
00444 5, 6, 6, 7,
00445 2, 3, 3, 4,
00446 3, 4, 4, 5,
00447 3, 4, 4, 5,
00448 4, 5, 5, 6,
00449 3, 4, 4, 5,
00450 4, 5, 5, 6,
00451 4, 5, 5, 6,
00452 5, 6, 6, 7,
00453 3, 4, 4, 5,
00454 4, 5, 5, 6,
00455 4, 5, 5, 6,
00456 5, 6, 6, 7,
00457 4, 5, 5, 6,
00458 5, 6, 6, 7,
00459 5, 6, 6, 7,
00460 6, 7, 7, 8
00461 };
00462 return table[b];
00463 }
00464 };
00465
00470 template<class T>
00471 struct HammingPopcnt
00472 {
00473 typedef T ElementType;
00474 typedef int ResultType;
00475
00476 template<typename Iterator1, typename Iterator2>
00477 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType = -1) const
00478 {
00479 ResultType result = 0;
00480 #if __GNUC__
00481 #if ANDROID && HAVE_NEON
00482 static uint64_t features = android_getCpuFeatures();
00483 if ((features& ANDROID_CPU_ARM_FEATURE_NEON)) {
00484 for (size_t i = 0; i < size; i += 16) {
00485 uint8x16_t A_vec = vld1q_u8 (a + i);
00486 uint8x16_t B_vec = vld1q_u8 (b + i);
00487
00488 uint8x16_t AxorB = veorq_u8 (A_vec, B_vec);
00489
00490 uint8x16_t bitsSet += vcntq_u8 (AxorB);
00491
00492 uint16x8_t bitSet8 = vpaddlq_u8 (bitsSet);
00493 uint32x4_t bitSet4 = vpaddlq_u16 (bitSet8);
00494
00495 uint64x2_t bitSet2 = vpaddlq_u32 (bitSet4);
00496 result += vgetq_lane_u64 (bitSet2,0);
00497 result += vgetq_lane_u64 (bitSet2,1);
00498 }
00499 }
00500 else
00501 #endif
00502
00503 typedef unsigned long long pop_t;
00504 const size_t modulo = size % sizeof(pop_t);
00505 const pop_t* a2 = reinterpret_cast<const pop_t*> (a);
00506 const pop_t* b2 = reinterpret_cast<const pop_t*> (b);
00507 const pop_t* a2_end = a2 + (size / sizeof(pop_t));
00508
00509 for (; a2 != a2_end; ++a2, ++b2) result += __builtin_popcountll((*a2) ^ (*b2));
00510
00511 if (modulo) {
00512
00513
00514 pop_t a_final = 0, b_final = 0;
00515 memcpy(&a_final, a2, modulo);
00516 memcpy(&b_final, b2, modulo);
00517 result += __builtin_popcountll(a_final ^ b_final);
00518 }
00519 #else
00520 HammingLUT lut;
00521 result = lut(reinterpret_cast<const unsigned char*> (a),
00522 reinterpret_cast<const unsigned char*> (b), size * sizeof(pop_t));
00523 #endif
00524 return result;
00525 }
00526 };
00527
00528 template<typename T>
00529 struct Hamming
00530 {
00531 typedef T ElementType;
00532 typedef unsigned int ResultType;
00533
00536 unsigned int popcnt32(uint32_t n) const
00537 {
00538 n -= ((n >> 1) & 0x55555555);
00539 n = (n & 0x33333333) + ((n >> 2) & 0x33333333);
00540 return (((n + (n >> 4))& 0xF0F0F0F)* 0x1010101) >> 24;
00541 }
00542
00543 unsigned int popcnt64(uint64_t n) const
00544 {
00545 n -= ((n >> 1) & 0x5555555555555555LL);
00546 n = (n & 0x3333333333333333LL) + ((n >> 2) & 0x3333333333333333LL);
00547 return (((n + (n >> 4))& 0x0f0f0f0f0f0f0f0fLL)* 0x0101010101010101LL) >> 56;
00548 }
00549
00550 template <typename Iterator1, typename Iterator2>
00551 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType = 0) const
00552 {
00553 #ifdef FLANN_PLATFORM_64_BIT
00554 const uint64_t* pa = reinterpret_cast<const uint64_t*>(a);
00555 const uint64_t* pb = reinterpret_cast<const uint64_t*>(b);
00556 ResultType result = 0;
00557 size /= (sizeof(uint64_t)/sizeof(unsigned char));
00558 for(size_t i = 0; i < size; ++i ) {
00559 result += popcnt64(*pa ^ *pb);
00560 ++pa;
00561 ++pb;
00562 }
00563 #else
00564 const uint32_t* pa = reinterpret_cast<const uint32_t*>(a);
00565 const uint32_t* pb = reinterpret_cast<const uint32_t*>(b);
00566 ResultType result = 0;
00567 size /= (sizeof(uint32_t)/sizeof(unsigned char));
00568 for(size_t i = 0; i < size; ++i ) {
00569 result += popcnt32(*pa ^ *pb);
00570 ++pa;
00571 ++pb;
00572 }
00573 #endif
00574 return result;
00575 }
00576 };
00577
00578
00579
00581
00582 template<class T>
00583 struct HistIntersectionDistance
00584 {
00585 typedef bool is_kdtree_distance;
00586
00587 typedef T ElementType;
00588 typedef typename Accumulator<T>::Type ResultType;
00589
00593 template <typename Iterator1, typename Iterator2>
00594 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00595 {
00596 ResultType result = ResultType();
00597 ResultType min0, min1, min2, min3;
00598 Iterator1 last = a + size;
00599 Iterator1 lastgroup = last - 3;
00600
00601
00602 while (a < lastgroup) {
00603 min0 = (ResultType)(a[0] < b[0] ? a[0] : b[0]);
00604 min1 = (ResultType)(a[1] < b[1] ? a[1] : b[1]);
00605 min2 = (ResultType)(a[2] < b[2] ? a[2] : b[2]);
00606 min3 = (ResultType)(a[3] < b[3] ? a[3] : b[3]);
00607 result += min0 + min1 + min2 + min3;
00608 a += 4;
00609 b += 4;
00610 if ((worst_dist>0)&&(result>worst_dist)) {
00611 return result;
00612 }
00613 }
00614
00615 while (a < last) {
00616 min0 = (ResultType)(*a < *b ? *a : *b);
00617 result += min0;
00618 ++a;
00619 ++b;
00620 }
00621 return result;
00622 }
00623
00627 template <typename U, typename V>
00628 inline ResultType accum_dist(const U& a, const V& b, int) const
00629 {
00630 return a<b ? a : b;
00631 }
00632 };
00633
00634
00635
00636 template<class T>
00637 struct HellingerDistance
00638 {
00639 typedef bool is_kdtree_distance;
00640
00641 typedef T ElementType;
00642 typedef typename Accumulator<T>::Type ResultType;
00643
00647 template <typename Iterator1, typename Iterator2>
00648 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType = -1) const
00649 {
00650 ResultType result = ResultType();
00651 ResultType diff0, diff1, diff2, diff3;
00652 Iterator1 last = a + size;
00653 Iterator1 lastgroup = last - 3;
00654
00655
00656 while (a < lastgroup) {
00657 diff0 = sqrt(static_cast<ResultType>(a[0])) - sqrt(static_cast<ResultType>(b[0]));
00658 diff1 = sqrt(static_cast<ResultType>(a[1])) - sqrt(static_cast<ResultType>(b[1]));
00659 diff2 = sqrt(static_cast<ResultType>(a[2])) - sqrt(static_cast<ResultType>(b[2]));
00660 diff3 = sqrt(static_cast<ResultType>(a[3])) - sqrt(static_cast<ResultType>(b[3]));
00661 result += diff0 * diff0 + diff1 * diff1 + diff2 * diff2 + diff3 * diff3;
00662 a += 4;
00663 b += 4;
00664 }
00665 while (a < last) {
00666 diff0 = sqrt(static_cast<ResultType>(*a++)) - sqrt(static_cast<ResultType>(*b++));
00667 result += diff0 * diff0;
00668 }
00669 return result;
00670 }
00671
00675 template <typename U, typename V>
00676 inline ResultType accum_dist(const U& a, const V& b, int) const
00677 {
00678 ResultType dist = sqrt(static_cast<ResultType>(a)) - sqrt(static_cast<ResultType>(b));
00679 return dist * dist;
00680 }
00681 };
00682
00683
00684 template<class T>
00685 struct ChiSquareDistance
00686 {
00687 typedef bool is_kdtree_distance;
00688
00689 typedef T ElementType;
00690 typedef typename Accumulator<T>::Type ResultType;
00691
00695 template <typename Iterator1, typename Iterator2>
00696 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00697 {
00698 ResultType result = ResultType();
00699 ResultType sum, diff;
00700 Iterator1 last = a + size;
00701
00702 while (a < last) {
00703 sum = (ResultType)(*a + *b);
00704 if (sum>0) {
00705 diff = (ResultType)(*a - *b);
00706 result += diff*diff/sum;
00707 }
00708 ++a;
00709 ++b;
00710
00711 if ((worst_dist>0)&&(result>worst_dist)) {
00712 return result;
00713 }
00714 }
00715 return result;
00716 }
00717
00721 template <typename U, typename V>
00722 inline ResultType accum_dist(const U& a, const V& b, int) const
00723 {
00724 ResultType result = ResultType();
00725 ResultType sum, diff;
00726
00727 sum = (ResultType)(a+b);
00728 if (sum>0) {
00729 diff = (ResultType)(a-b);
00730 result = diff*diff/sum;
00731 }
00732 return result;
00733 }
00734 };
00735
00736
00737 template<class T>
00738 struct KL_Divergence
00739 {
00740 typedef bool is_kdtree_distance;
00741
00742 typedef T ElementType;
00743 typedef typename Accumulator<T>::Type ResultType;
00744
00748 template <typename Iterator1, typename Iterator2>
00749 ResultType operator()(Iterator1 a, Iterator2 b, size_t size, ResultType worst_dist = -1) const
00750 {
00751 ResultType result = ResultType();
00752 Iterator1 last = a + size;
00753
00754 while (a < last) {
00755 if ( *a != 0 && *b != 0 ) {
00756 ResultType ratio = (ResultType)(*a / *b);
00757 if (ratio>0) {
00758 result += *a * log(ratio);
00759 }
00760 }
00761 ++a;
00762 ++b;
00763
00764 if ((worst_dist>0)&&(result>worst_dist)) {
00765 return result;
00766 }
00767 }
00768 return result;
00769 }
00770
00774 template <typename U, typename V>
00775 inline ResultType accum_dist(const U& a, const V& b, int) const
00776 {
00777 ResultType result = ResultType();
00778 if( a != 0 && b != 0 ) {
00779 ResultType ratio = (ResultType)(a / b);
00780 if (ratio>0) {
00781 result = a * log(ratio);
00782 }
00783 }
00784 return result;
00785 }
00786 };
00787
00788 }
00789
00790 #endif //FLANN_DIST_H_