CARMA C++
Complex.h
Go to the documentation of this file.
1 #ifndef SZA_UTIL_COMPLEX_H
2 #define SZA_UTIL_COMPLEX_H
3 
11 #include <cmath>
12 #include <iostream>
13 #include <sstream>
14 #include <complex>
15 
16 // Conversion from radians to degrees
17 
18 #define radiansToDegrees_ 180.0/M_PI
19 
20 namespace sza {
21  namespace util {
22 
23  // Non-member template friends require forward declaration
24 
25  template<class Type>
26  class Complex;
27 
28  template<class Type>
29  std::ostream& operator<<(std::ostream& os,
30  Complex<Type>& val);
31  template<class Type>
32  std::ostringstream& operator<<(std::ostringstream& os,
33  Complex<Type>& val);
34 
35  // A class for handling complex numbers, since std::complex<> is
36  // pretty useless
37 
38  template<class Type>
39  class Complex {
40 
41  public:
42 
43  // An internal data struct we will use for raw pointers. I.e.,
44  // a raw byte array can be cast to type (Complex<Type>::Data)*
45  // without confusion, whereas the same cannot be done with
46  // Complex<Type>*
47 
48  struct Data {
49  Type real_;
50  Type imag_;
51  };
52 
56  Complex(Type real, Type imag) {
57  data_.real_ = real;
58  data_.imag_ = imag;
59  }
60 
61  Complex(std::complex<Type> cVal) {
62  data_.real_ = cVal.real();
63  data_.imag_ = cVal.imag();
64  }
65 
66  // Constructor with a Data struct
67 
68  Complex(Data& data)
69  {
70  data_.real_ = data.real_;
71  data_.imag_ = data.imag_;
72  }
73 
74  // Copy constructor
75 
76  Complex(const Complex<Type>& complx)
77  {
78  data_.real_ = complx.data_.real_;
79  data_.imag_ = complx.data_.imag_;
80  }
81 
82  Complex() {
83  initialize();
84  };
85 
89  virtual ~Complex() {};
90 
91  void setReal(Type real) {
92  data_.real_ = real;
93  }
94 
95  void setImag(Type imag) {
96  data_.imag_ = imag;
97  }
98 
99  // Return the real part of the complex number
100 
101  inline Type real() {
102  return data_.real_;
103  }
104 
105  // Return the imaginary part of the complex number
106 
107  inline Type imag() {
108  return data_.imag_;
109  }
110 
111  // Return the amplitude of the complex number
112 
113  inline double amp() {
114  return amplitude();
115  }
116 
117  inline double amplitude() {
118  Type real = data_.real_;
119  Type imag = data_.imag_;
120  return sqrt((double)(real*real + imag*imag));
121  }
122 
123  inline double squaredAmplitude() const {
124  Type real = data_.real_;
125  Type imag = data_.imag_;
126  return (real*real + imag*imag);
127  }
128 
129  // Return the conjugate of a complex number
130 
131  Complex<Type> conjugate() const {
132  Complex<Type> conj(data_.real_, -data_.imag_);
133  return conj;
134  }
135 
136  // Return the phase of the complex number
137 
138  inline double phaseInRadians() {
139  if((double)data_.real_ == 0.0 && (double)data_.imag_ == 0.0)
140  return 0.0;
141  else {
142  Type real = data_.real_;
143  Type imag = data_.imag_;
144  return atan2((double)imag, (double)real);
145  }
146  }
147 
148  inline double phaseInDegrees() {
149  return phaseInRadians() * radiansToDegrees_;
150  }
151 
152  inline void initialize() {
153  data_.real_ = (Type)0;
154  data_.imag_ = (Type)0;
155  }
156 
157  // Assignment operator.
158 
159  void operator=(Data& data) {
160  data_.real_ = data.real_;
161  data_.imag_ = data.imag_;
162  }
163 
164  void operator=(const Complex<Type>& cmplx) {
165  data_.real_ = cmplx.data_.real_;
166  data_.imag_ = cmplx.data_.imag_;
167  }
168 
169  void operator|=(const Complex<Type>& cmplx) {
170  data_.real_ = (Type)((unsigned)data_.real_ | (unsigned)cmplx.data_.real_);
171  data_.imag_ = (Type)((unsigned)data_.imag_ | (unsigned)cmplx.data_.imag_);
172  }
173 
174  void operator+=(const Complex<Type>& cmplx) {
175  data_.real_ += cmplx.data_.real_;
176  data_.imag_ += cmplx.data_.imag_;
177  }
178 
179  void operator-=(const Complex<Type>& cmplx) {
180  data_.real_ -= cmplx.data_.real_;
181  data_.imag_ -= cmplx.data_.imag_;
182  }
183 
184  Complex<Type> operator+(const Complex<Type>& cmplx) {
185  Complex<Type> sum(data_.real_ + cmplx.data_.real_,
186  data_.imag_ + cmplx.data_.imag_);
187  return sum;
188  }
189 
190  Complex<Type> operator-(const Complex<Type>& cmplx) {
191  Complex<Type> diff(data_.real_ - cmplx.data_.real_,
192  data_.imag_ - cmplx.data_.imag_);
193  return diff;
194  }
195 
196  Complex<Type> operator*(const Complex<Type>& cmplx) {
197  Type re, im;
198 
199  re = data_.real_ * cmplx.data_.real_ - data_.imag_ * cmplx.data_.imag_;
200  im = data_.imag_ * cmplx.data_.real_ + data_.real_ * cmplx.data_.imag_;
201 
202  Complex<Type> product(re, im);
203  return product;
204  }
205 
206  Complex<Type> operator|(const Complex<Type>& cmplx) {
207  Type re, im;
208 
209  re = (Type)((unsigned)data_.real_ | (unsigned)cmplx.data_.real_);
210  im = (Type)((unsigned)data_.imag_ | (unsigned)cmplx.data_.imag_);
211 
212  Complex<Type> bitwiseOr(re, im);
213  return bitwiseOr;
214  }
215 
216  Complex<Type> operator/(const Complex<Type>& cmplx) {
217  return (*this) * (cmplx.conjugate()/cmplx.squaredAmplitude());
218  }
219 
220  Complex<Type> operator/(unsigned int divisor){
221  Complex<Type> div(data_.real_ / divisor,
222  data_.imag_ / divisor);
223  return div;
224  }
225 
226  Complex<Type> operator/(double divisor){
227  Complex<Type> div(data_.real_ / divisor,
228  data_.imag_ / divisor);
229  return div;
230  }
231 
232  // Comparison operator.
233 
234  bool operator==(Complex<Type>& comp) {
235  return (real() == comp.real()) && (imag() == comp.imag());
236  }
237 
238  bool operator>(Complex<Type>& comp) {
239  return amp() > comp.amp();
240  }
241 
242  bool operator>=(Complex<Type>& comp) {
243  return amp() >= comp.amp();
244  }
245 
246  bool operator<(Complex<Type>& comp) {
247  return amp() < comp.amp();
248  }
249 
250  bool operator<=(Complex<Type>& comp) {
251  return amp() <= comp.amp();
252  }
253 
254  // Return our internal data
255 
256  Data* data() {
257  return &data_;
258  }
259 
260  // Friend operators for printing a complex number
261 
262  friend std::ostream& operator << <>
263  (std::ostream& os, Complex<Type>& val);
264 
265  friend std::ostringstream& operator << <>
266  (std::ostringstream& os, Complex<Type>& val);
267 
268  private:
269 
270  // The internal data of this complex number
271 
272  Data data_;
273 
274  }; // End class Complex
275 
276 
277  // Class methods
278 
279  // Some friend helper functions
280 
281  // Print out a matrix to a stream
282 
283  template<class Type>
284  std::ostream& operator<<(std::ostream& os,
285  Complex<Type>& val)
286  {
287  Type real = val.real();
288  Type imag = val.imag();
289 
290  os << real << (imag < 0 ? " - " : " + ") << "i " << fabs(imag);
291  return os;
292  }
293 
294  // Print out a complex to an ostringstream
295 
296  template<class Type>
297  std::ostringstream& operator<<(std::ostringstream& os,
298  Complex<Type>& val)
299  {
300  Type real = val.real();
301  Type imag = val.imag();
302 
303  os << real() << (imag < 0 ? "-" : "+") << "i" << abs(imag);
304  return os;
305  }
306 
307  } // End namespace util
308 } // End namespace sza
309 
310 
311 
312 #endif // End #ifndef SZA_UTIL_COMPLEX_H
float amp(std::complex< float > visibility)
Compute the visibility amplitude from a complex visibility.
Definition: complexManip.h:15
std::complex< double > Complex
convenient definition of a complex number.
Definition: Selfcal.h:28