00001 //# Complex.h: Single and double precision complex numbers 00002 //# Copyright (C) 2000,2001,2002,2004 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: Complex.h 20939 2010-08-25 09:06:51Z gervandiepen $ 00027 00028 00029 #ifndef CASA_COMPLEX_H 00030 #define CASA_COMPLEX_H 00031 00032 00033 //# Includes 00034 #include <casa/aips.h> 00035 #include <casa/BasicSL/Complexfwd.h> 00036 #include <casa/complex.h> 00037 00038 namespace casa { //# NAMESPACE CASA - BEGIN 00039 00040 // <summary> 00041 // Single and double precision complex numbers 00042 // </summary> 00043 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00044 // </reviewed> 00045 00046 // <synopsis> 00047 // The class <src>Complex</src> is a straight typedef as the 00048 // standard library <src>complex<float></src>. 00049 // 00050 // In a similar way <src>DComplex</src> is typedef-ed as 00051 // <src>complex<double></src>. 00052 // 00053 // <linkto class=IComplex>IComplex</linkto> is defined as a specific class. 00054 // It is only used by the <src>FITS</src> classes. 00055 // 00056 // <src>lDComplex</src> has not been defined: <src>long double</src> is not 00057 // part of the standard aips++ data suite (yet) 00058 // 00059 // A set of global functions are added for historic reasons (they were present 00060 // in the original aips++/gcc complex implementation). 00061 // 00062 // See the standard library documentation for the expected behaviour of 00063 // the <src>Complex</src> and <src>DComplex</src> classes. 00064 // 00065 // <note role=tip> In the following all references to <src>Complex</src> 00066 // can be replaced with <src>DComplex</src>. with simultaneous 00067 // replacement of <src>Float</src> with <src>Double</src>. </note> 00068 // 00069 // Complex numbers may be constructed and used in the following ways: 00070 // <dl> 00071 // <dt>Complex x;</dt> 00072 // <dd> Declares an uninitialized Complex. </dd> 00073 // 00074 // <dt>Complex x = 2; Complex y(2.0);</dt> 00075 // <dd> Set x and y to the Complex value (2.0, 0.0); </dd> 00076 // 00077 // <dt>Complex x(2, 3);</dt> 00078 // <dd> Sets x to the Complex value (2, 3); </dd> 00079 // 00080 // <dt>Complex u(x); Complex v = x;</dt> 00081 // <dd> Set u and v to the same value as x. </dd> 00082 // 00083 // <dt>Float real(Complex& x);</dt> 00084 // <dd> returns the real part of x. </dd> 00085 // 00086 // <dt>Float imag(Complex& x);</dt> 00087 // <dd> returns the imaginary part of x. </dd> 00088 // 00089 // <dt>Float abs(Complex& x);</dt> 00090 // <dd> returns the magnitude of x. </dd> 00091 // 00092 // <dt>Float norm(Complex& x);</dt> 00093 // <dd> returns the square of the magnitude of x. </dd> 00094 // 00095 // <dt>Float arg(Complex& x);</dt> 00096 // <dd> returns the argument (amplitude) of x. </dd> 00097 // 00098 // <dt>Complex polar(Float r, Float t = 0.0);</dt> 00099 // <dd> returns a Complex with abs of r and arg of t. </dd> 00100 // 00101 // <dt>Complex conj(Complex& x);</dt> 00102 // <dd> returns the complex conjugate of x </dd> 00103 // 00104 // <dt>Complex cos(Complex& x);</dt> 00105 // <dd> returns the complex cosine of x. </dd> 00106 // 00107 // <dt>Complex sin(Complex& x);</dt> 00108 // <dd> returns the complex sine of x. </dd> 00109 // 00110 // <dt>Complex cosh(Complex& x);</dt> 00111 // <dd> returns the complex hyperbolic cosine of x. </dd> 00112 // 00113 // <dt>Complex sinh(Complex& x);</dt> 00114 // <dd> returns the complex hyperbolic sine of x. </dd> 00115 // 00116 // <dt>Complex exp(Complex& x);</dt> 00117 // <dd> returns the exponential of x. </dd> 00118 // 00119 // <dt>Complex log(Complex& x);</dt> 00120 // <dd> returns the natural log of x. </dd> 00121 // 00122 // <dt>Complex pow(Complex& x, long p);</dt> 00123 // <dd> returns x raised to the p power. </dd> 00124 // 00125 // <dt>Complex pow(Complex& x, Complex& p);</dt> 00126 // <dd> returns x raised to the p power. </dd> 00127 // 00128 // <dt>Complex sqrt(Complex& x);</dt> 00129 // <dd> returns the square root of x. </dd> 00130 // 00131 // <dt> Complex min(Complex x,Complex y); 00132 // <dd> Returns the minumum of x,y (using operator<=, i.e. the norm). 00133 // 00134 // <dt> Complex max(Complex x,Complex y); 00135 // <dd> Returns the maximum of x,y (using operator>=, i.e. the norm). 00136 // 00137 // <dt>Bool near(Complex val1, Complex val2, Double tol = 1.0e-5);</dt> 00138 // <dd> returns whether val1 is relatively near val2 (see Math.h). 00139 // (Note the Double tolerance) </dd> 00140 // 00141 // <dt>Bool nearAbs(Complex val1, Complex val2, Double tol = 1.0e-5);</dt> 00142 // <dd> returns whether val1 is absolutely near val2 (see Math.h). 00143 // (Note the Double tolerance) </dd> 00144 // 00145 // <dt>ostream << x;</dt> 00146 // <dd> prints x in the form (re, im). </dd> 00147 // 00148 // <dt>istream >> x;</dt> 00149 // <dd> reads x in the form (re, im), or just (re) or re in which case the 00150 // imaginary part is set to zero. </dd> 00151 // </dl> 00152 // </synopsis> 00153 00154 //# <todo asof="2000/11/27"> 00155 //# </todo> 00156 00157 // <group name="Complex_desc"> 00158 00159 // <summary>Complex NaN and Infinity</summary> 00160 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00161 // </reviewed> 00162 // <group name="Complex NaN and Infinity"> 00163 Bool isNaN (const Complex& val); 00164 void setNaN(Complex& val); 00165 Bool isInf (const Complex& val); 00166 void setInf(Complex& val); 00167 // </group> 00168 00169 // <summary>Complex comparisons </summary> 00170 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00171 // </reviewed> 00172 // <group name="Complex comparisons"> 00173 //# On Linux comparing the norm does not work well in debug mode 00174 //# for equal values. Therefore they are compared for equality first. 00175 inline Bool operator>= (const Complex& left, const Complex& right) 00176 { return left==right ? True : norm(left) >= norm(right); } 00177 inline Bool operator> (const Complex& left, const Complex& right) 00178 { return left==right ? False : norm(left) > norm(right); } 00179 inline Bool operator<= (const Complex& left, const Complex& right) 00180 { return left==right ? True : norm(left) <= norm(right); } 00181 inline Bool operator< (const Complex& left, const Complex& right) 00182 { return left==right ? False : norm(left) < norm(right); } 00183 // </group> 00184 00185 00186 // <summary>DComplex NaN and Infinity</summary> 00187 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00188 // </reviewed> 00189 // <group name="DComplex NaN and Infinity"> 00190 Bool isNaN (const DComplex& val); 00191 void setNaN(DComplex& val); 00192 Bool isInf (const DComplex& val); 00193 void setInf(DComplex& val); 00194 // </group> 00195 00196 // <summary> DComplex comparisons </summary> 00197 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00198 // </reviewed> 00199 // <group name="DComplex comparisons"> 00200 inline Bool operator>= (const DComplex& left, const DComplex& right) 00201 { return norm(left) >= norm(right); } 00202 inline Bool operator> (const DComplex& left, const DComplex& right) 00203 { return norm(left) > norm(right); } 00204 inline Bool operator<= (const DComplex& left, const DComplex& right) 00205 { return norm(left) <= norm(right); } 00206 inline Bool operator< (const DComplex& left, const DComplex& right) 00207 { return norm(left) < norm(right); } 00208 // </group> 00209 00210 00211 //# Global functions 00212 // <summary> Additional complex mathematical functions </summary> 00213 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00214 // </reviewed> 00215 // <group name=math> 00216 inline Double fabs(const DComplex &val) { return std::abs(val); } 00217 inline Float fabs(const Complex &val) { return std::abs(val); } 00218 00219 inline DComplex square(const DComplex &val) { return val*val; } 00220 inline Complex square(const Complex &val) { return val*val; } 00221 00222 inline DComplex cube(const DComplex &val) { return val*val*val; } 00223 inline Complex cube(const Complex &val) { return val*val*val; } 00224 00225 // The log10 should be in stl 00226 // <group> 00227 #if defined(NEEDS_LOG10_COMPLEX) 00228 Complex log10(const Complex &val); 00229 DComplex log10(const DComplex &val); 00230 #endif 00231 // </group> 00232 00233 // ArrayMath::pow needs this pow function (on SGI). 00234 inline Complex pow(const Complex& val, Double p) { return std::pow(val,Float(p)); } 00235 00236 // QMath and scimath need these operators * and / 00237 // <group> 00238 inline Complex operator*(const Complex& val, Double f) { return val*Float(f); } 00239 inline Complex operator*(Double f, const Complex& val) { return val*Float(f); } 00240 inline Complex operator/(const Complex& val, Double f) { return val/Float(f); } 00241 inline Complex operator/(Double f, const Complex& val) { return Float(f)/val; } 00242 // </group> 00243 // These operators are useful, otherwise both Float and Double are applicable 00244 // for Ints. 00245 // <group> 00246 inline Complex operator*(const Complex& val, Int f) { return val*Float(f); } 00247 inline Complex operator*(Int f, const Complex& val) { return val*Float(f); } 00248 inline Complex operator/(const Complex& val, Int f) { return val/Float(f); } 00249 inline Complex operator/(Int f, const Complex& val) { return Float(f)/val; } 00250 // </group> 00251 // </group> 00252 00253 // <summary> The near functions </summary> 00254 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00255 // </reviewed> 00256 // <group name=near> 00257 Bool near(const Complex &val1, const Complex &val2, Double tol=1.0e-5); 00258 Bool near(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13); 00259 Bool nearAbs(const Complex &val1, const Complex &val2, Double tol=1.0e-5); 00260 Bool nearAbs(const DComplex &val1, const DComplex &val2, Double tol=1.0e-13); 00261 inline Bool allNear(const Complex &val1, const Complex &val2, 00262 Double tol=1.0e-5) 00263 { return near(val1, val2, tol); } 00264 inline Bool allNear(const DComplex &val1, const DComplex &val2, 00265 Double tol=1.0e-13) 00266 { return near(val1, val2, tol); } 00267 inline Bool allNearAbs(const Complex &val1, const Complex &val2, 00268 Double tol=1.0e-5) 00269 { return nearAbs(val1, val2, tol); } 00270 inline Bool allNearAbs(const DComplex &val1, const DComplex &val2, 00271 Double tol=1.0e-13) 00272 { return nearAbs(val1, val2, tol); } 00273 // </group> 00274 00275 // <summary> Max and min, floor and ceil functions </summary> 00276 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00277 // </reviewed> 00278 // <group name=maxmin> 00279 inline Complex max(const Complex &x, const Complex &y) 00280 { return x >= y ? x : y; } 00281 inline DComplex max(const DComplex &x, const DComplex &y) 00282 { return x >= y ? x : y; } 00283 00284 inline Complex min(const Complex &x, const Complex &y) 00285 { return x <= y ? x : y; } 00286 inline DComplex min(const DComplex &x, const DComplex &y) 00287 { return x <= y ? x : y; } 00288 00289 inline Complex floor(const Complex &x) { 00290 return Complex(std::floor(x.real()), std::floor(x.imag())); } 00291 inline DComplex floor(const DComplex &x) { 00292 return DComplex(std::floor(x.real()), std::floor(x.imag())); } 00293 00294 inline Complex ceil(const Complex &x) { 00295 return Complex(std::ceil(x.real()), std::ceil(x.imag())); } 00296 inline DComplex ceil(const DComplex &x) { 00297 return DComplex(std::ceil(x.real()), std::ceil(x.imag())); } 00298 // </group> 00299 00300 // <summary> fmod </summary> 00301 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00302 // </reviewed> 00303 // <group name=fmod> 00304 DComplex fmod(const DComplex &in, const DComplex &f); 00305 Complex fmod(const Complex &in, const Complex &f); 00306 // </group> 00307 00308 // <summary> Inverse trigonometry </summary> 00309 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00310 // </reviewed> 00311 // <group name=inverse> 00312 // atan not valid for z == -1 00313 DComplex atan(const DComplex &in); 00314 Complex atan(const Complex &in); 00315 DComplex asin(const DComplex &in); 00316 Complex asin(const Complex &in); 00317 DComplex acos(const DComplex &in); 00318 Complex acos(const Complex &in); 00319 DComplex atan2(const DComplex &in, const DComplex &t2); 00320 Complex atan2(const Complex &in, const Complex &t2); 00321 // </group> 00322 00323 // <summary> Error function </summary> 00324 // <reviewed reviewer="UNKNOWN" date="before2004/08/25" tests="" demos=""> 00325 // </reviewed> 00326 // <group name=erf> 00327 // Preliminary to get Functionals working. erf(z) will return erf(real(z)) 00328 // only for now. 00329 DComplex erf(const DComplex &in); 00330 Complex erf(const Complex &in); 00331 DComplex erfc(const DComplex &in); 00332 Complex erfc(const Complex &in); 00333 // </group> 00334 00335 // </group> 00336 00337 } //# NAMESPACE CASA - END 00338 00339 // Define real & complex conjugation for non-complex types 00340 // and put comparisons into std namespace. 00341 namespace std { 00342 inline float conj(float x) { return x; } 00343 inline double conj(double x) { return x; } 00344 inline float real(float x) { return x; } 00345 inline double real(double x) { return x; } 00346 inline float imag(float ) { return 0; } 00347 inline double imag(double ) { return 0; } 00348 00349 using casa::operator>; 00350 using casa::operator>=; 00351 using casa::operator<; 00352 using casa::operator<=; 00353 } 00354 00355 #endif