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 }
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
58inline 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
77inline bool near(float val1, double val2, double tol) {
78 return near(double(val1), val2, tol);
79}
80
81inline bool near(double val1, float val2, double tol) {
82 return near(val1, double(val2), tol);
83}
84
85inline 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
99inline 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
109inline 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
114inline 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
119inline 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
129inline bool nearAbs(int val1, int val2, double tol) {
130 return (tol >= double(std::abs(val2 - val1)));
131}
132
133inline bool nearAbs(float val1, float val2, double tol) {
134 return (tol >= double(std::abs(val2 - val1)));
135}
136
137inline 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>
145template<typename InputIterator1, typename InputIterator2, typename CompareOperator>
146inline 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).
157template<typename InputIterator1, typename T, typename CompareOperator>
158inline 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).
169template<typename InputIterator1, typename T, typename CompareOperator>
170inline 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>
184template<typename InputIterator1, typename InputIterator2, typename CompareOperator>
185inline 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).
196template<typename InputIterator1, typename T, typename CompareOperator>
197inline 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).
208template<typename InputIterator1, typename T, typename CompareOperator>
209inline 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.
222template<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); }
228private:
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.
238template<typename T>
239struct 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())); }
245private:
246 std::complex<T> itsBase;
247};
248
249template<typename T>
250bool isnan(const std::complex<T> &val)
251{
252 return std::isnan(val.real()) || std::isnan(val.imag());
253}
254
255template<typename T>
256bool isinf(const std::complex<T> &val)
257{
258 return std::isinf(val.real()) || std::isinf(val.imag());
259}
260
261template<typename T>
262bool isfinite(const std::complex<T> &val)
263{
264 return std::isfinite(val.real()) || std::isfinite(val.imag());
265}
266
267inline 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}
273inline 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}
279inline 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}
285inline 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
292template<class T, class F> inline void convertScalar (T& out, F in)
293{ out = static_cast<T>(in); }
294
295inline 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 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.
this file contains all the compiler specific defines
Definition mainpage.dox:28
Define real & complex conjugation for non-complex types and put comparisons into std namespace.
Definition Complex.h:350
Functor to add squared diff of right and base value to left.
Accum operator()(Accum left, T right) const