LCOV - code coverage report
Current view: top level - tools - View.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 26 26 100.0 %
Date: 2025-12-04 11:19:34 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2025 The plumed team
       3             :    (see the PEOPLE file at the root of the distribution for a list of names)
       4             : 
       5             :    See http://www.plumed.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       8             : 
       9             :    plumed is free software: you can redistribute it and/or modify
      10             :    it under the terms of the GNU Lesser General Public License as published by
      11             :    the Free Software Foundation, either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    plumed is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU Lesser General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU Lesser General Public License
      20             :    along with plumed.  If not, see <http://www.gnu.org/licenses/>.
      21             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      22             : #ifndef __PLUMED_tools_View_h
      23             : #define __PLUMED_tools_View_h
      24             : #include <limits>
      25             : #include <type_traits>
      26             : 
      27             : #include "Vector.h"
      28             : 
      29             : namespace PLMD {
      30             : namespace helpers {
      31             : /// A way of specifying a dynamic extent for a view
      32             : inline constexpr std::size_t dynamic_extent =
      33             :   std::numeric_limits<std::size_t>::max();
      34             : template <unsigned N, typename T> static constexpr void _zero(T *d) noexcept {
      35             :   if constexpr (N == 1) {
      36             :     d[0] = T(0);
      37             :   } else {
      38             :     _zero<N - 1>(d);
      39             :     d[N - 1] = T(0);
      40             :   }
      41             : }
      42             : } // namespace helpers
      43             : 
      44             : /**A not-owning view for generic data
      45             : 
      46             : The main idea is to have something that works like the span from c++20.
      47             : 
      48             : View are CHEAP to copy (pointer and an integer), so it is better to pass
      49             : them as values
      50             : 
      51             : Can be used from PLMD::Vectors and standard types
      52             : 
      53             : accessing the data of a PLMD::Vector as double:
      54             : @code{.cpp}
      55             : std::vector<PLMD::VecorGeneric<3>> v(3);
      56             : PLMD::View<double,3> vd(&v[0][0]);
      57             : @endcode
      58             : 
      59             : accessing the data of a PLMD::Vector as PLMD::VectorGeneric<3>:
      60             : @code{.cpp}
      61             : std::vector<PLMD::VecorGeneric<3>> v(3);
      62             : PLMD::View<PLMD::VecorGeneric<3>,3> vd(v.data());
      63             : @endcode
      64             : 
      65             : @todo  ctors from std::array and from iterators to parallel the span
      66             : implementatio
      67             : */
      68             : template <typename T, std::size_t N = helpers::dynamic_extent> class View {
      69             : public:
      70             :   using value_type = T;
      71             :   using pointer = value_type *;
      72             :   using iterator = pointer;
      73             :   using const_iterator = const pointer;
      74             :   using reference = value_type &;
      75             :   using const_reference = const value_type &;
      76             : 
      77             : private:
      78             :   pointer ptr_;
      79             :   std::size_t size_{N};
      80             : 
      81             : public:
      82             :   // constructor for fixed size View
      83             :   template <size_t NN = N,
      84             :             typename = std::enable_if_t<NN != helpers::dynamic_extent>>
      85    64787202 :   explicit View(pointer p) noexcept : ptr_(p) {}
      86             :   // generic constructor, works also for non fixed view (this might change)
      87   240391390 :   View(pointer p, std::size_t const NN) noexcept : ptr_(p), size_(NN) {}
      88             :   View(const View &) noexcept = default;
      89             :   View(View &&) noexcept = default;
      90             :   View &operator=(const View &) noexcept = default;
      91             :   View &operator=(View &&) noexcept = default;
      92             :   // returns the dimension
      93             :   constexpr size_t size() const noexcept {
      94   953325190 :     return size_;
      95             :   }
      96             : 
      97             :   /// returns the reference i-th element
      98             :   constexpr reference operator[](size_t i) noexcept {
      99  3332390651 :     return ptr_[i];
     100             :   }
     101             : 
     102             :   /// returns the reference i-th element
     103             :   constexpr const_reference operator[](size_t i) const noexcept {
     104  2005286977 :     return ptr_[i];
     105             :   }
     106             : 
     107             :   /// return the pointer to the data
     108             :   constexpr pointer data() const noexcept {
     109   175172230 :     return ptr_;
     110             :   }
     111             : 
     112             :   /// return a subview on consecutive elements
     113             :   constexpr View<value_type, helpers::dynamic_extent>
     114             :   subview(size_t offset,
     115             :           size_t count = helpers::dynamic_extent) const noexcept {
     116             :     /// @TODO: enforce these or accept the risk of undefined behaviour in
     117             :     /// exchange for performance
     118             :     // assert(offset <= size(), "subview: offset out of range");
     119             :     // if (count != helpers::dynamic_extent) {
     120             :     //   assert(count <= (size()-offset), "subview: count out of range");
     121             :     // }
     122         256 :     return {data() + offset,
     123         256 :             count != helpers::dynamic_extent ? count : size() - offset};
     124             :   }
     125             : 
     126             :   /// return a subview on consecutive elements
     127             :   template <size_t Offset, size_t Count = helpers::dynamic_extent>
     128             :   constexpr auto subview() const noexcept {
     129             :     // I am more or less implementing the subspan form the std
     130             :     constexpr size_t FinalExtent =
     131             :       (Count != helpers::dynamic_extent)
     132             :       ? Count
     133             :       : (N != helpers::dynamic_extent ? N - Offset
     134             :          : helpers::dynamic_extent);
     135             :     static_assert(Offset <= N, "subview: offset out of range");
     136             :     if constexpr (Count != helpers::dynamic_extent) {
     137             :       static_assert(Count <= (N - Offset), "subview: count out of range");
     138             :     }
     139             :     return View<T, FinalExtent> {
     140             :       data() + Offset,
     141             :       Count != helpers::dynamic_extent ? Count : size() - Offset
     142             :     };
     143             :   }
     144             : 
     145             :   /// return a subview of specific size consecutive elements
     146             :   template <size_t Count>
     147             :   constexpr View<value_type, Count> subview_n(size_t offset) const noexcept {
     148             :     /// @TODO: enforce these or accept the risk of undefined behaviour in
     149             :     /// exchange for performance
     150             :     // assert(offset <= size(), "subview: offset out of range");
     151             :     // if (count != helpers::dynamic_extent) {
     152             :     //   assert(count <= (size()-offset), "subview: count out of range");
     153             :     // }
     154             :     static_assert(Count <= N, "subview: count out of range");
     155    16004493 :     return View<value_type, Count> {data() + offset};
     156             :   }
     157             : 
     158             :   constexpr iterator begin() noexcept {
     159             :     return ptr_;
     160             :   }
     161             : 
     162             :   constexpr const_iterator begin() const noexcept {
     163             :     return ptr_;
     164             :   }
     165             : 
     166             :   constexpr const_iterator cbegin() const noexcept {
     167             :     return ptr_;
     168             :   }
     169             : 
     170             :   constexpr iterator end() noexcept {
     171    15750174 :     return ptr_ + size_;
     172             :   }
     173             : 
     174             :   constexpr const_iterator end() const noexcept {
     175      119236 :     return ptr_ + size_;
     176             :   }
     177             : 
     178             :   constexpr const_iterator cend() const noexcept {
     179             :     return ptr_ + size_;
     180             :   }
     181             : 
     182           2 :   void zero() noexcept {
     183             :     if constexpr (N != helpers::dynamic_extent) {
     184           2 :       LoopUnroller<N>::_zero(ptr_);
     185             :     } else {
     186             :       for (unsigned i = 0; i < size_; ++i) {
     187             :         ptr_[i] = T(0);
     188             :       }
     189             :     }
     190           2 :   }
     191             : 
     192             :   /// assignment from a PLMD::VectorTyped of the same type
     193             :   template <size_t M = N, typename VT, unsigned VD,
     194             :             typename = std::enable_if_t<
     195             :               M >= VD && std::is_same_v<T, std::remove_const_t<VT>>>>
     196             :   auto &operator=(const VectorTyped<VT, VD> &v) noexcept {
     197             :     // NOTE: if N==dynamic_extent and size_<VD, this is UB
     198      946046 :     PLMD::LoopUnroller<VD>::_copy(ptr_, v.data());
     199             :     return *this;
     200             :   }
     201             : 
     202             :   /// assignment from a PLMD::VectorTyped explicitly request an eventual
     203             :   /// conversion
     204             :   template <size_t M = N, typename VT, unsigned VD,
     205             :             typename = std::enable_if_t<M >= VD>>
     206             :   auto &copyConv(const VectorTyped<VT, VD> &v) noexcept {
     207             :     // NOTE: if N==dynamic_extent and size_<VD, this is UB
     208             :     PLMD::LoopUnroller<VD>::_copy(ptr_, v.data());
     209             :     return *this;
     210             :   }
     211             : 
     212             :   template <size_t M = N, typename VT, unsigned VD,
     213             :             typename = std::enable_if_t<
     214             :               M >= VD && std::is_same_v<T, std::remove_const_t<VT>>>>
     215    13731677 :   auto &operator+=(const VectorTyped<VT, VD> &v) noexcept {
     216             :     // NOTE: if N==dynamic_extent and size_<VD, this is UB
     217    13731677 :     PLMD::LoopUnroller<VD>::_add(ptr_, v.data());
     218    13731677 :     return *this;
     219             :   }
     220             : 
     221             :   template <size_t M = N, typename VT, unsigned VD,
     222             :             typename = std::enable_if_t<
     223             :               M >= VD && std::is_same_v<T, std::remove_const_t<VT>>>>
     224    13731677 :   auto &operator-=(const VectorTyped<VT, VD> &v) noexcept {
     225             :     // NOTE: if N==dynamic_extent and size_<VD, this is UB
     226    13731677 :     PLMD::LoopUnroller<VD>::_sub(ptr_, v.data());
     227    13731677 :     return *this;
     228             :   }
     229             : 
     230     1012170 :   template <typename TT> auto &operator*=(const TT v) noexcept {
     231             :     if constexpr (N != helpers::dynamic_extent) {
     232     1012170 :       PLMD::LoopUnroller<N>::_mul(ptr_, v);
     233             :     } else {
     234             :       for (unsigned i = 0; i < size_; ++i) {
     235             :         ptr_[i] *= v;
     236             :       }
     237             :     }
     238     1012170 :     return *this;
     239             :   }
     240             : 
     241             :   template <typename TT> auto &operator/=(const TT v) noexcept {
     242             :     return operator*=(T(1.0) / v);
     243             :   }
     244             :   // some mathematical helper operations
     245             :   // summed as double for precision concerns, maybe it is paranoid, maybe not
     246             :   double modulo2() const noexcept {
     247             :     if constexpr (N != helpers::dynamic_extent) {
     248             :       return LoopUnroller<N>::_sum2(ptr_);
     249             :     } else {
     250             :       double sum = 0.0;
     251             :       for (unsigned i = 0; i < size_; ++i) {
     252             :         sum += ptr_[i] * ptr_[i];
     253             :       }
     254             :       return sum;
     255             :     }
     256             :   }
     257             : 
     258             :   double modulo() const noexcept {
     259             :     return sqrt(modulo2());
     260             :     ;
     261             :   }
     262             : };
     263             : 
     264             : template <typename T>
     265     2261983 : VectorTyped<std::remove_const_t<T>, 3> delta(const View<T, 3> v1,
     266             :     const View<T, 3> v2) noexcept {
     267             :   // removing the const will improve some code interactions
     268             :   return VectorTyped<std::remove_const_t<T>, 3> {
     269             :     v2[0] - v1[0],
     270             :     v2[1] - v1[1],
     271             :     v2[2] - v1[2]
     272     2261983 :   };
     273             : }
     274             : 
     275             : ///Returns a complete dynamic view of a container
     276             : ///
     277             : ///The container must have defined the methods `data()` and `size()`
     278             : ///Also the container must have defined a public type `value_type`
     279             : ///For example a std::vector is compatible
     280             : ///A const std::vector is not compatible with this signature, to avoid confusion
     281             : template <typename CT>
     282             : constexpr View<typename CT::value_type> make_view(CT& container) {
     283             :   return {container.data(),container.size()};
     284             : }
     285             : 
     286             : ///Returns a complete constant dynamic view of a container
     287             : ///
     288             : ///The container must have defined the methods `data()` and `size()`
     289             : ///Also the container must have defined a public type `value_type`
     290             : ///For example a std::vector is compatible
     291             : template <typename CT>
     292             : constexpr View<const typename CT::value_type> make_const_view(const CT& container) {
     293             :   return {container.data(),container.size()};
     294             : }
     295             : } // namespace PLMD
     296             : #endif // __PLUMED_tools_View_h

Generated by: LCOV version 1.16