LCOV - code coverage report
Current view: top level - tools - LoopUnroller.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 24 24 100.0 %
Date: 2026-11-05 10:19:04 Functions: 25 25 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2015-2023 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_LoopUnroller_h
      23             : #define __PLUMED_tools_LoopUnroller_h
      24             : 
      25             : namespace PLMD {
      26             : 
      27             : /**
      28             : \ingroup TOOLBOX
      29             : Utiliy class for loop unrolling.
      30             : 
      31             : Many c++ compilers do not unroll small loops such as those
      32             : used in the PLMD::Vector and PLMD::Tensor classes.
      33             : This class provides methods to perform basic vector
      34             : operations with unrolled loops. The methods work on double*
      35             : so that they can be used in principles in other places of the code,
      36             : but they are designed to be used in PLMD::Vector and PLMD::Tensor .
      37             : 
      38             : In case in the future we see that some compiler better optimize explicit loops,
      39             : it should be easy to replace the methods here with loops. Alternatively,
      40             : we could provide two paths using a cpp macro (e.g. __PLUMED_UNROLL_LOOPS or so).
      41             : 
      42             : All the methods for class LoopUnroller<n> act on n elements.
      43             : Implementation is made using template metaprogramming, that is:
      44             : - LoopUnroller<1>::xxx acts on the element [0] of the array.
      45             : - LoopUnroller<n>::xxx calls LoopUnroller<n-1>::xxx then acts on element [n-1] of the array.
      46             : 
      47             : Here xxx is any of the methods of the class.
      48             : 
      49             : */
      50             : //the typename is the second parameter argument so that it can be deduced
      51             : template<unsigned n>
      52             : class LoopUnroller {
      53             : public:
      54             : /// Set to zero.
      55             : /// Same as `for(unsigned i=0;i<n;i++) d[i]=0.0;`
      56             :   template<typename T>
      57             :   static constexpr void _zero(T*d) noexcept;
      58             : /// copy the content o v into v
      59             : /// Same as `for(unsigned i=0;i<n;i++) d[i]=v[i];`
      60             :   template<typename T,typename TT>
      61             :   static constexpr void _copy(T*d,TT const*v) noexcept;
      62             : /// Add v to d.
      63             : /// Same as `for(unsigned i=0;i<n;i++) d[i]+=v[i];`
      64             :   template<typename T,typename TT>
      65             :   static constexpr void _add(T*d,TT const*v) noexcept;
      66             : /// Subtract v from d.
      67             : /// Same as `for(unsigned i=0;i<n;i++) d[i]-=v[i];`
      68             :   template<typename T,typename TT>
      69             :   static constexpr void _sub(T*d,TT const*v) noexcept;
      70             : /// Multiply d by s.
      71             : /// Same as `for(unsigned i=0;i<n;i++) d[i]*=s;`
      72             :   template<typename T,typename TT>
      73             :   static constexpr void _mul(T*d,TT const s) noexcept;
      74             : /// Set d to -v.
      75             : /// Same as `for(unsigned i=0;i<n;i++) d[i]=-v[i];`
      76             :   template<typename T,typename TT>
      77             :   static constexpr void _neg(T*d,TT const*v) noexcept;
      78             : /// Squared modulo of d;
      79             : /// Same as `r=0.0; for(unsigned i=0;i<n;i++) r+=d[i]*d[i]; return r;`
      80             :   template<typename T>
      81             :   static constexpr T _sum2(T const*d) noexcept;
      82             : /// Dot product of d and v
      83             : /// Same as `r=0.0; for(unsigned i=0;i<n;i++) r+=d[i]*v[i]; return r;`
      84             :   template<typename T,typename TT>
      85             :   static constexpr T _dot(T const*d,TT const*v) noexcept;
      86             : };
      87             : 
      88             : template<unsigned n>
      89             : template<typename T>
      90             : constexpr void LoopUnroller<n>::_zero(T*d) noexcept {
      91             :   if constexpr (n>1) {
      92             :     LoopUnroller<n-1>::_zero(d);
      93             :   }
      94    91811603 :   d[n-1]=T(0);
      95             : }
      96             : 
      97             : template<unsigned n>
      98             : template<typename T,typename TT>
      99             : constexpr void LoopUnroller<n>::_copy(T*d,TT const*v) noexcept {
     100             :   if constexpr (n==1) {
     101    10243480 :     d[0]=v[0];
     102             :   } else {
     103             :     LoopUnroller<n-1>::_copy(d,v);
     104    12999027 :     d[n-1]=v[n-1];
     105             :   }
     106             : }
     107             : 
     108             : template<unsigned n>
     109             : template<typename T, typename TT>
     110   194884753 : constexpr void LoopUnroller<n>::_add(T*d,TT const*a) noexcept {
     111             :   if constexpr (n>1) {
     112   191280783 :     LoopUnroller<n-1>::_add(d,a);
     113             :   }
     114   855927476 :   d[n-1]+=a[n-1];
     115   194884753 : }
     116             : 
     117             : template<unsigned n>
     118             : template<typename T, typename TT>
     119   222652113 : constexpr void LoopUnroller<n>::_sub(T*d,TT const*a) noexcept {
     120             :   if constexpr (n>1) {
     121   205512363 :     LoopUnroller<n-1>::_sub(d,a);
     122             :   }
     123  1234230135 :   d[n-1]-=a[n-1];
     124   222652113 : }
     125             : 
     126             : template<unsigned n>
     127             : template<typename T, typename TT>
     128   346824563 : constexpr void LoopUnroller<n>::_mul(T*d,TT const s) noexcept {
     129             :   if constexpr (n>1) {
     130   268489730 :     LoopUnroller<n-1>::_mul(d,s);
     131             :   }
     132  1317425574 :   d[n-1]*=s;
     133   346824563 : }
     134             : 
     135             : template<unsigned n>
     136             : template<typename T, typename TT>
     137     9516933 : constexpr void LoopUnroller<n>::_neg(T*d,TT const*a ) noexcept {
     138             :   if constexpr (n>1) {
     139     7897682 :     LoopUnroller<n-1>::_neg(d,a);
     140             :   }
     141    26449899 :   d[n-1]=-a[n-1];
     142     9516933 : }
     143             : 
     144             : template<unsigned n>
     145             : template<typename T>
     146             : constexpr T LoopUnroller<n>::_sum2(T const*d) noexcept {
     147             :   if constexpr (n>1) {
     148  1120135149 :     return LoopUnroller<n-1>::_sum2(d)+d[n-1]*d[n-1];
     149             :   } else {
     150   785234731 :     return d[0]*d[0];
     151             :   }
     152             : }
     153             : template<unsigned n>
     154             : template<typename T, typename TT>
     155   141913330 : constexpr T LoopUnroller<n>::_dot(T const*d,TT const*v) noexcept {
     156             :   if constexpr (n>1) {
     157   377211732 :     return LoopUnroller<n-1>::_dot(d,v)+d[n-1]*v[n-1];
     158             :   } else {
     159   264277052 :     return d[0]*v[0];
     160             :   }
     161             : }
     162             : } //PLMD
     163             : #endif //__PLUMED_tools_LoopUnroller_h

Generated by: LCOV version 1.16