Skip to content

Commit b2bed14

Browse files
committed
[ntuple] Use newer boost_combine implementation
The previous implementation came from Boost v1.33. As explained in https://www.boost.org/doc/libs/1_81_0/libs/container_hash/doc/html/hash.html#notes_hash_combine, several improvements have been introduced until v1.81 to improve the distribution of the values and reduce the chance of collisions.
1 parent 4d228ae commit b2bed14

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

tree/ntuple/v7/inc/ROOT/RNTupleJoinTable.hxx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,18 +62,32 @@ private:
6262
}
6363
};
6464

65-
//////////////////////////////////////////////////////////////////////////
65+
/////////////////////////////////////////////////////////////////////////////
6666
/// Hash combining the individual join field value hashes from RCombinedJoinFieldValue. Uses the implementation
67-
/// from `boost::hash_combine` (see
68-
/// https://www.boost.org/doc/libs/1_55_0/doc/html/hash/reference.html#boost.hash_combine).
67+
/// from `boost::hash_combine`. See
68+
/// https://www.boost.org/doc/libs/1_87_0/libs/container_hash/doc/html/hash.html#notes_hash_combine for more
69+
/// background. In particular, it mentions: "Several improvements of the 64 bit function have been subsequently
70+
/// proposed, by [David Stafford](https://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html), [Pelle
71+
/// Evensen](https://mostlymangling.blogspot.com/2019/12/stronger-better-morer-moremur-better.html), and [Jon
72+
/// Maiga](http://jonkagstrom.com/mx3/mx3_rev2.html). We currently use Jon Maiga’s function."
6973
struct RCombinedJoinFieldValueHash {
70-
inline std::size_t operator()(const RCombinedJoinFieldValue &joinFieldValue) const
74+
inline std::size_t operator()(const RCombinedJoinFieldValue &joinFieldVal) const
7175
{
72-
std::size_t combinedHash = 0;
73-
for (const auto &fieldVal : joinFieldValue.fJoinFieldValues) {
74-
combinedHash ^= fieldVal + 0x9e3779b9 + (fieldVal << 6) + (fieldVal >> 2);
76+
std::size_t seed = 0;
77+
for (const auto &fieldVal : joinFieldVal.fJoinFieldValues) {
78+
seed ^= mix(seed + 0x9e3779b9 + fieldVal);
7579
}
76-
return combinedHash;
80+
return seed;
81+
}
82+
83+
inline std::size_t mix(std::size_t init) const
84+
{
85+
init ^= init >> 32;
86+
init *= 0xe9846af9b1a615d;
87+
init ^= init >> 32;
88+
init *= 0xe9846af9b1a615d;
89+
init ^= init >> 28;
90+
return init;
7791
}
7892
};
7993

0 commit comments

Comments
 (0)