LCOV - code coverage report
Current view: top level - tools - Random.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 85 93 91.4 %
Date: 2026-11-05 10:19:04 Functions: 10 11 90.9 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-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             : #include "Random.h"
      23             : #include <cmath>
      24             : #include <cstdlib>
      25             : #include <sstream>
      26             : #include <iostream>
      27             : #include <iterator>
      28             : 
      29             : namespace PLMD {
      30             : 
      31             : const std::string Random::noname="noname";
      32             : 
      33      813011 : Random::Random(const std::string & title):
      34      813011 :   switchGaussian(false),
      35      813011 :   saveGaussian(0.0),
      36             : // this is required because if a Random object is created during
      37             : // initialization than Random::noname could still be initialized.
      38             : // In practice: without this it is not possible to declare
      39             : // a static Random object without enforcing the order of the
      40             : // static constructors.
      41      813011 :   name(&title!=&noname?title:"noname") {
      42      813011 :   iy=0;
      43    26829363 :   for(unsigned i=0; i<NTAB; i++) {
      44    26016352 :     iv[i]=0;
      45             :   }
      46      813011 :   setSeed(0);
      47      813011 : }
      48             : 
      49      814609 : void Random::setSeed(int idum_) {
      50      814609 :   if(idum_>0) {
      51         362 :     idum_=-idum_;
      52             :   }
      53      814609 :   idum=idum_;
      54      814609 :   incPrec=false;
      55      814609 : }
      56             : 
      57     3751378 : double Random::RandU01 () {
      58     3751378 :   if (incPrec) {
      59           1 :     return U01d();
      60             :   } else {
      61     3751377 :     return U01();
      62             :   }
      63             : }
      64             : 
      65             : 
      66           2 : double Random::U01d () {
      67             :   double u;
      68           2 :   u = U01();
      69           2 :   u += U01() * fact;
      70           2 :   return (u < 1.0) ? u : (u - 1.0);
      71             : }
      72             : 
      73     7788021 : double Random::U01() {
      74             :   int j,k;
      75             :   double temp;
      76     7788021 :   if (idum <= 0 || !iy) {
      77        2123 :     if (-idum < 1) {
      78        1128 :       idum=1;
      79             :     } else {
      80         995 :       idum = -idum;
      81             :     }
      82       87043 :     for (j=NTAB+7; j>=0; j--) {
      83       84920 :       k=idum/IQ;
      84       84920 :       idum=IA*(idum-k*IQ)-IR*k;
      85       84920 :       if (idum < 0) {
      86        1238 :         idum += IM;
      87             :       }
      88       84920 :       if (j < NTAB) {
      89       67936 :         iv[j] = idum;
      90             :       }
      91             :     }
      92        2123 :     iy=iv[0];
      93             :   }
      94     7788021 :   k=idum/IQ;
      95     7788021 :   idum=IA*(idum-k*IQ)-IR*k;
      96     7788021 :   if (idum < 0) {
      97       87119 :     idum += IM;
      98             :   }
      99     7788021 :   j=iy/NDIV;
     100     7788021 :   iy=iv[j];
     101     7788021 :   iv[j] = idum;
     102     7788021 :   if ((temp=AM*iy) > RNMX) {
     103             :     return RNMX;
     104             :   } else {
     105     7788021 :     return temp;
     106             :   }
     107             : }
     108             : 
     109           1 : void Random::WriteStateFull(std::ostream & out)const {
     110             :   out<<name<<std::endl;
     111           1 :   out<<idum<<" "<<iy;
     112          33 :   for(int i=0; i<NTAB; i++) {
     113          32 :     out<<" "<<iv[i];
     114             :   };
     115           1 :   out<<" "<<switchGaussian;
     116           1 :   out<<" "<<saveGaussian;
     117             :   out<<std::endl;
     118           1 : }
     119             : 
     120           0 : void Random::ReadStateFull (std::istream & in) {
     121           0 :   getline(in,name);
     122           0 :   in>>idum>>iy;
     123           0 :   for (int i = 0; i < NTAB; i++) {
     124           0 :     in>>iv[i];
     125             :   }
     126           0 :   in>>switchGaussian;
     127           0 :   in>>saveGaussian;
     128           0 : }
     129             : 
     130           2 : void Random::toString(std::string & str)const {
     131           2 :   std::ostringstream ostr;
     132           2 :   ostr<<idum<<"|"<<iy;
     133          66 :   for(int i=0; i<NTAB; i++) {
     134          64 :     ostr<<"|"<<iv[i];
     135             :   };
     136           2 :   str=ostr.str();
     137           2 : }
     138             : 
     139           2 : void Random::fromString(const std::string & str) {
     140           2 :   std::string s=str;
     141         425 :   for(unsigned i=0; i<s.length(); i++)
     142         423 :     if(s[i]=='|') {
     143          66 :       s[i]=' ';
     144             :     }
     145           2 :   std::istringstream istr(s.c_str());
     146           2 :   istr>>idum>>iy;
     147          66 :   for (int i = 0; i < NTAB; i++) {
     148          64 :     istr>>iv[i];
     149             :   }
     150           4 : }
     151             : 
     152             : // This allows to have the same stream of random numbers
     153             : // with different compilers:
     154             : #ifdef __INTEL_COMPILER
     155             : #pragma intel optimization_level 0
     156             : #endif
     157             : 
     158     1386820 : double Random::Gaussian() {
     159             :   double v1,v2,rsq;
     160     1386820 :   if(switchGaussian) {
     161      693379 :     switchGaussian=false;
     162      693379 :     return saveGaussian;
     163             :   }
     164             :   while(true) {
     165      882469 :     v1=2.0*RandU01()-1.0;
     166      882469 :     v2=2.0*RandU01()-1.0;
     167      882469 :     rsq=v1*v1+v2*v2;
     168      882469 :     if(rsq<1.0 && rsq>0.0) {
     169             :       break;
     170             :     }
     171             :   }
     172      693441 :   double fac=std::sqrt(-2.*std::log(rsq)/rsq);
     173      693441 :   saveGaussian=v1*fac;
     174      693441 :   switchGaussian=true;
     175      693441 :   return v2*fac;
     176             : }
     177             : 
     178      360068 : void Random::Shuffle(std::vector<unsigned>& vec) {
     179             :   std::iterator_traits<std::vector<unsigned>::iterator >::difference_type i, n;
     180             :   n = vec.end() - vec.begin();
     181     1080300 :   for(i=n-1; i>0; --i) {
     182             :     // Fisher-Yates: j is drawn from [0,i]. Drawing it from [0,i-1] (Sattolo's algorithm)
     183             :     // would only produce cyclic permutations
     184      720232 :     std::swap(vec[i], vec[(int)round(RandU01() * IM) % (i+1)]);
     185             :   }
     186      360068 : }
     187             : 
     188             : 
     189             : }

Generated by: LCOV version 1.16