LCOV - code coverage report
Current view: top level - tools - LoopUnroller.h (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 31 31 100.0 %
Date: 2024-10-11 08:09:47 Functions: 52 52 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             : template<unsigned n>
      51             : class LoopUnroller {
      52             : public:
      53             : /// Set to zero.
      54             : /// Same as `for(unsigned i=0;i<n;i++) d[i]=0.0;`
      55             :   static void _zero(double*d);
      56             : /// Add v to d.
      57             : /// Same as `for(unsigned i=0;i<n;i++) d[i]+=v[i];`
      58             :   static void _add(double*d,const double*v);
      59             : /// Subtract v from d.
      60             : /// Same as `for(unsigned i=0;i<n;i++) d[i]-=v[i];`
      61             :   static void _sub(double*d,const double*v);
      62             : /// Multiply d by s.
      63             : /// Same as `for(unsigned i=0;i<n;i++) d[i]*=s;`
      64             :   static void _mul(double*d,const double s);
      65             : /// Set d to -v.
      66             : /// Same as `for(unsigned i=0;i<n;i++) d[i]=-v[i];`
      67             :   static void _neg(double*d,const double*v);
      68             : /// Squared modulo of d;
      69             : /// Same as `r=0.0; for(unsigned i=0;i<n;i++) r+=d[i]*d[i]; return r;`
      70             :   static double _sum2(const double*d);
      71             : /// Dot product of d and v
      72             : /// Same as `r=0.0; for(unsigned i=0;i<n;i++) r+=d[i]*v[i]; return r;`
      73             :   static double _dot(const double*d,const double*v);
      74             : };
      75             : 
      76             : template<unsigned n>
      77  1454755214 : void LoopUnroller<n>::_zero(double*d) {
      78   911070975 :   LoopUnroller<n-1>::_zero(d);
      79  1454755214 :   d[n-1]=0.0;
      80  1454755214 : }
      81             : 
      82             : template<>
      83             : inline
      84             : void LoopUnroller<1>::_zero(double*d) {
      85   544233159 :   d[0]=0.0;
      86             : }
      87             : 
      88             : template<unsigned n>
      89  3584322848 : void LoopUnroller<n>::_add(double*d,const double*a) {
      90  1919431930 :   LoopUnroller<n-1>::_add(d,a);
      91  3584322848 :   d[n-1]+=a[n-1];
      92  3584322848 : }
      93             : 
      94             : template<>
      95             : inline
      96             : void LoopUnroller<1>::_add(double*d,const double*a) {
      97  1664890918 :   d[0]+=a[0];
      98             : }
      99             : 
     100             : template<unsigned n>
     101  2475070414 : void LoopUnroller<n>::_sub(double*d,const double*a) {
     102  1378467806 :   LoopUnroller<n-1>::_sub(d,a);
     103  2475070414 :   d[n-1]-=a[n-1];
     104  2475070414 : }
     105             : 
     106             : template<>
     107             : inline
     108             : void LoopUnroller<1>::_sub(double*d,const double*a) {
     109  1096602608 :   d[0]-=a[0];
     110             : }
     111             : 
     112             : template<unsigned n>
     113  4553354452 : void LoopUnroller<n>::_mul(double*d,const double s) {
     114  2739280337 :   LoopUnroller<n-1>::_mul(d,s);
     115  4553354452 :   d[n-1]*=s;
     116  4553354452 : }
     117             : 
     118             : template<>
     119             : inline
     120             : void LoopUnroller<1>::_mul(double*d,const double s) {
     121  1814074115 :   d[0]*=s;
     122             : }
     123             : 
     124             : template<unsigned n>
     125   212690122 : void LoopUnroller<n>::_neg(double*d,const double*a ) {
     126   106534958 :   LoopUnroller<n-1>::_neg(d,a);
     127   212690122 :   d[n-1]=-a[n-1];
     128   212690122 : }
     129             : 
     130             : template<>
     131             : inline
     132             : void LoopUnroller<1>::_neg(double*d,const double*a) {
     133   106155164 :   d[0]=-a[0];
     134             : }
     135             : 
     136             : template<unsigned n>
     137  1480667744 : double LoopUnroller<n>::_sum2(const double*d) {
     138  1480667744 :   return LoopUnroller<n-1>::_sum2(d)+d[n-1]*d[n-1];
     139             : }
     140             : 
     141             : template<>
     142             : inline
     143             : double LoopUnroller<1>::_sum2(const double*d) {
     144   739774321 :   return d[0]*d[0];
     145             : }
     146             : 
     147             : template<unsigned n>
     148   332627812 : double LoopUnroller<n>::_dot(const double*d,const double*v) {
     149   332627812 :   return LoopUnroller<n-1>::_dot(d,v)+d[n-1]*v[n-1];
     150             : }
     151             : 
     152             : template<>
     153             : inline
     154             : double LoopUnroller<1>::_dot(const double*d,const double*v) {
     155   166313906 :   return d[0]*v[0];
     156             : }
     157             : 
     158             : }
     159             : 
     160             : #endif

Generated by: LCOV version 1.15