Fowler–Noll–Vo 1a (or FNV1a) non-cryptographic hash function
From the page FNV Hash by Landon Curt Noll with additional edits by jeblad (Dec 13, 2025).
The basis of the FNV hash algorithm is an idea sent as reviewer comments to the IEEE POSIX P1003.2 committee by Glenn Fowler and Phong Vo in 1991, with Landon Curt Noll improving their algorithm.
The library uses preset offset and prime, with the original offset being chongo <Landon Curt Noll> /\../\ and the prime for 32 bit set by the initial IEEE POSIX P1003.2 committee proposal.
The current implementation is meant for a specific use case, and might not be generally usable.
The hash-fnv1a library is in a single header file. Simply grab the file and put it wherever it is needed, or pull the repo as a submodule.
wget https://raw.githubusercontent.com/jeblad/hash-fnv1a/refs/heads/main/hash-fnv1a.hor
git submodule add [email protected]:jeblad/hash-fnv1a.git path-to-submoduleThe path-to-submodule would typically be something like include/hash-fnv1a if you're in the project folder.
If you're adding the hash-fnv1a as a submodule, then pull an updated version.
The most common use is to use the library to generate a hash from a string
#include "hash-fnv1a.h"
// with a non-standard prime or base the general implementation will be used
// the base will be calculated if missing
hash::FNV1a<uint32_t, 16777499ULL> fnv1a{};
// with a standard prime and base the specialization will be used
// unless it is blocked at compile time with NO_FNV_OPTIMIZATION
hash::FNV1a<uint32_t, 16777619ULL, 2166136261ULL> fnv1a{};
// then call the hash function
uint32_t result = fnv1a.hash("some string");It is possible to force the library to use ordinary multiply by setting NO_FNV_OPTIMIZATION. Otherwise, it will use bit shifts.
The testing library doctest is used during development, but it isn't part of the library as such. It is although necessary for running the tests. Likewise, the implementation in hash-fnv1a-test.cpp isn't necessary for non-development use, it is only used during tests.
The doctest library is in a single header file. Simply grab the file and put it wherever it is needed, or pull the repo as a submodule.
wget https://raw.githubusercontent.com/doctest/doctest/refs/heads/master/doctest/doctest.hor
git submodule add [email protected]:doctest/doctest.git path-to-submoduleThe path-to-submodule would typically be something like include/doctest if you're in the project folder.
If you're adding the doctest as a submodule, then pull an updated version.
The usual development cycle is to compile the test file, and then run it
# when doctest.h residews in ./include
g++ -Wall -Wextra -Werror -std=c++20 -O3 -I ./include -I ./src/ -o hash-fnv1a-test test/hash-fnv1a-test.cpp
# when doctest.h residews in an module in ./include
g++ -Wall -Wextra -Werror -std=c++20 -O3 -I ./include/doctest/doctest -I ./src/ -o hash-fnv1a-test test/hash-fnv1a-test.cppIt should be compiled with optimization level 3 to get a speedup from the bit shift multiply.
Then run the executable hash-fnv1a-test that has the actual tests.
./hash-fnv1a-testThe executable can take several arguments. Check the doctest manual for examples.