From 9fc9ff1bf952850401783a42083213885027b318 Mon Sep 17 00:00:00 2001 From: ralfulrich <ralf.ulrich@kit.edu> Date: Fri, 2 Oct 2020 22:15:37 +0200 Subject: [PATCH] added a hash as member of NuclearComposition, so that it can be used as unique map-key etc. --- Environment/NuclearComposition.h | 24 +++++++++++++++++++++++ Processes/Proposal/ContinuousProcess.cc | 6 +++--- Processes/Proposal/ProposalProcessBase.cc | 7 +++---- Processes/Proposal/ProposalProcessBase.h | 8 ++++---- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Environment/NuclearComposition.h b/Environment/NuclearComposition.h index 596302609..3e45513a4 100644 --- a/Environment/NuclearComposition.h +++ b/Environment/NuclearComposition.h @@ -18,6 +18,8 @@ #include <stdexcept> #include <vector> + + namespace corsika::environment { class NuclearComposition { std::vector<float> const fNumberFractions; //!< relative fractions of number density @@ -26,6 +28,8 @@ namespace corsika::environment { double const fAvgMassNumber; + std::size_t hash_; + template <class AConstIterator, class BConstIterator> class WeightProviderIterator { AConstIterator fAIter; @@ -77,6 +81,7 @@ namespace corsika::environment { if (!(0.999f < sumFractions && sumFractions < 1.001f)) { throw std::runtime_error("element fractions do not add up to 1"); } + updateHash(); } template <typename TFunction> @@ -125,6 +130,25 @@ namespace corsika::environment { auto const iChannel = channelDist(randomStream); return fComponents[iChannel]; } + + // Note: when this class ever modifies its internal data, the hash + // must be updated, too! + size_t hash() const { return hash_; } + + private: + void updateHash() const { + std::vector<std::size_t> hashes; + for (float ifrac : GetFractions()) + hashes.push_back(std::hash<float>{}(ifrac)); + for (corsika::particles::Code icode : GetComponents()) + hashes.push_back(std::hash<int>{}(static_cast<int>(icode))); + std::size_t h = std::hash<double>{}(GetAverageMassNumber()); + for (std::size_t ih : hashes) + h = h ^ (ih<<1); + hash_ = h; + } + }; } // namespace corsika::environment + diff --git a/Processes/Proposal/ContinuousProcess.cc b/Processes/Proposal/ContinuousProcess.cc index 7ceb75b47..ef1216788 100644 --- a/Processes/Proposal/ContinuousProcess.cc +++ b/Processes/Proposal/ContinuousProcess.cc @@ -30,14 +30,14 @@ namespace corsika::process::proposal { // interpolate the crosssection for given media and energy cut. These may // take some minutes if you have to build the tables and cannot read the // from disk - auto c = p_cross->second(media.at(&comp), emCut_); + auto c = p_cross->second(media.at(comp.hash()), emCut_); // Build displacement integral and scattering object and interpolate them too and // saved in the calc map by a key build out of a hash of composed of the component and // particle code. auto disp = PROPOSAL::make_displacement(c, true); - auto scatter = PROPOSAL::make_scattering("highland", particle[code], media.at(&comp)); - calc[std::make_pair(&comp, code)] = + auto scatter = PROPOSAL::make_scattering("highland", particle[code], media.at(comp.hash())); + calc[std::make_pair(comp.hash(), code)] = std::make_tuple(std::move(disp), std::move(scatter)); } diff --git a/Processes/Proposal/ProposalProcessBase.cc b/Processes/Proposal/ProposalProcessBase.cc index 0211b4788..3d1bd1e98 100644 --- a/Processes/Proposal/ProposalProcessBase.cc +++ b/Processes/Proposal/ProposalProcessBase.cc @@ -43,7 +43,7 @@ namespace corsika::process::proposal { *frac_iter); ++frac_iter; } - media[ncarg] = PROPOSAL::Medium( + media[ncarg->hash()] = PROPOSAL::Medium( "Modified Air", PROPOSAL::Air().GetI(), PROPOSAL::Air().GetC(), PROPOSAL::Air().GetA(), PROPOSAL::Air().GetM(), PROPOSAL::Air().GetX0(), PROPOSAL::Air().GetX1(), PROPOSAL::Air().GetD0(), 1.0, comp_vec); @@ -64,10 +64,9 @@ namespace corsika::process::proposal { "table directory. "); } } - + size_t ProposalProcessBase::hash::operator()(const calc_key_t& p) const noexcept { - return std::hash<const environment::NuclearComposition*>{}(p.first) ^ - std::hash<particles::Code>{}(p.second); + return p.first ^ std::hash<particles::Code>{}(p.second); } } // namespace corsika::process::proposal diff --git a/Processes/Proposal/ProposalProcessBase.h b/Processes/Proposal/ProposalProcessBase.h index b1696526a..82d833022 100644 --- a/Processes/Proposal/ProposalProcessBase.h +++ b/Processes/Proposal/ProposalProcessBase.h @@ -73,7 +73,7 @@ namespace corsika::process::proposal { //!< will be handeled continuously. corsika::random::RNG& fRNG; //!< random number generator used by proposal - std::unordered_map<const environment::NuclearComposition*, PROPOSAL::Medium> + std::unordered_map<std::size_t, PROPOSAL::Medium> media; //!< maps nuclear composition from univers to media to produce //!< crosssections, which requires further ionization constants. @@ -89,7 +89,7 @@ namespace corsika::process::proposal { //! bool CanInteract(particles::Code pcode) const; - using calc_key_t = std::pair<const environment::NuclearComposition*, particles::Code>; + using calc_key_t = std::pair<std::size_t, particles::Code>; //! //! Hash to store interpolation tables related to a pair of particle and nuclear @@ -112,8 +112,8 @@ namespace corsika::process::proposal { //! template <typename Particle, typename Calculators> auto GetCalculator(Particle& vP, Calculators& calc) { - auto& comp = vP.GetNode()->GetModelProperties().GetNuclearComposition(); - auto calc_it = calc.find(std::make_pair(&comp, vP.GetPID())); + const auto& comp = vP.GetNode()->GetModelProperties().GetNuclearComposition(); + auto calc_it = calc.find(std::make_pair(comp.hash(), vP.GetPID())); if (calc_it != calc.end()) return calc_it; BuildCalculator(vP.GetPID(), comp); return GetCalculator(vP, calc); -- GitLab