version  0.0.1
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 <iostream>
11#include <vector>
12
13#define REAL(z, i) ((z)[2 * (i)])
14#define IMAG(z, i) ((z)[2 * (i) + 1])
15namespace mspass::algorithms::deconvolution {
16typedef std::complex<double> Complex64;
17typedef std::complex<float> Complex32;
18
19typedef struct FortranComplex32 {
20 float real;
21 float imag;
23typedef struct FortranComplex64 {
24 double real;
25 double imag;
27/* needed for boost serialization */
28template <class Archive>
29void serialize(Archive &ar, FortranComplex64 &z, const unsigned int version) {
30 ar & z.real;
31 ar & z.imag;
32}
33
34/* \brief Interfacing object to ease conversion between FORTRAN and C++ complex.
35
36 */
38public:
42 ComplexArray(std::vector<Complex64> &d);
44 ComplexArray(std::vector<Complex32> &d);
55 ComplexArray(int nsamp, FortranComplex32 *d);
56 ComplexArray(int nsamp, FortranComplex64 *d);
57 ComplexArray(int nsamp, float *d);
58 ComplexArray(int nsamp, double *d);
59 ComplexArray(int nsamp);
63 template <class T> ComplexArray(int nsamp, std::vector<T> d);
64 template <class T> ComplexArray(int nsamp, T d);
65
67 ComplexArray(std::vector<double> mag, std::vector<double> phase);
68
69 /* These will need to be implemented. Likely cannot
70 depend on the compiler to generate them correctly */
71 ComplexArray(const ComplexArray &parent);
72 ComplexArray &operator=(const ComplexArray &parent);
74
75 /* These are kind of the inverse of the constructor.
76 Independent of what the internal representation is they
77 will return useful interface representations. */
85 // template<class T> T *FortranData();
86 /* This is same for what I think fortran calls
87 double complex */
88 // double *FortranData();
89 /* C representation. This can be templated easily.
90 See below. The syntax is weird and should probably
91 be wrapped with a typedef */
92 // template<class T> std::vector<std::complex<T> > CPPData();
93
94 /* Operators are the most important elements of this
95 thing to make life easier. */
102 Complex64 operator[](int sample);
103 double *ptr();
104 double *ptr(int sample);
105 ComplexArray &operator+=(const ComplexArray &other) noexcept(false);
106 ComplexArray &operator-=(const ComplexArray &other) noexcept(false);
107 /* This actually is like .* in matlab - sample by sample multiply not
108 a dot product */
109 ComplexArray &operator*=(const ComplexArray &other) noexcept(false);
110 /* This is like *= but complex divide element by element */
111 ComplexArray &operator/=(const ComplexArray &other) noexcept(false);
112 const ComplexArray operator+(const ComplexArray &other) const noexcept(false);
113 // template<class T> ComplexArray operator +(const vector<T> &other);
114 // template<class T> ComplexArray operator +(const T &other);
115 const ComplexArray operator-(const ComplexArray &other) const noexcept(false);
116 // template<class T> ComplexArray operator -(const vector<T> &other);
117 // template<class T> ComplexArray operator -(const T &other);
118 const ComplexArray operator*(const ComplexArray &other) const noexcept(false);
119 const ComplexArray operator/(const ComplexArray &other) const noexcept(false);
121 // template<class T> ComplexArray operator *(const vector<T> &other);
122 // template<class T> friend ComplexArray operator *(const vector<T> &lhs,const
123 // ComplexArray &rhs);
125 // template<class T> ComplexArray operator *(const T &other);
126 // template<class T> friend ComplexArray operator *(const T &lhs,const
127 // ComplexArray &rhs);
129 void conj();
130 /* Return stl vector of amplitude spectrum. */
131 std::vector<double> abs() const;
132 /* Return rms value. */
133 double rms() const;
134 /* Return 2-norm value. */
135 double norm2() const;
136 /* Return stl vector of phase */
137 std::vector<double> phase() const;
138 /* Return size of the array*/
139 int size() const;
140
141private:
142 /* Here is an implementation detail. There are three ways
143 I can think to do this. First, we could internally store
144 data as fortran array of 32 bit floats. That is probably
145 the best because we can use BLAS routines (if you haven't
146 heard of this - likely - I need to educate you.) to do
147 most of the numerics fast. Second, we could use stl
148 vector container of std::complex. The third is excessively
149 messy but technically feasible - I would not recommend it.
150 That is, one could store pointers to either representation
151 and internally convert back and forth. Ugly and dangerous
152 I think.
153
154 I suggest we store a FORTRAN 32 bit form since that is
155 what standard numeric libraries (e.g. most fft routines)
156 use. */
157 /*I decided to use 64 bit, since the GSL's fft routine is using that.*/
158 /* Changed from raw pointer to shared_ptr by glp - Dec 2024 */
159 // FortranComplex64 *data;
160 std::shared_ptr<FortranComplex64[]> data;
161 int nsamp;
162 friend boost::serialization::access;
163 template <class Archive>
164 void save(Archive &ar, const unsigned int version) const {
165 std::vector<FortranComplex64> dv;
166 dv.reserve(this->nsamp);
167 for (auto i = 0; i < nsamp; ++i)
168 dv.push_back(this->data[i]);
169 ar & nsamp;
170 ar & dv;
171 }
172 template <class Archive> void load(Archive &ar, const unsigned int version) {
173 ar &this->nsamp;
174 std::vector<FortranComplex64> dv;
175 dv.reserve(this->nsamp);
176 ar & dv;
177 this->data =
178 std::shared_ptr<FortranComplex64[]>(new FortranComplex64[this->nsamp]);
179 for (auto i = 0; i < this->nsamp; ++i)
180 this->data[i] = dv[i];
181 }
182 BOOST_SERIALIZATION_SPLIT_MEMBER()
183};
184/* This would normally be in the .h file and since I don't think
185 you've used templates worth showing you how it would work. */
186/*
187template <class T> std::vector<std::complex<T> > ComplexArray::CPPData()
188{
189 std::vector<std::complex<T> > result;
190 result.reserve(nsamp);
191 std::size_t i;
192 for(i=0; i<nsamp; ++i)
193 {
194 std::complex<T> z(data[i].real, data[i].imag);
195 result.push_back(z);
196 }
197 return result;
198}
199*/
200
201/*
202template<class T> T* ComplexArray::FortranData()
203{
204 T* result=new T[nsamp];
205 for(std::size_t i=0; i<nsamp; i++)
206 result[i]=data[i];
207 return result;
208}
209*/
210
211template <class T> ComplexArray::ComplexArray(int n, std::vector<T> d) {
212 nsamp = n;
213 if (nsamp > d.size()) {
214 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
215 for (std::size_t i = 0; i < d.size(); i++) {
216 this->data[i].real = d[i];
217 this->data[i].imag = 0.0;
218 }
219 for (std::size_t i = d.size(); i < nsamp; i++) {
220 this->data[i].real = 0.0;
221 this->data[i].imag = 0.0;
222 }
223 } else {
224 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
225 for (std::size_t i = 0; i < nsamp; i++) {
226 this->data[i].real = d[i];
227 this->data[i].imag = 0.0;
228 }
229 }
230}
231template <class T> ComplexArray::ComplexArray(int n, T d) {
232 nsamp = n;
233 data = std::shared_ptr<FortranComplex64[]>(new FortranComplex64[nsamp]);
234 for (std::size_t i = 0; i < nsamp; i++) {
235 this->data[i].real = d;
236 this->data[i].imag = 0.0;
237 }
238}
239/*
240template<class T> ComplexArray ComplexArray::operator +(const vector<T> &other)
241{
242 ComplexArray result(*this);
243 int n;
244 if(nsamp>other.size())
245 n=other.size();
246 else
247 n=nsamp;
248 for(int i=0; i<n; i++)
249 {
250 result.data[i].real=data[i].real+other[i];
251 }
252 return result;
253}
254template<class T> ComplexArray ComplexArray::operator +(const T &other)
255{
256 ComplexArray result(*this);
257 for(int i=0; i<nsamp; i++)
258 {
259 result.data[i].real=data[i].real+other;
260 }
261 return result;
262}
263template<class T> ComplexArray ComplexArray::operator -(const vector<T> &other)
264{
265 ComplexArray result(*this);
266 int n;
267 if(nsamp>other.size())
268 n=other.size();
269 else
270 n=nsamp;
271 for(int i=0; i<n; i++)
272 {
273 result.data[i].real=data[i].real-other[i];
274 }
275 return result;
276}
277template<class T> ComplexArray ComplexArray::operator -(const T &other)
278{
279 ComplexArray result(*this);
280 for(int i=0; i<nsamp; i++)
281 {
282 result.data[i].real=data[i].real-other;
283 }
284 return result;
285}
286template<class T> ComplexArray ComplexArray::operator *(const vector<T> &other)
287{
288 ComplexArray result(*this);
289 int n;
290 if(nsamp>other.size())
291 n=other.size();
292 else
293 n=nsamp;
294 for(int i=0; i<n; i++)
295 {
296 result.data[i].real=data[i].real*other[i];
297 result.data[i].imag=data[i].imag*other[i];
298 }
299 return result;
300}
301template<class T> ComplexArray operator *(const vector<T>& lhs,const
302ComplexArray& rhs)
303{
304 return rhs*lhs;
305}
306template<class T> ComplexArray ComplexArray::operator *(const T &other)
307{
308 ComplexArray result(*this);
309 for(int i=0; i<nsamp; i++)
310 {
311 result.data[i].real=data[i].real*other;
312 result.data[i].imag=data[i].imag*other;
313 }
314 return result;
315}
316template<class T> ComplexArray operator *(const T& lhs,const ComplexArray& rhs)
317{
318 return rhs*lhs;
319}
320*/
321} // namespace mspass::algorithms::deconvolution
322#endif
ComplexArray()
Definition ComplexArray.cc:8
void conj()
Definition ComplexArray.cc:241
Complex64 operator[](int sample)
Definition ComplexArray.cc:117
ComplexArray(std::vector< double > mag, std::vector< double > phase)
ComplexArray(std::vector< Complex32 > &d)
ComplexArray(std::vector< Complex64 > &d)