#ifndef ELEMENT_FUNCTIONS_H #define ELEMENT_FUNCTIONS_H #include #include #include namespace casacore { namespace arrays_internal { inline bool near(unsigned val1, unsigned val2, double tol) { if (tol <= 0) { return (val1 == val2); } if (val1 == val2) { return true; } else if (val1 > val2) { return (double(val1-val2) <= tol*std::max(val1,val2)); } else { return (double(val2-val1) <= tol*std::max(val1,val2)); } } inline bool near(int val1, int val2, double tol) { if (tol <=0) { return (val1 == val2); } if (val1 == val2) { return true; } if ((0::min()); } else if (val2 == 0) { return (std::abs(val1) <= (1+tol)*std::numeric_limits::min()); } if ((0::min()); } else if (val2 == 0) { return (std::abs(val1) <= (1+tol)*std::numeric_limits::min()); } if ((0 &val1, const std::complex &val2, double tol=1.0e-5) { if (tol <= 0) return val1 == val2; if (val1 == val2) return true; if (near(val1.real(), val2.real(), tol) && near(val1.imag(), val2.imag(), tol)) return true; float aval1(std::abs(val1)), aval2(std::abs(val2)); if (aval1 == 0) return aval2 <= (1+tol)*std::numeric_limits::min(); else if (aval2 == 0) return aval1 <= (1+tol)*std::numeric_limits::min(); std::complex dval(val1); dval -= std::complex(val2); return std::abs(dval) <= tol * (aval1 < aval2 ? aval2 : aval1); } inline bool near(const std::complex &val1, const std::complex &val2, double tol=1.0e-13) { if (tol <= 0) return val1 == val2; if (val1 == val2) return true; if (std::abs(val1) == 0) return std::abs(val2) <= (1+tol)*std::numeric_limits::min(); else if (std::abs(val2) == 0) return std::abs(val1) <= (1+tol)*std::numeric_limits::min(); double aval1(std::abs(val1)), aval2(std::abs(val2)); return std::abs(val1-val2) <= tol * (aval1 < aval2 ? aval2 : aval1); } inline bool nearAbs(const std::complex &val1, const std::complex &val2, double tol=1.0e-5) { return std::abs(val2 - val1) <= tol; } inline bool nearAbs(const std::complex &val1, const std::complex &val2, double tol=1.0e-13) { return std::abs(val2 - val1) <= tol; } inline bool nearAbs(unsigned val1, unsigned val2, double tol) { if (val1 == val2) { return true; } else if (val1 > val2) { return (tol >= double(val1 - val2)); } else { return (tol >= double(val2 - val1)); } } inline bool nearAbs(int val1, int val2, double tol) { return (tol >= double(std::abs(val2 - val1))); } inline bool nearAbs(float val1, float val2, double tol) { return (tol >= double(std::abs(val2 - val1))); } inline bool nearAbs(double val1, double val2, double tol) { return (tol >= std::abs(val2 - val1)); } // Define a function to compare all elements of two sequences. // It returns true if all elements compare true. // An example compare operator is std::equal_to. // template inline bool compareAll (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, CompareOperator op) { for (; first1!=last1; ++first1, ++first2) { if (!op(*first1, *first2)) return false; } return true; } // For use with a constant left value. // This avoids use of bind1st or bind2nd which can fail for gcc-4.3. // (see ArrayMath.h). template inline bool compareAllLeft (InputIterator1 first1, InputIterator1 last1, T left, CompareOperator op) { for (; first1!=last1; ++first1) { if (!op(left, *first1)) return false; } return true; } // For use with a constant right value. // This avoids use of bind1st or bind2nd which can fail for gcc-4.3. // (see ArrayMath.h). template inline bool compareAllRight (InputIterator1 first1, InputIterator1 last1, T right, CompareOperator op) { for (; first1!=last1; ++first1) { if (!op(*first1, right)) return false; } return true; } // // Define a function to compare all elements of two sequences. // It returns true if any element compares true. // An example compare operator is std::equal_to. // template inline bool compareAny (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, CompareOperator op) { for (; first1!=last1; ++first1, ++first2) { if (op(*first1, *first2)) return true; } return false; } // For use with a constant left value. // This avoids use of bind1st or bind2nd which can fail for gcc-4.3. // (see ArrayMath.h). template inline bool compareAnyLeft (InputIterator1 first1, InputIterator1 last1, T left, CompareOperator op) { for (; first1!=last1; ++first1) { if (op(left, *first1)) return true; } return false; } // For use with a constant right value. // This avoids use of bind1st or bind2nd which can fail for gcc-4.3. // (see ArrayMath.h). template inline bool compareAnyRight (InputIterator1 first1, InputIterator1 last1, T right, CompareOperator op) { for (; first1!=last1; ++first1) { if (op(*first1, right)) return true; } return false; } // // Functor to add squared diff of right and base value to left. // It can be used to calculate the variance. // Note: it is specialized for complex values to handle real and imag separately. template struct SumSqrDiff { explicit SumSqrDiff(T base) : itsBase(base) {} Accum operator() (Accum left, T right) const { return left + (right-itsBase)*(right-itsBase); } private: Accum itsBase; // store as Accum, so subtraction results in Accum }; // Specialize for complex values. // Variance has to be taken for the absolute value of a complex value. thus // sum(abs((a[i] - mean)**2 // where the sqrt used in abs and the **2 cancel each other, thus can be left out. // See also https://en.wikipedia.org/wiki/Complex_random_variable#Variance // Note that although the sum is real, a complex value is used to have equal template types. template struct SumSqrDiff> { explicit SumSqrDiff(std::complex base) : itsBase(base) {} std::complex operator() (std::complex left, std::complex right) const { return left + ((right.real() - itsBase.real()) * (right.real() - itsBase.real()) + (right.imag() - itsBase.imag()) * (right.imag() - itsBase.imag())); } private: std::complex itsBase; }; template bool isnan(const std::complex &val) { return std::isnan(val.real()) || std::isnan(val.imag()); } template bool isinf(const std::complex &val) { return std::isinf(val.real()) || std::isinf(val.imag()); } template bool isfinite(const std::complex &val) { return std::isfinite(val.real()) || std::isfinite(val.imag()); } inline int floormod (int x, int y) { int r = x%y; if (r != 0 && (x<0) != (y<0)) r+=y; return r; } inline long long floormod (long long x, long long y) { long long r = x%y; if (r != 0 && (x<0) != (y<0)) r+=y; return r; } inline float floormod (float x, float y) { float r = std::fmod(x,y); if (r != 0 && (x<0) != (y<0)) r+=y; return r; } inline double floormod (double x, double y) { double r = std::fmod(x,y); if (r != 0 && (x<0) != (y<0)) r+=y; return r; } template inline void convertScalar (T& out, F in) { out = static_cast(in); } inline void convertScalar (std::complex& out, std::complex in) { out = std::complex(in.real(), in.imag()); } } } #endif