PCL
FFT2D.h
Go to the documentation of this file.
1 // ____ ______ __
2 // / __ \ / ____// /
3 // / /_/ // / / /
4 // / ____// /___ / /___ PixInsight Class Library
5 // /_/ \____//_____/ PCL 2.8.5
6 // ----------------------------------------------------------------------------
7 // pcl/FFT2D.h - Released 2024-12-28T16:53:48Z
8 // ----------------------------------------------------------------------------
9 // This file is part of the PixInsight Class Library (PCL).
10 // PCL is a multiplatform C++ framework for development of PixInsight modules.
11 //
12 // Copyright (c) 2003-2024 Pleiades Astrophoto S.L. All Rights Reserved.
13 //
14 // Redistribution and use in both source and binary forms, with or without
15 // modification, is permitted provided that the following conditions are met:
16 //
17 // 1. All redistributions of source code must retain the above copyright
18 // notice, this list of conditions and the following disclaimer.
19 //
20 // 2. All redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the names "PixInsight" and "Pleiades Astrophoto", nor the names
25 // of their contributors, may be used to endorse or promote products derived
26 // from this software without specific prior written permission. For written
27 // permission, please contact info@pixinsight.com.
28 //
29 // 4. All products derived from this software, in any form whatsoever, must
30 // reproduce the following acknowledgment in the end-user documentation
31 // and/or other materials provided with the product:
32 //
33 // "This product is based on software from the PixInsight project, developed
34 // by Pleiades Astrophoto and its contributors (https://pixinsight.com/)."
35 //
36 // Alternatively, if that is where third-party acknowledgments normally
37 // appear, this acknowledgment must be reproduced in the product itself.
38 //
39 // THIS SOFTWARE IS PROVIDED BY PLEIADES ASTROPHOTO AND ITS CONTRIBUTORS
40 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
41 // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PLEIADES ASTROPHOTO OR ITS
43 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
44 // EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, BUSINESS
45 // INTERRUPTION; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; AND LOSS OF USE,
46 // DATA OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
47 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
49 // POSSIBILITY OF SUCH DAMAGE.
50 // ----------------------------------------------------------------------------
51 
52 #ifndef __PCL_FFT2D_h
53 #define __PCL_FFT2D_h
54 
56 
57 #include <pcl/Defs.h>
58 
59 #include <pcl/FFT1D.h>
60 #include <pcl/Matrix.h>
61 #include <pcl/ParallelProcess.h>
62 #include <pcl/StatusMonitor.h>
63 
64 namespace pcl
65 {
66 
67 // ----------------------------------------------------------------------------
68 
69 class FFT2DBase
70 {
71 protected:
72 
73  static void Transform( int, int, fcomplex*, const fcomplex*, int, StatusMonitor*, bool, int );
74  static void Transform( int, int, dcomplex*, const dcomplex*, int, StatusMonitor*, bool, int );
75  static void Transform( int, int, fcomplex*, const float*, StatusMonitor*, bool, int );
76  static void Transform( int, int, dcomplex*, const double*, StatusMonitor*, bool, int );
77  static void InverseTransform( int, int, float*, const fcomplex*, StatusMonitor*, bool, int );
78  static void InverseTransform( int, int, double*, const dcomplex*, StatusMonitor*, bool, int );
79 };
80 
81 // ----------------------------------------------------------------------------
82 
92 template <typename T>
93 class PCL_CLASS AbstractFFT2D : public FFT2DBase, public ParallelProcess
94 {
95 public:
96 
100  using scalar = T;
101 
106 
111 
116 
121 
126 
131 
136  AbstractFFT2D( int rows, int cols )
137  : m_rows( rows )
138  , m_cols( cols )
139  {
140  }
141 
149  AbstractFFT2D( int rows, int cols, StatusMonitor& monitor )
150  : m_rows( rows )
151  , m_cols( cols )
152  , m_monitor( &monitor )
153  {
154  }
155 
160  ~AbstractFFT2D() override
161  {
162  Release();
163  }
164 
170  int Rows() const
171  {
172  return m_rows;
173  }
174 
180  int Cols() const
181  {
182  return m_cols;
183  }
184 
190  int NumberOfElements() const
191  {
192  return m_rows*m_cols;
193  }
194 
206  transform DFT() const
207  {
208  return m_dft;
209  }
210 
223  {
224  return m_dft;
225  }
226 
231  virtual void Release()
232  {
233  m_dft = transform();
234  }
235 
236 private:
237 
238  // Transform dimensions
239  int m_rows;
240  int m_cols;
241 
242 protected:
243 
244  transform m_dft; // DFT of complex or real data
245  StatusMonitor* m_monitor = nullptr;
246 };
247 
248 // ----------------------------------------------------------------------------
249 
250 #define m_dft this->m_dft
251 #define m_rows this->Rows()
252 #define m_cols this->Cols()
253 #define m_monitor this->m_monitor
254 #define m_parallel this->m_parallel
255 #define m_maxProcessors this->m_maxProcessors
256 
257 // ----------------------------------------------------------------------------
258 
271 template <typename T>
272 class PCL_CLASS GenericFFT2D : public AbstractFFT2D<T>
273 {
274 public:
275 
280 
284  using scalar = typename base::scalar;
285 
289  using complex = typename base::complex;
290 
294  using vector = typename base::vector;
295 
300 
304  using matrix = typename base::matrix;
305 
310 
314  using transform = typename base::transform;
315 
331  GenericFFT2D( int rows, int cols )
332  : base( rows, cols )
333  {
334  }
335 
345  GenericFFT2D( int rows, int cols, StatusMonitor& status )
346  : base( rows, cols, status )
347  {
348  }
349 
353  ~GenericFFT2D() override
354  {
355  }
356 
369  {
370  if ( m_dft.IsEmpty() )
371  m_dft = transform( m_rows, m_cols );
372  this->Transform( m_rows, m_cols, *m_dft, x, PCL_FFT_FORWARD, m_monitor, m_parallel, m_maxProcessors );
373  return *this;
374  }
375 
391  {
392  if ( m_dft.IsEmpty() )
393  throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." );
394  this->Transform( m_rows, m_cols, y, *m_dft, PCL_FFT_BACKWARD, m_monitor, m_parallel, m_maxProcessors );
395  return *this;
396  }
397 
408  {
409  PCL_PRECONDITION( x.Rows() == m_rows )
410  PCL_PRECONDITION( x.Cols() == m_cols )
411  if ( x.Rows() != m_rows || x.Cols() != m_cols )
412  throw Error( "Invalid FFT input matrix dimensions." );
413  return operator <<( *x );
414  }
415 
429  {
430  PCL_PRECONDITION( y.Rows() == m_rows )
431  PCL_PRECONDITION( y.Cols() == m_cols )
432  if ( y.Rows() != m_rows || y.Cols() != m_cols )
433  throw Error( "Invalid FFT output matrix dimensions." );
434  return operator >>( *y );
435  }
436 
469  GenericFFT2D& operator ()( complex* y, const complex* x, int dir = PCL_FFT_FORWARD ) const
470  {
471  this->Transform( m_rows, m_cols, y, x, dir, m_monitor, m_parallel, m_maxProcessors );
472  return const_cast<GenericFFT2D&>( *this );
473  }
474 
482  static int OptimizedLength( int n )
483  {
484  return GenericFFT<T>::OptimizedLength( n );
485  }
486 };
487 
488 // ----------------------------------------------------------------------------
489 
504 template <typename T>
505 class PCL_CLASS GenericRealFFT2D : public AbstractFFT2D<T>
506 {
507 public:
508 
513 
517  using scalar = typename base::scalar;
518 
522  using complex = typename base::complex;
523 
527  using vector = typename base::vector;
528 
533 
537  using matrix = typename base::matrix;
538 
543 
547  using transform = typename base::transform;
548 
568  GenericRealFFT2D( int rows, int cols )
569  : base( rows, cols )
570  {
571  }
572 
582  GenericRealFFT2D( int rows, int cols, StatusMonitor& status )
583  : base( rows, cols, status )
584  {
585  }
586 
590  ~GenericRealFFT2D() override
591  {
592  }
593 
606  {
607  if ( m_dft.IsEmpty() )
608  m_dft = transform( m_rows, m_cols/2 + 1 );
609  this->Transform( m_rows, m_cols, *m_dft, x, m_monitor, m_parallel, m_maxProcessors );
610  return *this;
611  }
612 
628  {
629  if ( m_dft.IsEmpty() )
630  throw Error( "Invalid out-of-place inverse FFT: No FFT has been performed." );
631  this->InverseTransform( m_rows, m_cols, y, *m_dft, m_monitor, m_parallel, m_maxProcessors );
632  return *this;
633  }
634 
645  {
646  PCL_PRECONDITION( x.Rows() == m_rows )
647  PCL_PRECONDITION( x.Cols() == m_cols )
648  if ( x.Rows() != m_rows || x.Cols() != m_cols )
649  throw Error( "Invalid FFT input matrix dimensions." );
650  return operator <<( *x );
651  }
652 
666  {
667  PCL_PRECONDITION( y.Rows() == m_rows )
668  PCL_PRECONDITION( y.Cols() == m_cols )
669  if ( y.Rows() != m_rows || y.Cols() != m_cols )
670  throw Error( "Invalid FFT output matrix dimensions." );
671  return operator >>( *y );
672  }
673 
699  GenericRealFFT2D& operator()( complex* y, const scalar* x ) const
700  {
701  this->Transform( m_rows, m_cols, y, x, m_monitor, m_parallel, m_maxProcessors );
702  return const_cast<GenericRealFFT2D&>( *this );
703  }
704 
730  GenericRealFFT2D& operator()( scalar* y, const complex* x ) const
731  {
732  this->InverseTransform( m_rows, m_cols, y, x, m_monitor, m_parallel, m_maxProcessors );
733  return const_cast<GenericRealFFT2D&>( *this );
734  }
735 
743  static int OptimizedLength( int n )
744  {
745  return GenericFFT<T>::OptimizedLength( n );
746  }
747 };
748 
749 // ----------------------------------------------------------------------------
750 
751 #undef m_dft
752 #undef m_rows
753 #undef m_cols
754 #undef m_monitor
755 #undef m_parallel
756 #undef m_maxProcessors
757 
758 // ----------------------------------------------------------------------------
759 
764 #ifndef __PCL_NO_FFT2D_INSTANTIATE
765 
773 using FFFT2D = GenericFFT2D<float>;
774 
782 using DFFT2D = GenericFFT2D<double>;
783 
791 using FRealFFT2D = GenericRealFFT2D<float>;
792 
800 using DRealFFT2D = GenericRealFFT2D<double>;
801 
810 using FFT2D = FFFT2D;
811 
820 using RealFFT2D = FRealFFT2D;
821 
822 #endif // __PCL_NO_FFT2D_INSTANTIATE
823 
824 // ----------------------------------------------------------------------------
825 
826 } // pcl
827 
828 #endif // __PCL_FFT2D_h
829 
830 // ----------------------------------------------------------------------------
831 // EOF pcl/FFT2D.h - Released 2024-12-28T16:53:48Z
Abstract base class of all two-dimensional fast Fourier transform classes.
Definition: FFT2D.h:94
int Cols() const
Definition: FFT2D.h:180
int NumberOfElements() const
Definition: FFT2D.h:190
int Rows() const
Definition: FFT2D.h:170
transform & DFT()
Definition: FFT2D.h:222
AbstractFFT2D(int rows, int cols, StatusMonitor &monitor)
Definition: FFT2D.h:149
virtual void Release()
Definition: FFT2D.h:231
transform DFT() const
Definition: FFT2D.h:206
~AbstractFFT2D() override
Definition: FFT2D.h:160
AbstractFFT2D(int rows, int cols)
Definition: FFT2D.h:136
Generic complex number.
Definition: Complex.h:84
Fast Fourier transform of 64-bit floating point complex data.
Fast Fourier transform of 64-bit floating point real data.
A simple exception with an associated error message.
Definition: Exception.h:239
Fast Fourier transform of 32-bit floating point complex data.
Fast Fourier transform of 32-bit floating point complex data.
Fast Fourier transform of 32-bit floating point real data.
Generic two-dimensional fast Fourier transform of complex data.
Definition: FFT2D.h:273
~GenericFFT2D() override
Definition: FFT2D.h:353
GenericFFT2D(int rows, int cols, StatusMonitor &status)
Definition: FFT2D.h:345
GenericFFT2D(int rows, int cols)
Definition: FFT2D.h:331
static int OptimizedLength(int n)
Definition: FFT2D.h:482
static int OptimizedLength(int n)
Definition: FFT1D.h:486
Generic dynamic matrix of arbitrary dimensions.
Definition: Matrix.h:123
int Cols() const noexcept
Definition: Matrix.h:987
int Rows() const noexcept
Definition: Matrix.h:978
Generic two-dimensional fast Fourier transform of real data.
Definition: FFT2D.h:506
GenericRealFFT2D & operator()(complex *y, const scalar *x) const
Definition: FFT2D.h:699
~GenericRealFFT2D() override
Definition: FFT2D.h:590
GenericRealFFT2D(int rows, int cols)
Definition: FFT2D.h:568
static int OptimizedLength(int n)
Definition: FFT2D.h:743
GenericRealFFT2D(int rows, int cols, StatusMonitor &status)
Definition: FFT2D.h:582
GenericRealFFT2D & operator()(scalar *y, const complex *x) const
Definition: FFT2D.h:730
A process using multiple concurrent execution threads.
Fast Fourier transform of 32-bit floating point real data.
An asynchronous status monitoring system.
A complex number whose components are 64-bit floating point real numbers.
A complex number whose components are 32-bit floating point real numbers.
Array< T, A > & operator<<(Array< T, A > &x, const V &v)
Definition: Array.h:2313
Console & operator>>(Console &o, char &c)
Definition: Console.h:807
#define PCL_FFT_BACKWARD
Indicates an inverse Fourier transform.
Definition: FFT1D.h:116
#define PCL_FFT_FORWARD
Indicates a Fourier transform.
Definition: FFT1D.h:109
PCL root namespace.
Definition: AbstractImage.h:77