fourdst::libcomposition v2.3.1
Robust atomic species information library
Loading...
Searching...
No Matches
composition_hash.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstring>
4#include <vector>
5#include <bit>
6
7#include "xxhash64.h"
10
12 // Make a concept which checks if a type inherits from CompositionAbstract
13 template <typename CompT>
14 concept CompositionType = std::is_base_of_v<CompositionAbstract, CompT>;
15
17 template <CompositionType CompositionT>
18 static uint64_t hash_exact(const CompositionT& comp) {
19 uint64_t h0 = kSeed;
20 uint64_t h1 = kSeed ^ kPrime1;
21 uint64_t h2 = kSeed ^ kPrime2;
22 uint64_t h3 = kSeed ^ kPrime3;
23
24 auto it = comp.begin();
25 size_t remaining = comp.size();
26
27 while (remaining >= 4) {
28 const auto& p0 = *it;
29 ++it;
30 h0 ^= pack_species_id(p0.first);
31 h0 = mum(h0, kPrime1);
32 h0 ^= normalize_double_bits(p0.second);
33 h0 = mum(h0, kPrime2);
34
35 const auto& p1 = *it;
36 ++it;
37 h1 ^= pack_species_id(p1.first);
38 h1 = mum(h1, kPrime1);
39 h1 ^= normalize_double_bits(p1.second);
40 h1 = mum(h1, kPrime2);
41
42 const auto& p2 = *it;
43 ++it;
44 h2 ^= pack_species_id(p2.first);
45 h2 = mum(h2, kPrime1);
46 h2 ^= normalize_double_bits(p2.second);
47 h2 = mum(h2, kPrime2);
48
49 const auto& p3 = *it;
50 ++it;
51 h3 ^= pack_species_id(p3.first);
52 h3 = mum(h3, kPrime1);
53 h3 ^= normalize_double_bits(p3.second);
54 h3 = mum(h3, kPrime2);
55
56 remaining -= 4;
57 }
58
59 while (remaining > 0) {
60 const auto& p = *it;
61 ++it;
62 h0 ^= pack_species_id(p.first);
63 h0 = mum(h0, kPrime1);
64 h0 ^= normalize_double_bits(p.second);
65 h0 = mum(h0, kPrime2);
66 --remaining;
67 }
68
69 return mum(h0 ^ h1 ^ h2 ^ h3, kPrime3);
70 }
71
72 private:
73 static constexpr uint64_t kSeed = 0xC04D5EEDBEEFull;
74 static constexpr uint64_t kPrime1 = 0xa0761d6478bd642fULL;
75 static constexpr uint64_t kPrime2 = 0xe7037ed1a0b428dbULL;
76 static constexpr uint64_t kPrime3 = 0x8ebc6af09c88c6e3ULL;
77
78 // --- Helper: Fast integer mixing ---
79 static inline uint64_t mum(const uint64_t a, const uint64_t b) noexcept {
80 const unsigned __int128 r = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b);
81 return static_cast<uint64_t>(r) ^ static_cast<uint64_t>(r >> 64);
82 }
83
84 static inline uint64_t mix(const uint64_t h) noexcept {
85 return mum(h, kPrime1);
86 }
87
88 // --- Normalization Logic ---
89 static inline uint64_t normalize_double_bits(double v) noexcept {
90 if (v == 0.0) v = 0.0; // fold -0.0 -> +0.0
91 if (std::isnan(v)) {
92 return 0x7ff8000000000000ULL; // canonical quiet NaN
93 }
94 return std::bit_cast<uint64_t>(v);
95 }
96
97 static inline uint32_t pack_species_id(const auto& s) noexcept {
98 const auto z = static_cast<uint16_t>(s.z());
99 const auto a = static_cast<uint16_t>(s.a());
100 return (static_cast<uint32_t>(z) << 16) | static_cast<uint32_t>(a);
101 }
102 };
103}
104
105template<>
106struct std::hash<fourdst::composition::CompositionAbstract> {
107 std::size_t operator()(const fourdst::composition::CompositionAbstract& c) const noexcept {
108 return static_cast<std::size_t>(
110 );
111 }
112};
113template<>
114struct std::hash<fourdst::composition::Composition> {
115 std::size_t operator()(const fourdst::composition::Composition& c) const noexcept {
116 return static_cast<std::size_t>(
118 );
119 }
120};
Abstract base class for chemical composition representations.
Manages a collection of chemical species and their abundances.
Definition composition.h:99
static uint64_t normalize_double_bits(double v) noexcept
static uint32_t pack_species_id(const auto &s) noexcept
static uint64_t mix(const uint64_t h) noexcept
static uint64_t mum(const uint64_t a, const uint64_t b) noexcept
static uint64_t hash_exact(const CompositionT &comp)
std::size_t operator()(const fourdst::composition::Composition &c) const noexcept
std::size_t operator()(const fourdst::composition::CompositionAbstract &c) const noexcept