LCOV - code coverage report
Current view: top level - include/sigproc - autocorrelation.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 93.8 % 16 15
Test Date: 2026-08-30 22:23:37 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /** \file autocorrelation.hpp
       2              :  * \brief Tools for working with autocorrelations
       3              :  *
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  * \ingroup signal_processing_files
       7              :  *
       8              :  */
       9              : 
      10              : //***********************************************************************//
      11              : // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
      12              : //
      13              : // This file is part of mxlib.
      14              : //
      15              : // mxlib is free software: you can redistribute it and/or modify
      16              : // it under the terms of the GNU General Public License as published by
      17              : // the Free Software Foundation, either version 3 of the License, or
      18              : // (at your option) any later version.
      19              : //
      20              : // mxlib is distributed in the hope that it will be useful,
      21              : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      22              : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      23              : // GNU General Public License for more details.
      24              : //
      25              : // You should have received a copy of the GNU General Public License
      26              : // along with mxlib.  If not, see <http://www.gnu.org/licenses/>.
      27              : //***********************************************************************//
      28              : 
      29              : #ifndef autocorrelation_hpp
      30              : #define autocorrelation_hpp
      31              : 
      32              : #include "../math/ft/fftT.hpp"
      33              : 
      34              : namespace mx
      35              : {
      36              : 
      37              : namespace sigproc
      38              : {
      39              : 
      40              : /// Calculate the autocorrelation of a time-series
      41              : /**
      42              :  * \tparam T is the real type of the data and autocorrelation.
      43              :  *
      44              :  * \ingroup signal_processing
      45              :  */
      46              : template <typename T>
      47              : void autocorrelation(
      48              :     T *ac,      ///< [out] is the pre-allocated array of length Nac which will contain the autocorrelation on return
      49              :     size_t Nac, ///< [in] is the length of ac
      50              :     T *sig,     ///< [in] is the input time-series (signal)
      51              :     size_t Nsig ///< [in] is the length of the input time-series
      52              : )
      53              : {
      54              : 
      55              :     #pragma omp parallel for
      56              :     for( int i = 0; i < Nac; ++i )
      57              :     {
      58              :         ac[i] = 0;
      59              :         for( int j = 0; j < Nsig - i; ++j )
      60              :         {
      61              :             ac[i] += sig[j] * sig[j + i];
      62              :         }
      63              :     }
      64              : 
      65              :     T norm = ac[0];
      66              :     for( int i = 0; i < Nac; ++i )
      67              :     {
      68              :         ac[i] /= norm;
      69              :     }
      70              : }
      71              : 
      72              : /// Calculate the autocorrelation of a time-series
      73              : /**
      74              :  * \tparam T is the real type of the data and autocorrelation.
      75              :  *
      76              :  * \todo this should probably re-allocate if ac.size() != sig.size(), or at least <
      77              :  *
      78              :  * \ingroup signal_processing
      79              :  */
      80              : template <typename T>
      81              : void autocorrelation( std::vector<T> &ac, ///< [out] will contain the autocorrelation on return.  If ac.size()==0 then
      82              :                                           ///< it is resized to sig.size().
      83              :                       std::vector<T> &sig ///< [in] is the input time-series (signal)
      84              : )
      85              : {
      86              :     if( ac.size() == 0 )
      87              :     {
      88              :         ac.resize( sig.size() );
      89              :     }
      90              : 
      91              :     autocorrelation( ac.data(), ac.size(), sig.data(), sig.size() );
      92              : }
      93              : 
      94              : /// Functor for calculating the autocorrelation given a PSD
      95              : /** Stores the fftT object and related working memory so that
      96              :  * repeated calls do not re-allocate or re-plan the FFT.
      97              :  *
      98              :  * \tparam T is the real type of the PSD and resultig A.C.
      99              :  *
     100              :  * \ingroup signal_processing
     101              :  */
     102              : template <typename T>
     103              : struct autocorrelationFromPSD
     104              : {
     105              :     std::vector<std::complex<T>> fftOut;
     106              :     std::vector<std::complex<T>> fftIn;
     107              : 
     108              :     math::ft::fftT<std::complex<T>, std::complex<T>, 1, 0> fft;
     109              : 
     110              :     /// Calculate the A.C. as the inverse FFT of the PSD
     111              :     /** This calculates the circular autocorrelation from the PSD.
     112              :      *
     113              :      */
     114              :     void
     115          121 :     operator()( T *ac, ///<  [out] pre-allocated array, on output contains the first Nac points of the autocorrelation
     116              :                 size_t Nac, ///< [in] the allocated size of ac.
     117              :                 T *psd,     ///< [in] the 2-sided FFT storage order PSD
     118              :                 size_t Npsd ///< [in] the number of points in the PSD
     119              :     )
     120              :     {
     121          121 :         fft.plan( Npsd, math::ft::dir::forward );
     122              : 
     123          121 :         fftOut.resize( Npsd );
     124          121 :         fftIn.resize( Npsd );
     125              : 
     126        15609 :         for( size_t i = 0; i < Npsd; ++i )
     127        15488 :             fftIn[i] = psd[i];
     128              : 
     129          121 :         fft( fftOut.data(), fftIn.data() );
     130              : 
     131          121 :         T norm = fftOut[0].real();
     132        15609 :         for( size_t i = 0; i < Npsd && i < Nac; ++i )
     133        15488 :             ac[i] = fftOut[i].real() / norm;
     134          121 :     }
     135              : 
     136              :     /// Calculate the A.C. as the inverse FFT of the PSD
     137              :     /** This calculates the circular autocorrelation from the PSD.
     138              :      *
     139              :      */
     140          121 :     void operator()( std::vector<T> &ac, ///< [out] On output contains the autocorrelation.  If ac.size()==0, it is
     141              :                                          ///< allocated to psd.size().
     142              :                      std::vector<T> &psd ///<  [in] the 2-sided FFT storage order PSD
     143              :     )
     144              :     {
     145          121 :         if( ac.size() == 0 )
     146            0 :             ac.resize( psd.size() );
     147          121 :         operator()( ac.data(), ac.size(), psd.data(), psd.size() );
     148          121 :     }
     149              : };
     150              : 
     151              : } // namespace sigproc
     152              : } // namespace mx
     153              : 
     154              : #endif // autocorrelation_hpp
        

Generated by: LCOV version 2.0-1