MsPASS C++ API  2.4.3.dev1+g61b06b96
Defines the C++ API for MsPASS
Loading...
Searching...
No Matches
ComplexArray.h
1#ifndef __COMPLEX_ARRAY_H__
2#define __COMPLEX_ARRAY_H__
3
4#include <boost/archive/text_iarchive.hpp>
5#include <boost/archive/text_oarchive.hpp>
6#include <boost/serialization/shared_ptr.hpp>
7#include <complex>
8#include <gsl/gsl_errno.h>
9#include <gsl/gsl_fft_complex.h>
10#include "mspass/utility/MsPASSError.h"
11#include <iostream>
12#include <string>
13#include <utility>
14#include <vector>
15
16#define REAL(z, i) ((z)[2 * (i)])
17#define IMAG(z, i) ((z)[2 * (i) + 1])
18namespace mspass::algorithms::deconvolution {
19typedef std::complex<double> Complex64;
20typedef std::complex<float> Complex32;
21
23typedef struct FortranComplex32 {
24 float real;
25 float imag;
28typedef struct FortranComplex64 {
29 double real;
30 double imag;
32/* needed for boost serialization */
33template <class Archive>
34void serialize(Archive &ar, FortranComplex64 &z, const unsigned int version) {
35 ar & z.real;
36 ar & z.imag;
37}
38
45public:
49 ComplexArray(std::vector<Complex64> &d);
51 ComplexArray(std::vector<Complex32> &d);
62 ComplexArray(int nsamp, FortranComplex32 *d);
64 ComplexArray(int nsamp, FortranComplex64 *d);
66 ComplexArray(int nsamp, float *d);
68 ComplexArray(int nsamp, double *d);
70 ComplexArray(int nsamp);
74 template <class T> ComplexArray(int nsamp, std::vector<T> d);
76 template <class T> ComplexArray(int nsamp, T d);
77
79 ComplexArray(std::vector<double> mag, std::vector<double> phase);
80
81 /* These will need to be implemented. Likely cannot
82 depend on the compiler to generate them correctly */
84 ComplexArray(const ComplexArray &parent);
86 ComplexArray &operator=(const ComplexArray &parent);
88 void swap(ComplexArray &other) noexcept {
89 data.swap(other.data);
90 std::swap(nsamp, other.nsamp);
91 }
94
95 /* These are kind of the inverse of the constructor.
96 Independent of what the internal representation is they
97 will return useful interface representations. */
105 // template<class T> T *FortranData();
106 /* This is same for what I think fortran calls
107 double complex */
108 // double *FortranData();
109 /* C representation. This can be templated easily.
110 See below. The syntax is weird and should probably
111 be wrapped with a typedef */
112 // template<class T> std::vector<std::complex<T> > CPPData();
113
114 /* Operators are the most important elements of this
115 thing to make life easier. */
122 Complex64 operator[](int sample);
124 double *ptr();
126 double *ptr(int sample);
128 ComplexArray &operator+=(const ComplexArray &other) noexcept(false);
130 ComplexArray &operator-=(const ComplexArray &other) noexcept(false);
131 /* This actually is like .* in matlab - sample by sample multiply not
132 a dot product */
134 ComplexArray &operator*=(const ComplexArray &other) noexcept(false);
135 /* This is like *= but complex divide element by element */
137 ComplexArray &operator/=(const ComplexArray &other) noexcept(false);
139 const ComplexArray operator+(const ComplexArray &other) const noexcept(false);
140 // template<class T> ComplexArray operator +(const vector<T> &other);
141 // template<class T> ComplexArray operator +(const T &other);
143 const ComplexArray operator-(const ComplexArray &other) const noexcept(false);
144 // template<class T> ComplexArray operator -(const vector<T> &other);
145 // template<class T> ComplexArray operator -(const T &other);
147 const ComplexArray operator*(const ComplexArray &other) const noexcept(false);
149 const ComplexArray operator/(const ComplexArray &other) const noexcept(false);
151 // template<class T> ComplexArray operator *(const vector<T> &other);
152 // template<class T> friend ComplexArray operator *(const vector<T> &lhs,const
153 // ComplexArray &rhs);
155 // template<class T> ComplexArray operator *(const T &other);
156 // template<class T> friend ComplexArray operator *(const T &lhs,const
157 // ComplexArray &rhs);
159 void conj();
161 std::vector<double> abs() const;
163 double rms() const;
165 double norm2() const;
167 std::vector<double> phase() const;
169 int size() const;
170
171private:
172 /* Here is an implementation detail. There are three ways
173 I can think to do this. First, we could internally store
174 data as fortran array of 32 bit floats. That is probably
175 the best because we can use BLAS routines (if you haven't
176 heard of this - likely - I need to educate you.) to do
177 most of the numerics fast. Second, we could use stl
178 vector container of std::complex. The third is excessively
179 messy but technically feasible - I would not recommend it.
180 That is, one could store pointers to either representation
181 and internally convert back and forth. Ugly and dangerous
182 I think.
183
184 I suggest we store a FORTRAN 32 bit form since that is
185 what standard numeric libraries (e.g. most fft routines)
186 use. */
187 /*I decided to use 64 bit, since the GSL's fft routine is using that.*/
188 /* Changed from raw pointer to shared_ptr by glp - Dec 2024 */
189 // FortranComplex64 *data;
190 std::shared_ptr<FortranComplex64[]> data;
191 int nsamp;
192 friend boost::serialization::access;
193 template <class Archive>
194 void save(Archive &ar, const unsigned int version) const {
195 std::vector<FortranComplex64> dv;
196 dv.reserve(this->nsamp);
197 for (auto i = 0; i < nsamp; ++i)
198 dv.push_back(this->data[i]);
199 ar & nsamp;
200 ar & dv;
201 }
202 template <class Archive> void load(Archive &ar, const unsigned int version) {
203 int loaded_nsamp;
204 std::vector<FortranComplex64> dv;
205 ar & loaded_nsamp;
206 ar & dv;
207 const std::string caller("ComplexArray serialization load");
208 if (loaded_nsamp < 0)
210 caller + ": archived sample count cannot be negative",
211 mspass::utility::ErrorSeverity::Invalid);
212 if (dv.size() != static_cast<size_t>(loaded_nsamp))
214 caller + ": archived sample count does not match data vector",
215 mspass::utility::ErrorSeverity::Invalid);
216
217 std::shared_ptr<FortranComplex64[]> loaded_data;
218 if (loaded_nsamp > 0) {
219 loaded_data = std::shared_ptr<FortranComplex64[]>(
220 new FortranComplex64[loaded_nsamp]);
221 for (int i = 0; i < loaded_nsamp; ++i)
222 loaded_data[i] = dv[i];
223 }
224 data.swap(loaded_data);
225 nsamp = loaded_nsamp;
226 }
227 BOOST_SERIALIZATION_SPLIT_MEMBER()
228};
229/* This would normally be in the .h file and since I don't think
230 you've used templates worth showing you how it would work. */
231/*
232template <class T> std::vector<std::complex<T> > ComplexArray::CPPData()
233{
234 std::vector<std::complex<T> > result;
235 result.reserve(nsamp);
236 std::size_t i;
237 for(i=0; i<nsamp; ++i)
238 {
239 std::complex<T> z(data[i].real, data[i].imag);
240 result.push_back(z);
241 }
242 return result;
243}
244*/
245
246/*
247template<class T> T* ComplexArray::FortranData()
248{
249 T* result=new T[nsamp];
250 for(std::size_t i=0; i<nsamp; i++)
251 result[i]=data[i];
252 return result;
253}
254*/
255
256template <class T> ComplexArray::ComplexArray(int n, std::vector<T> d) {
257 nsamp = n;
258 if (nsamp > d.size()) {
259 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
260 for (std::size_t i = 0; i < d.size(); i++) {
261 this->data[i].real = d[i];
262 this->data[i].imag = 0.0;
263 }
264 for (std::size_t i = d.size(); i < nsamp; i++) {
265 this->data[i].real = 0.0;
266 this->data[i].imag = 0.0;
267 }
268 } else {
269 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
270 for (std::size_t i = 0; i < nsamp; i++) {
271 this->data[i].real = d[i];
272 this->data[i].imag = 0.0;
273 }
274 }
275}
276template <class T> ComplexArray::ComplexArray(int n, T d) {
277 nsamp = n;
278 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
279 for (std::size_t i = 0; i < nsamp; i++) {
280 this->data[i].real = d;
281 this->data[i].imag = 0.0;
282 }
283}
284/*
285template<class T> ComplexArray ComplexArray::operator +(const vector<T> &other)
286{
287 ComplexArray result(*this);
288 int n;
289 if(nsamp>other.size())
290 n=other.size();
291 else
292 n=nsamp;
293 for(int i=0; i<n; i++)
294 {
295 result.data[i].real=data[i].real+other[i];
296 }
297 return result;
298}
299template<class T> ComplexArray ComplexArray::operator +(const T &other)
300{
301 ComplexArray result(*this);
302 for(int i=0; i<nsamp; i++)
303 {
304 result.data[i].real=data[i].real+other;
305 }
306 return result;
307}
308template<class T> ComplexArray ComplexArray::operator -(const vector<T> &other)
309{
310 ComplexArray result(*this);
311 int n;
312 if(nsamp>other.size())
313 n=other.size();
314 else
315 n=nsamp;
316 for(int i=0; i<n; i++)
317 {
318 result.data[i].real=data[i].real-other[i];
319 }
320 return result;
321}
322template<class T> ComplexArray ComplexArray::operator -(const T &other)
323{
324 ComplexArray result(*this);
325 for(int i=0; i<nsamp; i++)
326 {
327 result.data[i].real=data[i].real-other;
328 }
329 return result;
330}
331template<class T> ComplexArray ComplexArray::operator *(const vector<T> &other)
332{
333 ComplexArray result(*this);
334 int n;
335 if(nsamp>other.size())
336 n=other.size();
337 else
338 n=nsamp;
339 for(int i=0; i<n; i++)
340 {
341 result.data[i].real=data[i].real*other[i];
342 result.data[i].imag=data[i].imag*other[i];
343 }
344 return result;
345}
346template<class T> ComplexArray operator *(const vector<T>& lhs,const
347ComplexArray& rhs)
348{
349 return rhs*lhs;
350}
351template<class T> ComplexArray ComplexArray::operator *(const T &other)
352{
353 ComplexArray result(*this);
354 for(int i=0; i<nsamp; i++)
355 {
356 result.data[i].real=data[i].real*other;
357 result.data[i].imag=data[i].imag*other;
358 }
359 return result;
360}
361template<class T> ComplexArray operator *(const T& lhs,const ComplexArray& rhs)
362{
363 return rhs*lhs;
364}
365*/
366} // namespace mspass::algorithms::deconvolution
367#endif
Interfacing object to ease conversion between FORTRAN and C++ complex.
Definition ComplexArray.h:44
const ComplexArray operator*(const ComplexArray &other) const noexcept(false)
Definition ComplexArray.cc:221
ComplexArray()
Definition ComplexArray.cc:8
double rms() const
Definition ComplexArray.cc:253
double norm2() const
Definition ComplexArray.cc:261
int size() const
Definition ComplexArray.cc:275
const ComplexArray operator/(const ComplexArray &other) const noexcept(false)
Definition ComplexArray.cc:231
ComplexArray & operator=(const ComplexArray &parent)
Definition ComplexArray.cc:94
std::vector< double > abs() const
Definition ComplexArray.cc:245
ComplexArray & operator-=(const ComplexArray &other) noexcept(false)
Definition ComplexArray.cc:135
void conj()
Definition ComplexArray.cc:241
Complex64 operator[](int sample)
Definition ComplexArray.cc:117
void swap(ComplexArray &other) noexcept
Definition ComplexArray.h:88
double * ptr()
Definition ComplexArray.cc:111
ComplexArray & operator+=(const ComplexArray &other) noexcept(false)
Definition ComplexArray.cc:120
const ComplexArray operator+(const ComplexArray &other) const noexcept(false)
Definition ComplexArray.cc:201
ComplexArray & operator/=(const ComplexArray &other) noexcept(false)
Definition ComplexArray.cc:168
std::vector< double > phase() const
Definition ComplexArray.cc:268
const ComplexArray operator-(const ComplexArray &other) const noexcept(false)
Definition ComplexArray.cc:211
~ComplexArray()
Definition ComplexArray.cc:106
ComplexArray & operator*=(const ComplexArray &other) noexcept(false)
Definition ComplexArray.cc:150
Base class for error object thrown by MsPASS library routines.
Definition MsPASSError.h:38
FORTRAN-compatible single-precision complex value.
Definition ComplexArray.h:23
float imag
Definition ComplexArray.h:25
float real
Definition ComplexArray.h:24
FORTRAN-compatible double-precision complex value.
Definition ComplexArray.h:28
double imag
Definition ComplexArray.h:30
double real
Definition ComplexArray.h:29