diff --git a/src/V3Hash.h b/src/V3Hash.h index 41a81140c..6bb2963ba 100644 --- a/src/V3Hash.h +++ b/src/V3Hash.h @@ -24,40 +24,44 @@ // V3Hash -- Generic hashing class V3Hash final { - // A 32-bit hash value. A value of 0 is illegal. - uint32_t m_value; + uint32_t m_value; // The 32-bit hash value. public: + // CONSTRUCTORS + V3Hash() + : m_value{0} {} + explicit V3Hash(uint32_t val) + : m_value{val + 0x9e3779b9} {} // This is the same as 'V3Hash() + val' + explicit V3Hash(int32_t val) + : m_value{static_cast(val)} {} + explicit V3Hash(size_t val) + : m_value{static_cast(val)} {} + explicit V3Hash(const std::string& val); + // METHODS uint32_t value() const { return m_value; } // OPERATORS + // Comparisons bool operator==(const V3Hash& rh) const { return m_value == rh.m_value; } bool operator!=(const V3Hash& rh) const { return m_value != rh.m_value; } bool operator<(const V3Hash& rh) const { return m_value < rh.m_value; } - V3Hash operator+(uint32_t value) const { - const uint64_t prod = (static_cast(m_value) * 31) + value; - return V3Hash(static_cast(prod ^ (prod >> 32))); - } - V3Hash operator+(int32_t value) const { return *this + static_cast(value); } - V3Hash operator+(const V3Hash& that) const { return *this + that.m_value; } - V3Hash& operator+=(const V3Hash& that) { - *this = *this + that.m_value; - return *this; + // '+' combines hashes + V3Hash operator+(const V3Hash& that) const { + return V3Hash(m_value ^ (that.m_value + 0x9e3779b9 + (m_value << 6) + (m_value >> 2))); } + V3Hash operator+(uint32_t value) const { return *this + V3Hash(value); } + V3Hash operator+(int32_t value) const { return *this + V3Hash(value); } + V3Hash operator+(size_t value) const { return *this + V3Hash(value); } + V3Hash operator+(const std::string& value) const { return *this + V3Hash(value); } + + // '+=' combines in place + V3Hash& operator+=(const V3Hash& that) { return *this = *this + that; } V3Hash& operator+=(uint32_t value) { return *this += V3Hash(value); } V3Hash& operator+=(int32_t value) { return *this += V3Hash(value); } + V3Hash& operator+=(size_t value) { return *this += V3Hash(value); } V3Hash& operator+=(const std::string& that) { return *this += V3Hash(that); } - - // CONSTRUCTORS - V3Hash() - : m_value{1} {} - explicit V3Hash(uint32_t val) - : m_value{val | 1} {} - explicit V3Hash(int32_t val) - : m_value{static_cast(val)} {} - explicit V3Hash(const std::string& val); }; std::ostream& operator<<(std::ostream& os, const V3Hash& rhs); diff --git a/src/V3Number.cpp b/src/V3Number.cpp index f880996c1..6abe9d4ae 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -24,6 +24,7 @@ #include #include #include +#include constexpr int MAX_SPRINTF_DOUBLE_SIZE = 1100; // Maximum characters with a sprintf %e/%f/%g (really 1079) @@ -883,7 +884,11 @@ string V3Number::toString() const { return str; } -V3Hash V3Number::toHash() const { return V3Hash(m_width * (m_value[0] | 1)); } +V3Hash V3Number::toHash() const { + V3Hash hash(m_width); + for (int i = 0; i < words(); ++i) { hash += m_value[i]; } + return hash; +} uint32_t V3Number::edataWord(int eword) const { UASSERT(!isFourState(), "edataWord with 4-state " << *this);