Quinoa all test code coverage report
Current view: top level - Base - Data.hpp (source / functions) Hit Total Coverage
Commit: -128-NOTFOUND Lines: 109 109 100.0 %
Date: 2024-11-22 09:12:55 Functions: 30 30 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 497 1008 49.3 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Base/Data.hpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.
       7                 :            :              All rights reserved. See the LICENSE file for details.
       8                 :            :   \brief     Generic data storage with different memory layouts
       9                 :            :   \details   Generic data storage with different memory layouts. See also the
      10                 :            :     rationale discussed in the [design](layout.html) document.
      11                 :            : */
      12                 :            : // *****************************************************************************
      13                 :            : #ifndef Data_h
      14                 :            : #define Data_h
      15                 :            : 
      16                 :            : #include <array>
      17                 :            : #include <string>
      18                 :            : #include <cstdint>
      19                 :            : #include <vector>
      20                 :            : #include <set>
      21                 :            : #include <algorithm>
      22                 :            : 
      23                 :            : #include "Types.hpp"
      24                 :            : #include "Exception.hpp"
      25                 :            : 
      26                 :            : #include "NoWarning/pup_stl.hpp"
      27                 :            : 
      28                 :            : namespace tk {
      29                 :            : 
      30                 :            : //! Tags for selecting data layout policies
      31                 :            : const uint8_t UnkEqComp = 0;
      32                 :            : const uint8_t EqCompUnk = 1;
      33                 :            : 
      34                 :            : //! Zero-runtime-cost data-layout wrappers with type-based compile-time dispatch
      35                 :            : template< uint8_t Layout >
      36 [ +  - ][ +  - ]:     248427 : class Data {
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      37                 :            : 
      38                 :            :   private:
      39                 :            :     //! \brief Inherit type of number of components from keyword 'ncomp'
      40                 :            :     using ncomp_t = tk::ncomp_t;
      41                 :            : 
      42                 :            :   public:
      43                 :            :     //! Default constructor (required for Charm++ migration)
      44 [ +  - ][ -  - ]:      28878 :     explicit Data() : m_vec(), m_nunk(), m_nprop() {}
      45                 :            : 
      46                 :            :     //! Constructor
      47                 :            :     //! \param[in] nu Number of unknowns to allocate memory for
      48                 :            :     //! \param[in] np Total number of properties, i.e., scalar variables or
      49                 :            :     //!   components, per unknown
      50 [ +  - ][ +  - ]:       7054 :     explicit Data( ncomp_t nu, ncomp_t np ) :
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
      51                 :            :       m_vec( nu*np ),
      52                 :            :       m_nunk( nu ),
      53 [ +  - ][ +  + ]:    2110581 :       m_nprop( np ) {}
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
      54                 :            : 
      55                 :            :     //! Const data access dispatch
      56                 :            :     //! \details Public interface to const-ref data access to a single real
      57                 :            :     //!   value. Use it as Data(p,c), where p is the unknown index, and c is
      58                 :            :     //!   the component index specifying the scalar equation within a system of
      59                 :            :     //!   equations. Requirement: component <
      60                 :            :     //!   nprop, unknown < nunk, enforced with an assert in DEBUG mode, see also
      61                 :            :     //!   the constructor.
      62                 :            :     //! \param[in] unknown Unknown index
      63                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
      64                 :            :     //!   a system
      65                 :            :     //! \return Const reference to data of type tk::real
      66                 :            :     const tk::real&
      67                 :            :     operator()( ncomp_t unknown, ncomp_t component ) const
      68                 :            :     { return access( unknown, component, int2type< Layout >() ); }
      69                 :            : 
      70                 :            :     //! Non-const data access dispatch
      71                 :            :     //! \details Public interface to non-const-ref data access to a single real
      72                 :            :     //!   value. Use it as Data(p,c), where p is the unknown index, and c is
      73                 :            :     //!   the component index specifying the scalar equation within a system of
      74                 :            :     //!   equations. Requirement: component <
      75                 :            :     //!   nprop, unknown < nunk, enforced with an assert in DEBUG mode, see also
      76                 :            :     //!   the constructor.
      77                 :            :     //! \param[in] unknown Unknown index
      78                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
      79                 :            :     //!   a system
      80                 :            :     //! \return Non-const reference to data of type tk::real
      81                 :            :     //! \see "Avoid Duplication in const and Non-const Member Function," and
      82                 :            :     //!   "Use const whenever possible," Scott Meyers, Effective C++, 3d ed.
      83                 :            :     tk::real&
      84                 :            :     operator()( ncomp_t unknown, ncomp_t component ) {
      85                 :            :       return const_cast< tk::real& >(
      86                 :            :                static_cast< const Data& >( *this ).
      87                 :            :                  operator()( unknown, component ) );
      88                 :            :     }
      89                 :            : 
      90                 :            :     //! Const ptr to physical variable access dispatch
      91                 :            :     //! \details Public interface to the first half of a physical variable
      92                 :            :     //!   access. cptr() and var() are two member functions intended to be used
      93                 :            :     //!   together in case when component would be expensive to
      94                 :            :     //!   compute for data access via the function call operator, i.e., cptr()
      95                 :            :     //!   can be used to pre-compute part of the address, which returns a
      96                 :            :     //!   pointer and var() can be used to finish the data access using the
      97                 :            :     //!   pointer returned by cptr(). In other words, cptr() returns part of the
      98                 :            :     //!   address known based on component and intended to be used in
      99                 :            :     //!   a setup phase. Then var() takes this partial address and finishes the
     100                 :            :     //!   address calculation given the unknown id. Thus the following two data
     101                 :            :     //!   accesses are equivalent (modulo constness):
     102                 :            :     //!   * real& value = operator()( unk, comp ); and
     103                 :            :     //!   * const real* p = cptr( comp ); and
     104                 :            :     //!     const real& value = var( p, unk ); or real& value = var( p, unk );
     105                 :            :     //!   Requirement: component < nprop, enforced with an assert in
     106                 :            :     //!   DEBUG mode, see also the constructor.
     107                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     108                 :            :     //!   a system
     109                 :            :     //! \return Pointer to data of type tk::real for use with var()
     110                 :            :     //! \see Example client code in Statistics::setupOrdinary() and
     111                 :            :     //!   Statistics::accumulateOrd() in Statistics/Statistics.C.
     112                 :            :     const tk::real*
     113                 :            :     cptr( ncomp_t component ) const
     114                 :            :     { return cptr( component, int2type< Layout >() ); }
     115                 :            : 
     116                 :            :     //! Const-ref data-access dispatch
     117                 :            :     //! \details Public interface to the second half of a physical variable
     118                 :            :     //!   access. cptr() and var() are two member functions intended to be used
     119                 :            :     //!   together in case when component would be expensive to
     120                 :            :     //!   compute for data access via the function call operator, i.e., cptr()
     121                 :            :     //!   can be used to pre-compute part of the address, which returns a
     122                 :            :     //!   pointer and var() can be used to finish the data access using the
     123                 :            :     //!   pointer returned by cptr(). In other words, cptr() returns part of the
     124                 :            :     //!   address known based on component and intended to be used in
     125                 :            :     //!   a setup phase. Then var() takes this partial address and finishes the
     126                 :            :     //!   address calculation given the unknown id. Thus the following two data
     127                 :            :     //!   accesses are equivalent (modulo constness):
     128                 :            :     //!   * real& value = operator()( unk, comp ); and
     129                 :            :     //!   * const real* p = cptr( comp ); and
     130                 :            :     //!     const real& value = var( p, unk ); or real& value = var( p, unk );
     131                 :            :     //!   Requirement: unknown < nunk, enforced with an assert in DEBUG mode,
     132                 :            :     //!   see also the constructor.
     133                 :            :     //! \param[in] pt Pointer to data of type tk::real as returned from cptr()
     134                 :            :     //! \param[in] unknown Unknown index
     135                 :            :     //! \return Const reference to data of type tk::real
     136                 :            :     //! \see Example client code in Statistics::setupOrdinary() and
     137                 :            :     //!   Statistics::accumulateOrd() in Statistics/Statistics.C.
     138                 :            :     const tk::real&
     139                 :            :     var( const tk::real* pt, ncomp_t unknown ) const
     140                 : 1365923362 :     { return var( pt, unknown, int2type< Layout >() ); }
     141                 :            : 
     142                 :            :     //! Non-const-ref data-access dispatch
     143                 :            :     //! \details Public interface to the second half of a physical variable
     144                 :            :     //!   access. cptr() and var() are two member functions intended to be used
     145                 :            :     //!   together in case when component would be expensive to
     146                 :            :     //!   compute for data access via the function call operator, i.e., cptr()
     147                 :            :     //!   can be used to pre-compute part of the address, which returns a
     148                 :            :     //!   pointer and var() can be used to finish the data access using the
     149                 :            :     //!   pointer returned by cptr(). In other words, cptr() returns part of the
     150                 :            :     //!   address known based on component and intended to be used in
     151                 :            :     //!   a setup phase. Then var() takes this partial address and finishes the
     152                 :            :     //!   address calculation given the unknown id. Thus the following two data
     153                 :            :     //!   accesses are equivalent (modulo constness):
     154                 :            :     //!   * real& value = operator()( unk, comp ); and
     155                 :            :     //!   * const real* p = cptr( comp ); and
     156                 :            :     //!     const real& value = var( p, unk ); or real& value = var( p, unk );
     157                 :            :     //!   Requirement: unknown < nunk, enforced with an assert in DEBUG mode,
     158                 :            :     //!   see also the constructor.
     159                 :            :     //! \param[in] pt Pointer to data of type tk::real as returned from cptr()
     160                 :            :     //! \param[in] unknown Unknown index
     161                 :            :     //! \return Non-const reference to data of type tk::real
     162                 :            :     //! \see Example client code in Statistics::setupOrdinary() and
     163                 :            :     //!   Statistics::accumulateOrd() in Statistics/Statistics.C.
     164                 :            :     //! \see "Avoid Duplication in const and Non-const Member Function," and
     165                 :            :     //!   "Use const whenever possible," Scott Meyers, Effective C++, 3d ed.
     166                 :            :     tk::real&
     167                 :            :     var( const tk::real* pt, ncomp_t unknown ) {
     168                 :            :       return const_cast< tk::real& >(
     169                 :            :                static_cast< const Data& >( *this ).var( pt, unknown ) );
     170                 :            :     }
     171                 :            : 
     172                 :            :     //! Access to number of unknowns
     173                 :            :     //! \return Number of unknowns
     174                 :            :     ncomp_t nunk() const noexcept { return m_nunk; }
     175                 :            : 
     176                 :            :     //! Access to number of properties
     177                 :            :     //! \details This is the total number of scalar components per unknown
     178                 :            :     //! \return Number of propertes/unknown
     179                 :            :     ncomp_t nprop() const noexcept { return m_nprop; }
     180                 :            : 
     181                 :            :     //! Extract flat vector of all unknowns
     182                 :            :     //! \return Flat vector of reals
     183                 :            :     std::vector< tk::real >
     184                 :        679 :     flat() const {
     185                 :        679 :       std::vector< tk::real > w( m_nunk * m_nprop );
     186         [ +  + ]:       2716 :       for (std::size_t j=0; j<m_nprop; ++j)
     187         [ +  + ]:    3754755 :         for (std::size_t i=0; i<m_nunk; ++i)
     188                 :    3752718 :           w[i*m_nprop+j] = operator()( i, j );
     189                 :        679 :       return w;
     190                 :            :     }
     191                 :            : 
     192                 :            :     //! Assign from flat vector
     193                 :            :     //! \param[in] rhs Flat vector to assign from
     194                 :            :     //! \note This is the opposite of flat().
     195                 :          1 :     void operator=( const std::vector< tk::real >& rhs ) {
     196                 :            :       Assert( rhs.size() == m_nunk * m_nprop, "Size mismatch" );
     197 [ +  + ][ +  + ]:          8 :       for (std::size_t j=0; j<m_nprop; ++j)
     198 [ +  + ][ +  + ]:         18 :         for (std::size_t i=0; i<m_nunk; ++i)
     199                 :         12 :           operator()( i, j ) = rhs[i*m_nprop+j];
     200                 :          1 :     }
     201                 :            : 
     202                 :            :     //! Assign from array(3) of vectors
     203                 :            :     //! \param[in] rhs Array(3) of vectors to assign from
     204                 :            :     void operator=( const std::array< std::vector< tk::real >, 3 >& rhs ) {
     205                 :            :       Assert( m_nprop == 3, "Size mismatch" );
     206                 :            :       Assert( rhs[0].size() == m_nunk, "Size mismatch" );
     207                 :            :       Assert( rhs[1].size() == m_nunk, "Size mismatch" );
     208                 :            :       Assert( rhs[2].size() == m_nunk, "Size mismatch" );
     209 [ +  + ][ +  + ]:          8 :       for (std::size_t j=0; j<3; ++j)
     210 [ +  + ][ +  + ]:         18 :         for (std::size_t i=0; i<m_nunk; ++i)
     211                 :         12 :           operator()( i, j ) = rhs[j][i];
     212                 :            :     }
     213                 :            : 
     214                 :            :     //! Extract vector of unknowns given component
     215                 :            :     //! \details Requirement: component < nprop, enforced with an
     216                 :            :     //!   assert in DEBUG mode, see also the constructor.
     217                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     218                 :            :     //!   a system
     219                 :            :     //! \return A vector of unknowns given by component (length:
     220                 :            :     //!   nunk(), i.e., the first constructor argument)
     221                 :            :     std::vector< tk::real >
     222                 :      99622 :     extract_comp( ncomp_t component ) const {
     223                 :      99622 :       std::vector< tk::real > w( m_nunk );
     224         [ +  + ]:   25194293 :       for (ncomp_t i=0; i<m_nunk; ++i)
     225                 :   25094671 :         w[i] = operator()( i, component );
     226                 :      99622 :       return w;
     227                 :            :     }
     228                 :            : 
     229                 :            :     //! Extract (a copy of) all components for an unknown
     230                 :            :     //! \details Requirement: unknown < nunk, enforced with an assert in DEBUG
     231                 :            :     //!   mode, see also the constructor.
     232                 :            :     //! \param[in] unknown Index of unknown
     233                 :            :     //! \return A vector of components for a single unknown (length: nprop,
     234                 :            :     //!   i.e., the second constructor argument)
     235                 :            :     std::vector< tk::real >
     236                 :   67254236 :     extract( ncomp_t unknown ) const {
     237                 :   67254236 :       std::vector< tk::real > w( m_nprop );
     238         [ +  + ]:  667801057 :       for (ncomp_t i=0; i<m_nprop; ++i) w[i] = operator()( unknown, i );
     239                 :   67254236 :       return w;
     240                 :            :     }
     241                 :            : 
     242                 :            :     //! Extract all components for unknown
     243                 :            :     //! \details Requirement: unknown < nunk, enforced with an assert in DEBUG
     244                 :            :     //!   mode, see also the constructor.
     245                 :            :     //! \param[in] unknown Index of unknown
     246                 :            :     //! \return A vector of components for a single unknown (length: nprop,
     247                 :            :     //!   i.e., the second constructor argument)
     248                 :            :     //! \note This is simply an alias for extract( unknown )
     249                 :            :     std::vector< tk::real >
     250 [ +  - ][ +  - ]:   66540870 :     operator[]( ncomp_t unknown ) const { return extract( unknown ); }
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     251                 :            : 
     252                 :            :     //! Extract (a copy of) four values of unknowns
     253                 :            :     //! \details Requirement: component < nprop, [A,B,C,D] < nunk,
     254                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     255                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     256                 :            :     //!   a system
     257                 :            :     //! \param[in] A Index of 1st unknown
     258                 :            :     //! \param[in] B Index of 2nd unknown
     259                 :            :     //! \param[in] C Index of 3rd unknown
     260                 :            :     //! \param[in] D Index of 4th unknown
     261                 :            :     //! \return Array of the four values of component
     262                 :            :     std::array< tk::real, 4 >
     263                 :            :     extract( ncomp_t component,
     264                 :            :              ncomp_t A, ncomp_t B, ncomp_t C, ncomp_t D ) const
     265                 :            :     {
     266                 :            :       auto p = cptr( component );
     267         [ +  - ]:   28802926 :       return {{ var(p,A), var(p,B), var(p,C), var(p,D) }};
     268                 :            :     }
     269                 :            : 
     270                 :            :     //! Extract (a copy of) four values of unknowns
     271                 :            :     //! \details Requirement: component < nprop, for all N[i] < nunk,
     272                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     273                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     274                 :            :     //!   a system
     275                 :            :     //! \param[in] N Indices of the 4 unknowns
     276                 :            :     //! \return Array of the four values of component
     277                 :            :     std::array< tk::real, 4 >
     278                 :   28802929 :     extract( ncomp_t component,
     279                 :            :              const std::array< ncomp_t, 4 >& N ) const
     280                 :            :     {
     281                 :   28802929 :       return extract( component, N[0], N[1], N[2], N[3] );
     282                 :            :     }
     283                 :            : 
     284                 :            :     //! Extract (a copy of) three values of unknowns
     285                 :            :     //! \details Requirement: component < nprop, [A,B,C] < nunk,
     286                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     287                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     288                 :            :     //!   a system
     289                 :            :     //! \param[in] A Index of 1st unknown
     290                 :            :     //! \param[in] B Index of 2nd unknown
     291                 :            :     //! \param[in] C Index of 3rd unknown
     292                 :            :     //! \return Array of the four values of component
     293                 :            :     std::array< tk::real, 3 >
     294                 :            :     extract( ncomp_t component,
     295                 :            :              ncomp_t A, ncomp_t B, ncomp_t C ) const
     296                 :            :     {
     297                 :            :       auto p = cptr( component );
     298 [ +  - ][ +  - ]:          2 :       return {{ var(p,A), var(p,B), var(p,C) }};
     299                 :            :     }
     300                 :            : 
     301                 :            :     //! Extract (a copy of) three values of unknowns
     302                 :            :     //! \details Requirement: component < nprop, for all N[i] < nunk,
     303                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     304                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     305                 :            :     //!   a system
     306                 :            :     //! \param[in] N Indices of the 3 unknowns
     307                 :            :     //! \return Array of the three values of component
     308                 :            :     std::array< tk::real, 3 >
     309                 :            :     extract( ncomp_t component,
     310                 :            :              const std::array< ncomp_t, 3 >& N ) const
     311                 :            :     {
     312                 :            :       return extract( component, N[0], N[1], N[2] );
     313                 :            :     }
     314                 :            : 
     315                 :            :     //! Const-ref accessor to underlying raw data as a std::vector
     316                 :            :     //! \return Constant reference to underlying raw data
     317                 :            :     const std::vector< tk::real >& vec() const { return m_vec; }
     318                 :            : 
     319                 :            :     //! Non-const-ref accessor to underlying raw data as a std::vector
     320                 :            :     //! \return Non-constant reference to underlying raw data
     321                 :            :     std::vector< tk::real >& vec() { return m_vec; }
     322                 :            : 
     323                 :            :     //! Compound operator-=
     324                 :            :     //! \param[in] rhs Data object to subtract
     325                 :            :     //! \return Reference to ourselves after subtraction
     326                 :            :     Data< Layout >& operator-= ( const Data< Layout >& rhs ) {
     327                 :            :       Assert( rhs.nunk() == m_nunk, "Incorrect number of unknowns" );
     328                 :            :       Assert( rhs.nprop() == m_nprop, "Incorrect number of properties" );
     329                 :          2 :       std::transform( rhs.vec().cbegin(), rhs.vec().cend(),
     330                 :            :                       m_vec.cbegin(), m_vec.begin(),
     331                 :         24 :                       []( tk::real s, tk::real d ){ return d-s; } );
     332                 :            :       return *this;
     333                 :            :     }
     334                 :            :     //! Operator -
     335                 :            :     //! \param[in] rhs Data object to subtract
     336                 :            :     //! \return Copy of Data object after rhs has been subtracted
     337                 :            :     //! \details Implemented in terms of compound operator-=
     338                 :          2 :     Data< Layout > operator- ( const Data< Layout >& rhs )
     339                 :          2 :     const { return Data< Layout >( *this ) -= rhs; }
     340                 :            : 
     341                 :            :     //! Compound operator+=
     342                 :            :     //! \param[in] rhs Data object to add
     343                 :            :     //! \return Reference to ourselves after addition
     344                 :            :     Data< Layout >& operator+= ( const Data< Layout >& rhs ) {
     345                 :            :       Assert( rhs.nunk() == m_nunk, "Incorrect number of unknowns" );
     346                 :            :       Assert( rhs.nprop() == m_nprop, "Incorrect number of properties" );
     347                 :      42551 :       std::transform( rhs.vec().cbegin(), rhs.vec().cend(),
     348                 :            :                       m_vec.cbegin(), m_vec.begin(),
     349                 :   18809511 :                       []( tk::real s, tk::real d ){ return d+s; } );
     350                 :            :       return *this;
     351                 :            :     }
     352                 :            :     //! Operator +
     353                 :            :     //! \param[in] rhs Data object to add
     354                 :            :     //! \return Copy of Data object after rhs has been multiplied with
     355                 :            :     //! \details Implemented in terms of compound operator+=
     356                 :      42551 :     Data< Layout > operator+ ( const Data< Layout >& rhs )
     357                 :      42551 :     const { return Data< Layout >( *this ) += rhs; }
     358                 :            : 
     359                 :            :     //! Compound operator*= multiplying by another Data object item by item
     360                 :            :     //! \param[in] rhs Data object to multiply with
     361                 :            :     //! \return Reference to ourselves after multiplication
     362                 :            :     Data< Layout >& operator*= ( const Data< Layout >& rhs ) {
     363                 :            :       Assert( rhs.nunk() == m_nunk, "Incorrect number of unknowns" );
     364                 :            :       Assert( rhs.nprop() == m_nprop, "Incorrect number of properties" );
     365                 :          2 :       std::transform( rhs.vec().cbegin(), rhs.vec().cend(),
     366                 :            :                       m_vec.cbegin(), m_vec.begin(),
     367                 :         24 :                       []( tk::real s, tk::real d ){ return d*s; } );
     368                 :            :       return *this;
     369                 :            :     }
     370                 :            :     //! Operator * multiplying by another Data object item by item
     371                 :            :     //! \param[in] rhs Data object to multiply with
     372                 :            :     //! \return Copy of Data object after rhs has been multiplied with
     373                 :            :     //! \details Implemented in terms of compound operator*=
     374                 :          2 :     Data< Layout > operator* ( const Data< Layout >& rhs )
     375                 :          2 :     const { return Data< Layout >( *this ) *= rhs; }
     376                 :            : 
     377                 :            :     //! Compound operator*= multiplying all items by a scalar
     378                 :            :     //! \param[in] rhs Scalar to multiply with
     379                 :            :     //! \return Reference to ourselves after multiplication
     380                 :            :     Data< Layout >& operator*= ( tk::real rhs ) {
     381                 :            :       // cppcheck-suppress useStlAlgorithm
     382 [ +  + ][ +  + ]:   18852078 :       for (auto& v : m_vec) v *= rhs;
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
     383                 :            :       return *this;
     384                 :            :     }
     385                 :            :     //! Operator * multiplying all items by a scalar
     386                 :            :     //! \param[in] rhs Scalar to multiply with
     387                 :            :     //! \return Copy of Data object after rhs has been multiplied with
     388                 :            :     //! \details Implemented in terms of compound operator*=
     389                 :          2 :     Data< Layout > operator* ( tk::real rhs )
     390                 :          2 :     const { return Data< Layout >( *this ) *= rhs; }
     391                 :            : 
     392                 :            :     //! Compound operator/=
     393                 :            :     //! \param[in] rhs Data object to divide by
     394                 :            :     //! \return Reference to ourselves after division
     395                 :            :     Data< Layout >& operator/= ( const Data< Layout >& rhs ) {
     396                 :            :       Assert( rhs.nunk() == m_nunk, "Incorrect number of unknowns" );
     397                 :            :       Assert( rhs.nprop() == m_nprop, "Incorrect number of properties" );
     398                 :          2 :       std::transform( rhs.vec().cbegin(), rhs.vec().cend(),
     399                 :            :                       m_vec.cbegin(), m_vec.begin(),
     400                 :         24 :                       []( tk::real s, tk::real d ){ return d/s; } );
     401                 :            :       return *this;
     402                 :            :     }
     403                 :            :     //! Operator /
     404                 :            :     //! \param[in] rhs Data object to divide by
     405                 :            :     //! \return Copy of Data object after rhs has been divided by
     406                 :            :     //! \details Implemented in terms of compound operator/=
     407                 :          2 :     Data< Layout > operator/ ( const Data< Layout >& rhs )
     408                 :          2 :     const { return Data< Layout >( *this ) /= rhs; }
     409                 :            : 
     410                 :            :     //! Compound operator/= dividing all items by a scalar
     411                 :            :     //! \param[in] rhs Scalar to divide with
     412                 :            :     //! \return Reference to ourselves after division
     413                 :            :     Data< Layout >& operator/= ( tk::real rhs ) {
     414                 :            :       // cppcheck-suppress useStlAlgorithm
     415 [ +  + ][ +  + ]:         28 :       for (auto& v : m_vec) v /= rhs;
         [ +  + ][ +  + ]
     416                 :            :       return *this;
     417                 :            :     }
     418                 :            :     //! Operator / dividing all items by a scalar
     419                 :            :     //! \param[in] rhs Scalar to divide with
     420                 :            :     //! \return Copy of Data object after rhs has been divided by
     421                 :            :     //! \details Implemented in terms of compound operator/=
     422                 :          2 :     Data< Layout > operator/ ( tk::real rhs )
     423                 :          2 :     const { return Data< Layout >( *this ) /= rhs; }
     424                 :            : 
     425                 :            :     //! Add new unknown at the end of the container
     426                 :            :     //! \param[in] prop Vector of properties to initialize the new unknown with
     427                 :            :     void push_back( const std::vector< tk::real >& prop )
     428         [ +  - ]:     158930 :     { return push_back( prop, int2type< Layout >() ); }
     429                 :            : 
     430                 :            :     //! Resize data store to contain 'count' elements
     431                 :            :     //! \param[in] count Resize store to contain count * nprop elements
     432                 :            :     //! \param[in] value Value to initialize new data with (default: 0.0)
     433                 :            :     //! \note This works for both shrinking and enlarging, as this simply
     434                 :            :     //!   translates to std::vector::resize(). Note that count changes, nprop
     435                 :            :     //!   does not, see the private overload resize().
     436                 :            :     void resize( std::size_t count, tk::real value = 0.0 )
     437                 :      19073 :     { resize( count, value, int2type< Layout >() ); }
     438                 :            : 
     439                 :            :     //! Remove a number of unknowns
     440                 :            :     //! \param[in] unknown Set of indices of unknowns to remove
     441                 :          3 :     void rm( const std::set< ncomp_t >& unknown ) {
     442                 :            :       auto remove = [ &unknown ]( std::size_t i ) -> bool {
     443         [ +  + ]:         11 :         if (unknown.find(i) != end(unknown)) return true;
     444                 :            :         return false;
     445                 :            :       };
     446                 :            :       std::size_t last = 0;
     447         [ +  + ]:          7 :       for(std::size_t i=0; i<m_nunk; ++i, ++last) {
     448                 :          5 :         while( remove(i) ) ++i;
     449         [ +  + ]:          6 :         if (i >= m_nunk) break;
     450         [ +  + ]:         11 :         for (ncomp_t p = 0; p<m_nprop; ++p)
     451                 :          7 :           m_vec[ last*m_nprop+p ] = m_vec[ i*m_nprop+p ];
     452                 :            :       }
     453                 :          3 :       m_vec.resize( last*m_nprop );
     454                 :          3 :       m_nunk -= unknown.size();
     455                 :          3 :     }
     456                 :            : 
     457                 :            :     //! Fill vector of unknowns with the same value
     458                 :            :     //! \details Requirement: component < nprop, enforced with an
     459                 :            :     //!   assert in DEBUG mode, see also the constructor.
     460                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     461                 :            :     //!   a system
     462                 :            :     //! \param[in] value Value to fill vector of unknowns with
     463                 :            :     inline void fill( ncomp_t component, tk::real value ) {
     464                 :            :       auto p = cptr( component );
     465 [ +  + ][ +  + ]:   24849253 :       for (ncomp_t i=0; i<m_nunk; ++i) var(p,i) = value;
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     466                 :            :     }
     467                 :            : 
     468                 :            :     //! Fill full data storage with value
     469                 :            :     //! \param[in] value Value to fill data with
     470                 :            :     void fill( tk::real value )
     471                 :            :     { std::fill( begin(m_vec), end(m_vec), value ); }
     472                 :            : 
     473                 :            :     //! Check if vector of unknowns is empty
     474                 :            :     bool empty() const noexcept { return m_vec.empty(); }
     475                 :            : 
     476                 :            :     //! Layout name dispatch
     477                 :            :     //! \return The name of the data layout used
     478                 :            :     static std::string layout() { return layout( int2type< Layout >() ); }
     479                 :            : 
     480                 :            :     /** @name Pack/Unpack: Serialize Data object for Charm++ */
     481                 :            :     ///@{
     482                 :            :     //! \brief Pack/Unpack serialize member function
     483                 :            :     //! \param[in,out] p Charm++'s PUP::er serializer object reference
     484                 :     300793 :     void pup( PUP::er &p ) {
     485                 :     300793 :       p | m_vec;
     486                 :     300793 :       p | m_nunk;
     487                 :     300793 :       p | m_nprop;
     488                 :     300793 :     }
     489                 :            :     //! \brief Pack/Unpack serialize operator|
     490                 :            :     //! \param[in,out] p Charm++'s PUP::er serializer object reference
     491                 :            :     //! \param[in,out] d DataLyaout object reference
     492                 :     104834 :     friend void operator|( PUP::er& p, Data& d ) { d.pup(p); }
     493                 :            :     //@}
     494                 :            : 
     495                 :            :   private:
     496                 :            :     //! Transform a compile-time uint8_t into a type, used for dispatch
     497                 :            :     //! \see A. Alexandrescu, Modern C++ Design: Generic Programming and Design
     498                 :            :     //!   Patterns Applied, Addison-Wesley Professional, 2001.
     499                 :            :     template< uint8_t m > struct int2type { enum { value = m }; };
     500                 :            : 
     501                 :            :     //! Overloads for the various const data accesses
     502                 :            :     //! \details Requirement: component < nprop, unknown < nunk,
     503                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     504                 :            :     //! \param[in] unknown Unknown index
     505                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     506                 :            :     //!   a system
     507                 :            :     //! \return Const reference to data of type tk::real
     508                 :            :     //! \see A. Alexandrescu, Modern C++ Design: Generic Programming and Design
     509                 :            :     //!   Patterns Applied, Addison-Wesley Professional, 2001.
     510                 :            :     const tk::real&
     511                 :            :     access( ncomp_t unknown, ncomp_t component, int2type< UnkEqComp > ) const
     512                 :            :     {
     513                 :            :       Assert( component < m_nprop, "Out-of-bounds access: "
     514                 :            :               "component < number of properties" );
     515                 :            :       Assert( unknown < m_nunk, "Out-of-bounds access: unknown < number of "
     516                 :            :               "unknowns" );
     517 [ +  + ][ +  + ]:13116822236 :       return m_vec[ unknown*m_nprop + component ];
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  + ]
         [ +  + ][ -  - ]
         [ +  + ][ +  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
         [ +  - ][ +  + ]
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  + ][ +  - ]
         [ +  + ][ +  + ]
         [ -  - ][ -  - ]
         [ -  - ][ -  - ]
                 [ -  - ]
     518                 :            :     }
     519                 :            :     const tk::real&
     520                 :            :     access( ncomp_t unknown, ncomp_t component, int2type< EqCompUnk > ) const
     521                 :            :     {
     522                 :            :       Assert( component < m_nprop, "Out-of-bounds access: "
     523                 :            :               "component < number of properties" );
     524                 :            :       Assert( unknown < m_nunk, "Out-of-bounds access: unknown < number of "
     525                 :            :               "unknowns" );
     526 [ +  - ][ -  + ]:        396 :       return m_vec[ (component)*m_nunk + unknown ];
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     527                 :            :     }
     528                 :            : 
     529                 :            :     // Overloads for the various const ptr to physical variable accesses
     530                 :            :     //! \details Requirement: component < nprop, unknown < nunk,
     531                 :            :     //!   enforced with an assert in DEBUG mode, see also the constructor.
     532                 :            :     //! \param[in] component Component index, i.e., position of a scalar within
     533                 :            :     //!   a system
     534                 :            :     //! \return Pointer to data of type tk::real for use with var()
     535                 :            :     //! \see A. Alexandrescu, Modern C++ Design: Generic Programming and Design
     536                 :            :     //!   Patterns Applied, Addison-Wesley Professional, 2001.
     537                 :            :     const tk::real*
     538                 :            :     cptr( ncomp_t component, int2type< UnkEqComp > ) const {
     539                 :            :       Assert( component < m_nprop, "Out-of-bounds access: "
     540                 :            :               "component < number of properties" );
     541 [ -  - ][ -  - ]:    4268194 :       return m_vec.data() + component;
     542                 :            :     }
     543                 :            :     const tk::real*
     544                 :            :     cptr( ncomp_t component, int2type< EqCompUnk > ) const {
     545                 :            :       Assert( component < m_nprop, "Out-of-bounds access: "
     546                 :            :               "component < number of properties" );
     547 [ +  - ][ +  - ]:         10 :       return m_vec.data() + (component)*m_nunk;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     548                 :            :     }
     549                 :            : 
     550                 :            :     // Overloads for the various const physical variable accesses
     551                 :            :     //!   Requirement: unknown < nunk, enforced with an assert in DEBUG mode,
     552                 :            :     //!   see also the constructor.
     553                 :            :     //! \param[in] pt Pointer to data of type tk::real as returned from cptr()
     554                 :            :     //! \param[in] unknown Unknown index
     555                 :            :     //! \return Const reference to data of type tk::real
     556                 :            :     //! \see A. Alexandrescu, Modern C++ Design: Generic Programming and Design
     557                 :            :     //!   Patterns Applied, Addison-Wesley Professional, 2001.
     558                 :            :     inline const tk::real&
     559                 :            :     var( const tk::real* const pt, ncomp_t unknown, int2type< UnkEqComp > )
     560                 :            :     const {
     561                 :            :       Assert( unknown < m_nunk, "Out-of-bounds access: unknown < number of "
     562                 :            :               "unknowns" );
     563 [ +  - ][ +  - ]: 1340840302 :       return *(pt + unknown*m_nprop);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     564                 :            :     }
     565                 :            :     inline const tk::real&
     566                 :            :     var( const tk::real* const pt, ncomp_t unknown, int2type< EqCompUnk > )
     567                 :            :     const {
     568                 :            :       Assert( unknown < m_nunk, "Out-of-bounds access: unknown < number of "
     569                 :            :               "unknowns" );
     570 [ +  - ][ +  - ]:         15 :       return *(pt + unknown);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     571                 :            :     }
     572                 :            : 
     573                 :            :     //! Add new unknown
     574                 :            :     //! \param[in] prop Vector of properties to initialize the new unknown with
     575                 :            :     //! \note Only the UnkEqComp overload is provided as this operation would be
     576                 :            :     //!   too inefficient with the EqCompUnk data layout.
     577                 :            :     void push_back( const std::vector< tk::real >& prop, int2type< UnkEqComp > )
     578                 :            :     {
     579                 :            :       Assert( prop.size() == m_nprop, "Incorrect number of properties" );
     580                 :            :       m_vec.resize( (m_nunk+1) * m_nprop );
     581                 :            :       ncomp_t u = m_nunk;
     582                 :            :       ++m_nunk;
     583                 :            :       for (ncomp_t i=0; i<m_nprop; ++i) operator()( u, i ) = prop[i];
     584                 :            :     }
     585                 :            : 
     586                 :            :     void push_back( const std::vector< tk::real >&, int2type< EqCompUnk > )
     587                 :            :     { Throw( "Not implented. It would be inefficient" ); }
     588                 :            : 
     589                 :            :     //! Resize data store to contain 'count' elements
     590                 :            :     //! \param[in] count Resize store to contain 'count' elements
     591                 :            :     //! \param[in] value Value to initialize new data with
     592                 :            :     //! \note Only the UnkEqComp overload is provided as this operation would be
     593                 :            :     //!   too inefficient with the EqCompUnk data layout.
     594                 :            :     //! \note This works for both shrinking and enlarging, as this simply
     595                 :            :     //!   translates to std::vector::resize().
     596                 :            :     void resize( std::size_t count, tk::real value, int2type< UnkEqComp > ) {
     597 [ +  - ][ +  - ]:      14973 :       m_vec.resize( count * m_nprop, value );
     598 [ +  - ][ +  - ]:      12923 :       m_nunk = count;
     599                 :            :     }
     600                 :            : 
     601                 :            :     void resize( std::size_t, tk::real, int2type< EqCompUnk > ) {
     602                 :            :       Throw( "Not implemented. It would be inefficient" );
     603                 :            :     }
     604                 :            : 
     605                 :            :     // Overloads for the name-queries of data lauouts
     606                 :            :     //! \return The name of the data layout used
     607                 :            :     //! \see A. Alexandrescu, Modern C++ Design: Generic Programming and Design
     608                 :            :     //!   Patterns Applied, Addison-Wesley Professional, 2001.
     609                 :            :     static std::string layout( int2type< UnkEqComp > )
     610 [ +  - ][ +  - ]:        190 :     { return "unknown-major"; }
     611                 :            :     static std::string layout( int2type< EqCompUnk > )
     612 [ +  - ][ +  - ]:          1 :     { return "equation-major"; }
     613                 :            : 
     614                 :            :     std::vector< tk::real > m_vec;      //!< Data pointer
     615                 :            :     ncomp_t m_nunk;                     //!< Number of unknowns
     616                 :            :     ncomp_t m_nprop;                    //!< Number of properties/unknown
     617                 :            : };
     618                 :            : 
     619                 :            : //! Operator * multiplying all items by a scalar from the left
     620                 :            : //! \param[in] lhs Scalar to multiply with
     621                 :            : //! \param[in] rhs Date object to multiply
     622                 :            : //! \return New Data object with all items multipled with lhs
     623                 :            : template< uint8_t Layout >
     624                 :      42551 : Data< Layout > operator* ( tk::real lhs, const Data< Layout >& rhs ) {
     625                 :      42551 :   return Data< Layout >( rhs ) *= lhs;
     626                 :            : }
     627                 :            : 
     628                 :            : //! Operator min between two Data objects
     629                 :            : //! \param[in] a 1st Data object
     630                 :            : //! \param[in] b 2nd Data object
     631                 :            : //! \return New Data object containing the minimum of all values for each
     632                 :            : //!   value in _a_ and _b_
     633                 :            : //! \note The Data objects _a_ and _b_ must have the same number of
     634                 :            : //!   unknowns and properties.
     635                 :            : //! \note As opposed to std::min, this function creates and returns a new object
     636                 :            : //!   instead of returning a reference to one of the operands.
     637                 :            : template< uint8_t Layout >
     638                 :          2 : Data< Layout > min( const Data< Layout >& a, const Data< Layout >& b ) {
     639                 :            :   Assert( a.nunk() == b.nunk(), "Number of unknowns unequal" );
     640                 :            :   Assert( a.nprop() == b.nprop(), "Number of properties unequal" );
     641                 :          2 :   Data< Layout > r( a.nunk(), a.nprop() );
     642                 :          2 :   std::transform( a.vec().cbegin(), a.vec().cend(),
     643                 :            :                   b.vec().cbegin(), r.vec().begin(),
     644                 :         12 :                   []( tk::real s, tk::real d ){ return std::min(s,d); } );
     645                 :            : 
     646                 :          2 :   return r;
     647                 :            : }
     648                 :            : 
     649                 :            : //! Operator max between two Data objects
     650                 :            : //! \param[in] a 1st Data object
     651                 :            : //! \param[in] b 2nd Data object
     652                 :            : //! \return New Data object containing the maximum of all values for each
     653                 :            : //!   value in _a_ and _b_
     654                 :            : //! \note The Data objects _a_ and _b_ must have the same number of
     655                 :            : //!   unknowns and properties.
     656                 :            : //! \note As opposed to std::max, this function creates and returns a new object
     657                 :            : //!   instead of returning a reference to one of the operands.
     658                 :            : template< uint8_t Layout >
     659                 :          2 : Data< Layout > max( const Data< Layout >& a, const Data< Layout >& b ) {
     660                 :            :   Assert( a.nunk() == b.nunk(), "Number of unknowns unequal" );
     661                 :            :   Assert( a.nprop() == b.nprop(), "Number of properties unequal" );
     662                 :          2 :   Data< Layout > r( a.nunk(), a.nprop() );
     663                 :          2 :   std::transform( a.vec().cbegin(), a.vec().cend(),
     664                 :            :                   b.vec().cbegin(), r.vec().begin(),
     665                 :         12 :                   []( tk::real s, tk::real d ){ return std::max(s,d); } );
     666                 :          2 :   return r;
     667                 :            : }
     668                 :            : 
     669                 :            : //! Operator == between two Data objects
     670                 :            : //! \param[in] lhs Data object to compare
     671                 :            : //! \param[in] rhs Data object to compare
     672                 :            : //! \return True if all entries are equal up to epsilon
     673                 :            : template< uint8_t Layout >
     674                 :            : bool operator== ( const Data< Layout >& lhs, const Data< Layout >& rhs ) {
     675                 :            :   Assert( rhs.nunk() == lhs.nunk(), "Incorrect number of unknowns" );
     676                 :            :   Assert( rhs.nprop() == lhs.nprop(), "Incorrect number of properties" );
     677                 :          4 :   auto l = lhs.vec().cbegin();
     678                 :          4 :   auto r = rhs.vec().cbegin();
     679 [ +  + ][ +  - ]:         32 :   while (l != lhs.vec().cend()) {
         [ +  - ][ +  + ]
         [ +  + ][ +  - ]
         [ +  - ][ +  + ]
     680 [ +  - ][ -  + ]:         28 :     if (std::abs(*l - *r) > std::numeric_limits< tk::real >::epsilon())
         [ -  + ][ +  - ]
         [ +  - ][ -  + ]
         [ -  + ][ +  - ]
     681                 :            :      return false;
     682                 :            :     ++l; ++r;
     683                 :            :   }
     684                 :            :   return true;
     685                 :            : }
     686                 :            : 
     687                 :            : //! Operator != between two Data objects
     688                 :            : //! \param[in] lhs Data object to compare
     689                 :            : //! \param[in] rhs Data object to compare
     690                 :            : //! \return True if all entries are unequal up to epsilon
     691                 :            : template< uint8_t Layout >
     692                 :            : bool operator!= ( const Data< Layout >& lhs, const Data< Layout >& rhs )
     693 [ +  - ][ +  - ]:          4 : { return !(lhs == rhs); }
         [ +  - ][ +  - ]
     694                 :            : 
     695                 :            : //! Compute the maximum difference between the elements of two Data objects
     696                 :            : //! \param[in] lhs 1st Data object
     697                 :            : //! \param[in] rhs 2nd Data object
     698                 :            : //! \return The index, i.e., the raw position, of and the largest absolute value
     699                 :            : //!   of the difference between all corresponding elements of _lhs_ and _rhs_.
     700                 :            : //! \details The position returned is the position in the underlying raw data
     701                 :            : //!   structure, independent of components, etc. If lhs == rhs with
     702                 :            : //!   precision  std::numeric_limits< tk::real >::epsilon(), a pair of (0,0.0)
     703                 :            : //!   is returned.
     704                 :            : //! \note The Data objects _lhs_ and _rhs_ must have the same number of
     705                 :            : //!   unknowns and properties.
     706                 :            : template< uint8_t Layout >
     707                 :            : std::pair< std::size_t, tk::real >
     708                 :          4 : maxdiff( const Data< Layout >& lhs, const Data< Layout >& rhs ) {
     709                 :            :   Assert( lhs.nunk() == rhs.nunk(), "Number of unknowns unequal" );
     710                 :            :   Assert( lhs.nprop() == rhs.nprop(), "Number of properties unequal" );
     711                 :          4 :   auto l = lhs.vec().cbegin();
     712                 :          4 :   auto r = rhs.vec().cbegin();
     713                 :          4 :   std::pair< std::size_t, tk::real > m( 0, std::abs(*l - *r) );
     714                 :            :   ++l; ++r;
     715         [ +  + ]:         24 :   while (l != lhs.vec().cend()) {
     716         [ +  + ]:         20 :     const auto d = std::abs(*l - *r);
     717         [ +  + ]:         20 :     if (d > m.second) m = { std::distance(lhs.vec().cbegin(),l), d };
     718                 :            :     ++l; ++r;
     719                 :            :   }
     720                 :          4 :   return m;
     721                 :            : }
     722                 :            : 
     723                 :            : } // tk::
     724                 :            : 
     725                 :            : #endif // Data_h

Generated by: LCOV version 1.14