├── .clang-format ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── meson.build ├── src ├── t1ha0.c ├── t1ha0_ia32aes_a.h ├── t1ha0_ia32aes_avx.c ├── t1ha0_ia32aes_avx2.c ├── t1ha0_ia32aes_b.h ├── t1ha0_ia32aes_noavx.c ├── t1ha0_selfcheck.c ├── t1ha1.c ├── t1ha1_selfcheck.c ├── t1ha2.c ├── t1ha2_selfcheck.c ├── t1ha_bits.h ├── t1ha_selfcheck.c ├── t1ha_selfcheck.h └── t1ha_selfcheck_all.c ├── t1ha-dll.vcxproj ├── t1ha-static.vcxproj ├── t1ha-test.vcxproj ├── t1ha.creator ├── t1ha.files ├── t1ha.h ├── t1ha.sln └── tests ├── 4bench_t1ha0_ia32aes_avx.c ├── 4bench_t1ha0_ia32aes_avx2.c ├── 4bench_t1ha0_ia32aes_noavx.c ├── bench.c ├── common.h ├── highwayhash ├── 4bench_avx2.cc ├── 4bench_portable.cc ├── 4bench_sse41.cc ├── 4bench_vsx.cc ├── arch_specific.cc ├── arch_specific.h ├── compiler_specific.h ├── endianess.h ├── hh_avx2.cc ├── hh_avx2.h ├── hh_buffer.h ├── hh_portable.cc ├── hh_portable.h ├── hh_sse41.cc ├── hh_sse41.h ├── hh_types.h ├── hh_vsx.cc ├── hh_vsx.h ├── highwayhash.h ├── highwayhash_target.cc ├── highwayhash_target.h ├── iaca.h ├── load3.h ├── pure_c.c ├── pure_c.h ├── vector128.h ├── vector256.h └── verifier.c ├── main.c ├── mera.c ├── mera.h ├── stadtx ├── LICENSE ├── stadtx_hash.h └── stadtx_thunk.c ├── test.c ├── wyhash ├── LICENSE ├── README.md ├── wyhash.h └── wyhash_thunk.c └── xxhash ├── xxh3.h ├── xxh_thunk.c ├── xxhash.c └── xxhash.h /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | Standard: Cpp11 3 | ReflowComments: true 4 | ColumnLimit: 80 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | *.o 3 | *.s 4 | *.i 5 | *.a 6 | *.so 7 | ARM/ 8 | ARM64/ 9 | Win32/ 10 | t1ha-dll.VC.db 11 | t1ha-static.VC.db 12 | t1ha-test.VC.db 13 | t1ha.VC.VC.opendb 14 | t1ha.VC.db 15 | t1ha.config 16 | t1ha.creator.user 17 | t1ha.includes 18 | t1ha0_ia32aes_avx.bc 19 | t1ha0_ia32aes_noavx.bc 20 | test 21 | x64/ 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | zlib License, see https://en.wikipedia.org/wiki/Zlib_License 2 | 3 | Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 4 | Fast Positive Hash. 5 | 6 | Portions Copyright (c) 2010-2013 Leonid Yuriev , 7 | The 1Hippeus project (t1h). 8 | 9 | This software is provided 'as-is', without any express or implied 10 | warranty. In no event will the authors be held liable for any damages 11 | arising from the use of this software. 12 | 13 | Permission is granted to anyone to use this software for any purpose, 14 | including commercial applications, and to alter it and redistribute it 15 | freely, subject to the following restrictions: 16 | 17 | 1. The origin of this software must not be misrepresented; you must not 18 | claim that you wrote the original software. If you use this software 19 | in a product, an acknowledgement in the product documentation would be 20 | appreciated but is not required. 21 | 2. Altered source versions must be plainly marked as such, and must not be 22 | misrepresented as being the original software. 23 | 3. This notice may not be removed or altered from any source distribution. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # GNU Makefile for t1ha, https://abf.io/erthink/t1ha 2 | 3 | ######################################################################## 4 | 5 | # T1HA_USE_FAST_ONESHOT_READ: 6 | # Define it to 1 for little bit faster code. 7 | # Unfortunately this may triggering a false-positive alarms from Valgrind, 8 | # AddressSanitizer and other similar tool. 9 | # So, define it to 0 for calmness if doubt. 10 | T1HA_USE_FAST_ONESHOT_READ ?=1 11 | 12 | # To use the Intel compiler you need something like this 13 | #CC=/opt/intel/compilers_and_libraries/linux/bin/intel64/icc 14 | #CXX=/opt/intel/compilers_and_libraries/linux/bin/intel64/icc 15 | #LD=/opt/intel/compilers_and_libraries/linux/bin/intel64/xild 16 | #AR=/opt/intel/compilers_and_libraries/linux/bin/intel64/xiar 17 | #TARGET_ARCH_ia32=yes 18 | 19 | CC ?= gcc 20 | CXX ?= g++ 21 | 22 | # T1HA_EXTRA_CFLAGS ?= -DT1HA_USE_INDIRECT_FUNCTIONS=0 -m32 23 | 24 | CFLAGS ?= $(T1HA_EXTRA_CFLAGS) -std=c11 -O3 -DNDEBUG -D_DEFAULT_SOURCE -fno-stack-protector 25 | CXXFLAGS = -std=c++11 $(filter-out -std=c11,$(CFLAGS)) 26 | 27 | TARGET_ARCH_e2k ?= $(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i 'e2k' && echo yes || echo no)) 28 | TARGET_ARCH_ia32 ?= $(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i -e '^Target: \(x86_64\)\|\([iI][3-6]86\)-.*' && echo yes || echo no)) 29 | TARGET_ARCH_ppc ?= $(shell (export LC_ALL=C; ($(CC) --version 2>&1; $(CC) -v 2>&1) | grep -q -i -e '^Target: powerpc.*' && echo yes || echo no)) 30 | 31 | OBJ_LIST := t1ha0.o t1ha1.o t1ha2.o t1ha0_selfcheck.o t1ha1_selfcheck.o t1ha2_selfcheck.o t1ha_selfcheck.o t1ha_selfcheck_all.o 32 | BENCH_EXTRA := bench.o mera.o test.o 4bench_xxhash.o 4bench_stadtx.o 4bench_wyhash.o 4bench_highwayhash_test.o 4bench_highwayhash_pure_c.o 4bench_highwayhash_portable.o 33 | ifeq ($(TARGET_ARCH_e2k),yes) 34 | TARGET_ARCH := e2k 35 | CFLAGS += -mtune=native 36 | OBJ_LIST += t1ha0_aes_noavx.o t1ha0_aes_avx.o 37 | BENCH_EXTRA += 4bench_t1ha0_aes_noavx.o 4bench_t1ha0_aes_avx.o 38 | else ifeq ($(TARGET_ARCH_ia32),yes) 39 | TARGET_ARCH := ia32 40 | CFLAGS += -mtune=native 41 | OBJ_LIST += t1ha0_aes_noavx.o t1ha0_aes_avx.o t1ha0_aes_avx2.o 42 | BENCH_EXTRA += 4bench_t1ha0_aes_noavx.o 4bench_t1ha0_aes_avx.o 4bench_t1ha0_aes_avx2.o 43 | else 44 | TARGET_ARCH := portable 45 | endif 46 | 47 | CFLAGS_TEST ?= -Wextra -Werror $(CFLAGS) 48 | CXXFLAGS_TEST ?= -Wextra -Werror $(CXXFLAGS) 49 | CFLAGS_LIB ?= -Wall -ffunction-sections -fPIC $(CFLAGS) -fvisibility=hidden -Dt1ha_EXPORTS 50 | 51 | all: test libt1ha.a libt1ha.so 52 | 53 | clean: 54 | rm -f test test32 test64 *.i *.bc *.s *.o *.a *.so 55 | 56 | CLANG_FORMAT ?= $(shell (which clang-format || which clang-format-10 || which clang-format-11 || which clang-format-12) 2>/dev/null) 57 | 58 | reformat: 59 | @if [ -n "$(CLANG_FORMAT)" ]; then \ 60 | git ls-files | grep -E '\.(c|cxx|cc|cpp|h|hxx|hpp)(\.in)?$$' | xargs -r $(CLANG_FORMAT) -i --style=file; \ 61 | else \ 62 | echo "clang-format version 8..12 not found for 'reformat'"; \ 63 | fi 64 | 65 | t1ha_selfcheck.o: t1ha.h src/t1ha_bits.h src/t1ha_selfcheck.h src/t1ha_selfcheck.c Makefile 66 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha_selfcheck.c 67 | 68 | t1ha_selfcheck_all.o: t1ha.h src/t1ha_bits.h src/t1ha_selfcheck.h src/t1ha_selfcheck_all.c Makefile 69 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha_selfcheck_all.c 70 | 71 | t1ha0.o: t1ha.h src/t1ha_bits.h src/t1ha0.c Makefile 72 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha0.c 73 | 74 | t1ha0_selfcheck.o: t1ha.h src/t1ha_bits.h src/t1ha0_selfcheck.c Makefile 75 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha0_selfcheck.c 76 | 77 | t1ha0_aes_noavx.o_ARCH_ia32_CFLAGS = -mno-avx2 -mno-avx -maes 78 | t1ha0_aes_noavx.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h src/t1ha0_ia32aes_noavx.c Makefile 79 | $(CC) $(CFLAGS_LIB) -save-temps $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ src/t1ha0_ia32aes_noavx.c 80 | 81 | t1ha0_aes_avx.o_ARCH_ia32_CFLAGS = -mno-avx2 -mavx -maes 82 | t1ha0_aes_avx.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h src/t1ha0_ia32aes_avx.c Makefile 83 | $(CC) $(CFLAGS_LIB) -save-temps $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ src/t1ha0_ia32aes_avx.c 84 | 85 | t1ha0_aes_avx2.o_ARCH_ia32_CFLAGS = -mavx2 -mavx -maes 86 | t1ha0_aes_avx2.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h src/t1ha0_ia32aes_avx2.c Makefile 87 | $(CC) $(CFLAGS_LIB) -save-temps $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ src/t1ha0_ia32aes_avx2.c 88 | 89 | 4bench_t1ha0_aes_noavx.o_ARCH_ia32_CFLAGS = -mno-avx2 -mno-avx -maes 90 | 4bench_t1ha0_aes_noavx.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h tests/4bench_t1ha0_ia32aes_noavx.c Makefile 91 | $(CC) $(CFLAGS_LIB) $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ tests/4bench_t1ha0_ia32aes_noavx.c 92 | 93 | 4bench_t1ha0_aes_avx.o_ARCH_ia32_CFLAGS = -mno-avx2 -mavx -maes 94 | 4bench_t1ha0_aes_avx.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h tests/4bench_t1ha0_ia32aes_avx.c Makefile 95 | $(CC) $(CFLAGS_LIB) $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ tests/4bench_t1ha0_ia32aes_avx.c 96 | 97 | 4bench_t1ha0_aes_avx2.o_ARCH_ia32_CFLAGS = -mavx2 -mavx -maes 98 | 4bench_t1ha0_aes_avx2.o: t1ha.h src/t1ha_bits.h src/t1ha0_ia32aes_a.h src/t1ha0_ia32aes_b.h tests/4bench_t1ha0_ia32aes_avx2.c Makefile 99 | $(CC) $(CFLAGS_LIB) $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -c -o $@ tests/4bench_t1ha0_ia32aes_avx2.c 100 | 101 | t1ha1.o: t1ha.h src/t1ha_bits.h src/t1ha1.c Makefile 102 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha1.c 103 | 104 | t1ha1_selfcheck.o: t1ha.h src/t1ha_bits.h src/t1ha1_selfcheck.c Makefile 105 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha1_selfcheck.c 106 | 107 | t1ha2.o: t1ha.h src/t1ha_bits.h src/t1ha2.c Makefile 108 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha2.c 109 | 110 | t1ha2_selfcheck.o: t1ha.h src/t1ha_bits.h src/t1ha2_selfcheck.c Makefile 111 | $(CC) $(CFLAGS_LIB) -c -o $@ src/t1ha2_selfcheck.c 112 | 113 | libt1ha.a: $(OBJ_LIST) Makefile 114 | $(AR) rs $@ $(OBJ_LIST) 115 | 116 | libt1ha.so: $(OBJ_LIST) Makefile 117 | $(CC) $(CFLAGS) -shared -s -o $@ $(OBJ_LIST) 118 | 119 | ############################################################################### 120 | 121 | mera.o: t1ha.h tests/mera.h tests/mera.c \ 122 | Makefile 123 | $(CC) $(CFLAGS_TEST) -save-temps -c -o $@ tests/mera.c 124 | 125 | bench.o: t1ha.h tests/common.h tests/mera.h tests/bench.c \ 126 | Makefile 127 | $(CC) $(CFLAGS_TEST) -c -o $@ tests/bench.c 128 | 129 | test.o: t1ha.h tests/common.h tests/mera.h tests/test.c \ 130 | Makefile 131 | $(CC) $(CFLAGS_TEST) -c -o $@ tests/test.c 132 | 133 | 4bench_xxhash.o: tests/xxhash/xxhash.h tests/xxhash/xxhash.c \ 134 | tests/xxhash/xxh_thunk.c tests/common.h Makefile 135 | $(CC) $(CFLAGS_TEST) -Wno-error -c -o $@ tests/xxhash/xxh_thunk.c 136 | 137 | 4bench_stadtx.o: tests/common.h tests/stadtx/stadtx_hash.h \ 138 | tests/stadtx/stadtx_thunk.c tests/common.h Makefile 139 | $(CC) $(CFLAGS_TEST) -Wno-error -c -o $@ tests/stadtx/stadtx_thunk.c 140 | 141 | 4bench_wyhash.o: tests/wyhash/wyhash.h tests/wyhash/wyhash_thunk.c \ 142 | tests/common.h Makefile 143 | $(CC) $(CFLAGS_TEST) -Wno-error -c -o $@ tests/wyhash/wyhash_thunk.c 144 | 145 | 4bench_highwayhash_pure_c.o: tests/highwayhash/pure_c.h \ 146 | tests/highwayhash/pure_c.c Makefile 147 | $(CC) $(CFLAGS_TEST) -Wno-error -c -o $@ tests/highwayhash/pure_c.c 148 | 149 | HIGHWAYHASH_SRC = $(addprefix tests/highwayhash/, \ 150 | arch_specific.cc arch_specific.h compiler_specific.h \ 151 | endianess.h hh_types.h hh_buffer.h highwayhash.h \ 152 | highwayhash_target.cc highwayhash_target.h iaca.h \ 153 | load3.h vector128.h vector256.h) 154 | 155 | 4bench_highwayhash_portable.o: $(addprefix tests/highwayhash/, \ 156 | hh_portable.cc hh_portable.h 4bench_portable.cc) \ 157 | $(HIGHWAYHASH_SRC) tests/common.h Makefile 158 | $(CXX) -I tests $(CXXFLAGS_TEST) -Wno-error -c -o $@ tests/highwayhash/4bench_portable.cc 159 | 160 | 4bench_highwayhash_avx2.o_ARCH_ia32_CFLAGS = -mavx2 161 | 4bench_highwayhash_avx2.o: $(addprefix tests/highwayhash/, \ 162 | hh_avx2.cc hh_avx2.h 4bench_avx2.cc) \ 163 | $(HIGHWAYHASH_SRC) tests/common.h Makefile 164 | $(CXX) -I tests $(CXXFLAGS_TEST) $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -Wno-error -c -o $@ tests/highwayhash/4bench_avx2.cc 165 | 166 | 4bench_highwayhash_sse41.o_ARCH_ia32_CFLAGS = -msse4.1 167 | 4bench_highwayhash_sse41.o: $(addprefix tests/highwayhash/, \ 168 | hh_sse41.cc hh_sse41.h 4bench_sse41.cc) \ 169 | $(HIGHWAYHASH_SRC) tests/common.h Makefile 170 | $(CXX) -I tests $(CXXFLAGS_TEST) $($(@)_ARCH_$(TARGET_ARCH)_CFLAGS) -Wno-error -c -o $@ tests/highwayhash/4bench_sse41.cc 171 | 172 | ifeq ($(TARGET_ARCH_ia32),yes) 173 | BENCH_EXTRA += 4bench_highwayhash_avx2.o 4bench_highwayhash_sse41.o 174 | endif 175 | 176 | 4bench_highwayhash_vsx.o: $(addprefix tests/highwayhash/, \ 177 | hh_vsx.cc hh_vsx.h 4bench_vsx.cc) \ 178 | $(HIGHWAYHASH_SRC) tests/common.h Makefile 179 | $(CXX) -I tests $(CXXFLAGS_TEST) -mpower8-vector -mvsx -Wno-error -c -o $@ tests/highwayhash/4bench_vsx.cc 180 | 181 | ifeq ($(TARGET_ARCH_ppc),yes) 182 | BENCH_EXTRA += 4bench_highwayhash_vsx.o 183 | endif 184 | 185 | ifeq ($(TARGET_ARCH_e2k),yes) 186 | BENCH_EXTRA += 4bench_highwayhash_sse41.o 187 | endif 188 | 189 | 4bench_highwayhash_test.o: tests/common.h tests/highwayhash/pure_c.h \ 190 | tests/highwayhash/verifier.c Makefile 191 | $(CC) $(CFLAGS_TEST) -Wno-error -c -o $@ tests/highwayhash/verifier.c 192 | 193 | test: $(OBJ_LIST) $(BENCH_EXTRA) tests/main.c Makefile \ 194 | t1ha.h tests/common.h tests/mera.h \ 195 | mera.o bench.o test.o 196 | @echo "Target-ARCH: $(TARGET_ARCH)" || true 197 | $(CC) $(CFLAGS_TEST) -o $@ tests/main.c $(OBJ_LIST) $(BENCH_EXTRA) -lm 198 | 199 | check: test 200 | ./test 201 | 202 | bench: test 203 | ./test --all-funcs --all-sizes 204 | 205 | bench-verbose: test 206 | ./test --bench-verbose 207 | 208 | ############################################################################### 209 | 210 | CROSS_LIST = sh4-linux-gnu-gcc alpha-linux-gnu-gcc \ 211 | powerpc64-linux-gnu-gcc powerpc-linux-gnu-gcc \ 212 | mips64-linux-gnuabi64-gcc mips-linux-gnu-gcc \ 213 | arm-linux-gnueabihf-gcc aarch64-linux-gnu-gcc \ 214 | sparc64-linux-gnu-gcc 215 | 216 | # hppa-linux-gnu-gcc - don't supported by current qemu release 217 | # s390x-linux-gnu-gcc - qemu troubles (hang/abort) 218 | CROSS_LIST_NOQEMU = hppa-linux-gnu-gcc s390x-linux-gnu-gcc 219 | 220 | cross-gcc: 221 | @echo "CORRESPONDING CROSS-COMPILERs ARE REQUIRED." 222 | @echo "FOR INSTANCE: apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" 223 | @for CC in $(CROSS_LIST_NOQEMU) $(CROSS_LIST); do \ 224 | echo "===================== $$CC"; \ 225 | $(MAKE) clean && CC=$$CC CXX=$$(echo "$$CC" | sed 's/gcc/g++/') $(MAKE) all || exit $$?; \ 226 | done 227 | 228 | cross-qemu: 229 | @echo "CORRESPONDING CROSS-COMPILERs AND QEMUs ARE REQUIRED." 230 | @echo "FOR INSTANCE: " 231 | @echo " 1) apt install g++-aarch64-linux-gnu g++-alpha-linux-gnu g++-arm-linux-gnueabihf g++-hppa-linux-gnu g++-mips-linux-gnu g++-mips64-linux-gnuabi64 g++-powerpc-linux-gnu g++-powerpc64-linux-gnu g++-s390x-linux-gnu g++-sh4-linux-gnu g++-sparc64-linux-gnu" 232 | @echo " 2) apt install binfmt-support qemu-user-static qemu-user qemu-system-arm qemu-system-mips qemu-system-misc qemu-system-ppc qemu-system-sparc" 233 | @for CC in $(CROSS_LIST); do \ 234 | echo "===================== $$CC + qemu"; \ 235 | $(MAKE) clean && CC=$$CC CXX=$$(echo "$$CC" | sed 's/gcc/g++/') CFLAGS_TEST="-std=c11 -static" $(MAKE) bench-verbose || exit $$?; \ 236 | done 237 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | ## meson.build for t1ha v2.0.1 2 | 3 | project('t1ha', 'c') 4 | 5 | cc = meson.get_compiler('c') 6 | t1ha_sources = files( 7 | 'src/t1ha0.c', 8 | 'src/t1ha1.c', 9 | 'src/t1ha2.c') 10 | 11 | t1ha_objects = [] 12 | t1ha_c_args = [] 13 | t1ha_link_with = [] 14 | 15 | foreach a : ['-Wall', '-ffunction-sections', '-std=c99'] 16 | if cc.has_argument(a) 17 | t1ha_c_args += a 18 | endif 19 | endforeach 20 | 21 | if true 22 | t1ha_c_args = ['-Dt1ha_EXPORTS'] 23 | if cc.has_argument('-fvisibility=hidden') 24 | t1ha_c_args += '-fvisibility=hidden' 25 | endif 26 | endif 27 | 28 | if target_machine.cpu_family().startswith('x86') 29 | t1ha_ia32aes_noavx_c_args = t1ha_c_args 30 | t1ha_ia32aes_avx_c_args = t1ha_c_args 31 | t1ha_ia32aes_avx2_c_args = t1ha_c_args 32 | 33 | if cc.get_id() == 'msvc' 34 | t1ha_ia32aes_avx_c_args += '/arch:AVX' 35 | t1ha_ia32aes_avx2_c_args += '/arch:AVX2' 36 | else 37 | t1ha_ia32aes_noavx_c_args += ['-mno-avx2', '-mno-avx', '-maes', '-mtune=native'] 38 | t1ha_ia32aes_avx_c_args += ['-mno-avx2', '-mavx', '-maes', '-mtune=native'] 39 | t1ha_ia32aes_avx2_c_args += ['-mavx2', '-mavx', '-maes', '-mtune=native'] 40 | endif 41 | 42 | # Need a staging lib since meson cannot set c_args per object. 43 | # Need all versions since th1a0 hash checks processor and chooses 44 | # the appropriate version at runtime. 45 | lib = static_library('t1ha_ia32aes_noavx_stage', 46 | 'src/t1ha0_ia32aes_noavx.c', c_args: t1ha_ia32aes_noavx_c_args) 47 | t1ha_objects += lib.extract_objects('src/t1ha0_ia32aes_noavx.c') 48 | 49 | lib = static_library('t1ha_ia32aes_avx_stage', 50 | 'src/t1ha0_ia32aes_avx.c', c_args: t1ha_ia32aes_avx_c_args) 51 | t1ha_objects += lib.extract_objects('src/t1ha0_ia32aes_avx.c') 52 | 53 | lib = static_library('t1ha_ia32aes_avx2_stage', 54 | 'src/t1ha0_ia32aes_avx2.c', c_args: t1ha_ia32aes_avx2_c_args) 55 | t1ha_objects += lib.extract_objects('src/t1ha0_ia32aes_avx2.c') 56 | endif 57 | 58 | libt1ha = static_library('t1ha', t1ha_sources, c_args: t1ha_c_args, objects: t1ha_objects) 59 | 60 | ## this makes it possible to use the source and objects in parent project without using libt1ha directly. 61 | #lib_objects += t1ha_objects 62 | #lib_sources += t1ha_sources 63 | -------------------------------------------------------------------------------- /src/t1ha0_ia32aes_a.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #include "t1ha_bits.h" 45 | #include "t1ha_selfcheck.h" 46 | 47 | #if T1HA0_AESNI_AVAILABLE 48 | 49 | uint64_t T1HA_IA32AES_NAME(const void *data, size_t len, uint64_t seed) { 50 | uint64_t a = seed; 51 | uint64_t b = len; 52 | 53 | if (unlikely(len > 32)) { 54 | __m128i x = _mm_set_epi64x(a, b); 55 | __m128i y = _mm_aesenc_si128(x, _mm_set_epi64x(prime_5, prime_6)); 56 | 57 | const __m128i *__restrict v = (const __m128i *)data; 58 | const __m128i *__restrict const detent = 59 | (const __m128i *)((const uint8_t *)data + len - 127); 60 | 61 | while (v < detent) { 62 | __m128i v0 = _mm_loadu_si128(v + 0); 63 | __m128i v1 = _mm_loadu_si128(v + 1); 64 | __m128i v2 = _mm_loadu_si128(v + 2); 65 | __m128i v3 = _mm_loadu_si128(v + 3); 66 | __m128i v4 = _mm_loadu_si128(v + 4); 67 | __m128i v5 = _mm_loadu_si128(v + 5); 68 | __m128i v6 = _mm_loadu_si128(v + 6); 69 | __m128i v7 = _mm_loadu_si128(v + 7); 70 | 71 | __m128i v0y = _mm_aesenc_si128(v0, y); 72 | __m128i v2x6 = _mm_aesenc_si128(v2, _mm_xor_si128(x, v6)); 73 | __m128i v45_67 = 74 | _mm_xor_si128(_mm_aesenc_si128(v4, v5), _mm_add_epi64(v6, v7)); 75 | 76 | __m128i v0y7_1 = _mm_aesdec_si128(_mm_sub_epi64(v7, v0y), v1); 77 | __m128i v2x6_3 = _mm_aesenc_si128(v2x6, v3); 78 | 79 | x = _mm_aesenc_si128(v45_67, _mm_add_epi64(x, y)); 80 | y = _mm_aesenc_si128(v2x6_3, _mm_xor_si128(v0y7_1, v5)); 81 | v += 8; 82 | } 83 | 84 | if (len & 64) { 85 | __m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++)); 86 | __m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++)); 87 | x = _mm_aesdec_si128(x, v0y); 88 | y = _mm_aesdec_si128(y, v1x); 89 | 90 | __m128i v2y = _mm_add_epi64(y, _mm_loadu_si128(v++)); 91 | __m128i v3x = _mm_sub_epi64(x, _mm_loadu_si128(v++)); 92 | x = _mm_aesdec_si128(x, v2y); 93 | y = _mm_aesdec_si128(y, v3x); 94 | } 95 | 96 | if (len & 32) { 97 | __m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++)); 98 | __m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++)); 99 | x = _mm_aesdec_si128(x, v0y); 100 | y = _mm_aesdec_si128(y, v1x); 101 | } 102 | 103 | if (len & 16) { 104 | y = _mm_add_epi64(x, y); 105 | x = _mm_aesdec_si128(x, _mm_loadu_si128(v++)); 106 | } 107 | 108 | x = _mm_add_epi64(_mm_aesdec_si128(x, _mm_aesenc_si128(y, x)), y); 109 | #if defined(__x86_64__) || defined(_M_X64) 110 | #if defined(__SSE4_1__) || defined(__AVX__) 111 | a = _mm_extract_epi64(x, 0); 112 | b = _mm_extract_epi64(x, 1); 113 | #else 114 | a = _mm_cvtsi128_si64(x); 115 | b = _mm_cvtsi128_si64(_mm_unpackhi_epi64(x, x)); 116 | #endif 117 | #else 118 | #if defined(__SSE4_1__) || defined(__AVX__) 119 | a = (uint32_t)_mm_extract_epi32(x, 0) | (uint64_t)_mm_extract_epi32(x, 1) 120 | << 32; 121 | b = (uint32_t)_mm_extract_epi32(x, 2) | (uint64_t)_mm_extract_epi32(x, 3) 122 | << 32; 123 | #else 124 | a = (uint32_t)_mm_cvtsi128_si32(x); 125 | a |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32; 126 | x = _mm_unpackhi_epi64(x, x); 127 | b = (uint32_t)_mm_cvtsi128_si32(x); 128 | b |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32; 129 | #endif 130 | #endif 131 | #ifdef __AVX__ 132 | _mm256_zeroupper(); 133 | #elif !(defined(_X86_64_) || defined(__x86_64__) || defined(_M_X64) || \ 134 | defined(__e2k__)) 135 | _mm_empty(); 136 | #endif 137 | data = v; 138 | len &= 15; 139 | } 140 | 141 | const uint64_t *v = (const uint64_t *)data; 142 | switch (len) { 143 | default: 144 | mixup64(&a, &b, fetch64_le_unaligned(v++), prime_4); 145 | /* fall through */ 146 | case 24: 147 | case 23: 148 | case 22: 149 | case 21: 150 | case 20: 151 | case 19: 152 | case 18: 153 | case 17: 154 | mixup64(&b, &a, fetch64_le_unaligned(v++), prime_3); 155 | /* fall through */ 156 | case 16: 157 | case 15: 158 | case 14: 159 | case 13: 160 | case 12: 161 | case 11: 162 | case 10: 163 | case 9: 164 | mixup64(&a, &b, fetch64_le_unaligned(v++), prime_2); 165 | /* fall through */ 166 | case 8: 167 | case 7: 168 | case 6: 169 | case 5: 170 | case 4: 171 | case 3: 172 | case 2: 173 | case 1: 174 | mixup64(&b, &a, tail64_le_unaligned(v, len), prime_1); 175 | /* fall through */ 176 | case 0: 177 | return final64(a, b); 178 | } 179 | } 180 | 181 | #endif /* T1HA0_AESNI_AVAILABLE */ 182 | #undef T1HA_IA32AES_NAME 183 | -------------------------------------------------------------------------------- /src/t1ha0_ia32aes_avx.c: -------------------------------------------------------------------------------- 1 | #ifndef T1HA0_DISABLED 2 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx 3 | #include "t1ha0_ia32aes_a.h" 4 | #endif /* T1HA0_DISABLED */ 5 | -------------------------------------------------------------------------------- /src/t1ha0_ia32aes_avx2.c: -------------------------------------------------------------------------------- 1 | #ifndef T1HA0_DISABLED 2 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx2 3 | #include "t1ha0_ia32aes_b.h" 4 | #endif /* T1HA0_DISABLED */ 5 | -------------------------------------------------------------------------------- /src/t1ha0_ia32aes_b.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #include "t1ha_bits.h" 45 | #include "t1ha_selfcheck.h" 46 | 47 | #if T1HA0_AESNI_AVAILABLE 48 | 49 | uint64_t T1HA_IA32AES_NAME(const void *data, size_t len, uint64_t seed) { 50 | uint64_t a = seed; 51 | uint64_t b = len; 52 | 53 | if (unlikely(len > 32)) { 54 | __m128i x = _mm_set_epi64x(a, b); 55 | __m128i y = _mm_aesenc_si128(x, _mm_set_epi64x(prime_0, prime_1)); 56 | 57 | const __m128i *v = (const __m128i *)data; 58 | const __m128i *const detent = 59 | (const __m128i *)((const uint8_t *)data + (len & ~15ul)); 60 | data = detent; 61 | 62 | if (len & 16) { 63 | x = _mm_add_epi64(x, _mm_loadu_si128(v++)); 64 | y = _mm_aesenc_si128(x, y); 65 | } 66 | len &= 15; 67 | 68 | if (v + 7 < detent) { 69 | __m128i salt = y; 70 | do { 71 | __m128i t = _mm_aesenc_si128(_mm_loadu_si128(v++), salt); 72 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 73 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 74 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 75 | 76 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 77 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 78 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 79 | t = _mm_aesdec_si128(t, _mm_loadu_si128(v++)); 80 | 81 | salt = _mm_add_epi64(salt, _mm_set_epi64x(prime_5, prime_6)); 82 | t = _mm_aesenc_si128(x, t); 83 | x = _mm_add_epi64(y, x); 84 | y = t; 85 | } while (v + 7 < detent); 86 | } 87 | 88 | while (v < detent) { 89 | __m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++)); 90 | __m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++)); 91 | x = _mm_aesdec_si128(x, v0y); 92 | y = _mm_aesdec_si128(y, v1x); 93 | } 94 | 95 | x = _mm_add_epi64(_mm_aesdec_si128(x, _mm_aesenc_si128(y, x)), y); 96 | #if defined(__x86_64__) || defined(_M_X64) 97 | #if defined(__SSE4_1__) || defined(__AVX__) 98 | a = _mm_extract_epi64(x, 0); 99 | b = _mm_extract_epi64(x, 1); 100 | #else 101 | a = _mm_cvtsi128_si64(x); 102 | b = _mm_cvtsi128_si64(_mm_unpackhi_epi64(x, x)); 103 | #endif 104 | #else 105 | #if defined(__SSE4_1__) || defined(__AVX__) 106 | a = (uint32_t)_mm_extract_epi32(x, 0) | (uint64_t)_mm_extract_epi32(x, 1) 107 | << 32; 108 | b = (uint32_t)_mm_extract_epi32(x, 2) | (uint64_t)_mm_extract_epi32(x, 3) 109 | << 32; 110 | #else 111 | a = (uint32_t)_mm_cvtsi128_si32(x); 112 | a |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32; 113 | x = _mm_unpackhi_epi64(x, x); 114 | b = (uint32_t)_mm_cvtsi128_si32(x); 115 | b |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32; 116 | #endif 117 | #endif 118 | #ifdef __AVX__ 119 | _mm256_zeroupper(); 120 | #elif !(defined(_X86_64_) || defined(__x86_64__) || defined(_M_X64) || \ 121 | defined(__e2k__)) 122 | _mm_empty(); 123 | #endif 124 | } 125 | 126 | const uint64_t *v = (const uint64_t *)data; 127 | switch (len) { 128 | default: 129 | mixup64(&a, &b, fetch64_le_unaligned(v++), prime_4); 130 | /* fall through */ 131 | case 24: 132 | case 23: 133 | case 22: 134 | case 21: 135 | case 20: 136 | case 19: 137 | case 18: 138 | case 17: 139 | mixup64(&b, &a, fetch64_le_unaligned(v++), prime_3); 140 | /* fall through */ 141 | case 16: 142 | case 15: 143 | case 14: 144 | case 13: 145 | case 12: 146 | case 11: 147 | case 10: 148 | case 9: 149 | mixup64(&a, &b, fetch64_le_unaligned(v++), prime_2); 150 | /* fall through */ 151 | case 8: 152 | case 7: 153 | case 6: 154 | case 5: 155 | case 4: 156 | case 3: 157 | case 2: 158 | case 1: 159 | mixup64(&b, &a, tail64_le_unaligned(v, len), prime_1); 160 | /* fall through */ 161 | case 0: 162 | return final64(a, b); 163 | } 164 | } 165 | 166 | #endif /* T1HA0_AESNI_AVAILABLE */ 167 | #undef T1HA_IA32AES_NAME 168 | -------------------------------------------------------------------------------- /src/t1ha0_ia32aes_noavx.c: -------------------------------------------------------------------------------- 1 | #ifndef T1HA0_DISABLED 2 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_noavx 3 | #include "t1ha0_ia32aes_a.h" 4 | #endif /* T1HA0_DISABLED */ 5 | -------------------------------------------------------------------------------- /src/t1ha0_selfcheck.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #ifndef T1HA0_DISABLED 45 | #include "t1ha_bits.h" 46 | #include "t1ha_selfcheck.h" 47 | 48 | /* *INDENT-OFF* */ 49 | /* clang-format off */ 50 | 51 | const uint64_t t1ha_refval_32le[81] = { 0, 52 | 0xC92229C10FAEA50E, 0x3DF1354B0DFDC443, 0x968F016D60417BB3, 0x85AAFB50C6DA770F, 53 | 0x66CCE3BB6842C7D6, 0xDDAA39C11537C226, 0x35958D281F0C9C8C, 0x8C5D64B091DE608E, 54 | 0x4094DF680D39786B, 0x1014F4AA2A2EDF4D, 0x39D21891615AA310, 0x7EF51F67C398C7C4, 55 | 0x06163990DDBF319D, 0xE229CAA00C8D6F3F, 0xD2240B4B0D54E0F5, 0xEA2E7E905DDEAF94, 56 | 0x8D4F8A887183A5CE, 0x44337F9A63C5820C, 0x94938D1E86A9B797, 0x96E9CABA5CA210CC, 57 | 0x6EFBB9CC9E8F7708, 0x3D12EA0282FB8BBC, 0x5DA781EE205A2C48, 0xFA4A51A12677FE12, 58 | 0x81D5F04E20660B28, 0x57258D043BCD3841, 0x5C9BEB62059C1ED2, 0x57A02162F9034B33, 59 | 0xBA2A13E457CE19B8, 0xE593263BF9451F3A, 0x0BC1175539606BC5, 0xA3E2929E9C5F289F, 60 | 0x86BDBD06835E35F7, 0xA180950AB48BAADC, 0x7812C994D9924028, 0x308366011415F46B, 61 | 0x77FE9A9991C5F959, 0x925C340B70B0B1E3, 0xCD9C5BA4C41E2E10, 0x7CC4E7758B94CD93, 62 | 0x898B235962EA4625, 0xD7E3E5BF22893286, 0x396F4CDD33056C64, 0x740AB2E32F17CD9F, 63 | 0x60D12FF9CD15B321, 0xBEE3A6C9903A81D8, 0xB47040913B33C35E, 0x19EE8C2ACC013CFF, 64 | 0x5DEC94C5783B55C4, 0x78DC122D562C5F1D, 0x6520F008DA1C181E, 0x77CAF155A36EBF7C, 65 | 0x0A09E02BDB883CA6, 0xFD5D9ADA7E3FB895, 0xC6F5FDD9EEAB83B5, 0x84589BB29F52A92A, 66 | 0x9B2517F13F8E9814, 0x6F752AF6A52E31EC, 0x8E717799E324CE8A, 0x84D90AEF39262D58, 67 | 0x79C27B13FC28944D, 0xE6D6DF6438E0044A, 0x51B603E400D79CA4, 0x6A902B28C588B390, 68 | 0x8D7F8DE9E6CB1D83, 0xCF1A4DC11CA7F044, 0xEF02E43C366786F1, 0x89915BCDBCFBE30F, 69 | 0x5928B306F1A9CC7F, 0xA8B59092996851C5, 0x22050A20427E8B25, 0x6E6D64018941E7EE, 70 | 0x9798C898B81AE846, 0x80EF218CDC30124A, 0xFCE45E60D55B0284, 0x4010E735D3147C35, 71 | 0xEB647D999FD8DC7E, 0xD3544DCAB14FE907, 0xB588B27D8438700C, 0xA49EBFC43E057A4C 72 | }; 73 | 74 | const uint64_t t1ha_refval_32be[81] = { 0, 75 | 0xC92229C10FAEA50E, 0x0FE212630DD87E0F, 0x968F016D60417BB3, 0xE6B12B2C889913AB, 76 | 0xAA3787887A9DA368, 0x06EE7202D53CEF39, 0x6149AFB2C296664B, 0x86C893210F9A5805, 77 | 0x8379E5DA988AA04C, 0x24763AA7CE411A60, 0x9CF9C64B395A4CF8, 0xFFC192C338DDE904, 78 | 0x094575BAB319E5F5, 0xBBBACFE7728C6511, 0x36B8C3CEBE4EF409, 0xAA0BA8A3397BA4D0, 79 | 0xF9F85CF7124EE653, 0x3ADF4F7DF2A887AE, 0xAA2A0F5964AA9A7A, 0xF18B563F42D36EB8, 80 | 0x034366CEF8334F5C, 0xAE2E85180E330E5F, 0xA5CE9FBFDF5C65B8, 0x5E509F25A9CA9B0B, 81 | 0xE30D1358C2013BD2, 0xBB3A04D5EB8111FE, 0xB04234E82A15A28D, 0x87426A56D0EA0E2F, 82 | 0x095086668E07F9F8, 0xF4CD3A43B6A6AEA5, 0x73F9B9B674D472A6, 0x558344229A1E4DCF, 83 | 0x0AD4C95B2279181A, 0x5E3D19D80821CA6B, 0x652492D25BEBA258, 0xEFA84B02EAB849B1, 84 | 0x81AD2D253059AC2C, 0x1400CCB0DFB2F457, 0x5688DC72A839860E, 0x67CC130E0FD1B0A7, 85 | 0x0A851E3A94E21E69, 0x2EA0000B6A073907, 0xAE9776FF9BF1D02E, 0xC0A96B66B160631C, 86 | 0xA93341DE4ED7C8F0, 0x6FBADD8F5B85E141, 0xB7D295F1C21E0CBA, 0x6D6114591B8E434F, 87 | 0xF5B6939B63D97BE7, 0x3C80D5053F0E5DB4, 0xAC520ACC6B73F62D, 0xD1051F5841CF3966, 88 | 0x62245AEA644AE760, 0x0CD56BE15497C62D, 0x5BB93435C4988FB6, 0x5FADB88EB18DB512, 89 | 0xC897CAE2242475CC, 0xF1A094EF846DC9BB, 0x2B1D8B24924F79B6, 0xC6DF0C0E8456EB53, 90 | 0xE6A40128303A9B9C, 0x64D37AF5EFFA7BD9, 0x90FEB70A5AE2A598, 0xEC3BA5F126D9FF4B, 91 | 0x3121C8EC3AC51B29, 0x3B41C4D422166EC1, 0xB4878DDCBF48ED76, 0x5CB850D77CB762E4, 92 | 0x9A27A43CC1DD171F, 0x2FDFFC6F99CB424A, 0xF54A57E09FDEA7BB, 0x5F78E5EE2CAB7039, 93 | 0xB8BA95883DB31CBA, 0x131C61EB84AF86C3, 0x84B1F64E9C613DA7, 0xE94C1888C0C37C02, 94 | 0xEA08F8BFB2039CDE, 0xCCC6D04D243EC753, 0x8977D105298B0629, 0x7AAA976494A5905E 95 | }; 96 | 97 | #if T1HA0_AESNI_AVAILABLE 98 | const uint64_t t1ha_refval_ia32aes_a[81] = { 0, 99 | 0x772C7311BE32FF42, 0xB231AC660E5B23B5, 0x71F6DF5DA3B4F532, 0x555859635365F660, 100 | 0xE98808F1CD39C626, 0x2EB18FAF2163BB09, 0x7B9DD892C8019C87, 0xE2B1431C4DA4D15A, 101 | 0x1984E718A5477F70, 0x08DD17B266484F79, 0x4C83A05D766AD550, 0x92DCEBB131D1907D, 102 | 0xD67BC6FC881B8549, 0xF6A9886555FBF66B, 0x6E31616D7F33E25E, 0x36E31B7426E3049D, 103 | 0x4F8E4FAF46A13F5F, 0x03EB0CB3253F819F, 0x636A7769905770D2, 0x3ADF3781D16D1148, 104 | 0x92D19CB1818BC9C2, 0x283E68F4D459C533, 0xFA83A8A88DECAA04, 0x8C6F00368EAC538C, 105 | 0x7B66B0CF3797B322, 0x5131E122FDABA3FF, 0x6E59FF515C08C7A9, 0xBA2C5269B2C377B0, 106 | 0xA9D24FD368FE8A2B, 0x22DB13D32E33E891, 0x7B97DFC804B876E5, 0xC598BDFCD0E834F9, 107 | 0xB256163D3687F5A7, 0x66D7A73C6AEF50B3, 0xBB34C6A4396695D2, 0x7F46E1981C3256AD, 108 | 0x4B25A9B217A6C5B4, 0x7A0A6BCDD2321DA9, 0x0A1F55E690A7B44E, 0x8F451A91D7F05244, 109 | 0x624D5D3C9B9800A7, 0x09DDC2B6409DDC25, 0x3E155765865622B6, 0x96519FAC9511B381, 110 | 0x512E58482FE4FBF0, 0x1AB260EA7D54AE1C, 0x67976F12CC28BBBD, 0x0607B5B2E6250156, 111 | 0x7E700BEA717AD36E, 0x06A058D9D61CABB3, 0x57DA5324A824972F, 0x1193BA74DBEBF7E7, 112 | 0xC18DC3140E7002D4, 0x9F7CCC11DFA0EF17, 0xC487D6C20666A13A, 0xB67190E4B50EF0C8, 113 | 0xA53DAA608DF0B9A5, 0x7E13101DE87F9ED3, 0x7F8955AE2F05088B, 0x2DF7E5A097AD383F, 114 | 0xF027683A21EA14B5, 0x9BB8AEC3E3360942, 0x92BE39B54967E7FE, 0x978C6D332E7AFD27, 115 | 0xED512FE96A4FAE81, 0x9E1099B8140D7BA3, 0xDFD5A5BE1E6FE9A6, 0x1D82600E23B66DD4, 116 | 0x3FA3C3B7EE7B52CE, 0xEE84F7D2A655EF4C, 0x2A4361EC769E3BEB, 0x22E4B38916636702, 117 | 0x0063096F5D39A115, 0x6C51B24DAAFA5434, 0xBAFB1DB1B411E344, 0xFF529F161AE0C4B0, 118 | 0x1290EAE3AC0A686F, 0xA7B0D4585447D1BE, 0xAED3D18CB6CCAD53, 0xFC73D46F8B41BEC6 119 | }; 120 | 121 | const uint64_t t1ha_refval_ia32aes_b[81] = { 0, 122 | 0x772C7311BE32FF42, 0x4398F62A8CB6F72A, 0x71F6DF5DA3B4F532, 0x555859635365F660, 123 | 0xE98808F1CD39C626, 0x2EB18FAF2163BB09, 0x7B9DD892C8019C87, 0xE2B1431C4DA4D15A, 124 | 0x1984E718A5477F70, 0x08DD17B266484F79, 0x4C83A05D766AD550, 0x92DCEBB131D1907D, 125 | 0xD67BC6FC881B8549, 0xF6A9886555FBF66B, 0x6E31616D7F33E25E, 0x36E31B7426E3049D, 126 | 0x4F8E4FAF46A13F5F, 0x03EB0CB3253F819F, 0x636A7769905770D2, 0x3ADF3781D16D1148, 127 | 0x92D19CB1818BC9C2, 0x283E68F4D459C533, 0xFA83A8A88DECAA04, 0x8C6F00368EAC538C, 128 | 0x7B66B0CF3797B322, 0x5131E122FDABA3FF, 0x6E59FF515C08C7A9, 0xBA2C5269B2C377B0, 129 | 0xA9D24FD368FE8A2B, 0x22DB13D32E33E891, 0x7B97DFC804B876E5, 0xC598BDFCD0E834F9, 130 | 0xB256163D3687F5A7, 0x66D7A73C6AEF50B3, 0xE810F88E85CEA11A, 0x4814F8F3B83E4394, 131 | 0x9CABA22D10A2F690, 0x0D10032511F58111, 0xE9A36EF5EEA3CD58, 0xC79242DE194D9D7C, 132 | 0xC3871AA0435EE5C8, 0x52890BED43CCF4CD, 0x07A1D0861ACCD373, 0x227B816FF0FEE9ED, 133 | 0x59FFBF73AACFC0C4, 0x09AB564F2BEDAD0C, 0xC05F744F2EE38318, 0x7B50B621D547C661, 134 | 0x0C1F71CB4E68E5D1, 0x0E33A47881D4DBAA, 0xF5C3BF198E9A7C2E, 0x16328FD8C0F68A91, 135 | 0xA3E399C9AB3E9A59, 0x163AE71CBCBB18B8, 0x18F17E4A8C79F7AB, 0x9250E2EA37014B45, 136 | 0x7BBBB111D60B03E4, 0x3DAA4A3071A0BD88, 0xA28828D790A2D6DC, 0xBC70FC88F64BE3F1, 137 | 0xA3E48008BA4333C7, 0x739E435ACAFC79F7, 0x42BBB360BE007CC6, 0x4FFB6FD2AF74EC92, 138 | 0x2A799A2994673146, 0xBE0A045B69D48E9F, 0x549432F54FC6A278, 0x371D3C60369FC702, 139 | 0xDB4557D415B08CA7, 0xE8692F0A83850B37, 0x022E46AEB36E9AAB, 0x117AC9B814E4652D, 140 | 0xA361041267AE9048, 0x277CB51C961C3DDA, 0xAFFC96F377CB8A8D, 0x83CC79FA01DD1BA7, 141 | 0xA494842ACF4B802C, 0xFC6D9CDDE2C34A3F, 0x4ED6863CE455F7A7, 0x630914D0DB7AAE98 142 | }; 143 | #endif /* T1HA0_AESNI_AVAILABLE */ 144 | 145 | /* *INDENT-ON* */ 146 | /* clang-format on */ 147 | 148 | __cold int t1ha_selfcheck__t1ha0_32le(void) { 149 | return t1ha_selfcheck(t1ha0_32le, t1ha_refval_32le); 150 | } 151 | 152 | __cold int t1ha_selfcheck__t1ha0_32be(void) { 153 | return t1ha_selfcheck(t1ha0_32be, t1ha_refval_32be); 154 | } 155 | 156 | #if T1HA0_AESNI_AVAILABLE 157 | __cold int t1ha_selfcheck__t1ha0_ia32aes_noavx(void) { 158 | return t1ha_selfcheck(t1ha0_ia32aes_noavx, t1ha_refval_ia32aes_a); 159 | } 160 | 161 | __cold int t1ha_selfcheck__t1ha0_ia32aes_avx(void) { 162 | return t1ha_selfcheck(t1ha0_ia32aes_avx, t1ha_refval_ia32aes_a); 163 | } 164 | 165 | #ifndef __e2k__ 166 | __cold int t1ha_selfcheck__t1ha0_ia32aes_avx2(void) { 167 | return t1ha_selfcheck(t1ha0_ia32aes_avx2, t1ha_refval_ia32aes_b); 168 | } 169 | #endif /* ! __e2k__ */ 170 | #endif /* if T1HA0_AESNI_AVAILABLE */ 171 | 172 | __cold int t1ha_selfcheck__t1ha0(void) { 173 | int rc = t1ha_selfcheck__t1ha0_32le() | t1ha_selfcheck__t1ha0_32be(); 174 | 175 | #if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \ 176 | (!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED)) 177 | #if defined(T1HA1_DISABLED) 178 | rc |= t1ha_selfcheck__t1ha2(); 179 | #else 180 | rc |= t1ha_selfcheck__t1ha1(); 181 | #endif /* T1HA1_DISABLED */ 182 | #endif /* 32/64 */ 183 | 184 | #if T1HA0_AESNI_AVAILABLE 185 | #ifdef __e2k__ 186 | rc |= t1ha_selfcheck__t1ha0_ia32aes_noavx(); 187 | rc |= t1ha_selfcheck__t1ha0_ia32aes_avx(); 188 | #else 189 | uint64_t features = t1ha_ia32cpu_features(); 190 | if (t1ha_ia32_AESNI_avail(features)) { 191 | rc |= t1ha_selfcheck__t1ha0_ia32aes_noavx(); 192 | if (t1ha_ia32_AVX_avail(features)) { 193 | rc |= t1ha_selfcheck__t1ha0_ia32aes_avx(); 194 | if (t1ha_ia32_AVX2_avail(features)) 195 | rc |= t1ha_selfcheck__t1ha0_ia32aes_avx2(); 196 | } 197 | } 198 | #endif /* __e2k__ */ 199 | #endif /* T1HA0_AESNI_AVAILABLE */ 200 | 201 | return rc; 202 | } 203 | 204 | #endif /* T1HA0_DISABLED */ 205 | -------------------------------------------------------------------------------- /src/t1ha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #ifndef T1HA1_DISABLED 45 | #include "t1ha_bits.h" 46 | #include "t1ha_selfcheck.h" 47 | 48 | /* xor-mul-xor mixer */ 49 | static __inline uint64_t mix64(uint64_t v, uint64_t p) { 50 | v *= p; 51 | return v ^ rot64(v, 41); 52 | } 53 | 54 | static __inline uint64_t final_weak_avalanche(uint64_t a, uint64_t b) { 55 | /* LY: for performance reason on a some not high-end CPUs 56 | * I replaced the second mux64() operation by mix64(). 57 | * Unfortunately this approach fails the "strict avalanche criteria", 58 | * see test results at https://github.com/demerphq/smhasher. */ 59 | return mux64(rot64(a + b, 17), prime_4) + mix64(a ^ b, prime_0); 60 | } 61 | 62 | /* TODO: C++ template in the next version */ 63 | #define T1HA1_BODY(ENDIANNES, ALIGNESS) \ 64 | const uint64_t *v = (const uint64_t *)data; \ 65 | if (unlikely(len > 32)) { \ 66 | uint64_t c = rot64(len, 17) + seed; \ 67 | uint64_t d = len ^ rot64(seed, 17); \ 68 | const uint64_t *detent = \ 69 | (const uint64_t *)((const uint8_t *)data + len - 31); \ 70 | do { \ 71 | const uint64_t w0 = fetch64_##ENDIANNES##_##ALIGNESS(v + 0); \ 72 | const uint64_t w1 = fetch64_##ENDIANNES##_##ALIGNESS(v + 1); \ 73 | const uint64_t w2 = fetch64_##ENDIANNES##_##ALIGNESS(v + 2); \ 74 | const uint64_t w3 = fetch64_##ENDIANNES##_##ALIGNESS(v + 3); \ 75 | v += 4; \ 76 | prefetch(v); \ 77 | \ 78 | const uint64_t d02 = w0 ^ rot64(w2 + d, 17); \ 79 | const uint64_t c13 = w1 ^ rot64(w3 + c, 17); \ 80 | d -= b ^ rot64(w1, 31); \ 81 | c += a ^ rot64(w0, 41); \ 82 | b ^= prime_0 * (c13 + w2); \ 83 | a ^= prime_1 * (d02 + w3); \ 84 | } while (likely(v < detent)); \ 85 | \ 86 | a ^= prime_6 * (rot64(c, 17) + d); \ 87 | b ^= prime_5 * (c + rot64(d, 17)); \ 88 | len &= 31; \ 89 | } \ 90 | \ 91 | switch (len) { \ 92 | default: \ 93 | b += mux64(fetch64_##ENDIANNES##_##ALIGNESS(v++), prime_4); \ 94 | /* fall through */ \ 95 | case 24: \ 96 | case 23: \ 97 | case 22: \ 98 | case 21: \ 99 | case 20: \ 100 | case 19: \ 101 | case 18: \ 102 | case 17: \ 103 | a += mux64(fetch64_##ENDIANNES##_##ALIGNESS(v++), prime_3); \ 104 | /* fall through */ \ 105 | case 16: \ 106 | case 15: \ 107 | case 14: \ 108 | case 13: \ 109 | case 12: \ 110 | case 11: \ 111 | case 10: \ 112 | case 9: \ 113 | b += mux64(fetch64_##ENDIANNES##_##ALIGNESS(v++), prime_2); \ 114 | /* fall through */ \ 115 | case 8: \ 116 | case 7: \ 117 | case 6: \ 118 | case 5: \ 119 | case 4: \ 120 | case 3: \ 121 | case 2: \ 122 | case 1: \ 123 | a += mux64(tail64_##ENDIANNES##_##ALIGNESS(v, len), prime_1); \ 124 | /* fall through */ \ 125 | case 0: \ 126 | return final_weak_avalanche(a, b); \ 127 | } 128 | 129 | uint64_t t1ha1_le(const void *data, size_t len, uint64_t seed) { 130 | uint64_t a = seed; 131 | uint64_t b = len; 132 | 133 | #if T1HA_SYS_UNALIGNED_ACCESS == T1HA_UNALIGNED_ACCESS__EFFICIENT 134 | T1HA1_BODY(le, unaligned); 135 | #else 136 | const bool misaligned = (((uintptr_t)data) & (ALIGNMENT_64 - 1)) != 0; 137 | if (misaligned) { 138 | T1HA1_BODY(le, unaligned); 139 | } else { 140 | T1HA1_BODY(le, aligned); 141 | } 142 | #endif 143 | } 144 | 145 | uint64_t t1ha1_be(const void *data, size_t len, uint64_t seed) { 146 | uint64_t a = seed; 147 | uint64_t b = len; 148 | 149 | #if T1HA_SYS_UNALIGNED_ACCESS == T1HA_UNALIGNED_ACCESS__EFFICIENT 150 | T1HA1_BODY(be, unaligned); 151 | #else 152 | const bool misaligned = (((uintptr_t)data) & (ALIGNMENT_64 - 1)) != 0; 153 | if (misaligned) { 154 | T1HA1_BODY(be, unaligned); 155 | } else { 156 | T1HA1_BODY(be, aligned); 157 | } 158 | #endif 159 | } 160 | 161 | #endif /* T1HA1_DISABLED */ 162 | -------------------------------------------------------------------------------- /src/t1ha1_selfcheck.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #ifndef T1HA1_DISABLED 45 | #include "t1ha_bits.h" 46 | #include "t1ha_selfcheck.h" 47 | 48 | /* *INDENT-OFF* */ 49 | /* clang-format off */ 50 | 51 | const uint64_t t1ha_refval_64le[81] = { 0, 52 | 0x6A580668D6048674, 0xA2FE904AFF0D0879, 0xE3AB9C06FAF4D023, 0x6AF1C60874C95442, 53 | 0xB3557E561A6C5D82, 0x0AE73C696F3D37C0, 0x5EF25F7062324941, 0x9B784F3B4CE6AF33, 54 | 0x6993BB206A74F070, 0xF1E95DF109076C4C, 0x4E1EB70C58E48540, 0x5FDD7649D8EC44E4, 55 | 0x559122C706343421, 0x380133D58665E93D, 0x9CE74296C8C55AE4, 0x3556F9A5757AB6D0, 56 | 0xF62751F7F25C469E, 0x851EEC67F6516D94, 0xED463EE3848A8695, 0xDC8791FEFF8ED3AC, 57 | 0x2569C744E1A282CF, 0xF90EB7C1D70A80B9, 0x68DFA6A1B8050A4C, 0x94CCA5E8210D2134, 58 | 0xF5CC0BEABC259F52, 0x40DBC1F51618FDA7, 0x0807945BF0FB52C6, 0xE5EF7E09DE70848D, 59 | 0x63E1DF35FEBE994A, 0x2025E73769720D5A, 0xAD6120B2B8A152E1, 0x2A71D9F13959F2B7, 60 | 0x8A20849A27C32548, 0x0BCBC9FE3B57884E, 0x0E028D255667AEAD, 0xBE66DAD3043AB694, 61 | 0xB00E4C1238F9E2D4, 0x5C54BDE5AE280E82, 0x0E22B86754BC3BC4, 0x016707EBF858B84D, 62 | 0x990015FBC9E095EE, 0x8B9AF0A3E71F042F, 0x6AA56E88BD380564, 0xAACE57113E681A0F, 63 | 0x19F81514AFA9A22D, 0x80DABA3D62BEAC79, 0x715210412CABBF46, 0xD8FA0B9E9D6AA93F, 64 | 0x6C2FC5A4109FD3A2, 0x5B3E60EEB51DDCD8, 0x0A7C717017756FE7, 0xA73773805CA31934, 65 | 0x4DBD6BB7A31E85FD, 0x24F619D3D5BC2DB4, 0x3E4AF35A1678D636, 0x84A1A8DF8D609239, 66 | 0x359C862CD3BE4FCD, 0xCF3A39F5C27DC125, 0xC0FF62F8FD5F4C77, 0x5E9F2493DDAA166C, 67 | 0x17424152BE1CA266, 0xA78AFA5AB4BBE0CD, 0x7BFB2E2CEF118346, 0x647C3E0FF3E3D241, 68 | 0x0352E4055C13242E, 0x6F42FC70EB660E38, 0x0BEBAD4FABF523BA, 0x9269F4214414D61D, 69 | 0x1CA8760277E6006C, 0x7BAD25A859D87B5D, 0xAD645ADCF7414F1D, 0xB07F517E88D7AFB3, 70 | 0xB321C06FB5FFAB5C, 0xD50F162A1EFDD844, 0x1DFD3D1924FBE319, 0xDFAEAB2F09EF7E78, 71 | 0xA7603B5AF07A0B1E, 0x41CD044C0E5A4EE3, 0xF64D2F86E813BF33, 0xFF9FDB99305EB06A 72 | }; 73 | 74 | const uint64_t t1ha_refval_64be[81] = { 0, 75 | 0x6A580668D6048674, 0xDECC975A0E3B8177, 0xE3AB9C06FAF4D023, 0xE401FA8F1B6AF969, 76 | 0x67DB1DAE56FB94E3, 0x1106266A09B7A073, 0x550339B1EF2C7BBB, 0x290A2BAF590045BB, 77 | 0xA182C1258C09F54A, 0x137D53C34BE7143A, 0xF6D2B69C6F42BEDC, 0x39643EAF2CA2E4B4, 78 | 0x22A81F139A2C9559, 0x5B3D6AEF0AF33807, 0x56E3F80A68643C08, 0x9E423BE502378780, 79 | 0xCDB0986F9A5B2FD5, 0xD5B3C84E7933293F, 0xE5FB8C90399E9742, 0x5D393C1F77B2CF3D, 80 | 0xC8C82F5B2FF09266, 0xACA0230CA6F7B593, 0xCB5805E2960D1655, 0x7E2AD5B704D77C95, 81 | 0xC5E903CDB8B9EB5D, 0x4CC7D0D21CC03511, 0x8385DF382CFB3E93, 0xF17699D0564D348A, 82 | 0xF77EE7F8274A4C8D, 0xB9D8CEE48903BABE, 0xFE0EBD2A82B9CFE9, 0xB49FB6397270F565, 83 | 0x173735C8C342108E, 0xA37C7FBBEEC0A2EA, 0xC13F66F462BB0B6E, 0x0C04F3C2B551467E, 84 | 0x76A9CB156810C96E, 0x2038850919B0B151, 0xCEA19F2B6EED647B, 0x6746656D2FA109A4, 85 | 0xF05137F221007F37, 0x892FA9E13A3B4948, 0x4D57B70D37548A32, 0x1A7CFB3D566580E6, 86 | 0x7CB30272A45E3FAC, 0x137CCFFD9D51423F, 0xB87D96F3B82DF266, 0x33349AEE7472ED37, 87 | 0x5CC0D3C99555BC07, 0x4A8F4FA196D964EF, 0xE82A0D64F281FBFA, 0x38A1BAC2C36823E1, 88 | 0x77D197C239FD737E, 0xFB07746B4E07DF26, 0xC8A2198E967672BD, 0x5F1A146D143FA05A, 89 | 0x26B877A1201AB7AC, 0x74E5B145214723F8, 0xE9CE10E3C70254BC, 0x299393A0C05B79E8, 90 | 0xFD2D2B9822A5E7E2, 0x85424FEA50C8E50A, 0xE6839E714B1FFFE5, 0x27971CCB46F9112A, 91 | 0xC98695A2E0715AA9, 0x338E1CBB4F858226, 0xFC6B5C5CF7A8D806, 0x8973CAADDE8DA50C, 92 | 0x9C6D47AE32EBAE72, 0x1EBF1F9F21D26D78, 0x80A9704B8E153859, 0x6AFD20A939F141FB, 93 | 0xC35F6C2B3B553EEF, 0x59529E8B0DC94C1A, 0x1569DF036EBC4FA1, 0xDA32B88593C118F9, 94 | 0xF01E4155FF5A5660, 0x765A2522DCE2B185, 0xCEE95554128073EF, 0x60F072A5CA51DE2F 95 | }; 96 | 97 | /* *INDENT-ON* */ 98 | /* clang-format on */ 99 | 100 | __cold int t1ha_selfcheck__t1ha1_le(void) { 101 | return t1ha_selfcheck(t1ha1_le, t1ha_refval_64le); 102 | } 103 | 104 | __cold int t1ha_selfcheck__t1ha1_be(void) { 105 | return t1ha_selfcheck(t1ha1_be, t1ha_refval_64be); 106 | } 107 | 108 | __cold int t1ha_selfcheck__t1ha1(void) { 109 | return t1ha_selfcheck__t1ha1_le() | t1ha_selfcheck__t1ha1_be(); 110 | } 111 | 112 | #endif /* T1HA1_DISABLED */ 113 | -------------------------------------------------------------------------------- /src/t1ha2_selfcheck.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #ifndef T1HA2_DISABLED 45 | #include "t1ha_bits.h" 46 | #include "t1ha_selfcheck.h" 47 | 48 | /* *INDENT-OFF* */ 49 | /* clang-format off */ 50 | 51 | const uint64_t t1ha_refval_2atonce[81] = { 0, 52 | 0x772C7311BE32FF42, 0x444753D23F207E03, 0x71F6DF5DA3B4F532, 0x555859635365F660, 53 | 0xE98808F1CD39C626, 0x2EB18FAF2163BB09, 0x7B9DD892C8019C87, 0xE2B1431C4DA4D15A, 54 | 0x1984E718A5477F70, 0x08DD17B266484F79, 0x4C83A05D766AD550, 0x92DCEBB131D1907D, 55 | 0xD67BC6FC881B8549, 0xF6A9886555FBF66B, 0x6E31616D7F33E25E, 0x36E31B7426E3049D, 56 | 0x4F8E4FAF46A13F5F, 0x03EB0CB3253F819F, 0x636A7769905770D2, 0x3ADF3781D16D1148, 57 | 0x92D19CB1818BC9C2, 0x283E68F4D459C533, 0xFA83A8A88DECAA04, 0x8C6F00368EAC538C, 58 | 0x7B66B0CF3797B322, 0x5131E122FDABA3FF, 0x6E59FF515C08C7A9, 0xBA2C5269B2C377B0, 59 | 0xA9D24FD368FE8A2B, 0x22DB13D32E33E891, 0x7B97DFC804B876E5, 0xC598BDFCD0E834F9, 60 | 0xB256163D3687F5A7, 0x66D7A73C6AEF50B3, 0x25A7201C85D9E2A3, 0x911573EDA15299AA, 61 | 0x5C0062B669E18E4C, 0x17734ADE08D54E28, 0xFFF036E33883F43B, 0xFE0756E7777DF11E, 62 | 0x37972472D023F129, 0x6CFCE201B55C7F57, 0xE019D1D89F02B3E1, 0xAE5CC580FA1BB7E6, 63 | 0x295695FB7E59FC3A, 0x76B6C820A40DD35E, 0xB1680A1768462B17, 0x2FB6AF279137DADA, 64 | 0x28FB6B4366C78535, 0xEC278E53924541B1, 0x164F8AAB8A2A28B5, 0xB6C330AEAC4578AD, 65 | 0x7F6F371070085084, 0x94DEAD60C0F448D3, 0x99737AC232C559EF, 0x6F54A6F9CA8EDD57, 66 | 0x979B01E926BFCE0C, 0xF7D20BC85439C5B4, 0x64EDB27CD8087C12, 0x11488DE5F79C0BE2, 67 | 0x25541DDD1680B5A4, 0x8B633D33BE9D1973, 0x404A3113ACF7F6C6, 0xC59DBDEF8550CD56, 68 | 0x039D23C68F4F992C, 0x5BBB48E4BDD6FD86, 0x41E312248780DF5A, 0xD34791CE75D4E94F, 69 | 0xED523E5D04DCDCFF, 0x7A6BCE0B6182D879, 0x21FB37483CAC28D8, 0x19A1B66E8DA878AD, 70 | 0x6F804C5295B09ABE, 0x2A4BE5014115BA81, 0xA678ECC5FC924BE0, 0x50F7A54A99A36F59, 71 | 0x0FD7E63A39A66452, 0x5AB1B213DD29C4E4, 0xF3ED80D9DF6534C5, 0xC736B12EF90615FD 72 | }; 73 | 74 | const uint64_t t1ha_refval_2atonce128[81] = { 0x4EC7F6A48E33B00A, 75 | 0xB7B7FAA5BD7D8C1E, 0x3269533F66534A76, 0x6C3EC6B687923BFC, 0xC096F5E7EFA471A9, 76 | 0x79D8AFB550CEA471, 0xCEE0507A20FD5119, 0xFB04CFFC14A9F4BF, 0xBD4406E923807AF2, 77 | 0x375C02FF11010491, 0xA6EA4C2A59E173FF, 0xE0A606F0002CADDF, 0xE13BEAE6EBC07897, 78 | 0xF069C2463E48EA10, 0x75BEE1A97089B5FA, 0x378F22F8DE0B8085, 0x9C726FC4D53D0D8B, 79 | 0x71F6130A2D08F788, 0x7A9B20433FF6CF69, 0xFF49B7CD59BF6D61, 0xCCAAEE0D1CA9C6B3, 80 | 0xC77889D86039D2AD, 0x7B378B5BEA9B0475, 0x6520BFA79D59AD66, 0x2441490CB8A37267, 81 | 0xA715A66B7D5CF473, 0x9AE892C88334FD67, 0xD2FFE9AEC1D2169A, 0x790B993F18B18CBB, 82 | 0xA0D02FBCF6A7B1AD, 0xA90833E6F151D0C1, 0x1AC7AFA37BD79BE0, 0xD5383628B2881A24, 83 | 0xE5526F9D63F9F8F1, 0xC1F165A01A6D1F4D, 0x6CCEF8FF3FCFA3F2, 0x2030F18325E6DF48, 84 | 0x289207230E3FB17A, 0x077B66F713A3C4B9, 0x9F39843CAF871754, 0x512FDA0F808ACCF3, 85 | 0xF4D9801CD0CD1F14, 0x28A0C749ED323638, 0x94844CAFA671F01C, 0xD0E261876B8ACA51, 86 | 0x8FC2A648A4792EA2, 0x8EF87282136AF5FE, 0x5FE6A54A9FBA6B40, 0xA3CC5B8FE6223D54, 87 | 0xA8C3C0DD651BB01C, 0x625E9FDD534716F3, 0x1AB2604083C33AC5, 0xDE098853F8692F12, 88 | 0x4B0813891BD87624, 0x4AB89C4553D182AD, 0x92C15AA2A3C27ADA, 0xFF2918D68191F5D9, 89 | 0x06363174F641C325, 0x667112ADA74A2059, 0x4BD605D6B5E53D7D, 0xF2512C53663A14C8, 90 | 0x21857BCB1852667C, 0xAFBEBD0369AEE228, 0x7049340E48FBFD6B, 0x50710E1924F46954, 91 | 0x869A75E04A976A3F, 0x5A41ABBDD6373889, 0xA781778389B4B188, 0x21A3AFCED6C925B6, 92 | 0x107226192EC10B42, 0x62A862E84EC2F9B1, 0x2B15E91659606DD7, 0x613934D1F9EC5A42, 93 | 0x4DC3A96DC5361BAF, 0xC80BBA4CB5F12903, 0x3E3EDAE99A7D6987, 0x8F97B2D55941DCB0, 94 | 0x4C9787364C3E4EC1, 0xEF0A2D07BEA90CA7, 0x5FABF32C70AEEAFB, 0x3356A5CFA8F23BF4 95 | }; 96 | 97 | const uint64_t t1ha_refval_2stream[81] = { 0x3C8426E33CB41606, 98 | 0xFD74BE70EE73E617, 0xF43DE3CDD8A20486, 0x882FBCB37E8EA3BB, 0x1AA2CDD34CAA3D4B, 99 | 0xEE755B2BFAE07ED5, 0xD4E225250D92E213, 0xA09B49083205965B, 0xD47B21724EF9EC9E, 100 | 0xAC888FC3858CEE11, 0x94F820D85736F244, 0x1707951CCA920932, 0x8E0E45603F7877F0, 101 | 0x9FD2592C0E3A7212, 0x9A66370F3AE3D427, 0xD33382D2161DE2B7, 0x9A35BE079DA7115F, 102 | 0x73457C7FF58B4EC3, 0xBE8610BD53D7CE98, 0x65506DFE5CCD5371, 0x286A321AF9D5D9FA, 103 | 0xB81EF9A7EF3C536D, 0x2CFDB5E6825C6E86, 0xB2A58CBFDFDD303A, 0xD26094A42B950635, 104 | 0xA34D666A5F02AD9A, 0x0151E013EBCC72E5, 0x9254A6EA7FCB6BB5, 0x10C9361B3869DC2B, 105 | 0xD7EC55A060606276, 0xA2FF7F8BF8976FFD, 0xB5181BB6852DCC88, 0x0EE394BB6178BAFF, 106 | 0x3A8B4B400D21B89C, 0xEC270461970960FD, 0x615967FAB053877E, 0xFA51BF1CFEB4714C, 107 | 0x29FDA8383070F375, 0xC3B663061BC52EDA, 0x192BBAF1F1A57923, 0x6D193B52F93C53AF, 108 | 0x7F6F5639FE87CA1E, 0x69F7F9140B32EDC8, 0xD0F2416FB24325B6, 0x62C0E37FEDD49FF3, 109 | 0x57866A4B809D373D, 0x9848D24BD935E137, 0xDFC905B66734D50A, 0x9A938DD194A68529, 110 | 0x8276C44DF0625228, 0xA4B35D00AD67C0AB, 0x3D9CB359842DB452, 0x4241BFA8C23B267F, 111 | 0x650FA517BEF15952, 0x782DE2ABD8C7B1E1, 0x4EAE456166CA3E15, 0x40CDF3A02614E337, 112 | 0xAD84092C46102172, 0x0C68479B03F9A167, 0x7E1BA046749E181C, 0x3F3AB41A697382C1, 113 | 0xC5E5DD6586EBFDC4, 0xFF926CD4EB02555C, 0x035CFE67F89E709B, 0x89F06AB6464A1B9D, 114 | 0x8EFF58F3F7DEA758, 0x8B54AC657902089F, 0xC6C4F1F9F8DA4D64, 0xBDB729048AAAC93A, 115 | 0xEA76BA628F5E5CD6, 0x742159B728B8A979, 0x6D151CD3C720E53D, 0xE97FFF9368FCDC42, 116 | 0xCA5B38314914FBDA, 0xDD92C91D8B858EAE, 0x66E5F07CF647CBF2, 0xD4CF9B42F4985AFB, 117 | 0x72AE17AC7D92F6B7, 0xB8206B22AB0472E1, 0x385876B5CFD42479, 0x03294A249EBE6B26 118 | }; 119 | 120 | const uint64_t t1ha_refval_2stream128[81] = { 0xCD2801D3B92237D6, 121 | 0x10E4D47BD821546D, 0x9100704B9D65CD06, 0xD6951CB4016313EF, 0x24DB636F96F474DA, 122 | 0x3F4AF7DF3C49E422, 0xBFF25B8AF143459B, 0xA157EC13538BE549, 0xD3F5F52C47DBD419, 123 | 0x0EF3D7D735AF1575, 0x46B7B892823F7B1B, 0xEE22EA4655213289, 0x56AD76F02FE929BC, 124 | 0x9CF6CD1AC886546E, 0xAF45CE47AEA0B933, 0x535F9DC09F3996B7, 0x1F0C3C01694AE128, 125 | 0x18495069BE0766F7, 0x37E5FFB3D72A4CB1, 0x6D6C2E9299F30709, 0x4F39E693F50B41E3, 126 | 0xB11FC4EF0658E116, 0x48BFAACB78E5079B, 0xE1B4C89C781B3AD0, 0x81D2F34888D333A1, 127 | 0xF6D02270D2EA449C, 0xC884C3C2C3CE1503, 0x711AE16BA157A9B9, 0x1E6140C642558C9D, 128 | 0x35AB3D238F5DC55B, 0x33F07B6AEF051177, 0xE57336776EEFA71C, 0x6D445F8318BA3752, 129 | 0xD4F5F6631934C988, 0xD5E260085727C4A2, 0x5B54B41EC180B4FA, 0x7F5D75769C15A898, 130 | 0xAE5A6DB850CA33C6, 0x038CCB8044663403, 0xDA16310133DC92B8, 0x6A2FFB7AB2B7CE2B, 131 | 0xDC1832D9229BAE20, 0x8C62C479F5ABC9E4, 0x5EB7B617857C9CCB, 0xB79CF7D749A1E80D, 132 | 0xDE7FAC3798324FD3, 0x8178911813685D06, 0x6A726CBD394D4410, 0x6CBE6B3280DA1113, 133 | 0x6829BA4410CF1148, 0xFA7E417EB26C5BC6, 0x22ED87884D6E3A49, 0x15F1472D5115669D, 134 | 0x2EA0B4C8BF69D318, 0xDFE87070AA545503, 0x6B4C14B5F7144AB9, 0xC1ED49C06126551A, 135 | 0x351919FC425C3899, 0x7B569C0FA6F1BD3E, 0x713AC2350844CFFD, 0xE9367F9A638C2FF3, 136 | 0x97F17D325AEA0786, 0xBCB907CC6CF75F91, 0x0CB7517DAF247719, 0xBE16093CC45BE8A9, 137 | 0x786EEE97359AD6AB, 0xB7AFA4F326B97E78, 0x2694B67FE23E502E, 0x4CB492826E98E0B4, 138 | 0x838D119F74A416C7, 0x70D6A91E4E5677FD, 0xF3E4027AD30000E6, 0x9BDF692795807F77, 139 | 0x6A371F966E034A54, 0x8789CF41AE4D67EF, 0x02688755484D60AE, 0xD5834B3A4BF5CE42, 140 | 0x9405FC61440DE25D, 0x35EB280A157979B6, 0x48D40D6A525297AC, 0x6A87DC185054BADA 141 | }; 142 | 143 | /* *INDENT-ON* */ 144 | /* clang-format on */ 145 | 146 | __cold int t1ha_selfcheck__t1ha2_atonce(void) { 147 | return t1ha_selfcheck(t1ha2_atonce, t1ha_refval_2atonce); 148 | } 149 | 150 | __cold static uint64_t thunk_atonce128(const void *data, size_t len, 151 | uint64_t seed) { 152 | uint64_t unused; 153 | return t1ha2_atonce128(&unused, data, len, seed); 154 | } 155 | 156 | __cold int t1ha_selfcheck__t1ha2_atonce128(void) { 157 | return t1ha_selfcheck(thunk_atonce128, t1ha_refval_2atonce128); 158 | } 159 | 160 | __cold static uint64_t thunk_stream(const void *data, size_t len, 161 | uint64_t seed) { 162 | t1ha_context_t ctx; 163 | t1ha2_init(&ctx, seed, seed); 164 | t1ha2_update(&ctx, data, len); 165 | return t1ha2_final(&ctx, NULL); 166 | } 167 | 168 | __cold static uint64_t thunk_stream128(const void *data, size_t len, 169 | uint64_t seed) { 170 | t1ha_context_t ctx; 171 | t1ha2_init(&ctx, seed, seed); 172 | t1ha2_update(&ctx, data, len); 173 | uint64_t unused; 174 | return t1ha2_final(&ctx, &unused); 175 | } 176 | 177 | __cold int t1ha_selfcheck__t1ha2_stream(void) { 178 | return t1ha_selfcheck(thunk_stream, t1ha_refval_2stream) | 179 | t1ha_selfcheck(thunk_stream128, t1ha_refval_2stream128); 180 | } 181 | 182 | __cold int t1ha_selfcheck__t1ha2(void) { 183 | return t1ha_selfcheck__t1ha2_atonce() | t1ha_selfcheck__t1ha2_atonce128() | 184 | t1ha_selfcheck__t1ha2_stream(); 185 | } 186 | 187 | #endif /* T1HA2_DISABLED */ 188 | -------------------------------------------------------------------------------- /src/t1ha_selfcheck.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #include "t1ha_selfcheck.h" 45 | #include "t1ha_bits.h" 46 | 47 | const uint8_t t1ha_test_pattern[64] = { 48 | 0, 1, 2, 3, 4, 5, 6, 7, 0xFF, 0x7F, 0x3F, 49 | 0x1F, 0xF, 8, 16, 32, 64, 0x80, 0xFE, 0xFC, 0xF8, 0xF0, 50 | 0xE0, 0xC0, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x55, 0xAA, 11, 51 | 17, 19, 23, 29, 37, 42, 43, 'a', 'b', 'c', 'd', 52 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 53 | 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x'}; 54 | 55 | static __inline bool probe(uint64_t (*hash)(const void *, size_t, uint64_t), 56 | const uint64_t reference, const void *data, 57 | unsigned len, uint64_t seed) { 58 | const uint64_t actual = hash(data, len, seed); 59 | assert(actual == reference); 60 | return actual != reference; 61 | } 62 | 63 | __cold int t1ha_selfcheck(uint64_t (*hash)(const void *, size_t, uint64_t), 64 | const uint64_t *reference_values) { 65 | bool failed = false; 66 | 67 | const uint64_t zero = 0; 68 | failed |= probe(hash, /* empty-zero */ *reference_values++, NULL, 0, zero); 69 | failed |= probe(hash, /* empty-all1 */ *reference_values++, NULL, 0, ~zero); 70 | failed |= probe(hash, /* bin64-zero */ *reference_values++, t1ha_test_pattern, 71 | 64, zero); 72 | 73 | uint64_t seed = 1; 74 | for (int i = 1; i < 64; i++) { 75 | /* bin%i-1p%i */ 76 | failed |= probe(hash, *reference_values++, t1ha_test_pattern, i, seed); 77 | seed <<= 1; 78 | } 79 | 80 | seed = ~zero; 81 | for (int i = 1; i <= 7; i++) { 82 | seed <<= 1; 83 | /* align%i_F%i */; 84 | failed |= 85 | probe(hash, *reference_values++, t1ha_test_pattern + i, 64 - i, seed); 86 | } 87 | 88 | uint8_t pattern_long[512]; 89 | for (size_t i = 0; i < sizeof(pattern_long); ++i) 90 | pattern_long[i] = (uint8_t)i; 91 | for (int i = 0; i <= 7; i++) { 92 | /* long-%05i */ 93 | failed |= 94 | probe(hash, *reference_values++, pattern_long + i, 128 + i * 17, seed); 95 | } 96 | 97 | return failed ? -1 : 0; 98 | } 99 | -------------------------------------------------------------------------------- /src/t1ha_selfcheck.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #pragma once 45 | #if defined(_MSC_VER) && _MSC_VER > 1800 46 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 47 | #endif /* MSVC */ 48 | #include "../t1ha.h" 49 | 50 | /***************************************************************************/ 51 | /* Self-checking */ 52 | 53 | extern const uint8_t t1ha_test_pattern[64]; 54 | int t1ha_selfcheck(uint64_t (*hash)(const void *, size_t, uint64_t), 55 | const uint64_t *reference_values); 56 | 57 | #ifndef T1HA2_DISABLED 58 | extern const uint64_t t1ha_refval_2atonce[81]; 59 | extern const uint64_t t1ha_refval_2atonce128[81]; 60 | extern const uint64_t t1ha_refval_2stream[81]; 61 | extern const uint64_t t1ha_refval_2stream128[81]; 62 | #endif /* T1HA2_DISABLED */ 63 | 64 | #ifndef T1HA1_DISABLED 65 | extern const uint64_t t1ha_refval_64le[81]; 66 | extern const uint64_t t1ha_refval_64be[81]; 67 | #endif /* T1HA1_DISABLED */ 68 | 69 | #ifndef T1HA0_DISABLED 70 | extern const uint64_t t1ha_refval_32le[81]; 71 | extern const uint64_t t1ha_refval_32be[81]; 72 | #if T1HA0_AESNI_AVAILABLE 73 | extern const uint64_t t1ha_refval_ia32aes_a[81]; 74 | extern const uint64_t t1ha_refval_ia32aes_b[81]; 75 | #endif /* T1HA0_AESNI_AVAILABLE */ 76 | #endif /* T1HA0_DISABLED */ 77 | -------------------------------------------------------------------------------- /src/t1ha_selfcheck_all.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com, 3 | * Fast Positive Hash. 4 | * 5 | * Portions Copyright (c) 2010-2020 Leonid Yuriev , 6 | * The 1Hippeus project (t1h). 7 | * 8 | * This software is provided 'as-is', without any express or implied 9 | * warranty. In no event will the authors be held liable for any damages 10 | * arising from the use of this software. 11 | * 12 | * Permission is granted to anyone to use this software for any purpose, 13 | * including commercial applications, and to alter it and redistribute it 14 | * freely, subject to the following restrictions: 15 | * 16 | * 1. The origin of this software must not be misrepresented; you must not 17 | * claim that you wrote the original software. If you use this software 18 | * in a product, an acknowledgement in the product documentation would be 19 | * appreciated but is not required. 20 | * 2. Altered source versions must be plainly marked as such, and must not be 21 | * misrepresented as being the original software. 22 | * 3. This notice may not be removed or altered from any source distribution. 23 | */ 24 | 25 | /* 26 | * t1ha = { Fast Positive Hash, aka "Позитивный Хэш" } 27 | * by [Positive Technologies](https://www.ptsecurity.ru) 28 | * 29 | * Briefly, it is a 64-bit Hash Function: 30 | * 1. Created for 64-bit little-endian platforms, in predominantly for x86_64, 31 | * but portable and without penalties it can run on any 64-bit CPU. 32 | * 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash 33 | * and all others portable hash-functions (which do not use specific 34 | * hardware tricks). 35 | * 3. Not suitable for cryptography. 36 | * 37 | * The Future will (be) Positive. Всё будет хорошо. 38 | * 39 | * ACKNOWLEDGEMENT: 40 | * The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев) 41 | * for The 1Hippeus project - zerocopy messaging in the spirit of Sparta! 42 | */ 43 | 44 | #include "t1ha_bits.h" 45 | #include "t1ha_selfcheck.h" 46 | 47 | __cold int t1ha_selfcheck__all_enabled(void) { 48 | int rc = 0; 49 | 50 | #ifndef T1HA2_DISABLED 51 | rc |= t1ha_selfcheck__t1ha2(); 52 | #endif /* T1HA2_DISABLED */ 53 | 54 | #ifndef T1HA1_DISABLED 55 | rc |= t1ha_selfcheck__t1ha1(); 56 | #endif /* T1HA1_DISABLED */ 57 | 58 | #ifndef T1HA0_DISABLED 59 | rc |= t1ha_selfcheck__t1ha0(); 60 | #endif /* T1HA0_DISABLED */ 61 | 62 | return rc; 63 | } 64 | -------------------------------------------------------------------------------- /t1ha.creator: -------------------------------------------------------------------------------- 1 | [General] 2 | -------------------------------------------------------------------------------- /t1ha.files: -------------------------------------------------------------------------------- 1 | .travis.yml 2 | LICENSE 3 | Makefile 4 | README.md 5 | circle.yml 6 | meson.build 7 | src/t1ha0.c 8 | src/t1ha0_ia32aes_a.h 9 | src/t1ha0_ia32aes_avx.c 10 | src/t1ha0_ia32aes_avx2.c 11 | src/t1ha0_ia32aes_b.h 12 | src/t1ha0_ia32aes_noavx.c 13 | src/t1ha0_selfcheck.c 14 | src/t1ha1.c 15 | src/t1ha1_selfcheck.c 16 | src/t1ha2.c 17 | src/t1ha2_selfcheck.c 18 | src/t1ha_bits.h 19 | src/t1ha_selfcheck.c 20 | src/t1ha_selfcheck.h 21 | src/t1ha_selfcheck_all.c 22 | t1ha.h 23 | tests/4bench_t1ha0_ia32aes_avx.c 24 | tests/4bench_t1ha0_ia32aes_avx2.c 25 | tests/4bench_t1ha0_ia32aes_noavx.c 26 | tests/bench.c 27 | tests/common.h 28 | tests/highwayhash/4bench_avx2.cc 29 | tests/highwayhash/4bench_portable.cc 30 | tests/highwayhash/4bench_sse41.cc 31 | tests/highwayhash/4bench_vsx.cc 32 | tests/highwayhash/arch_specific.cc 33 | tests/highwayhash/arch_specific.h 34 | tests/highwayhash/compiler_specific.h 35 | tests/highwayhash/endianess.h 36 | tests/highwayhash/hh_avx2.cc 37 | tests/highwayhash/hh_avx2.h 38 | tests/highwayhash/hh_buffer.h 39 | tests/highwayhash/hh_portable.cc 40 | tests/highwayhash/hh_portable.h 41 | tests/highwayhash/hh_sse41.cc 42 | tests/highwayhash/hh_sse41.h 43 | tests/highwayhash/hh_types.h 44 | tests/highwayhash/hh_vsx.cc 45 | tests/highwayhash/hh_vsx.h 46 | tests/highwayhash/highwayhash.h 47 | tests/highwayhash/highwayhash_target.cc 48 | tests/highwayhash/highwayhash_target.h 49 | tests/highwayhash/iaca.h 50 | tests/highwayhash/load3.h 51 | tests/highwayhash/pure_c.c 52 | tests/highwayhash/pure_c.h 53 | tests/highwayhash/vector128.h 54 | tests/highwayhash/vector256.h 55 | tests/highwayhash/verifier.c 56 | tests/main.c 57 | tests/mera.c 58 | tests/mera.h 59 | tests/stadtx/stadtx_hash.h 60 | tests/stadtx/stadtx_thunk.c 61 | tests/test.c 62 | tests/wyhash/LICENSE 63 | tests/wyhash/README.md 64 | tests/wyhash/wyhash.h 65 | tests/wyhash/wyhash_thunk.c 66 | tests/xxhash/xxh3.h 67 | tests/xxhash/xxh_thunk.c 68 | tests/xxhash/xxhash.c 69 | tests/xxhash/xxhash.h 70 | -------------------------------------------------------------------------------- /t1ha.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2024 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "t1ha-test", "t1ha-test.vcxproj", "{BEF30B4A-6826-4166-B11E-5BB8E6FB8682}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "t1ha-static", "t1ha-static.vcxproj", "{EF987F12-27EC-4300-8B20-63A2C7156AFC}" 9 | EndProject 10 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "t1ha-dll", "t1ha-dll.vcxproj", "{E243D17B-648E-429B-ABEB-113B9175FB6C}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|ARM = Debug|ARM 15 | Debug|ARM64 = Debug|ARM64 16 | Debug|x64 = Debug|x64 17 | Debug|x86 = Debug|x86 18 | Release|ARM = Release|ARM 19 | Release|ARM64 = Release|ARM64 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Debug|x64.ActiveCfg = Debug|x64 25 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Debug|x64.Build.0 = Debug|x64 26 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Debug|x86.ActiveCfg = Debug|Win32 27 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Debug|x86.Build.0 = Debug|Win32 28 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Release|x64.ActiveCfg = Release|x64 29 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Release|x64.Build.0 = Release|x64 30 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Release|x86.ActiveCfg = Release|Win32 31 | {BEF30B4A-6826-4166-B11E-5BB8E6FB8682}.Release|x86.Build.0 = Release|Win32 32 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|ARM.ActiveCfg = Debug|ARM 33 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|ARM.Build.0 = Debug|ARM 34 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|ARM64.ActiveCfg = Debug|ARM64 35 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|ARM64.Build.0 = Debug|ARM64 36 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|x64.ActiveCfg = Debug|x64 37 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|x64.Build.0 = Debug|x64 38 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|x86.ActiveCfg = Debug|Win32 39 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Debug|x86.Build.0 = Debug|Win32 40 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|ARM.ActiveCfg = Release|ARM 41 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|ARM.Build.0 = Release|ARM 42 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|ARM64.ActiveCfg = Release|ARM64 43 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|ARM64.Build.0 = Release|ARM64 44 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|x64.ActiveCfg = Release|x64 45 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|x64.Build.0 = Release|x64 46 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|x86.ActiveCfg = Release|Win32 47 | {EF987F12-27EC-4300-8B20-63A2C7156AFC}.Release|x86.Build.0 = Release|Win32 48 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Debug|x64.ActiveCfg = Debug|x64 49 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Debug|x64.Build.0 = Debug|x64 50 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Debug|x86.ActiveCfg = Debug|Win32 51 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Debug|x86.Build.0 = Debug|Win32 52 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Release|x64.ActiveCfg = Release|x64 53 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Release|x64.Build.0 = Release|x64 54 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Release|x86.ActiveCfg = Release|Win32 55 | {E243D17B-648E-429B-ABEB-113B9175FB6C}.Release|x86.Build.0 = Release|Win32 56 | EndGlobalSection 57 | GlobalSection(SolutionProperties) = preSolution 58 | HideSolutionNode = FALSE 59 | EndGlobalSection 60 | GlobalSection(ExtensibilityGlobals) = postSolution 61 | SolutionGuid = {C88E6722-10B0-4766-B350-D6A3C66B5943} 62 | EndGlobalSection 63 | EndGlobal 64 | -------------------------------------------------------------------------------- /tests/4bench_t1ha0_ia32aes_avx.c: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 3 | #endif 4 | 5 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx_a 6 | #include "../src/t1ha0_ia32aes_a.h" 7 | 8 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx_b 9 | #include "../src/t1ha0_ia32aes_b.h" 10 | -------------------------------------------------------------------------------- /tests/4bench_t1ha0_ia32aes_avx2.c: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 3 | #endif 4 | 5 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx2_a 6 | #include "../src/t1ha0_ia32aes_a.h" 7 | 8 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_avx2_b 9 | #include "../src/t1ha0_ia32aes_b.h" 10 | -------------------------------------------------------------------------------- /tests/4bench_t1ha0_ia32aes_noavx.c: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 3 | #endif 4 | 5 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_noavx_a 6 | #include "../src/t1ha0_ia32aes_a.h" 7 | 8 | #define T1HA_IA32AES_NAME t1ha0_ia32aes_noavx_b 9 | #include "../src/t1ha0_ia32aes_b.h" 10 | -------------------------------------------------------------------------------- /tests/bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include "common.h" 23 | #include 24 | #include 25 | #include 26 | 27 | double bench_mats(void) { return mera_bench(NULL, NULL, 0, 0); } 28 | 29 | void bench(const char *caption, 30 | uint64_t (*hash)(const void *, size_t, uint64_t), const void *data, 31 | unsigned len, uint64_t seed) { 32 | 33 | printf("%-24s: ", caption); 34 | fflush(NULL); 35 | 36 | double value = mera_bench(hash, data, len, seed); 37 | printf("%10.3f %s/hash, %6.3f %s/byte, %6.3f byte/%s", value, mera.units, 38 | value / len, mera.units, len / value, mera.units); 39 | 40 | if (mera.flags & timestamp_cycles) { 41 | if (fabs(round(GHz_scale) - GHz_scale) < 0.1) 42 | printf(", %6.3f GiB/s @%.0fGHz", GHz_scale * len / value, GHz_scale); 43 | else 44 | printf(", %6.3f GiB/s @%.1fGHz", GHz_scale * len / value, GHz_scale); 45 | } else if ((mera.flags & timestamp_ticks) == 0) { 46 | printf(", %6.3f GiB/s", len / value); 47 | } 48 | printf(" %s\n", (mera.flags & timestamp_clock_stable) ? "" : "roughly"); 49 | 50 | if (is_option_set(bench_verbose)) { 51 | printf(" - convergence: "); 52 | if (mera_bci.retry_count) 53 | printf("retries %u, ", mera_bci.retry_count); 54 | printf("restarts %u, accounted-loops %u, worthless-loops %u, spent <%us\n", 55 | mera_bci.restart_count, mera_bci.target_accounted_loops, 56 | mera_bci.target_worthless_loops, mera_bci.spent_seconds); 57 | printf(" - mats/overhead: best %" PRIu64 ", gate %" PRIu64 58 | ", inner-loops-max %u, best-count %u\n", 59 | mera_bci.overhead_best, mera_bci.overhead_gate, 60 | mera_bci.overhead_loops_max, mera_bci.overhead_best_count); 61 | printf(" - hash: loops %u, best %" PRIu64 ", gate %" PRIu64 62 | ", tailloops-max %u, best-count %u\n\n", 63 | mera_bci.target_loops, mera_bci.target_best, mera_bci.target_gate, 64 | mera_bci.tail_loops_max, mera_bci.target_best_count); 65 | } 66 | fflush(NULL); 67 | } 68 | 69 | uint64_t thunk_HighwayHash64_pure_c(const void *input, size_t length, 70 | uint64_t seed) { 71 | uint64_t key[4] = {seed, seed, seed, seed}; 72 | return HighwayHash64_pure_c(key, input, length); 73 | } 74 | 75 | void bench_size(const unsigned size, const char *caption) { 76 | printf("\nBench for %s keys (%u bytes):\n", caption, size); 77 | const uint64_t seed = ~UINT64_C(42); 78 | char *buffer = malloc(size); 79 | for (unsigned i = 0; i < size; ++i) 80 | buffer[i] = (char)(rand() + i); 81 | 82 | #ifndef T1HA2_DISABLED 83 | if (is_selected(bench_64 | bench_2)) { 84 | bench("t1ha2_atonce", t1ha2_atonce, buffer, size, seed); 85 | bench("t1ha2_atonce128*", thunk_t1ha2_atonce128, buffer, size, seed); 86 | bench("t1ha2_stream*", thunk_t1ha2_stream, buffer, size, seed); 87 | bench("t1ha2_stream128*", thunk_t1ha2_stream128, buffer, size, seed); 88 | } 89 | #endif 90 | 91 | #ifndef T1HA1_DISABLED 92 | if (is_selected(bench_64 | bench_le | bench_1)) 93 | bench("t1ha1_64le", t1ha1_le, buffer, size, seed); 94 | if (is_selected(bench_64 | bench_be | bench_1)) 95 | bench("t1ha1_64be", t1ha1_be, buffer, size, seed); 96 | #endif 97 | 98 | #ifndef T1HA0_DISABLED 99 | if (is_selected(bench_0)) 100 | bench("t1ha0", t1ha0, buffer, size, seed); 101 | if (is_selected(bench_32 | bench_le | bench_0)) 102 | bench("t1ha0_32le", t1ha0_32le, buffer, size, seed); 103 | if (is_selected(bench_32 | bench_be | bench_0)) 104 | bench("t1ha0_32be", t1ha0_32be, buffer, size, seed); 105 | 106 | #if T1HA0_AESNI_AVAILABLE 107 | if (is_selected(bench_aes)) { 108 | bench("t1ha0_ia32aes_noavx_a", t1ha0_ia32aes_noavx_a, buffer, size, seed); 109 | bench("t1ha0_ia32aes_noavx_b", t1ha0_ia32aes_noavx_b, buffer, size, seed); 110 | bench("t1ha0_ia32aes_noavx", t1ha0_ia32aes_noavx, buffer, size, seed); 111 | if (is_selected(bench_avx)) { 112 | bench("t1ha0_ia32aes_avx_a", t1ha0_ia32aes_avx_a, buffer, size, seed); 113 | bench("t1ha0_ia32aes_avx_b", t1ha0_ia32aes_avx_b, buffer, size, seed); 114 | bench("t1ha0_ia32aes_avx", t1ha0_ia32aes_avx, buffer, size, seed); 115 | } 116 | #ifndef __e2k__ 117 | if (is_selected(bench_avx2)) { 118 | bench("t1ha0_ia32aes_avx2_a", t1ha0_ia32aes_avx2_a, buffer, size, seed); 119 | bench("t1ha0_ia32aes_avx2_b", t1ha0_ia32aes_avx2_b, buffer, size, seed); 120 | bench("t1ha0_ia32aes_avx2", t1ha0_ia32aes_avx2, buffer, size, seed); 121 | } 122 | #endif /* !__e2k__ */ 123 | } 124 | 125 | #endif /* T1HA0_AESNI_AVAILABLE */ 126 | #endif /* T1HA0_DISABLED */ 127 | 128 | if (is_selected(bench_xxhash)) { 129 | bench("xxhash32", XXH_32, buffer, size, (uint32_t)seed); 130 | bench("xxhash64", XXH_64, buffer, size, seed); 131 | bench("xxh3_64", XXH3_64, buffer, size, seed); 132 | bench("xxh3_128", XXH3_128, buffer, size, seed); 133 | } 134 | if (is_selected(bench_stadtx)) { 135 | bench("StadtX", thunk_StadtX, buffer, size, seed); 136 | } 137 | if (is_selected(bench_highwayhash)) { 138 | bench("HighwayHash64_pure_c", thunk_HighwayHash64_pure_c, buffer, size, 139 | seed); 140 | bench("HighwayHash64_portable", thunk_HighwayHash64_Portable, buffer, size, 141 | seed); 142 | #ifdef __ia32__ 143 | if (ia32_cpu_features.basic.ecx & (1ul << 19)) 144 | bench("HighwayHash64_sse41", thunk_HighwayHash64_SSE41, buffer, size, 145 | seed); 146 | if (ia32_cpu_features.extended_7.ebx & 32) 147 | bench("HighwayHash64_avx2", thunk_HighwayHash64_AVX2, buffer, size, seed); 148 | #endif 149 | #ifdef __e2k__ 150 | bench("HighwayHash64_sse41", thunk_HighwayHash64_SSE41, buffer, size, seed); 151 | #endif 152 | /* TODO: thunk_HighwayHash64_VSX() */ 153 | } 154 | if (is_selected(bench_wyhash)) { 155 | bench("wyhash_20221102", thunk_wyhash_20221102, buffer, size, seed); 156 | } 157 | free(buffer); 158 | } 159 | -------------------------------------------------------------------------------- /tests/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #if defined(_MSC_VER) 30 | #pragma warning(disable : 4127) /* conditional expression is constant */ 31 | #if _MSC_VER > 1800 32 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 33 | #endif 34 | #pragma warning(disable : 4204) /* nonstandard extension used: non-constant \ 35 | aggregate initializer */ 36 | #endif /* MSVC */ 37 | 38 | #include "../src/t1ha_selfcheck.h" 39 | #include "../t1ha.h" /* for T1HA0_AESNI_AVAILABLE, __ia32__, etc */ 40 | #include "mera.h" /* for ia32_cpu_features */ 41 | 42 | extern double GHz_scale; 43 | 44 | enum test_flags { 45 | test_verbose = 1u << 0, 46 | test_quiet = 1u << 1, 47 | hash_stdin_strings = 1u << 2, 48 | bench_verbose = 1u << 3, 49 | bench_xxhash = 1u << 4, 50 | bench_highwayhash = 1u << 5, 51 | bench_stadtx = 1u << 6, 52 | bench_wyhash = 1u << 7, 53 | 54 | bench_0 = 1u << 8, 55 | bench_1 = 1u << 9, 56 | bench_2 = 1u << 10, 57 | bench_3 = 1u << 11, 58 | bench_4 = 1u << 12, 59 | bench_5 = 1u << 13, 60 | bench_6 = 1u << 14, 61 | bench_7 = 1u << 15, 62 | 63 | bench_tiny = 1u << 16, 64 | bench_small = 1u << 17, 65 | bench_medium = 1u << 18, 66 | bench_large = 1u << 19, 67 | bench_huge = 1u << 20, 68 | /* 21, 22, 23 */ 69 | bench_size_flags = 70 | bench_tiny | bench_small | bench_medium | bench_large | bench_huge, 71 | 72 | bench_32 = 1u << 24, 73 | bench_64 = 1u << 25, 74 | bench_le = 1u << 26, 75 | bench_be = 1u << 27, 76 | #if T1HA0_AESNI_AVAILABLE || defined(__ia32__) 77 | bench_aes = 1u << 28, 78 | bench_avx = 1u << 29, 79 | #ifndef __e2k__ 80 | bench_avx2 = 1u << 30, 81 | #endif /* !__e2k__ */ 82 | user_wanna_aes = 1u << 31, 83 | #endif /* T1HA0_AESNI_AVAILABLE */ 84 | 85 | bench_funcs_flags = bench_0 | bench_1 | bench_2 | bench_3 | bench_4 | 86 | bench_5 | bench_6 | bench_7 | bench_32 | bench_64 | 87 | bench_le | bench_be | 1u << 28 | 1u << 29 | 1u << 30 | 88 | 1u << 31 | bench_xxhash | bench_highwayhash | 89 | bench_stadtx | bench_wyhash 90 | }; 91 | 92 | extern unsigned option_flags, disabled_option_flags; 93 | 94 | static __inline bool is_option_set(unsigned mask) { 95 | return (option_flags & mask) != 0; 96 | } 97 | 98 | static __inline bool is_selected(unsigned mask) { 99 | return is_option_set(mask) && (disabled_option_flags & mask) == 0; 100 | } 101 | 102 | #if T1HA0_AESNI_AVAILABLE 103 | uint64_t t1ha0_ia32aes_noavx_a(const void *data, size_t length, uint64_t seed); 104 | uint64_t t1ha0_ia32aes_avx_a(const void *data, size_t length, uint64_t seed); 105 | #ifndef __e2k__ 106 | uint64_t t1ha0_ia32aes_avx2_a(const void *data, size_t length, uint64_t seed); 107 | #endif /* !__e2k__ */ 108 | 109 | uint64_t t1ha0_ia32aes_noavx_b(const void *data, size_t length, uint64_t seed); 110 | uint64_t t1ha0_ia32aes_avx_b(const void *data, size_t length, uint64_t seed); 111 | #ifndef __e2k__ 112 | uint64_t t1ha0_ia32aes_avx2_b(const void *data, size_t length, uint64_t seed); 113 | #endif /* !__e2k__ */ 114 | #endif /* T1HA0_AESNI_AVAILABLE */ 115 | 116 | bool verify(const char *title, uint64_t (*hash)(const void *, size_t, uint64_t), 117 | const uint64_t *reference_values); 118 | 119 | uint64_t thunk_t1ha2_atonce128(const void *data, size_t len, uint64_t seed); 120 | uint64_t thunk_t1ha2_stream(const void *data, size_t len, uint64_t seed); 121 | uint64_t thunk_t1ha2_stream128(const void *data, size_t len, uint64_t seed); 122 | 123 | double bench_mats(void); 124 | void bench(const char *caption, 125 | uint64_t (*hash)(const void *, size_t, uint64_t), const void *data, 126 | unsigned len, uint64_t seed); 127 | 128 | void bench_size(const unsigned size, const char *caption); 129 | 130 | /*****************************************************************************/ 131 | /* Other hashes, just for comparison */ 132 | 133 | /* xxHash */ 134 | uint64_t XXH_32(const void *input, size_t length, uint64_t seed); 135 | uint64_t XXH_64(const void *input, size_t length, uint64_t seed); 136 | uint64_t XXH3_64(const void *input, size_t length, uint64_t seed); 137 | uint64_t XXH3_128(const void *input, size_t length, uint64_t seed); 138 | 139 | /* StadtX hash */ 140 | uint64_t thunk_StadtX(const void *input, size_t length, uint64_t seed); 141 | extern const uint64_t refval_StadtX[]; 142 | 143 | /* HighwayHash */ 144 | typedef uint64_t (*HighwayHash64_t)(const uint64_t key[4], const uint8_t *data, 145 | size_t size); 146 | 147 | bool HighwayHash64_verify(HighwayHash64_t fn, const char *title); 148 | 149 | /* HighwayHash C */ 150 | #include "highwayhash/pure_c.h" 151 | uint64_t thunk_HighwayHash64_pure_c(const void *input, size_t length, 152 | uint64_t seed); 153 | 154 | /* HighwayHash CXX */ 155 | uint64_t HighwayHash64_Portable(const uint64_t key[4], const uint8_t *data, 156 | size_t size); 157 | uint64_t HighwayHash64_AVX2(const uint64_t key[4], const uint8_t *data, 158 | size_t size); 159 | uint64_t HighwayHash64_SSE41(const uint64_t key[4], const uint8_t *data, 160 | size_t size); 161 | uint64_t HighwayHash64_VSX(const uint64_t key[4], const uint8_t *data, 162 | size_t size); 163 | 164 | uint64_t thunk_HighwayHash64_Portable(const void *input, size_t length, 165 | uint64_t seed); 166 | uint64_t thunk_HighwayHash64_AVX2(const void *input, size_t length, 167 | uint64_t seed); 168 | uint64_t thunk_HighwayHash64_SSE41(const void *input, size_t length, 169 | uint64_t seed); 170 | uint64_t thunk_HighwayHash64_VSX(const void *input, size_t length, 171 | uint64_t seed); 172 | 173 | /* wyhash 20221102 */ 174 | uint64_t thunk_wyhash_20221102(const void *input, size_t length, uint64_t seed); 175 | extern const uint64_t refval_wyhash_20221102[]; 176 | bool wyhash_20221102_selftest(void); 177 | -------------------------------------------------------------------------------- /tests/highwayhash/4bench_avx2.cc: -------------------------------------------------------------------------------- 1 | #include "highwayhash/hh_avx2.cc" 2 | -------------------------------------------------------------------------------- /tests/highwayhash/4bench_portable.cc: -------------------------------------------------------------------------------- 1 | #include "highwayhash/hh_portable.cc" 2 | -------------------------------------------------------------------------------- /tests/highwayhash/4bench_sse41.cc: -------------------------------------------------------------------------------- 1 | #include "highwayhash/hh_sse41.cc" 2 | -------------------------------------------------------------------------------- /tests/highwayhash/4bench_vsx.cc: -------------------------------------------------------------------------------- 1 | #include "highwayhash/hh_vsx.cc" 2 | -------------------------------------------------------------------------------- /tests/highwayhash/arch_specific.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "highwayhash/arch_specific.h" 16 | 17 | #include 18 | 19 | #if HH_ARCH_X64 && !HH_MSC_VERSION 20 | #include 21 | #endif 22 | 23 | #if HH_ARCH_PPC 24 | #include // __ppc_get_timebase_freq 25 | #endif 26 | 27 | #include // memcpy 28 | #include 29 | 30 | namespace highwayhash { 31 | 32 | const char *TargetName(const TargetBits target_bit) { 33 | switch (target_bit) { 34 | case HH_TARGET_Portable: 35 | return "Portable"; 36 | case HH_TARGET_SSE41: 37 | return "SSE41"; 38 | case HH_TARGET_AVX2: 39 | return "AVX2"; 40 | case HH_TARGET_VSX: 41 | return "VSX"; 42 | default: 43 | return nullptr; // zero, multiple, or unknown bits 44 | } 45 | } 46 | 47 | #if HH_ARCH_X64 48 | 49 | namespace { 50 | 51 | std::string BrandString() { 52 | char brand_string[49]; 53 | uint32_t abcd[4]; 54 | 55 | // Check if brand string is supported (it is on all reasonable Intel/AMD) 56 | Cpuid(0x80000000U, 0, abcd); 57 | if (abcd[0] < 0x80000004U) { 58 | return std::string(); 59 | } 60 | 61 | for (int i = 0; i < 3; ++i) { 62 | Cpuid(0x80000002U + i, 0, abcd); 63 | memcpy(brand_string + i * 16, &abcd, sizeof(abcd)); 64 | } 65 | brand_string[48] = 0; 66 | return brand_string; 67 | } 68 | 69 | } // namespace 70 | 71 | void Cpuid(const uint32_t level, const uint32_t count, 72 | uint32_t *HH_RESTRICT abcd) { 73 | #if HH_MSC_VERSION 74 | int regs[4]; 75 | __cpuidex(regs, level, count); 76 | for (int i = 0; i < 4; ++i) { 77 | abcd[i] = regs[i]; 78 | } 79 | #else 80 | uint32_t a, b, c, d; 81 | __cpuid_count(level, count, a, b, c, d); 82 | abcd[0] = a; 83 | abcd[1] = b; 84 | abcd[2] = c; 85 | abcd[3] = d; 86 | #endif 87 | } 88 | 89 | uint32_t ApicId() { 90 | uint32_t abcd[4]; 91 | Cpuid(1, 0, abcd); 92 | return abcd[1] >> 24; // ebx 93 | } 94 | 95 | #endif // HH_ARCH_X64 96 | 97 | namespace { 98 | 99 | double DetectNominalClockRate() { 100 | #if HH_ARCH_X64 101 | const std::string &brand_string = BrandString(); 102 | // Brand strings include the maximum configured frequency. These prefixes are 103 | // defined by Intel CPUID documentation. 104 | const char *prefixes[3] = {"MHz", "GHz", "THz"}; 105 | const double multipliers[3] = {1E6, 1E9, 1E12}; 106 | for (size_t i = 0; i < 3; ++i) { 107 | const size_t pos_prefix = brand_string.find(prefixes[i]); 108 | if (pos_prefix != std::string::npos) { 109 | const size_t pos_space = brand_string.rfind(' ', pos_prefix - 1); 110 | if (pos_space != std::string::npos) { 111 | const std::string digits = 112 | brand_string.substr(pos_space + 1, pos_prefix - pos_space - 1); 113 | return std::stod(digits) * multipliers[i]; 114 | } 115 | } 116 | } 117 | #elif HH_ARCH_PPC 118 | double freq = -1; 119 | char line[200]; 120 | char *s; 121 | char *value; 122 | 123 | FILE *f = fopen("/proc/cpuinfo", "r"); 124 | if (f != nullptr) { 125 | while (fgets(line, sizeof(line), f) != nullptr) { 126 | // NOTE: the ':' is the only character we can rely on 127 | if (!(value = strchr(line, ':'))) 128 | continue; 129 | // terminate the valuename 130 | *value++ = '\0'; 131 | // skip any leading spaces 132 | while (*value == ' ') 133 | value++; 134 | if ((s = strchr(value, '\n'))) 135 | *s = '\0'; 136 | 137 | if (!strncasecmp(line, "clock", strlen("clock")) && 138 | sscanf(value, "%lf", &freq) == 1) { 139 | freq *= 1E6; 140 | break; 141 | } 142 | } 143 | fclose(f); 144 | return freq; 145 | } 146 | #endif 147 | 148 | return 0.0; 149 | } 150 | 151 | } // namespace 152 | 153 | double NominalClockRate() { 154 | // Thread-safe caching - this is called several times. 155 | static const double cycles_per_second = DetectNominalClockRate(); 156 | return cycles_per_second; 157 | } 158 | 159 | double InvariantTicksPerSecond() { 160 | #if HH_ARCH_PPC 161 | static const double cycles_per_second = __ppc_get_timebase_freq(); 162 | return cycles_per_second; 163 | #else 164 | return NominalClockRate(); 165 | #endif 166 | } 167 | 168 | } // namespace highwayhash 169 | -------------------------------------------------------------------------------- /tests/highwayhash/arch_specific.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_ARCH_SPECIFIC_H_ 16 | #define HIGHWAYHASH_ARCH_SPECIFIC_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. 22 | // 23 | // Background: older GCC/Clang require flags such as -mavx2 before AVX2 SIMD 24 | // intrinsics can be used. These intrinsics are only used within blocks that 25 | // first verify CPU capabilities. However, the flag also allows the compiler to 26 | // generate AVX2 code in other places. This can violate the One Definition Rule, 27 | // which requires multiple instances of a function with external linkage 28 | // (e.g. extern inline in a header) to be "equivalent". To prevent the resulting 29 | // crashes on non-AVX2 CPUs, any header (transitively) included from a 30 | // translation unit compiled with different flags is "restricted". This means 31 | // all function definitions must have internal linkage (e.g. static inline), or 32 | // reside in namespace HH_TARGET_NAME, which expands to a name unique to the 33 | // current compiler flags. 34 | // 35 | // Most C system headers are safe to include, but C++ headers should generally 36 | // be avoided because they often do not specify static linkage and cannot 37 | // reliably be wrapped in a namespace. 38 | 39 | #include "highwayhash/compiler_specific.h" 40 | 41 | #include 42 | 43 | #if HH_MSC_VERSION 44 | #include // _byteswap_* 45 | #endif 46 | 47 | namespace highwayhash { 48 | 49 | #if defined(__x86_64__) || defined(_M_X64) 50 | #define HH_ARCH_X64 1 51 | #else 52 | #define HH_ARCH_X64 0 53 | #endif 54 | 55 | #ifdef __aarch64__ 56 | #define HH_ARCH_AARCH64 1 57 | #else 58 | #define HH_ARCH_AARCH64 0 59 | #endif 60 | 61 | #if defined(__powerpc64__) || defined(_M_PPC) 62 | #define HH_ARCH_PPC 1 63 | #else 64 | #define HH_ARCH_PPC 0 65 | #endif 66 | 67 | // Target := instruction set extension(s) such as SSE41. A translation unit can 68 | // only provide a single target-specific implementation because they require 69 | // different compiler flags. 70 | 71 | // Either the build system specifies the target by defining HH_TARGET_NAME 72 | // (which is necessary for Portable on X64, and SSE41 on MSVC), or we'll choose 73 | // the most efficient one that can be compiled given the current flags: 74 | #ifndef HH_TARGET_NAME 75 | 76 | // To avoid excessive code size and dispatch overhead, we only support a few 77 | // groups of extensions, e.g. FMA+BMI2+AVX+AVX2 =: "AVX2". These names must 78 | // match the HH_TARGET_* suffixes below. 79 | #ifdef __AVX2__ 80 | #define HH_TARGET_NAME AVX2 81 | #elif defined(__SSE4_1__) 82 | #define HH_TARGET_NAME SSE41 83 | #elif defined(__VSX__) 84 | #define HH_TARGET_NAME VSX 85 | #else 86 | #define HH_TARGET_NAME Portable 87 | #endif 88 | 89 | #endif // HH_TARGET_NAME 90 | 91 | #define HH_CONCAT(first, second) first##second 92 | // Required due to macro expansion rules. 93 | #define HH_EXPAND_CONCAT(first, second) HH_CONCAT(first, second) 94 | // Appends HH_TARGET_NAME to "identifier_prefix". 95 | #define HH_ADD_TARGET_SUFFIX(identifier_prefix) \ 96 | HH_EXPAND_CONCAT(identifier_prefix, HH_TARGET_NAME) 97 | 98 | // HH_TARGET expands to an integer constant. Typical usage: HHStateT. 99 | // This ensures your code will work correctly when compiler flags are changed, 100 | // and benefit from subsequently added targets/specializations. 101 | #define HH_TARGET HH_ADD_TARGET_SUFFIX(HH_TARGET_) 102 | 103 | // Deprecated former name of HH_TARGET; please use HH_TARGET instead. 104 | #define HH_TARGET_PREFERRED HH_TARGET 105 | 106 | // Associate targets with integer literals so the preprocessor can compare them 107 | // with HH_TARGET. Do not instantiate templates with these values - use 108 | // HH_TARGET instead. Must be unique powers of two, see TargetBits. Always 109 | // defined even if unavailable on this HH_ARCH to allow calling TargetName. 110 | // The suffixes must match the HH_TARGET_NAME identifiers. 111 | #define HH_TARGET_Portable 1 112 | #define HH_TARGET_SSE41 2 113 | #define HH_TARGET_AVX2 4 114 | #define HH_TARGET_VSX 8 115 | 116 | // Bit array for one or more HH_TARGET_*. Used to indicate which target(s) are 117 | // supported or were called by InstructionSets::RunAll. 118 | using TargetBits = unsigned; 119 | 120 | namespace HH_TARGET_NAME { 121 | 122 | // Calls func(bit_value) for every nonzero bit in "bits". 123 | template void ForeachTarget(TargetBits bits, const Func &func) { 124 | while (bits != 0) { 125 | const TargetBits lowest = bits & (~bits + 1); 126 | func(lowest); 127 | bits &= ~lowest; 128 | } 129 | } 130 | 131 | } // namespace HH_TARGET_NAME 132 | 133 | // Returns a brief human-readable string literal identifying one of the above 134 | // bits, or nullptr if zero, multiple, or unknown bits are set. 135 | const char *TargetName(const TargetBits target_bit); 136 | 137 | // Returns the nominal (without Turbo Boost) CPU clock rate [Hertz]. Useful for 138 | // (roughly) characterizing the CPU speed. 139 | double NominalClockRate(); 140 | 141 | // Returns tsc_timer frequency, useful for converting ticks to seconds. This is 142 | // unaffected by CPU throttling ("invariant"). Thread-safe. Returns timebase 143 | // frequency on PPC and NominalClockRate on all other platforms. 144 | double InvariantTicksPerSecond(); 145 | 146 | #if HH_ARCH_X64 147 | 148 | // Calls CPUID instruction with eax=level and ecx=count and returns the result 149 | // in abcd array where abcd = {eax, ebx, ecx, edx} (hence the name abcd). 150 | void Cpuid(const uint32_t level, const uint32_t count, 151 | uint32_t *HH_RESTRICT abcd); 152 | 153 | // Returns the APIC ID of the CPU on which we're currently running. 154 | uint32_t ApicId(); 155 | 156 | #endif // HH_ARCH_X64 157 | 158 | } // namespace highwayhash 159 | 160 | #endif // HIGHWAYHASH_ARCH_SPECIFIC_H_ 161 | -------------------------------------------------------------------------------- /tests/highwayhash/compiler_specific.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_COMPILER_SPECIFIC_H_ 16 | #define HIGHWAYHASH_COMPILER_SPECIFIC_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 22 | 23 | // Compiler 24 | 25 | // #if is shorter and safer than #ifdef. *_VERSION are zero if not detected, 26 | // otherwise 100 * major + minor version. Note that other packages check for 27 | // #ifdef COMPILER_MSVC, so we cannot use that same name. 28 | 29 | #ifdef _MSC_VER 30 | #define HH_MSC_VERSION _MSC_VER 31 | #else 32 | #define HH_MSC_VERSION 0 33 | #endif 34 | 35 | #ifdef __GNUC__ 36 | #define HH_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) 37 | #else 38 | #define HH_GCC_VERSION 0 39 | #endif 40 | 41 | #ifdef __clang__ 42 | #define HH_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) 43 | #else 44 | #define HH_CLANG_VERSION 0 45 | #endif 46 | 47 | //----------------------------------------------------------------------------- 48 | 49 | #ifndef __has_builtin 50 | #define __has_builtin(x) (0) 51 | #endif 52 | 53 | #if HH_GCC_VERSION && HH_GCC_VERSION < 408 54 | #define HH_ALIGNAS(object, multiple) object __attribute__((aligned(multiple))) 55 | #elif HH_MSC_VERSION && HH_MSC_VERSION < 1900 56 | #define HH_ALIGNAS(object, multiple) __declspec(align(multiple)) object 57 | #else 58 | #define HH_ALIGNAS(object, multiple) object alignas(multiple) // C++11 59 | #endif 60 | 61 | #if HH_MSC_VERSION && HH_MSC_VERSION < 1900 62 | #define constexpr const 63 | #endif 64 | 65 | #if HH_MSC_VERSION 66 | #define HH_RESTRICT __restrict 67 | #elif HH_GCC_VERSION 68 | #define HH_RESTRICT __restrict__ 69 | #else 70 | #define HH_RESTRICT 71 | #endif 72 | 73 | #if HH_MSC_VERSION 74 | #define HH_INLINE __forceinline 75 | #define HH_NOINLINE __declspec(noinline) 76 | #else 77 | #define HH_INLINE inline 78 | #define HH_NOINLINE __attribute__((noinline)) 79 | #endif 80 | 81 | #if HH_MSC_VERSION 82 | // Unsupported, __assume is not the same. 83 | #define HH_LIKELY(expr) expr 84 | #define HH_UNLIKELY(expr) expr 85 | #else 86 | #define HH_LIKELY(expr) __builtin_expect(!!(expr), 1) 87 | #define HH_UNLIKELY(expr) __builtin_expect(!!(expr), 0) 88 | #endif 89 | 90 | #if HH_MSC_VERSION 91 | #include 92 | #pragma intrinsic(_ReadWriteBarrier) 93 | #define HH_COMPILER_FENCE _ReadWriteBarrier() 94 | #elif HH_GCC_VERSION 95 | #define HH_COMPILER_FENCE asm volatile("" : : : "memory") 96 | #else 97 | #define HH_COMPILER_FENCE 98 | #endif 99 | 100 | #endif // HIGHWAYHASH_COMPILER_SPECIFIC_H_ 101 | -------------------------------------------------------------------------------- /tests/highwayhash/endianess.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_ENDIANESS_H_ 16 | #define HIGHWAYHASH_ENDIANESS_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 22 | 23 | #include 24 | 25 | #if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) 26 | 27 | /* Someone has already included or equivalent. */ 28 | 29 | #elif defined(__LITTLE_ENDIAN__) 30 | 31 | #define HH_IS_LITTLE_ENDIAN 1 32 | #define HH_IS_BIG_ENDIAN 0 33 | #ifdef __BIG_ENDIAN__ 34 | #error "Platform is both little and big endian?" 35 | #endif 36 | 37 | #elif defined(__BIG_ENDIAN__) 38 | 39 | #define HH_IS_LITTLE_ENDIAN 0 40 | #define HH_IS_BIG_ENDIAN 1 41 | 42 | #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ 43 | defined(__ORDER_LITTLE_ENDIAN__) 44 | 45 | #define HH_IS_LITTLE_ENDIAN (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) 46 | #define HH_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) 47 | 48 | #elif defined(__linux__) || defined(__CYGWIN__) || defined(__GNUC__) || \ 49 | defined(__GNU_LIBRARY__) 50 | 51 | #include 52 | 53 | #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || \ 54 | defined(__DragonFly__) 55 | 56 | #include 57 | 58 | #elif defined(_WIN32) 59 | 60 | #define HH_IS_LITTLE_ENDIAN 1 61 | #define HH_IS_BIG_ENDIAN 0 62 | 63 | #else 64 | 65 | #error "Unsupported platform. Cannot determine byte order." 66 | 67 | #endif 68 | 69 | #ifndef HH_IS_LITTLE_ENDIAN 70 | #define HH_IS_LITTLE_ENDIAN (BYTE_ORDER == LITTLE_ENDIAN) 71 | #define HH_IS_BIG_ENDIAN (BYTE_ORDER == BIG_ENDIAN) 72 | #endif 73 | 74 | namespace highwayhash { 75 | 76 | #if HH_IS_LITTLE_ENDIAN 77 | 78 | static inline uint32_t le32_from_host(uint32_t x) { return x; } 79 | static inline uint32_t host_from_le32(uint32_t x) { return x; } 80 | static inline uint64_t le64_from_host(uint64_t x) { return x; } 81 | static inline uint64_t host_from_le64(uint64_t x) { return x; } 82 | 83 | #elif !HH_IS_BIG_ENDIAN 84 | 85 | #error "Unsupported byte order." 86 | 87 | #elif defined(_WIN16) || defined(_WIN32) || defined(_WIN64) 88 | 89 | #include 90 | static inline uint32_t host_from_le32(uint32_t x) { return _byteswap_ulong(x); } 91 | static inline uint32_t le32_from_host(uint32_t x) { return _byteswap_ulong(x); } 92 | static inline uint64_t host_from_le64(uint64_t x) { 93 | return _byteswap_uint64(x); 94 | } 95 | static inline uint64_t le64_from_host(uint64_t x) { 96 | return _byteswap_uint64(x); 97 | } 98 | 99 | #else 100 | 101 | static inline uint32_t host_from_le32(uint32_t x) { 102 | return __builtin_bswap32(x); 103 | } 104 | static inline uint32_t le32_from_host(uint32_t x) { 105 | return __builtin_bswap32(x); 106 | } 107 | static inline uint64_t host_from_le64(uint64_t x) { 108 | return __builtin_bswap64(x); 109 | } 110 | static inline uint64_t le64_from_host(uint64_t x) { 111 | return __builtin_bswap64(x); 112 | } 113 | 114 | #endif 115 | 116 | } // namespace highwayhash 117 | 118 | #endif // HIGHWAYHASH_ENDIANESS_H_ 119 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_avx2.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // WARNING: this is a "restricted" source file; avoid including any headers 16 | // unless they are also restricted. See arch_specific.h for details. 17 | 18 | #define HH_TARGET_NAME AVX2 19 | #include "highwayhash/highwayhash_target.cc" 20 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HH_BUFFER_H_ 16 | #define HIGHWAYHASH_HH_BUFFER_H_ 17 | 18 | // Helper functions used by hh_avx2 and hh_sse41. 19 | 20 | // WARNING: this is a "restricted" header because it is included from 21 | // translation units compiled with different flags. This header and its 22 | // dependencies must not define any function unless it is static inline and/or 23 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 24 | 25 | #include "highwayhash/vector128.h" 26 | 27 | // For auto-dependency generation, we need to include all headers but not their 28 | // contents (otherwise compilation fails because -msse4.1 is not specified). 29 | #ifndef HH_DISABLE_TARGET_SPECIFIC 30 | 31 | namespace highwayhash { 32 | // To prevent ODR violations when including this from multiple translation 33 | // units (TU) that are compiled with different flags, the contents must reside 34 | // in a namespace whose name is unique to the TU. NOTE: this behavior is 35 | // incompatible with precompiled modules and requires textual inclusion instead. 36 | namespace HH_TARGET_NAME { 37 | 38 | template struct IntMask {}; // primary template 39 | 40 | template <> struct IntMask<0> { 41 | // Returns 32-bit lanes : ~0U if that lane can be loaded given "size" bytes. 42 | // Typical case: size = 0..16, nothing deducted. 43 | HH_INLINE V4x32U operator()(const V4x32U &size) const { 44 | // Lane n is valid if size >= (n + 1) * 4; subtract one because we only have 45 | // greater-than comparisons and don't want a negated mask. 46 | return V4x32U(_mm_cmpgt_epi32(size, V4x32U(15, 11, 7, 3))); 47 | } 48 | }; 49 | 50 | template <> struct IntMask<16> { 51 | // "size" is 16..31; this is for loading the upper half of a packet, so 52 | // effectively deduct 16 from size by changing the comparands. 53 | HH_INLINE V4x32U operator()(const V4x32U &size) const { 54 | return V4x32U(_mm_cmpgt_epi32(size, V4x32U(31, 27, 23, 19))); 55 | } 56 | }; 57 | 58 | // Inserts "bytes4" into "prev" at the lowest i such that mask[i] = 0. 59 | // Assumes prev[j] == 0 if mask[j] = 0. 60 | HH_INLINE V4x32U Insert4AboveMask(const uint32_t bytes4, const V4x32U &mask, 61 | const V4x32U &prev) { 62 | // There is no 128-bit shift by a variable count. Using shuffle_epi8 with a 63 | // control mask requires a table lookup. We know the shift count is a 64 | // multiple of 4 bytes, so we can broadcastd_epi32 and clear all lanes except 65 | // those where mask != 0. This works because any upper output lanes need not 66 | // be zero. 67 | return prev | AndNot(mask, V4x32U(bytes4)); 68 | } 69 | 70 | // Shifts "suffix" left by "prefix_len" = 0..15 bytes, clears upper bytes of 71 | // "prefix", and returns the merged/concatenated bytes. 72 | HH_INLINE V4x32U Concatenate(const V4x32U &prefix, const size_t prefix_len, 73 | const V4x32U &suffix) { 74 | static const uint64_t table[V16x8U::N][V2x64U::N] = { 75 | {0x0706050403020100ull, 0x0F0E0D0C0B0A0908ull}, 76 | {0x06050403020100FFull, 0x0E0D0C0B0A090807ull}, 77 | {0x050403020100FFFFull, 0x0D0C0B0A09080706ull}, 78 | {0x0403020100FFFFFFull, 0x0C0B0A0908070605ull}, 79 | {0x03020100FFFFFFFFull, 0x0B0A090807060504ull}, 80 | {0x020100FFFFFFFFFFull, 0x0A09080706050403ull}, 81 | {0x0100FFFFFFFFFFFFull, 0x0908070605040302ull}, 82 | {0x00FFFFFFFFFFFFFFull, 0x0807060504030201ull}, 83 | {0xFFFFFFFFFFFFFFFFull, 0x0706050403020100ull}, 84 | {0xFFFFFFFFFFFFFFFFull, 0x06050403020100FFull}, 85 | {0xFFFFFFFFFFFFFFFFull, 0x050403020100FFFFull}, 86 | {0xFFFFFFFFFFFFFFFFull, 0x0403020100FFFFFFull}, 87 | {0xFFFFFFFFFFFFFFFFull, 0x03020100FFFFFFFFull}, 88 | {0xFFFFFFFFFFFFFFFFull, 0x020100FFFFFFFFFFull}, 89 | {0xFFFFFFFFFFFFFFFFull, 0x0100FFFFFFFFFFFFull}, 90 | {0xFFFFFFFFFFFFFFFFull, 0x00FFFFFFFFFFFFFFull}}; 91 | const V2x64U control = Load(&table[prefix_len][0]); 92 | const V2x64U shifted_suffix(_mm_shuffle_epi8(suffix, control)); 93 | return V4x32U(_mm_blendv_epi8(shifted_suffix, prefix, control)); 94 | } 95 | 96 | } // namespace HH_TARGET_NAME 97 | } // namespace highwayhash 98 | 99 | #endif // HH_DISABLE_TARGET_SPECIFIC 100 | #endif // HIGHWAYHASH_HH_BUFFER_H_ 101 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_portable.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // WARNING: this is a "restricted" source file; avoid including any headers 16 | // unless they are also restricted. See arch_specific.h for details. 17 | 18 | #define HH_TARGET_NAME Portable 19 | #include "highwayhash/highwayhash_target.cc" 20 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_portable.h: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HH_PORTABLE_H_ 16 | #define HIGHWAYHASH_HH_PORTABLE_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 22 | 23 | #include "highwayhash/arch_specific.h" 24 | #include "highwayhash/compiler_specific.h" 25 | #include "highwayhash/endianess.h" 26 | #include "highwayhash/hh_types.h" 27 | #include "highwayhash/load3.h" 28 | 29 | namespace highwayhash { 30 | // See vector128.h for why this namespace is necessary; we match it here for 31 | // consistency. As a result, this header requires textual inclusion. 32 | namespace HH_TARGET_NAME { 33 | 34 | class HHStatePortable { 35 | public: 36 | static const int kNumLanes = 4; 37 | using Lanes = uint64_t[kNumLanes]; 38 | 39 | explicit HH_INLINE HHStatePortable(const HHKey keys) { Reset(keys); } 40 | 41 | HH_INLINE void Reset(const HHKey keys) { 42 | static const Lanes init0 = {0xdbe6d5d5fe4cce2full, 0xa4093822299f31d0ull, 43 | 0x13198a2e03707344ull, 0x243f6a8885a308d3ull}; 44 | static const Lanes init1 = {0x3bd39e10cb0ef593ull, 0xc0acf169b5f18a8cull, 45 | 0xbe5466cf34e90c6cull, 0x452821e638d01377ull}; 46 | Lanes rotated_keys; 47 | Rotate64By32(keys, &rotated_keys); 48 | Copy(init0, &mul0); 49 | Copy(init1, &mul1); 50 | Xor(init0, keys, &v0); 51 | Xor(init1, rotated_keys, &v1); 52 | } 53 | 54 | HH_INLINE void Update(const HHPacket &packet) { 55 | Lanes packet_lanes; 56 | CopyPartial(&packet[0], sizeof(HHPacket), 57 | reinterpret_cast(&packet_lanes)); 58 | for (int lane = 0; lane < kNumLanes; ++lane) { 59 | packet_lanes[lane] = host_from_le64(packet_lanes[lane]); 60 | } 61 | Update(packet_lanes); 62 | } 63 | 64 | HH_INLINE void UpdateRemainder(const char *bytes, const size_t size_mod32) { 65 | // 'Length padding' differentiates zero-valued inputs that have the same 66 | // size/32. mod32 is sufficient because each Update behaves as if a 67 | // counter were injected, because the state is large and mixed thoroughly. 68 | const uint64_t mod32_pair = 69 | (static_cast(size_mod32) << 32) + size_mod32; 70 | for (int lane = 0; lane < kNumLanes; ++lane) { 71 | v0[lane] += mod32_pair; 72 | } 73 | Rotate32By(reinterpret_cast(&v1), size_mod32); 74 | 75 | const size_t size_mod4 = size_mod32 & 3; 76 | const char *remainder = bytes + (size_mod32 & ~3); 77 | 78 | HHPacket HH_ALIGNAS(packet, 32) = {0}; 79 | CopyPartial(bytes, remainder - bytes, &packet[0]); 80 | 81 | if (size_mod32 & 16) { // 16..31 bytes left 82 | // Read the last 0..3 bytes and previous 1..4 into the upper bits. 83 | // Insert into the upper four bytes of packet, which are zero. 84 | uint32_t last4 = 85 | Load3()(Load3::AllowReadBeforeAndReturn(), remainder, size_mod4); 86 | CopyPartial(reinterpret_cast(&last4), 4, &packet[28]); 87 | } else { // size_mod32 < 16 88 | uint64_t last4 = Load3()(Load3::AllowUnordered(), remainder, size_mod4); 89 | 90 | // Rather than insert at packet + 28, it is faster to initialize 91 | // the otherwise empty packet + 16 with up to 64 bits of padding. 92 | CopyPartial(reinterpret_cast(&last4), sizeof(last4), 93 | &packet[16]); 94 | } 95 | Update(packet); 96 | } 97 | 98 | HH_INLINE void Finalize(HHResult64 *HH_RESTRICT result) { 99 | for (int n = 0; n < 4; n++) { 100 | PermuteAndUpdate(); 101 | } 102 | 103 | *result = v0[0] + v1[0] + mul0[0] + mul1[0]; 104 | } 105 | 106 | HH_INLINE void Finalize(HHResult128 *HH_RESTRICT result) { 107 | for (int n = 0; n < 6; n++) { 108 | PermuteAndUpdate(); 109 | } 110 | 111 | (*result)[0] = v0[0] + mul0[0] + v1[2] + mul1[2]; 112 | (*result)[1] = v0[1] + mul0[1] + v1[3] + mul1[3]; 113 | } 114 | 115 | HH_INLINE void Finalize(HHResult256 *HH_RESTRICT result) { 116 | for (int n = 0; n < 10; n++) { 117 | PermuteAndUpdate(); 118 | } 119 | 120 | ModularReduction(v1[1] + mul1[1], v1[0] + mul1[0], v0[1] + mul0[1], 121 | v0[0] + mul0[0], &(*result)[1], &(*result)[0]); 122 | ModularReduction(v1[3] + mul1[3], v1[2] + mul1[2], v0[3] + mul0[3], 123 | v0[2] + mul0[2], &(*result)[3], &(*result)[2]); 124 | } 125 | 126 | static HH_INLINE void ZeroInitialize(char *HH_RESTRICT buffer) { 127 | for (size_t i = 0; i < sizeof(HHPacket); ++i) { 128 | buffer[i] = 0; 129 | } 130 | } 131 | 132 | static HH_INLINE void CopyPartial(const char *HH_RESTRICT from, 133 | const size_t size_mod32, 134 | char *HH_RESTRICT buffer) { 135 | for (size_t i = 0; i < size_mod32; ++i) { 136 | buffer[i] = from[i]; 137 | } 138 | } 139 | 140 | static HH_INLINE void AppendPartial(const char *HH_RESTRICT from, 141 | const size_t size_mod32, 142 | char *HH_RESTRICT buffer, 143 | const size_t buffer_valid) { 144 | for (size_t i = 0; i < size_mod32; ++i) { 145 | buffer[buffer_valid + i] = from[i]; 146 | } 147 | } 148 | 149 | HH_INLINE void AppendAndUpdate(const char *HH_RESTRICT from, 150 | const size_t size_mod32, 151 | const char *HH_RESTRICT buffer, 152 | const size_t buffer_valid) { 153 | HHPacket HH_ALIGNAS(tmp, 32); 154 | for (size_t i = 0; i < buffer_valid; ++i) { 155 | tmp[i] = buffer[i]; 156 | } 157 | for (size_t i = 0; i < size_mod32; ++i) { 158 | tmp[buffer_valid + i] = from[i]; 159 | } 160 | Update(tmp); 161 | } 162 | 163 | private: 164 | static HH_INLINE void Copy(const Lanes &source, Lanes *HH_RESTRICT dest) { 165 | for (int lane = 0; lane < kNumLanes; ++lane) { 166 | (*dest)[lane] = source[lane]; 167 | } 168 | } 169 | 170 | static HH_INLINE void Add(const Lanes &source, Lanes *HH_RESTRICT dest) { 171 | for (int lane = 0; lane < kNumLanes; ++lane) { 172 | (*dest)[lane] += source[lane]; 173 | } 174 | } 175 | 176 | template 177 | static HH_INLINE void Xor(const Lanes &op1, const LanesOrPointer &op2, 178 | Lanes *HH_RESTRICT dest) { 179 | for (int lane = 0; lane < kNumLanes; ++lane) { 180 | (*dest)[lane] = op1[lane] ^ op2[lane]; 181 | } 182 | } 183 | 184 | // Clears all bits except one byte at the given offset. 185 | #define MASK(v, bytes) ((v) & (0xFFull << ((bytes)*8))) 186 | 187 | // 16-byte permutation; shifting is about 10% faster than byte loads. 188 | // Adds zipper-merge result to add*. 189 | static HH_INLINE void ZipperMergeAndAdd(const uint64_t v1, const uint64_t v0, 190 | uint64_t *HH_RESTRICT add1, 191 | uint64_t *HH_RESTRICT add0) { 192 | *add0 += ((MASK(v0, 3) + MASK(v1, 4)) >> 24) + 193 | ((MASK(v0, 5) + MASK(v1, 6)) >> 16) + MASK(v0, 2) + 194 | (MASK(v0, 1) << 32) + (MASK(v1, 7) >> 8) + (v0 << 56); 195 | 196 | *add1 += ((MASK(v1, 3) + MASK(v0, 4)) >> 24) + MASK(v1, 2) + 197 | (MASK(v1, 5) >> 16) + (MASK(v1, 1) << 24) + (MASK(v0, 6) >> 8) + 198 | (MASK(v1, 0) << 48) + MASK(v0, 7); 199 | } 200 | 201 | #undef MASK 202 | 203 | // For inputs that are already in native byte order (e.g. PermuteAndAdd) 204 | HH_INLINE void Update(const Lanes &packet_lanes) { 205 | Add(packet_lanes, &v1); 206 | Add(mul0, &v1); 207 | 208 | // (Loop is faster than unrolling) 209 | for (int lane = 0; lane < kNumLanes; ++lane) { 210 | const uint32_t v1_32 = static_cast(v1[lane]); 211 | mul0[lane] ^= v1_32 * (v0[lane] >> 32); 212 | v0[lane] += mul1[lane]; 213 | const uint32_t v0_32 = static_cast(v0[lane]); 214 | mul1[lane] ^= v0_32 * (v1[lane] >> 32); 215 | } 216 | 217 | ZipperMergeAndAdd(v1[1], v1[0], &v0[1], &v0[0]); 218 | ZipperMergeAndAdd(v1[3], v1[2], &v0[3], &v0[2]); 219 | 220 | ZipperMergeAndAdd(v0[1], v0[0], &v1[1], &v1[0]); 221 | ZipperMergeAndAdd(v0[3], v0[2], &v1[3], &v1[2]); 222 | } 223 | 224 | static HH_INLINE uint64_t Rotate64By32(const uint64_t x) { 225 | return (x >> 32) | (x << 32); 226 | } 227 | 228 | template 229 | static HH_INLINE void Rotate64By32(const LanesOrPointer &v, 230 | Lanes *HH_RESTRICT rotated) { 231 | for (int i = 0; i < kNumLanes; ++i) { 232 | (*rotated)[i] = Rotate64By32(v[i]); 233 | } 234 | } 235 | 236 | static HH_INLINE void Rotate32By(uint32_t *halves, const uint64_t count) { 237 | for (int i = 0; i < 2 * kNumLanes; ++i) { 238 | const uint32_t x = halves[i]; 239 | halves[i] = (x << count) | (x >> (32 - count)); 240 | } 241 | } 242 | 243 | static HH_INLINE void Permute(const Lanes &v, Lanes *HH_RESTRICT permuted) { 244 | (*permuted)[0] = Rotate64By32(v[2]); 245 | (*permuted)[1] = Rotate64By32(v[3]); 246 | (*permuted)[2] = Rotate64By32(v[0]); 247 | (*permuted)[3] = Rotate64By32(v[1]); 248 | } 249 | 250 | HH_INLINE void PermuteAndUpdate() { 251 | Lanes permuted; 252 | Permute(v0, &permuted); 253 | Update(permuted); 254 | } 255 | 256 | // Computes a << kBits for 128-bit a = (a1, a0). 257 | // Bit shifts are only possible on independent 64-bit lanes. We therefore 258 | // insert the upper bits of a0 that were lost into a1. This is slightly 259 | // shorter than Lemire's (a << 1) | (((a >> 8) << 1) << 8) approach. 260 | template 261 | static HH_INLINE void Shift128Left(uint64_t *HH_RESTRICT a1, 262 | uint64_t *HH_RESTRICT a0) { 263 | const uint64_t shifted1 = (*a1) << kBits; 264 | const uint64_t top_bits = (*a0) >> (64 - kBits); 265 | *a0 <<= kBits; 266 | *a1 = shifted1 | top_bits; 267 | } 268 | 269 | // Modular reduction by the irreducible polynomial (x^128 + x^2 + x). 270 | // Input: a 256-bit number a3210. 271 | static HH_INLINE void ModularReduction(const uint64_t a3_unmasked, 272 | const uint64_t a2, const uint64_t a1, 273 | const uint64_t a0, 274 | uint64_t *HH_RESTRICT m1, 275 | uint64_t *HH_RESTRICT m0) { 276 | // The upper two bits must be clear, otherwise a3 << 2 would lose bits, 277 | // in which case we're no longer computing a reduction. 278 | const uint64_t a3 = a3_unmasked & 0x3FFFFFFFFFFFFFFFull; 279 | // See Lemire, https://arxiv.org/pdf/1503.03465v8.pdf. 280 | uint64_t a3_shl1 = a3; 281 | uint64_t a2_shl1 = a2; 282 | uint64_t a3_shl2 = a3; 283 | uint64_t a2_shl2 = a2; 284 | Shift128Left<1>(&a3_shl1, &a2_shl1); 285 | Shift128Left<2>(&a3_shl2, &a2_shl2); 286 | *m1 = a1 ^ a3_shl1 ^ a3_shl2; 287 | *m0 = a0 ^ a2_shl1 ^ a2_shl2; 288 | } 289 | 290 | Lanes v0; 291 | Lanes v1; 292 | Lanes mul0; 293 | Lanes mul1; 294 | }; 295 | 296 | } // namespace HH_TARGET_NAME 297 | } // namespace highwayhash 298 | 299 | #endif // HIGHWAYHASH_HH_PORTABLE_H_ 300 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_sse41.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // WARNING: this is a "restricted" source file; avoid including any headers 16 | // unless they are also restricted. See arch_specific.h for details. 17 | 18 | #define HH_TARGET_NAME SSE41 19 | #include "highwayhash/highwayhash_target.cc" 20 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HH_TYPES_H_ 16 | #define HIGHWAYHASH_HH_TYPES_H_ 17 | 18 | // WARNING: included from c_bindings => must be C-compatible. 19 | // WARNING: this is a "restricted" header because it is included from 20 | // translation units compiled with different flags. This header and its 21 | // dependencies must not define any function unless it is static inline and/or 22 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 23 | 24 | #include // size_t 25 | #include 26 | 27 | #ifdef __cplusplus 28 | namespace highwayhash { 29 | #endif 30 | 31 | // 256-bit secret key that should remain unknown to attackers. 32 | // We recommend initializing it to a random value. 33 | typedef uint64_t HHKey[4]; 34 | 35 | // How much input is hashed by one call to HHStateT::Update. 36 | typedef char HHPacket[32]; 37 | 38 | // Hash 'return' types. 39 | typedef uint64_t HHResult64; // returned directly 40 | typedef uint64_t HHResult128[2]; 41 | typedef uint64_t HHResult256[4]; 42 | 43 | // Called if a test fails, indicating which target and size. 44 | typedef void (*HHNotify)(const char *, size_t); 45 | 46 | #ifdef __cplusplus 47 | } // namespace highwayhash 48 | #endif 49 | 50 | #endif // HIGHWAYHASH_HH_TYPES_H_ 51 | -------------------------------------------------------------------------------- /tests/highwayhash/hh_vsx.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // WARNING: this is a "restricted" source file; avoid including any headers 16 | // unless they are also restricted. See arch_specific.h for details. 17 | 18 | #define HH_TARGET_NAME VSX 19 | 20 | #ifdef __VSX__ 21 | #include "highwayhash/highwayhash_target.cc" 22 | #endif 23 | -------------------------------------------------------------------------------- /tests/highwayhash/highwayhash.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HIGHWAYHASH_H_ 16 | #define HIGHWAYHASH_HIGHWAYHASH_H_ 17 | 18 | // This header's templates are useful for inlining into other CPU-specific code: 19 | // template CodeUsingHash() { HighwayHashT(...); }, 20 | // and can also be instantiated with HH_TARGET when callers don't care about the 21 | // exact implementation. Otherwise, they are implementation details of the 22 | // highwayhash_target wrapper. Use that instead if you need to detect the best 23 | // available implementation at runtime. 24 | 25 | // WARNING: this is a "restricted" header because it is included from 26 | // translation units compiled with different flags. This header and its 27 | // dependencies must not define any function unless it is static inline and/or 28 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 29 | 30 | #include "highwayhash/arch_specific.h" 31 | #include "highwayhash/compiler_specific.h" 32 | #include "highwayhash/hh_types.h" 33 | 34 | #if HH_ARCH_X64 35 | #include "highwayhash/iaca.h" 36 | #endif 37 | 38 | // Include exactly one (see arch_specific.h) header, which defines a state 39 | // object in a target-specific namespace, e.g. AVX2::HHStateAVX2. 40 | // Attempts to use "computed includes" (#define MACRO "path/or_just_filename", 41 | // #include MACRO) fail with 'file not found', so we need an #if chain. 42 | #if HH_TARGET == HH_TARGET_AVX2 43 | #include "highwayhash/hh_avx2.h" 44 | #elif HH_TARGET == HH_TARGET_SSE41 45 | #include "highwayhash/hh_sse41.h" 46 | #elif HH_TARGET == HH_TARGET_VSX 47 | #include "highwayhash/hh_vsx.h" 48 | #elif HH_TARGET == HH_TARGET_Portable 49 | #include "highwayhash/hh_portable.h" 50 | #else 51 | #error "Unknown target, add its hh_*.h include here." 52 | #endif 53 | 54 | #ifndef HH_DISABLE_TARGET_SPECIFIC 55 | namespace highwayhash { 56 | 57 | // Alias templates (HHStateT) cannot be specialized, so we need a helper struct. 58 | // Note that hh_*.h don't just specialize HHStateT directly because vector128.h 59 | // must reside in a distinct namespace (to allow including it from multiple 60 | // translation units), and it is easier if its users, i.e. the concrete HHState, 61 | // also reside in that same namespace, which precludes specialization. 62 | template struct HHStateForTarget {}; 63 | 64 | template <> struct HHStateForTarget { 65 | // (The namespace is sufficient and the additional HH_TARGET_NAME suffix is 66 | // technically redundant, but it makes searching easier.) 67 | using type = HH_TARGET_NAME::HH_ADD_TARGET_SUFFIX(HHState); 68 | }; 69 | 70 | // Typically used as HHStateT. It would be easier to just have a 71 | // concrete type HH_STATE, but this alias template is required by the 72 | // templates in highwayhash_target.cc. 73 | template 74 | using HHStateT = typename HHStateForTarget::type; 75 | 76 | // Computes HighwayHash of "bytes" using the implementation chosen by "State". 77 | // 78 | // "state" is a HHStateT<> initialized with a key. 79 | // "bytes" is the data to hash (possibly unaligned). 80 | // "size" is the number of bytes to hash; we do not read any additional bytes. 81 | // "hash" is a HHResult* (either 64, 128 or 256 bits). 82 | // 83 | // HighwayHash is a strong pseudorandom function with security claims 84 | // [https://arxiv.org/abs/1612.06257]. It is intended as a safer general-purpose 85 | // hash, about 4x faster than SipHash and 10x faster than BLAKE2. 86 | // 87 | // This template allows callers (e.g. tests) to invoke a specific 88 | // implementation. It must be compiled with the flags required by the desired 89 | // implementation. If the entire program cannot be built with these flags, use 90 | // the wrapper in highwayhash_target.h instead. 91 | // 92 | // Callers wanting to hash multiple pieces of data should duplicate this 93 | // function, calling HHStateT::Update for each input and only Finalizing once. 94 | template 95 | HH_INLINE void HighwayHashT(State *HH_RESTRICT state, 96 | const char *HH_RESTRICT bytes, const size_t size, 97 | Result *HH_RESTRICT hash) { 98 | // BeginIACA(); 99 | const size_t remainder = size & (sizeof(HHPacket) - 1); 100 | const size_t truncated = size & ~(sizeof(HHPacket) - 1); 101 | for (size_t offset = 0; offset < truncated; offset += sizeof(HHPacket)) { 102 | state->Update(*reinterpret_cast(bytes + offset)); 103 | } 104 | 105 | if (remainder != 0) { 106 | state->UpdateRemainder(bytes + truncated, remainder); 107 | } 108 | 109 | state->Finalize(hash); 110 | // EndIACA(); 111 | } 112 | 113 | // Wrapper class for incrementally hashing a series of data ranges. The final 114 | // result is the same as HighwayHashT of the concatenation of all the ranges. 115 | // This is useful for computing the hash of cords, iovecs, and similar 116 | // data structures. 117 | template class HighwayHashCatT { 118 | public: 119 | HH_INLINE HighwayHashCatT(const HHKey &key) : state_(key) { 120 | // Avoids msan uninitialized-memory warnings. 121 | HHStateT::ZeroInitialize(buffer_); 122 | } 123 | 124 | // Resets the state of the hasher so it can be used to hash a new string. 125 | HH_INLINE void Reset(const HHKey &key) { 126 | state_.Reset(key); 127 | buffer_usage_ = 0; 128 | } 129 | 130 | // Adds "bytes" to the internal buffer, feeding it to HHStateT::Update as 131 | // required. Call this as often as desired. Only reads bytes within the 132 | // interval [bytes, bytes + num_bytes). "num_bytes" == 0 has no effect. 133 | // There are no alignment requirements. 134 | HH_INLINE void Append(const char *HH_RESTRICT bytes, size_t num_bytes) { 135 | // BeginIACA(); 136 | const size_t capacity = sizeof(HHPacket) - buffer_usage_; 137 | // New bytes fit within buffer, but still not enough to Update. 138 | if (HH_UNLIKELY(num_bytes < capacity)) { 139 | HHStateT::AppendPartial(bytes, num_bytes, buffer_, buffer_usage_); 140 | buffer_usage_ += num_bytes; 141 | return; 142 | } 143 | 144 | // HACK: ensures the state is kept in SIMD registers; otherwise, Update 145 | // constantly load/stores its operands, which is much slower. 146 | // Restrict-qualified pointers to external state or the state_ member are 147 | // not sufficient for keeping this in registers. 148 | HHStateT state_copy = state_; 149 | 150 | // Have prior bytes to flush. 151 | const size_t buffer_usage = buffer_usage_; 152 | if (HH_LIKELY(buffer_usage != 0)) { 153 | // Calls update with prior buffer contents plus new data. Does not modify 154 | // the buffer because some implementations can load into SIMD registers 155 | // and Append to them directly. 156 | state_copy.AppendAndUpdate(bytes, capacity, buffer_, buffer_usage); 157 | bytes += capacity; 158 | num_bytes -= capacity; 159 | } 160 | 161 | // Buffer currently empty => Update directly from the source. 162 | while (num_bytes >= sizeof(HHPacket)) { 163 | state_copy.Update(*reinterpret_cast(bytes)); 164 | bytes += sizeof(HHPacket); 165 | num_bytes -= sizeof(HHPacket); 166 | } 167 | 168 | // Unconditionally assign even if zero because we didn't reset to zero 169 | // after the AppendAndUpdate above. 170 | buffer_usage_ = num_bytes; 171 | 172 | state_ = state_copy; 173 | 174 | // Store any remainders in buffer, no-op if multiple of a packet. 175 | if (HH_LIKELY(num_bytes != 0)) { 176 | HHStateT::CopyPartial(bytes, num_bytes, buffer_); 177 | } 178 | // EndIACA(); 179 | } 180 | 181 | // Stores the resulting 64, 128 or 256-bit hash of all data passed to Append. 182 | // Must be called exactly once, or after a prior Reset. 183 | template // HHResult* 184 | HH_INLINE void Finalize(Result *HH_RESTRICT hash) { 185 | // BeginIACA(); 186 | HHStateT state_copy = state_; 187 | const size_t buffer_usage = buffer_usage_; 188 | if (HH_LIKELY(buffer_usage != 0)) { 189 | state_copy.UpdateRemainder(buffer_, buffer_usage); 190 | } 191 | state_copy.Finalize(hash); 192 | // EndIACA(); 193 | } 194 | 195 | private: 196 | HHPacket HH_ALIGNAS(buffer_, 64); 197 | HHStateT HH_ALIGNAS(state_, 32); 198 | // How many bytes in buffer_ (starting with offset 0) are valid. 199 | size_t buffer_usage_ = 0; 200 | }; 201 | 202 | } // namespace highwayhash 203 | #endif // HH_DISABLE_TARGET_SPECIFIC 204 | #endif // HIGHWAYHASH_HIGHWAYHASH_H_ 205 | -------------------------------------------------------------------------------- /tests/highwayhash/highwayhash_target.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // WARNING: this is a "restricted" source file; avoid including any headers 16 | // unless they are also restricted. See arch_specific.h for details. 17 | 18 | #include "highwayhash/highwayhash_target.h" 19 | 20 | #include "highwayhash/highwayhash.h" 21 | 22 | #ifndef HH_DISABLE_TARGET_SPECIFIC 23 | namespace highwayhash { 24 | 25 | extern "C" { 26 | uint64_t HH_ADD_TARGET_SUFFIX(HighwayHash64_)(const HHKey key, 27 | const char *bytes, 28 | const size_t size) { 29 | HHStateT state(key); 30 | HHResult64 result; 31 | HighwayHashT(&state, bytes, size, &result); 32 | return result; 33 | } 34 | 35 | uint64_t HH_ADD_TARGET_SUFFIX(thunk_HighwayHash64_)(const void *input, 36 | size_t length, 37 | uint64_t seed) { 38 | uint64_t key[4] = {seed, seed, seed, seed}; 39 | HHStateT state(key); 40 | HHResult64 result; 41 | HighwayHashT(&state, (const char *)input, length, &result); 42 | return result; 43 | } 44 | 45 | } // extern "C" 46 | 47 | template 48 | void HighwayHash::operator()(const HHKey &key, 49 | const char *HH_RESTRICT bytes, 50 | const size_t size, 51 | HHResult64 *HH_RESTRICT hash) const { 52 | HHStateT state(key); 53 | HighwayHashT(&state, bytes, size, hash); 54 | } 55 | 56 | template 57 | void HighwayHash::operator()(const HHKey &key, 58 | const char *HH_RESTRICT bytes, 59 | const size_t size, 60 | HHResult128 *HH_RESTRICT hash) const { 61 | HHStateT state(key); 62 | HighwayHashT(&state, bytes, size, hash); 63 | } 64 | 65 | template 66 | void HighwayHash::operator()(const HHKey &key, 67 | const char *HH_RESTRICT bytes, 68 | const size_t size, 69 | HHResult256 *HH_RESTRICT hash) const { 70 | HHStateT state(key); 71 | HighwayHashT(&state, bytes, size, hash); 72 | } 73 | 74 | template 75 | void HighwayHashCat::operator()(const HHKey &key, 76 | const StringView *HH_RESTRICT fragments, 77 | const size_t num_fragments, 78 | HHResult64 *HH_RESTRICT hash) const { 79 | HighwayHashCatT cat(key); 80 | for (size_t i = 0; i < num_fragments; ++i) { 81 | cat.Append(fragments[i].data, fragments[i].num_bytes); 82 | } 83 | cat.Finalize(hash); 84 | } 85 | 86 | template 87 | void HighwayHashCat::operator()(const HHKey &key, 88 | const StringView *HH_RESTRICT fragments, 89 | const size_t num_fragments, 90 | HHResult128 *HH_RESTRICT hash) const { 91 | HighwayHashCatT cat(key); 92 | for (size_t i = 0; i < num_fragments; ++i) { 93 | cat.Append(fragments[i].data, fragments[i].num_bytes); 94 | } 95 | cat.Finalize(hash); 96 | } 97 | 98 | template 99 | void HighwayHashCat::operator()(const HHKey &key, 100 | const StringView *HH_RESTRICT fragments, 101 | const size_t num_fragments, 102 | HHResult256 *HH_RESTRICT hash) const { 103 | HighwayHashCatT cat(key); 104 | for (size_t i = 0; i < num_fragments; ++i) { 105 | cat.Append(fragments[i].data, fragments[i].num_bytes); 106 | } 107 | cat.Finalize(hash); 108 | } 109 | 110 | // Instantiate for the current target. 111 | template struct HighwayHash; 112 | template struct HighwayHashCat; 113 | 114 | } // namespace highwayhash 115 | #endif // HH_DISABLE_TARGET_SPECIFIC 116 | -------------------------------------------------------------------------------- /tests/highwayhash/highwayhash_target.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HIGHWAYHASH_TARGET_H_ 16 | #define HIGHWAYHASH_HIGHWAYHASH_TARGET_H_ 17 | 18 | // Adapter for the InstructionSets::Run dispatcher, which invokes the best 19 | // implementations available on the current CPU. 20 | 21 | // WARNING: this is a "restricted" header because it is included from 22 | // translation units compiled with different flags. This header and its 23 | // dependencies must not define any function unless it is static inline and/or 24 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 25 | 26 | #include "highwayhash/arch_specific.h" 27 | #include "highwayhash/compiler_specific.h" 28 | #include "highwayhash/hh_types.h" 29 | 30 | namespace highwayhash { 31 | 32 | // Usage: InstructionSets::Run(key, bytes, size, hash). 33 | // This incurs some small dispatch overhead. If the entire program is compiled 34 | // for the target CPU, you can instead call HighwayHashT directly to avoid any 35 | // overhead. This template is instantiated in the source file, which is 36 | // compiled once for every target with the required flags (e.g. -mavx2). 37 | template struct HighwayHash { 38 | // Stores a 64/128/256 bit hash of "bytes" using the HighwayHashT 39 | // implementation for the "Target" CPU. The hash result is identical 40 | // regardless of which implementation is used. 41 | // 42 | // "key" is a (randomly generated or hard-coded) HHKey. 43 | // "bytes" is the data to hash (possibly unaligned). 44 | // "size" is the number of bytes to hash; we do not read any additional bytes. 45 | // "hash" is a HHResult* (either 64, 128 or 256 bits). 46 | // 47 | // HighwayHash is a strong pseudorandom function with security claims 48 | // [https://arxiv.org/abs/1612.06257]. It is intended as a safer 49 | // general-purpose hash, 5x faster than SipHash and 10x faster than BLAKE2. 50 | void operator()(const HHKey &key, const char *HH_RESTRICT bytes, 51 | const size_t size, HHResult64 *HH_RESTRICT hash) const; 52 | void operator()(const HHKey &key, const char *HH_RESTRICT bytes, 53 | const size_t size, HHResult128 *HH_RESTRICT hash) const; 54 | void operator()(const HHKey &key, const char *HH_RESTRICT bytes, 55 | const size_t size, HHResult256 *HH_RESTRICT hash) const; 56 | }; 57 | 58 | // Replacement for C++17 std::string_view that avoids dependencies. 59 | // A struct requires fewer allocations when calling HighwayHashCat with 60 | // non-const "num_fragments". 61 | struct StringView { 62 | const char *data; // not necessarily aligned/padded 63 | size_t num_bytes; // possibly zero 64 | }; 65 | 66 | // Note: this interface avoids dispatch overhead per fragment. 67 | template struct HighwayHashCat { 68 | // Stores a 64/128/256 bit hash of all "num_fragments" "fragments" using the 69 | // HighwayHashCatT implementation for "Target". The hash result is identical 70 | // to HighwayHash of the flattened data, regardless of Target. 71 | // 72 | // "key" is a (randomly generated or hard-coded) HHKey. 73 | // "fragments" contain unaligned pointers and the number of valid bytes. 74 | // "num_fragments" indicates the number of entries in "fragments". 75 | // "hash" is a HHResult* (either 64, 128 or 256 bits). 76 | void operator()(const HHKey &key, const StringView *HH_RESTRICT fragments, 77 | const size_t num_fragments, 78 | HHResult64 *HH_RESTRICT hash) const; 79 | void operator()(const HHKey &key, const StringView *HH_RESTRICT fragments, 80 | const size_t num_fragments, 81 | HHResult128 *HH_RESTRICT hash) const; 82 | void operator()(const HHKey &key, const StringView *HH_RESTRICT fragments, 83 | const size_t num_fragments, 84 | HHResult256 *HH_RESTRICT hash) const; 85 | }; 86 | 87 | } // namespace highwayhash 88 | 89 | #endif // HIGHWAYHASH_HIGHWAYHASH_TARGET_H_ 90 | -------------------------------------------------------------------------------- /tests/highwayhash/iaca.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_IACA_H_ 16 | #define HIGHWAYHASH_IACA_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 22 | 23 | #include "highwayhash/compiler_specific.h" 24 | 25 | // IACA (Intel's Code Analyzer, go/intel-iaca) analyzes instruction latencies, 26 | // but only for code between special markers. These functions embed such markers 27 | // in an executable, but only for reading via IACA - they deliberately trigger 28 | // a crash if executed to ensure they are removed in normal builds. 29 | 30 | // Default off; callers must `#define HH_ENABLE_IACA 1` before including this. 31 | #ifndef HH_ENABLE_IACA 32 | #define HH_ENABLE_IACA 0 33 | #endif 34 | 35 | namespace highwayhash { 36 | 37 | #if HH_ENABLE_IACA && (HH_GCC_VERSION || HH_CLANG_VERSION) 38 | 39 | // Call before the region of interest. Fences hopefully prevent reordering. 40 | static HH_INLINE void BeginIACA() { 41 | HH_COMPILER_FENCE; 42 | asm volatile(".byte 0x0F, 0x0B\n\t" // UD2 43 | "movl $111, %ebx\n\t" 44 | ".byte 0x64, 0x67, 0x90\n\t"); 45 | HH_COMPILER_FENCE; 46 | } 47 | 48 | // Call after the region of interest. Fences hopefully prevent reordering. 49 | static HH_INLINE void EndIACA() { 50 | HH_COMPILER_FENCE; 51 | asm volatile("movl $222, %ebx\n\t" 52 | ".byte 0x64, 0x67, 0x90\n\t" 53 | ".byte 0x0F, 0x0B\n\t"); // UD2 54 | HH_COMPILER_FENCE; 55 | } 56 | 57 | #endif 58 | 59 | } // namespace highwayhash 60 | 61 | #endif // HIGHWAYHASH_IACA_H_ 62 | -------------------------------------------------------------------------------- /tests/highwayhash/load3.h: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef HIGHWAYHASH_HH_LOAD3_H_ 16 | #define HIGHWAYHASH_HH_LOAD3_H_ 17 | 18 | // WARNING: this is a "restricted" header because it is included from 19 | // translation units compiled with different flags. This header and its 20 | // dependencies must not define any function unless it is static inline and/or 21 | // within namespace HH_TARGET_NAME. See arch_specific.h for details. 22 | 23 | #include 24 | #include 25 | 26 | #include "highwayhash/arch_specific.h" 27 | #include "highwayhash/compiler_specific.h" 28 | #include "highwayhash/endianess.h" 29 | 30 | namespace highwayhash { 31 | // To prevent ODR violations when including this from multiple translation 32 | // units (TU) that are compiled with different flags, the contents must reside 33 | // in a namespace whose name is unique to the TU. NOTE: this behavior is 34 | // incompatible with precompiled modules and requires textual inclusion instead. 35 | namespace HH_TARGET_NAME { 36 | 37 | // Loads 0 to 3 bytes from a given location using one of several policies. 38 | // These are potentially faster than 8-bit loads, but require certain additional 39 | // promises by the caller: that 'out of bounds' memory accesses are allowed, 40 | // and/or that the bytes may be permuted or duplicated. 41 | class Load3 { 42 | public: 43 | // In increasing order of complexity: 44 | struct AllowReadBeforeAndReturn {}; 45 | struct AllowReadBefore {}; 46 | struct AllowUnordered {}; 47 | struct AllowNone {}; 48 | 49 | // Up to 4 preceding bytes may be read and returned along with the 0..3 50 | // valid bytes. The valid bytes are in little-endian order, except that the 51 | // preceding bytes occupy the least-significant bytes. 52 | HH_INLINE uint32_t operator()(AllowReadBeforeAndReturn, const char *from, 53 | const size_t size_mod4) { 54 | // It's safe to read before "from", so we can load 32 bits, which is faster 55 | // than individual byte loads. We assume little-endian byte order, so 56 | // big-endian platforms will need to swap. Type punning can generate 57 | // incorrect code if compiled with strict aliasing; the only safe 58 | // alternatives are memcpy and reading through char*. We must avoid memcpy 59 | // because string.h must not be included per the warning above. On GCC and 60 | // Clang, we can use a builtin instead. 61 | uint32_t last4; 62 | Copy(from + size_mod4 - 4, 4, reinterpret_cast(&last4)); 63 | return host_from_le32(last4); 64 | } 65 | 66 | // As above, but preceding bytes are removed and upper byte(s) are zero. 67 | HH_INLINE uint64_t operator()(AllowReadBefore, const char *from, 68 | const size_t size_mod4) { 69 | // Shift 0..3 valid bytes into LSB as if loaded in little-endian order. 70 | // 64-bit type enables 32-bit shift when size_mod4 == 0. 71 | uint64_t last3 = operator()(AllowReadBeforeAndReturn(), from, size_mod4); 72 | last3 >>= 32 - (size_mod4 * 8); 73 | return last3; 74 | } 75 | 76 | // The bytes need not be loaded in little-endian order. This particular order 77 | // (and the duplication of some bytes depending on "size_mod4") was chosen for 78 | // computational convenience and can no longer be changed because it is part 79 | // of the HighwayHash length padding definition. 80 | HH_INLINE uint64_t operator()(AllowUnordered, const char *from, 81 | const size_t size_mod4) { 82 | uint64_t last3 = 0; 83 | // Not allowed to read any bytes; early-out is faster than reading from a 84 | // constant array of zeros. 85 | if (size_mod4 == 0) { 86 | return last3; 87 | } 88 | 89 | // These indices are chosen as an easy-to-compute sequence containing the 90 | // same elements as [0, size), but repeated and/or reordered. This enables 91 | // unconditional loads, which outperform conditional 8 or 16+8 bit loads. 92 | const uint64_t idx0 = 0; 93 | const uint64_t idx1 = size_mod4 >> 1; 94 | const uint64_t idx2 = size_mod4 - 1; 95 | // Store into least significant bytes (avoids one shift). 96 | last3 = U64FromChar(from[idx0]); 97 | last3 += U64FromChar(from[idx1]) << 8; 98 | last3 += U64FromChar(from[idx2]) << 16; 99 | return last3; 100 | } 101 | 102 | // Must read exactly [0, size) bytes in little-endian order. 103 | HH_INLINE uint64_t operator()(AllowNone, const char *from, 104 | const size_t size_mod4) { 105 | // We need to load in little-endian order without accessing anything outside 106 | // [from, from + size_mod4). Unrolling is faster than looping backwards. 107 | uint64_t last3 = 0; 108 | if (size_mod4 >= 1) { 109 | last3 += U64FromChar(from[0]); 110 | } 111 | if (size_mod4 >= 2) { 112 | last3 += U64FromChar(from[1]) << 8; 113 | } 114 | if (size_mod4 == 3) { 115 | last3 += U64FromChar(from[2]) << 16; 116 | } 117 | return last3; 118 | } 119 | 120 | private: 121 | static HH_INLINE uint32_t U32FromChar(const char c) { 122 | return static_cast(static_cast(c)); 123 | } 124 | 125 | static HH_INLINE uint64_t U64FromChar(const char c) { 126 | return static_cast(static_cast(c)); 127 | } 128 | 129 | static HH_INLINE void Copy(const char *HH_RESTRICT from, const size_t size, 130 | char *HH_RESTRICT to) { 131 | #if HH_MSC_VERSION 132 | for (size_t i = 0; i < size; ++i) { 133 | to[i] = from[i]; 134 | } 135 | #else 136 | __builtin_memcpy(to, from, size); 137 | #endif 138 | } 139 | }; 140 | 141 | } // namespace HH_TARGET_NAME 142 | } // namespace highwayhash 143 | 144 | #endif // HIGHWAYHASH_LOAD3_H_ 145 | -------------------------------------------------------------------------------- /tests/highwayhash/pure_c.c: -------------------------------------------------------------------------------- 1 | #include "pure_c.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | This code is compatible with C90 with the additional requirement of 9 | supporting uint64_t. 10 | */ 11 | 12 | /* Internal implementation */ 13 | 14 | void HighwayHashReset_pure_c(const uint64_t key[4], HighwayHashState *state) { 15 | state->mul0[0] = 0xdbe6d5d5fe4cce2full; 16 | state->mul0[1] = 0xa4093822299f31d0ull; 17 | state->mul0[2] = 0x13198a2e03707344ull; 18 | state->mul0[3] = 0x243f6a8885a308d3ull; 19 | state->mul1[0] = 0x3bd39e10cb0ef593ull; 20 | state->mul1[1] = 0xc0acf169b5f18a8cull; 21 | state->mul1[2] = 0xbe5466cf34e90c6cull; 22 | state->mul1[3] = 0x452821e638d01377ull; 23 | state->v0[0] = state->mul0[0] ^ key[0]; 24 | state->v0[1] = state->mul0[1] ^ key[1]; 25 | state->v0[2] = state->mul0[2] ^ key[2]; 26 | state->v0[3] = state->mul0[3] ^ key[3]; 27 | state->v1[0] = state->mul1[0] ^ ((key[0] >> 32) | (key[0] << 32)); 28 | state->v1[1] = state->mul1[1] ^ ((key[1] >> 32) | (key[1] << 32)); 29 | state->v1[2] = state->mul1[2] ^ ((key[2] >> 32) | (key[2] << 32)); 30 | state->v1[3] = state->mul1[3] ^ ((key[3] >> 32) | (key[3] << 32)); 31 | } 32 | 33 | static void ZipperMergeAndAdd(const uint64_t v1, const uint64_t v0, 34 | uint64_t *add1, uint64_t *add0) { 35 | *add0 += (((v0 & 0xff000000ull) | (v1 & 0xff00000000ull)) >> 24) | 36 | (((v0 & 0xff0000000000ull) | (v1 & 0xff000000000000ull)) >> 16) | 37 | (v0 & 0xff0000ull) | ((v0 & 0xff00ull) << 32) | 38 | ((v1 & 0xff00000000000000ull) >> 8) | (v0 << 56); 39 | *add1 += (((v1 & 0xff000000ull) | (v0 & 0xff00000000ull)) >> 24) | 40 | (v1 & 0xff0000ull) | ((v1 & 0xff0000000000ull) >> 16) | 41 | ((v1 & 0xff00ull) << 24) | ((v0 & 0xff000000000000ull) >> 8) | 42 | ((v1 & 0xffull) << 48) | (v0 & 0xff00000000000000ull); 43 | } 44 | 45 | static void Update(const uint64_t lanes[4], HighwayHashState *state) { 46 | int i; 47 | for (i = 0; i < 4; ++i) { 48 | state->v1[i] += state->mul0[i] + lanes[i]; 49 | state->mul0[i] ^= (state->v1[i] & 0xffffffff) * (state->v0[i] >> 32); 50 | state->v0[i] += state->mul1[i]; 51 | state->mul1[i] ^= (state->v0[i] & 0xffffffff) * (state->v1[i] >> 32); 52 | } 53 | ZipperMergeAndAdd(state->v1[1], state->v1[0], &state->v0[1], &state->v0[0]); 54 | ZipperMergeAndAdd(state->v1[3], state->v1[2], &state->v0[3], &state->v0[2]); 55 | ZipperMergeAndAdd(state->v0[1], state->v0[0], &state->v1[1], &state->v1[0]); 56 | ZipperMergeAndAdd(state->v0[3], state->v0[2], &state->v1[3], &state->v1[2]); 57 | } 58 | 59 | static uint64_t Read64(const uint8_t *src) { 60 | return (uint64_t)src[0] | ((uint64_t)src[1] << 8) | ((uint64_t)src[2] << 16) | 61 | ((uint64_t)src[3] << 24) | ((uint64_t)src[4] << 32) | 62 | ((uint64_t)src[5] << 40) | ((uint64_t)src[6] << 48) | 63 | ((uint64_t)src[7] << 56); 64 | } 65 | 66 | void HighwayHashUpdatePacket_pure_c(const uint8_t *packet, 67 | HighwayHashState *state) { 68 | uint64_t lanes[4]; 69 | lanes[0] = Read64(packet + 0); 70 | lanes[1] = Read64(packet + 8); 71 | lanes[2] = Read64(packet + 16); 72 | lanes[3] = Read64(packet + 24); 73 | Update(lanes, state); 74 | } 75 | 76 | static void Rotate32By(uint64_t count, uint64_t lanes[4]) { 77 | int i; 78 | for (i = 0; i < 4; ++i) { 79 | uint32_t half0 = lanes[i] & 0xffffffff; 80 | uint32_t half1 = (lanes[i] >> 32); 81 | lanes[i] = (half0 << count) | (half0 >> (32 - count)); 82 | lanes[i] |= (uint64_t)((half1 << count) | (half1 >> (32 - count))) << 32; 83 | } 84 | } 85 | 86 | void HighwayHashUpdateRemainder_pure_c(const uint8_t *bytes, 87 | const size_t size_mod32, 88 | HighwayHashState *state) { 89 | int i; 90 | const size_t size_mod4 = size_mod32 & 3; 91 | const uint8_t *remainder = bytes + (size_mod32 & ~3); 92 | uint8_t packet[32] = {0}; 93 | for (i = 0; i < 4; ++i) { 94 | state->v0[i] += ((uint64_t)size_mod32 << 32) + size_mod32; 95 | } 96 | Rotate32By(size_mod32, state->v1); 97 | for (i = 0; i < remainder - bytes; i++) { 98 | packet[i] = bytes[i]; 99 | } 100 | if (size_mod32 & 16) { 101 | for (i = 0; i < 4; i++) { 102 | packet[28 + i] = remainder[i + size_mod4 - 4]; 103 | } 104 | } else { 105 | if (size_mod4) { 106 | packet[16 + 0] = remainder[0]; 107 | packet[16 + 1] = remainder[size_mod4 >> 1]; 108 | packet[16 + 2] = remainder[size_mod4 - 1]; 109 | } 110 | } 111 | HighwayHashUpdatePacket_pure_c(packet, state); 112 | } 113 | 114 | static void Permute(const uint64_t v[4], uint64_t *permuted) { 115 | permuted[0] = (v[2] >> 32) | (v[2] << 32); 116 | permuted[1] = (v[3] >> 32) | (v[3] << 32); 117 | permuted[2] = (v[0] >> 32) | (v[0] << 32); 118 | permuted[3] = (v[1] >> 32) | (v[1] << 32); 119 | } 120 | 121 | void PermuteAndUpdate(HighwayHashState *state) { 122 | uint64_t permuted[4]; 123 | Permute(state->v0, permuted); 124 | Update(permuted, state); 125 | } 126 | 127 | static void ModularReduction(uint64_t a3_unmasked, uint64_t a2, uint64_t a1, 128 | uint64_t a0, uint64_t *m1, uint64_t *m0) { 129 | uint64_t a3 = a3_unmasked & 0x3FFFFFFFFFFFFFFFull; 130 | *m1 = a1 ^ ((a3 << 1) | (a2 >> 63)) ^ ((a3 << 2) | (a2 >> 62)); 131 | *m0 = a0 ^ (a2 << 1) ^ (a2 << 2); 132 | } 133 | 134 | static uint64_t HighwayHashFinalize64_pure_c(HighwayHashState *state) { 135 | int i; 136 | for (i = 0; i < 4; i++) { 137 | PermuteAndUpdate(state); 138 | } 139 | return state->v0[0] + state->v1[0] + state->mul0[0] + state->mul1[0]; 140 | } 141 | 142 | static void HighwayHashFinalize128_pure_c(HighwayHashState *state, 143 | uint64_t hash[2]) { 144 | int i; 145 | for (i = 0; i < 6; i++) { 146 | PermuteAndUpdate(state); 147 | } 148 | hash[0] = state->v0[0] + state->mul0[0] + state->v1[2] + state->mul1[2]; 149 | hash[1] = state->v0[1] + state->mul0[1] + state->v1[3] + state->mul1[3]; 150 | } 151 | 152 | static void HighwayHashFinalize256_pure_c(HighwayHashState *state, 153 | uint64_t hash[4]) { 154 | int i; 155 | /* We anticipate that 256-bit hashing will be mostly used with long messages 156 | because storing and using the 256-bit hash (in contrast to 128-bit) 157 | carries a larger additional constant cost by itself. Doing extra rounds 158 | here hardly increases the per-byte cost of long messages. */ 159 | for (i = 0; i < 10; i++) { 160 | PermuteAndUpdate(state); 161 | } 162 | ModularReduction(state->v1[1] + state->mul1[1], state->v1[0] + state->mul1[0], 163 | state->v0[1] + state->mul0[1], state->v0[0] + state->mul0[0], 164 | &hash[1], &hash[0]); 165 | ModularReduction(state->v1[3] + state->mul1[3], state->v1[2] + state->mul1[2], 166 | state->v0[3] + state->mul0[3], state->v0[2] + state->mul0[2], 167 | &hash[3], &hash[2]); 168 | } 169 | 170 | /* Non-cat API: single call on full data */ 171 | 172 | static void ProcessAll(const uint8_t *data, size_t size, const uint64_t key[4], 173 | HighwayHashState *state) { 174 | size_t i; 175 | HighwayHashReset_pure_c(key, state); 176 | for (i = 0; i + 32 <= size; i += 32) { 177 | HighwayHashUpdatePacket_pure_c(data + i, state); 178 | } 179 | if ((size & 31) != 0) 180 | HighwayHashUpdateRemainder_pure_c(data + i, size & 31, state); 181 | } 182 | 183 | uint64_t HighwayHash64_pure_c(const uint64_t key[4], const uint8_t *data, 184 | size_t size) { 185 | HighwayHashState state; 186 | ProcessAll(data, size, key, &state); 187 | return HighwayHashFinalize64_pure_c(&state); 188 | } 189 | 190 | void HighwayHash128_pure_c(const uint64_t key[4], const uint8_t *data, 191 | size_t size, uint64_t hash[2]) { 192 | HighwayHashState state; 193 | ProcessAll(data, size, key, &state); 194 | HighwayHashFinalize128_pure_c(&state, hash); 195 | } 196 | 197 | void HighwayHash256_pure_c(const uint64_t key[4], const uint8_t *data, 198 | size_t size, uint64_t hash[4]) { 199 | HighwayHashState state; 200 | ProcessAll(data, size, key, &state); 201 | HighwayHashFinalize256_pure_c(&state, hash); 202 | } 203 | 204 | /* Cat API: allows appending with multiple calls */ 205 | 206 | void HighwayHashCatStart_pure_c(const uint64_t key[4], HighwayHashCat *state) { 207 | HighwayHashReset_pure_c(key, &state->state); 208 | state->num = 0; 209 | } 210 | 211 | void HighwayHashCatAppend_pure_c(const uint8_t *bytes, size_t num, 212 | HighwayHashCat *state) { 213 | size_t i; 214 | if (state->num != 0) { 215 | size_t num_add = num > (32u - state->num) ? (32u - state->num) : num; 216 | for (i = 0; i < num_add; i++) { 217 | state->packet[state->num + i] = bytes[i]; 218 | } 219 | state->num += num_add; 220 | num -= num_add; 221 | bytes += num_add; 222 | if (state->num == 32) { 223 | HighwayHashUpdatePacket_pure_c(state->packet, &state->state); 224 | state->num = 0; 225 | } 226 | } 227 | while (num >= 32) { 228 | HighwayHashUpdatePacket_pure_c(bytes, &state->state); 229 | num -= 32; 230 | bytes += 32; 231 | } 232 | for (i = 0; i < num; i++) { 233 | state->packet[state->num] = bytes[i]; 234 | state->num++; 235 | } 236 | } 237 | 238 | uint64_t HighwayHashCatFinish64_pure_c(const HighwayHashCat *state) { 239 | HighwayHashState copy = state->state; 240 | if (state->num) { 241 | HighwayHashUpdateRemainder_pure_c(state->packet, state->num, ©); 242 | } 243 | return HighwayHashFinalize64_pure_c(©); 244 | } 245 | 246 | void HighwayHashCatFinish128_pure_c(const HighwayHashCat *state, 247 | uint64_t hash[2]) { 248 | HighwayHashState copy = state->state; 249 | if (state->num) { 250 | HighwayHashUpdateRemainder_pure_c(state->packet, state->num, ©); 251 | } 252 | HighwayHashFinalize128_pure_c(©, hash); 253 | } 254 | 255 | void HighwayHashCatFinish256_pure_c(const HighwayHashCat *state, 256 | uint64_t hash[4]) { 257 | HighwayHashState copy = state->state; 258 | if (state->num) { 259 | HighwayHashUpdateRemainder_pure_c(state->packet, state->num, ©); 260 | } 261 | HighwayHashFinalize256_pure_c(©, hash); 262 | } 263 | -------------------------------------------------------------------------------- /tests/highwayhash/pure_c.h: -------------------------------------------------------------------------------- 1 | #ifndef C_HIGHWAYHASH_H_ 2 | #define C_HIGHWAYHASH_H_ 3 | 4 | #include 5 | #include 6 | 7 | #if defined(__cplusplus) || defined(c_plusplus) 8 | extern "C" { 9 | #endif 10 | 11 | /* Low-level API, use for implementing streams etc... */ 12 | 13 | typedef struct { 14 | uint64_t v0[4]; 15 | uint64_t v1[4]; 16 | uint64_t mul0[4]; 17 | uint64_t mul1[4]; 18 | } HighwayHashState; 19 | 20 | /* Initializes state with given key */ 21 | static void HighwayHashReset_pure_c(const uint64_t key[4], 22 | HighwayHashState *state); 23 | /* Takes a packet of 32 bytes */ 24 | void HighwayHashUpdatePacket_pure_c(const uint8_t *packet, 25 | HighwayHashState *state); 26 | /* Adds the final 1..31 bytes, do not use if 0 remain */ 27 | void HighwayHashUpdateRemainder_pure_c(const uint8_t *bytes, 28 | const size_t size_mod32, 29 | HighwayHashState *state); 30 | /* Compute final hash value. Makes state invalid. */ 31 | static uint64_t HighwayHashFinalize64_pure_c(HighwayHashState *state); 32 | static void HighwayHashFinalize128_pure_c(HighwayHashState *state, 33 | uint64_t hash[2]); 34 | static void HighwayHashFinalize256_pure_c(HighwayHashState *state, 35 | uint64_t hash[4]); 36 | 37 | /* Non-cat API: single call on full data */ 38 | 39 | uint64_t HighwayHash64_pure_c(const uint64_t key[4], const uint8_t *data, 40 | size_t size); 41 | 42 | void HighwayHash128_pure_c(const uint64_t key[4], const uint8_t *data, 43 | size_t size, uint64_t hash[2]); 44 | 45 | void HighwayHash256_pure_c(const uint64_t key[4], const uint8_t *data, 46 | size_t size, uint64_t hash[4]); 47 | 48 | /* Cat API: allows appending with multiple calls */ 49 | 50 | typedef struct { 51 | HighwayHashState state; 52 | uint8_t packet[32]; 53 | size_t num; 54 | } HighwayHashCat; 55 | 56 | /* Allocates new state for a new streaming hash computation */ 57 | void HighwayHashCatStart_pure_c(const uint64_t key[4], HighwayHashCat *state); 58 | 59 | void HighwayHashCatAppend_pure_c(const uint8_t *bytes, size_t num, 60 | HighwayHashCat *state); 61 | 62 | /* Computes final hash value */ 63 | uint64_t HighwayHashCatFinish64_pure_c(const HighwayHashCat *state); 64 | void HighwayHashCatFinish128_pure_c(const HighwayHashCat *state, 65 | uint64_t hash[2]); 66 | void HighwayHashCatFinish256_pure_c(const HighwayHashCat *state, 67 | uint64_t hash[4]); 68 | 69 | /* 70 | Usage examples: 71 | 72 | #include 73 | #include 74 | 75 | void Example64() { 76 | uint64_t key[4] = {1, 2, 3, 4}; 77 | const char* text = "Hello world!"; 78 | size_t size = strlen(text); 79 | uint64_t hash = HighwayHash64((const uint8_t*)text, size, key); 80 | printf("%016"PRIx64"\n", hash); 81 | } 82 | 83 | void Example64Cat() { 84 | uint64_t key[4] = {1, 2, 3, 4}; 85 | HighwayHashCat state; 86 | uint64_t hash; 87 | 88 | HighwayHashCatStart(key, &state); 89 | 90 | HighwayHashCatAppend((const uint8_t*)"Hello", 5, &state); 91 | HighwayHashCatAppend((const uint8_t*)" world!", 7, &state); 92 | 93 | hash = HighwayHashCatFinish64(state); 94 | printf("%016"PRIx64"\n", hash); 95 | } 96 | */ 97 | 98 | #if defined(__cplusplus) || defined(c_plusplus) 99 | } /* extern "C" */ 100 | #endif 101 | 102 | #endif // C_HIGHWAYHASH_H_ 103 | -------------------------------------------------------------------------------- /tests/highwayhash/verifier.c: -------------------------------------------------------------------------------- 1 | #include "../common.h" 2 | 3 | #include 4 | #include 5 | 6 | #define kMaxSize 64 7 | 8 | static const uint64_t kTestKey1[4] = { 9 | 0x0706050403020100ull, 0x0F0E0D0C0B0A0908ull, 0x1716151413121110ull, 10 | 0x1F1E1D1C1B1A1918ull}; 11 | 12 | static const uint64_t kTestKey2[4] = {1ull, 2ull, 3ull, 4ull}; 13 | 14 | static const uint64_t kExpected64[kMaxSize + 1] = { 15 | 0x907A56DE22C26E53ull, 0x7EAB43AAC7CDDD78ull, 0xB8D0569AB0B53D62ull, 16 | 0x5C6BEFAB8A463D80ull, 0xF205A46893007EDAull, 0x2B8A1668E4A94541ull, 17 | 0xBD4CCC325BEFCA6Full, 0x4D02AE1738F59482ull, 0xE1205108E55F3171ull, 18 | 0x32D2644EC77A1584ull, 0xF6E10ACDB103A90Bull, 0xC3BBF4615B415C15ull, 19 | 0x243CC2040063FA9Cull, 0xA89A58CE65E641FFull, 0x24B031A348455A23ull, 20 | 0x40793F86A449F33Bull, 0xCFAB3489F97EB832ull, 0x19FE67D2C8C5C0E2ull, 21 | 0x04DD90A69C565CC2ull, 0x75D9518E2371C504ull, 0x38AD9B1141D3DD16ull, 22 | 0x0264432CCD8A70E0ull, 0xA9DB5A6288683390ull, 0xD7B05492003F028Cull, 23 | 0x205F615AEA59E51Eull, 0xEEE0C89621052884ull, 0x1BFC1A93A7284F4Full, 24 | 0x512175B5B70DA91Dull, 0xF71F8976A0A2C639ull, 0xAE093FEF1F84E3E7ull, 25 | 0x22CA92B01161860Full, 0x9FC7007CCF035A68ull, 0xA0C964D9ECD580FCull, 26 | 0x2C90F73CA03181FCull, 0x185CF84E5691EB9Eull, 0x4FC1F5EF2752AA9Bull, 27 | 0xF5B7391A5E0A33EBull, 0xB9B84B83B4E96C9Cull, 0x5E42FE712A5CD9B4ull, 28 | 0xA150F2F90C3F97DCull, 0x7FA522D75E2D637Dull, 0x181AD0CC0DFFD32Bull, 29 | 0x3889ED981E854028ull, 0xFB4297E8C586EE2Dull, 0x6D064A45BB28059Cull, 30 | 0x90563609B3EC860Cull, 0x7AA4FCE94097C666ull, 0x1326BAC06B911E08ull, 31 | 0xB926168D2B154F34ull, 0x9919848945B1948Dull, 0xA2A98FC534825EBEull, 32 | 0xE9809095213EF0B6ull, 0x582E5483707BC0E9ull, 0x086E9414A88A6AF5ull, 33 | 0xEE86B98D20F6743Dull, 0xF89B7FF609B1C0A7ull, 0x4C7D9CC19E22C3E8ull, 34 | 0x9A97005024562A6Full, 0x5DD41CF423E6EBEFull, 0xDF13609C0468E227ull, 35 | 0x6E0DA4F64188155Aull, 0xB755BA4B50D7D4A1ull, 0x887A3484647479BDull, 36 | 0xAB8EEBE9BF2139A0ull, 0x75542C5D4CD2A6FFull}; 37 | 38 | static bool TestHash64(HighwayHash64_t fn, uint64_t expected, 39 | const uint8_t *data, size_t size, const uint64_t *key) { 40 | uint64_t hash = fn(key, data, size); 41 | if (expected != hash) { 42 | if (!is_option_set(test_quiet)) 43 | printf("Failed! : expected %016" PRIx64 ", got %016" PRIx64 44 | ", size: %d\n", 45 | expected, hash, (int)size); 46 | return true; 47 | } 48 | return false; 49 | } 50 | 51 | bool HighwayHash64_verify(HighwayHash64_t fn, const char *title) { 52 | if (!is_option_set(test_quiet)) 53 | printf("Testing %s...%s", title, is_option_set(test_verbose) ? "\n" : ""); 54 | 55 | bool failed = false; 56 | uint8_t data[kMaxSize + 1] = {0}; 57 | int i; 58 | for (i = 0; i <= kMaxSize; i++) { 59 | data[i] = (uint8_t)i; 60 | failed |= TestHash64(fn, kExpected64[i], data, i, kTestKey1); 61 | } 62 | 63 | for (i = 0; i < 33; i++) { 64 | data[i] = 128 + (uint8_t)i; 65 | } 66 | failed |= TestHash64(fn, 0x53c516cce478cad7ull, data, 33, kTestKey2); 67 | 68 | if (is_option_set(test_verbose)) 69 | printf("Passed\n"); 70 | 71 | if (!is_option_set(test_quiet)) 72 | printf(" %s\n", (!is_option_set(test_verbose) && !failed) ? "Ok" : ""); 73 | 74 | return failed; 75 | } 76 | -------------------------------------------------------------------------------- /tests/mera.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2001-2020 Leonid Yuriev , 3 | * The "Mera" library. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #pragma once 23 | 24 | #include 25 | #include 26 | 27 | #if defined(_MSC_VER) 28 | #pragma warning(disable : 4127) /* conditional expression is constant */ 29 | #if _MSC_VER > 1800 30 | #pragma warning(disable : 4464) /* relative include path contains '..' */ 31 | #endif 32 | #endif /* MSVC */ 33 | 34 | #include "../t1ha.h" /* for byteorder and common __ia32__ */ 35 | 36 | /*****************************************************************************/ 37 | 38 | typedef uint64_t timestamp_t; 39 | 40 | enum mera_flags { 41 | timestamp_clock_have = 1u << 0, 42 | timestamp_clock_cheap = 1u << 1, 43 | timestamp_ticks = 1u << 2, 44 | timestamp_cycles = 1u << 3, 45 | timestamp_clock_stable = 1u << 4, 46 | }; 47 | 48 | typedef struct { 49 | unsigned (*start)(timestamp_t *); 50 | unsigned (*finish)(timestamp_t *); 51 | double (*convert)(timestamp_t); 52 | const char *units; 53 | const char *source; 54 | unsigned flags; 55 | int cpunum; 56 | } mera_t; 57 | 58 | extern mera_t mera; 59 | bool mera_init(void); 60 | 61 | typedef struct { 62 | unsigned retry_count, restart_count; 63 | unsigned overhead_loops_max, overhead_best_count, overhead_accounted_loops, 64 | overhead_worthless_loops; 65 | uint64_t overhead_best, overhead_gate; 66 | 67 | unsigned target_loops, tail_loops_max, target_best_count, 68 | target_accounted_loops, target_worthless_loops, spent_seconds; 69 | uint64_t target_best, target_gate; 70 | } mera_bci_t /* bci = Bench Convergence Info */; 71 | 72 | extern mera_bci_t mera_bci; 73 | typedef uint64_t (*mera_bench_target_t)(const void *data, size_t bytes, 74 | uint64_t seed); 75 | 76 | #define MERA_BENCH_TARGET mera_bench_target_t 77 | #define MERA_BENCH_SELF_ARGS const void *data, size_t bytes, uint64_t seed 78 | #define MERA_BENCH_TARGET_ARGS data, bytes, seed 79 | #define MERA_PERROR_PREFIX " - " 80 | 81 | double mera_bench(MERA_BENCH_TARGET target, MERA_BENCH_SELF_ARGS); 82 | 83 | /*****************************************************************************/ 84 | 85 | #if defined(__ia32__) 86 | typedef struct _ia32_cpu_features { 87 | struct { 88 | uint32_t ebx; 89 | uint32_t ecx; 90 | uint32_t edx; 91 | } basic /* https://en.wikipedia.org/wiki/CPUID#EAX=1:_Processor_Info_and_Feature_Bits 92 | */ 93 | , 94 | extended_7 /* https://en.wikipedia.org/wiki/CPUID#EAX=7,_ECX=0:_Extended_Features 95 | */ 96 | ; 97 | 98 | struct { 99 | uint32_t ecx; 100 | uint32_t edx; 101 | } extended_80000001 /* https://en.wikipedia.org/wiki/CPUID#EAX=80000001h:_Extended_Processor_Info_and_Feature_Bits 102 | */ 103 | ; 104 | 105 | struct { 106 | uint32_t ecx; 107 | uint32_t edx; 108 | } extended_80000007 /* Advanced Power Management Information */; 109 | 110 | } ia32_cpu_features_t; 111 | 112 | extern ia32_cpu_features_t ia32_cpu_features; 113 | void ia32_fetch_cpu_features(void); 114 | #endif /* __ia32__ */ 115 | -------------------------------------------------------------------------------- /tests/stadtx/LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /tests/stadtx/stadtx_hash.h: -------------------------------------------------------------------------------- 1 | /* StadtX hash implementaion. 2 | * Author: Yves Orton . 3 | * License: LGPLv3. 4 | * 5 | * This file copied from https://github.com/demerphq/BeagleHash 6 | * Please refer there for detailed Copyright and License information. */ 7 | #ifndef STADTX_HASH_H 8 | #define STADTX_HASH_H 9 | 10 | /* LY: simple way to fix endianess and provide portable marcos */ 11 | #include "../../src/t1ha_bits.h" 12 | #define ROTL64(x, r) rot64(x, 64 - r) 13 | #define ROTR64(x, r) rot64(x, r) 14 | 15 | /* do a marsaglia xor-shift permutation followed by a 16 | * multiply by a prime (presumably large) and another 17 | * marsaglia xor-shift permutation. 18 | * One of these thoroughly changes the bits of the input. 19 | * Two of these with different primes passes the Strict Avalanche Criteria 20 | * in all the tests I did. 21 | * 22 | * Note that v cannot end up zero after a scramble64 unless it 23 | * was zero in the first place. 24 | */ 25 | #define STADTX_SCRAMBLE64(v, prime) \ 26 | do { \ 27 | v ^= (v >> 13); \ 28 | v ^= (v << 35); \ 29 | v ^= (v >> 30); \ 30 | v *= prime; \ 31 | v ^= (v >> 19); \ 32 | v ^= (v << 15); \ 33 | v ^= (v >> 46); \ 34 | } while (0) 35 | 36 | static __inline void stadtx_seed_state(const uint64_t *seed, uint64_t *state) { 37 | /* first we apply two masks to each word of the seed, this means that 38 | * a) at least one of state[0] and state[2] is nonzero, 39 | * b) at least one of state[1] and state[3] is nonzero 40 | * c) that state[0] and state[2] are different 41 | * d) that state[1] and state[3] are different 42 | * e) that the replacement value for any zero's is a totally different from 43 | * the seed value. (iow, if seed[0] is 0x43f6a8885a308d31UL then state[0] 44 | * becomes 0, which is the replaced with 1, which is totally different.). */ 45 | /* hex expansion of pi, skipping first two digits. pi= 3.2[43f6...]*/ 46 | /* pi value in hex from here: 47 | * http://turner.faculty.swau.edu/mathematics/materialslibrary/pi/pibases.html*/ 48 | state[0] = seed[0] ^ 0x43f6a8885a308d31UL; 49 | state[1] = seed[1] ^ 0x3198a2e03707344aUL; 50 | state[2] = seed[0] ^ 0x4093822299f31d00UL; 51 | state[3] = seed[1] ^ 0x82efa98ec4e6c894UL; 52 | if (!state[0]) 53 | state[0] = 1; 54 | if (!state[1]) 55 | state[1] = 2; 56 | if (!state[2]) 57 | state[2] = 4; 58 | if (!state[3]) 59 | state[3] = 8; 60 | /* and now for good measure we double scramble all four - 61 | * a double scramble guarantees a complete avalanche of all the 62 | * bits in the seed - IOW, by the time we are hashing the 63 | * four state vectors should be completely different and utterly 64 | * uncognizable from the input seed bits */ 65 | STADTX_SCRAMBLE64(state[0], 0x801178846e899d17UL); 66 | STADTX_SCRAMBLE64(state[0], 0xdd51e5d1c9a5a151UL); 67 | STADTX_SCRAMBLE64(state[1], 0x93a7d6c8c62e4835UL); 68 | STADTX_SCRAMBLE64(state[1], 0x803340f36895c2b5UL); 69 | STADTX_SCRAMBLE64(state[2], 0xbea9344eb7565eebUL); 70 | STADTX_SCRAMBLE64(state[2], 0xcd95d1e509b995cdUL); 71 | STADTX_SCRAMBLE64(state[3], 0x9999791977e30c13UL); 72 | STADTX_SCRAMBLE64(state[3], 0xaab8b6b05abfc6cdUL); 73 | } 74 | 75 | #define STADTX_K0_uint64_t 0xb89b0f8e1655514fUL 76 | #define STADTX_K1_uint64_t 0x8c6f736011bd5127UL 77 | #define STADTX_K2_uint64_t 0x8f29bd94edce7b39UL 78 | #define STADTX_K3_uint64_t 0x9c1b8e1e9628323fUL 79 | 80 | #define STADTX_K2_uint32_t 0x802910e3 81 | #define STADTX_K3_uint32_t 0x819b13af 82 | #define STADTX_K4_uint32_t 0x91cb27e5 83 | #define STADTX_K5_uint32_t 0xc1a269c1 84 | 85 | static __inline uint64_t stadtx_hash_with_state(const uint64_t *state_ch, 86 | const uint8_t *key, 87 | const size_t key_len) { 88 | uint64_t *state = (uint64_t *)state_ch; 89 | uint64_t len = key_len; 90 | uint64_t v0 = state[0] ^ ((key_len + 1) * STADTX_K0_uint64_t); 91 | uint64_t v1 = state[1] ^ ((key_len + 2) * STADTX_K1_uint64_t); 92 | if (len < 32) { 93 | switch (len >> 3) { 94 | case 3: 95 | v0 += fetch64_le_unaligned(key) * STADTX_K3_uint64_t; 96 | v0 = ROTR64(v0, 17) ^ v1; 97 | v1 = ROTR64(v1, 53) + v0; 98 | key += 8; 99 | /* fallthrough */ 100 | case 2: 101 | v0 += fetch64_le_unaligned(key) * STADTX_K3_uint64_t; 102 | v0 = ROTR64(v0, 17) ^ v1; 103 | v1 = ROTR64(v1, 53) + v0; 104 | key += 8; 105 | /* fallthrough */ 106 | case 1: 107 | v0 += fetch64_le_unaligned(key) * STADTX_K3_uint64_t; 108 | v0 = ROTR64(v0, 17) ^ v1; 109 | v1 = ROTR64(v1, 53) + v0; 110 | key += 8; 111 | /* fallthrough */ 112 | case 0: 113 | default: 114 | break; 115 | } 116 | switch (len & 0x7) { 117 | case 7: 118 | v0 += (uint64_t)key[6] << 32; 119 | /* fallthrough */ 120 | case 6: 121 | v1 += (uint64_t)key[5] << 48; 122 | /* fallthrough */ 123 | case 5: 124 | v0 += (uint64_t)key[4] << 16; 125 | /* fallthrough */ 126 | case 4: 127 | v1 += (uint64_t)fetch32_le_unaligned(key); 128 | break; 129 | case 3: 130 | v0 += (uint64_t)key[2] << 48; 131 | /* fallthrough */ 132 | case 2: 133 | v1 += (uint64_t)fetch16_le_unaligned(key); 134 | break; 135 | case 1: 136 | v0 += (uint64_t)key[0]; 137 | /* fallthrough */ 138 | case 0: 139 | v1 = ROTL64(v1, 32) ^ 0xFF; 140 | break; 141 | } 142 | v1 ^= v0; 143 | v0 = ROTR64(v0, 33) + v1; 144 | v1 = ROTL64(v1, 17) ^ v0; 145 | v0 = ROTL64(v0, 43) + v1; 146 | v1 = ROTL64(v1, 31) - v0; 147 | v0 = ROTL64(v0, 13) ^ v1; 148 | v1 -= v0; 149 | v0 = ROTL64(v0, 41) + v1; 150 | v1 = ROTL64(v1, 37) ^ v0; 151 | v0 = ROTR64(v0, 39) + v1; 152 | v1 = ROTR64(v1, 15) + v0; 153 | v0 = ROTL64(v0, 15) ^ v1; 154 | v1 = ROTR64(v1, 5); 155 | return v0 ^ v1; 156 | } else { 157 | uint64_t v2 = state[2] ^ ((key_len + 3) * STADTX_K2_uint64_t); 158 | uint64_t v3 = state[3] ^ ((key_len + 4) * STADTX_K3_uint64_t); 159 | 160 | do { 161 | v0 += (uint64_t)fetch64_le_unaligned(key + 0) * STADTX_K2_uint32_t; 162 | v0 = ROTL64(v0, 57) ^ v3; 163 | v1 += (uint64_t)fetch64_le_unaligned(key + 8) * STADTX_K3_uint32_t; 164 | v1 = ROTL64(v1, 63) ^ v2; 165 | v2 += (uint64_t)fetch64_le_unaligned(key + 16) * STADTX_K4_uint32_t; 166 | v2 = ROTR64(v2, 47) + v0; 167 | v3 += (uint64_t)fetch64_le_unaligned(key + 24) * STADTX_K5_uint32_t; 168 | v3 = ROTR64(v3, 11) - v1; 169 | key += 32; 170 | len -= 32; 171 | } while (len >= 32); 172 | 173 | switch (len >> 3) { 174 | case 3: 175 | v0 += ((uint64_t)fetch64_le_unaligned(key) * STADTX_K2_uint32_t); 176 | key += 8; 177 | v0 = ROTL64(v0, 57) ^ v3; 178 | /* fallthrough */ 179 | case 2: 180 | v1 += ((uint64_t)fetch64_le_unaligned(key) * STADTX_K3_uint32_t); 181 | key += 8; 182 | v1 = ROTL64(v1, 63) ^ v2; 183 | /* fallthrough */ 184 | case 1: 185 | v2 += ((uint64_t)fetch64_le_unaligned(key) * STADTX_K4_uint32_t); 186 | key += 8; 187 | v2 = ROTR64(v2, 47) + v0; 188 | /* fallthrough */ 189 | case 0: 190 | v3 = ROTR64(v3, 11) - v1; 191 | } 192 | v0 ^= (len + 1) * STADTX_K3_uint64_t; 193 | switch (len & 0x7) { 194 | case 7: 195 | v1 += (uint64_t)key[6]; 196 | /* fallthrough */ 197 | case 6: 198 | v2 += (uint64_t)fetch16_le_unaligned(key + 4); 199 | v3 += (uint64_t)fetch32_le_unaligned(key); 200 | break; 201 | case 5: 202 | v1 += (uint64_t)key[4]; 203 | /* fallthrough */ 204 | case 4: 205 | v2 += (uint64_t)fetch32_le_unaligned(key); 206 | break; 207 | case 3: 208 | v3 += (uint64_t)key[2]; 209 | /* fallthrough */ 210 | case 2: 211 | v1 += (uint64_t)fetch16_le_unaligned(key); 212 | break; 213 | case 1: 214 | v2 += (uint64_t)key[0]; 215 | /* fallthrough */ 216 | case 0: 217 | v3 = ROTL64(v3, 32) ^ 0xFF; 218 | break; 219 | } 220 | 221 | v1 -= v2; 222 | v0 = ROTR64(v0, 19); 223 | v1 -= v0; 224 | v1 = ROTR64(v1, 53); 225 | v3 ^= v1; 226 | v0 -= v3; 227 | v3 = ROTL64(v3, 43); 228 | v0 += v3; 229 | v0 = ROTR64(v0, 3); 230 | v3 -= v0; 231 | v2 = ROTR64(v2, 43) - v3; 232 | v2 = ROTL64(v2, 55) ^ v0; 233 | v1 -= v2; 234 | v3 = ROTR64(v3, 7) - v2; 235 | v2 = ROTR64(v2, 31); 236 | v3 += v2; 237 | v2 -= v1; 238 | v3 = ROTR64(v3, 39); 239 | v2 ^= v3; 240 | v3 = ROTR64(v3, 17) ^ v2; 241 | v1 += v3; 242 | v1 = ROTR64(v1, 9); 243 | v2 ^= v1; 244 | v2 = ROTL64(v2, 24); 245 | v3 ^= v2; 246 | v3 = ROTR64(v3, 59); 247 | v0 = ROTR64(v0, 1) - v1; 248 | 249 | return v0 ^ v1 ^ v2 ^ v3; 250 | } 251 | } 252 | 253 | static __inline uint64_t stadtx_hash(const uint64_t *seed_ch, const void *key, 254 | const size_t key_len) { 255 | uint64_t state[4]; 256 | stadtx_seed_state(seed_ch, state); 257 | return stadtx_hash_with_state(state, key, key_len); 258 | } 259 | 260 | #endif 261 | -------------------------------------------------------------------------------- /tests/stadtx/stadtx_thunk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include "../common.h" 23 | #include "stadtx_hash.h" 24 | 25 | uint64_t thunk_StadtX(const void *input, size_t length, uint64_t seed) { 26 | uint64_t state[4] = {seed, seed, seed, seed}; 27 | return stadtx_hash_with_state(state, input, length); 28 | } 29 | 30 | /* *INDENT-OFF* */ 31 | /* clang-format off */ 32 | const uint64_t refval_StadtX[81] = { 0x1D8FDD3902761988, 33 | 0x3E73CCEA8E7BD54E, 0xA43590A0D6F8C2E5, 0x7D3D74C2D6259671, 0xD7208FDA176BB9D2, 34 | 0x001DAB349BE63C03, 0xDE0B7C82898ECECD, 0xA2B6C896B799DB01, 0x668A589EFD80D2EA, 35 | 0xCDF2E57587745456, 0x56F69ED9BA2D20BE, 0x0B13A4425AF3F03B, 0x4C84D86118CDAC49, 36 | 0xF2A7F9EBA65C76E8, 0xEEDE04FF04ED7F52, 0xC1BD47E8E384A965, 0xE3BA60B1B3C00B21, 37 | 0x2C08F618D6430962, 0x462CFF45FEBDC320, 0x97B0484A7B28A710, 0x36E941F33D42AAEB, 38 | 0xED4C0116E649985F, 0xF1F34BA1B5F39635, 0x1F1AA01DCFAA1173, 0x9F61B2CF31B9B4C3, 39 | 0x115B4048147C3684, 0x1C0E0768A16B6464, 0x3DDBE38A80A51F63, 0x705FD8A4EFB19585, 40 | 0xB73012A80F64D66C, 0x6FD48B29F3C6D139, 0x56CF356428A43889, 0x4B858D94E9DECDBA, 41 | 0x81EDB9F56373AC80, 0xF60BF2ECDCABECC6, 0x8ABDCCB98B998133, 0x085F1C19F547EADC, 42 | 0xCB435795F64E9553, 0x316FC6F580388FBE, 0x1B0E8FE6FB7EA1E7, 0xFB3A2C79D53A2B2D, 43 | 0x6470C632D75ADF36, 0x3B5E28ED0C39A53D, 0x63963B97BD6FACBA, 0x271932D82564C326, 44 | 0x76972A129F6BB4D0, 0x4478443177161BAE, 0x241C98736A3C7D8F, 0xC53E0DF5151F4335, 45 | 0x08D079ED3C7BC23F, 0x8933C4E5216472C1, 0xAEAEFDDAD4111C76, 0xA7B51A722A85E8E4, 46 | 0x08B0E5A1B46C275A, 0x55881D991E32B4E7, 0x6C725B1B8FDD598D, 0x9797C7C03BA0492E, 47 | 0xA1072974BF576D37, 0x610A517B2A6FD168, 0x64328409659C86C5, 0x88DF17915E00C40A, 48 | 0xA6B5F8FFF65C2C0F, 0xD40CBCAC358DEC32, 0x02115A34E6A0ED62, 0xAA83E7415E9F40C0, 49 | 0x3A54A2CFFCCDB157, 0x7759C39A6EB25EB5, 0x7BA43A2BD2FCF2E0, 0x267B3FC1DFCBCF48, 50 | 0x938113D2808C9755, 0x9B7DB24F2F8AE5BE, 0xC4ADCEE6AF5353DC, 0xDD57A317D32ABE13, 51 | 0x55BE7E43FACA96DC, 0x7442CABF0D0B46AE, 0xA5052ACBF7B1F40C, 0xA80CBC3FA292FB8A, 52 | 0xF7C5FD3F347C1718, 0x93E2F9C5471F8524, 0xFB130F138ED9E665, 0x41736945A6E44A8E 53 | }; 54 | /* *INDENT-ON* */ 55 | /* clang-format on */ 56 | -------------------------------------------------------------------------------- /tests/test.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include "../src/t1ha_selfcheck.h" 23 | #include "common.h" 24 | 25 | #include 26 | 27 | #if defined(_MSC_VER) 28 | #if _MSC_VER < 1900 29 | #define snprintf _snprintf 30 | #pragma warning(disable : 4996) /* '_snprintf': This function or variable \ 31 | may be unsafe */ 32 | #endif 33 | #endif /* MSVC */ 34 | 35 | /*****************************************************************************/ 36 | 37 | #ifndef T1HA2_DISABLED 38 | uint64_t thunk_t1ha2_atonce128(const void *data, size_t len, uint64_t seed) { 39 | uint64_t unused; 40 | return t1ha2_atonce128(&unused, data, len, seed); 41 | } 42 | 43 | uint64_t thunk_t1ha2_stream(const void *data, size_t len, uint64_t seed) { 44 | t1ha_context_t ctx; 45 | t1ha2_init(&ctx, seed, seed); 46 | t1ha2_update(&ctx, data, len); 47 | return t1ha2_final(&ctx, NULL); 48 | } 49 | 50 | uint64_t thunk_t1ha2_stream128(const void *data, size_t len, uint64_t seed) { 51 | t1ha_context_t ctx; 52 | t1ha2_init(&ctx, seed, seed); 53 | t1ha2_update(&ctx, data, len); 54 | uint64_t unused; 55 | return t1ha2_final(&ctx, &unused); 56 | } 57 | #endif /* T1HA2_DISABLED */ 58 | 59 | static bool probe(uint64_t (*hash)(const void *, size_t, uint64_t), 60 | const char *caption, const uint64_t check, const void *data, 61 | unsigned len, uint64_t seed) { 62 | uint64_t value = hash(data, len, seed); 63 | if (is_option_set(test_verbose) || (value != check)) 64 | printf("Pattern '%s', reference value %08X%08X: ", caption, 65 | (uint32_t)(check >> 32), (uint32_t)check); 66 | if (check == value) { 67 | if (is_option_set(test_verbose)) 68 | printf("Passed\n"); 69 | return false; 70 | } 71 | if (!is_option_set(test_quiet)) 72 | printf("Failed! Got %08X%08X\n", (uint32_t)(value >> 32), (uint32_t)value); 73 | return true; 74 | } 75 | 76 | bool verify(const char *title, uint64_t (*hash)(const void *, size_t, uint64_t), 77 | const uint64_t *reference_values) { 78 | if (!is_option_set(test_quiet)) 79 | printf("Testing %s...%s", title, is_option_set(test_verbose) ? "\n" : ""); 80 | 81 | const uint64_t zero = 0; 82 | bool failed = false; 83 | failed |= probe(hash, "empty-zero", *reference_values++, NULL, 0, zero); 84 | failed |= probe(hash, "empty-all1", *reference_values++, NULL, 0, ~zero); 85 | failed |= probe(hash, "bin64-zero", *reference_values++, t1ha_test_pattern, 86 | 64, zero); 87 | 88 | char caption[32]; 89 | uint64_t seed = 1; 90 | for (int i = 1; i < 64; i++) { 91 | snprintf(caption, sizeof(caption), "bin%02i-1p%02u", i, i & 63); 92 | failed |= 93 | probe(hash, caption, *reference_values++, t1ha_test_pattern, i, seed); 94 | seed <<= 1; 95 | } 96 | 97 | seed = ~zero; 98 | for (int i = 1; i <= 7; i++) { 99 | seed <<= 1; 100 | snprintf(caption, sizeof(caption), "align%i_F%u", i, 64 - i); 101 | failed |= probe(hash, caption, *reference_values++, t1ha_test_pattern + i, 102 | 64 - i, seed); 103 | } 104 | 105 | uint8_t pattern_long[512]; 106 | for (size_t i = 0; i < sizeof(pattern_long); ++i) 107 | pattern_long[i] = (uint8_t)i; 108 | for (int i = 0; i <= 7; i++) { 109 | snprintf(caption, sizeof(caption), "long-%05u", 128 + i * 17); 110 | failed |= probe(hash, caption, *reference_values++, pattern_long + i, 111 | 128 + i * 17, seed); 112 | } 113 | 114 | if (!is_option_set(test_quiet)) 115 | printf(" %s\n", (!is_option_set(test_verbose) && !failed) ? "Ok" : ""); 116 | return failed; 117 | } 118 | -------------------------------------------------------------------------------- /tests/wyhash/LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | 26 | -------------------------------------------------------------------------------- /tests/wyhash/README.md: -------------------------------------------------------------------------------- 1 | No hash function is perfect, but some are useful. 2 | ==== 3 | 4 | wyhash and wyrand are the ideal 64-bit hash function and PRNG respectively: 5 | 6 | **solid**: wyhash passed SMHasher, wyrand passed BigCrush, practrand. 7 | 8 | **portable**: 64-bit/32-bit system, big/little endian. 9 | 10 | **fastest**: Efficient on 64-bit machines, especially for short keys. 11 | 12 | **simplest**: In the sense of code size. 13 | 14 | ---------------------------------------- 15 | 16 | g++-9 benchmark.cpp t1ha/src/t1ha2.c -o benchmark -Ofast -s -Wall -march=native 17 | 18 | /usr/share/dict/words 19 | 20 | |hash function |short hash/us |bulk_256B GB/s |bulk_64KB GB/s | 21 | |---- |---- |---- |---- | 22 | |wyhash:safety=0|444.31 |18.86 |24.35 | 23 | |wyhash:safety=1|195.42 |17.97 |23.44 | 24 | |wyhash:safety=2|181.56 |14.33 |15.97 | 25 | |xxh3:avx2 |147.33 |9.73 |45.39 | 26 | |xxh3:sse2 |154.30 |11.53 |27.15 | 27 | |xxh3:scalar |153.61 |8.49 |13.05 | 28 | |xxHash64 |83.10 |10.89 |14.72 | 29 | |t1ha2_atonce |115.12 |12.96 |17.64 | 30 | 31 | ---------------------------------------- 32 | wyhash is the default hasher for a hash table of the great Zig and V language. 33 | 34 | **C#** https://github.com/cocowalla/wyhash-dotnet 35 | 36 | **C++** https://github.com/tommyettinger/waterhash 37 | 38 | **GO** https://github.com/dgryski/go-wyhash 39 | 40 | **GO** https://github.com/orisano/wyhash 41 | 42 | **GO** https://github.com/littleli/go-wyhash16 43 | 44 | **GO** https://github.com/zeebo/wyhash 45 | 46 | **GO** https://github.com/lonewolf3739/wyhash-go 47 | 48 | **Java** https://github.com/OpenHFT/Zero-Allocation-Hashing 49 | 50 | **Rust** https://github.com/eldruin/wyhash-rs 51 | 52 | **Swift** https://github.com/lemire/SwiftWyhash 53 | 54 | **Swift** https://github.com/lemire/SwiftWyhashBenchmark 55 | 56 | **Swift** https://github.com/jeudesprits/PSWyhash 57 | 58 | **V** https://github.com/vlang/v/tree/master/vlib/hash/wyhash (v4) 59 | 60 | **Zig** https://github.com/ManDeJan/zig-wyhash 61 | 62 | ---------------------------------------- 63 | 64 | I thank these names: 65 | 66 | Reini Urban 67 | 68 | Dietrich Epp 69 | 70 | Joshua Haberman 71 | 72 | Tommy Ettinger 73 | 74 | Daniel Lemire 75 | 76 | Otmar Ertl 77 | 78 | cocowalla 79 | 80 | leo-yuriev 81 | 82 | Diego Barrios Romero 83 | 84 | paulie-g 85 | 86 | dumblob 87 | 88 | Yann Collet 89 | 90 | ivte-ms 91 | 92 | hyb 93 | 94 | James Z.M. Gao 95 | 96 | easyaspi314 (Devin) 97 | 98 | -------------------------------------------------------------------------------- /tests/wyhash/wyhash_thunk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include "../common.h" 23 | #include "wyhash.h" 24 | 25 | uint64_t thunk_wyhash_20221102(const void *input, size_t length, 26 | uint64_t seed) { 27 | return wyhash(input, length, seed, _wyp); 28 | } 29 | 30 | bool wyhash_20221102_selftest(void) { 31 | bool failed = wyhash(NULL, 0, 0, _wyp) != UINT64_C(0x42bc986dc5eec4d3); 32 | failed |= wyhash("a", 1, 1, _wyp) != UINT64_C(0x84508dc903c31551); 33 | failed |= wyhash("abc", 3, 2, _wyp) != UINT64_C(0xbc54887cfc9ecb1); 34 | failed |= 35 | wyhash("message digest", 14, 3, _wyp) != UINT64_C(0xadc146444841c430); 36 | failed |= wyhash("abcdefghijklmnopqrstuvwxyz", 26, 4, _wyp) != 37 | UINT64_C(0x4c0977bd4f14f34a); 38 | failed |= 39 | wyhash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 40 | 62, 5, _wyp) != UINT64_C(0x6f8bd609a8a276d2); 41 | failed |= wyhash("12345678901234567890123456789012345678901234567890123456789" 42 | "012345678901234567890", 43 | 80, 6, _wyp) != UINT64_C(0x498d7c21668259ad); 44 | return failed; 45 | } 46 | 47 | const uint64_t refval_wyhash_20221102[81] = { 48 | UINT64_C(0x0409638EE2BDE459), UINT64_C(0x20AC8B93D401D5E6), 49 | UINT64_C(0xADF5D942B29AC953), UINT64_C(0x85669AF5073EE8BE), 50 | UINT64_C(0xA3D943AE2A6A1F49), UINT64_C(0xACEB1673F381D842), 51 | UINT64_C(0xB8F865B9B67D71F1), UINT64_C(0xA823CA869C757D01), 52 | UINT64_C(0x515DEA81A624910F), UINT64_C(0x16512C92EF02820E), 53 | UINT64_C(0xD092B9938C07AFE9), UINT64_C(0x7B2D35E96C8BA7A7), 54 | UINT64_C(0x6D0B8FC30333766E), UINT64_C(0x779F3BCB4537DCB3), 55 | UINT64_C(0xCFE564C0AA14F310), UINT64_C(0x77D3AABECC41447F), 56 | UINT64_C(0xCDE8A6F00447CBEF), UINT64_C(0x443AB500177172F3), 57 | UINT64_C(0x52F9295860FF7508), UINT64_C(0x0814B2D8D1F8BA2F), 58 | UINT64_C(0x6392C84FE42811BA), UINT64_C(0x9BB4ADAFA9D22B3C), 59 | UINT64_C(0x54EA1BB3B85CC6F6), UINT64_C(0xD8D35AA18FF9437D), 60 | UINT64_C(0xD651F4DFED91193D), UINT64_C(0x66D61A1812CF88CB), 61 | UINT64_C(0xC56BBE49BB86C144), UINT64_C(0xB923E2245EF3992C), 62 | UINT64_C(0x178F823861148013), UINT64_C(0x28508E8C2668A35B), 63 | UINT64_C(0x3300E573BAAF799C), UINT64_C(0x3A927FD33A784518), 64 | UINT64_C(0xA7BD74219F20C3C0), UINT64_C(0xDA8673005B55D0EC), 65 | UINT64_C(0x59385BF4E094F4C0), UINT64_C(0x5465707439543CAD), 66 | UINT64_C(0xD5D5B909A7F48AE0), UINT64_C(0xACE58AC11CD3A86C), 67 | UINT64_C(0x641B2163F08F27CE), UINT64_C(0x157A09D318CEB3D5), 68 | UINT64_C(0xBE00A4D76D45DD9D), UINT64_C(0x060C9893E6DD73FE), 69 | UINT64_C(0xA3636A34F128CFDC), UINT64_C(0xEF1877BF3A115E1E), 70 | UINT64_C(0x9E8A8E936360BB86), UINT64_C(0x4E6D68F0D3DE72C0), 71 | UINT64_C(0xB259F961BCADAC3F), UINT64_C(0x30F920AC087D79C3), 72 | UINT64_C(0x061299C04CEC0497), UINT64_C(0x60A506EB14A66CD3), 73 | UINT64_C(0x9CFF515DFCDCC27B), UINT64_C(0x9AA94CF1E091A90E), 74 | UINT64_C(0x4A7EF439DD279283), UINT64_C(0xAFF445AFECDF6747), 75 | UINT64_C(0x5DB3CCA6D4A94743), UINT64_C(0x70C94AB02256340F), 76 | UINT64_C(0x00F872F67F7B0984), UINT64_C(0xFA1936C9F46C2DDB), 77 | UINT64_C(0x0FB69B5CDCC4E06C), UINT64_C(0x632F83BA82DB982D), 78 | UINT64_C(0x85E11D763BD37EB1), UINT64_C(0x85E91AC3CF02E2E4), 79 | UINT64_C(0x91FBBF5B85956695), UINT64_C(0xF2139573275574A0), 80 | UINT64_C(0x0F783945C534D10A), UINT64_C(0x39DA7FACA6F862EE), 81 | UINT64_C(0x08F4AA2C7C360739), UINT64_C(0xBB39EB5E18C7BEC6), 82 | UINT64_C(0x00B1A7C3D3C462AA), UINT64_C(0x7D427996B8FEA79F), 83 | UINT64_C(0x6EF01EB123B957C7), UINT64_C(0xC5E3F5A764689B23), 84 | UINT64_C(0x77EFD58244C30D34), UINT64_C(0xCB1A99B226F4335B), 85 | UINT64_C(0x2A747A3A2645497C), UINT64_C(0xDFAA75DA597CDC98), 86 | UINT64_C(0x6CF8D4DDD4B6712D), UINT64_C(0x2AAB2280F8059908), 87 | UINT64_C(0xFDFDEFA760BB4480), UINT64_C(0x0D8AE62BBF275DBD), 88 | UINT64_C(0x7FA21E9E6D9EED92)}; 89 | -------------------------------------------------------------------------------- /tests/xxhash/xxh_thunk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 Leonid Yuriev , 3 | * Fast Positive Hash. 4 | * 5 | * This software is provided 'as-is', without any express or implied 6 | * warranty. In no event will the authors be held liable for any damages 7 | * arising from the use of this software. 8 | * 9 | * Permission is granted to anyone to use this software for any purpose, 10 | * including commercial applications, and to alter it and redistribute it 11 | * freely, subject to the following restrictions: 12 | * 13 | * 1. The origin of this software must not be misrepresented; you must not 14 | * claim that you wrote the original software. If you use this software 15 | * in a product, an acknowledgement in the product documentation would be 16 | * appreciated but is not required. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | */ 21 | 22 | #include "../common.h" 23 | 24 | #define XXH_STATIC_LINKING_ONLY 25 | #define XXH_INLINE_ALL 26 | #define XXH_PRIVATE_API 27 | #define XXH_VECTOR 0 28 | 29 | #include "xxhash.h" 30 | 31 | uint64_t XXH_32(const void *input, size_t length, uint64_t seed) { 32 | return XXH32(input, length, (uint32_t)seed); 33 | } 34 | 35 | uint64_t XXH_64(const void *input, size_t length, uint64_t seed) { 36 | return XXH64(input, length, seed); 37 | } 38 | 39 | /* xxHash3 */ 40 | uint64_t XXH3_64(const void *input, size_t length, uint64_t seed) { 41 | return XXH3_64bits_withSeed(input, length, seed); 42 | } 43 | 44 | uint64_t XXH3_128(const void *input, size_t length, uint64_t seed) { 45 | return XXH3_128bits_withSeed(input, length, seed).low64; 46 | } 47 | -------------------------------------------------------------------------------- /tests/xxhash/xxhash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * xxHash - Extremely Fast Hash algorithm 3 | * Copyright (C) 2012-2020 Yann Collet 4 | * 5 | * BSD 2-Clause License (https://www.opensource.org/licenses/bsd-license.php) 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are 9 | * met: 10 | * 11 | * * Redistributions of source code must retain the above copyright 12 | * notice, this list of conditions and the following disclaimer. 13 | * * Redistributions in binary form must reproduce the above 14 | * copyright notice, this list of conditions and the following disclaimer 15 | * in the documentation and/or other materials provided with the 16 | * distribution. 17 | * 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | * 30 | * You can contact the author at: 31 | * - xxHash homepage: https://www.xxhash.com 32 | * - xxHash source repository: https://github.com/Cyan4973/xxHash 33 | */ 34 | 35 | 36 | /* 37 | * xxhash.c instantiates functions defined in xxhash.h 38 | */ 39 | 40 | #define XXH_STATIC_LINKING_ONLY /* access advanced declarations */ 41 | #define XXH_IMPLEMENTATION /* access definitions */ 42 | 43 | #include "xxhash.h" 44 | --------------------------------------------------------------------------------