Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-08-20 02:14:57

0001 #include "IOMC/RandomEngine/interface/TRandomAdaptor.h"
0002 #include "FWCore/Utilities/interface/EDMException.h"
0003 
0004 #include "CLHEP/Random/engineIDulong.h"
0005 
0006 #include "TBufferFile.h"
0007 
0008 #include <cstddef>
0009 #include <iomanip>
0010 #include <iostream>
0011 #include <sstream>
0012 #include <cstdint>
0013 #include <string>
0014 
0015 namespace edm {
0016 
0017   TRandomAdaptor::TRandomAdaptor() : trand_(new TRandom3()) { theSeed = trand_->GetSeed(); }
0018   TRandomAdaptor::TRandomAdaptor(long seed) : trand_(new TRandom3(seed)) { theSeed = trand_->GetSeed(); }
0019   TRandomAdaptor::TRandomAdaptor(int rowIndex, int colIndex) : trand_(new TRandom3(rowIndex * colIndex - 1)) {
0020     theSeed = trand_->GetSeed();
0021   }
0022 
0023   TRandomAdaptor::TRandomAdaptor(std::istream&) {
0024     Grumble(std::string("Cannot instantiate a TRandom engine from an istream"));
0025   }
0026 
0027   TRandomAdaptor::~TRandomAdaptor() {}
0028 
0029   std::ostream& TRandomAdaptor::put(std::ostream& os) const {
0030     Grumble(std::string("put(std::ostream) not available for TRandom engines"));
0031     return os;
0032   }
0033 
0034   std::vector<unsigned long> TRandomAdaptor::put() const {
0035     std::vector<unsigned long> v;
0036 
0037     int32_t itemSize = sizeof(uint32_t);
0038     TBufferFile buffer(TBuffer::kWrite, 2048 * itemSize);
0039     trand_->Streamer(buffer);
0040     buffer.SetReadMode();
0041     char* bufferPtr = buffer.Buffer();
0042     int32_t numItems = (buffer.Length() + itemSize - 1) / itemSize;
0043     v.reserve(numItems + 1);
0044     v.push_back(CLHEP::engineIDulong<TRandomAdaptor>());
0045     for (int i = 0; i < numItems; ++i) {
0046       // Here we do some ugly manipulations to the data to match the format
0047       // of the output of the CLHEP put function (the whole point of this adaptor
0048       // is to make TRandom3 work through the CLHEP interface as if it were a
0049       // a CLHEP engine ...).  In CLHEP, the vector returned by put contains
0050       // unsigned long's, but these always contain only 32 bits of information.
0051       // In the case of a 64 bit build the top 32 bits is only padding (all 0's).
0052 
0053       // Get the next 32 bits of data from the buffer
0054       uint32_t value32 = *reinterpret_cast<uint32_t*>(bufferPtr + i * itemSize);
0055 
0056       if (i == numItems - 1) {
0057         int nBytes = buffer.Length() % itemSize;
0058         if (nBytes == 1)
0059           value32 &= 0xffu;
0060         else if (nBytes == 2)
0061           value32 &= 0xffffu;
0062         else if (nBytes == 3)
0063           value32 &= 0xffffffu;
0064       }
0065 
0066       // Push it into the vector in an unsigned long which may be 32 or 64 bits
0067       v.push_back(static_cast<unsigned long>(value32));
0068     }
0069     return v;
0070   }
0071 
0072   void TRandomAdaptor::setSeed(long seed, int) {
0073     trand_->SetSeed(seed);
0074     theSeed = trand_->GetSeed();
0075   }
0076 
0077   // Sets the state of the algorithm according to the zero terminated
0078   // array of seeds. It is allowed to ignore one or many seeds in this array.
0079   void TRandomAdaptor::setSeeds(long const* seeds, int) {
0080     trand_->SetSeed(seeds[0]);
0081     theSeed = trand_->GetSeed();
0082   }
0083 
0084   std::istream& TRandomAdaptor::get(std::istream& is) {
0085     Grumble(std::string("get(std::istream) not available for TRandom engines"));
0086     return getState(is);
0087   }
0088 
0089   std::istream& TRandomAdaptor::getState(std::istream& is) {
0090     Grumble(std::string("getState(std::istream) not available for TRandom engines"));
0091     return is;
0092   }
0093 
0094   bool TRandomAdaptor::get(std::vector<unsigned long> const& v) {
0095     if (v.empty())
0096       return false;
0097     if (v[0] != CLHEP::engineIDulong<TRandomAdaptor>())
0098       return false;
0099     int32_t numItems = v.size() - 1;
0100 
0101     int32_t itemSize = sizeof(uint32_t);
0102     TBufferFile buffer(TBuffer::kRead, numItems * itemSize + 1024);
0103     char* bufferPtr = buffer.Buffer();
0104     for (int32_t i = 0; i < numItems; ++i) {
0105       *reinterpret_cast<uint32_t*>(bufferPtr + i * itemSize) = static_cast<uint32_t>(v[i + 1] & 0xffffffff);
0106     }
0107 
0108     // Note that this will fail if the TRandom3 version (specifically the TStreamerInfo)
0109     // has changed between the time the state was saved and the time the following call
0110     // is made.  Because we are manually calling the Streamer function, the original
0111     // TStreamerInfo is not saved anywhere. Normally ROOT saves the TStreamerInfo
0112     // automatically.
0113     trand_->Streamer(buffer);
0114 
0115     return true;
0116   }
0117 
0118   void TRandomAdaptor::Grumble(std::string const& errortext) const {
0119     // Throw an edm::Exception for unimplemented functions
0120     std::ostringstream sstr;
0121     sstr << "Unimplemented Feature: " << errortext << '\n';
0122     edm::Exception except(edm::errors::UnimplementedFeature, sstr.str());
0123     throw except;
0124   }
0125 
0126 }  // namespace edm