#pragma once #include #include #include #include #include #include #include #include // FNV-1a 64-bit accumulator used to fingerprint simulation state for // determinism verification (see docs/replay_design.md "Determinism"). // // Subsystems contribute their own state through appendChecksum(Hasher&) so the // hash stays close to the data it covers and no state knowledge is duplicated. // The accumulator is order-sensitive; callers fold state in a deterministic // order (sorted containers, fixed view iteration). class Hasher { public: // Folds raw bytes into the running hash. void appendBytes(const void* data, std::size_t byteCount); // Trivially-copyable scalars (ints, enums) are hashed by object representation. // Floating-point and Qt types have dedicated overloads below and bypass this. template void append(const T& value) { static_assert(std::is_trivially_copyable::value, "Hasher::append requires a trivially copyable type " "(add a dedicated overload otherwise)"); appendBytes(&value, sizeof(T)); } // Floats are hashed by bit pattern so equal values always hash equally; // negative zero is normalized so -0.0 and +0.0 collapse to one value. void append(float value); void append(double value); void append(const QPoint& point); void append(const QPointF& point); void append(const QVector2D& vector); void append(const std::string& text); std::uint64_t getValue() const { return m_state; } private: std::uint64_t m_state = 14695981039346656037ull; // FNV-1a 64-bit offset basis }; // Folds the full mt19937 internal state into a 64-bit fingerprint. mt19937 has a // portable, bit-identical text serialization, so this fingerprint is stable // across platforms (see docs/replay_design.md "Cross-platform"). std::uint64_t fingerprintRng(const std::mt19937& rng);