//# Functors.h: Define STL functors for basic math functions. //# Copyright (C) 2008 //# Associated Universities, Inc. Washington DC, USA. //# //# This library is free software; you can redistribute it and/or modify it //# under the terms of the GNU Library General Public License as published by //# the Free Software Foundation; either version 2 of the License, or (at your //# option) any later version. //# //# This library is distributed in the hope that it will be useful, but WITHOUT //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public //# License for more details. //# //# You should have received a copy of the GNU Library General Public License //# along with this library; if not, write to the Free Software Foundation, //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. //# //# Correspondence concerning AIPS++ should be addressed as follows: //# Internet email: aips2-request@nrao.edu. //# Postal address: AIPS++ Project Office //# National Radio Astronomy Observatory //# 520 Edgemont Road //# Charlottesville, VA 22903-2475 USA //# //# $Id$ #ifndef CASA_FUNCTORS_H #define CASA_FUNCTORS_H #include #include #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN // Define a function to do a binary transform in place. // It is functionally equivalent to std::transform where the first and result // iterator are the same, but it is faster for non-trivial iterators. template inline void transformInPlace (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, BinaryOperator op) { for (; first1!=last1; ++first1, ++first2) { *first1 = op(*first1, *first2); } } // Define a function to do a unary transform in place. // It is functionally equivalent to std::transform where the first and result // iterator are the same, but it is faster for non-trivial iterators. template inline void transformInPlace (InputIterator1 first1, InputIterator1 last1, UnaryOperator op) { for (; first1!=last1; ++first1) { *first1 = op(*first1); } } // Define a function (similar to std::accumulate) to do accumulation of // elements for which the corresponding mask value is true. // The default accumulation is addition. template inline Accum accumulateTrue (InputIterator first, InputIterator last, MaskIterator mask, Accum acc, BinaryOperator op = std::plus()) { for (; first!=last; ++first, ++mask) { if (*mask) acc = op(acc, *first); } return acc; } // Define a function (similar to std::accumulate) to do accumulation of // elements for which the corresponding mask value is false. // The default accumulation is addition. template inline Accum accumulateFalse (InputIterator first, InputIterator last, MaskIterator mask, Accum acc, BinaryOperator op = std::plus()) { for (; first!=last; ++first, ++mask) { if (!*mask) acc = op(acc, *first); } return acc; } // 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 variables of possibly different types. // This is unlike std::plus which requires equal types. template struct Plus { RES operator() (const L& x, const R& y) const { return RES(x)+y; } }; // Functor to subtract variables of possibly different types. // This is unlike std::minus which requires equal types. template struct Minus { RES operator() (const L& x, const R& y) const { return RES(x)-y; } }; // Functor to multiply variables of possibly different types. // This is unlike std::multiplies which requires equal types. template struct Multiplies { RES operator() (const L& x, const R& y) const { return RES(x)*y; } }; // Functor to divide variables of possibly different types. // This is unlike std::divides which requires equal types. template struct Divides { RES operator() (const L& x, const R& y) const { return RES(x)/y; } }; // Functor to take modulo of (integer) variables of possibly different types // in the C way. // This is unlike std::modulo which requires equal types. template struct Modulo { RES operator() (const L& x, const R& y) const { return RES(x)%y; } }; // Functor to take modulo of variables of possibly different types // using the floor modulo (% as used in Python). template struct FloorMod { RES operator() (const L& x, const R& y) const { return floormod (RES(x), RES(y)); } }; // Functor for bitwise and of (integer) values. template struct BitAnd { T operator() (const T& x, const T& y) const { return x&y; } }; // Functor for bitwise or of (integer) values. template struct BitOr { T operator() (const T& x, const T& y) const { return x|y; } }; // Functor for bitwise xor of (integer) values. template struct BitXor { T operator() (const T& x, const T& y) const { return x^y; } }; // Functor for bitwise negate of (integer) values. template struct BitNegate { T operator() (const T& x) const { return ~x; } }; // Functor to test for NaN. // It can be used in something like: // // std::transform (array.begin(), array.end(), // result.begin(), IsNaN()); // template struct IsNaN { bool operator() (T value) const { return isNaN (value); } }; // Functor to test for infinity. template struct IsInf { bool operator() (T value) const { return isInf (value); } }; // Functor to test for finiteness. template struct IsFinite { bool operator() (T value) const { return isFinite (value); } }; // Functor to test if two values are relatively near each other. // It can be used in something like: // // std::transform (left.begin(), left.cend(), right.begin(), // result.cbegin(), Near(tolerance)); // template struct Near { explicit Near (double tolerance=1e-5) : itsTolerance (tolerance) {} bool operator() (L left, R right) const { return near (left, L(right), itsTolerance); } private: double itsTolerance; }; // Functor to test for if two values are absolutely near each other. template struct NearAbs { explicit NearAbs (double tolerance=1e-13) : itsTolerance (tolerance) {} bool operator() (L left, R right) const { return nearAbs (left, L(right), itsTolerance); } private: double itsTolerance; }; // Functor to apply sin. template struct Sin { RES operator() (T value) const { return RES(sin (value)); } }; // Functor to apply sinh. template struct Sinh { RES operator() (T value) const { return RES(sinh (value)); } }; // Functor to apply asin. template struct Asin { RES operator() (T value) const { return RES(asin (value)); } }; // Functor to apply cos. template struct Cos { RES operator() (T value) const { return RES(cos (value)); } }; // Functor to apply cosh. template struct Cosh { RES operator() (T value) const { return RES(cosh (value)); } }; // Functor to apply acos. template struct Acos { RES operator() (T value) const { return RES(acos (value)); } }; // Functor to apply tan. template struct Tan { RES operator() (T value) const { return RES(tan (value)); } }; // Functor to apply tanh. template struct Tanh { RES operator() (T value) const { return RES(tanh (value)); } }; // Functor to apply atan. template struct Atan { RES operator() (T value) const { return RES(atan (value)); } }; // Functor to apply atan2. template struct Atan2 { RES operator() (L left, R right) const { return RES(atan2 (left, L(right))); } }; // Functor to apply sqr (power of 2). template struct Sqr { RES operator() (T value) const { return RES(value*value); } }; // Functor to apply a power of 3. template struct Pow3 { RES operator() (T value) const { return RES(value*value*value); } }; // Functor to apply sqrt. template struct Sqrt { RES operator() (T value) const { return RES(sqrt (value)); } }; // Functor to apply exp. template struct Exp { RES operator() (T value) const { return RES(exp (value)); } }; // Functor to apply log. template struct Log { RES operator() (T value) const { return RES(log (value)); } }; // Functor to apply log10. template struct Log10 { RES operator() (T value) const { return RES(log10 (value)); } }; // Functor to apply abs. template struct Abs { RES operator() (T value) const { return RES(abs (value)); } }; // Functor to apply floor. template struct Floor { RES operator() (T value) const { return RES(floor (value)); } }; // Functor to apply ceil. template struct Ceil { RES operator() (T value) const { return RES(ceil (value)); } }; // Functor to apply round (e.g. -3.7 gets -4). template struct Round { RES operator() (T value) const { return RES(value<0 ? ceil(value-0.5) : floor(value+0.5)); } }; // Functor to apply sign (result is -1, 0, or 1). template struct Sign { RES operator() (T value) const { return (value<0 ? -1 : (value>0 ? 1:0)); } }; // Functor to form a complex number from the left and right value. template struct MakeComplex { RES operator() (L l, R r) const { return RES(l, r); } }; // Functor to form a complex number from the real part of the // left value and the right value. template struct MakeComplexReal { RES operator() (L l, R r) const { return RES(real(l), r); } }; // Functor to form a complex number from the left value and the // imaginary part of the right value. template struct MakeComplexImag { RES operator() (L l, R r) const { return RES(l, imag(r)); } }; // Functor to form a complex number from the real part of the // left value and the imaginary part of the right value. template struct MakeComplexRealImag { RES operator() (L l, R r) const { return RES(real(l), imag(r)); } }; // Functor to apply complex function conj. template struct Conj { RES operator() (T value) const { return RES(conj (value)); } }; // Functor to apply complex function real. template struct Real { RES operator() (T value) const { return RES(real (value)); } }; // Functor to apply complex function imag. template struct Imag { RES operator() (T value) const { return RES(imag (value)); } }; // Functor to apply complex function arg. template struct CArg { RES operator() (T value) const { return RES(arg (value)); } }; // Functor to apply complex function fabs. template struct CAbs { RES operator() (T value) const { return RES(fabs (value)); } }; // Functor to apply pow. template struct Pow { RES operator() (T left, E exponent) const { return RES(pow (left, exponent)); } }; // Functor to apply fmod. template struct Fmod { RES operator() (R left, L right) const { return RES(fmod (left, L(right))); } }; // Functor to get minimum of two values. template struct Min { RES operator() (L left, R right) const { return RES(left struct Max { RES operator() (L left, R right) const { return RES(left struct SumSqr { Accum operator() (Accum left, T right) const { return left + Accum(right)*Accum(right); } }; // 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; }; // Functor to add absolute diff of right and base value to left. // It can be used to calculate the average deviation. template struct SumAbsDiff { explicit SumAbsDiff(T base) : itsBase(base) {} Accum operator() (Accum left, T right) const { return left + abs((right-itsBase)); } private: Accum itsBase; // store as Accum, so subtraction results in Accum }; // Functor to downcase a std::string. The result is a casacore::String. struct Downcase { String operator() (const std::string& value) const { return downcase(value); } }; // Functor to upcase a std::string. The result is a casacore::String. struct Upcase { String operator() (const std::string& value) const { return upcase(value); } }; // Functor to capitalize a std::string. The result is a casacore::String. struct Capitalize { String operator() (const std::string& value) const { return capitalize(value); } }; // Functor to trim a std::string. The result is a casacore::String. // Leading and trailing whitespace is removed. struct Trim { String operator() (const std::string& value) const { return trim(value); } }; } //# NAMESPACE CASACORE - END #endif