LCOV - code coverage report
Current view: top level - include/wfp - imagingArray.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 0.0 % 82 0
Test Date: 2026-08-30 22:23:37 Functions: 0.0 % 21 0

            Line data    Source code
       1              : /** \file imagingArray.hpp
       2              :  * \brief Declares and defines a class for managing images
       3              :  * \ingroup imaging
       4              :  * \author Jared R. Males (jaredmales@gmail.com)
       5              :  *
       6              :  */
       7              : 
       8              : #ifndef imagingArray_hpp
       9              : #define imagingArray_hpp
      10              : 
      11              : #pragma GCC system_header
      12              : #include <Eigen/Dense>
      13              : 
      14              : #include "../math/templateBLAS.hpp"
      15              : #include "../math/ft/fftT.hpp"
      16              : 
      17              : namespace mx
      18              : {
      19              : namespace wfp
      20              : {
      21              : 
      22              : template <typename Scalar>
      23              : struct fftwAllocator
      24              : {
      25            0 :     Scalar *alloc( size_t sz )
      26              :     {
      27            0 :         return (Scalar *)::fftw_malloc( sz * sizeof( Scalar ) );
      28              :     }
      29              : 
      30            0 :     void free( Scalar *ptr )
      31              :     {
      32            0 :         fftw_free( ptr );
      33            0 :     }
      34              : };
      35              : 
      36              : /// Test whether a type is an imagingArray by testing whether it has a typedef of "is_imagingArray"
      37              : /** Used for compile-time determination of type
      38              :  * Example usage:
      39              :  * \code
      40              :  * bool is_eC = is_imagingArray<eigenCube<float> >; //Evaluates to true
      41              :  * bool is_not_eC = is_imagingArray<float>; //Evaluates to false
      42              :  * \endcode
      43              :  */
      44              : // This was taken directly from the example at http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
      45              : template <typename T>
      46              : struct is_imagingArray
      47              : {
      48              :     // Types "yes" and "no" are guaranteed to have different sizes,
      49              :     // specifically sizeof(yes) == 1 and sizeof(no) == 2.
      50              :     typedef char yes[1];
      51              :     typedef char no[2];
      52              : 
      53              :     template <typename imageT>
      54              :     static yes &test( typename imageT::imagingArrayT * );
      55              : 
      56              :     template <typename>
      57              :     static no &test( ... );
      58              : 
      59              :     // If the "sizeof" of the result of calling test<T>(0) would be equal to sizeof(yes),
      60              :     // the first overload worked and T has a nested type named "is_mmatrix".
      61              :     static const bool value = sizeof( test<T>( 0 ) ) == sizeof( yes );
      62              : };
      63              : 
      64              : template <typename imageT, typename typeT, bool isScalar = is_imagingArray<typeT>::value>
      65              : struct imagingArrayInplaceProduct
      66              : {
      67              :     imagingArrayInplaceProduct()
      68              :     {
      69              :         static_assert( is_imagingArray<imageT>::value,
      70              :                        "imagingArrayInplaceProduct template parameter 1 must be an imagingArray type" );
      71              :     }
      72              : 
      73              :     void operator()( imageT &im, typeT &alpha )
      74              :     {
      75              :         math::scal<typename imageT::Scalar>( im.cols() * im.rows(), (typeT)alpha, im.data(), 1 );
      76              :     }
      77              : };
      78              : 
      79              : template <typename imageT, typename typeT>
      80              : struct imagingArrayInplaceProduct<imageT, typeT, true>
      81              : {
      82            0 :     imagingArrayInplaceProduct()
      83              :     {
      84              :         static_assert( is_imagingArray<imageT>::value,
      85              :                        "imagingArrayInplaceProduct template parameter 1 must be an imagingArray type" );
      86            0 :     }
      87              : 
      88            0 :     void operator()( imageT &im, typeT &alpha )
      89              :     {
      90              :         typedef typename imageT::Scalar scalarT;
      91              :         // hadp<scalarT>(im.cols()*im.rows(), alpha.data(), im.data());
      92              : 
      93            0 :         Eigen::Map<Eigen::Array<scalarT, -1, -1>> eigY( alpha.data(), alpha.cols(), alpha.rows() );
      94            0 :         Eigen::Map<Eigen::Array<scalarT, -1, -1>> eigX( im.data(), im.cols(), im.rows() );
      95              : 
      96            0 :         eigX *= eigY;
      97            0 :     }
      98              : };
      99              : 
     100              : template <typename imageT, typename typeT, bool isScalar = is_imagingArray<typeT>::value>
     101              : struct imagingArrayInplaceDivision
     102              : {
     103              :     imagingArrayInplaceDivision()
     104              :     {
     105              :         static_assert( is_imagingArray<imageT>::value,
     106              :                        "imagingArrayInplaceDivision template parameter 1 must be an imagingArray type" );
     107              :     }
     108              : 
     109              :     void operator()( imageT im, typeT alpha )
     110              :     {
     111              :         math::scal<typename imageT::Scalar>( im.cols() * im.rows(), ( (typeT)( 1 ) ) / alpha, im.data(), 1 );
     112              :     }
     113              : };
     114              : 
     115              : template <typename imageT, typename typeT>
     116              : struct imagingArrayInplaceDivision<imageT, typeT, true>
     117              : {
     118              :     imagingArrayInplaceDivision()
     119              :     {
     120              :         static_assert( is_imagingArray<imageT>::value,
     121              :                        "imagingArrayInplaceDivision template parameter 1 must be an imagingArray type" );
     122              :     }
     123              : 
     124              :     void operator()( imageT im, typeT alpha )
     125              :     {
     126              :         typedef typename imageT::Scalar scalarT;
     127              :         math::hadd<scalarT>( im.cols() * im.rows(), (scalarT)1.0, alpha.data(), 1, im.data(), 1 );
     128              :     }
     129              : };
     130              : 
     131              : template <typename imageT, typename typeT, bool isScalar = is_imagingArray<typeT>::value>
     132              : struct imagingArrayInplaceAdd
     133              : {
     134              :     imagingArrayInplaceAdd()
     135              :     {
     136              :         static_assert( is_imagingArray<imageT>::value,
     137              :                        "imagingArrayInplaceAdd template parameter 1 must be an imagingArray type" );
     138              :     }
     139              : 
     140              :     void operator()( imageT &im, typeT &alpha )
     141              :     {
     142              :         typedef typename imageT::Scalar scalarT;
     143              :         Eigen::Map<Eigen::Array<scalarT, -1, -1>> eigX( im.data(), im.cols(), im.rows() );
     144              :         eigX += alpha;
     145              :     }
     146              : };
     147              : 
     148              : template <typename imageT, typename typeT>
     149              : struct imagingArrayInplaceAdd<imageT, typeT, true>
     150              : {
     151              :     imagingArrayInplaceAdd()
     152              :     {
     153              :         static_assert( is_imagingArray<imageT>::value,
     154              :                        "imagingArrayInplaceAdd template parameter 1 must be an imagingArray type" );
     155              :     }
     156              : 
     157              :     void operator()( imageT &im, typeT &alpha )
     158              :     {
     159              :         typedef typename imageT::Scalar scalarT;
     160              :         // hadp<scalarT>(im.cols()*im.rows(), alpha.data(), im.data());
     161              : 
     162              :         Eigen::Map<Eigen::Array<scalarT, -1, -1>> eigY( alpha.data(), alpha.cols(), alpha.rows() );
     163              :         Eigen::Map<Eigen::Array<scalarT, -1, -1>> eigX( im.data(), im.cols(), im.rows() );
     164              : 
     165              :         eigX += eigY;
     166              :     }
     167              : };
     168              : 
     169              : template <typename _Scalar, class _allocatorT, int cudaGPU>
     170              : class imagingArray;
     171              : 
     172              : template <typename _Scalar, class _allocatorT>
     173              : class imagingArray<_Scalar, _allocatorT, 0>
     174              : {
     175              :   public:
     176              :     typedef bool imagingArrayT;
     177              :     typedef _Scalar Scalar;
     178              :     typedef _allocatorT allocatorT;
     179              : 
     180              :   protected:
     181              :     allocatorT allocator;
     182              : 
     183              :     Scalar *_data;
     184              : 
     185              :     bool _owner;
     186              : 
     187              :     int _cols;
     188              :     int _rows;
     189              : 
     190              :   public:
     191            0 :     imagingArray()
     192              :     {
     193            0 :         _data = 0;
     194            0 :         _owner = false;
     195            0 :         _cols = 0;
     196            0 :         _rows = 0;
     197            0 :     }
     198              : 
     199            0 :     imagingArray( int x, int y )
     200              :     {
     201            0 :         _data = 0;
     202            0 :         _owner = false;
     203            0 :         _cols = 0;
     204            0 :         _rows = 0;
     205              : 
     206            0 :         resize( x, y );
     207            0 :     }
     208              : 
     209              :     template <typename eigenT>
     210              :     explicit imagingArray( eigenT &im )
     211              :     {
     212              :         _data = im.data();
     213              :         _owner = false;
     214              :         _cols = im.cols();
     215              :         _rows = im.rows();
     216              :     }
     217              : 
     218            0 :     ~imagingArray()
     219              :     {
     220            0 :         free();
     221            0 :     }
     222              : 
     223            0 :     void resize( int szx, int szy )
     224              :     {
     225            0 :         if( szx == _cols && szy == _rows && _owner )
     226            0 :             return;
     227              : 
     228            0 :         free();
     229              : 
     230            0 :         _cols = szx;
     231            0 :         _rows = szy;
     232              : 
     233            0 :         _data = allocator.alloc( _cols * _rows );
     234            0 :         _owner = true;
     235              :     }
     236              : 
     237            0 :     void free()
     238              :     {
     239            0 :         if( _data && _owner )
     240              :         {
     241            0 :             allocator.free( _data );
     242            0 :             _data = 0;
     243            0 :             _cols = 0;
     244            0 :             _rows = 0;
     245              :         }
     246            0 :     }
     247              : 
     248            0 :     int cols() const
     249              :     {
     250            0 :         return _cols;
     251              :     }
     252              : 
     253            0 :     int rows() const
     254              :     {
     255            0 :         return _rows;
     256              :     }
     257              : 
     258            0 :     Scalar *data()
     259              :     {
     260            0 :         return _data;
     261              :     }
     262              : 
     263            0 :     Scalar *data() const
     264              :     {
     265            0 :         return _data;
     266              :     }
     267              : 
     268            0 :     Scalar operator()( int x, int y ) const
     269              :     {
     270            0 :         return _data[x + y * _cols];
     271              :     }
     272              : 
     273            0 :     Scalar &operator()( int x, int y )
     274              :     {
     275            0 :         return _data[x + y * _cols];
     276              :     }
     277              : 
     278              :     template <typename argT>
     279            0 :     void setConstant( argT val )
     280              :     {
     281            0 :         int N = _cols * _rows;
     282              : 
     283            0 :         Scalar dval = (Scalar)val;
     284            0 :         for( int i = 0; i < N; ++i )
     285            0 :             _data[i] = dval;
     286            0 :     }
     287              : 
     288            0 :     void setZero()
     289              :     {
     290            0 :         setConstant( (Scalar)0 );
     291            0 :     }
     292              : 
     293            0 :     imagingArray &operator=( const imagingArray &arr )
     294              :     {
     295            0 :         resize( arr.rows(), arr.cols() );
     296              : 
     297            0 :         for( int i = 0; i < _rows; ++i )
     298              :         {
     299            0 :             for( int j = 0; j < _cols; ++j )
     300              :             {
     301            0 :                 operator()( i, j ) = arr( i, j );
     302              :             }
     303              :         }
     304              : 
     305            0 :         return ( *this );
     306              :     }
     307              : 
     308              :     /// In-place product.  Works for both scalars and imagingArray types.
     309              :     template <typename typeT>
     310            0 :     imagingArray &operator*=( typeT &alpha )
     311              :     {
     312            0 :         imagingArrayInplaceProduct<imagingArray, typeT> prod;
     313            0 :         prod( *this, alpha );
     314            0 :         return *this;
     315              :     }
     316              : 
     317              :     /// In-place division.  Works for both scalars and imagingArray types.
     318              :     template <typename typeT>
     319              :     imagingArray &operator/=( typeT alpha )
     320              :     {
     321              :         imagingArrayInplaceDivision<imagingArray, typeT> div;
     322              :         div( *this, alpha );
     323              :         return *this;
     324              :     }
     325              : 
     326              :     /// In-place add.  Works for both scalars and imagingArray types.
     327              :     template <typename typeT>
     328              :     imagingArray &operator+=( typeT &alpha )
     329              :     {
     330              :         imagingArrayInplaceAdd<imagingArray, typeT> prod;
     331              :         prod( *this, alpha );
     332              :         return *this;
     333              :     }
     334              : 
     335            0 :     Scalar sum()
     336              :     {
     337            0 :         int N = _cols * _rows;
     338            0 :         Scalar _sum = 0;
     339              : 
     340            0 :         for( int i = 0; i < N; ++i )
     341            0 :             _sum += _data[i];
     342              : 
     343            0 :         return _sum;
     344              :     }
     345              : 
     346            0 :     Eigen::Map<Eigen::Array<Scalar, -1, -1>> eigenMap()
     347              :     {
     348            0 :         return Eigen::Map<Eigen::Array<Scalar, -1, -1>>( _data, _rows, _cols );
     349              :     }
     350              : };
     351              : 
     352              : template <typename scalarT>
     353              : using imagingArrayT = imagingArray<scalarT, fftwAllocator<scalarT>, 0>;
     354              : 
     355              : // typedef imagingArray<float,mx::fftwAllocator<float>,0> imagingArrayf;
     356              : // typedef imagingArray<double,mx::fftwAllocator<double>,0> imagingArrayd;
     357              : // typedef imagingArray<std::complex<float>,mx::fftwAllocator<std::complex<float> >,0> imagingArraycf;
     358              : 
     359              : } // namespace wfp
     360              : } // namespace mx
     361              : 
     362              : #endif // imagingArray_hpp
        

Generated by: LCOV version 2.0-1