Waveform
Waveform is a C++ header-only library which represents both the time and the frequency domains of a waveform/signal as a single object, transforming using FFTW automatically when needed.
 All Classes Namespaces Functions Typedefs Friends Groups
Waveform.hpp
1 /*
2  Waveform.hpp
3  Waveform class provides functions frequently used in the RF simulations.
4  Written by Paul Schellin at the Ohio State University, 2012-2013
5  */
6 
7 #ifndef WAVEFORM_HPP
8 #define WAVEFORM_HPP 1
9 #pragma once
10 
11 
12 // Standard libraries
13 #include <iostream>
14 #include <algorithm>
15 #include <functional>
16 #include <iterator>
17 #include <numeric>
18 //#include <fstream>
19 #include <string>
20 #include <cmath>
21 //#include <iomanip>
22 //#include <sstream>
23 
24 
25 // Boost header files
26 
27 #include <boost/operators.hpp>
28 
29 #include <boost/range.hpp>
30 
31 #include <boost/assert.hpp>
32 
33 
34 #define WAVEFORM_USE_CBEGIN_CEND 1
35 
41 namespace PS {
43 
45 
62  public:
64  template <typename Iterator1, typename Iterator2>
65  PlaceholderTransformClass (Iterator1 first1, Iterator1 last1, Iterator2 first2)
66  {
67 
68  }
69 
71  template <typename RandomAccessRange1, typename RandomAccessRange2>
72  PlaceholderTransformClass (RandomAccessRange1& range1, RandomAccessRange2& range2)
73  {
74 
75  }
76 
79  {
80 
81  }
82 
83 
85  void
87  {
88 
89  }
90 
91 
93  void
95  {
96 
97  }
98  };
99 
100 
101 
102 
104 
117  template< /*template<typename...> class*/ typename TimeContainer
118  , /*template<typename...> class*/ typename FreqContainer = TimeContainer
119  , typename TransformT = PlaceholderTransformClass
120  >
121  /*
122  < typename T1
123  , typename T2 = T1
124  , template <typename ...ArgsX1> class Container1 = std::vector
125  , template <typename ...ArgsX2> class Container2 = Container1
126  //, typename ...Args1
127  //, typename ...Args2
128  >
129  */
130 
131  class Waveform {
132  public:
133 
135  typedef typename TimeContainer::value_type TimeT;
136 
138  typedef typename FreqContainer::value_type FreqT;
139 
141  typedef typename std::pair<TimeT,FreqT> value_type;
142 
144  typedef typename TimeContainer::allocator_type TimeAllocT;
145 
147  typedef typename FreqContainer::allocator_type FreqAllocT;
148 
150  typedef typename TimeContainer::iterator TimeIterator;
151 
153  typedef typename FreqContainer::iterator FreqIterator;
154 
155 
157  typedef typename TimeContainer::const_iterator TimeConstIterator;
158 
160  typedef typename FreqContainer::const_iterator FreqConstIterator;
161 
162 
163 
165 
170  enum DomainSpecifier {TimeDomain, FreqDomain, EitherDomain};
171 
172  private:
173 
175  DomainSpecifier validDomain_;
176 
178  TimeContainer timeSeries_;
179 
181  FreqContainer freqSpectrum_;
182 
184  TransformT transform_;
185 
187 
196  Waveform(void) = delete;
197  /*
198  Waveform(void)
199  : validDomain_(EitherDomain)
200  { }
201  */
202 
203  public:
204 
206  Waveform(const std::size_t count)
207  : validDomain_(EitherDomain)
208  , timeSeries_(count)
209  , freqSpectrum_(count)
210  , transform_(timeSeries_, freqSpectrum_)
211  {
212  if (timeSeries_.size()%2)
213  throw std::length_error("Waveform: The array length was not a multiple of 2!");
214  }
215 
216 
218  explicit Waveform(const Waveform& toCopy)
219  : validDomain_(toCopy.validDomain_)
220  , timeSeries_(toCopy.timeSeries_)
221  , freqSpectrum_(toCopy.freqSpectrum_)
222  , transform_(timeSeries_, freqSpectrum_)
223  {
224  if (timeSeries_.size()%2)
225  throw std::length_error("Waveform: The array length was not a multiple of 2!");
226  }
227 
228 
230  explicit Waveform(const TimeContainer& toCopy)
231  : validDomain_(TimeDomain)
232  , timeSeries_(toCopy)
233  , freqSpectrum_(timeSeries_.size()/2 + 1)
234  , transform_(timeSeries_, freqSpectrum_)
235  {
236  if (timeSeries_.size()%2)
237  throw std::length_error("Waveform: The array length was not a multiple of 2!");
238  }
239 
241  explicit Waveform(const FreqContainer& toCopy)
242  : validDomain_(FreqDomain)
243  , timeSeries_((toCopy.size() - 1) * 2)
244  , freqSpectrum_(toCopy)
245  , transform_(timeSeries_, freqSpectrum_)
246  {
247  if (timeSeries_.size()%2)
248  throw std::length_error("Waveform: The array length was not a multiple of 2!");
249  }
250 
252  ~Waveform (void) {}
253 
254 
256 
262  std::size_t
263  GetSize (void) //const
264  { return GetConstTimeSeries().size(); }
265 
266 
268  std::size_t
269  size (void) //const
270  { return GetConstTimeSeries().size(); }
271 
272 
274 
284  const TimeContainer&
286  { ValidateDomain(EitherDomain); return timeSeries_; }
287 
288 
290 
299  const FreqContainer&
301  { ValidateDomain(EitherDomain); return freqSpectrum_; }
302 
303 
305 
310  TimeContainer&
312  { ValidateDomain(TimeDomain); return timeSeries_; }
313 
314 
316 
321  FreqContainer&
323  { ValidateDomain(FreqDomain); return freqSpectrum_; }
324 
325 
326 
327 
328  //
329  //
330  // Iterator Access Functions
331  //
332  //
333 
334  /*
335  Because of the nature of the Waveform class, I'm most likely
336  going to be removing the iterator functions from the library.
337 
338  The iterators will still be available from the containers
339  themselves, of course, but because there is no obvious way
340  to have just a "begin()" or "end()" function instead of
341  "beginTime()" and "beginFreq()", and with there being no
342  impact on performance either way, there is no good reason to
343  keep the functions.
344 
345  Issues with not being able to mark "const" a function at the
346  same time as checking the domain array validity (though there
347  is a way to do it -- check in the function itself and throw an
348  exception if the domain is not valid, but it's error prone and
349  ugly) makes it difficult to consider this portion of the library
350  intuitive or well-formed.
351 
352  The only reason iterators would be very useful is if they
353  provided validation checks as well, but at the moment that
354  portion of the library is not yet completed.
355 
356 
357  [ Iterator access functions have been removed ]
358  */
359 
360  //______________________________________________________________________
362 
449  int
450  ValidateDomain (const DomainSpecifier toValidate)
451  {
452  if (toValidate == validDomain_ || validDomain_ == EitherDomain) {
453  // There aren't any transforms to be performed
454  }
455  else if (toValidate == TimeDomain) {
456  transform_.exec_inverse_transform();
457  }
458  else if (toValidate == FreqDomain) {
459  transform_.exec_transform();
460  }
461  else if (toValidate == EitherDomain) {
462  if (validDomain_ == TimeDomain) {
463  transform_.exec_transform();
464  } else // if (validDomain_ == FreqDomain)
465  {
466  transform_.exec_inverse_transform();
467  }
468  }
469 
470  validDomain_ = toValidate;
471  return 0;
472  }
473 
474 
475 
477 
500  friend void swap(Waveform& first, Waveform& second)
501  {
502  using std::swap;
503 
504  swap(first.validDomain_, second.validDomain_);
505 
506  swap(first.timeSeries_, second.timeSeries_);
507 
508  swap(first.freqSpectrum_, second.freqSpectrum_);
509 
510  swap(first.transform_, second.transform_);
511  }
512 
513 
515 
535  //template <typename WaveformT>
536  Waveform&
537  //operator= (const Waveform& rhs)
538  //operator= (WaveformT rhs)
540  {
541  swap(*this, rhs);
542 
543  return *this;
544  }
545 
546 
548 
558  : Waveform()
559  {
560  swap(*this, rhs);
561  }
562 
563  };
564 
565 
566  template <typename ...Args1, typename ...Args2>
567  inline bool
568  operator==(const Waveform<Args1...>& lhs, const Waveform<Args2...>& rhs)
569  {
570  // Could probably just see what the valid domain is and compare only that.
571  // Perhaps in a later version.
572 
573  // At the very least it makes sense to check the valid domain first, because
574  // the valid domain doesn't require a transform.
575  // However, that would require either this function to be a friend function or
576  // for the validDomain_ variable to be made public.
577  return lhs.GetTimeSeries() == rhs.GetTimeSeries() && lhs.GetFreqSpectrum() == rhs.GetFreqSpectrum();
578  }
579 
580  template <typename ...Args1, typename ...Args2>
581  inline bool
582  operator!=(const Waveform<Args1...>& lhs, const Waveform<Args2...>& rhs)
583  {
584  return !(lhs == rhs);
585  }
586 
587 
588 
589 } // End of namespace PS
590 
593 #endif
Waveform & operator=(Waveform rhs)
Copy-assignment operator.
Definition: Waveform.hpp:539
friend void swap(Waveform &first, Waveform &second)
Swaps two values without throwing.
Definition: Waveform.hpp:500
~Waveform(void)
Default destructor.
Definition: Waveform.hpp:252
PlaceholderTransformClass(RandomAccessRange1 &range1, RandomAccessRange2 &range2)
Boost::range constructor (Random Access Range)
Definition: Waveform.hpp:72
FreqContainer & GetFreqSpectrum(void)
Returns mutable reference to the frequency domain container.
Definition: Waveform.hpp:322
~PlaceholderTransformClass(void)
Destructor.
Definition: Waveform.hpp:78
std::size_t size(void)
Returns the size of the time domain container.
Definition: Waveform.hpp:269
TimeContainer::allocator_type TimeAllocT
The allocator type of the time domain container.
Definition: Waveform.hpp:144
TimeContainer::const_iterator TimeConstIterator
The const iterator type of the time domain container.
Definition: Waveform.hpp:157
FreqContainer::iterator FreqIterator
The iterator type of the frequency domain container.
Definition: Waveform.hpp:153
Waveform(const TimeContainer &toCopy)
Time domain copy constructor.
Definition: Waveform.hpp:230
void exec_inverse_transform(void)
Execute the inverse/reverse transform.
Definition: Waveform.hpp:94
std::size_t GetSize(void)
Returns the size of the time domain container.
Definition: Waveform.hpp:263
Waveform(Waveform &&rhs)
Move constructor (C++11)
Definition: Waveform.hpp:557
PlaceholderTransformClass: Defines the minimum interface for a transform class.
Definition: Waveform.hpp:61
TimeContainer::value_type TimeT
The type of the time domain.
Definition: Waveform.hpp:135
Waveform class: Transform as-needed between time and freq domains.
Definition: Waveform.hpp:131
FreqContainer::value_type FreqT
The type of the frequency domain.
Definition: Waveform.hpp:138
FreqContainer::const_iterator FreqConstIterator
The const iterator type of the frequency domain container.
Definition: Waveform.hpp:160
Waveform(const Waveform &toCopy)
Copy constructor.
Definition: Waveform.hpp:218
std::pair< TimeT, FreqT > value_type
The "type" of the Waveform, inspired by std::map.
Definition: Waveform.hpp:141
int ValidateDomain(const DomainSpecifier toValidate)
Validate and ensure that the specified domain is up-to-date.
Definition: Waveform.hpp:450
PlaceholderTransformClass(Iterator1 first1, Iterator1 last1, Iterator2 first2)
Iterator bounds constructor.
Definition: Waveform.hpp:65
FreqContainer::allocator_type FreqAllocT
The allocator type of the frequency domain container.
Definition: Waveform.hpp:147
Waveform(const std::size_t count)
Fill constructor.
Definition: Waveform.hpp:206
const FreqContainer & GetConstFreqSpectrum(void)
Returns constant reference to the frequency domain container.
Definition: Waveform.hpp:300
void exec_transform(void)
Execute the forward transform.
Definition: Waveform.hpp:86
Waveform(const FreqContainer &toCopy)
Frequency domain copy constructor.
Definition: Waveform.hpp:241
TimeContainer::iterator TimeIterator
The iterator type of the time domain container.
Definition: Waveform.hpp:150
TimeContainer & GetTimeSeries(void)
Returns mutable reference to the time domain container.
Definition: Waveform.hpp:311
const TimeContainer & GetConstTimeSeries(void)
Returns constant reference to the time domain container.
Definition: Waveform.hpp:285