//# Complex.h: Single and double precision complex numbers //# Copyright (C) 2000,2001,2002,2004 //# 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_COMPLEX_H #define CASA_COMPLEX_H //# Includes #include #include #include namespace casacore { //# NAMESPACE CASACORE - BEGIN // // Single and double precision complex numbers // // // // // The class Complex is a straight typedef as the // standard library complex. // // In a similar way DComplex is typedef-ed as // complex. // // IComplex is defined as a specific class. // It is only used by the FITS classes. // // lDComplex has not been defined: long double is not // part of the standard Casacore data suite (yet) // // A set of global functions are added for historic reasons (they were present // in the original Casacore/gcc complex implementation). // // See the standard library documentation for the expected behaviour of // the Complex and DComplex classes. // // In the following all references to Complex // can be replaced with DComplex. with simultaneous // replacement of Float with Double. // // Complex numbers may be constructed and used in the following ways: //
//
Complex x;
//
Declares an uninitialized Complex.
// //
Complex x = 2; Complex y(2.0);
//
Set x and y to the Complex value (2.0, 0.0);
// //
Complex x(2, 3);
//
Sets x to the Complex value (2, 3);
// //
Complex u(x); Complex v = x;
//
Set u and v to the same value as x.
// //
Float real(Complex& x);
//
returns the real part of x.
// //
Float imag(Complex& x);
//
returns the imaginary part of x.
// //
Float abs(Complex& x);
//
returns the magnitude of x.
// //
Float norm(Complex& x);
//
returns the square of the magnitude of x.
// //
Float arg(Complex& x);
//
returns the argument (amplitude) of x.
// //
Complex polar(Float r, Float t = 0.0);
//
returns a Complex with abs of r and arg of t.
// //
Complex conj(Complex& x);
//
returns the complex conjugate of x
// //
Complex cos(Complex& x);
//
returns the complex cosine of x.
// //
Complex sin(Complex& x);
//
returns the complex sine of x.
// //
Complex cosh(Complex& x);
//
returns the complex hyperbolic cosine of x.
// //
Complex sinh(Complex& x);
//
returns the complex hyperbolic sine of x.
// //
Complex exp(Complex& x);
//
returns the exponential of x.
// //
Complex log(Complex& x);
//
returns the natural log of x.
// //
Complex pow(Complex& x, long p);
//
returns x raised to the p power.
// //
Complex pow(Complex& x, Complex& p);
//
returns x raised to the p power.
// //
Complex sqrt(Complex& x);
//
returns the square root of x.
// //
Complex min(Complex x,Complex y); //
Returns the minumum of x,y (using operator<=, i.e. the norm). // //
Complex max(Complex x,Complex y); //
Returns the maximum of x,y (using operator>=, i.e. the norm). // //
Bool near(Complex val1, Complex val2, Double tol = 1.0e-5);
//
returns whether val1 is relatively near val2 (see Math.h). // (Note the Double tolerance)
// //
Bool nearAbs(Complex val1, Complex val2, Double tol = 1.0e-5);
//
returns whether val1 is absolutely near val2 (see Math.h). // (Note the Double tolerance)
// //
ostream << x;
//
prints x in the form (re, im).
// //
istream >> x;
//
reads x in the form (re, im), or just (re) or re in which case the // imaginary part is set to zero.
//
//
//# //# // // Complex NaN and Infinity // // // Bool isNaN (const Complex& val); void setNaN(Complex& val); Bool isInf (const Complex& val); void setInf(Complex& val); Bool isFinite(const Complex& val); // // Complex comparisons // // // //# On Linux comparing the norm does not work well in debug mode //# for equal values. Therefore they are compared for equality first. inline Bool operator>= (const Complex& left, const Complex& right) { return left==right ? True : norm(left) >= norm(right); } inline Bool operator> (const Complex& left, const Complex& right) { return left==right ? False : norm(left) > norm(right); } inline Bool operator<= (const Complex& left, const Complex& right) { return left==right ? True : norm(left) <= norm(right); } inline Bool operator< (const Complex& left, const Complex& right) { return left==right ? False : norm(left) < norm(right); } // // DComplex NaN and Infinity // // // Bool isNaN (const DComplex& val); void setNaN(DComplex& val); Bool isInf (const DComplex& val); void setInf(DComplex& val); Bool isFinite(const DComplex& val); // // DComplex comparisons // // // inline Bool operator>= (const DComplex& left, const DComplex& right) { return norm(left) >= norm(right); } inline Bool operator> (const DComplex& left, const DComplex& right) { return norm(left) > norm(right); } inline Bool operator<= (const DComplex& left, const DComplex& right) { return norm(left) <= norm(right); } inline Bool operator< (const DComplex& left, const DComplex& right) { return norm(left) < norm(right); } // //# Global functions // Additional complex mathematical functions // // // inline Double fabs(const DComplex &val) { return std::abs(val); } inline Float fabs(const Complex &val) { return std::abs(val); } inline DComplex square(const DComplex &val) { return val*val; } inline Complex square(const Complex &val) { return val*val; } inline DComplex cube(const DComplex &val) { return val*val*val; } inline Complex cube(const Complex &val) { return val*val*val; } // ArrayMath::pow needs this pow function. ///inline Complex pow(const Complex& val, Double p) { return std::pow(val,Float(p)); } // We have to explicitly implement these for different type operands inline DComplex operator+(const DComplex& d, const Complex& c) { return (DComplex)c + d; } inline DComplex operator+(const Complex& c, const DComplex& d) { return (DComplex)c + d; } inline DComplex operator-(const DComplex& d, const Complex& c) { return d - (DComplex)c; } inline DComplex operator-(const Complex& c, const DComplex& d) { return (DComplex)c - d; } // QMath and scimath need these operators * and / // inline Complex operator*(const Complex& val, Double f) { return val*Float(f); } inline Complex operator*(Double f, const Complex& val) { return val*Float(f); } inline Complex operator/(const Complex& val, Double f) { return val/Float(f); } inline Complex operator/(Double f, const Complex& val) { return Float(f)/val; } // // These operators are useful, otherwise both Float and Double are applicable // for Ints. // inline Complex operator*(const Complex& val, Int f) { return val*Float(f); } inline Complex operator*(Int f, const Complex& val) { return val*Float(f); } inline Complex operator/(const Complex& val, Int f) { return val/Float(f); } inline Complex operator/(Int f, const Complex& val) { return Float(f)/val; } // // // The near functions // // // Bool near(const Complex &val1, const Complex &val2, Double tol=1.0e-5); Bool near(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13); Bool nearAbs(const Complex &val1, const Complex &val2, Double tol=1.0e-5); Bool nearAbs(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13); inline Bool allNear(const Complex &val1, const Complex &val2, Double tol=1.0e-5) { return near(val1, val2, tol); } inline Bool allNear(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13) { return near(val1, val2, tol); } inline Bool allNearAbs(const Complex &val1, const Complex &val2, Double tol=1.0e-5) { return nearAbs(val1, val2, tol); } inline Bool allNearAbs(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13) { return nearAbs(val1, val2, tol); } // // Max and min, floor and ceil functions // // // inline Complex max(const Complex &x, const Complex &y) { return x >= y ? x : y; } inline DComplex max(const DComplex &x, const DComplex &y) { return x >= y ? x : y; } inline Complex min(const Complex &x, const Complex &y) { return x <= y ? x : y; } inline DComplex min(const DComplex &x, const DComplex &y) { return x <= y ? x : y; } inline Complex floor(const Complex &x) { return Complex(std::floor(x.real()), std::floor(x.imag())); } inline DComplex floor(const DComplex &x) { return DComplex(std::floor(x.real()), std::floor(x.imag())); } inline Complex ceil(const Complex &x) { return Complex(std::ceil(x.real()), std::ceil(x.imag())); } inline DComplex ceil(const DComplex &x) { return DComplex(std::ceil(x.real()), std::ceil(x.imag())); } // // fmod // // // DComplex fmod(const DComplex &in, const DComplex &f); Complex fmod(const Complex &in, const Complex &f); // // Inverse trigonometry // // // // atan not valid for z == -1 DComplex atan(const DComplex &in); Complex atan(const Complex &in); DComplex asin(const DComplex &in); Complex asin(const Complex &in); DComplex acos(const DComplex &in); Complex acos(const Complex &in); DComplex atan2(const DComplex &in, const DComplex &t2); Complex atan2(const Complex &in, const Complex &t2); // // Error function // // // // Preliminary to get Functionals working. erf(z) will return erf(real(z)) // only for now. DComplex erf(const DComplex &in); Complex erf(const Complex &in); DComplex erfc(const DComplex &in); Complex erfc(const Complex &in); // // } //# NAMESPACE CASACORE - END // Define real & complex conjugation for non-complex types // and put comparisons into std namespace. namespace std { inline float conj(float x) { return x; } inline double conj(double x) { return x; } using casacore::operator>; using casacore::operator>=; using casacore::operator<; using casacore::operator<=; } #endif