casacore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElementFunctions.h
Go to the documentation of this file.
1 #ifndef ELEMENT_FUNCTIONS_H
2 #define ELEMENT_FUNCTIONS_H
3 
4 #include <cmath>
5 #include <complex>
6 #include <limits>
7 
8 namespace casacore {
9 namespace arrays_internal {
10 
11 inline bool near(unsigned val1, unsigned val2, double tol) {
12  if (tol <= 0) {
13  return (val1 == val2);
14  }
15  if (val1 == val2) {
16  return true;
17  } else if (val1 > val2) {
18  return (double(val1-val2) <= tol*std::max(val1,val2));
19  } else {
20  return (double(val2-val1) <= tol*std::max(val1,val2));
21  }
22 }
23 
24 inline bool near(int val1, int val2, double tol) {
25  if (tol <=0) {
26  return (val1 == val2);
27  }
28  if (val1 == val2) {
29  return true;
30  }
31  if ((0<val1) != (0<val2)) {
32  return false;
33  }
34  const int aval1 = std::abs(val1);
35  const int aval2 = std::abs(val2);
36  return (double(aval1-aval2) <= tol*double(std::max(aval1,aval2)));
37 }
38 
39 inline bool near(float val1, float val2, double tol) {
40  if (tol <=0) {
41  return (val1 == val2);
42  }
43  if (val1 == val2) {
44  return true;
45  }
46  if (val1 == 0) {
47  return (std::abs(val2) <= (1+tol)*std::numeric_limits<float>::min());
48  }
49  else if (val2 == 0) {
50  return (std::abs(val1) <= (1+tol)*std::numeric_limits<float>::min());
51  }
52  if ((0<val1) != (0<val2)) {
53  return false;
54  }
55  return (std::abs(val1-val2) <= tol*std::max(std::abs(val1), std::abs(val2)));
56 }
57 
58 inline bool near(double val1, double val2, double tol) {
59  if (tol <=0) {
60  return (val1 == val2);
61  }
62  if (val1 == val2) {
63  return true;
64  }
65  if (val1 == 0) {
66  return (std::abs(val2) <= (1+tol)*std::numeric_limits<double>::min());
67  }
68  else if (val2 == 0) {
69  return (std::abs(val1) <= (1+tol)*std::numeric_limits<double>::min());
70  }
71  if ((0<val1) != (0<val2)) {
72  return false;
73  }
74  return (std::abs(val1-val2) <= tol*std::max(std::abs(val1),std::abs(val2)));
75 }
76 
77 inline bool near(float val1, double val2, double tol) {
78  return near(double(val1), val2, tol);
79 }
80 
81 inline bool near(double val1, float val2, double tol) {
82  return near(val1, double(val2), tol);
83 }
84 
85 inline bool near(const std::complex<float> &val1, const std::complex<float> &val2, double tol=1.0e-5)
86 {
87  if (tol <= 0) return val1 == val2;
88  if (val1 == val2) return true;
89  if (near(val1.real(), val2.real(), tol) &&
90  near(val1.imag(), val2.imag(), tol)) return true;
91  float aval1(std::abs(val1)), aval2(std::abs(val2));
92  if (aval1 == 0) return aval2 <= (1+tol)*std::numeric_limits<float>::min();
93  else if (aval2 == 0) return aval1 <= (1+tol)*std::numeric_limits<float>::min();
94  std::complex<double> dval(val1);
95  dval -= std::complex<double>(val2);
96  return std::abs(dval) <= tol * (aval1 < aval2 ? aval2 : aval1);
97 }
98 
99 inline bool near(const std::complex<double> &val1, const std::complex<double> &val2, double tol=1.0e-13)
100 {
101  if (tol <= 0) return val1 == val2;
102  if (val1 == val2) return true;
103  if (std::abs(val1) == 0) return std::abs(val2) <= (1+tol)*std::numeric_limits<double>::min();
104  else if (std::abs(val2) == 0) return std::abs(val1) <= (1+tol)*std::numeric_limits<double>::min();
105  double aval1(std::abs(val1)), aval2(std::abs(val2));
106  return std::abs(val1-val2) <= tol * (aval1 < aval2 ? aval2 : aval1);
107 }
108 
109 inline bool nearAbs(const std::complex<float> &val1, const std::complex<float> &val2, double tol=1.0e-5)
110 {
111  return std::abs(val2 - val1) <= tol;
112 }
113 
114 inline bool nearAbs(const std::complex<double> &val1, const std::complex<double> &val2, double tol=1.0e-13)
115 {
116  return std::abs(val2 - val1) <= tol;
117 }
118 
119 inline bool nearAbs(unsigned val1, unsigned val2, double tol) {
120  if (val1 == val2) {
121  return true;
122  } else if (val1 > val2) {
123  return (tol >= double(val1 - val2));
124  } else {
125  return (tol >= double(val2 - val1));
126  }
127 }
128 
129 inline bool nearAbs(int val1, int val2, double tol) {
130  return (tol >= double(std::abs(val2 - val1)));
131 }
132 
133 inline bool nearAbs(float val1, float val2, double tol) {
134  return (tol >= double(std::abs(val2 - val1)));
135 }
136 
137 inline bool nearAbs(double val1, double val2, double tol) {
138  return (tol >= std::abs(val2 - val1));
139 }
140 
141 // Define a function to compare all elements of two sequences.
142 // It returns true if all elements compare true.
143 // An example compare operator is <src>std::equal_to</src>.
144 // <group>
145 template<typename InputIterator1, typename InputIterator2, typename CompareOperator>
146 inline bool compareAll (InputIterator1 first1, InputIterator1 last1,
147  InputIterator2 first2, CompareOperator op)
148 {
149  for (; first1!=last1; ++first1, ++first2) {
150  if (!op(*first1, *first2)) return false;
151  }
152  return true;
153 }
154 // For use with a constant left value.
155 // This avoids use of bind1st or bind2nd which can fail for gcc-4.3.
156 // (see ArrayMath.h).
157 template<typename InputIterator1, typename T, typename CompareOperator>
158 inline bool compareAllLeft (InputIterator1 first1, InputIterator1 last1,
159  T left, CompareOperator op)
160 {
161  for (; first1!=last1; ++first1) {
162  if (!op(left, *first1)) return false;
163  }
164  return true;
165 }
166 // For use with a constant right value.
167 // This avoids use of bind1st or bind2nd which can fail for gcc-4.3.
168 // (see ArrayMath.h).
169 template<typename InputIterator1, typename T, typename CompareOperator>
170 inline bool compareAllRight (InputIterator1 first1, InputIterator1 last1,
171  T right, CompareOperator op)
172 {
173  for (; first1!=last1; ++first1) {
174  if (!op(*first1, right)) return false;
175  }
176  return true;
177 }
178 // </group>
179 
180 // Define a function to compare all elements of two sequences.
181 // It returns true if any element compares true.
182 // An example compare operator is <src>std::equal_to</src>.
183 // <group>
184 template<typename InputIterator1, typename InputIterator2, typename CompareOperator>
185 inline bool compareAny (InputIterator1 first1, InputIterator1 last1,
186  InputIterator2 first2, CompareOperator op)
187 {
188  for (; first1!=last1; ++first1, ++first2) {
189  if (op(*first1, *first2)) return true;
190  }
191  return false;
192 }
193 // For use with a constant left value.
194 // This avoids use of bind1st or bind2nd which can fail for gcc-4.3.
195 // (see ArrayMath.h).
196 template<typename InputIterator1, typename T, typename CompareOperator>
197 inline bool compareAnyLeft (InputIterator1 first1, InputIterator1 last1,
198  T left, CompareOperator op)
199 {
200  for (; first1!=last1; ++first1) {
201  if (op(left, *first1)) return true;
202  }
203  return false;
204 }
205 // For use with a constant right value.
206 // This avoids use of bind1st or bind2nd which can fail for gcc-4.3.
207 // (see ArrayMath.h).
208 template<typename InputIterator1, typename T, typename CompareOperator>
209 inline bool compareAnyRight (InputIterator1 first1, InputIterator1 last1,
210  T right, CompareOperator op)
211 {
212  for (; first1!=last1; ++first1) {
213  if (op(*first1, right)) return true;
214  }
215  return false;
216 }
217 // </group>
218 
219 // Functor to add squared diff of right and base value to left.
220 // It can be used to calculate the variance.
221 // Note: it is specialized for complex values to handle real and imag separately.
222 template<typename T, typename Accum=T>
224 {
225  explicit SumSqrDiff(T base) : itsBase(base) {}
226  Accum operator() (Accum left, T right) const
227  { return left + (right-itsBase)*(right-itsBase); }
228 private:
229  Accum itsBase; // store as Accum, so subtraction results in Accum
230 };
231 
232 // Specialize for complex values.
233 // Variance has to be taken for the absolute value of a complex value. thus
234 // sum(abs((a[i] - mean)**2
235 // where the sqrt used in abs and the **2 cancel each other, thus can be left out.
236 // See also https://en.wikipedia.org/wiki/Complex_random_variable#Variance
237 // Note that although the sum is real, a complex value is used to have equal template types.
238 template<typename T>
239 struct SumSqrDiff<std::complex<T>>
240 {
241  explicit SumSqrDiff(std::complex<T> base) : itsBase(base) {}
242  std::complex<T> operator() (std::complex<T> left, std::complex<T> right) const
243  { return left + ((right.real() - itsBase.real()) * (right.real() - itsBase.real()) +
244  (right.imag() - itsBase.imag()) * (right.imag() - itsBase.imag())); }
245 private:
246  std::complex<T> itsBase;
247 };
248 
249 template<typename T>
250 bool isnan(const std::complex<T> &val)
251 {
252  return std::isnan(val.real()) || std::isnan(val.imag());
253 }
254 
255 template<typename T>
256 bool isinf(const std::complex<T> &val)
257 {
258  return std::isinf(val.real()) || std::isinf(val.imag());
259 }
260 
261 template<typename T>
262 bool isfinite(const std::complex<T> &val)
263 {
264  return std::isfinite(val.real()) || std::isfinite(val.imag());
265 }
266 
267 inline int floormod (int x, int y)
268 {
269  int r = x%y;
270  if (r != 0 && (x<0) != (y<0)) r+=y;
271  return r;
272 }
273 inline long long floormod (long long x, long long y)
274 {
275  long long r = x%y;
276  if (r != 0 && (x<0) != (y<0)) r+=y;
277  return r;
278 }
279 inline float floormod (float x, float y)
280 {
281  float r = std::fmod(x,y);
282  if (r != 0 && (x<0) != (y<0)) r+=y;
283  return r;
284 }
285 inline double floormod (double x, double y)
286 {
287  double r = std::fmod(x,y);
288  if (r != 0 && (x<0) != (y<0)) r+=y;
289  return r;
290 }
291 
292 template<class T, class F> inline void convertScalar (T& out, F in)
293 { out = static_cast<T>(in); }
294 
295 inline void convertScalar (std::complex<float>& out, std::complex<double> in)
296 { out = std::complex<float>(in.real(), in.imag()); }
297 
298 } }
299 
300 #endif
bool compareAllLeft(InputIterator1 first1, InputIterator1 last1, T left, CompareOperator op)
For use with a constant left value.
bool compareAny(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, CompareOperator op)
Define a function to compare all elements of two sequences.
void convertScalar(T &out, F in)
LatticeExprNode max(const LatticeExprNode &left, const LatticeExprNode &right)
Accum operator()(Accum left, T right) const
bool compareAllRight(InputIterator1 first1, InputIterator1 last1, T right, CompareOperator op)
For use with a constant right value.
bool nearAbs(const std::complex< float > &val1, const std::complex< float > &val2, double tol=1.0e-5)
bool compareAll(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, CompareOperator op)
Define a function to compare all elements of two sequences.
bool isnan(const std::complex< T > &val)
bool isfinite(const std::complex< T > &val)
bool compareAnyLeft(InputIterator1 first1, InputIterator1 last1, T left, CompareOperator op)
For use with a constant left value.
Functor to add squared diff of right and base value to left.
bool near(unsigned val1, unsigned val2, double tol)
LatticeExprNode min(const LatticeExprNode &left, const LatticeExprNode &right)
bool compareAnyRight(InputIterator1 first1, InputIterator1 last1, T right, CompareOperator op)
For use with a constant right value.
LatticeExprNode abs(const LatticeExprNode &expr)
Numerical 1-argument functions which result in a real number regardless of input expression type...
bool isinf(const std::complex< T > &val)
LatticeExprNode fmod(const LatticeExprNode &left, const LatticeExprNode &right)
const Double e
e and functions thereof:
int floormod(int x, int y)