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