Xyst test code coverage report
Current view: top level - Base - ContainerUtil.hpp (source / functions) Hit Total Coverage
Commit: 5689ba12dc66a776d3d75f1ee48cc7d78eaa18dc Lines: 79 87 90.8 %
Date: 2024-11-22 19:17:03 Functions: 95 99 96.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 56 110 50.9 %

           Branch data     Line data    Source code
       1                 :            : // *****************************************************************************
       2                 :            : /*!
       3                 :            :   \file      src/Base/ContainerUtil.hpp
       4                 :            :   \copyright 2012-2015 J. Bakosi,
       5                 :            :              2016-2018 Los Alamos National Security, LLC.,
       6                 :            :              2019-2021 Triad National Security, LLC.,
       7                 :            :              2022-2024 J. Bakosi
       8                 :            :              All rights reserved. See the LICENSE file for details.
       9                 :            :   \brief     Various STL container utilities
      10                 :            :   \details   Various STL container utilities.
      11                 :            : */
      12                 :            : // *****************************************************************************
      13                 :            : #ifndef ContainerUtil_h
      14                 :            : #define ContainerUtil_h
      15                 :            : 
      16                 :            : #include <vector>
      17                 :            : #include <map>
      18                 :            : #include <set>
      19                 :            : #include <algorithm>
      20                 :            : #include <iterator>
      21                 :            : #include <unordered_set>
      22                 :            : #include <unordered_map>
      23                 :            : #include <type_traits>
      24                 :            : #include <sstream>
      25                 :            : 
      26                 :            : #include "Exception.hpp"
      27                 :            : 
      28                 :            : namespace tk {
      29                 :            : 
      30                 :            : //! Make elements of container unique (in-place, overwriting source container)
      31                 :            : //! \param[in,out] c Container
      32                 :            : template< class Container >
      33                 :            : void
      34                 :     148924 : unique( Container& c )
      35                 :            : {
      36         [ +  - ]:     148924 :   std::sort( begin(c), end(c) );
      37         [ +  - ]:     148924 :   auto it = std::unique( begin(c), end(c) );
      38         [ +  - ]:     148924 :   auto d = std::distance( begin(c), it );
      39                 :            :   // cppcheck-suppress unsignedPositive
      40 [ -  + ][ -  - ]:     148924 :   Assert( d >= 0, "Distance must be non-negative in tk::unique()" );
         [ -  - ][ -  - ]
      41         [ +  - ]:     148924 :   c.resize( static_cast< std::size_t >( d ) );
      42                 :     148924 : }
      43                 :            : 
      44                 :            : //! Make elements of container unique (on a copy, leaving the source as is)
      45                 :            : //! \param[in] src Container
      46                 :            : //! \return Container containing only unique elements compared to src
      47                 :            : template< class Container >
      48                 :            : Container
      49                 :      44255 : uniquecopy( const Container& src )
      50                 :            : {
      51                 :      44255 :   auto c = src;
      52         [ +  - ]:      44255 :   unique( c );
      53                 :      44255 :   return c;
      54                 :          0 : }
      55                 :            : 
      56                 :            : //! \brief Find and return a constant reference to value for key in container
      57                 :            : //!   that provides a find() member function with error handling
      58                 :            : //! \param[in] map Map associating values to keys
      59                 :            : //! \param[in] key Key to search for
      60                 :            : //! \return A constant reference to the value associated to the key in map
      61                 :            : //! \note If key is not found an exception is thrown.
      62                 :            : template< typename Container >
      63                 :   57190360 : auto cref_find( const Container& map, const typename Container::key_type& key )
      64                 :            : noexcept(ndebug)
      65                 :            :   -> const typename Container::mapped_type&
      66                 :            : {
      67         [ +  - ]:   57190360 :   const auto it = map.find( key );
      68                 :            :   // cppcheck-suppress throwInNoexceptFunction
      69 [ +  + ][ +  - ]:   57190360 :   Assert( it != end(map), "Can't find key" );
         [ +  - ][ +  - ]
      70                 :   57190356 :   return it->second;
      71                 :            : }
      72                 :            : 
      73                 :            : //! \brief Find and return a reference to value for key in a container that
      74                 :            : //!   provides a find() member function with error handling
      75                 :            : //! \param[in] map Map associating values to keys
      76                 :            : //! \param[in] key Key to search for
      77                 :            : //! \return A reference to the value associated to the key in map
      78                 :            : //! \note If key is not found an exception is thrown.
      79                 :            : template< typename Container >
      80                 :      33108 : auto ref_find( const Container& map, const typename Container::key_type& key )
      81                 :            : noexcept(ndebug)
      82                 :            :   -> typename Container::mapped_type&
      83                 :            : {
      84                 :            :   // cppcheck-suppress throwInNoexceptFunction
      85                 :      33108 :   return const_cast< typename Container::mapped_type& >( cref_find(map,key) );
      86                 :            : }
      87                 :            : 
      88                 :            : //! \brief Return minimum and maximum values of a vector
      89                 :            : //! \param[in] vec Vector whose extents to compute
      90                 :            : //! \return Array of two values with the minimum and maximum values
      91                 :            : //! \note This function should not be called with heavy T types, as the a copy
      92                 :            : //!   of a std::array< T, 2 > is created and returned.
      93                 :            : template< typename T >
      94                 :            : std::array< T, 2 >
      95                 :          2 : extents( const std::vector< T >& vec )
      96                 :            : {
      97         [ +  - ]:          2 :   auto x = std::minmax_element( begin(vec), end(vec) );
      98                 :          2 :   return {{ *x.first, *x.second }};
      99                 :            : }
     100                 :            : 
     101                 :            : //! \brief Find and return minimum and maximum values in associative container
     102                 :            : //! \param[in] map Map whose extents of values to find 
     103                 :            : //! \return Array of two values with the minimum and maximum values in the map
     104                 :            : //! \note This function should not be called with heavy Value types, as the a
     105                 :            : //!   copy of a std::array< Value, 2 > is created and returned.
     106                 :            : template< typename Container >
     107                 :          2 : auto extents( const Container& map )
     108                 :            :   -> std::array< typename Container::mapped_type, 2 >
     109                 :            : {
     110         [ +  - ]:          2 :   auto x = std::minmax_element( begin(map), end(map),
     111                 :          5 :              []( const auto& a, const auto& b )
     112                 :          5 :              { return a.second < b.second; } );
     113                 :          2 :   return {{ x.first->second, x.second->second }};
     114                 :            : }
     115                 :            : 
     116                 :            : //! Add all elements of an array to those of another one
     117                 :            : //! \param[in,out] dst Destination array, i.e., left-hand side of a1 += a2
     118                 :            : //! \param[in] src Source array, i.e., righ-hand side of a1 += a2
     119                 :            : //! \return Destination containing a1[0] += a2[0], a1[1] += a2[1], ...
     120                 :            : template< class T, std::size_t N >
     121                 :            : std::array< T, N >&
     122                 :          1 : operator+=( std::array< T, N >& dst, const std::array< T, N >& src ) {
     123                 :          1 :   std::transform( src.cbegin(), src.cend(), dst.begin(), dst.begin(),
     124                 :          3 :                   []( const T& s, T& d ){ return d += s; } );
     125                 :          1 :   return dst;
     126                 :            : }
     127                 :            : 
     128                 :            : //! Add all elements of a vector to those of another one
     129                 :            : //! \param[in,out] dst Destination vector, i.e., left-hand side of v1 += v2
     130                 :            : //! \param[in] src Source vector, i.e., righ-hand side of v1 += v2
     131                 :            : //! \return Destination containing v1[0] += v2[0], v1[1] += v2[1], ...
     132                 :            : //! \details If src.size() > dst.size() will grow dst to that of src.size()
     133                 :            : //!   padding with zeros.
     134                 :            : //! \note Will throw exception in DEBUG if src is empty (to warn on no-op), and
     135                 :            : //!   if src.size() < dst.size() (to warn on loosing data).
     136                 :            : template< class T, class Allocator >
     137                 :            : std::vector< T, Allocator >&
     138                 :   14103408 : operator+=( std::vector< T, Allocator >& dst,
     139                 :            :             const std::vector< T, Allocator >& src )
     140                 :            : {
     141         [ +  + ]:   14103408 :   if (src.empty()) return dst;
     142 [ +  + ][ +  - ]:   13938206 :   Assert( src.size() >= dst.size(), "src.size() < dst.size() would loose data "
         [ +  - ][ +  - ]
     143                 :            :           "in std::vector<T,Allocator>::operator+=()" );
     144                 :   13938205 :   dst.resize( src.size() );
     145                 :   13938205 :   std::transform( src.cbegin(), src.cend(), dst.begin(), dst.begin(),
     146                 :   85386105 :                   []( const T& s, T& d ){ return d += s; } );
     147                 :   13938205 :   return dst;
     148                 :            : }
     149                 :            : 
     150                 :            : //! Subtract all elements of a vector from those of another one
     151                 :            : //! \param[in,out] dst Destination vector, i.e., left-hand side of v1 -= v2
     152                 :            : //! \param[in] src Source vector, i.e., righ-hand side of v1 -= v2
     153                 :            : //! \return Destination containing v1[0] -= v2[0], v1[1] -= v2[1], ...
     154                 :            : //! \details If src.size() > dst.size() will grow dst to that of src.size()
     155                 :            : //!   padding with zeros.
     156                 :            : //! \note Will throw exception in DEBUG if src is empty (to warn on no-op), and
     157                 :            : //!   if src.size() < dst.size() (to warn on loosing data).
     158                 :            : template< class T, class Allocator >
     159                 :            : std::vector< T, Allocator >&
     160                 :       5024 : operator-=( std::vector< T, Allocator >& dst,
     161                 :            :             const std::vector< T, Allocator >& src )
     162                 :            : {
     163         [ +  + ]:       5024 :   if (src.empty()) return dst;
     164 [ +  + ][ +  - ]:       5022 :   Assert( src.size() >= dst.size(), "src.size() < dst.size() would loose data "
         [ +  - ][ +  - ]
     165                 :            :           "in std::vector<T,Allocator>::operator-=()" );
     166                 :       5021 :   dst.resize( src.size() );
     167                 :       5021 :   std::transform( src.cbegin(), src.cend(), dst.begin(), dst.begin(),
     168                 :     509655 :                   []( const T& s, T& d ){ return d -= s; } );
     169                 :       5021 :   return dst;
     170                 :            : }
     171                 :            : 
     172                 :            : //! Divide all elements of a vector with those of another one
     173                 :            : //! \param[in,out] dst Destination vector, i.e., left-hand side of v1 /= v2
     174                 :            : //! \param[in] src Source vector, i.e., righ-hand side of v1 /= v2
     175                 :            : //! \return Destination containing v1[0] /= v2[0], v1[1] /= v2[1], ...
     176                 :            : //! \details If src.size() > dst.size() will grow dst to that of src.size()
     177                 :            : //!   padding with zeros.
     178                 :            : //! \note Will throw exception in DEBUG if src is empty (to warn on no-op), and
     179                 :            : //!   if src.size() < dst.size() (to warn on loosing data).
     180                 :            : template< class T, class Allocator >
     181                 :            : std::vector< T, Allocator >&
     182                 :      11068 : operator/=( std::vector< T, Allocator >& dst,
     183                 :            :             const std::vector< T, Allocator >& src )
     184                 :            : {
     185         [ -  + ]:      11068 :   if (src.empty()) return dst;
     186 [ -  + ][ -  - ]:      11068 :   Assert( src.size() >= dst.size(), "src.size() < dst.size() would loose data "
         [ -  - ][ -  - ]
     187                 :            :           "in std::vector<T,Allocator>::operator/=()" );
     188                 :      11068 :   dst.resize( src.size() );
     189                 :      11068 :   std::transform( src.cbegin(), src.cend(), dst.begin(), dst.begin(),
     190                 :    3286604 :                   []( const T& s, T& d ){ return d /= s; } );
     191                 :      11068 :   return dst;
     192                 :            : }
     193                 :            : 
     194                 :            : //! Test if all keys of two associative containers are equal
     195                 :            : //! \param[in] a 1st container to compare
     196                 :            : //! \param[in] b 2nd container to compare
     197                 :            : //! \return True if the containers have the same size and all keys (and only the
     198                 :            : //!   keys) of the two containers are equal
     199                 :            : //! \note It is an error to call this function with unequal-size containers,
     200                 :            : //!   triggering an exception in DEBUG mode.
     201                 :            : //! \note Operator != is used to compare the container keys.
     202                 :            : template< class C1, class C2 >
     203                 :          3 : bool keyEqual( const C1& a, const C2& b ) {
     204 [ +  + ][ +  - ]:          3 :   Assert( a.size() == b.size(), "Size mismatch comparing containers" );
         [ +  - ][ +  - ]
     205                 :          2 :   std::set< typename C1::key_type > sorted_keys_of_a;
     206 [ +  - ][ +  + ]:          6 :   for (const auto& c : a) sorted_keys_of_a.insert( c.first );
     207                 :          2 :   std::set< typename C2::key_type > sorted_keys_of_b;
     208 [ +  - ][ +  + ]:          6 :   for (const auto& c : b) sorted_keys_of_b.insert( c.first );
     209         [ +  - ]:          4 :   return sorted_keys_of_a == sorted_keys_of_b;
     210                 :          2 : }
     211                 :            : 
     212                 :            : //! Compute the sum of the sizes of a container of containers
     213                 :            : //! \param[in] c Container of containers
     214                 :            : //! \return Sum of the sizes of the containers of the container
     215                 :            : template< class Container >
     216                 :       7087 : std::size_t sumsize( const Container& c ) {
     217                 :       7087 :   std::size_t sum = 0;
     218                 :            :   // cppcheck-suppress useStlAlgorithm
     219         [ +  + ]:      21261 :   for (const auto& s : c) sum += s.size();
     220                 :       7087 :   return sum;
     221                 :            : }
     222                 :            : 
     223                 :            : //! Compute the number of unique values in a container of containers
     224                 :            : //! \param[in] c Container of containers
     225                 :            : //! \return Number of unique values in a container of containers
     226                 :            : template< class Container >
     227                 :          3 : std::size_t numunique( const Container& c ) {
     228                 :            :   using value_type = typename Container::value_type::value_type;
     229                 :            :   static_assert( std::is_integral<value_type>::value,
     230                 :            :     "Container::value_type::value_type must be an integral type." );
     231                 :          3 :   std::unordered_set< value_type > u;
     232 [ +  - ][ +  + ]:          9 :   for (const auto& r : c) u.insert( begin(r), end(r) );
     233                 :          6 :   return u.size();
     234                 :          3 : }
     235                 :            : 
     236                 :            : //! Compute the sum of the sizes of the values of an associative container
     237                 :            : //! \tparam Map Container of containers type
     238                 :            : //! \param[in] c Container of containers
     239                 :            : //! \return Sum of the sizes of the values of the associative container
     240                 :            : template< class Map >
     241                 :       2480 : std::size_t sumvalsize( const Map& c ) {
     242                 :       2480 :   std::size_t sum = 0;
     243                 :            :   // cppcheck-suppress useStlAlgorithm
     244         [ +  + ]:      26968 :   for (const auto& s : c) sum += s.second.size();
     245                 :       2480 :   return sum;
     246                 :            : }
     247                 :            : 
     248                 :            : //! Free memory of a container
     249                 :            : //! \param[in] c Container defining a swap() member function
     250                 :            : //! \details See http://stackoverflow.com/a/10465032 as to why this is done with
     251                 :            : //!   the swap() member function of the container.
     252                 :            : //! \see Specializations of std::swap are documented at
     253                 :            : //!   http://en.cppreference.com/w/cpp/algorithm/swap
     254                 :            : template< class Container >
     255                 :     563003 : void destroy( Container& c ) {
     256                 :     563003 :   typename std::remove_reference< decltype(c) >::type().swap( c );
     257                 :     563003 : }
     258                 :            : 
     259                 :            : //! Remove items from container based on predicate
     260                 :            : //! \tparam Container Type of container to remove from
     261                 :            : //! \tparam Predicate Type for functor defining the predicate
     262                 :            : //! \param items Container object to remove from
     263                 :            : //! \param predicate Predicate object instance to use
     264                 :            : template< typename Container, typename Predicate >
     265                 :        245 : void erase_if( Container& items, const Predicate& predicate ) {
     266         [ +  + ]:       1617 :   for ( auto it = items.begin(); it != items.end(); ) {
     267 [ +  + ][ +  + ]:       1372 :     if ( predicate(*it) ) it = items.erase(it);
                 [ +  - ]
     268                 :        739 :     else ++it;
     269                 :            :   }
     270                 :        245 : }
     271                 :            : 
     272                 :            : //! Concatenate vectors of T
     273                 :            : //! \tparam T Vector value type
     274                 :            : //! \param[in,out] src Source vector (moved from)
     275                 :            : //! \param[in,out] dst Destination vector
     276                 :            : template< class T >
     277                 :            : void concat( std::vector< T >&& src, std::vector< T >& dst )
     278                 :            : {
     279                 :            :   Assert( dst.empty(), "Dest vector must be empty to concat" );
     280                 :            :   dst = std::move(src);
     281                 :            : }
     282                 :            : 
     283                 :            : //! Overwrite vectors of pair< bool, tk::real >
     284                 :            : //! \tparam T Vector value type
     285                 :            : //! \param[in,out] src Source vector (moved from)
     286                 :            : //! \param[in,out] dst Destination vector
     287                 :            : template< class T >
     288                 :            : void concat( std::vector< std::pair< bool, T > >&& src,
     289                 :            :              std::vector< std::pair< bool, T > >& dst )
     290                 :            : {
     291                 :            :   dst = std::move(src);
     292                 :            : }
     293                 :            : 
     294                 :            : //! Concatenate unordered sets
     295                 :            : //! \tparam Key Set key
     296                 :            : //! \tparam Hash Set hasher
     297                 :            : //! \tparam Eq Set equality operator
     298                 :            : //! \param[in,out] src Source set (moved from)
     299                 :            : //! \param[in,out] dst Destination set
     300                 :            : template< class Key,
     301                 :            :           class Hash = std::hash< Key >,
     302                 :            :           class Eq = std::equal_to< Key > >
     303                 :            : void concat( std::unordered_set< Key, Hash,Eq >&& src,
     304                 :            :              std::unordered_set< Key, Hash, Eq >& dst )
     305                 :            : {
     306                 :            :   if (dst.empty())
     307                 :            :     dst = std::move(src);
     308                 :            :   else {
     309                 :            :     dst.reserve( dst.size() + src.size() );
     310                 :            :     std::move( std::begin(src), std::end(src), std::inserter(dst,end(dst)) );
     311                 :            :     src.clear();
     312                 :            :   }
     313                 :            : }
     314                 :            : 
     315                 :            : //! Operator << for writing value_type of a standard map to output streams
     316                 :            : //! \param[in,out] os Output stream to write to
     317                 :            : //! \param[in] v value_type entry of a map
     318                 :            : //! \return Updated output stream
     319                 :            : template< class Key, class Value >
     320                 :            : std::ostream&
     321                 :            : operator<< ( std::ostream& os, const std::pair< const Key, Value  >& v ) {
     322                 :            :   os << v.first << ':' << v.second;
     323                 :            :   return os;
     324                 :            : }
     325                 :            : 
     326                 :            : //! \brief Convert and return value as string
     327                 :            : //! \tparam T Value type for input
     328                 :            : //! \param[in] v Value for input to return as a string
     329                 :            : //! \return String for input value
     330                 :            : template< typename T >
     331                 :            : std::string parameter( const T& v ) {
     332                 :            :   std::stringstream s;
     333                 :            :   s << v;
     334                 :            :   return s.str();
     335                 :            : }
     336                 :            : 
     337                 :            : //! \brief Convert and return values from container as string
     338                 :            : //! \tparam V Container range for works on
     339                 :            : //! \param[in] v Container whose components to return as a string
     340                 :            : //! \return Concatenated string of values read from a container
     341                 :            : template< typename V >
     342                 :          0 : std::string parameters( const V& v ) {
     343         [ -  - ]:          0 :   std::stringstream s;
     344         [ -  - ]:          0 :   s << "{ ";
     345 [ -  - ][ -  - ]:          0 :   for (auto p : v) s << p << ' ';
                 [ -  - ]
     346         [ -  - ]:          0 :   s << "}";
     347         [ -  - ]:          0 :   return s.str();
     348                 :          0 : }
     349                 :            : 
     350                 :            : } // tk::
     351                 :            : 
     352                 :            : #endif // ContainerUtil_h

Generated by: LCOV version 1.16