blob: 597a26f83ebce3034ac46bb4b8d7cdddd7a38718 [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/**@file templates for Complex classes
2unlike the built-in complex<> templates, these inline most operations for speed
3*/
4
5/*
6* Copyright 2008 Free Software Foundation, Inc.
7*
Martin Hauke066fd042019-10-13 19:08:00 +02008* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
dburgessb3a0ca42011-10-12 07:44:40 +00009*
10* This use of this software may be subject to additional restrictions.
11* See the LEGAL file in the main directory for details.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17*/
18
19
20
21
22#ifndef COMPLEXCPP_H
23#define COMPLEXCPP_H
24
25#include <math.h>
26#include <ostream>
27
28
29template<class Real> class Complex {
30
31public:
Eric Wild621a49e2023-01-12 16:21:58 +010032 typedef Real value_type;
dburgessb3a0ca42011-10-12 07:44:40 +000033 Real r, i;
34
35 /**@name constructors */
36 //@{
37 /**@name from real */
38 //@{
39 Complex(Real real, Real imag) {r=real; i=imag;} // x=complex(a,b)
40 Complex(Real real) {r=real; i=0;} // x=complex(a)
41 //@}
42 /**@name from nothing */
43 //@{
44 Complex() {r=(Real)0; i=(Real)0;} // x=complex()
45 //@}
46 /**@name from other complex */
47 //@{
48 Complex(const Complex<float>& z) {r=z.r; i=z.i;} // x=complex(z)
49 Complex(const Complex<double>& z) {r=z.r; i=z.i;} // x=complex(z)
50 Complex(const Complex<long double>& z) {r=z.r; i=z.i;} // x=complex(z)
51 //@}
52 //@}
53
54 /**@name casting up from basic numeric types */
55 //@{
56 Complex& operator=(char a) { r=(Real)a; i=(Real)0; return *this; }
57 Complex& operator=(int a) { r=(Real)a; i=(Real)0; return *this; }
58 Complex& operator=(long int a) { r=(Real)a; i=(Real)0; return *this; }
59 Complex& operator=(short a) { r=(Real)a; i=(Real)0; return *this; }
60 Complex& operator=(float a) { r=(Real)a; i=(Real)0; return *this; }
61 Complex& operator=(double a) { r=(Real)a; i=(Real)0; return *this; }
62 Complex& operator=(long double a) { r=(Real)a; i=(Real)0; return *this; }
63 //@}
64
65 /**@name arithmetic */
66 //@{
67 /**@ binary operators */
68 //@{
69 Complex operator+(const Complex<Real>& a) const { return Complex<Real>(r+a.r, i+a.i); }
70 Complex operator+(Real a) const { return Complex<Real>(r+a,i); }
71 Complex operator-(const Complex<Real>& a) const { return Complex<Real>(r-a.r, i-a.i); }
72 Complex operator-(Real a) const { return Complex<Real>(r-a,i); }
73 Complex operator*(const Complex<Real>& a) const { return Complex<Real>(r*a.r-i*a.i, r*a.i+i*a.r); }
74 Complex operator*(Real a) const { return Complex<Real>(r*a, i*a); }
75 Complex operator/(const Complex<Real>& a) const { return operator*(a.inv()); }
76 Complex operator/(Real a) const { return Complex<Real>(r/a, i/a); }
77 //@}
78 /*@name component-wise product */
79 //@{
80 Complex operator&(const Complex<Real>& a) const { return Complex<Real>(r*a.r, i*a.i); }
81 //@}
82 /*@name inplace operations */
83 //@{
84 Complex& operator+=(const Complex<Real>&);
85 Complex& operator-=(const Complex<Real>&);
86 Complex& operator*=(const Complex<Real>&);
87 Complex& operator/=(const Complex<Real>&);
88 Complex& operator+=(Real);
89 Complex& operator-=(Real);
90 Complex& operator*=(Real);
91 Complex& operator/=(Real);
92 //@}
93 //@}
94
95 /**@name comparisons */
96 //@{
97 bool operator==(const Complex<Real>& a) const { return ((i==a.i)&&(r==a.r)); }
98 bool operator!=(const Complex<Real>& a) const { return ((i!=a.i)||(r!=a.r)); }
99 bool operator<(const Complex<Real>& a) const { return norm2()<a.norm2(); }
100 bool operator>(const Complex<Real>& a) const { return norm2()>a.norm2(); }
101 //@}
102
103 /// reciprocation
104 Complex inv() const;
105
106 // unary functions -- inlined
107 /**@name unary functions */
108 //@{
109 /**@name inlined */
110 //@{
111 Complex conj() const { return Complex<Real>(r,-i); }
112 Real norm2() const { return i*i+r*r; }
113 Complex flip() const { return Complex<Real>(i,r); }
114 Real real() const { return r;}
115 Real imag() const { return i;}
116 Complex neg() const { return Complex<Real>(-r, -i); }
117 bool isZero() const { return ((r==(Real)0) && (i==(Real)0)); }
118 //@}
119 /**@name not inlined due to outside calls */
120 //@{
121 Real abs() const { return ::sqrt(norm2()); }
122 Real arg() const { return ::atan2(i,r); }
123 float dB() const { return 10.0*log10(norm2()); }
124 Complex exp() const { return expj(i)*(::exp(r)); }
125 Complex unit() const; ///< unit phasor with same angle
126 Complex log() const { return Complex(::log(abs()),arg()); }
127 Complex pow(double n) const { return expj(arg()*n)*(::pow(abs(),n)); }
128 Complex sqrt() const { return pow(0.5); }
129 //@}
130 //@}
131
132};
133
134
135/**@name standard Complex manifestations */
136//@{
137typedef Complex<float> complex;
138typedef Complex<double> dcomplex;
139typedef Complex<short> complex16;
140typedef Complex<long> complex32;
141//@}
142
143
144template<class Real> inline Complex<Real> Complex<Real>::inv() const
145{
146 Real nVal;
147
148 nVal = norm2();
149 return Complex<Real>(r/nVal, -i/nVal);
150}
151
152template<class Real> Complex<Real>& Complex<Real>::operator+=(const Complex<Real>& a)
153{
154 r += a.r;
155 i += a.i;
156 return *this;
157}
158
159template<class Real> Complex<Real>& Complex<Real>::operator*=(const Complex<Real>& a)
160{
161 operator*(a);
162 return *this;
163}
164
165template<class Real> Complex<Real>& Complex<Real>::operator-=(const Complex<Real>& a)
166{
167 r -= a.r;
168 i -= a.i;
169 return *this;
170}
171
172template<class Real> Complex<Real>& Complex<Real>::operator/=(const Complex<Real>& a)
173{
174 operator/(a);
175 return *this;
176}
177
178
179/* op= style operations with reals */
180
181template<class Real> Complex<Real>& Complex<Real>::operator+=(Real a)
182{
183 r += a;
184 return *this;
185}
186
187template<class Real> Complex<Real>& Complex<Real>::operator*=(Real a)
188{
189 r *=a;
190 i *=a;
191 return *this;
192}
193
194template<class Real> Complex<Real>& Complex<Real>::operator-=(Real a)
195{
196 r -= a;
197 return *this;
198}
199
200template<class Real> Complex<Real>& Complex<Real>::operator/=(Real a)
201{
202 r /= a;
203 i /= a;
204 return *this;
205}
206
207
208template<class Real> Complex<Real> Complex<Real>::unit() const
209{
210 Real absVal = abs();
211 return (Complex<Real>(r/absVal, i/absVal));
212}
213
214
215
216/**@name complex functions outside of the Complex<> class. */
217//@{
218
219/** this allows type-commutative multiplication */
220template<class Real> Complex<Real> operator*(Real a, const Complex<Real>& z)
221{
222 return Complex<Real>(z.r*a, z.i*a);
223}
224
225
226/** this allows type-commutative addition */
227template<class Real> Complex<Real> operator+(Real a, const Complex<Real>& z)
228{
229 return Complex<Real>(z.r+a, z.i);
230}
231
232
233/** this allows type-commutative subtraction */
234template<class Real> Complex<Real> operator-(Real a, const Complex<Real>& z)
235{
236 return Complex<Real>(z.r-a, z.i);
237}
238
239
240
241/// e^jphi
242template<class Real> Complex<Real> expj(Real phi)
243{
244 return Complex<Real>(cos(phi),sin(phi));
245}
246
247/// phasor expression of a complex number
248template<class Real> Complex<Real> phasor(Real C, Real phi)
249{
250 return (expj(phi)*C);
251}
252
253/// formatted stream output
254template<class Real> std::ostream& operator<<(std::ostream& os, const Complex<Real>& z)
255{
256 os << z.r << ' ';
257 //os << z.r << ", ";
258 //if (z.i>=0) { os << "+"; }
259 os << z.i << "j";
dburgessb3a0ca42011-10-12 07:44:40 +0000260 return os;
261}
262
263//@}
264
265
266#endif