This is one of the possible ways to prepare a hashing mechanism to use a custom object in a std::unordered_map
container.
It has been preferred here to use a new struct
instead of injecting a specialization into the std
namespace, because we are here in the smash
namespace and the object is going to be possibly better localized. Since the hash is not trivial, we also preferred this approach to using a lambda function to declare the hashing function.
Definition at line 101 of file clebschgordan_lookup.h.
Public Member Functions | |
std::size_t | operator() (const ThreeSpins &in) const noexcept |
The overload of the operator() is the only needed ingredient to make this class ready to be used as hashing algorithm. More... | |
|
inlinenoexcept |
The overload of the operator()
is the only needed ingredient to make this class ready to be used as hashing algorithm.
Since there is not (yet) a C++ standard way of combining hashes, to implement functions like this one, it is necessary to choose a hashing algorithm. The algorithm should minimize the hash collision (different input giving the same output), but at the same time be as fast as possible. One could use boost library approach, which defines
as function to combine hashes. Then this should be used here on each in
member to produce the final hash. Although it has been tested to work, there is a simpler approach.
ThreeSpins
members are numbers smaller than 16 (in absolute value). Hence 5 bits are enough to represent them (numbers between -16 and 15). Using bit-shift operations, it is then possible to build a bit-sequence that in its last 6*5=30 bits contains the 6 integer information, appropriately "converted" to 5-bit sequences that are then concatenated.int
as a 5 bits integer into a std::size_t
variable, one way is to cast to it first and then get rid of all but 5 rightmost bits. If e.g. the result variable is 64 bits large, this means to bit-shift to the left by 64-5=59 positions and then again to the right to bring the 5 bits back to the least significant positions (this is only an example, since the size of std::size_t
is architecture dependent).std::size_t
variables, these can be combined shifting them to the left in a way that the 5 relevant bits do not "overlap" (i.e. occupy different positions) and then summing them. In the implementation we use the minimum needed shift, i.e. having N=6 numbers we shift the first number by (N-1)*5, the second by (N-2)*5 and so on till the last one that does not get shifted. Since both the cast to "5-bits" numbers and the preparation of the sum involve bit-shifts, these are combined together.std::bitset
would probably make the code easier to read, but it has been benchmarked to be some % slower at low energies.in | The spin information (meant to be used as input to be hashed) |
std::size_t
The calculated hash value Definition at line 163 of file clebschgordan_lookup.h.