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