1 // Dakota extension to override macros and allow norm selection at 2 // run-time (with a performance penalty). Thanks to Dan Turner for 3 // initial implementation. 4 5 /* 6 Example of using this in client code to override to l_inf norm: 7 Conditionally compile ANN.h with -D ANN_NORM_SELECT (see ANN.h) 8 9 approxnn::normSelector::instance().method(approxnn::LINF_NORM); 10 ANN_kdtree(...); 11 12 // optional, but recommended if another intervening context might 13 // call into the library 14 normSelector::instance().reset(); 15 */ 16 17 #ifndef ANN_NORMSELECT_H 18 #define ANN_NORMSELECT_H 19 20 namespace approxnn { 21 22 enum {L2_NORM, LINF_NORM}; 23 24 /// \class normSelector 25 /// \brief singleton class to keep track of which norm method 26 /// should be used for NORM macro 27 class normSelector{ 28 public: 29 /// return an instance of the singleton instance()30 static normSelector &instance(){ 31 static normSelector instance_; 32 return instance_; 33 } 34 reset()35 void reset() { 36 method_ = L2_NORM; 37 } 38 /// set the method to use 39 /// \param method an integer value that represents the norm flag method(const int method)40 void method(const int method){ 41 method_ = method; 42 } 43 44 /// returns the current method method()45 int method(){ 46 return method_; 47 } 48 49 /// runtime-switched implementation of ANN_POW 50 template<typename T> pow(const T & v)51 T pow(const T& v) { 52 switch(normSelector::instance().method()) { 53 case L2_NORM: 54 return v*v; 55 break; 56 case LINF_NORM: 57 return std::fabs(v); 58 break; 59 } 60 } 61 62 /// runtime-switched implementation of ANN_POW 63 template<typename T> root(const T & x)64 T root(const T& x) { 65 switch(normSelector::instance().method()) { 66 case L2_NORM: 67 return std::sqrt(x); 68 break; 69 case LINF_NORM: 70 return x; 71 break; 72 } 73 } 74 75 /// runtime-switched implementation of ANN_SUM 76 template<typename T> sum(const T & x,const T & y)77 T sum(const T& x, const T& y) { 78 switch(normSelector::instance().method()) { 79 case L2_NORM: 80 return x + y; 81 break; 82 case LINF_NORM: 83 return (x > y) ? x : y; 84 break; 85 } 86 } 87 88 /// runtime-switched implementation of ANN_DIFF 89 template<typename T> diff(const T & x,const T & y)90 T diff(const T& x, const T& y) { 91 switch(normSelector::instance().method()) { 92 case L2_NORM: 93 return (y-x); 94 break; 95 case LINF_NORM: 96 return y; 97 break; 98 } 99 } 100 101 private: 102 /// constructor normSelector()103 normSelector():method_(L2_NORM){}; 104 /// copy constructor 105 normSelector(normSelector const&); 106 /// asignment operator 107 void operator=(normSelector const &); 108 /// method to use 109 int method_; 110 }; 111 112 113 } // namespace approxnn 114 115 #endif 116