├── .cirrus.yml ├── .gitignore ├── LICENSE ├── Makefile.am ├── README.md ├── autogen.sh ├── build-aux └── m4 │ ├── ax_check_compile_flag.m4 │ ├── ax_check_link_flag.m4 │ ├── ax_check_preproc_flag.m4 │ └── ax_cxx_compile_stdcxx.m4 ├── ci ├── cirrus.sh └── linux-debian.Dockerfile ├── configure.ac ├── doc ├── example.c ├── gen_basefpbits.sage ├── gen_params.sage ├── log2_factorial.sage ├── math.md ├── minisketch-vs.png ├── moduli.md ├── plot_bits.png ├── plot_capacity.png ├── plot_diff.png ├── plot_size.png └── protocoltips.md ├── include └── minisketch.h ├── sources.mk ├── src ├── bench.cpp ├── false_positives.h ├── fielddefines.h ├── fields │ ├── clmul_1byte.cpp │ ├── clmul_2bytes.cpp │ ├── clmul_3bytes.cpp │ ├── clmul_4bytes.cpp │ ├── clmul_5bytes.cpp │ ├── clmul_6bytes.cpp │ ├── clmul_7bytes.cpp │ ├── clmul_8bytes.cpp │ ├── clmul_common_impl.h │ ├── generic_1byte.cpp │ ├── generic_2bytes.cpp │ ├── generic_3bytes.cpp │ ├── generic_4bytes.cpp │ ├── generic_5bytes.cpp │ ├── generic_6bytes.cpp │ ├── generic_7bytes.cpp │ ├── generic_8bytes.cpp │ └── generic_common_impl.h ├── int_utils.h ├── lintrans.h ├── minisketch.cpp ├── sketch.h ├── sketch_impl.h ├── test.cpp └── util.h └── tests └── pyminisketch.py /.cirrus.yml: -------------------------------------------------------------------------------- 1 | env: 2 | BUILD: check 3 | HOST: 4 | MAKEFLAGS: -j4 5 | BENCH: yes 6 | TESTRUNS: 7 | EXEC_CMD: 8 | ENABLE_FIELDS: 9 | 10 | cat_logs_snippet: &CAT_LOGS 11 | on_failure: 12 | cat_test_log_script: 13 | - cat test-suite.log || true 14 | cat_config_log_script: 15 | - cat config.log || true 16 | cat_test_env_script: 17 | - cat test_env.log || true 18 | cat_ci_env_script: 19 | - env 20 | 21 | merge_base_script_snippet: &MERGE_BASE 22 | merge_base_script: 23 | - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi 24 | - git fetch $CIRRUS_REPO_CLONE_URL $CIRRUS_BASE_BRANCH 25 | - git config --global user.email "ci@ci.ci" 26 | - git config --global user.name "ci" 27 | - git merge FETCH_HEAD # Merge base to detect silent merge conflicts 28 | 29 | env_matrix_snippet: &ENV_MATRIX_VALGRIND 30 | - env: 31 | ENABLE_FIELDS: "7,32,58" 32 | - env: 33 | BUILD: distcheck 34 | - env: 35 | EXEC_CMD: valgrind --error-exitcode=42 36 | TESTRUNS: 1 37 | BUILD: 38 | 39 | env_matrix_snippet: &ENV_MATRIX_SAN_VALGRIND 40 | - env: 41 | ENABLE_FIELDS: "11,64,37" 42 | - env: 43 | BUILD: distcheck 44 | - env: 45 | EXEC_CMD: valgrind --error-exitcode=42 46 | TESTRUNS: 1 47 | BUILD: 48 | - env: 49 | CXXFLAGS: "-fsanitize=undefined -fno-omit-frame-pointer" 50 | LDFLAGS: "-fsanitize=undefined -fno-omit-frame-pointer" 51 | UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" 52 | BENCH: no 53 | 54 | task: 55 | name: "x86_64: Linux (Debian stable)" 56 | container: 57 | dockerfile: ci/linux-debian.Dockerfile 58 | memory: 2G 59 | cpu: 4 60 | matrix: 61 | << : *ENV_MATRIX_SAN_VALGRIND 62 | matrix: 63 | - env: 64 | CXX: g++ 65 | - env: 66 | CXX: clang++ -gdwarf-4 67 | << : *MERGE_BASE 68 | test_script: 69 | - ./ci/cirrus.sh 70 | << : *CAT_LOGS 71 | 72 | task: 73 | name: "i686: Linux (Debian stable)" 74 | container: 75 | dockerfile: ci/linux-debian.Dockerfile 76 | memory: 2G 77 | cpu: 4 78 | env: 79 | HOST: i686-linux-gnu 80 | matrix: 81 | << : *ENV_MATRIX_VALGRIND 82 | matrix: 83 | - env: 84 | CXX: i686-linux-gnu-g++ 85 | - env: 86 | CXX: clang++ --target=i686-linux-gnu -gdwarf-4 87 | CXXFLAGS: -g -O2 -isystem /usr/i686-linux-gnu/include -isystem /usr/i686-linux-gnu/include/c++/10/i686-linux-gnu 88 | test_script: 89 | - ./ci/cirrus.sh 90 | << : *CAT_LOGS 91 | 92 | task: 93 | name: "arm64: macOS Monterey" 94 | macos_instance: 95 | image: ghcr.io/cirruslabs/macos-monterey-base:latest 96 | env: 97 | # Cirrus gives us a fixed number of 4 virtual CPUs. 98 | MAKEFLAGS: -j5 99 | matrix: 100 | - env: 101 | CXX: g++-11 102 | # Homebrew's gcc for arm64 has no libubsan. 103 | matrix: 104 | - env: 105 | ENABLE_FIELDS: 28 106 | - env: 107 | BUILD: distcheck 108 | - env: 109 | CXX: clang++ 110 | matrix: 111 | - env: 112 | ENABLE_FIELDS: 28 113 | - env: 114 | BUILD: distcheck 115 | - env: 116 | CXXFLAGS: "-fsanitize=undefined -fno-omit-frame-pointer" 117 | LDFLAGS: "-fsanitize=undefined -fno-omit-frame-pointer" 118 | UBSAN_OPTIONS: "print_stacktrace=1:halt_on_error=1" 119 | BENCH: no 120 | brew_script: 121 | - brew update 122 | - brew install automake libtool gcc@11 123 | << : *MERGE_BASE 124 | test_script: 125 | - ./ci/cirrus.sh 126 | << : *CAT_LOGS 127 | 128 | task: 129 | name: "s390x (big-endian): Linux (Debian stable, QEMU)" 130 | container: 131 | dockerfile: ci/linux-debian.Dockerfile 132 | cpu: 4 133 | memory: 2G 134 | env: 135 | EXEC_CMD: qemu-s390x 136 | HOST: s390x-linux-gnu 137 | BUILD: 138 | << : *MERGE_BASE 139 | test_script: 140 | - ./ci/cirrus.sh 141 | << : *CAT_LOGS 142 | 143 | task: 144 | name: "x86_64-w64-mingw32: Linux (Debian stable, Wine)" 145 | container: 146 | dockerfile: ci/linux-debian.Dockerfile 147 | cpu: 4 148 | memory: 2G 149 | env: 150 | EXEC_CMD: wine 151 | EXEC_EXT: .exe 152 | HOST: x86_64-w64-mingw32 153 | BUILD: 154 | << : *MERGE_BASE 155 | test_script: 156 | - ./ci/cirrus.sh 157 | << : *CAT_LOGS 158 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.lo 3 | *.la 4 | *.dll 5 | *.dylib 6 | *.so.* 7 | .* 8 | *.a 9 | *~ 10 | 11 | Makefile 12 | Makefile.in 13 | aclocal.m4 14 | autom4te.cache/ 15 | build-aux/config.guess 16 | build-aux/config.sub 17 | build-aux/depcomp 18 | build-aux/install-sh 19 | build-aux/ltmain.sh 20 | build-aux/m4/libtool.m4 21 | build-aux/m4/lt~obsolete.m4 22 | build-aux/m4/ltoptions.m4 23 | build-aux/m4/ltsugar.m4 24 | build-aux/m4/ltversion.m4 25 | build-aux/missing 26 | build-aux/compile 27 | build-aux/test-driver 28 | config.log 29 | config.status 30 | configure 31 | libtool 32 | stamp-h1 33 | 34 | test* 35 | bench 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I build-aux/m4 2 | AM_CXXFLAGS = $(WARN_CXXFLAGS) $(NOWARN_CXXFLAGS) 3 | 4 | include sources.mk 5 | 6 | include_HEADERS = $(MINISKETCH_DIST_HEADERS_INT) 7 | noinst_HEADERS = $(MINISKETCH_LIB_HEADERS_INT) $(MINISKETCH_FIELD_GENERIC_HEADERS_INT) $(MINISKETCH_FIELD_CLMUL_HEADERS_INT) 8 | 9 | LIBMINISKETCH = libminisketch.la 10 | LIBMINISKETCH_FIELD_GENERIC = libminisketch_field_generic.la 11 | if ENABLE_CLMUL 12 | LIBMINISKETCH_FIELD_CLMUL = libminisketch_field_clmul.la 13 | endif 14 | if USE_TESTS 15 | LIBMINISKETCH_VERIFY=libminisketch_verify.la 16 | LIBMINISKETCH_FIELD_GENERIC_VERIFY=libminisketch_field_generic_verify.la 17 | if ENABLE_CLMUL 18 | LIBMINISKETCH_FIELD_CLMUL_VERIFY=libminisketch_field_clmul_verify.la 19 | endif 20 | endif 21 | 22 | lib_LTLIBRARIES = 23 | lib_LTLIBRARIES += $(LIBMINISKETCH) 24 | 25 | noinst_LTLIBRARIES = 26 | noinst_LTLIBRARIES += $(LIBMINISKETCH_FIELD_GENERIC) 27 | noinst_LTLIBRARIES += $(LIBMINISKETCH_FIELD_GENERIC_VERIFY) 28 | noinst_LTLIBRARIES += $(LIBMINISKETCH_FIELD_CLMUL) 29 | noinst_LTLIBRARIES += $(LIBMINISKETCH_FIELD_CLMUL_VERIFY) 30 | noinst_LTLIBRARIES += $(LIBMINISKETCH_VERIFY) 31 | 32 | # Release libs 33 | libminisketch_field_generic_la_SOURCES = $(MINISKETCH_FIELD_GENERIC_SOURCES_INT) 34 | libminisketch_field_generic_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES) 35 | 36 | libminisketch_field_clmul_la_SOURCES = $(MINISKETCH_FIELD_CLMUL_SOURCES_INT) 37 | libminisketch_field_clmul_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES) 38 | libminisketch_field_clmul_la_CXXFLAGS = $(AM_CXXFLAGS) $(CLMUL_CXXFLAGS) 39 | 40 | libminisketch_la_SOURCES = $(MINISKETCH_LIB_SOURCES_INT) 41 | libminisketch_la_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES) 42 | libminisketch_la_LIBADD = $(LIBMINISKETCH_FIELD_CLMUL) $(LIBMINISKETCH_FIELD_GENERIC) 43 | 44 | # Libs with extra verification checks 45 | libminisketch_field_generic_verify_la_SOURCES = $(MINISKETCH_FIELD_GENERIC_SOURCES_INT) 46 | libminisketch_field_generic_verify_la_CPPFLAGS = $(AM_CPPFLAGS) $(VERIFY_DEFINES) 47 | 48 | libminisketch_field_clmul_verify_la_SOURCES = $(MINISKETCH_FIELD_CLMUL_SOURCES_INT) 49 | libminisketch_field_clmul_verify_la_CPPFLAGS = $(AM_CPPFLAGS) $(VERIFY_DEFINES) 50 | libminisketch_field_clmul_verify_la_CXXFLAGS = $(AM_CXXFLAGS) $(CLMUL_CXXFLAGS) 51 | 52 | libminisketch_verify_la_SOURCES = $(MINISKETCH_LIB_SOURCES_INT) 53 | libminisketch_verify_la_CPPFLAGS = $(AM_CPPFLAGS) $(VERIFY_DEFINES) 54 | libminisketch_verify_la_LIBADD = $(LIBMINISKETCH_FIELD_CLMUL_VERIFY) $(LIBMINISKETCH_FIELD_GENERIC_VERIFY) 55 | 56 | noinst_PROGRAMS = 57 | if USE_BENCHMARK 58 | noinst_PROGRAMS += bench 59 | endif 60 | if USE_TESTS 61 | noinst_PROGRAMS += test test-verify 62 | TESTS = test test-verify 63 | endif 64 | 65 | bench_SOURCES = $(MINISKETCH_BENCH_SOURCES_INT) 66 | bench_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES) 67 | bench_LDADD = $(LIBMINISKETCH) 68 | bench_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) 69 | 70 | test_SOURCES = $(MINISKETCH_TEST_SOURCES_INT) 71 | test_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES) 72 | test_LDADD = $(LIBMINISKETCH) 73 | test_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) 74 | 75 | test_verify_SOURCES = $(MINISKETCH_TEST_SOURCES_INT) 76 | test_verify_CPPFLAGS = $(AM_CPPFLAGS) $(VERIFY_DEFINES) 77 | test_verify_LDADD = $(LIBMINISKETCH_VERIFY) 78 | test_verify_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) 79 | 80 | EXTRA_DIST= 81 | EXTRA_DIST += LICENSE 82 | EXTRA_DIST += README.md 83 | EXTRA_DIST += doc/example.c 84 | EXTRA_DIST += doc/gen_params.sage 85 | EXTRA_DIST += doc/math.md 86 | EXTRA_DIST += doc/moduli.md 87 | EXTRA_DIST += doc/plot_bits.png 88 | EXTRA_DIST += doc/plot_capacity.png 89 | EXTRA_DIST += doc/plot_diff.png 90 | EXTRA_DIST += doc/plot_size.png 91 | EXTRA_DIST += doc/protocoltips.md 92 | EXTRA_DIST += tests/pyminisketch.py 93 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Copyright (c) 2013-2016 The Bitcoin Core developers 3 | # Distributed under the MIT software license, see the accompanying 4 | # file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 | 6 | set -e 7 | srcdir="$(dirname $0)" 8 | cd "$srcdir" 9 | if [ -z ${LIBTOOLIZE} ] && GLIBTOOLIZE="`which glibtoolize 2>/dev/null`"; then 10 | LIBTOOLIZE="${GLIBTOOLIZE}" 11 | export LIBTOOLIZE 12 | fi 13 | which autoreconf >/dev/null || \ 14 | (echo "configuration failed, please install autoconf first" && exit 1) 15 | autoreconf --install --force --warnings=all 16 | -------------------------------------------------------------------------------- /build-aux/m4/ax_check_compile_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's compiler 12 | # or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the current language's default 18 | # flags (e.g. CFLAGS) when the check is done. The check is thus made with 19 | # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to 20 | # force the compiler to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_COMPILE_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_COMPILE_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS 44 | _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" 45 | AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_COMPILE_FLAGS 54 | -------------------------------------------------------------------------------- /build-aux/m4/ax_check_link_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the linker or gives an error. 12 | # (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the linker's default flags 18 | # when the check is done. The check is thus made with the flags: "LDFLAGS 19 | # EXTRA-FLAGS FLAG". This can for example be used to force the linker to 20 | # issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_LINK_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_LINK_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$LDFLAGS 44 | LDFLAGS="$LDFLAGS $4 $1" 45 | AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | LDFLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_LINK_FLAGS 54 | -------------------------------------------------------------------------------- /build-aux/m4/ax_check_preproc_flag.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # https://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_CHECK_PREPROC_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # Check whether the given FLAG works with the current language's 12 | # preprocessor or gives an error. (Warnings, however, are ignored) 13 | # 14 | # ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on 15 | # success/failure. 16 | # 17 | # If EXTRA-FLAGS is defined, it is added to the preprocessor's default 18 | # flags when the check is done. The check is thus made with the flags: 19 | # "CPPFLAGS EXTRA-FLAGS FLAG". This can for example be used to force the 20 | # preprocessor to issue an error when a bad flag is given. 21 | # 22 | # INPUT gives an alternative input source to AC_PREPROC_IFELSE. 23 | # 24 | # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this 25 | # macro in sync with AX_CHECK_{COMPILE,LINK}_FLAG. 26 | # 27 | # LICENSE 28 | # 29 | # Copyright (c) 2008 Guido U. Draheim 30 | # Copyright (c) 2011 Maarten Bosmans 31 | # 32 | # Copying and distribution of this file, with or without modification, are 33 | # permitted in any medium without royalty provided the copyright notice 34 | # and this notice are preserved. This file is offered as-is, without any 35 | # warranty. 36 | 37 | #serial 6 38 | 39 | AC_DEFUN([AX_CHECK_PREPROC_FLAG], 40 | [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF 41 | AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]cppflags_$4_$1])dnl 42 | AC_CACHE_CHECK([whether _AC_LANG preprocessor accepts $1], CACHEVAR, [ 43 | ax_check_save_flags=$CPPFLAGS 44 | CPPFLAGS="$CPPFLAGS $4 $1" 45 | AC_PREPROC_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], 46 | [AS_VAR_SET(CACHEVAR,[yes])], 47 | [AS_VAR_SET(CACHEVAR,[no])]) 48 | CPPFLAGS=$ax_check_save_flags]) 49 | AS_VAR_IF(CACHEVAR,yes, 50 | [m4_default([$2], :)], 51 | [m4_default([$3], :)]) 52 | AS_VAR_POPDEF([CACHEVAR])dnl 53 | ])dnl AX_CHECK_PREPROC_FLAGS 54 | -------------------------------------------------------------------------------- /ci/cirrus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | export LC_ALL=C 7 | 8 | env >> test_env.log 9 | 10 | $CXX -v || true 11 | valgrind --version || true 12 | 13 | ./autogen.sh 14 | 15 | FIELDS= 16 | if [ -n "$ENABLE_FIELDS" ]; then 17 | FIELDS="--enable-fields=$ENABLE_FIELDS" 18 | fi 19 | ./configure --host="$HOST" --enable-benchmark="$BENCH" $FIELDS 20 | 21 | # We have set "-j" in MAKEFLAGS. 22 | make 23 | 24 | # Print information about binaries so that we can see that the architecture is correct 25 | file test* || true 26 | file bench* || true 27 | file .libs/* || true 28 | 29 | if [ -n "$BUILD" ] 30 | then 31 | make "$BUILD" 32 | fi 33 | 34 | if [ -n "$EXEC_CMD" ]; then 35 | $EXEC_CMD "./test$EXEC_EXT" $TESTRUNS 36 | $EXEC_CMD "./test-verify$EXEC_EXT" $TESTRUNS 37 | fi 38 | 39 | if [ "$BENCH" = "yes" ]; then 40 | $EXEC_CMD "./bench$EXEC_EXT" 41 | fi 42 | -------------------------------------------------------------------------------- /ci/linux-debian.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stable 2 | 3 | RUN dpkg --add-architecture i386 4 | RUN dpkg --add-architecture s390x 5 | RUN apt-get update 6 | 7 | # dkpg-dev: to make pkg-config work in cross-builds 8 | RUN apt-get install --no-install-recommends --no-upgrade -y \ 9 | git ca-certificates \ 10 | make automake libtool pkg-config dpkg-dev valgrind qemu-user \ 11 | gcc g++ clang libclang-rt-dev libc6-dbg \ 12 | gcc-i686-linux-gnu g++-i686-linux-gnu libc6-dev-i386-cross libc6-dbg:i386 \ 13 | g++-s390x-linux-gnu libstdc++6:s390x gcc-s390x-linux-gnu libc6-dev-s390x-cross libc6-dbg:s390x \ 14 | wine wine64 g++-mingw-w64-x86-64 15 | 16 | # Run a dummy command in wine to make it set up configuration 17 | RUN wine true || true 18 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([minisketch], [0.0.1], [http://github.com/bitcoin-core/minisketch/]) 2 | 3 | m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) 4 | 5 | AC_PREREQ(2.60) 6 | AC_CONFIG_SRCDIR([src/minisketch.cpp]) 7 | AC_CONFIG_AUX_DIR([build-aux]) 8 | AC_CONFIG_MACRO_DIR([build-aux/m4]) 9 | AM_INIT_AUTOMAKE([subdir-objects foreign]) 10 | 11 | LT_INIT 12 | LT_LANG([C++]) 13 | AC_LANG([C++]) 14 | 15 | AC_PATH_PROG(CCACHE,ccache) 16 | 17 | AC_ARG_ENABLE([ccache], 18 | [AS_HELP_STRING([--disable-ccache], 19 | [do not use ccache for building (default is to use if found)])], 20 | [use_ccache=$enableval], 21 | [use_ccache=auto]) 22 | 23 | AC_ARG_ENABLE(tests, 24 | AS_HELP_STRING([--enable-tests],[compile tests (default is yes)]), 25 | [use_tests=$enableval], 26 | [use_tests=yes]) 27 | 28 | AC_ARG_ENABLE(benchmark, 29 | AS_HELP_STRING([--enable-benchmark],[compile benchmark (default is no)]), 30 | [use_benchmark=$enableval], 31 | [use_benchmark=no]) 32 | 33 | m4_define([SUPPORTED_FIELDS], [2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64]) 34 | 35 | AC_MSG_CHECKING([which field sizes to build]) 36 | AC_ARG_ENABLE([fields], AS_HELP_STRING([--enable-fields=LIST], [Comma-separated list of field sizes to build. Default=all. Available sizes:] m4_translit(m4_defn([SUPPORTED_FIELDS]), [,], [ ])), [], [enable_fields=SUPPORTED_FIELDS]) 37 | have_disabled_fields=no 38 | have_enabled_fields=no 39 | m4_foreach([FIELD], [SUPPORTED_FIELDS], [ 40 | case ",$enable_fields," in 41 | *,FIELD,*) 42 | have_enabled_fields=yes 43 | ;; 44 | *) 45 | AC_DEFINE(DISABLE_FIELD_[]FIELD, [1], 46 | [Define to 1 to remove support for field size] FIELD [.]) 47 | have_disabled_fields=yes 48 | ;; 49 | esac 50 | ]) 51 | AC_MSG_RESULT([$enable_fields]) 52 | if test "x$have_enabled_fields" = xno; then 53 | AC_MSG_ERROR([No field sizes are enabled.]) 54 | fi 55 | 56 | AX_CHECK_COMPILE_FLAG([-Werror],[CXXFLAG_WERROR="-Werror"],[CXXFLAG_WERROR=""]) 57 | 58 | AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory]) 59 | enable_clmul= 60 | AX_CHECK_COMPILE_FLAG([-mpclmul],[[enable_clmul=yes]],,[[$CXXFLAG_WERROR]],[AC_LANG_PROGRAM([ 61 | #include 62 | #include 63 | ], [ 64 | __m128i a = _mm_cvtsi64_si128((uint64_t)7); 65 | __m128i b = _mm_clmulepi64_si128(a, a, 37); 66 | __m128i c = _mm_srli_epi64(b, 41); 67 | __m128i d = _mm_xor_si128(b, c); 68 | uint64_t e = _mm_cvtsi128_si64(d); 69 | return e == 0; 70 | ])]) 71 | if test x$enable_clmul = xyes; then 72 | CLMUL_CXXFLAGS="-mpclmul" 73 | AC_DEFINE(HAVE_CLMUL, 1, [Define this symbol if clmul instructions can be used]) 74 | fi 75 | 76 | 77 | AC_MSG_CHECKING(for working clz builtins) 78 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ 79 | unsigned a = __builtin_clz(1); 80 | unsigned long b = __builtin_clzl(1); 81 | unsigned long long c = __builtin_clzll(1); 82 | ])], 83 | [ 84 | AC_DEFINE(HAVE_CLZ, 1, [Define this symbol if clz builtins are present and working]) 85 | AC_MSG_RESULT(yes) 86 | ],[ 87 | AC_MSG_RESULT(no) 88 | ] 89 | ) 90 | 91 | AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]],[LDFLAGS="-Wl,--exclude-libs,ALL $LDFLAGS"]) 92 | 93 | case $host in 94 | *mingw*) 95 | dnl -static is interpreted by libtool, where it has a different meaning. 96 | dnl In libtool-speak, it's -all-static. 97 | AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"]) 98 | ;; 99 | *) 100 | AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="-static"]) 101 | ;; 102 | esac 103 | 104 | AX_CHECK_COMPILE_FLAG([-Wall],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]]) 105 | AX_CHECK_COMPILE_FLAG([-Wundef], [WARN_CXXFLAGS="$WARN_CXXFLAGS -Wundef"], [], [$CXXFLAG_WERROR]) 106 | AX_CHECK_COMPILE_FLAG([-fvisibility=hidden],[CXXFLAGS="$CXXFLAGS -fvisibility=hidden"],[],[$CXXFLAG_WERROR]) 107 | 108 | if test "x$use_ccache" != "xno"; then 109 | AC_MSG_CHECKING(if ccache should be used) 110 | if test x$CCACHE = x; then 111 | if test "x$use_ccache" = "xyes"; then 112 | AC_MSG_ERROR([ccache not found.]); 113 | else 114 | use_ccache=no 115 | fi 116 | else 117 | use_ccache=yes 118 | CXX="$ac_cv_path_CCACHE $CXX" 119 | fi 120 | AC_MSG_RESULT($use_ccache) 121 | fi 122 | 123 | VERIFY_DEFINES=-DMINISKETCH_VERIFY 124 | RELEASE_DEFINES= 125 | 126 | AC_CONFIG_FILES([ 127 | Makefile 128 | ]) 129 | 130 | AC_SUBST(CLMUL_CXXFLAGS) 131 | AC_SUBST(WARN_CXXFLAGS) 132 | AC_SUBST(NOWARN_CXXFLAGS) 133 | AC_SUBST(VERIFY_DEFINES) 134 | AC_SUBST(RELEASE_DEFINES) 135 | AC_SUBST(LIBTOOL_APP_LDFLAGS) 136 | AM_CONDITIONAL([ENABLE_CLMUL],[test x$enable_clmul = xyes]) 137 | AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"]) 138 | AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"]) 139 | AC_OUTPUT 140 | 141 | echo 142 | echo "Build Options:" 143 | echo " with benchmarks = $use_benchmark" 144 | echo " with tests = $use_tests" 145 | echo " enable clmul fields = $enable_clmul" 146 | echo " CXX = $CXX" 147 | echo " CXXFLAGS = $CXXFLAGS" 148 | echo " CPPFLAGS = $CPPFLAGS" 149 | echo " LDFLAGS = $LDFLAGS" 150 | if test "$have_disabled_fields" = "yes"; then 151 | echo 152 | echo "Only compiling in support for field sizes: $enable_fields" 153 | echo "WARNING: this means the library will lack support for other field sizes entirely" 154 | fi 155 | -------------------------------------------------------------------------------- /doc/example.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include 8 | #include 9 | #include "../include/minisketch.h" 10 | 11 | int main(void) { 12 | 13 | minisketch *sketch_a = minisketch_create(12, 0, 4); 14 | 15 | for (int i = 3000; i < 3010; ++i) { 16 | minisketch_add_uint64(sketch_a, i); 17 | } 18 | 19 | size_t sersize = minisketch_serialized_size(sketch_a); 20 | assert(sersize == 12 * 4 / 8); // 4 12-bit values is 6 bytes. 21 | unsigned char *buffer_a = malloc(sersize); 22 | minisketch_serialize(sketch_a, buffer_a); 23 | minisketch_destroy(sketch_a); 24 | 25 | minisketch *sketch_b = minisketch_create(12, 0, 4); // Bob's own sketch 26 | for (int i = 3002; i < 3012; ++i) { 27 | minisketch_add_uint64(sketch_b, i); 28 | } 29 | 30 | sketch_a = minisketch_create(12, 0, 4); // Alice's sketch 31 | minisketch_deserialize(sketch_a, buffer_a); // Load Alice's sketch 32 | free(buffer_a); 33 | 34 | // Merge the elements from sketch_a into sketch_b. The result is a sketch_b 35 | // which contains all elements that occurred in Alice's or Bob's sets, but not 36 | // in both. 37 | minisketch_merge(sketch_b, sketch_a); 38 | 39 | uint64_t differences[4]; 40 | ssize_t num_differences = minisketch_decode(sketch_b, 4, differences); 41 | minisketch_destroy(sketch_a); 42 | minisketch_destroy(sketch_b); 43 | if (num_differences < 0) { 44 | printf("More than 4 differences!\n"); 45 | } else { 46 | ssize_t i; 47 | for (i = 0; i < num_differences; ++i) { 48 | printf("%u is in only one of the two sets\n", (unsigned)differences[i]); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /doc/gen_basefpbits.sage: -------------------------------------------------------------------------------- 1 | # Require exact values up to 2 | FPBITS = 256 3 | 4 | # Overkill accuracy 5 | F = RealField(400) 6 | 7 | def BaseFPBits(bits, capacity): 8 | return bits * capacity - int(ceil(F(log(sum(binomial(2**bits - 1, i) for i in range(capacity+1)), 2)))) 9 | 10 | def Log2Factorial(capacity): 11 | return int(floor(log(factorial(capacity), 2))) 12 | 13 | print("uint64_t BaseFPBits(uint32_t bits, uint32_t capacity) {") 14 | print(" // Correction table for low bits/capacities") 15 | TBLS={} 16 | FARS={} 17 | SKIPS={} 18 | for bits in range(1, 32): 19 | TBL = [] 20 | for capacity in range(1, min(2**bits, FPBITS)): 21 | exact = BaseFPBits(bits, capacity) 22 | approx = Log2Factorial(capacity) 23 | TBL.append((exact, approx)) 24 | MIN = 10000000000 25 | while len(TBL) and ((TBL[-1][0] == TBL[-1][1]) or (TBL[-1][0] >= FPBITS and TBL[-1][1] >= FPBITS)): 26 | MIN = min(MIN, TBL[-1][0] - TBL[-1][1]) 27 | TBL.pop() 28 | while len(TBL) and (TBL[-1][0] - TBL[-1][1] == MIN): 29 | TBL.pop() 30 | SKIP = 0 31 | while SKIP < len(TBL) and TBL[SKIP][0] == TBL[SKIP][1]: 32 | SKIP += 1 33 | DIFFS = [TBL[i][0] - TBL[i][1] for i in range(SKIP, len(TBL))] 34 | if len(DIFFS) > 0 and len(DIFFS) * Integer(max(DIFFS)).nbits() > 64: 35 | print(" static constexpr uint8_t ADD%i[] = {%s};" % (bits, ", ".join(("%i" % (TBL[i][0] - TBL[i][1])) for i in range(SKIP, len(TBL))))) 36 | TBLS[bits] = DIFFS 37 | FARS[bits] = MIN 38 | SKIPS[bits] = SKIP 39 | print("") 40 | print(" if (capacity == 0) return 0;") 41 | print(" uint64_t ret = 0;") 42 | print(" if (bits < 32 && capacity >= (1U << bits)) {") 43 | print(" ret = uint64_t{bits} * (capacity - (1U << bits) + 1);") 44 | print(" capacity = (1U << bits) - 1;") 45 | print(" }") 46 | print(" ret += Log2Factorial(capacity);") 47 | print(" switch (bits) {") 48 | for bits in sorted(TBLS.keys()): 49 | if len(TBLS[bits]) == 0: 50 | continue 51 | width = Integer(max(TBLS[bits])).nbits() 52 | if len(TBLS[bits]) == 1: 53 | add = "%i" % TBLS[bits][0] 54 | elif len(TBLS[bits]) * width <= 64: 55 | code = sum((2**(width*i) * TBLS[bits][i]) for i in range(len(TBLS[bits]))) 56 | if width == 1: 57 | add = "(0x%x >> (capacity - %i)) & 1" % (code, 1 + SKIPS[bits]) 58 | else: 59 | add = "(0x%x >> %i * (capacity - %i)) & %i" % (code, width, 1 + SKIPS[bits], 2**width - 1) 60 | else: 61 | add = "ADD%i[capacity - %i]" % (bits, 1 + SKIPS[bits]) 62 | if len(TBLS[bits]) + SKIPS[bits] == 2**bits - 1: 63 | print(" case %i: return ret + (capacity <= %i ? 0 : %s);" % (bits, SKIPS[bits], add)) 64 | else: 65 | print(" case %i: return ret + (capacity <= %i ? 0 : capacity > %i ? %i : %s);" % (bits, SKIPS[bits], len(TBLS[bits]) + SKIPS[bits], FARS[bits], add)) 66 | print(" default: return ret;") 67 | print(" }") 68 | print("}") 69 | 70 | print("void TestBaseFPBits() {") 71 | print(" static constexpr uint16_t TBL[20][100] = {%s};" % (", ".join("{" + ", ".join(("%i" % BaseFPBits(bits, capacity)) for capacity in range(0, 100)) + "}" for bits in range(1, 21)))) 72 | print(" for (int bits = 1; bits <= 20; ++bits) {") 73 | print(" for (int capacity = 0; capacity < 100; ++capacity) {") 74 | print(" uint64_t computed = BaseFPBits(bits, capacity), exact = TBL[bits - 1][capacity];") 75 | print(" CHECK(exact == computed || (exact >= 256 && computed >= 256));") 76 | print(" }") 77 | print(" }") 78 | print("}") 79 | -------------------------------------------------------------------------------- /doc/gen_params.sage: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sage 2 | r""" 3 | Generate finite field parameters for minisketch. 4 | 5 | This script selects the finite fields used by minisketch 6 | for various sizes and generates the required tables for 7 | the implementation. 8 | 9 | The output (after formatting) can be found in src/fields/*.cpp. 10 | 11 | """ 12 | B. = GF(2) 13 | P.

= B[] 14 | 15 | def apply_map(m, v): 16 | r = 0 17 | i = 0 18 | while v != 0: 19 | if (v & 1): 20 | r ^^= m[i] 21 | i += 1 22 | v >>= 1 23 | return r 24 | 25 | def recurse_moduli(acc, maxweight, maxdegree): 26 | for pos in range(maxweight, maxdegree + 1, 1): 27 | poly = acc + p^pos 28 | if maxweight == 1: 29 | if poly.is_irreducible(): 30 | return (pos, poly) 31 | else: 32 | (deg, ret) = recurse_moduli(poly, maxweight - 1, pos - 1) 33 | if ret is not None: 34 | return (pos, ret) 35 | return (None, None) 36 | 37 | def compute_moduli(bits): 38 | # Return all optimal irreducible polynomials for GF(2^bits) 39 | # The result is a list of tuples (weight, degree of second-highest nonzero coefficient, polynomial) 40 | maxdegree = bits - 1 41 | result = [] 42 | for weight in range(1, bits, 2): 43 | deg, res = None, None 44 | while True: 45 | ret = recurse_moduli(p^bits + 1, weight, maxdegree) 46 | if ret[0] is not None: 47 | (deg, res) = ret 48 | maxdegree = deg - 1 49 | else: 50 | break 51 | if res is not None: 52 | result.append((weight + 2, deg, res)) 53 | return result 54 | 55 | def bits_to_int(vals): 56 | ret = 0 57 | base = 1 58 | for val in vals: 59 | ret += Integer(val) * base 60 | base *= 2 61 | return ret 62 | 63 | def sqr_table(f, bits, n=1): 64 | ret = [] 65 | for i in range(bits): 66 | ret.append((f^(2^n*i)).integer_representation()) 67 | return ret 68 | 69 | # Compute x**(2**n) 70 | def pow2(x, n): 71 | for i in range(n): 72 | x = x**2 73 | return x 74 | 75 | def qrt_table(F, f, bits): 76 | # Table for solving x2 + x = a 77 | # This implements the technique from https://www.raco.cat/index.php/PublicacionsMatematiques/article/viewFile/37927/40412, Lemma 1 78 | for i in range(bits): 79 | if (f**i).trace() != 0: 80 | u = f**i 81 | ret = [] 82 | for i in range(0, bits): 83 | d = f^i 84 | y = sum(pow2(d, j) * sum(pow2(u, k) for k in range(j)) for j in range(1, bits)) 85 | ret.append(y.integer_representation() ^^ (y.integer_representation() & 1)) 86 | return ret 87 | 88 | def conv_tables(F, NF, bits): 89 | # Generate a F(2) linear projection that maps elements from one field 90 | # to an isomorphic field with a different modulus. 91 | f = F.gen() 92 | fp = f.minimal_polynomial() 93 | assert(fp == F.modulus()) 94 | nfp = fp.change_ring(NF) 95 | nf = sorted(nfp.roots(multiplicities=False))[0] 96 | ret = [] 97 | matrepr = [[B(0) for x in range(bits)] for y in range(bits)] 98 | for i in range(bits): 99 | val = (nf**i).integer_representation() 100 | ret.append(val) 101 | for j in range(bits): 102 | matrepr[j][i] = B((val >> j) & 1) 103 | mat = Matrix(matrepr).inverse().transpose() 104 | ret2 = [] 105 | for i in range(bits): 106 | ret2.append(bits_to_int(mat[i])) 107 | 108 | for t in range(100): 109 | f1a = F.random_element() 110 | f1b = F.random_element() 111 | f1r = f1a * f1b 112 | f2a = NF.fetch_int(apply_map(ret, f1a.integer_representation())) 113 | f2b = NF.fetch_int(apply_map(ret, f1b.integer_representation())) 114 | f2r = NF.fetch_int(apply_map(ret, f1r.integer_representation())) 115 | f2s = f2a * f2b 116 | assert(f2r == f2s) 117 | 118 | for t in range(100): 119 | f2a = NF.random_element() 120 | f2b = NF.random_element() 121 | f2r = f2a * f2b 122 | f1a = F.fetch_int(apply_map(ret2, f2a.integer_representation())) 123 | f1b = F.fetch_int(apply_map(ret2, f2b.integer_representation())) 124 | f1r = F.fetch_int(apply_map(ret2, f2r.integer_representation())) 125 | f1s = f1a * f1b 126 | assert(f1r == f1s) 127 | 128 | return (ret, ret2) 129 | 130 | def fmt(i,typ): 131 | if i == 0: 132 | return "0" 133 | else: 134 | return "0x%x" % i 135 | 136 | def lintranstype(typ, bits, maxtbl): 137 | gsize = min(maxtbl, bits) 138 | array_size = (bits + gsize - 1) // gsize 139 | bits_list = [] 140 | total = 0 141 | for i in range(array_size): 142 | rsize = (bits - total + array_size - i - 1) // (array_size - i) 143 | total += rsize 144 | bits_list.append(rsize) 145 | return "RecLinTrans<%s, %s>" % (typ, ", ".join("%i" % x for x in bits_list)) 146 | 147 | INT=0 148 | CLMUL=1 149 | CLMUL_TRI=2 150 | MD=3 151 | 152 | def print_modulus_md(mod): 153 | ret = "" 154 | pos = mod.degree() 155 | for c in reversed(list(mod)): 156 | if c: 157 | if ret: 158 | ret += " + " 159 | if pos == 0: 160 | ret += "1" 161 | elif pos == 1: 162 | ret += "x" 163 | else: 164 | ret += "x%i" % pos 165 | pos -= 1 166 | return ret 167 | 168 | def pick_modulus(bits, style): 169 | # Choose the lexicographicly-first lowest-weight modulus 170 | # optionally subject to implementation specific constraints. 171 | moduli = compute_moduli(bits) 172 | if style == INT or style == MD: 173 | multi_sqr = False 174 | need_trans = False 175 | elif style == CLMUL: 176 | # Fast CLMUL reduction requires that bits + the highest 177 | # set bit are less than 66. 178 | moduli = list(filter((lambda x: bits+x[1] <= 66), moduli)) + moduli 179 | multi_sqr = True 180 | need_trans = True 181 | if not moduli or moduli[0][2].change_ring(ZZ)(2) == 3 + 2**bits: 182 | # For modulus 3, CLMUL_TRI is obviously better. 183 | return None 184 | elif style == CLMUL_TRI: 185 | moduli = list(filter(lambda x: bits+x[1] <= 66, moduli)) + moduli 186 | moduli = list(filter(lambda x: x[0] == 3, moduli)) 187 | multi_sqr = True 188 | need_trans = True 189 | else: 190 | assert(False) 191 | if not moduli: 192 | return None 193 | return moduli[0][2] 194 | 195 | def print_result(bits, style): 196 | if style == INT: 197 | multi_sqr = False 198 | need_trans = False 199 | table_id = "%i" % bits 200 | elif style == MD: 201 | pass 202 | elif style == CLMUL: 203 | multi_sqr = True 204 | need_trans = True 205 | table_id = "%i" % bits 206 | elif style == CLMUL_TRI: 207 | multi_sqr = True 208 | need_trans = True 209 | table_id = "TRI%i" % bits 210 | else: 211 | assert(False) 212 | 213 | nmodulus = pick_modulus(bits, INT) 214 | modulus = pick_modulus(bits, style) 215 | if modulus is None: 216 | return 217 | 218 | if style == MD: 219 | print("* *%s*" % print_modulus_md(modulus)) 220 | return 221 | 222 | if bits > 32: 223 | typ = "uint64_t" 224 | elif bits > 16: 225 | typ = "uint32_t" 226 | elif bits > 8: 227 | typ = "uint16_t" 228 | else: 229 | typ = "uint8_t" 230 | 231 | ttyp = lintranstype(typ, bits, 4) 232 | rtyp = lintranstype(typ, bits, 6) 233 | 234 | F. = GF(2**bits, modulus=modulus) 235 | 236 | include_table = True 237 | if style != INT and style != CLMUL: 238 | cmodulus = pick_modulus(bits, CLMUL) 239 | if cmodulus == modulus: 240 | include_table = False 241 | table_id = "%i" % bits 242 | 243 | if include_table: 244 | print("typedef %s StatTable%s;" % (rtyp, table_id)) 245 | rtyp = "StatTable%s" % table_id 246 | if (style == INT): 247 | print("typedef %s DynTable%s;" % (ttyp, table_id)) 248 | ttyp = "DynTable%s" % table_id 249 | 250 | if need_trans: 251 | if modulus != nmodulus: 252 | # If the bitstream modulus is not the best modulus for 253 | # this implementation a conversion table will be needed. 254 | ctyp = rtyp 255 | NF. = GF(2**bits, modulus=nmodulus) 256 | ctables = conv_tables(NF, F, bits) 257 | loadtbl = "&LOAD_TABLE_%s" % table_id 258 | savetbl = "&SAVE_TABLE_%s" % table_id 259 | if include_table: 260 | print("constexpr %s LOAD_TABLE_%s({%s});" % (ctyp, table_id, ", ".join([fmt(x,typ) for x in ctables[0]]))) 261 | print("constexpr %s SAVE_TABLE_%s({%s});" % (ctyp, table_id, ", ".join([fmt(x,typ) for x in ctables[1]]))) 262 | else: 263 | ctyp = "IdTrans" 264 | loadtbl = "&ID_TRANS" 265 | savetbl = "&ID_TRANS" 266 | else: 267 | assert(modulus == nmodulus) 268 | 269 | if include_table: 270 | print("constexpr %s SQR_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in sqr_table(f, bits, 1)]))) 271 | if multi_sqr: 272 | # Repeated squaring is a linearised polynomial so in F(2^n) it is 273 | # F(2) linear and can be computed by a simple bit-matrix. 274 | # Repeated squaring is especially useful in powering ladders such as 275 | # for inversion. 276 | # When certain repeated squaring tables are not in use, use the QRT 277 | # table instead to make the C++ compiler happy (it always has the 278 | # same type). 279 | sqr2 = "&QRT_TABLE_%s" % table_id 280 | sqr4 = "&QRT_TABLE_%s" % table_id 281 | sqr8 = "&QRT_TABLE_%s" % table_id 282 | sqr16 = "&QRT_TABLE_%s" % table_id 283 | if ((bits - 1) >= 4): 284 | if include_table: 285 | print("constexpr %s SQR2_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in sqr_table(f, bits, 2)]))) 286 | sqr2 = "&SQR2_TABLE_%s" % table_id 287 | if ((bits - 1) >= 8): 288 | if include_table: 289 | print("constexpr %s SQR4_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in sqr_table(f, bits, 4)]))) 290 | sqr4 = "&SQR4_TABLE_%s" % table_id 291 | if ((bits - 1) >= 16): 292 | if include_table: 293 | print("constexpr %s SQR8_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in sqr_table(f, bits, 8)]))) 294 | sqr8 = "&SQR8_TABLE_%s" % table_id 295 | if ((bits - 1) >= 32): 296 | if include_table: 297 | print("constexpr %s SQR16_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in sqr_table(f, bits, 16)]))) 298 | sqr16 = "&SQR16_TABLE_%s" % table_id 299 | if include_table: 300 | print("constexpr %s QRT_TABLE_%s({%s});" % (rtyp, table_id, ", ".join([fmt(x,typ) for x in qrt_table(F, f, bits)]))) 301 | 302 | modulus_weight = modulus.hamming_weight() 303 | modulus_degree = (modulus - p**bits).degree() 304 | modulus_int = (modulus - p**bits).change_ring(ZZ)(2) 305 | 306 | lfsr = "" 307 | 308 | if style == INT: 309 | print("typedef Field<%s, %i, %i, %s, %s, &SQR_TABLE_%s, &QRT_TABLE_%s%s> Field%i;" % (typ, bits, modulus_int, rtyp, ttyp, table_id, table_id, lfsr, bits)) 310 | elif style == CLMUL: 311 | print("typedef Field<%s, %i, %i, %s, &SQR_TABLE_%s, %s, %s, %s, %s, &QRT_TABLE_%s, %s, %s, %s%s> Field%i;" % (typ, bits, modulus_int, rtyp, table_id, sqr2, sqr4, sqr8, sqr16, table_id, ctyp, loadtbl, savetbl, lfsr, bits)) 312 | elif style == CLMUL_TRI: 313 | print("typedef FieldTri<%s, %i, %i, %s, &SQR_TABLE_%s, %s, %s, %s, %s, &QRT_TABLE_%s, %s, %s, %s> FieldTri%i;" % (typ, bits, modulus_degree, rtyp, table_id, sqr2, sqr4, sqr8, sqr16, table_id, ctyp, loadtbl, savetbl, bits)) 314 | else: 315 | assert(False) 316 | 317 | for bits in range(2, 65): 318 | print("#ifdef ENABLE_FIELD_INT_%i" % bits) 319 | print("// %i bit field" % bits) 320 | print_result(bits, INT) 321 | print("#endif") 322 | print("") 323 | 324 | for bits in range(2, 65): 325 | print("#ifdef ENABLE_FIELD_INT_%i" % bits) 326 | print("// %i bit field" % bits) 327 | print_result(bits, CLMUL) 328 | print_result(bits, CLMUL_TRI) 329 | print("#endif") 330 | print("") 331 | 332 | for bits in range(2, 65): 333 | print_result(bits, MD) 334 | -------------------------------------------------------------------------------- /doc/log2_factorial.sage: -------------------------------------------------------------------------------- 1 | import bisect 2 | 3 | INPUT_BITS = 32 4 | TABLE_BITS = 5 5 | INT_BITS = 64 6 | EXACT_FPBITS = 256 7 | 8 | F = RealField(100) # overkill 9 | 10 | def BestOverApproxInvLog2(mulof, maxd): 11 | """ 12 | Compute denominator of an approximation of 1/log(2). 13 | 14 | Specifically, find the value of d (<= maxd, and a multiple of mulof) 15 | such that ceil(d/log(2))/d is the best approximation of 1/log(2). 16 | """ 17 | dist=1 18 | best=0 19 | # Precomputed denominators that lead to good approximations of 1/log(2) 20 | for d in [1, 2, 9, 70, 131, 192, 445, 1588, 4319, 11369, 18419, 25469, 287209, 836158, 3057423, 8336111, 21950910, 35565709, 49180508, 161156323, 273132138, 385107953, 882191721]: 21 | kd = lcm(mulof, d) 22 | if kd <= maxd: 23 | n = ceil(kd / log(2)) 24 | dis = F((n / kd) - 1 / log(2)) 25 | if dis < dist: 26 | dist = dis 27 | best = kd 28 | return best 29 | 30 | 31 | LOG2_TABLE = [] 32 | A = 0 33 | B = 0 34 | C = 0 35 | D = 0 36 | K = 0 37 | 38 | def Setup(k): 39 | global LOG2_TABLE, A, B, C, D, K 40 | K = k 41 | LOG2_TABLE = [] 42 | for i in range(2 ** TABLE_BITS): 43 | LOG2_TABLE.append(int(floor(F(K * log(1 + i / 2**TABLE_BITS, 2))))) 44 | 45 | # Maximum for (2*x+1)*LogK2(x) 46 | max_T = (2^(INPUT_BITS + 1) - 1) * (INPUT_BITS*K - 1) 47 | # Maximum for A 48 | max_A = (2^INT_BITS - 1) // max_T 49 | D = BestOverApproxInvLog2(2 * K, max_A * 2 * K) 50 | A = D // (2 * K) 51 | B = int(ceil(F(D/log(2)))) 52 | C = int(floor(F(D*log(2*pi,2)/2))) 53 | 54 | def LogK2(n): 55 | assert(n >= 1 and n < (1 << INPUT_BITS)) 56 | bits = Integer(n).nbits() 57 | return K * (bits - 1) + LOG2_TABLE[((n << (INPUT_BITS - bits)) >> (INPUT_BITS - TABLE_BITS - 1)) - 2**TABLE_BITS] 58 | 59 | def Log2Fact(n): 60 | # Use formula (A*(2*x+1)*LogK2(x) - B*x + C) / D 61 | return (A*(2*n+1)*LogK2(n) - B*n + C) // D + (n < 3) 62 | 63 | RES = [int(F(log(factorial(i),2))) for i in range(EXACT_FPBITS * 10)] 64 | 65 | best_worst_ratio = 0 66 | 67 | for K in range(1, 10000): 68 | Setup(K) 69 | assert(LogK2(1) == 0) 70 | assert(LogK2(2) == K) 71 | assert(LogK2(4) == 2 * K) 72 | good = True 73 | worst_ratio = 1 74 | for i in range(1, EXACT_FPBITS * 10): 75 | exact = RES[i] 76 | approx = Log2Fact(i) 77 | if not (approx <= exact and ((approx == exact) or (approx >= EXACT_FPBITS and exact >= EXACT_FPBITS))): 78 | good = False 79 | break 80 | if worst_ratio * exact > approx: 81 | worst_ratio = approx / exact 82 | if good and worst_ratio > best_worst_ratio: 83 | best_worst_ratio = worst_ratio 84 | print("Formula: (%i*(2*x+1)*floor(%i*log2(x)) - %i*x + %i) / %i; log(max_ratio)=%f" % (A, K, B, C, D, RR(-log(worst_ratio)))) 85 | print("LOG2K_TABLE: %r" % LOG2_TABLE) 86 | -------------------------------------------------------------------------------- /doc/math.md: -------------------------------------------------------------------------------- 1 | # The mathematics of Minisketch sketches 2 | 3 | This is an unconventional mathematical overview of the PinSketch algorithm without references to coding theory[[1]](#myfootnote1). 4 | 5 | ## Set sketches 6 | 7 | A sketch, for the purpose of this description, can be seen as a "set checksum" with two peculiar properties: 8 | 9 | * Sketches have a predetermined capacity, and when the number of elements in the set is not higher than the capacity, minisketch will always recover the entire set from the sketch. A sketch of *b*-bit elements with capacity *c* can be stored in *bc* bits. 10 | * The sketches of two sets can be combined by adding them (XOR) to obtain a sketch of the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) between the two sets (*i.e.*, all elements that occur in one but not both input sets). 11 | 12 | This overview explains how sets can be converted into a sketch and how a set can be recovered from a sketch. 13 | 14 | ## From field elements to sketches 15 | 16 | **Data entries as field elements** 17 | 18 | Every integer in the range *[1...2b-1]* (the acceptable data elements for a Minisketch sketch with field size *b*) can be mapped to a nonzero field element of *GF(2b)*. In this [finite field](https://en.wikipedia.org/wiki/Finite_field), we can add and multiply elements together, with many of the expected properties for those operations. Addition (and subtraction!) of field elements corresponds to bitwise XOR of the integers they correspond to, though multiplication is more involved. 19 | 20 | **Sets as power series** 21 | 22 | We define a function *S* which maps field elements *m* to the following [formal power series](https://en.wikipedia.org/wiki/Formal_power_series) (similar to a polynomial, except there can be an infinite number of terms, and we don't care about concepts like convergence as we're never going to actually evaluate it for a specific value of *x*): 23 | 24 | * *S(m) = 1 + mx + m2x2 + m3x3 + ...*. 25 | 26 | We then extend this function to operate on sets of field elements, by adding together the images of every set element. If *M = {m1, m2, ... }*: 27 | 28 | * *S(M) = S({m1,m2,...}) = S(m1) + S(m2) + ... = (1 + 1 + ...) + (m1 + m2 + ...)x + (m12 + m22 + ...)x2 + (m13 + ...* 29 | 30 | Because in our field addition corresponds to XOR of integers, it holds for every *a* that *a + a = 0*. This carries over to the *S* function, meaning that *S(a) + S(a) = 0* for every *a*. This means that the coefficients of these power series have the second of the properties we 31 | desire from a sketch, namely that an efficient operation exists to 32 | combine two sketches such that the result is a sketch of the symmetric 33 | difference of the sets. It holds that 34 | *S({m1,m2}) + S({m2,m3}) = S(m1) + (S(m2) + S(m2)) + S(m3) = S(m1) + S(m3) = S({m1,m3})*. The question is whether we can also efficiently recover the elements from their power series' coefficients. 35 | 36 | **An infinity of coefficients is hard** 37 | 38 | To make reasoning about these power series easier, notice that the series for a single element is in fact a [geometric series](https://en.wikipedia.org/wiki/Geometric_series). If we were working over real numbers rather than a finite field and *|mx| < 1*, it would converge to *(1 - mx)-1*. Convergence has no meaning in formal power series, however it is still the case that: 39 | 40 | * *(1 - mx) S(m) = 1* 41 | 42 | You can verify this by seeing that every coefficient except the constant one gets cancelled out by the multiplication. This can be generalized to the series for multiple set elements. For two elements we have: 43 | 44 | * *(1 - m1x) (1 - m2x) S({m1,m2}) = (1 - m1x) (1 - m2x) (S(m1) + S(m2)) = (1 - m2x) + (1 - m1x)* 45 | 46 | And for three: 47 | 48 | * *(1 - m1x) (1 - m2x) (1 - m3x) S({m1,m2,m3}) = (1 - m1x) (1 - m2x) (1 - m3x) (S(m1) + S(m2) + S(m3)) = (1 - m2x)(1 - m3x) + (1 - m1x)(1 - m3x) + (1 - m1x)(1 - m2x)* 49 | 50 | In each case, we notice that multiplying *S(M)* with *(1 - mix)* for each element *mi ∈ M* results in a polynomial of degree *n-1*. 51 | 52 | **Solving for the set elements** 53 | 54 | The above insight lets us build a solver that extracts the set elements from the coefficients of a power series. If we can find a polynomial *L* that is the product of *n* different *(1 - mix)* factors for various values of *mi*, such that *P = S(M)L* is an *n-1* degree polynomial, then those values *mi* are the elements of *M*. 55 | 56 | The coefficients of *P* are nontrivial expressions of the set elements themselves. However, we can just focus on the coefficients of degree *n* and higher in *P*, as those are all 0. Let *si* be the coefficients of *S(M)*, and *li* the coefficients of L. In other words, *S(M) = s0 + s1x + s2x2 + s3x3 + ...* and *L = l0 + l1x + l2x2 + l3x3 + ... + lnxn*. Note that *l0 = 1*, as it is the product of all the *1* terms in the *(1 - mix)* factors. 57 | 58 | Here are the equations for the coefficients of *S(M)L* of degree *n+1* through *2n*: 59 | * *sn+1 + sn+0l1 + sn-1l2 + sn-2l3 + ... + s1ln = 0* 60 | * *sn+2 + sn+1l1 + sn+0l2 + sn-1l3 + ... + s2ln = 0* 61 | * *sn+3 + sn+2l1 + sn+1l2 + sn+0l3 + ... + s3ln = 0* 62 | * ... 63 | * *s2n + s2n-1l1 + s2n-2l2 + s2n-3l3 + ... + snln = 0* 64 | 65 | These are *n* linear equations with *n* unknowns (the *li* 66 | values, for *i=1..n*), which can be solved using [Gaussian elimination](https://en.wikipedia.org/wiki/Gaussian_elimination). After doing so, 67 | we have the coefficients of *L*, which can then be [factored](https://en.wikipedia.org/wiki/Factorization_of_polynomials_over_finite_fields) 68 | into first degree factors of the form *(1 - mix)*. The resulting *m* values are our set elements. 69 | 70 | **Putting it all together** 71 | 72 | Interestingly, only *2n* coefficients of *S(M)* were needed for solving 73 | the set of equations above. This means we have our answer: the 74 | coefficients *1* through *2n* of *S(M)*, or the list 75 | *[m1 + m2 + ..., m12 + m22 + ..., ..., m12n + m22n + ...]* 76 | functions as a sketch, satisfying the two properties we want: 77 | 78 | * Sketches can be combined to form the sketch of their symmetric difference, by simply pairwise adding the list elements together. 79 | * With *2n* list elements we can efficiently recover *n* elements from a sketch. 80 | 81 | **Capacity and difference** 82 | 83 | The approach above only works when the number of elements *n* in the sketch is known. Of course we want to support cases where only an upper bound on the number of elements in the sketch is known, the capacity *c*. Given that we can reconstruct a set of size *c* from a sketch with *2c* terms, we should be able to reconstruct a set of size *n* too as long as *n ≤ c*. This is simply a matter of trying to solve the above set of equations assuming values of *n* that count down from *c* until a solution is found for one. This is known as the [Peterson-Gorenstein-Zierler algorithm](https://en.wikipedia.org/wiki/BCH_code#Peterson%E2%80%93Gorenstein%E2%80%93Zierler_algorithm). 84 | 85 | ## Optimizations 86 | 87 | **Halving the sketch size** 88 | 89 | We can in fact only include the odd terms in the sketch, and reconstruct the even ones before solving the equation to find *L*. This means the size of a sketch becomes just *c* field elements, the same size as would be needed to send its contents naively. 90 | 91 | To see how this is possible, we need the [Frobenius endomorphism](https://en.wikipedia.org/wiki/Frobenius_endomorphism), which in short states that in fields where *x + x = 0* it holds that *(x + y)2 = x2 + y2* for every *x* and *y* (the dream of every high school math student!). This means that: 92 | 93 | * *s2 = m12 + m22 + ... = (m1 + m2 + ...)2 = s12*. 94 | * *s4 = m14 + m24 + ... = (m12 + m22 + ...)2 = s22*. 95 | * *s6 = m16 + m26 + ... = (m13 + m23 + ...)2 = s32*. 96 | * ... 97 | 98 | In other words, we only need to send *s1, s3, s5, ..., s2n-1* to recover all *2n* *si* values, and proceed with reconstruction. 99 | 100 | **Quadratic performance rather than cubic** 101 | 102 | Using Gaussian elimination to solve the set of equations above for the *li* values requires *O(n3)* field operations. However, due to the special structure in the equations (look at the repeated *si* values), it can be solved in *O(n2)* time using a number of techniques, including the [Berlekamp-Massey algorithm](https://en.wikipedia.org/wiki/Berlekamp%E2%80%93Massey_algorithm) (BM). 103 | 104 | **Roots instead of factorization** 105 | 106 | As explained above, the polynomial *L* can be factored into *(1 - mix)* factors, where the values *mi* are the set elements. However, since we know that a decodable sketch must result in a polynomial that is fully factorizable into degree-*1* factors, we can instead use a more efficient root-finding algorithm rather than a factorization algorithm. As the root of each *(1 - mix)* factor is *mi-1*, we conclude that the set elements are in fact the inverses of the roots of *L*. 107 | 108 | **Avoiding inversions** 109 | 110 | As inversions are a relatively expensive operation, it would be useful to avoid them. 111 | 112 | Say that we're trying to find the inverses of the roots of *L = 1 + l1x + l2x2 + ... + lnxn*, then we're really interested in the solutions *y* for *1 + l1y-1 + l2y-2 + ... + lny-n = 0*. By multiplying both sides in the equations with *yn*, we find *ln + ln-1y + ln-2y2 + ... + yn = 0*. 113 | 114 | In other words, we can find the inverses of the roots of *L* by instead factoring the polynomial with the coefficients of *L* in reverse order. 115 | 116 | * [1] For those familiar with coding theory: PinSketch communicates a set difference by encoding the set members as errors in a binary [BCH](https://en.wikipedia.org/wiki/BCH_code) codeword 2bits in size and sends the syndromes. 117 | The linearity of the syndromes provides all the properties needed for a sketch. Sketch decoding is simply finding the error locations. Decode is much faster than an ordinary BCH decoder for such a large codeword because the need to take a discrete log is avoided by storing the set in the roots directly instead of in an exponent (logically permuting the bits of the codeword). 118 | -------------------------------------------------------------------------------- /doc/minisketch-vs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core/minisketch/ea8f66b1eabb0388d221daaa4706120a5083da0c/doc/minisketch-vs.png -------------------------------------------------------------------------------- /doc/moduli.md: -------------------------------------------------------------------------------- 1 | These are the irreducible polynomials over *GF(2)* used to represent field elements: 2 | 3 | * *x2 + x + 1* 4 | * *x3 + x + 1* 5 | * *x4 + x + 1* 6 | * *x5 + x2 + 1* 7 | * *x6 + x + 1* 8 | * *x7 + x + 1* 9 | * *x8 + x4 + x3 + x + 1* 10 | * *x9 + x + 1* 11 | * *x10 + x3 + 1* 12 | * *x11 + x2 + 1* 13 | * *x12 + x3 + 1* 14 | * *x13 + x4 + x3 + x + 1* 15 | * *x14 + x5 + 1* 16 | * *x15 + x + 1* 17 | * *x16 + x5 + x3 + x + 1* 18 | * *x17 + x3 + 1* 19 | * *x18 + x3 + 1* 20 | * *x19 + x5 + x2 + x + 1* 21 | * *x20 + x3 + 1* 22 | * *x21 + x2 + 1* 23 | * *x22 + x + 1* 24 | * *x23 + x5 + 1* 25 | * *x24 + x4 + x3 + x + 1* 26 | * *x25 + x3 + 1* 27 | * *x26 + x4 + x3 + x + 1* 28 | * *x27 + x5 + x2 + x + 1* 29 | * *x28 + x + 1* 30 | * *x29 + x2 + 1* 31 | * *x30 + x + 1* 32 | * *x31 + x3 + 1* 33 | * *x32 + x7 + x3 + x2 + 1* 34 | * *x33 + x10 + 1* 35 | * *x34 + x7 + 1* 36 | * *x35 + x2 + 1* 37 | * *x36 + x9 + 1* 38 | * *x37 + x6 + x4 + x + 1* 39 | * *x38 + x6 + x5 + x + 1* 40 | * *x39 + x4 + 1* 41 | * *x40 + x5 + x4 + x3 + 1* 42 | * *x41 + x3 + 1* 43 | * *x42 + x7 + 1* 44 | * *x43 + x6 + x4 + x3 + 1* 45 | * *x44 + x5 + 1* 46 | * *x45 + x4 + x3 + x + 1* 47 | * *x46 + x + 1* 48 | * *x47 + x5 + 1* 49 | * *x48 + x5 + x3 + x2 + 1* 50 | * *x49 + x9 + 1* 51 | * *x50 + x4 + x3 + x2 + 1* 52 | * *x51 + x6 + x3 + x + 1* 53 | * *x52 + x3 + 1* 54 | * *x53 + x6 + x2 + x + 1* 55 | * *x54 + x9 + 1* 56 | * *x55 + x7 + 1* 57 | * *x56 + x7 + x4 + x2 + 1* 58 | * *x57 + x4 + 1* 59 | * *x58 + x19 + 1* 60 | * *x59 + x7 + x4 + x2 + 1* 61 | * *x60 + x + 1* 62 | * *x61 + x5 + x2 + x + 1* 63 | * *x62 + x29 + 1* 64 | * *x63 + x + 1* 65 | * *x64 + x4 + x3 + x + 1* 66 | -------------------------------------------------------------------------------- /doc/plot_bits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core/minisketch/ea8f66b1eabb0388d221daaa4706120a5083da0c/doc/plot_bits.png -------------------------------------------------------------------------------- /doc/plot_capacity.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core/minisketch/ea8f66b1eabb0388d221daaa4706120a5083da0c/doc/plot_capacity.png -------------------------------------------------------------------------------- /doc/plot_diff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core/minisketch/ea8f66b1eabb0388d221daaa4706120a5083da0c/doc/plot_diff.png -------------------------------------------------------------------------------- /doc/plot_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core/minisketch/ea8f66b1eabb0388d221daaa4706120a5083da0c/doc/plot_size.png -------------------------------------------------------------------------------- /doc/protocoltips.md: -------------------------------------------------------------------------------- 1 | # Tips for designing protocols using `libminisketch` 2 | 3 | Sending a sketch is less efficient than just sending your whole set with efficient entropy coding if the number of differences is larger than *log2( 2b choose set_size ) / b*. 4 | 5 | In most applications your set can be hashed to entries just large enough to make the probability of collision negligible. This can be a considerable speedup and bandwidth savings. Short hashes (<128 bits) should be salted with an unpredictable value to prevent malicious inputs from intentionally causing collisions. Salting also allows an entry missed due to a collision to be reconciled on a later run with a different salt. Pre-hashing may not be possible in some applications, such as where there is only one-way communication, where the confidentiality of entry origin matters, or where security depends on the total absence of collisions. 6 | 7 | Some element sizes are faster to decode than others; see the benchmarks in the readme. 8 | 9 | Almost all the computational burden of reconciliation is in minisketch_decode(). Denial-of-service attacks can be mitigated by arranging protocol flow so that a party requests a sketch and decodes it rather than a construction where the participants will decode unsolicited sketches. Decode times can be constrained by limiting sketch capacity or via the max_count argument to minisketch_decode(). 10 | 11 | In most cases you don't actually know the size of the set difference in advance, but often you know a lower bound on it (the difference in set sizes). 12 | 13 | * There are difference size estimation techniques such as min-wise hashing[[1]](#myfootnote1) or random projections[[2]](#myfootnote2), but complex estimators can end up using more bandwidth than they save. 14 | 15 | * It may be useful to always overestimate the sketch size needed to amortize communications overheads (*e.g.* packet headers, round trip delays). 16 | 17 | * If the total data sent would end up leaving you better off having just sent the whole set, per above, then you can send the set in response to a failure but leave out as many elements as the size of the previously sent sketch. The receiver can decode the partial set and use the data they already have to complete it, reducing bandwidth waste. 18 | 19 | * Additional elements can be sent for a sketch as few as one at a time with little decode cost until enough data is received to decode. This is most easily implemented by always computing the largest sketch size and sending it incrementally as needed. 20 | 21 | * Because sketches are linear you can adaptively subdivide to decode an overfull set. The sender uses a hash function to select approximately half their set members and sends a sketch of those members. The receiver can do the same and combine the result with the initially sent sketch to get two sketches with roughly half the number of members and attempt to decode them. Repeat recursively on failure. This adaptive subdivision procedure makes decode time essentially linear at the cost of communications inefficiency. Minisketches can also be used as the cells in an IBLT for similar reasons. 22 | 23 | Less efficient reconciliation techniques like IBLT or adaptive subdivision, or overheads like complex estimators effectively lower the threshold where sending the whole set efficiently would use less bandwidth. 24 | 25 | When the number of differences is more than 2b/2-1 an alternative sketch encoding is possible that is somewhat smaller, but requires a table of size 2b; contact the authors if you have an application where that might be useful. 26 | 27 | ## References 28 | 29 | * [1] Broder, A. *On the Resemblance and Containment of Documents* Proceedings of the Compression and Complexity of Sequences 1997 [[PDF]](https://www.cs.princeton.edu/courses/archive/spring13/cos598C/broder97resemblance.pdf) 30 | * [2] Feigenbaum, Joan and Kannan, Sampath and Strauss, Martin J. and Viswanathan, Mahesh. *An Approximate L1-Difference Algorithm for Massive Data Streams* SIAM J. Comput. 2003 [[PDF]](http://www.cs.yale.edu/homes/jf/FKSV1.pdf) 31 | -------------------------------------------------------------------------------- /sources.mk: -------------------------------------------------------------------------------- 1 | # - All variables are namespaced with MINISKETCH_ to avoid colliding with 2 | # downstream makefiles. 3 | # - All Variables ending in _HEADERS or _SOURCES confuse automake, so the 4 | # _INT postfix is applied. 5 | # - Convenience variables, for example a MINISKETCH_FIELDS_DIR should not be used 6 | # as they interfere with automatic dependency generation 7 | # - The %reldir% is the relative path from the Makefile.am. This allows 8 | # downstreams to use these variables without having to manually account for 9 | # the path change. 10 | 11 | MINISKETCH_INCLUDE_DIR_INT = %reldir%/include 12 | 13 | MINISKETCH_DIST_HEADERS_INT = 14 | MINISKETCH_DIST_HEADERS_INT += %reldir%/include/minisketch.h 15 | 16 | MINISKETCH_LIB_HEADERS_INT = 17 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/false_positives.h 18 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/fielddefines.h 19 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/int_utils.h 20 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/lintrans.h 21 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/sketch.h 22 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/sketch_impl.h 23 | MINISKETCH_LIB_HEADERS_INT += %reldir%/src/util.h 24 | 25 | MINISKETCH_LIB_SOURCES_INT = 26 | MINISKETCH_LIB_SOURCES_INT += %reldir%/src/minisketch.cpp 27 | 28 | MINISKETCH_FIELD_GENERIC_HEADERS_INT = 29 | MINISKETCH_FIELD_GENERIC_HEADERS_INT += %reldir%/src/fields/generic_common_impl.h 30 | 31 | MINISKETCH_FIELD_GENERIC_SOURCES_INT = 32 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_1byte.cpp 33 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_2bytes.cpp 34 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_3bytes.cpp 35 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_4bytes.cpp 36 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_5bytes.cpp 37 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_6bytes.cpp 38 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_7bytes.cpp 39 | MINISKETCH_FIELD_GENERIC_SOURCES_INT += %reldir%/src/fields/generic_8bytes.cpp 40 | 41 | MINISKETCH_FIELD_CLMUL_HEADERS_INT = 42 | MINISKETCH_FIELD_CLMUL_HEADERS_INT += %reldir%/src/fields/clmul_common_impl.h 43 | 44 | MINISKETCH_FIELD_CLMUL_SOURCES_INT = 45 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_1byte.cpp 46 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_2bytes.cpp 47 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_3bytes.cpp 48 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_4bytes.cpp 49 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_5bytes.cpp 50 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_6bytes.cpp 51 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_7bytes.cpp 52 | MINISKETCH_FIELD_CLMUL_SOURCES_INT += %reldir%/src/fields/clmul_8bytes.cpp 53 | 54 | MINISKETCH_BENCH_SOURCES_INT = 55 | MINISKETCH_BENCH_SOURCES_INT += %reldir%/src/bench.cpp 56 | 57 | MINISKETCH_TEST_SOURCES_INT = 58 | MINISKETCH_TEST_SOURCES_INT += %reldir%/src/test.cpp 59 | -------------------------------------------------------------------------------- /src/bench.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #include "../include/minisketch.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc, char** argv) { 17 | if (argc < 1 || argc > 4) { 18 | printf("Usage: %s [syndromes=150] [errors=syndromes] [iters=10]\n", argv[0]); 19 | return 1; 20 | } 21 | int syndromes = argc > 1 ? strtoul(argv[1], NULL, 10) : 150; 22 | int errors = argc > 2 ? strtoul(argv[2], NULL, 10) : syndromes; 23 | int iters = argc > 3 ? strtoul(argv[3], NULL, 10) : 10; 24 | if (syndromes < 0 || syndromes > 1000000) { 25 | printf("Number of syndromes (%i) out of range 0..1000000\n", syndromes); 26 | return 1; 27 | } 28 | if (errors < 0) { 29 | printf("Number of errors (%i) is negative(%i)\n", errors, syndromes); 30 | return 1; 31 | } 32 | if (iters < 0 || iters > 1000000000) { 33 | printf("Number of iterations (%i) out of range 0..1000000000\n", iters); 34 | return 1; 35 | } 36 | uint32_t max_impl = minisketch_implementation_max(); 37 | for (int bits = 2; bits <= 64; ++bits) { 38 | if (errors > pow(2.0, bits - 1)) continue; 39 | if (!minisketch_bits_supported(bits)) continue; 40 | printf("recover[ms]\t% 3i\t", bits); 41 | for (uint32_t impl = 0; impl <= max_impl; ++impl) { 42 | std::vector states; 43 | std::vector roots(2 * syndromes); 44 | std::random_device rng; 45 | std::uniform_int_distribution dist(1, (uint64_t(1) << bits) - 1); 46 | states.resize(iters); 47 | std::vector benches; 48 | benches.reserve(iters); 49 | for (int i = 0; i < iters; ++i) { 50 | states[i] = minisketch_create(bits, impl, syndromes); 51 | if (!states[i]) break; 52 | std::set done; 53 | for (int j = 0; j < errors; ++j) { 54 | uint64_t r; 55 | do { 56 | r = dist(rng); 57 | } while (done.count(r)); 58 | done.insert(r); 59 | minisketch_add_uint64(states[i], r); 60 | } 61 | } 62 | if (!states[0]) { 63 | printf(" -\t"); 64 | } else { 65 | for (auto& state : states) { 66 | auto start = std::chrono::steady_clock::now(); 67 | minisketch_decode(state, 2 * syndromes, roots.data()); 68 | auto stop = std::chrono::steady_clock::now(); 69 | std::chrono::duration dur(stop - start); 70 | benches.push_back(dur.count()); 71 | } 72 | std::sort(benches.begin(), benches.end()); 73 | printf("% 10.5f\t", benches[0] * 1000.0); 74 | } 75 | for (auto& state : states) { 76 | minisketch_destroy(state); 77 | } 78 | } 79 | printf("\n"); 80 | printf("create[ns]\t% 3i\t", bits); 81 | for (uint32_t impl = 0; impl <= max_impl; ++impl) { 82 | std::vector states; 83 | std::random_device rng; 84 | std::uniform_int_distribution dist; 85 | std::vector data; 86 | data.resize(errors * 10); 87 | states.resize(iters); 88 | std::vector benches; 89 | benches.reserve(iters); 90 | for (int i = 0; i < iters; ++i) { 91 | states[i] = minisketch_create(bits, impl, syndromes); 92 | } 93 | for (size_t i = 0; i < data.size(); ++i) { 94 | data[i] = dist(rng); 95 | } 96 | if (!states[0]) { 97 | printf(" -\t"); 98 | } else { 99 | for (auto& state : states) { 100 | auto start = std::chrono::steady_clock::now(); 101 | for (auto val : data) { 102 | minisketch_add_uint64(state, val); 103 | } 104 | auto stop = std::chrono::steady_clock::now(); 105 | std::chrono::duration dur(stop - start); 106 | benches.push_back(dur.count()); 107 | } 108 | std::sort(benches.begin(), benches.end()); 109 | printf("% 10.5f\t", benches[0] * 1000000000.0 / data.size() / syndromes); 110 | } 111 | for (auto& state : states) { 112 | minisketch_destroy(state); 113 | } 114 | } 115 | printf("\n"); 116 | } 117 | return 0; 118 | } 119 | -------------------------------------------------------------------------------- /src/false_positives.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2020 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_FALSE_POSITIVES_H_ 8 | #define _MINISKETCH_FALSE_POSITIVES_H_ 9 | 10 | #include "util.h" 11 | 12 | #include "int_utils.h" 13 | 14 | #include 15 | 16 | namespace { 17 | 18 | /** Compute floor(log2(x!)), exactly up to x=57; an underestimate up to x=2^32-1. */ 19 | uint64_t Log2Factorial(uint32_t x) { 20 | //! Values of floor(106*log2(1 + i/32)) for i=0..31 21 | static constexpr uint8_t T[32] = { 22 | 0, 4, 9, 13, 18, 22, 26, 30, 34, 37, 41, 45, 48, 52, 55, 58, 62, 65, 68, 23 | 71, 74, 77, 80, 82, 85, 88, 90, 93, 96, 98, 101, 103 24 | }; 25 | int bits = CountBits(x, 32); 26 | // Compute an (under)estimate of floor(106*log2(x)). 27 | // This works by relying on floor(log2(x)) = countbits(x)-1, and adding 28 | // precision using the top 6 bits of x (the highest one of which is always 29 | // one). 30 | unsigned l2_106 = 106 * (bits - 1) + T[((x << (32 - bits)) >> 26) & 31]; 31 | // Based on Stirling approximation for log2(x!): 32 | // log2(x!) = log(x!) / log(2) 33 | // = ((x + 1/2) * log(x) - x + log(2*pi)/2 + ...) / log(2) 34 | // = (x + 1/2) * log2(x) - x/log(2) + log2(2*pi)/2 + ... 35 | // = 1/2*(2*x+1)*log2(x) - (1/log(2))*x + log2(2*pi)/2 + ... 36 | // = 1/212*(2*x+1)*(106*log2(x)) + (-1/log(2))*x + log2(2*pi)/2 + ... 37 | // where 418079/88632748 is exactly 1/212 38 | // -127870026/88632748 is slightly less than -1/log(2) 39 | // 117504694/88632748 is less than log2(2*pi)/2 40 | // A correction term is only needed for x < 3. 41 | // 42 | // See doc/log2_factorial.sage for how these constants were obtained. 43 | return (418079 * (2 * uint64_t{x} + 1) * l2_106 - 127870026 * uint64_t{x} + 117504694 + 88632748 * (x < 3)) / 88632748; 44 | } 45 | 46 | /** Compute floor(log2(2^(bits * capacity) / sum((2^bits - 1) choose k, k=0..capacity))), for bits>1 47 | * 48 | * See doc/gen_basefpbits.sage for how the tables were obtained. */ 49 | uint64_t BaseFPBits(uint32_t bits, uint32_t capacity) { 50 | // Correction table for low bits/capacities 51 | static constexpr uint8_t ADD5[] = {1, 1, 1, 1, 2, 2, 2, 3, 4, 4, 5, 5, 6, 7, 8, 8, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12, 12}; 52 | static constexpr uint8_t ADD6[] = {1, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 4, 5, 6, 6, 6, 7, 8, 8, 10, 10, 11, 12, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 20, 20, 21, 21, 22, 22, 23, 23, 23, 24, 24, 24, 24}; 53 | static constexpr uint8_t ADD7[] = {1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 7, 7, 8, 7, 8, 9, 9, 9, 10, 11, 11, 12, 12, 13, 13, 15, 15, 15, 16, 17, 17, 18, 19, 20, 20}; 54 | static constexpr uint8_t ADD8[] = {1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 3, 4, 4, 5, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, 9}; 55 | static constexpr uint8_t ADD9[] = {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 3, 3, 3, 3, 4, 3, 3, 4, 4, 4, 4}; 56 | 57 | if (capacity == 0) return 0; 58 | uint64_t ret = 0; 59 | if (bits < 32 && capacity >= (1U << bits)) { 60 | ret = uint64_t{bits} * (capacity - (1U << bits) + 1); 61 | capacity = (1U << bits) - 1; 62 | } 63 | ret += Log2Factorial(capacity); 64 | switch (bits) { 65 | case 2: return ret + (capacity <= 2 ? 0 : 1); 66 | case 3: return ret + (capacity <= 2 ? 0 : (0x2a5 >> 2 * (capacity - 3)) & 3); 67 | case 4: return ret + (capacity <= 3 ? 0 : (0xb6d91a449 >> 3 * (capacity - 4)) & 7); 68 | case 5: return ret + (capacity <= 4 ? 0 : ADD5[capacity - 5]); 69 | case 6: return ret + (capacity <= 4 ? 0 : capacity > 54 ? 25 : ADD6[capacity - 5]); 70 | case 7: return ret + (capacity <= 4 ? 0 : capacity > 57 ? 21 : ADD7[capacity - 5]); 71 | case 8: return ret + (capacity <= 9 ? 0 : capacity > 56 ? 10 : ADD8[capacity - 10]); 72 | case 9: return ret + (capacity <= 11 ? 0 : capacity > 54 ? 5 : ADD9[capacity - 12]); 73 | case 10: return ret + (capacity <= 21 ? 0 : capacity > 50 ? 2 : (0x1a6665545555041 >> 2 * (capacity - 22)) & 3); 74 | case 11: return ret + (capacity <= 21 ? 0 : capacity > 45 ? 1 : (0x5b3dc1 >> (capacity - 22)) & 1); 75 | case 12: return ret + (capacity <= 21 ? 0 : capacity > 57 ? 0 : (0xe65522041 >> (capacity - 22)) & 1); 76 | case 13: return ret + (capacity <= 27 ? 0 : capacity > 55 ? 0 : (0x8904081 >> (capacity - 28)) & 1); 77 | case 14: return ret + (capacity <= 47 ? 0 : capacity > 48 ? 0 : 1); 78 | default: return ret; 79 | } 80 | } 81 | 82 | size_t ComputeCapacity(uint32_t bits, size_t max_elements, uint32_t fpbits) { 83 | if (bits == 0) return 0; 84 | if (max_elements > 0xffffffff) return max_elements; 85 | uint64_t base_fpbits = BaseFPBits(bits, static_cast(max_elements)); 86 | // The fpbits provided by the base max_elements==capacity case are sufficient. 87 | if (base_fpbits >= fpbits) return max_elements; 88 | // Otherwise, increment capacity by ceil(fpbits / bits) beyond that. 89 | return max_elements + (fpbits - base_fpbits + bits - 1) / bits; 90 | } 91 | 92 | size_t ComputeMaxElements(uint32_t bits, size_t capacity, uint32_t fpbits) { 93 | if (bits == 0) return 0; 94 | if (capacity > 0xffffffff) return capacity; 95 | // Start with max_elements=capacity, and decrease max_elements until the corresponding capacity is capacity. 96 | size_t max_elements = capacity; 97 | while (true) { 98 | size_t capacity_for_max_elements = ComputeCapacity(bits, max_elements, fpbits); 99 | CHECK_SAFE(capacity_for_max_elements >= capacity); 100 | if (capacity_for_max_elements <= capacity) return max_elements; 101 | size_t adjust = capacity_for_max_elements - capacity; 102 | // Decrementing max_elements by N will at most decrement the corresponding capacity by N. 103 | // As the observed capacity is adjust too high, we can safely decrease max_elements by adjust. 104 | // If that brings us into negative max_elements territory, no solution exists and we return 0. 105 | if (max_elements < adjust) return 0; 106 | max_elements -= adjust; 107 | } 108 | } 109 | 110 | } // namespace 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/fields/clmul_1byte.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_1) 11 | 12 | #include "clmul_common_impl.h" 13 | 14 | #include "../int_utils.h" 15 | #include "../lintrans.h" 16 | #include "../sketch_impl.h" 17 | 18 | #endif 19 | 20 | #include "../sketch.h" 21 | 22 | namespace { 23 | #ifdef ENABLE_FIELD_INT_2 24 | // 2 bit field 25 | typedef RecLinTrans StatTableTRI2; 26 | constexpr StatTableTRI2 SQR_TABLE_TRI2({0x1, 0x3}); 27 | constexpr StatTableTRI2 QRT_TABLE_TRI2({0x2, 0}); 28 | typedef FieldTri FieldTri2; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_3 32 | // 3 bit field 33 | typedef RecLinTrans StatTableTRI3; 34 | constexpr StatTableTRI3 SQR_TABLE_TRI3({0x1, 0x4, 0x6}); 35 | constexpr StatTableTRI3 QRT_TABLE_TRI3({0, 0x4, 0x6}); 36 | typedef FieldTri FieldTri3; 37 | #endif 38 | 39 | #ifdef ENABLE_FIELD_INT_4 40 | // 4 bit field 41 | typedef RecLinTrans StatTableTRI4; 42 | constexpr StatTableTRI4 SQR_TABLE_TRI4({0x1, 0x4, 0x3, 0xc}); 43 | constexpr StatTableTRI4 QRT_TABLE_TRI4({0x6, 0xa, 0x8, 0}); 44 | typedef FieldTri FieldTri4; 45 | #endif 46 | 47 | #ifdef ENABLE_FIELD_INT_5 48 | // 5 bit field 49 | typedef RecLinTrans StatTable5; 50 | constexpr StatTable5 SQR_TABLE_5({0x1, 0x4, 0x10, 0xa, 0xd}); 51 | constexpr StatTable5 SQR2_TABLE_5({0x1, 0x10, 0xd, 0xe, 0x1b}); 52 | constexpr StatTable5 QRT_TABLE_5({0x14, 0x8, 0xa, 0, 0xe}); 53 | typedef Field Field5; 54 | typedef FieldTri, &SQR_TABLE_5, &SQR2_TABLE_5, &QRT_TABLE_5, &QRT_TABLE_5, &QRT_TABLE_5, &QRT_TABLE_5, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri5; 55 | #endif 56 | 57 | #ifdef ENABLE_FIELD_INT_6 58 | // 6 bit field 59 | typedef RecLinTrans StatTableTRI6; 60 | constexpr StatTableTRI6 SQR_TABLE_TRI6({0x1, 0x4, 0x10, 0x3, 0xc, 0x30}); 61 | constexpr StatTableTRI6 SQR2_TABLE_TRI6({0x1, 0x10, 0xc, 0x5, 0x13, 0x3c}); 62 | constexpr StatTableTRI6 QRT_TABLE_TRI6({0x3a, 0x26, 0x24, 0x14, 0x20, 0}); 63 | typedef FieldTri FieldTri6; 64 | #endif 65 | 66 | #ifdef ENABLE_FIELD_INT_7 67 | // 7 bit field 68 | typedef RecLinTrans StatTableTRI7; 69 | constexpr StatTableTRI7 SQR_TABLE_TRI7({0x1, 0x4, 0x10, 0x40, 0x6, 0x18, 0x60}); 70 | constexpr StatTableTRI7 SQR2_TABLE_TRI7({0x1, 0x10, 0x6, 0x60, 0x14, 0x46, 0x78}); 71 | constexpr StatTableTRI7 QRT_TABLE_TRI7({0, 0x14, 0x16, 0x72, 0x12, 0x40, 0x7a}); 72 | typedef FieldTri FieldTri7; 73 | #endif 74 | 75 | #ifdef ENABLE_FIELD_INT_8 76 | // 8 bit field 77 | typedef RecLinTrans StatTable8; 78 | constexpr StatTable8 SQR_TABLE_8({0x1, 0x4, 0x10, 0x40, 0x1b, 0x6c, 0xab, 0x9a}); 79 | constexpr StatTable8 SQR2_TABLE_8({0x1, 0x10, 0x1b, 0xab, 0x5e, 0x97, 0xb3, 0xc5}); 80 | constexpr StatTable8 QRT_TABLE_8({0xbc, 0x2a, 0x28, 0x86, 0x2c, 0xde, 0x8e, 0}); 81 | typedef Field Field8; 82 | #endif 83 | } 84 | 85 | Sketch* ConstructClMul1Byte(int bits, int implementation) { 86 | switch (bits) { 87 | #ifdef ENABLE_FIELD_INT_5 88 | case 5: return new SketchImpl(implementation, 5); 89 | #endif 90 | #ifdef ENABLE_FIELD_INT_8 91 | case 8: return new SketchImpl(implementation, 8); 92 | #endif 93 | } 94 | return nullptr; 95 | } 96 | 97 | Sketch* ConstructClMulTri1Byte(int bits, int implementation) { 98 | switch (bits) { 99 | #ifdef ENABLE_FIELD_INT_2 100 | case 2: return new SketchImpl(implementation, 2); 101 | #endif 102 | #ifdef ENABLE_FIELD_INT_3 103 | case 3: return new SketchImpl(implementation, 3); 104 | #endif 105 | #ifdef ENABLE_FIELD_INT_4 106 | case 4: return new SketchImpl(implementation, 4); 107 | #endif 108 | #ifdef ENABLE_FIELD_INT_5 109 | case 5: return new SketchImpl(implementation, 5); 110 | #endif 111 | #ifdef ENABLE_FIELD_INT_6 112 | case 6: return new SketchImpl(implementation, 6); 113 | #endif 114 | #ifdef ENABLE_FIELD_INT_7 115 | case 7: return new SketchImpl(implementation, 7); 116 | #endif 117 | } 118 | return nullptr; 119 | } 120 | -------------------------------------------------------------------------------- /src/fields/clmul_2bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_2) 11 | 12 | #include "clmul_common_impl.h" 13 | 14 | #include "../int_utils.h" 15 | #include "../lintrans.h" 16 | #include "../sketch_impl.h" 17 | 18 | #endif 19 | 20 | #include "../sketch.h" 21 | 22 | namespace { 23 | #ifdef ENABLE_FIELD_INT_9 24 | // 9 bit field 25 | typedef RecLinTrans StatTableTRI9; 26 | constexpr StatTableTRI9 SQR_TABLE_TRI9({0x1, 0x4, 0x10, 0x40, 0x100, 0x6, 0x18, 0x60, 0x180}); 27 | constexpr StatTableTRI9 SQR2_TABLE_TRI9({0x1, 0x10, 0x100, 0x18, 0x180, 0x14, 0x140, 0x1e, 0x1e0}); 28 | constexpr StatTableTRI9 SQR4_TABLE_TRI9({0x1, 0x180, 0x1e0, 0x198, 0x1fe, 0x80, 0xa0, 0x88, 0xaa}); 29 | constexpr StatTableTRI9 QRT_TABLE_TRI9({0, 0x4e, 0x4c, 0x1aa, 0x48, 0x22, 0x1a2, 0x100, 0x58}); 30 | typedef FieldTri FieldTri9; 31 | #endif 32 | 33 | #ifdef ENABLE_FIELD_INT_10 34 | // 10 bit field 35 | typedef RecLinTrans StatTable10; 36 | constexpr StatTable10 SQR_TABLE_10({0x1, 0x4, 0x10, 0x40, 0x100, 0x9, 0x24, 0x90, 0x240, 0x112}); 37 | constexpr StatTable10 SQR2_TABLE_10({0x1, 0x10, 0x100, 0x24, 0x240, 0x41, 0x19, 0x190, 0x136, 0x344}); 38 | constexpr StatTable10 SQR4_TABLE_10({0x1, 0x240, 0x136, 0x141, 0x35d, 0x18, 0x265, 0x2e6, 0x227, 0x36b}); 39 | constexpr StatTable10 QRT_TABLE_10({0xec, 0x86, 0x84, 0x30e, 0x80, 0x3c2, 0x306, 0, 0x90, 0x296}); 40 | typedef Field Field10; 41 | typedef FieldTri, &SQR_TABLE_10, &SQR2_TABLE_10, &SQR4_TABLE_10, &QRT_TABLE_10, &QRT_TABLE_10, &QRT_TABLE_10, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri10; 42 | #endif 43 | 44 | #ifdef ENABLE_FIELD_INT_11 45 | // 11 bit field 46 | typedef RecLinTrans StatTable11; 47 | constexpr StatTable11 SQR_TABLE_11({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0xa, 0x28, 0xa0, 0x280, 0x205}); 48 | constexpr StatTable11 SQR2_TABLE_11({0x1, 0x10, 0x100, 0xa, 0xa0, 0x205, 0x44, 0x440, 0x428, 0x2a8, 0x291}); 49 | constexpr StatTable11 SQR4_TABLE_11({0x1, 0xa0, 0x428, 0x1a, 0x645, 0x3a9, 0x144, 0x2d5, 0x9e, 0x4e7, 0x649}); 50 | constexpr StatTable11 QRT_TABLE_11({0x734, 0x48, 0x4a, 0x1de, 0x4e, 0x35e, 0x1d6, 0x200, 0x5e, 0, 0x37e}); 51 | typedef Field Field11; 52 | typedef FieldTri, &SQR_TABLE_11, &SQR2_TABLE_11, &SQR4_TABLE_11, &QRT_TABLE_11, &QRT_TABLE_11, &QRT_TABLE_11, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri11; 53 | #endif 54 | 55 | #ifdef ENABLE_FIELD_INT_12 56 | // 12 bit field 57 | typedef RecLinTrans StatTable12; 58 | constexpr StatTable12 SQR_TABLE_12({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x9, 0x24, 0x90, 0x240, 0x900, 0x412}); 59 | constexpr StatTable12 SQR2_TABLE_12({0x1, 0x10, 0x100, 0x9, 0x90, 0x900, 0x41, 0x410, 0x124, 0x249, 0x482, 0x804}); 60 | constexpr StatTable12 SQR4_TABLE_12({0x1, 0x90, 0x124, 0x8, 0x480, 0x920, 0x40, 0x412, 0x924, 0x200, 0x82, 0x904}); 61 | constexpr StatTable12 QRT_TABLE_12({0x48, 0xc10, 0xc12, 0x208, 0xc16, 0xd82, 0x200, 0x110, 0xc06, 0, 0xda2, 0x5a4}); 62 | typedef Field Field12; 63 | typedef FieldTri, &SQR_TABLE_12, &SQR2_TABLE_12, &SQR4_TABLE_12, &QRT_TABLE_12, &QRT_TABLE_12, &QRT_TABLE_12, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri12; 64 | #endif 65 | 66 | #ifdef ENABLE_FIELD_INT_13 67 | // 13 bit field 68 | typedef RecLinTrans StatTable13; 69 | constexpr StatTable13 SQR_TABLE_13({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x36, 0xd8, 0x360, 0xd80, 0x161b, 0x185a}); 70 | constexpr StatTable13 SQR2_TABLE_13({0x1, 0x10, 0x100, 0x1000, 0xd8, 0xd80, 0x185a, 0x514, 0x1176, 0x17b8, 0x1b75, 0x17ff, 0x1f05}); 71 | constexpr StatTable13 SQR4_TABLE_13({0x1, 0xd8, 0x1176, 0x1f05, 0xd96, 0x18e8, 0x68, 0xbdb, 0x1a61, 0x1af2, 0x1a37, 0x3b9, 0x1440}); 72 | constexpr StatTable13 QRT_TABLE_13({0xcfc, 0x1500, 0x1502, 0x382, 0x1506, 0x149c, 0x38a, 0x118, 0x1516, 0, 0x14bc, 0x100e, 0x3ca}); 73 | typedef Field Field13; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_14 77 | // 14 bit field 78 | typedef RecLinTrans StatTable14; 79 | constexpr StatTable14 SQR_TABLE_14({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x21, 0x84, 0x210, 0x840, 0x2100, 0x442, 0x1108}); 80 | constexpr StatTable14 SQR2_TABLE_14({0x1, 0x10, 0x100, 0x1000, 0x84, 0x840, 0x442, 0x401, 0x31, 0x310, 0x3100, 0x118c, 0x1844, 0x486}); 81 | constexpr StatTable14 SQR4_TABLE_14({0x1, 0x84, 0x31, 0x1844, 0x501, 0x15ce, 0x3552, 0x3101, 0x8c5, 0x3a5, 0x1cf3, 0xd74, 0xc8a, 0x3411}); 82 | constexpr StatTable14 QRT_TABLE_14({0x13f2, 0x206, 0x204, 0x3e06, 0x200, 0x1266, 0x3e0e, 0x114, 0x210, 0, 0x1246, 0x2848, 0x3e4e, 0x2258}); 83 | typedef Field Field14; 84 | typedef FieldTri, &SQR_TABLE_14, &SQR2_TABLE_14, &SQR4_TABLE_14, &QRT_TABLE_14, &QRT_TABLE_14, &QRT_TABLE_14, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri14; 85 | #endif 86 | 87 | #ifdef ENABLE_FIELD_INT_15 88 | // 15 bit field 89 | typedef RecLinTrans StatTableTRI15; 90 | constexpr StatTableTRI15 SQR_TABLE_TRI15({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x6, 0x18, 0x60, 0x180, 0x600, 0x1800, 0x6000}); 91 | constexpr StatTableTRI15 SQR2_TABLE_TRI15({0x1, 0x10, 0x100, 0x1000, 0x6, 0x60, 0x600, 0x6000, 0x14, 0x140, 0x1400, 0x4006, 0x78, 0x780, 0x7800}); 92 | constexpr StatTableTRI15 SQR4_TABLE_TRI15({0x1, 0x6, 0x14, 0x78, 0x110, 0x660, 0x1540, 0x7f80, 0x106, 0x614, 0x1478, 0x7910, 0x1666, 0x7554, 0x3ffe}); 93 | constexpr StatTableTRI15 QRT_TABLE_TRI15({0, 0x114, 0x116, 0x428, 0x112, 0x137a, 0x420, 0x6d62, 0x102, 0x73a, 0x135a, 0x6460, 0x460, 0x4000, 0x6de2}); 94 | typedef FieldTri FieldTri15; 95 | #endif 96 | 97 | #ifdef ENABLE_FIELD_INT_16 98 | // 16 bit field 99 | typedef RecLinTrans StatTable16; 100 | constexpr StatTable16 SQR_TABLE_16({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x2b, 0xac, 0x2b0, 0xac0, 0x2b00, 0xac00, 0xb056, 0xc10e}); 101 | constexpr StatTable16 SQR2_TABLE_16({0x1, 0x10, 0x100, 0x1000, 0x2b, 0x2b0, 0x2b00, 0xb056, 0x445, 0x4450, 0x45ac, 0x5a6c, 0xa647, 0x657e, 0x571a, 0x7127}); 102 | constexpr StatTable16 SQR4_TABLE_16({0x1, 0x2b, 0x445, 0xa647, 0x12a1, 0xf69d, 0x7f07, 0x9825, 0x6fad, 0x399d, 0xb515, 0xd7d1, 0x3fb4, 0x4b06, 0xe4df, 0x93c7}); 103 | constexpr StatTable16 QRT_TABLE_16({0x732, 0x72b8, 0x72ba, 0x7e96, 0x72be, 0x78b2, 0x7e9e, 0x8cba, 0x72ae, 0xfa24, 0x7892, 0x5892, 0x7ede, 0xbec6, 0x8c3a, 0}); 104 | typedef Field Field16; 105 | #endif 106 | } 107 | 108 | Sketch* ConstructClMul2Bytes(int bits, int implementation) { 109 | switch (bits) { 110 | #ifdef ENABLE_FIELD_INT_10 111 | case 10: return new SketchImpl(implementation, 10); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_11 114 | case 11: return new SketchImpl(implementation, 11); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_12 117 | case 12: return new SketchImpl(implementation, 12); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_13 120 | case 13: return new SketchImpl(implementation, 13); 121 | #endif 122 | #ifdef ENABLE_FIELD_INT_14 123 | case 14: return new SketchImpl(implementation, 14); 124 | #endif 125 | #ifdef ENABLE_FIELD_INT_16 126 | case 16: return new SketchImpl(implementation, 16); 127 | #endif 128 | } 129 | return nullptr; 130 | } 131 | 132 | Sketch* ConstructClMulTri2Bytes(int bits, int implementation) { 133 | switch (bits) { 134 | #ifdef ENABLE_FIELD_INT_9 135 | case 9: return new SketchImpl(implementation, 9); 136 | #endif 137 | #ifdef ENABLE_FIELD_INT_10 138 | case 10: return new SketchImpl(implementation, 10); 139 | #endif 140 | #ifdef ENABLE_FIELD_INT_11 141 | case 11: return new SketchImpl(implementation, 11); 142 | #endif 143 | #ifdef ENABLE_FIELD_INT_12 144 | case 12: return new SketchImpl(implementation, 12); 145 | #endif 146 | #ifdef ENABLE_FIELD_INT_14 147 | case 14: return new SketchImpl(implementation, 14); 148 | #endif 149 | #ifdef ENABLE_FIELD_INT_15 150 | case 15: return new SketchImpl(implementation, 15); 151 | #endif 152 | } 153 | return nullptr; 154 | } 155 | -------------------------------------------------------------------------------- /src/fields/clmul_3bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_3) 11 | 12 | #include "clmul_common_impl.h" 13 | 14 | #include "../int_utils.h" 15 | #include "../lintrans.h" 16 | #include "../sketch_impl.h" 17 | 18 | #endif 19 | 20 | #include "../sketch.h" 21 | 22 | namespace { 23 | #ifdef ENABLE_FIELD_INT_17 24 | // 17 bit field 25 | typedef RecLinTrans StatTable17; 26 | constexpr StatTable17 SQR_TABLE_17({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x12, 0x48, 0x120, 0x480, 0x1200, 0x4800, 0x12000, 0x8012}); 27 | constexpr StatTable17 SQR2_TABLE_17({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x48, 0x480, 0x4800, 0x8012, 0x104, 0x1040, 0x10400, 0x4048, 0x492, 0x4920, 0x9212, 0x12104}); 28 | constexpr StatTable17 SQR4_TABLE_17({0x1, 0x10000, 0x8012, 0x4048, 0x12104, 0x1480, 0x5840, 0x14d20, 0x19202, 0x8112, 0x44c8, 0x13144, 0x5da0, 0x15850, 0x1cd7a, 0x1d34e, 0x1a484}); 29 | constexpr StatTable17 SQR8_TABLE_17({0x1, 0x1a484, 0x1f24a, 0x1d572, 0x1eec4, 0x15448, 0xf9de, 0x9af0, 0x1ab78, 0x6048, 0xdc9a, 0x1eb24, 0x2ef4, 0x7c5e, 0x170b2, 0x16c1a, 0xa660}); 30 | constexpr StatTable17 QRT_TABLE_17({0, 0x4c3e, 0x4c3c, 0x1a248, 0x4c38, 0x428, 0x1a240, 0x1b608, 0x4c28, 0x206, 0x408, 0x4000, 0x1a200, 0x18006, 0x1b688, 0x14d2e, 0x4d28}); 31 | typedef Field Field17; 32 | typedef FieldTri, &SQR_TABLE_17, &SQR2_TABLE_17, &SQR4_TABLE_17, &SQR8_TABLE_17, &QRT_TABLE_17, &QRT_TABLE_17, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri17; 33 | #endif 34 | 35 | #ifdef ENABLE_FIELD_INT_18 36 | // 18 bit field 37 | typedef RecLinTrans StatTable18; 38 | constexpr StatTable18 SQR_TABLE_18({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x9, 0x24, 0x90, 0x240, 0x900, 0x2400, 0x9000, 0x24000, 0x10012}); 39 | constexpr StatTable18 SQR2_TABLE_18({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x24, 0x240, 0x2400, 0x24000, 0x41, 0x410, 0x4100, 0x1009, 0x10090, 0x924, 0x9240, 0x12412, 0x24104}); 40 | constexpr StatTable18 SQR4_TABLE_18({0x1, 0x10000, 0x24000, 0x1009, 0x12412, 0x124, 0x201, 0x10480, 0x24820, 0x241, 0x10410, 0x24924, 0x8, 0x12, 0x20024, 0x8048, 0x12082, 0x920}); 41 | constexpr StatTable18 SQR8_TABLE_18({0x1, 0x12082, 0x20904, 0x1000, 0x92, 0x904, 0x240, 0x12012, 0x4104, 0x41, 0x10080, 0x4924, 0x1009, 0x2412, 0x24804, 0x9240, 0x12410, 0x20}); 42 | constexpr StatTable18 QRT_TABLE_18({0x9208, 0x422, 0x420, 0x8048, 0x424, 0x68b0, 0x8040, 0x30086, 0x434, 0x1040, 0x6890, 0x30ca2, 0x8000, 0x32896, 0x30006, 0, 0x534, 0x20532}); 43 | typedef Field Field18; 44 | typedef FieldTri, &SQR_TABLE_18, &SQR2_TABLE_18, &SQR4_TABLE_18, &SQR8_TABLE_18, &QRT_TABLE_18, &QRT_TABLE_18, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri18; 45 | #endif 46 | 47 | #ifdef ENABLE_FIELD_INT_19 48 | // 19 bit field 49 | typedef RecLinTrans StatTable19; 50 | constexpr StatTable19 SQR_TABLE_19({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x4e, 0x138, 0x4e0, 0x1380, 0x4e00, 0x13800, 0x4e000, 0x3804e, 0x6011f}); 51 | constexpr StatTable19 SQR2_TABLE_19({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x4e, 0x4e0, 0x4e00, 0x4e000, 0x6011f, 0x1054, 0x10540, 0x544e, 0x544e0, 0x44f76, 0x4f658, 0x7649f, 0x6481a, 0x48004}); 52 | constexpr StatTable19 SQR4_TABLE_19({0x1, 0x10000, 0x4e000, 0x544e, 0x7649f, 0x15f0, 0x5afa, 0x35b7d, 0x17dca, 0x7390f, 0x151ae, 0x3902b, 0x41e9c, 0x7f117, 0x23ec7, 0x62c2f, 0x5e852, 0x69238, 0x775c}); 53 | constexpr StatTable19 SQR8_TABLE_19({0x1, 0x5e852, 0x394a3, 0x29f41, 0x618e5, 0x4210, 0x7add9, 0x31105, 0x5d098, 0x7bb13, 0x44f00, 0x966, 0x11ae6, 0x70901, 0x664bf, 0x67449, 0x3d2bf, 0x4cbf9, 0x54e0c}); 54 | constexpr StatTable19 QRT_TABLE_19({0x5d6b0, 0x2f476, 0x2f474, 0x1d6a2, 0x2f470, 0x42a, 0x1d6aa, 0x1060, 0x2f460, 0x19e92, 0x40a, 0x1da98, 0x1d6ea, 0x28c78, 0x10e0, 0xf56a, 0x2f560, 0, 0x19c92}); 55 | typedef Field Field19; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_20 59 | // 20 bit field 60 | typedef RecLinTrans StatTable20; 61 | constexpr StatTable20 SQR_TABLE_20({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x9, 0x24, 0x90, 0x240, 0x900, 0x2400, 0x9000, 0x24000, 0x90000, 0x40012}); 62 | constexpr StatTable20 SQR2_TABLE_20({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x9, 0x90, 0x900, 0x9000, 0x90000, 0x41, 0x410, 0x4100, 0x41000, 0x10024, 0x249, 0x2490, 0x24900, 0x49012, 0x90104}); 63 | constexpr StatTable20 SQR4_TABLE_20({0x1, 0x10000, 0x9000, 0x4100, 0x2490, 0x1001, 0x10900, 0x9410, 0x4349, 0x92594, 0x91, 0x10041, 0x19024, 0x4d112, 0x2599, 0x91091, 0x51941, 0x3dd34, 0x5d34b, 0x9b494}); 64 | constexpr StatTable20 SQR8_TABLE_20({0x1, 0x51941, 0x880b5, 0x66d0, 0x46103, 0x19025, 0x45a49, 0x8a4b4, 0x80b45, 0x81f9f, 0xb081, 0x41040, 0xd19f5, 0xc11be, 0x4634b, 0xd8d70, 0x11027, 0xf8651, 0x141fa, 0xdc63}); 65 | constexpr StatTable20 QRT_TABLE_20({0xc5dea, 0xc0110, 0xc0112, 0xe11de, 0xc0116, 0x24814, 0xe11d6, 0x20080, 0xc0106, 0xfe872, 0x24834, 0xe4106, 0xe1196, 0x1d9a4, 0x20000, 0x31190, 0xc0006, 0, 0xfea72, 0x7ea74}); 66 | typedef Field Field20; 67 | typedef FieldTri, &SQR_TABLE_20, &SQR2_TABLE_20, &SQR4_TABLE_20, &SQR8_TABLE_20, &QRT_TABLE_20, &QRT_TABLE_20, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri20; 68 | #endif 69 | 70 | #ifdef ENABLE_FIELD_INT_21 71 | // 21 bit field 72 | typedef RecLinTrans StatTable21; 73 | constexpr StatTable21 SQR_TABLE_21({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0xa, 0x28, 0xa0, 0x280, 0xa00, 0x2800, 0xa000, 0x28000, 0xa0000, 0x80005}); 74 | constexpr StatTable21 SQR2_TABLE_21({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x100000, 0x28, 0x280, 0x2800, 0x28000, 0x80005, 0x44, 0x440, 0x4400, 0x44000, 0x4000a, 0xaa, 0xaa0, 0xaa00, 0xaa000, 0xa0011}); 75 | constexpr StatTable21 SQR4_TABLE_21({0x1, 0x10000, 0x2800, 0x440, 0xaa, 0xa0011, 0x101000, 0x28280, 0x4444, 0x40aaa, 0xaa101, 0x128, 0x8002d, 0xc4005, 0x4ea00, 0xba10, 0x101290, 0x1282c4, 0x6c44e, 0xeeeaa, 0xbaaa1}); 76 | constexpr StatTable21 SQR8_TABLE_21({0x1, 0x101290, 0xc412d, 0x1ab101, 0x986d1, 0x1c6cc5, 0x3aa8c, 0x14b0fe, 0x1e7301, 0xb491d, 0x10d23e, 0xa4015, 0x4c2fa, 0xce8e5, 0xadfd9, 0xf110, 0x5220c, 0xf225f, 0xb8bdb, 0x159467, 0xc0df9}); 77 | constexpr StatTable21 QRT_TABLE_21({0x1bd5fc, 0xbc196, 0xbc194, 0x74b96, 0xbc190, 0x1048, 0x74b9e, 0x672c8, 0xbc180, 0x4080, 0x1068, 0xc8200, 0x74bde, 0x64280, 0x67248, 0xc4280, 0xbc080, 0x80000, 0x4280, 0, 0x1468}); 78 | typedef Field Field21; 79 | typedef FieldTri, &SQR_TABLE_21, &SQR2_TABLE_21, &SQR4_TABLE_21, &SQR8_TABLE_21, &QRT_TABLE_21, &QRT_TABLE_21, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri21; 80 | #endif 81 | 82 | #ifdef ENABLE_FIELD_INT_22 83 | // 22 bit field 84 | typedef RecLinTrans StatTableTRI22; 85 | constexpr StatTableTRI22 SQR_TABLE_TRI22({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x3, 0xc, 0x30, 0xc0, 0x300, 0xc00, 0x3000, 0xc000, 0x30000, 0xc0000, 0x300000}); 86 | constexpr StatTableTRI22 SQR2_TABLE_TRI22({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x100000, 0xc, 0xc0, 0xc00, 0xc000, 0xc0000, 0x5, 0x50, 0x500, 0x5000, 0x50000, 0x100003, 0x3c, 0x3c0, 0x3c00, 0x3c000, 0x3c0000}); 87 | constexpr StatTableTRI22 SQR4_TABLE_TRI22({0x1, 0x10000, 0xc00, 0x50, 0x100003, 0x3c000, 0x1100, 0xcc, 0xc0005, 0x55000, 0x3fc0, 0x101, 0x1000c, 0xc0c00, 0x5050, 0x1003c3, 0x3c011, 0x111100, 0xcccc, 0xc0555, 0x15503f, 0x3fffc0}); 88 | constexpr StatTableTRI22 SQR8_TABLE_TRI22({0x1, 0x3c011, 0x3ec1, 0x101103, 0x14503e, 0x28282, 0xd0009, 0x1d9c, 0xcc598, 0x25c81, 0x47304, 0xc0004, 0x3cc41, 0xcf758, 0x11415f, 0x1d11f7, 0x128280, 0x1b9027, 0x1070ce, 0x10eb5e, 0x5c0ec, 0x2097e0}); 89 | constexpr StatTableTRI22 QRT_TABLE_TRI22({0x210d16, 0x104a, 0x1048, 0x4088, 0x104c, 0x200420, 0x4080, 0x492dc, 0x105c, 0x1a67f0, 0x200400, 0x21155c, 0x40c0, 0x20346c, 0x4925c, 0x1af7ac, 0x115c, 0x2274ac, 0x1a65f0, 0x2a65f0, 0x200000, 0}); 90 | typedef FieldTri FieldTri22; 91 | #endif 92 | 93 | #ifdef ENABLE_FIELD_INT_23 94 | // 23 bit field 95 | typedef RecLinTrans StatTable23; 96 | constexpr StatTable23 SQR_TABLE_23({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x42, 0x108, 0x420, 0x1080, 0x4200, 0x10800, 0x42000, 0x108000, 0x420000, 0x80042, 0x200108}); 97 | constexpr StatTable23 SQR2_TABLE_23({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x100000, 0x42, 0x420, 0x4200, 0x42000, 0x420000, 0x200108, 0x1004, 0x10040, 0x100400, 0x4042, 0x40420, 0x404200, 0x42108, 0x421080, 0x210908, 0x109004, 0x90002}); 98 | constexpr StatTable23 SQR4_TABLE_23({0x1, 0x10000, 0x4200, 0x1004, 0x40420, 0x210908, 0x52, 0x520000, 0x142400, 0x52148, 0x494202, 0x10c204, 0x1104, 0x40462, 0x630908, 0x100452, 0x562108, 0x1d2402, 0x57348, 0x495626, 0x34c72c, 0x21584e, 0x4614b0}); 99 | constexpr StatTable23 SQR8_TABLE_23({0x1, 0x562108, 0x662840, 0x5304, 0x6d3842, 0x738f46, 0x50472, 0x6ff79e, 0x7cf204, 0x436274, 0x3e4bde, 0x42a93e, 0x147704, 0x6c3810, 0x28bff4, 0x78815c, 0x7ab4b0, 0x62852a, 0x255b30, 0x5653d0, 0x1afd36, 0x5f118, 0x601dd4}); 100 | constexpr StatTable23 QRT_TABLE_23({0, 0x1040, 0x1042, 0x43056, 0x1046, 0x121d76, 0x4305e, 0x40a0, 0x1056, 0x15176, 0x121d56, 0x7ee1f6, 0x4301e, 0x40000, 0x4020, 0x4f0be, 0x1156, 0x7cf0a0, 0x15376, 0x1ee9e8, 0x121956, 0x3ac9f6, 0x7ee9f6}); 101 | typedef Field Field23; 102 | typedef FieldTri, &SQR_TABLE_23, &SQR2_TABLE_23, &SQR4_TABLE_23, &SQR8_TABLE_23, nullptr, &QRT_TABLE_23, IdTrans, &ID_TRANS, &ID_TRANS> FieldTri23; 103 | #endif 104 | 105 | #ifdef ENABLE_FIELD_INT_24 106 | // 24 bit field 107 | typedef RecLinTrans StatTable24; 108 | constexpr StatTable24 SQR_TABLE_24({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1b, 0x6c, 0x1b0, 0x6c0, 0x1b00, 0x6c00, 0x1b000, 0x6c000, 0x1b0000, 0x6c0000, 0xb0001b, 0xc0005a}); 109 | constexpr StatTable24 SQR2_TABLE_24({0x1, 0x10, 0x100, 0x1000, 0x10000, 0x100000, 0x1b, 0x1b0, 0x1b00, 0x1b000, 0x1b0000, 0xb0001b, 0x145, 0x1450, 0x14500, 0x145000, 0x45001b, 0x5001dc, 0x1db7, 0x1db70, 0x1db700, 0xdb701b, 0xb7011f, 0x701105}); 110 | constexpr StatTable24 SQR4_TABLE_24({0x1, 0x10000, 0x1b00, 0x145, 0x45001b, 0x1db700, 0x11011, 0x111ab0, 0xb1aa5e, 0x51450e, 0x96db7, 0xb7c60f, 0x1a1a, 0x1a015e, 0x5f5e1b, 0x1ceef2, 0xf30ca2, 0xabbdb4, 0xba1aff, 0xf0bf5e, 0x579fc9, 0xce3da9, 0xa2c07f, 0x71dd40}); 111 | constexpr StatTable24 SQR8_TABLE_24({0x1, 0xf30ca2, 0x573345, 0xb0a14e, 0xafd77d, 0x1419b, 0xb616a2, 0xba7db, 0xbe1560, 0xe0d0a3, 0x15bf5, 0x1056dd, 0xa29845, 0xf83d32, 0x13e0e9, 0xe2d8d3, 0xa10841, 0x57ac5a, 0x1c432f, 0x57044e, 0x454fba, 0x2bb37c, 0xf50fa, 0x85d5b9}); 112 | constexpr StatTable24 QRT_TABLE_24({0x104e, 0xaf42a8, 0xaf42aa, 0xb78186, 0xaf42ae, 0x4090, 0xb7818e, 0x4a37c, 0xaf42be, 0x3688c0, 0x40b0, 0x80080e, 0xb781ce, 0xaf2232, 0x4a3fc, 0x856a82, 0xaf43be, 0x29c970, 0x368ac0, 0x968ace, 0x44b0, 0x77d570, 0x80000e, 0}); 113 | typedef Field Field24; 114 | #endif 115 | } 116 | 117 | Sketch* ConstructClMul3Bytes(int bits, int implementation) { 118 | switch (bits) { 119 | #ifdef ENABLE_FIELD_INT_17 120 | case 17: return new SketchImpl(implementation, 17); 121 | #endif 122 | #ifdef ENABLE_FIELD_INT_18 123 | case 18: return new SketchImpl(implementation, 18); 124 | #endif 125 | #ifdef ENABLE_FIELD_INT_19 126 | case 19: return new SketchImpl(implementation, 19); 127 | #endif 128 | #ifdef ENABLE_FIELD_INT_20 129 | case 20: return new SketchImpl(implementation, 20); 130 | #endif 131 | #ifdef ENABLE_FIELD_INT_21 132 | case 21: return new SketchImpl(implementation, 21); 133 | #endif 134 | #ifdef ENABLE_FIELD_INT_23 135 | case 23: return new SketchImpl(implementation, 23); 136 | #endif 137 | #ifdef ENABLE_FIELD_INT_24 138 | case 24: return new SketchImpl(implementation, 24); 139 | #endif 140 | } 141 | return nullptr; 142 | } 143 | 144 | Sketch* ConstructClMulTri3Bytes(int bits, int implementation) { 145 | switch (bits) { 146 | #ifdef ENABLE_FIELD_INT_17 147 | case 17: return new SketchImpl(implementation, 17); 148 | #endif 149 | #ifdef ENABLE_FIELD_INT_18 150 | case 18: return new SketchImpl(implementation, 18); 151 | #endif 152 | #ifdef ENABLE_FIELD_INT_20 153 | case 20: return new SketchImpl(implementation, 20); 154 | #endif 155 | #ifdef ENABLE_FIELD_INT_21 156 | case 21: return new SketchImpl(implementation, 21); 157 | #endif 158 | #ifdef ENABLE_FIELD_INT_22 159 | case 22: return new SketchImpl(implementation, 22); 160 | #endif 161 | #ifdef ENABLE_FIELD_INT_23 162 | case 23: return new SketchImpl(implementation, 23); 163 | #endif 164 | } 165 | return nullptr; 166 | } 167 | -------------------------------------------------------------------------------- /src/fields/clmul_common_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_FIELDS_CLMUL_COMMON_IMPL_H_ 8 | #define _MINISKETCH_FIELDS_CLMUL_COMMON_IMPL_H_ 1 9 | 10 | #include 11 | #include 12 | 13 | #include "../int_utils.h" 14 | #include "../lintrans.h" 15 | 16 | namespace { 17 | 18 | // The memory sanitizer in clang < 11 cannot reason through _mm_clmulepi64_si128 calls. 19 | // Disable memory sanitization in the functions using them for those compilers. 20 | #if defined(__clang__) && (__clang_major__ < 11) 21 | # if defined(__has_feature) 22 | # if __has_feature(memory_sanitizer) 23 | # define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) 24 | # endif 25 | # endif 26 | #endif 27 | #ifndef NO_SANITIZE_MEMORY 28 | # define NO_SANITIZE_MEMORY 29 | #endif 30 | 31 | template NO_SANITIZE_MEMORY I MulWithClMulReduce(I a, I b) 32 | { 33 | static constexpr I MASK = Mask(); 34 | 35 | const __m128i MOD128 = _mm_cvtsi64_si128(MOD); 36 | __m128i product = _mm_clmulepi64_si128(_mm_cvtsi64_si128((uint64_t)a), _mm_cvtsi64_si128((uint64_t)b), 0x00); 37 | if (BITS <= 32) { 38 | __m128i high1 = _mm_srli_epi64(product, BITS); 39 | __m128i red1 = _mm_clmulepi64_si128(high1, MOD128, 0x00); 40 | __m128i high2 = _mm_srli_epi64(red1, BITS); 41 | __m128i red2 = _mm_clmulepi64_si128(high2, MOD128, 0x00); 42 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 43 | } else if (BITS == 64) { 44 | __m128i red1 = _mm_clmulepi64_si128(product, MOD128, 0x01); 45 | __m128i red2 = _mm_clmulepi64_si128(red1, MOD128, 0x01); 46 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)); 47 | } else if ((BITS % 8) == 0) { 48 | __m128i high1 = _mm_srli_si128(product, BITS / 8); 49 | __m128i red1 = _mm_clmulepi64_si128(high1, MOD128, 0x00); 50 | __m128i high2 = _mm_srli_si128(red1, BITS / 8); 51 | __m128i red2 = _mm_clmulepi64_si128(high2, MOD128, 0x00); 52 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 53 | } else { 54 | __m128i high1 = _mm_or_si128(_mm_srli_epi64(product, BITS), _mm_srli_si128(_mm_slli_epi64(product, 64 - BITS), 8)); 55 | __m128i red1 = _mm_clmulepi64_si128(high1, MOD128, 0x00); 56 | if ((uint64_t(MOD) >> (66 - BITS)) == 0) { 57 | __m128i high2 = _mm_srli_epi64(red1, BITS); 58 | __m128i red2 = _mm_clmulepi64_si128(high2, MOD128, 0x00); 59 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 60 | } else { 61 | __m128i high2 = _mm_or_si128(_mm_srli_epi64(red1, BITS), _mm_srli_si128(_mm_slli_epi64(red1, 64 - BITS), 8)); 62 | __m128i red2 = _mm_clmulepi64_si128(high2, MOD128, 0x00); 63 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 64 | } 65 | } 66 | } 67 | 68 | template NO_SANITIZE_MEMORY I MulTrinomial(I a, I b) 69 | { 70 | static constexpr I MASK = Mask(); 71 | 72 | __m128i product = _mm_clmulepi64_si128(_mm_cvtsi64_si128((uint64_t)a), _mm_cvtsi64_si128((uint64_t)b), 0x00); 73 | if (BITS <= 32) { 74 | __m128i high1 = _mm_srli_epi64(product, BITS); 75 | __m128i red1 = _mm_xor_si128(high1, _mm_slli_epi64(high1, POS)); 76 | if (POS == 1) { 77 | return _mm_cvtsi128_si64(_mm_xor_si128(product, red1)) & MASK; 78 | } else { 79 | __m128i high2 = _mm_srli_epi64(red1, BITS); 80 | __m128i red2 = _mm_xor_si128(high2, _mm_slli_epi64(high2, POS)); 81 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 82 | } 83 | } else { 84 | __m128i high1 = _mm_or_si128(_mm_srli_epi64(product, BITS), _mm_srli_si128(_mm_slli_epi64(product, 64 - BITS), 8)); 85 | if (BITS + POS <= 66) { 86 | __m128i red1 = _mm_xor_si128(high1, _mm_slli_epi64(high1, POS)); 87 | if (POS == 1) { 88 | return _mm_cvtsi128_si64(_mm_xor_si128(product, red1)) & MASK; 89 | } else if (BITS + POS <= 66) { 90 | __m128i high2 = _mm_srli_epi64(red1, BITS); 91 | __m128i red2 = _mm_xor_si128(high2, _mm_slli_epi64(high2, POS)); 92 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 93 | } 94 | } else { 95 | const __m128i MOD128 = _mm_cvtsi64_si128(1 + (((uint64_t)1) << POS)); 96 | __m128i red1 = _mm_clmulepi64_si128(high1, MOD128, 0x00); 97 | __m128i high2 = _mm_or_si128(_mm_srli_epi64(red1, BITS), _mm_srli_si128(_mm_slli_epi64(red1, 64 - BITS), 8)); 98 | __m128i red2 = _mm_xor_si128(high2, _mm_slli_epi64(high2, POS)); 99 | return _mm_cvtsi128_si64(_mm_xor_si128(_mm_xor_si128(product, red1), red2)) & MASK; 100 | } 101 | } 102 | } 103 | 104 | /** Implementation of fields that use the SSE clmul intrinsic for multiplication. */ 105 | template struct GenField 106 | { 107 | typedef BitsInt O; 108 | typedef LFSR L; 109 | 110 | static inline constexpr I Sqr1(I a) { return SQR->template Map(a); } 111 | static inline constexpr I Sqr2(I a) { return SQR2->template Map(a); } 112 | static inline constexpr I Sqr4(I a) { return SQR4->template Map(a); } 113 | static inline constexpr I Sqr8(I a) { return SQR8->template Map(a); } 114 | static inline constexpr I Sqr16(I a) { return SQR16->template Map(a); } 115 | 116 | public: 117 | typedef I Elem; 118 | 119 | inline constexpr int Bits() const { return B; } 120 | 121 | inline constexpr Elem Mul2(Elem val) const { return L::Call(val); } 122 | 123 | inline Elem Mul(Elem a, Elem b) const { return MUL(a, b); } 124 | 125 | class Multiplier 126 | { 127 | Elem m_val; 128 | public: 129 | inline constexpr explicit Multiplier(const GenField&, Elem a) : m_val(a) {} 130 | constexpr Elem operator()(Elem a) const { return MUL(m_val, a); } 131 | }; 132 | 133 | /** Compute the square of a. */ 134 | inline constexpr Elem Sqr(Elem val) const { return SQR->template Map(val); } 135 | 136 | /** Compute x such that x^2 + x = a (undefined result if no solution exists). */ 137 | inline constexpr Elem Qrt(Elem val) const { return QRT->template Map(val); } 138 | 139 | /** Compute the inverse of x1. */ 140 | inline Elem Inv(Elem val) const { return InvLadder(val); } 141 | 142 | /** Generate a random field element. */ 143 | Elem FromSeed(uint64_t seed) const { 144 | uint64_t k0 = 0x434c4d554c466c64ull; // "CLMULFld" 145 | uint64_t k1 = seed; 146 | uint64_t count = ((uint64_t)B) << 32; 147 | I ret; 148 | do { 149 | ret = O::Mask(I(SipHash(k0, k1, count++))); 150 | } while(ret == 0); 151 | return LOAD->template Map(ret); 152 | } 153 | 154 | Elem Deserialize(BitReader& in) const { return LOAD->template Map(in.Read()); } 155 | 156 | void Serialize(BitWriter& out, Elem val) const { out.Write(SAVE->template Map(val)); } 157 | 158 | constexpr Elem FromUint64(uint64_t x) const { return LOAD->template Map(O::Mask(I(x))); } 159 | constexpr uint64_t ToUint64(Elem val) const { return uint64_t(SAVE->template Map(val)); } 160 | }; 161 | 162 | template 163 | using Field = GenField, F, SQR, SQR2, SQR4, SQR8, SQR16, QRT, T, LOAD, SAVE>; 164 | 165 | template 166 | using FieldTri = GenField, F, SQR, SQR2, SQR4, SQR8, SQR16, QRT, T, LOAD, SAVE>; 167 | 168 | } 169 | 170 | #endif 171 | -------------------------------------------------------------------------------- /src/fields/generic_1byte.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_1) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_2 23 | // 2 bit field 24 | typedef RecLinTrans StatTable2; 25 | typedef RecLinTrans DynTable2; 26 | constexpr StatTable2 SQR_TABLE_2({0x1, 0x3}); 27 | constexpr StatTable2 QRT_TABLE_2({0x2, 0}); 28 | typedef Field Field2; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_3 32 | // 3 bit field 33 | typedef RecLinTrans StatTable3; 34 | typedef RecLinTrans DynTable3; 35 | constexpr StatTable3 SQR_TABLE_3({0x1, 0x4, 0x6}); 36 | constexpr StatTable3 QRT_TABLE_3({0, 0x4, 0x6}); 37 | typedef Field Field3; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_4 41 | // 4 bit field 42 | typedef RecLinTrans StatTable4; 43 | typedef RecLinTrans DynTable4; 44 | constexpr StatTable4 SQR_TABLE_4({0x1, 0x4, 0x3, 0xc}); 45 | constexpr StatTable4 QRT_TABLE_4({0x6, 0xa, 0x8, 0}); 46 | typedef Field Field4; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_5 50 | // 5 bit field 51 | typedef RecLinTrans StatTable5; 52 | typedef RecLinTrans DynTable5; 53 | constexpr StatTable5 SQR_TABLE_5({0x1, 0x4, 0x10, 0xa, 0xd}); 54 | constexpr StatTable5 QRT_TABLE_5({0x14, 0x8, 0xa, 0, 0xe}); 55 | typedef Field Field5; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_6 59 | // 6 bit field 60 | typedef RecLinTrans StatTable6; 61 | typedef RecLinTrans DynTable6; 62 | constexpr StatTable6 SQR_TABLE_6({0x1, 0x4, 0x10, 0x3, 0xc, 0x30}); 63 | constexpr StatTable6 QRT_TABLE_6({0x3a, 0x26, 0x24, 0x14, 0x20, 0}); 64 | typedef Field Field6; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_7 68 | // 7 bit field 69 | typedef RecLinTrans StatTable7; 70 | typedef RecLinTrans DynTable7; 71 | constexpr StatTable7 SQR_TABLE_7({0x1, 0x4, 0x10, 0x40, 0x6, 0x18, 0x60}); 72 | constexpr StatTable7 QRT_TABLE_7({0, 0x14, 0x16, 0x72, 0x12, 0x40, 0x7a}); 73 | typedef Field Field7; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_8 77 | // 8 bit field 78 | typedef RecLinTrans StatTable8; 79 | typedef RecLinTrans DynTable8; 80 | constexpr StatTable8 SQR_TABLE_8({0x1, 0x4, 0x10, 0x40, 0x1b, 0x6c, 0xab, 0x9a}); 81 | constexpr StatTable8 QRT_TABLE_8({0xbc, 0x2a, 0x28, 0x86, 0x2c, 0xde, 0x8e, 0}); 82 | typedef Field Field8; 83 | #endif 84 | } 85 | 86 | Sketch* ConstructGeneric1Byte(int bits, int implementation) 87 | { 88 | switch (bits) { 89 | #ifdef ENABLE_FIELD_INT_2 90 | case 2: return new SketchImpl(implementation, 2); 91 | #endif 92 | #ifdef ENABLE_FIELD_INT_3 93 | case 3: return new SketchImpl(implementation, 3); 94 | #endif 95 | #ifdef ENABLE_FIELD_INT_4 96 | case 4: return new SketchImpl(implementation, 4); 97 | #endif 98 | #ifdef ENABLE_FIELD_INT_5 99 | case 5: return new SketchImpl(implementation, 5); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_6 102 | case 6: return new SketchImpl(implementation, 6); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_7 105 | case 7: return new SketchImpl(implementation, 7); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_8 108 | case 8: return new SketchImpl(implementation, 8); 109 | #endif 110 | default: return nullptr; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/fields/generic_2bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_2) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_9 23 | // 9 bit field 24 | typedef RecLinTrans StatTable9; 25 | typedef RecLinTrans DynTable9; 26 | constexpr StatTable9 SQR_TABLE_9({0x1, 0x4, 0x10, 0x40, 0x100, 0x6, 0x18, 0x60, 0x180}); 27 | constexpr StatTable9 QRT_TABLE_9({0, 0x4e, 0x4c, 0x1aa, 0x48, 0x22, 0x1a2, 0x100, 0x58}); 28 | typedef Field Field9; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_10 32 | // 10 bit field 33 | typedef RecLinTrans StatTable10; 34 | typedef RecLinTrans DynTable10; 35 | constexpr StatTable10 SQR_TABLE_10({0x1, 0x4, 0x10, 0x40, 0x100, 0x9, 0x24, 0x90, 0x240, 0x112}); 36 | constexpr StatTable10 QRT_TABLE_10({0xec, 0x86, 0x84, 0x30e, 0x80, 0x3c2, 0x306, 0, 0x90, 0x296}); 37 | typedef Field Field10; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_11 41 | // 11 bit field 42 | typedef RecLinTrans StatTable11; 43 | typedef RecLinTrans DynTable11; 44 | constexpr StatTable11 SQR_TABLE_11({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0xa, 0x28, 0xa0, 0x280, 0x205}); 45 | constexpr StatTable11 QRT_TABLE_11({0x734, 0x48, 0x4a, 0x1de, 0x4e, 0x35e, 0x1d6, 0x200, 0x5e, 0, 0x37e}); 46 | typedef Field Field11; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_12 50 | // 12 bit field 51 | typedef RecLinTrans StatTable12; 52 | typedef RecLinTrans DynTable12; 53 | constexpr StatTable12 SQR_TABLE_12({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x9, 0x24, 0x90, 0x240, 0x900, 0x412}); 54 | constexpr StatTable12 QRT_TABLE_12({0x48, 0xc10, 0xc12, 0x208, 0xc16, 0xd82, 0x200, 0x110, 0xc06, 0, 0xda2, 0x5a4}); 55 | typedef Field Field12; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_13 59 | // 13 bit field 60 | typedef RecLinTrans StatTable13; 61 | typedef RecLinTrans DynTable13; 62 | constexpr StatTable13 SQR_TABLE_13({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x36, 0xd8, 0x360, 0xd80, 0x161b, 0x185a}); 63 | constexpr StatTable13 QRT_TABLE_13({0xcfc, 0x1500, 0x1502, 0x382, 0x1506, 0x149c, 0x38a, 0x118, 0x1516, 0, 0x14bc, 0x100e, 0x3ca}); 64 | typedef Field Field13; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_14 68 | // 14 bit field 69 | typedef RecLinTrans StatTable14; 70 | typedef RecLinTrans DynTable14; 71 | constexpr StatTable14 SQR_TABLE_14({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x21, 0x84, 0x210, 0x840, 0x2100, 0x442, 0x1108}); 72 | constexpr StatTable14 QRT_TABLE_14({0x13f2, 0x206, 0x204, 0x3e06, 0x200, 0x1266, 0x3e0e, 0x114, 0x210, 0, 0x1246, 0x2848, 0x3e4e, 0x2258}); 73 | typedef Field Field14; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_15 77 | // 15 bit field 78 | typedef RecLinTrans StatTable15; 79 | typedef RecLinTrans DynTable15; 80 | constexpr StatTable15 SQR_TABLE_15({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x6, 0x18, 0x60, 0x180, 0x600, 0x1800, 0x6000}); 81 | constexpr StatTable15 QRT_TABLE_15({0, 0x114, 0x116, 0x428, 0x112, 0x137a, 0x420, 0x6d62, 0x102, 0x73a, 0x135a, 0x6460, 0x460, 0x4000, 0x6de2}); 82 | typedef Field Field15; 83 | #endif 84 | 85 | #ifdef ENABLE_FIELD_INT_16 86 | // 16 bit field 87 | typedef RecLinTrans StatTable16; 88 | typedef RecLinTrans DynTable16; 89 | constexpr StatTable16 SQR_TABLE_16({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x2b, 0xac, 0x2b0, 0xac0, 0x2b00, 0xac00, 0xb056, 0xc10e}); 90 | constexpr StatTable16 QRT_TABLE_16({0x732, 0x72b8, 0x72ba, 0x7e96, 0x72be, 0x78b2, 0x7e9e, 0x8cba, 0x72ae, 0xfa24, 0x7892, 0x5892, 0x7ede, 0xbec6, 0x8c3a, 0}); 91 | typedef Field Field16; 92 | #endif 93 | } 94 | 95 | Sketch* ConstructGeneric2Bytes(int bits, int implementation) 96 | { 97 | switch (bits) { 98 | #ifdef ENABLE_FIELD_INT_9 99 | case 9: return new SketchImpl(implementation, 9); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_10 102 | case 10: return new SketchImpl(implementation, 10); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_11 105 | case 11: return new SketchImpl(implementation, 11); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_12 108 | case 12: return new SketchImpl(implementation, 12); 109 | #endif 110 | #ifdef ENABLE_FIELD_INT_13 111 | case 13: return new SketchImpl(implementation, 13); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_14 114 | case 14: return new SketchImpl(implementation, 14); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_15 117 | case 15: return new SketchImpl(implementation, 15); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_16 120 | case 16: return new SketchImpl(implementation, 16); 121 | #endif 122 | default: return nullptr; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/fields/generic_3bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_3) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_17 23 | // 17 bit field 24 | typedef RecLinTrans StatTable17; 25 | typedef RecLinTrans DynTable17; 26 | constexpr StatTable17 SQR_TABLE_17({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x12, 0x48, 0x120, 0x480, 0x1200, 0x4800, 0x12000, 0x8012}); 27 | constexpr StatTable17 QRT_TABLE_17({0, 0x4c3e, 0x4c3c, 0x1a248, 0x4c38, 0x428, 0x1a240, 0x1b608, 0x4c28, 0x206, 0x408, 0x4000, 0x1a200, 0x18006, 0x1b688, 0x14d2e, 0x4d28}); 28 | typedef Field Field17; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_18 32 | // 18 bit field 33 | typedef RecLinTrans StatTable18; 34 | typedef RecLinTrans DynTable18; 35 | constexpr StatTable18 SQR_TABLE_18({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x9, 0x24, 0x90, 0x240, 0x900, 0x2400, 0x9000, 0x24000, 0x10012}); 36 | constexpr StatTable18 QRT_TABLE_18({0x9208, 0x422, 0x420, 0x8048, 0x424, 0x68b0, 0x8040, 0x30086, 0x434, 0x1040, 0x6890, 0x30ca2, 0x8000, 0x32896, 0x30006, 0, 0x534, 0x20532}); 37 | typedef Field Field18; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_19 41 | // 19 bit field 42 | typedef RecLinTrans StatTable19; 43 | typedef RecLinTrans DynTable19; 44 | constexpr StatTable19 SQR_TABLE_19({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x4e, 0x138, 0x4e0, 0x1380, 0x4e00, 0x13800, 0x4e000, 0x3804e, 0x6011f}); 45 | constexpr StatTable19 QRT_TABLE_19({0x5d6b0, 0x2f476, 0x2f474, 0x1d6a2, 0x2f470, 0x42a, 0x1d6aa, 0x1060, 0x2f460, 0x19e92, 0x40a, 0x1da98, 0x1d6ea, 0x28c78, 0x10e0, 0xf56a, 0x2f560, 0, 0x19c92}); 46 | typedef Field Field19; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_20 50 | // 20 bit field 51 | typedef RecLinTrans StatTable20; 52 | typedef RecLinTrans DynTable20; 53 | constexpr StatTable20 SQR_TABLE_20({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x9, 0x24, 0x90, 0x240, 0x900, 0x2400, 0x9000, 0x24000, 0x90000, 0x40012}); 54 | constexpr StatTable20 QRT_TABLE_20({0xc5dea, 0xc0110, 0xc0112, 0xe11de, 0xc0116, 0x24814, 0xe11d6, 0x20080, 0xc0106, 0xfe872, 0x24834, 0xe4106, 0xe1196, 0x1d9a4, 0x20000, 0x31190, 0xc0006, 0, 0xfea72, 0x7ea74}); 55 | typedef Field Field20; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_21 59 | // 21 bit field 60 | typedef RecLinTrans StatTable21; 61 | typedef RecLinTrans DynTable21; 62 | constexpr StatTable21 SQR_TABLE_21({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0xa, 0x28, 0xa0, 0x280, 0xa00, 0x2800, 0xa000, 0x28000, 0xa0000, 0x80005}); 63 | constexpr StatTable21 QRT_TABLE_21({0x1bd5fc, 0xbc196, 0xbc194, 0x74b96, 0xbc190, 0x1048, 0x74b9e, 0x672c8, 0xbc180, 0x4080, 0x1068, 0xc8200, 0x74bde, 0x64280, 0x67248, 0xc4280, 0xbc080, 0x80000, 0x4280, 0, 0x1468}); 64 | typedef Field Field21; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_22 68 | // 22 bit field 69 | typedef RecLinTrans StatTable22; 70 | typedef RecLinTrans DynTable22; 71 | constexpr StatTable22 SQR_TABLE_22({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x3, 0xc, 0x30, 0xc0, 0x300, 0xc00, 0x3000, 0xc000, 0x30000, 0xc0000, 0x300000}); 72 | constexpr StatTable22 QRT_TABLE_22({0x210d16, 0x104a, 0x1048, 0x4088, 0x104c, 0x200420, 0x4080, 0x492dc, 0x105c, 0x1a67f0, 0x200400, 0x21155c, 0x40c0, 0x20346c, 0x4925c, 0x1af7ac, 0x115c, 0x2274ac, 0x1a65f0, 0x2a65f0, 0x200000, 0}); 73 | typedef Field Field22; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_23 77 | // 23 bit field 78 | typedef RecLinTrans StatTable23; 79 | typedef RecLinTrans DynTable23; 80 | constexpr StatTable23 SQR_TABLE_23({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x42, 0x108, 0x420, 0x1080, 0x4200, 0x10800, 0x42000, 0x108000, 0x420000, 0x80042, 0x200108}); 81 | constexpr StatTable23 QRT_TABLE_23({0, 0x1040, 0x1042, 0x43056, 0x1046, 0x121d76, 0x4305e, 0x40a0, 0x1056, 0x15176, 0x121d56, 0x7ee1f6, 0x4301e, 0x40000, 0x4020, 0x4f0be, 0x1156, 0x7cf0a0, 0x15376, 0x1ee9e8, 0x121956, 0x3ac9f6, 0x7ee9f6}); 82 | typedef Field Field23; 83 | #endif 84 | 85 | #ifdef ENABLE_FIELD_INT_24 86 | // 24 bit field 87 | typedef RecLinTrans StatTable24; 88 | typedef RecLinTrans DynTable24; 89 | constexpr StatTable24 SQR_TABLE_24({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1b, 0x6c, 0x1b0, 0x6c0, 0x1b00, 0x6c00, 0x1b000, 0x6c000, 0x1b0000, 0x6c0000, 0xb0001b, 0xc0005a}); 90 | constexpr StatTable24 QRT_TABLE_24({0x104e, 0xaf42a8, 0xaf42aa, 0xb78186, 0xaf42ae, 0x4090, 0xb7818e, 0x4a37c, 0xaf42be, 0x3688c0, 0x40b0, 0x80080e, 0xb781ce, 0xaf2232, 0x4a3fc, 0x856a82, 0xaf43be, 0x29c970, 0x368ac0, 0x968ace, 0x44b0, 0x77d570, 0x80000e, 0}); 91 | typedef Field Field24; 92 | #endif 93 | } 94 | 95 | Sketch* ConstructGeneric3Bytes(int bits, int implementation) 96 | { 97 | switch (bits) { 98 | #ifdef ENABLE_FIELD_INT_17 99 | case 17: return new SketchImpl(implementation, 17); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_18 102 | case 18: return new SketchImpl(implementation, 18); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_19 105 | case 19: return new SketchImpl(implementation, 19); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_20 108 | case 20: return new SketchImpl(implementation, 20); 109 | #endif 110 | #ifdef ENABLE_FIELD_INT_21 111 | case 21: return new SketchImpl(implementation, 21); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_22 114 | case 22: return new SketchImpl(implementation, 22); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_23 117 | case 23: return new SketchImpl(implementation, 23); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_24 120 | case 24: return new SketchImpl(implementation, 24); 121 | #endif 122 | default: return nullptr; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/fields/generic_4bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_4) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_25 23 | // 25 bit field 24 | typedef RecLinTrans StatTable25; 25 | typedef RecLinTrans DynTable25; 26 | constexpr StatTable25 SQR_TABLE_25({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x12, 0x48, 0x120, 0x480, 0x1200, 0x4800, 0x12000, 0x48000, 0x120000, 0x480000, 0x1200000, 0x800012}); 27 | constexpr StatTable25 QRT_TABLE_25({0, 0x482110, 0x482112, 0x1b3c3e6, 0x482116, 0x4960ae, 0x1b3c3ee, 0x4088, 0x482106, 0x58a726, 0x49608e, 0x5ce52e, 0x1b3c3ae, 0x2006, 0x4008, 0x1c1a8, 0x482006, 0x1e96488, 0x58a526, 0x400000, 0x49648e, 0x1800006, 0x5ced2e, 0xb3d3a8, 0x1b3d3ae}); 28 | typedef Field Field25; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_26 32 | // 26 bit field 33 | typedef RecLinTrans StatTable26; 34 | typedef RecLinTrans DynTable26; 35 | constexpr StatTable26 SQR_TABLE_26({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x1b, 0x6c, 0x1b0, 0x6c0, 0x1b00, 0x6c00, 0x1b000, 0x6c000, 0x1b0000, 0x6c0000, 0x1b00000, 0x2c0001b, 0x300005a}); 36 | constexpr StatTable26 QRT_TABLE_26({0x217b530, 0x2ae82a8, 0x2ae82aa, 0x2001046, 0x2ae82ae, 0x2de032e, 0x200104e, 0x70c10c, 0x2ae82be, 0x20151f2, 0x2de030e, 0xbc1400, 0x200100e, 0x178570, 0x70c18c, 0x2ae4232, 0x2ae83be, 0x211d742, 0x20153f2, 0x21f54f2, 0x2de070e, 0x5e0700, 0xbc1c00, 0x3abb97e, 0x200000e, 0}); 37 | typedef Field Field26; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_27 41 | // 27 bit field 42 | typedef RecLinTrans StatTable27; 43 | typedef RecLinTrans DynTable27; 44 | constexpr StatTable27 SQR_TABLE_27({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x4e, 0x138, 0x4e0, 0x1380, 0x4e00, 0x13800, 0x4e000, 0x138000, 0x4e0000, 0x1380000, 0x4e00000, 0x380004e, 0x600011f}); 45 | constexpr StatTable27 QRT_TABLE_27({0x6bf0530, 0x2be4496, 0x2be4494, 0x2bf0522, 0x2be4490, 0x1896cca, 0x2bf052a, 0x408a, 0x2be4480, 0x368ae72, 0x1896cea, 0x18d2ee0, 0x2bf056a, 0x1c76d6a, 0x400a, 0x336e9f8, 0x2be4580, 0x36baf12, 0x368ac72, 0x430360, 0x18968ea, 0x34a6b80, 0x18d26e0, 0xbf1560, 0x2bf156a, 0, 0x1c74d6a}); 46 | typedef Field Field27; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_28 50 | // 28 bit field 51 | typedef RecLinTrans StatTable28; 52 | typedef RecLinTrans DynTable28; 53 | constexpr StatTable28 SQR_TABLE_28({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x3, 0xc, 0x30, 0xc0, 0x300, 0xc00, 0x3000, 0xc000, 0x30000, 0xc0000, 0x300000, 0xc00000, 0x3000000, 0xc000000}); 54 | constexpr StatTable28 QRT_TABLE_28({0x121d57a, 0x40216, 0x40214, 0x8112578, 0x40210, 0x10110, 0x8112570, 0x12597ec, 0x40200, 0x6983e00, 0x10130, 0x972b99c, 0x8112530, 0x8002000, 0x125976c, 0x815a76c, 0x40300, 0x936b29c, 0x6983c00, 0x97bb8ac, 0x10530, 0x9103000, 0x972b19c, 0xf6384ac, 0x8113530, 0x4113530, 0x8000000, 0}); 55 | typedef Field Field28; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_29 59 | // 29 bit field 60 | typedef RecLinTrans StatTable29; 61 | typedef RecLinTrans DynTable29; 62 | constexpr StatTable29 SQR_TABLE_29({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0xa, 0x28, 0xa0, 0x280, 0xa00, 0x2800, 0xa000, 0x28000, 0xa0000, 0x280000, 0xa00000, 0x2800000, 0xa000000, 0x8000005}); 63 | constexpr StatTable29 QRT_TABLE_29({0x1b8351dc, 0xb87135e, 0xb87135c, 0xda7b35e, 0xb871358, 0x621a116, 0xda7b356, 0x40200, 0xb871348, 0xc9e2620, 0x621a136, 0x478b16, 0xda7b316, 0x6762e20, 0x40280, 0x6202000, 0xb871248, 0x627a316, 0xc9e2420, 0xcd1ad36, 0x621a536, 0x760e20, 0x478316, 0xa760e20, 0xda7a316, 0x8000000, 0x6760e20, 0, 0x44280}); 64 | typedef Field Field29; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_30 68 | // 30 bit field 69 | typedef RecLinTrans StatTable30; 70 | typedef RecLinTrans DynTable30; 71 | constexpr StatTable30 SQR_TABLE_30({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x3, 0xc, 0x30, 0xc0, 0x300, 0xc00, 0x3000, 0xc000, 0x30000, 0xc0000, 0x300000, 0xc00000, 0x3000000, 0xc000000, 0x30000000}); 72 | constexpr StatTable30 QRT_TABLE_30({0x2159df4a, 0x109134a, 0x1091348, 0x10114, 0x109134c, 0x3a203420, 0x1011c, 0x20004080, 0x109135c, 0x2005439c, 0x3a203400, 0x100400, 0x1015c, 0x3eb21930, 0x20004000, 0x20504c00, 0x109125c, 0x3b2b276c, 0x2005419c, 0x210450c0, 0x3a203000, 0x3e93186c, 0x100c00, 0x3aa23530, 0x1115c, 0x6b3286c, 0x3eb23930, 0xeb23930, 0x20000000, 0}); 73 | typedef Field Field30; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_31 77 | // 31 bit field 78 | typedef RecLinTrans StatTable31; 79 | typedef RecLinTrans DynTable31; 80 | constexpr StatTable31 SQR_TABLE_31({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x12, 0x48, 0x120, 0x480, 0x1200, 0x4800, 0x12000, 0x48000, 0x120000, 0x480000, 0x1200000, 0x4800000, 0x12000000, 0x48000000, 0x20000012}); 81 | constexpr StatTable31 QRT_TABLE_31({0, 0x10110, 0x10112, 0x15076e, 0x10116, 0x117130e, 0x150766, 0x4743fa0, 0x10106, 0x1121008, 0x117132e, 0x176b248e, 0x150726, 0x172a2c88, 0x4743f20, 0x7eb81e86, 0x10006, 0x20008, 0x1121208, 0x56b2c8e, 0x117172e, 0x133f1bae, 0x176b2c8e, 0x7f2a0c8e, 0x151726, 0x10000000, 0x172a0c88, 0x60000006, 0x4747f20, 0x3eb89e80, 0x7eb89e86}); 82 | typedef Field Field31; 83 | #endif 84 | 85 | #ifdef ENABLE_FIELD_INT_32 86 | // 32 bit field 87 | typedef RecLinTrans StatTable32; 88 | typedef RecLinTrans DynTable32; 89 | constexpr StatTable32 SQR_TABLE_32({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x8d, 0x234, 0x8d0, 0x2340, 0x8d00, 0x23400, 0x8d000, 0x234000, 0x8d0000, 0x2340000, 0x8d00000, 0x23400000, 0x8d000000, 0x3400011a, 0xd0000468, 0x40001037}); 90 | constexpr StatTable32 QRT_TABLE_32({0x54fd1264, 0xc26fcd64, 0xc26fcd66, 0x238a7462, 0xc26fcd62, 0x973bccaa, 0x238a746a, 0x77766712, 0xc26fcd72, 0xc1bdd556, 0x973bcc8a, 0x572a094c, 0x238a742a, 0xb693be84, 0x77766792, 0x9555c03e, 0xc26fcc72, 0x568419f8, 0xc1bdd756, 0x96c3d2ca, 0x973bc88a, 0x54861fdc, 0x572a014c, 0xb79badc4, 0x238a642a, 0xb9b99fe0, 0xb6939e84, 0xc519fa86, 0x77762792, 0, 0x9555403e, 0x377627ba}); 91 | typedef Field Field32; 92 | #endif 93 | } 94 | 95 | Sketch* ConstructGeneric4Bytes(int bits, int implementation) 96 | { 97 | switch (bits) { 98 | #ifdef ENABLE_FIELD_INT_25 99 | case 25: return new SketchImpl(implementation, 25); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_26 102 | case 26: return new SketchImpl(implementation, 26); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_27 105 | case 27: return new SketchImpl(implementation, 27); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_28 108 | case 28: return new SketchImpl(implementation, 28); 109 | #endif 110 | #ifdef ENABLE_FIELD_INT_29 111 | case 29: return new SketchImpl(implementation, 29); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_30 114 | case 30: return new SketchImpl(implementation, 30); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_31 117 | case 31: return new SketchImpl(implementation, 31); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_32 120 | case 32: return new SketchImpl(implementation, 32); 121 | #endif 122 | default: return nullptr; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/fields/generic_5bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_5) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_33 23 | // 33 bit field 24 | typedef RecLinTrans StatTable33; 25 | typedef RecLinTrans DynTable33; 26 | constexpr StatTable33 SQR_TABLE_33({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x802, 0x2008, 0x8020, 0x20080, 0x80200, 0x200800, 0x802000, 0x2008000, 0x8020000, 0x20080000, 0x80200000, 0x800401, 0x2001004, 0x8004010, 0x20010040, 0x80040100}); 27 | constexpr StatTable33 QRT_TABLE_33({0xba504dd4, 0x1e2798ef2, 0x1e2798ef0, 0x6698a4ec, 0x1e2798ef4, 0x1c7f1bef0, 0x6698a4e4, 0x16da1b384, 0x1e2798ee4, 0x661ca6ec, 0x1c7f1bed0, 0x1483b87a6, 0x6698a4a4, 0x800000, 0x16da1b304, 0x1a185101c, 0x1e2798fe4, 0xaa400954, 0x661ca4ec, 0x667caeec, 0x1c7f1bad0, 0x400800, 0x1483b8fa6, 0, 0x6698b4a4, 0x1c61da4b8, 0x802000, 0x16e5dadec, 0x16da1f304, 0x62fc8eec, 0x1a185901c, 0x1661da5ec, 0x1e2788fe4}); 28 | typedef Field Field33; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_34 32 | // 34 bit field 33 | typedef RecLinTrans StatTable34; 34 | typedef RecLinTrans DynTable34; 35 | constexpr StatTable34 SQR_TABLE_34({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x81, 0x204, 0x810, 0x2040, 0x8100, 0x20400, 0x81000, 0x204000, 0x810000, 0x2040000, 0x8100000, 0x20400000, 0x81000000, 0x204000000, 0x10000102, 0x40000408, 0x100001020}); 36 | constexpr StatTable34 QRT_TABLE_34({0x2f973a1f6, 0x40202, 0x40200, 0x348102060, 0x40204, 0x8000420, 0x348102068, 0x1092195c8, 0x40214, 0x3f6881b6e, 0x8000400, 0x3f810383e, 0x348102028, 0x340002068, 0x109219548, 0x24015a774, 0x40314, 0x3f050343e, 0x3f688196e, 0x3f81c3a3a, 0x8000000, 0x24031a560, 0x3f810303e, 0xb08c1a12, 0x348103028, 0xb2881906, 0x340000068, 0, 0x10921d548, 0x2e131e576, 0x240152774, 0x18921d55e, 0x50314, 0x14015271c}); 37 | typedef Field Field34; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_35 41 | // 35 bit field 42 | typedef RecLinTrans StatTable35; 43 | typedef RecLinTrans DynTable35; 44 | constexpr StatTable35 SQR_TABLE_35({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0xa, 0x28, 0xa0, 0x280, 0xa00, 0x2800, 0xa000, 0x28000, 0xa0000, 0x280000, 0xa00000, 0x2800000, 0xa000000, 0x28000000, 0xa0000000, 0x280000000, 0x200000005}); 45 | constexpr StatTable35 QRT_TABLE_35({0x5c2038114, 0x2bf547ee8, 0x2bf547eea, 0x2bf1074e8, 0x2bf547eee, 0x1883d0736, 0x2bf1074e0, 0x100420, 0x2bf547efe, 0x400800, 0x1883d0716, 0x5e90e4a0, 0x2bf1074a0, 0x4e70ac20, 0x1004a0, 0x2f060c880, 0x2bf547ffe, 0x37d55fffe, 0x400a00, 0x3372573de, 0x1883d0316, 0x700c20, 0x5e90eca0, 0x10604880, 0x2bf1064a0, 0x18f35377e, 0x4e708c20, 0x33f557ffe, 0x1044a0, 0x1bf557ffe, 0x2f0604880, 0x200000000, 0x2bf557ffe, 0, 0x37d57fffe}); 46 | typedef Field Field35; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_36 50 | // 36 bit field 51 | typedef RecLinTrans StatTable36; 52 | typedef RecLinTrans DynTable36; 53 | constexpr StatTable36 SQR_TABLE_36({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x201, 0x804, 0x2010, 0x8040, 0x20100, 0x80400, 0x201000, 0x804000, 0x2010000, 0x8040000, 0x20100000, 0x80400000, 0x201000000, 0x804000000, 0x10000402, 0x40001008, 0x100004020, 0x400010080}); 54 | constexpr StatTable36 QRT_TABLE_36({0x40200, 0x8b0526186, 0x8b0526184, 0x240001000, 0x8b0526180, 0xcb6894d94, 0x240001008, 0xdb6880c22, 0x8b0526190, 0x8000200, 0xcb6894db4, 0x500424836, 0x240001048, 0x406cb2834, 0xdb6880ca2, 0x241200008, 0x8b0526090, 0xdb05021a6, 0x8000000, 0xdb01829b2, 0xcb68949b4, 0x1001000, 0x500424036, 0x106116406, 0x240000048, 0xcb29968a4, 0x406cb0834, 0, 0xdb6884ca2, 0x110010516, 0x241208008, 0x430434520, 0x8b0536090, 0x41208040, 0xdb05221a6, 0xb6884d14}); 55 | typedef Field Field36; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_37 59 | // 37 bit field 60 | typedef RecLinTrans StatTable37; 61 | typedef RecLinTrans DynTable37; 62 | constexpr StatTable37 SQR_TABLE_37({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0xa6, 0x298, 0xa60, 0x2980, 0xa600, 0x29800, 0xa6000, 0x298000, 0xa60000, 0x2980000, 0xa600000, 0x29800000, 0xa6000000, 0x298000000, 0xa60000000, 0x980000053, 0x60000011f, 0x180000047c}); 63 | constexpr StatTable37 QRT_TABLE_37({0xa3c62e7ba, 0xdc7a0c16a, 0xdc7a0c168, 0x12f7484546, 0xdc7a0c16c, 0xa9803a20, 0x12f748454e, 0xda07064a4, 0xdc7a0c17c, 0x123908de8e, 0xa9803a00, 0x122a888a8e, 0x12f748450e, 0x6790add8, 0xda0706424, 0x12e0a0384c, 0xdc7a0c07c, 0xcb28a2c2, 0x123908dc8e, 0xd09f85e86, 0xa9803e00, 0x124d682b6e, 0x122a88828e, 0x1738711a, 0x12f748550e, 0x73035b8, 0x67908dd8, 0xa0702438, 0xda0702424, 0xe0a0b860, 0x12e0a0b84c, 0x1c7a1c060, 0xdc7a1c07c, 0, 0xcb2aa2c2, 0x100000002c, 0x12390cdc8e}); 64 | typedef Field Field37; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_38 68 | // 38 bit field 69 | typedef RecLinTrans StatTable38; 70 | typedef RecLinTrans DynTable38; 71 | constexpr StatTable38 SQR_TABLE_38({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x63, 0x18c, 0x630, 0x18c0, 0x6300, 0x18c00, 0x63000, 0x18c000, 0x630000, 0x18c0000, 0x6300000, 0x18c00000, 0x63000000, 0x18c000000, 0x630000000, 0x18c0000000, 0x2300000063, 0xc0000014a, 0x3000000528}); 72 | constexpr StatTable38 QRT_TABLE_38({0x34b0ac6430, 0x2223262fa, 0x2223262f8, 0x35554405fe, 0x2223262fc, 0x355514098a, 0x35554405f6, 0x400840, 0x2223262ec, 0x1777726532, 0x35551409aa, 0x15c06fc0, 0x35554405b6, 0x1f5303fec, 0x4008c0, 0x236a21030, 0x2223263ec, 0x1a9008c00, 0x1777726732, 0x3692c60ab6, 0x3555140daa, 0x15556007ee, 0x15c067c0, 0x14a0b030f2, 0x35554415b6, 0x227c06d168, 0x1f5301fec, 0x16c3928fc2, 0x4048c0, 0x3a942c4c0, 0x236a29030, 0x1636a2902e, 0x2223363ec, 0x3a6e898276, 0x1a9028c00, 0x6de74eb2c, 0x1777766732, 0}); 73 | typedef Field Field38; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_39 77 | // 39 bit field 78 | typedef RecLinTrans StatTable39; 79 | typedef RecLinTrans DynTable39; 80 | constexpr StatTable39 SQR_TABLE_39({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x22, 0x88, 0x220, 0x880, 0x2200, 0x8800, 0x22000, 0x88000, 0x220000, 0x880000, 0x2200000, 0x8800000, 0x22000000, 0x88000000, 0x220000000, 0x880000000, 0x2200000000, 0x800000011, 0x2000000044}); 81 | constexpr StatTable39 QRT_TABLE_39({0x66b02a408c, 0x100420, 0x100422, 0x14206080, 0x100426, 0x5dccefab1c, 0x14206088, 0x9fc11e5b6, 0x100436, 0x5466bea62a, 0x5dccefab3c, 0x9aa110536, 0x142060c8, 0x54739ed6e2, 0x9fc11e536, 0xe7a82c080, 0x100536, 0x4002000, 0x5466bea42a, 0x6a4022000, 0x5dccefaf3c, 0x9e8118536, 0x9aa110d36, 0x5680e080, 0x142070c8, 0x7d293c5b6, 0x54739ef6e2, 0x8d680e080, 0x9fc11a536, 0x6d282c080, 0xe7a824080, 0x800000000, 0x110536, 0x2d680e080, 0x4022000, 0, 0x5466baa42a, 0x46b03a44aa, 0x6a40a2000}); 82 | typedef Field Field39; 83 | #endif 84 | 85 | #ifdef ENABLE_FIELD_INT_40 86 | // 40 bit field 87 | typedef RecLinTrans StatTable40; 88 | typedef RecLinTrans DynTable40; 89 | constexpr StatTable40 SQR_TABLE_40({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x39, 0xe4, 0x390, 0xe40, 0x3900, 0xe400, 0x39000, 0xe4000, 0x390000, 0xe40000, 0x3900000, 0xe400000, 0x39000000, 0xe4000000, 0x390000000, 0xe40000000, 0x3900000000, 0xe400000000, 0x900000004b, 0x400000015e}); 90 | constexpr StatTable40 QRT_TABLE_40({0x624b3cecc, 0xbc5c3f4c6, 0xbc5c3f4c4, 0xde1603e2c, 0xbc5c3f4c0, 0xaabec06cea, 0xde1603e24, 0x6cd9f724c2, 0xbc5c3f4d0, 0xcde1743818, 0xaabec06cca, 0xa138c314ca, 0xde1603e64, 0xaafc00f01a, 0x6cd9f72442, 0xcdca11bb4, 0xbc5c3f5d0, 0xa00002001a, 0xcde1743a18, 0xdf1407b90, 0xaabec068ca, 0xc043b482c8, 0xa138c31cca, 0xcb86977e3c, 0xde1602e64, 0x604596a326, 0xaafc00d01a, 0xcc1c165d0, 0x6cd9f76442, 0x673c94da26, 0xcdca19bb4, 0x67c0940a26, 0xbc5c2f5d0, 0xa4dca19bae, 0xa00000001a, 0x1bc5c2f5d0, 0xcde1703a18, 0, 0xdf1487b90, 0x8df1487b8a}); 91 | typedef Field Field40; 92 | #endif 93 | } 94 | 95 | Sketch* ConstructGeneric5Bytes(int bits, int implementation) 96 | { 97 | switch (bits) { 98 | #ifdef ENABLE_FIELD_INT_33 99 | case 33: return new SketchImpl(implementation, 33); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_34 102 | case 34: return new SketchImpl(implementation, 34); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_35 105 | case 35: return new SketchImpl(implementation, 35); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_36 108 | case 36: return new SketchImpl(implementation, 36); 109 | #endif 110 | #ifdef ENABLE_FIELD_INT_37 111 | case 37: return new SketchImpl(implementation, 37); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_38 114 | case 38: return new SketchImpl(implementation, 38); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_39 117 | case 39: return new SketchImpl(implementation, 39); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_40 120 | case 40: return new SketchImpl(implementation, 40); 121 | #endif 122 | default: return nullptr; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/fields/generic_6bytes.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | /* This file was substantially auto-generated by doc/gen_params.sage. */ 8 | #include "../fielddefines.h" 9 | 10 | #if defined(ENABLE_FIELD_BYTES_INT_6) 11 | 12 | #include "generic_common_impl.h" 13 | 14 | #include "../lintrans.h" 15 | #include "../sketch_impl.h" 16 | 17 | #endif 18 | 19 | #include "../sketch.h" 20 | 21 | namespace { 22 | #ifdef ENABLE_FIELD_INT_41 23 | // 41 bit field 24 | typedef RecLinTrans StatTable41; 25 | typedef RecLinTrans DynTable41; 26 | constexpr StatTable41 SQR_TABLE_41({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x12, 0x48, 0x120, 0x480, 0x1200, 0x4800, 0x12000, 0x48000, 0x120000, 0x480000, 0x1200000, 0x4800000, 0x12000000, 0x48000000, 0x120000000, 0x480000000, 0x1200000000, 0x4800000000, 0x12000000000, 0x8000000012}); 27 | constexpr StatTable41 QRT_TABLE_41({0, 0x1599a5e0b0, 0x1599a5e0b2, 0x105c119e0, 0x1599a5e0b6, 0x1a2030452a6, 0x105c119e8, 0x1a307c55b2e, 0x1599a5e0a6, 0x1ee3f47bc8e, 0x1a203045286, 0x400808, 0x105c119a8, 0x1a3038573a6, 0x1a307c55bae, 0x4d2882a520, 0x1599a5e1a6, 0x1ffbaa0b720, 0x1ee3f47be8e, 0x4d68c22528, 0x1a203045686, 0x200006, 0x400008, 0x1b79a21b200, 0x105c109a8, 0x1ef3886a526, 0x1a3038553a6, 0x1b692209200, 0x1a307c51bae, 0x5d99a4e1a6, 0x4d28822520, 0x185e109ae, 0x1599a4e1a6, 0x4e3f43be88, 0x1ffbaa2b720, 0x4000000000, 0x1ee3f43be8e, 0x18000000006, 0x4d68ca2528, 0xa203145680, 0x1a203145686}); 28 | typedef Field Field41; 29 | #endif 30 | 31 | #ifdef ENABLE_FIELD_INT_42 32 | // 42 bit field 33 | typedef RecLinTrans StatTable42; 34 | typedef RecLinTrans DynTable42; 35 | constexpr StatTable42 SQR_TABLE_42({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x81, 0x204, 0x810, 0x2040, 0x8100, 0x20400, 0x81000, 0x204000, 0x810000, 0x2040000, 0x8100000, 0x20400000, 0x81000000, 0x204000000, 0x810000000, 0x2040000000, 0x8100000000, 0x20400000000, 0x1000000102, 0x4000000408, 0x10000001020}); 36 | constexpr StatTable42 QRT_TABLE_42({0x810200080, 0x120810806, 0x120810804, 0x1068c1a1000, 0x120810800, 0x34005023008, 0x1068c1a1008, 0x800004080, 0x120810810, 0x162818a10, 0x34005023028, 0x42408a14, 0x1068c1a1048, 0x1001040, 0x800004000, 0xb120808906, 0x120810910, 0x34000020068, 0x162818810, 0x68c021400, 0x34005023428, 0x10004000, 0x42408214, 0x162418214, 0x1068c1a0048, 0xb002018116, 0x1003040, 0x10008180448, 0x800000000, 0x62c08b04, 0xb120800906, 0x2408d1a3060, 0x120800910, 0x34401003028, 0x34000000068, 0, 0x162858810, 0xa042058116, 0x68c0a1400, 0x8162858806, 0x34005123428, 0x3068c0a1468}); 37 | typedef Field Field42; 38 | #endif 39 | 40 | #ifdef ENABLE_FIELD_INT_43 41 | // 43 bit field 42 | typedef RecLinTrans StatTable43; 43 | typedef RecLinTrans DynTable43; 44 | constexpr StatTable43 SQR_TABLE_43({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0xb2, 0x2c8, 0xb20, 0x2c80, 0xb200, 0x2c800, 0xb2000, 0x2c8000, 0xb20000, 0x2c80000, 0xb200000, 0x2c800000, 0xb2000000, 0x2c8000000, 0xb20000000, 0x2c80000000, 0xb200000000, 0x2c800000000, 0x32000000059, 0x4800000013d, 0x20000000446}); 45 | constexpr StatTable43 QRT_TABLE_43({0x2bccc2d6f6c, 0x4bccc2d6f54, 0x4bccc2d6f56, 0x7cc7bc61df0, 0x4bccc2d6f52, 0x7d13b404b10, 0x7cc7bc61df8, 0x37456e9ac5a, 0x4bccc2d6f42, 0x4e042c6a6, 0x7d13b404b30, 0x4a56de9ef4c, 0x7cc7bc61db8, 0x14bc18d8e, 0x37456e9acda, 0x7c89f84fb1e, 0x4bccc2d6e42, 0x7ffae40d210, 0x4e042c4a6, 0x366f45dd06, 0x7d13b404f30, 0x496fcaf8cca, 0x4a56de9e74c, 0x370b62b6af4, 0x7cc7bc60db8, 0x1498185a8, 0x14bc1ad8e, 0x7e602c46a98, 0x37456e9ecda, 0x36ccc2c6e74, 0x7c89f847b1e, 0x7e27d06d516, 0x4bccc2c6e42, 0x7f93302c396, 0x7ffae42d210, 0x3dd3440706, 0x4e046c4a6, 0x78bbc09da36, 0x366f4ddd06, 0, 0x7d13b504f30, 0x8bbc09da00, 0x496fc8f8cca}); 46 | typedef Field Field43; 47 | #endif 48 | 49 | #ifdef ENABLE_FIELD_INT_44 50 | // 44 bit field 51 | typedef RecLinTrans StatTable44; 52 | typedef RecLinTrans DynTable44; 53 | constexpr StatTable44 SQR_TABLE_44({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0x21, 0x84, 0x210, 0x840, 0x2100, 0x8400, 0x21000, 0x84000, 0x210000, 0x840000, 0x2100000, 0x8400000, 0x21000000, 0x84000000, 0x210000000, 0x840000000, 0x2100000000, 0x8400000000, 0x21000000000, 0x84000000000, 0x10000000042, 0x40000000108}); 54 | constexpr StatTable44 QRT_TABLE_44({0xf05334f4f6e, 0x4002016, 0x4002014, 0xf04350e6246, 0x4002010, 0x4935b379a26, 0xf04350e624e, 0xf84250c228e, 0x4002000, 0xf04300e521e, 0x4935b379a06, 0xb966838dd48, 0xf04350e620e, 0xf7b8b80feda, 0xf84250c220e, 0xf972e097d5e, 0x4002100, 0x8000020000, 0xf04300e501e, 0x430025000, 0x4935b379e06, 0xf976a09dc5e, 0xb966838d548, 0xf84218c029a, 0xf04350e720e, 0x4925f36bf06, 0xf7b8b80deda, 0xb047d3ee758, 0xf84250c620e, 0xf80350e720e, 0xf972e09fd5e, 0x8091825284, 0x4012100, 0x9015063210, 0x8000000000, 0xff31a028c5e, 0xf04300a501e, 0x44340b7100, 0x4300a5000, 0, 0x4935b279e06, 0xa976b2dce18, 0xf976a29dc5e, 0x8935b279e18}); 55 | typedef Field Field44; 56 | #endif 57 | 58 | #ifdef ENABLE_FIELD_INT_45 59 | // 45 bit field 60 | typedef RecLinTrans StatTable45; 61 | typedef RecLinTrans DynTable45; 62 | constexpr StatTable45 SQR_TABLE_45({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0x100000000000, 0x36, 0xd8, 0x360, 0xd80, 0x3600, 0xd800, 0x36000, 0xd8000, 0x360000, 0xd80000, 0x3600000, 0xd800000, 0x36000000, 0xd8000000, 0x360000000, 0xd80000000, 0x3600000000, 0xd800000000, 0x36000000000, 0xd8000000000, 0x16000000001b, 0x18000000005a}); 63 | constexpr StatTable45 QRT_TABLE_45({0xede34e3e0fc, 0x1554148191aa, 0x1554148191a8, 0x1767be1dc4a6, 0x1554148191ac, 0x26bd4931492, 0x1767be1dc4ae, 0x233ab9c454a, 0x1554148191bc, 0x16939e8bb3dc, 0x26bd49314b2, 0x3c6ca8bac52, 0x1767be1dc4ee, 0x16caa5054c16, 0x233ab9c45ca, 0x14a1649628bc, 0x1554148190bc, 0x3c382881252, 0x16939e8bb1dc, 0x3c7ca0aa160, 0x26bd49310b2, 0x27f40158000, 0x3c6ca8ba452, 0x173fc092853c, 0x1767be1dd4ee, 0x16cbe284f25c, 0x16caa5056c16, 0x155559002f96, 0x233ab9c05ca, 0x26eb8908b32, 0x14a16496a8bc, 0x15440885333c, 0x1554148090bc, 0x17d60702e0, 0x3c3828a1252, 0x54548d10b2, 0x16939e8fb1dc, 0x3ac1e81b1d2, 0x3c7ca02a160, 0x166bd48310bc, 0x26bd48310b2, 0, 0x27f40358000, 0x10000000000e, 0x3c6cacba452}); 64 | typedef Field Field45; 65 | #endif 66 | 67 | #ifdef ENABLE_FIELD_INT_46 68 | // 46 bit field 69 | typedef RecLinTrans StatTable46; 70 | typedef RecLinTrans DynTable46; 71 | constexpr StatTable46 SQR_TABLE_46({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0x100000000000, 0x3, 0xc, 0x30, 0xc0, 0x300, 0xc00, 0x3000, 0xc000, 0x30000, 0xc0000, 0x300000, 0xc00000, 0x3000000, 0xc000000, 0x30000000, 0xc0000000, 0x300000000, 0xc00000000, 0x3000000000, 0xc000000000, 0x30000000000, 0xc0000000000, 0x300000000000}); 72 | constexpr StatTable46 QRT_TABLE_46({0x211c4fd486ba, 0x100104a, 0x1001048, 0x104d0492d4, 0x100104c, 0x20005040c820, 0x104d0492dc, 0x40008080, 0x100105c, 0x24835068ce00, 0x20005040c800, 0x200000400800, 0x104d04929c, 0x100904325c, 0x40008000, 0x25da9e77daf0, 0x100115c, 0x1184e1696f0, 0x24835068cc00, 0x24825169dd5c, 0x20005040cc00, 0x3ea3241c60c0, 0x200000400000, 0x211c4e5496f0, 0x104d04829c, 0x20005340d86c, 0x100904125c, 0x24835968de5c, 0x4000c000, 0x6400a0c0, 0x25da9e775af0, 0x118cf1687ac, 0x101115c, 0x1ea1745cacc0, 0x1184e1496f0, 0x20181e445af0, 0x2483506ccc00, 0x20240060c0, 0x24825161dd5c, 0x1e21755dbd9c, 0x20005050cc00, 0x26a3746cacc0, 0x3ea3243c60c0, 0xea3243c60c0, 0x200000000000, 0}); 73 | typedef Field Field46; 74 | #endif 75 | 76 | #ifdef ENABLE_FIELD_INT_47 77 | // 47 bit field 78 | typedef RecLinTrans StatTable47; 79 | typedef RecLinTrans DynTable47; 80 | constexpr StatTable47 SQR_TABLE_47({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0x100000000000, 0x400000000000, 0x42, 0x108, 0x420, 0x1080, 0x4200, 0x10800, 0x42000, 0x108000, 0x420000, 0x1080000, 0x4200000, 0x10800000, 0x42000000, 0x108000000, 0x420000000, 0x1080000000, 0x4200000000, 0x10800000000, 0x42000000000, 0x108000000000, 0x420000000000, 0x80000000042, 0x200000000108}); 81 | constexpr StatTable47 QRT_TABLE_47({0, 0x1001040, 0x1001042, 0x1047043076, 0x1001046, 0x112471c241e, 0x104704307e, 0x4304e052168, 0x1001056, 0x10004000, 0x112471c243e, 0x172a09c949d6, 0x104704303e, 0x4002020, 0x4304e0521e8, 0x5400e220, 0x1001156, 0x172b08c85080, 0x10004200, 0x41200b0800, 0x112471c203e, 0x172f0cca50a0, 0x172a09c941d6, 0x7eb88a11c1d6, 0x104704203e, 0x1044042020, 0x4000020, 0x42001011156, 0x4304e0561e8, 0x172a28c95880, 0x54006220, 0x112931cc21e, 0x1011156, 0x53670f283e, 0x172b08ca5080, 0x7a80c414a03e, 0x10044200, 0x40000000000, 0x4120030800, 0x1928318801e, 0x112470c203e, 0x799283188000, 0x172f0cea50a0, 0x1eb88a91c1c8, 0x172a098941d6, 0x3ea8cc95e1f6, 0x7eb88a91c1d6}); 82 | typedef Field Field47; 83 | #endif 84 | 85 | #ifdef ENABLE_FIELD_INT_48 86 | // 48 bit field 87 | typedef RecLinTrans StatTable48; 88 | typedef RecLinTrans DynTable48; 89 | constexpr StatTable48 SQR_TABLE_48({0x1, 0x4, 0x10, 0x40, 0x100, 0x400, 0x1000, 0x4000, 0x10000, 0x40000, 0x100000, 0x400000, 0x1000000, 0x4000000, 0x10000000, 0x40000000, 0x100000000, 0x400000000, 0x1000000000, 0x4000000000, 0x10000000000, 0x40000000000, 0x100000000000, 0x400000000000, 0x2d, 0xb4, 0x2d0, 0xb40, 0x2d00, 0xb400, 0x2d000, 0xb4000, 0x2d0000, 0xb40000, 0x2d00000, 0xb400000, 0x2d000000, 0xb4000000, 0x2d0000000, 0xb40000000, 0x2d00000000, 0xb400000000, 0x2d000000000, 0xb4000000000, 0x2d0000000000, 0xb40000000000, 0xd0000000005a, 0x40000000011f}); 90 | constexpr StatTable48 QRT_TABLE_48({0xc00442c284f0, 0xc16b7fda410a, 0xc16b7fda4108, 0xada3b5c79fbe, 0xc16b7fda410c, 0x16f3c18d5b0, 0xada3b5c79fb6, 0x7090a381f64, 0xc16b7fda411c, 0xcafc15d179f8, 0x16f3c18d590, 0x6630880e534e, 0xada3b5c79ff6, 0xa13dd1f49826, 0x7090a381fe4, 0xb87560f6a74, 0xc16b7fda401c, 0xaaaaffff0012, 0xcafc15d17bf8, 0xaafd15f07bf6, 0x16f3c18d190, 0x60000020000e, 0x6630880e5b4e, 0xcb977fcb401c, 0xada3b5c78ff6, 0x6663420cad0, 0xa13dd1f4b826, 0xc0045fc2f41c, 0x7090a385fe4, 0x6762e24b834, 0xb87560fea74, 0xc6351fed241c, 0xc16b7fdb401c, 0x60065622ea7a, 0xaaaafffd0012, 0xdf9562bea74, 0xcafc15d57bf8, 0x6657ea057bea, 0xaafd15f87bf6, 0xa79329ddaa66, 0x16f3c08d190, 0xa39229f0aa66, 0x60000000000e, 0x175fb4468ad0, 0x6630884e5b4e, 0, 0xcb977f4b401c, 0x2630884e5b40}); 91 | typedef Field Field48; 92 | #endif 93 | } 94 | 95 | Sketch* ConstructGeneric6Bytes(int bits, int implementation) 96 | { 97 | switch (bits) { 98 | #ifdef ENABLE_FIELD_INT_41 99 | case 41: return new SketchImpl(implementation, 41); 100 | #endif 101 | #ifdef ENABLE_FIELD_INT_42 102 | case 42: return new SketchImpl(implementation, 42); 103 | #endif 104 | #ifdef ENABLE_FIELD_INT_43 105 | case 43: return new SketchImpl(implementation, 43); 106 | #endif 107 | #ifdef ENABLE_FIELD_INT_44 108 | case 44: return new SketchImpl(implementation, 44); 109 | #endif 110 | #ifdef ENABLE_FIELD_INT_45 111 | case 45: return new SketchImpl(implementation, 45); 112 | #endif 113 | #ifdef ENABLE_FIELD_INT_46 114 | case 46: return new SketchImpl(implementation, 46); 115 | #endif 116 | #ifdef ENABLE_FIELD_INT_47 117 | case 47: return new SketchImpl(implementation, 47); 118 | #endif 119 | #ifdef ENABLE_FIELD_INT_48 120 | case 48: return new SketchImpl(implementation, 48); 121 | #endif 122 | default: return nullptr; 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/fields/generic_common_impl.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_FIELDS_GENERIC_COMMON_IMPL_H_ 8 | #define _MINISKETCH_FIELDS_GENERIC_COMMON_IMPL_H_ 1 9 | 10 | #include 11 | 12 | #include "../int_utils.h" 13 | #include "../lintrans.h" 14 | 15 | namespace { 16 | 17 | /** Generic implementation for fields whose elements can be represented by an integer type. */ 18 | template class Field 19 | { 20 | typedef BitsInt O; 21 | typedef LFSR L; 22 | 23 | public: 24 | typedef I Elem; 25 | constexpr int Bits() const { return B; } 26 | 27 | constexpr inline Elem Mul2(Elem val) const { return L::Call(val); } 28 | 29 | class Multiplier 30 | { 31 | T table; 32 | public: 33 | explicit Multiplier(const Field&, Elem a) { table.template Build(a); } 34 | constexpr inline Elem operator()(Elem a) const { return table.template Map(a); } 35 | }; 36 | 37 | Elem Mul(Elem a, Elem b) const { return GFMul(a, b); } 38 | 39 | /** Compute the square of a. */ 40 | inline constexpr Elem Sqr(Elem a) const { return SQR->template Map(a); } 41 | 42 | /** Compute x such that x^2 + x = a (undefined result if no solution exists). */ 43 | inline constexpr Elem Qrt(Elem a) const { return QRT->template Map(a); } 44 | 45 | /** Compute the inverse of x1. */ 46 | Elem Inv(Elem a) const { return InvExtGCD(a); } 47 | 48 | /** Generate a random field element. */ 49 | Elem FromSeed(uint64_t seed) const { 50 | uint64_t k0 = 0x496e744669656c64ull; // "IntField" 51 | uint64_t k1 = seed; 52 | uint64_t count = ((uint64_t)B) << 32; 53 | Elem ret; 54 | do { 55 | ret = O::Mask(I(SipHash(k0, k1, count++))); 56 | } while(ret == 0); 57 | return ret; 58 | } 59 | 60 | Elem Deserialize(BitReader& in) const { return in.template Read(); } 61 | 62 | void Serialize(BitWriter& out, Elem val) const { out.template Write(val); } 63 | 64 | constexpr Elem FromUint64(uint64_t x) const { return O::Mask(I(x)); } 65 | constexpr uint64_t ToUint64(Elem val) const { return uint64_t(val); } 66 | }; 67 | 68 | } 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /src/int_utils.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_INT_UTILS_H_ 8 | #define _MINISKETCH_INT_UTILS_H_ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L 18 | # include 19 | #elif defined(_MSC_VER) 20 | # include 21 | #endif 22 | 23 | template 24 | static constexpr inline uint64_t Rot(uint64_t x) { return (x << bits) | (x >> (64 - bits)); } 25 | 26 | static inline void SipHashRound(uint64_t& v0, uint64_t& v1, uint64_t& v2, uint64_t& v3) { 27 | v0 += v1; v1 = Rot<13>(v1); v1 ^= v0; 28 | v0 = Rot<32>(v0); 29 | v2 += v3; v3 = Rot<16>(v3); v3 ^= v2; 30 | v0 += v3; v3 = Rot<21>(v3); v3 ^= v0; 31 | v2 += v1; v1 = Rot<17>(v1); v1 ^= v2; 32 | v2 = Rot<32>(v2); 33 | } 34 | 35 | inline uint64_t SipHash(uint64_t k0, uint64_t k1, uint64_t data) { 36 | uint64_t v0 = 0x736f6d6570736575ULL ^ k0; 37 | uint64_t v1 = 0x646f72616e646f6dULL ^ k1; 38 | uint64_t v2 = 0x6c7967656e657261ULL ^ k0; 39 | uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ data; 40 | SipHashRound(v0, v1, v2, v3); 41 | SipHashRound(v0, v1, v2, v3); 42 | v0 ^= data; 43 | v3 ^= 0x800000000000000ULL; 44 | SipHashRound(v0, v1, v2, v3); 45 | SipHashRound(v0, v1, v2, v3); 46 | v0 ^= 0x800000000000000ULL; 47 | v2 ^= 0xFF; 48 | SipHashRound(v0, v1, v2, v3); 49 | SipHashRound(v0, v1, v2, v3); 50 | SipHashRound(v0, v1, v2, v3); 51 | SipHashRound(v0, v1, v2, v3); 52 | return v0 ^ v1 ^ v2 ^ v3; 53 | } 54 | 55 | class BitWriter { 56 | unsigned char state = 0; 57 | int offset = 0; 58 | unsigned char* out; 59 | 60 | template 61 | inline void WriteInner(I val) { 62 | // We right shift by up to 8 bits below. Verify that's well defined for the type I. 63 | static_assert(std::numeric_limits::digits > 8, "BitWriter::WriteInner needs I > 8 bits"); 64 | int bits = BITS; 65 | if (bits + offset >= 8) { 66 | state |= ((val & ((I(1) << (8 - offset)) - 1)) << offset); 67 | *(out++) = state; 68 | val >>= (8 - offset); 69 | bits -= 8 - offset; 70 | offset = 0; 71 | state = 0; 72 | } 73 | while (bits >= 8) { 74 | *(out++) = val & 255; 75 | val >>= 8; 76 | bits -= 8; 77 | } 78 | state |= ((val & ((I(1) << bits) - 1)) << offset); 79 | offset += bits; 80 | } 81 | 82 | 83 | public: 84 | BitWriter(unsigned char* output) : out(output) {} 85 | 86 | template 87 | inline void Write(I val) { 88 | // If I is smaller than an unsigned int, invoke WriteInner with argument converted to unsigned. 89 | using compute_type = typename std::conditional< 90 | (std::numeric_limits::digits < std::numeric_limits::digits), 91 | unsigned, I>::type; 92 | return WriteInner(val); 93 | } 94 | 95 | inline void Flush() { 96 | if (offset) { 97 | *(out++) = state; 98 | state = 0; 99 | offset = 0; 100 | } 101 | } 102 | }; 103 | 104 | class BitReader { 105 | unsigned char state = 0; 106 | int offset = 0; 107 | const unsigned char* in; 108 | 109 | public: 110 | BitReader(const unsigned char* input) : in(input) {} 111 | 112 | template 113 | inline I Read() { 114 | int bits = BITS; 115 | if (offset >= bits) { 116 | I ret = state & ((1 << bits) - 1); 117 | state >>= bits; 118 | offset -= bits; 119 | return ret; 120 | } 121 | I val = state; 122 | int out = offset; 123 | while (out + 8 <= bits) { 124 | val |= ((I(*(in++))) << out); 125 | out += 8; 126 | } 127 | if (out < bits) { 128 | unsigned char c = *(in++); 129 | val |= (c & ((I(1) << (bits - out)) - 1)) << out; 130 | state = c >> (bits - out); 131 | offset = 8 - (bits - out); 132 | } else { 133 | state = 0; 134 | offset = 0; 135 | } 136 | return val; 137 | } 138 | }; 139 | 140 | /** Return a value of type I with its `bits` lowest bits set (bits must be > 0). */ 141 | template 142 | constexpr inline I Mask() { return ((I((I(-1)) << (std::numeric_limits::digits - BITS))) >> (std::numeric_limits::digits - BITS)); } 143 | 144 | /** Compute the smallest power of two that is larger than val. */ 145 | template 146 | static inline int CountBits(I val, int max) { 147 | #if defined(__cpp_lib_int_pow2) && __cpp_lib_int_pow2 >= 202002L 148 | // c++20 impl 149 | (void)max; 150 | return std::bit_width(val); 151 | #elif defined(_MSC_VER) 152 | (void)max; 153 | unsigned long index; 154 | unsigned char ret; 155 | if (std::numeric_limits::digits <= 32) { 156 | ret = _BitScanReverse(&index, val); 157 | } else { 158 | ret = _BitScanReverse64(&index, val); 159 | } 160 | if (!ret) return 0; 161 | return index + 1; 162 | #elif defined(HAVE_CLZ) 163 | (void)max; 164 | if (val == 0) return 0; 165 | if (std::numeric_limits::digits >= std::numeric_limits::digits) { 166 | return std::numeric_limits::digits - __builtin_clz(val); 167 | } else if (std::numeric_limits::digits >= std::numeric_limits::digits) { 168 | return std::numeric_limits::digits - __builtin_clzl(val); 169 | } else { 170 | return std::numeric_limits::digits - __builtin_clzll(val); 171 | } 172 | #else 173 | while (max && (val >> (max - 1) == 0)) --max; 174 | return max; 175 | #endif 176 | } 177 | 178 | template 179 | class BitsInt { 180 | private: 181 | static_assert(std::is_integral::value && std::is_unsigned::value, "BitsInt requires an unsigned integer type"); 182 | static_assert(BITS > 0 && BITS <= std::numeric_limits::digits, "BitsInt requires 1 <= Bits <= representation type size"); 183 | 184 | static constexpr I MASK = Mask(); 185 | 186 | public: 187 | 188 | typedef I Repr; 189 | 190 | static constexpr int SIZE = BITS; 191 | 192 | static void inline Swap(I& a, I& b) { 193 | std::swap(a, b); 194 | } 195 | 196 | static constexpr inline bool IsZero(I a) { return a == 0; } 197 | static constexpr inline bool IsOne(I a) { return a == 1; } 198 | static constexpr inline I Mask(I val) { return val & MASK; } 199 | static constexpr inline I Shift(I val, int bits) { return ((val << bits) & MASK); } 200 | static constexpr inline I UnsafeShift(I val, int bits) { return (val << bits); } 201 | 202 | template 203 | static constexpr inline int MidBits(I val) { 204 | static_assert(Count > 0, "BITSInt::MidBits needs Count > 0"); 205 | static_assert(Count + Offset <= BITS, "BitsInt::MidBits overflow of Count+Offset"); 206 | return (val >> Offset) & ((I(1) << Count) - 1); 207 | } 208 | 209 | template 210 | static constexpr inline int TopBits(I val) { 211 | static_assert(Count > 0, "BitsInt::TopBits needs Count > 0"); 212 | static_assert(Count <= BITS, "BitsInt::TopBits needs Offset <= BITS"); 213 | return static_cast(val >> (BITS - Count)); 214 | } 215 | 216 | static inline constexpr I CondXorWith(I val, bool cond, I v) { 217 | return val ^ (-I(cond) & v); 218 | } 219 | 220 | template 221 | static inline constexpr I CondXorWith(I val, bool cond) { 222 | return val ^ (-I(cond) & MOD); 223 | } 224 | 225 | static inline int Bits(I val, int max) { return CountBits(val, max); } 226 | }; 227 | 228 | /** Class which implements a stateless LFSR for generic moduli. */ 229 | template 230 | struct LFSR { 231 | typedef typename F::Repr I; 232 | /** Shift a value `a` up once, treating it as an `N`-bit LFSR, with pattern `MOD`. */ 233 | static inline constexpr I Call(const I& a) { 234 | return F::template CondXorWith(F::Shift(a, 1), F::template TopBits<1>(a)); 235 | } 236 | }; 237 | 238 | /** Helper class for carryless multiplications. */ 239 | template struct GFMulHelper; 240 | template struct GFMulHelper 241 | { 242 | static inline constexpr I Run(const I& a, const I& b) { return I(0); } 243 | }; 244 | template struct GFMulHelper 245 | { 246 | static inline constexpr I Run(const I& a, const I& b) { return F::CondXorWith(GFMulHelper::Run(L::Call(a), b), F::template MidBits(b), a); } 247 | }; 248 | 249 | /** Compute the carry-less multiplication of a and b, with N bits, using L as LFSR type. */ 250 | template inline constexpr I GFMul(const I& a, const I& b) { return GFMulHelper::Run(a, b); } 251 | 252 | /** Compute the inverse of x using an extgcd algorithm. */ 253 | template 254 | inline I InvExtGCD(I x) 255 | { 256 | if (F::IsZero(x) || F::IsOne(x)) return x; 257 | I t(0), newt(1); 258 | I r(MOD), newr = x; 259 | int rlen = BITS + 1, newrlen = F::Bits(newr, BITS); 260 | while (newr) { 261 | int q = rlen - newrlen; 262 | r ^= F::Shift(newr, q); 263 | t ^= F::UnsafeShift(newt, q); 264 | rlen = F::Bits(r, rlen - 1); 265 | if (r < newr) { 266 | F::Swap(t, newt); 267 | F::Swap(r, newr); 268 | std::swap(rlen, newrlen); 269 | } 270 | } 271 | return t; 272 | } 273 | 274 | /** Compute the inverse of x1 using an exponentiation ladder. 275 | * 276 | * The `MUL` argument is a multiplication function, `SQR` is a squaring function, and the `SQRi` arguments 277 | * compute x**(2**i). 278 | */ 279 | template 280 | inline I InvLadder(I x1) 281 | { 282 | static constexpr int INV_EXP = BITS - 1; 283 | I x2 = (INV_EXP >= 2) ? MUL(SQR(x1), x1) : I(); 284 | I x4 = (INV_EXP >= 4) ? MUL(SQR2(x2), x2) : I(); 285 | I x8 = (INV_EXP >= 8) ? MUL(SQR4(x4), x4) : I(); 286 | I x16 = (INV_EXP >= 16) ? MUL(SQR8(x8), x8) : I(); 287 | I x32 = (INV_EXP >= 32) ? MUL(SQR16(x16), x16) : I(); 288 | I r; 289 | if (INV_EXP >= 32) { 290 | r = x32; 291 | } else if (INV_EXP >= 16) { 292 | r = x16; 293 | } else if (INV_EXP >= 8) { 294 | r = x8; 295 | } else if (INV_EXP >= 4) { 296 | r = x4; 297 | } else if (INV_EXP >= 2) { 298 | r = x2; 299 | } else { 300 | r = x1; 301 | } 302 | if (INV_EXP >= 32 && (INV_EXP & 16)) r = MUL(SQR16(r), x16); 303 | if (INV_EXP >= 16 && (INV_EXP & 8)) r = MUL(SQR8(r), x8); 304 | if (INV_EXP >= 8 && (INV_EXP & 4)) r = MUL(SQR4(r), x4); 305 | if (INV_EXP >= 4 && (INV_EXP & 2)) r = MUL(SQR2(r), x2); 306 | if (INV_EXP >= 2 && (INV_EXP & 1)) r = MUL(SQR(r), x1); 307 | return SQR(r); 308 | } 309 | 310 | #endif 311 | -------------------------------------------------------------------------------- /src/lintrans.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_LINTRANS_H_ 8 | #define _MINISKETCH_LINTRANS_H_ 9 | 10 | #include "int_utils.h" 11 | 12 | /** A type to represent integers in the type system. */ 13 | template struct Num {}; 14 | 15 | /** A Linear N-bit transformation over the field I. */ 16 | template class LinTrans { 17 | private: 18 | I table[1 << N]; 19 | public: 20 | LinTrans() = default; 21 | 22 | /* Construct a transformation over 3 to 8 bits, using the images of each bit. */ 23 | constexpr LinTrans(I a, I b) : table{I(0), I(a), I(b), I(a ^ b)} {} 24 | constexpr LinTrans(I a, I b, I c) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c)} {} 25 | constexpr LinTrans(I a, I b, I c, I d) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c), I(d), I(a ^ d), I(b ^ d), I(a ^ b ^ d), I(c ^ d), I(a ^ c ^ d), I(b ^ c ^ d), I(a ^ b ^ c ^ d)} {} 26 | constexpr LinTrans(I a, I b, I c, I d, I e) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c), I(d), I(a ^ d), I(b ^ d), I(a ^ b ^ d), I(c ^ d), I(a ^ c ^ d), I(b ^ c ^ d), I(a ^ b ^ c ^ d), I(e), I(a ^ e), I(b ^ e), I(a ^ b ^ e), I(c ^ e), I(a ^ c ^ e), I(b ^ c ^ e), I(a ^ b ^ c ^ e), I(d ^ e), I(a ^ d ^ e), I(b ^ d ^ e), I(a ^ b ^ d ^ e), I(c ^ d ^ e), I(a ^ c ^ d ^ e), I(b ^ c ^ d ^ e), I(a ^ b ^ c ^ d ^ e)} {} 27 | constexpr LinTrans(I a, I b, I c, I d, I e, I f) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c), I(d), I(a ^ d), I(b ^ d), I(a ^ b ^ d), I(c ^ d), I(a ^ c ^ d), I(b ^ c ^ d), I(a ^ b ^ c ^ d), I(e), I(a ^ e), I(b ^ e), I(a ^ b ^ e), I(c ^ e), I(a ^ c ^ e), I(b ^ c ^ e), I(a ^ b ^ c ^ e), I(d ^ e), I(a ^ d ^ e), I(b ^ d ^ e), I(a ^ b ^ d ^ e), I(c ^ d ^ e), I(a ^ c ^ d ^ e), I(b ^ c ^ d ^ e), I(a ^ b ^ c ^ d ^ e), I(f), I(a ^ f), I(b^ f), I(a ^ b ^ f), I(c^ f), I(a ^ c ^ f), I(b ^ c ^ f), I(a ^ b ^ c ^ f), I(d ^ f), I(a ^ d ^ f), I(b ^ d ^ f), I(a ^ b ^ d ^ f), I(c ^ d ^ f), I(a ^ c ^ d ^ f), I(b ^ c ^ d ^ f), I(a ^ b ^ c ^ d ^ f), I(e ^ f), I(a ^ e ^ f), I(b ^ e ^ f), I(a ^ b ^ e ^ f), I(c ^ e ^ f), I(a ^ c ^ e ^ f), I(b ^ c ^ e ^ f), I(a ^ b ^ c ^ e ^ f), I(d ^ e ^ f), I(a ^ d ^ e ^ f), I(b ^ d ^ e ^ f), I(a ^ b ^ d ^ e ^ f), I(c ^ d ^ e ^ f), I(a ^ c ^ d ^ e ^ f), I(b ^ c ^ d ^ e ^ f), I(a ^ b ^ c ^ d ^ e ^ f)} {} 28 | constexpr LinTrans(I a, I b, I c, I d, I e, I f, I g) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c), I(d), I(a ^ d), I(b ^ d), I(a ^ b ^ d), I(c ^ d), I(a ^ c ^ d), I(b ^ c ^ d), I(a ^ b ^ c ^ d), I(e), I(a ^ e), I(b ^ e), I(a ^ b ^ e), I(c ^ e), I(a ^ c ^ e), I(b ^ c ^ e), I(a ^ b ^ c ^ e), I(d ^ e), I(a ^ d ^ e), I(b ^ d ^ e), I(a ^ b ^ d ^ e), I(c ^ d ^ e), I(a ^ c ^ d ^ e), I(b ^ c ^ d ^ e), I(a ^ b ^ c ^ d ^ e), I(f), I(a ^ f), I(b^ f), I(a ^ b ^ f), I(c^ f), I(a ^ c ^ f), I(b ^ c ^ f), I(a ^ b ^ c ^ f), I(d ^ f), I(a ^ d ^ f), I(b ^ d ^ f), I(a ^ b ^ d ^ f), I(c ^ d ^ f), I(a ^ c ^ d ^ f), I(b ^ c ^ d ^ f), I(a ^ b ^ c ^ d ^ f), I(e ^ f), I(a ^ e ^ f), I(b ^ e ^ f), I(a ^ b ^ e ^ f), I(c ^ e ^ f), I(a ^ c ^ e ^ f), I(b ^ c ^ e ^ f), I(a ^ b ^ c ^ e ^ f), I(d ^ e ^ f), I(a ^ d ^ e ^ f), I(b ^ d ^ e ^ f), I(a ^ b ^ d ^ e ^ f), I(c ^ d ^ e ^ f), I(a ^ c ^ d ^ e ^ f), I(b ^ c ^ d ^ e ^ f), I(a ^ b ^ c ^ d ^ e ^ f), I(g), I(a ^ g), I(b ^ g), I(a ^ b ^ g), I(c ^ g), I(a ^ c ^ g), I(b ^ c ^ g), I(a ^ b ^ c ^ g), I(d ^ g), I(a ^ d ^ g), I(b ^ d ^ g), I(a ^ b ^ d ^ g), I(c ^ d ^ g), I(a ^ c ^ d ^ g), I(b ^ c ^ d ^ g), I(a ^ b ^ c ^ d ^ g), I(e ^ g), I(a ^ e ^ g), I(b ^ e ^ g), I(a ^ b ^ e ^ g), I(c ^ e ^ g), I(a ^ c ^ e ^ g), I(b ^ c ^ e ^ g), I(a ^ b ^ c ^ e ^ g), I(d ^ e ^ g), I(a ^ d ^ e ^ g), I(b ^ d ^ e ^ g), I(a ^ b ^ d ^ e ^ g), I(c ^ d ^ e ^ g), I(a ^ c ^ d ^ e ^ g), I(b ^ c ^ d ^ e ^ g), I(a ^ b ^ c ^ d ^ e ^ g), I(f ^ g), I(a ^ f ^ g), I(b^ f ^ g), I(a ^ b ^ f ^ g), I(c^ f ^ g), I(a ^ c ^ f ^ g), I(b ^ c ^ f ^ g), I(a ^ b ^ c ^ f ^ g), I(d ^ f ^ g), I(a ^ d ^ f ^ g), I(b ^ d ^ f ^ g), I(a ^ b ^ d ^ f ^ g), I(c ^ d ^ f ^ g), I(a ^ c ^ d ^ f ^ g), I(b ^ c ^ d ^ f ^ g), I(a ^ b ^ c ^ d ^ f ^ g), I(e ^ f ^ g), I(a ^ e ^ f ^ g), I(b ^ e ^ f ^ g), I(a ^ b ^ e ^ f ^ g), I(c ^ e ^ f ^ g), I(a ^ c ^ e ^ f ^ g), I(b ^ c ^ e ^ f ^ g), I(a ^ b ^ c ^ e ^ f ^ g), I(d ^ e ^ f ^ g), I(a ^ d ^ e ^ f ^ g), I(b ^ d ^ e ^ f ^ g), I(a ^ b ^ d ^ e ^ f ^ g), I(c ^ d ^ e ^ f ^ g), I(a ^ c ^ d ^ e ^ f ^ g), I(b ^ c ^ d ^ e ^ f ^ g), I(a ^ b ^ c ^ d ^ e ^ f ^ g)} {} 29 | constexpr LinTrans(I a, I b, I c, I d, I e, I f, I g, I h) : table{I(0), I(a), I(b), I(a ^ b), I(c), I(a ^ c), I(b ^ c), I(a ^ b ^ c), I(d), I(a ^ d), I(b ^ d), I(a ^ b ^ d), I(c ^ d), I(a ^ c ^ d), I(b ^ c ^ d), I(a ^ b ^ c ^ d), I(e), I(a ^ e), I(b ^ e), I(a ^ b ^ e), I(c ^ e), I(a ^ c ^ e), I(b ^ c ^ e), I(a ^ b ^ c ^ e), I(d ^ e), I(a ^ d ^ e), I(b ^ d ^ e), I(a ^ b ^ d ^ e), I(c ^ d ^ e), I(a ^ c ^ d ^ e), I(b ^ c ^ d ^ e), I(a ^ b ^ c ^ d ^ e), I(f), I(a ^ f), I(b^ f), I(a ^ b ^ f), I(c^ f), I(a ^ c ^ f), I(b ^ c ^ f), I(a ^ b ^ c ^ f), I(d ^ f), I(a ^ d ^ f), I(b ^ d ^ f), I(a ^ b ^ d ^ f), I(c ^ d ^ f), I(a ^ c ^ d ^ f), I(b ^ c ^ d ^ f), I(a ^ b ^ c ^ d ^ f), I(e ^ f), I(a ^ e ^ f), I(b ^ e ^ f), I(a ^ b ^ e ^ f), I(c ^ e ^ f), I(a ^ c ^ e ^ f), I(b ^ c ^ e ^ f), I(a ^ b ^ c ^ e ^ f), I(d ^ e ^ f), I(a ^ d ^ e ^ f), I(b ^ d ^ e ^ f), I(a ^ b ^ d ^ e ^ f), I(c ^ d ^ e ^ f), I(a ^ c ^ d ^ e ^ f), I(b ^ c ^ d ^ e ^ f), I(a ^ b ^ c ^ d ^ e ^ f), I(g), I(a ^ g), I(b ^ g), I(a ^ b ^ g), I(c ^ g), I(a ^ c ^ g), I(b ^ c ^ g), I(a ^ b ^ c ^ g), I(d ^ g), I(a ^ d ^ g), I(b ^ d ^ g), I(a ^ b ^ d ^ g), I(c ^ d ^ g), I(a ^ c ^ d ^ g), I(b ^ c ^ d ^ g), I(a ^ b ^ c ^ d ^ g), I(e ^ g), I(a ^ e ^ g), I(b ^ e ^ g), I(a ^ b ^ e ^ g), I(c ^ e ^ g), I(a ^ c ^ e ^ g), I(b ^ c ^ e ^ g), I(a ^ b ^ c ^ e ^ g), I(d ^ e ^ g), I(a ^ d ^ e ^ g), I(b ^ d ^ e ^ g), I(a ^ b ^ d ^ e ^ g), I(c ^ d ^ e ^ g), I(a ^ c ^ d ^ e ^ g), I(b ^ c ^ d ^ e ^ g), I(a ^ b ^ c ^ d ^ e ^ g), I(f ^ g), I(a ^ f ^ g), I(b^ f ^ g), I(a ^ b ^ f ^ g), I(c^ f ^ g), I(a ^ c ^ f ^ g), I(b ^ c ^ f ^ g), I(a ^ b ^ c ^ f ^ g), I(d ^ f ^ g), I(a ^ d ^ f ^ g), I(b ^ d ^ f ^ g), I(a ^ b ^ d ^ f ^ g), I(c ^ d ^ f ^ g), I(a ^ c ^ d ^ f ^ g), I(b ^ c ^ d ^ f ^ g), I(a ^ b ^ c ^ d ^ f ^ g), I(e ^ f ^ g), I(a ^ e ^ f ^ g), I(b ^ e ^ f ^ g), I(a ^ b ^ e ^ f ^ g), I(c ^ e ^ f ^ g), I(a ^ c ^ e ^ f ^ g), I(b ^ c ^ e ^ f ^ g), I(a ^ b ^ c ^ e ^ f ^ g), I(d ^ e ^ f ^ g), I(a ^ d ^ e ^ f ^ g), I(b ^ d ^ e ^ f ^ g), I(a ^ b ^ d ^ e ^ f ^ g), I(c ^ d ^ e ^ f ^ g), I(a ^ c ^ d ^ e ^ f ^ g), I(b ^ c ^ d ^ e ^ f ^ g), I(a ^ b ^ c ^ d ^ e ^ f ^ g), I(h), I(a ^ h), I(b ^ h), I(a ^ b ^ h), I(c ^ h), I(a ^ c ^ h), I(b ^ c ^ h), I(a ^ b ^ c ^ h), I(d ^ h), I(a ^ d ^ h), I(b ^ d ^ h), I(a ^ b ^ d ^ h), I(c ^ d ^ h), I(a ^ c ^ d ^ h), I(b ^ c ^ d ^ h), I(a ^ b ^ c ^ d ^ h), I(e ^ h), I(a ^ e ^ h), I(b ^ e ^ h), I(a ^ b ^ e ^ h), I(c ^ e ^ h), I(a ^ c ^ e ^ h), I(b ^ c ^ e ^ h), I(a ^ b ^ c ^ e ^ h), I(d ^ e ^ h), I(a ^ d ^ e ^ h), I(b ^ d ^ e ^ h), I(a ^ b ^ d ^ e ^ h), I(c ^ d ^ e ^ h), I(a ^ c ^ d ^ e ^ h), I(b ^ c ^ d ^ e ^ h), I(a ^ b ^ c ^ d ^ e ^ h), I(f ^ h), I(a ^ f ^ h), I(b^ f ^ h), I(a ^ b ^ f ^ h), I(c^ f ^ h), I(a ^ c ^ f ^ h), I(b ^ c ^ f ^ h), I(a ^ b ^ c ^ f ^ h), I(d ^ f ^ h), I(a ^ d ^ f ^ h), I(b ^ d ^ f ^ h), I(a ^ b ^ d ^ f ^ h), I(c ^ d ^ f ^ h), I(a ^ c ^ d ^ f ^ h), I(b ^ c ^ d ^ f ^ h), I(a ^ b ^ c ^ d ^ f ^ h), I(e ^ f ^ h), I(a ^ e ^ f ^ h), I(b ^ e ^ f ^ h), I(a ^ b ^ e ^ f ^ h), I(c ^ e ^ f ^ h), I(a ^ c ^ e ^ f ^ h), I(b ^ c ^ e ^ f ^ h), I(a ^ b ^ c ^ e ^ f ^ h), I(d ^ e ^ f ^ h), I(a ^ d ^ e ^ f ^ h), I(b ^ d ^ e ^ f ^ h), I(a ^ b ^ d ^ e ^ f ^ h), I(c ^ d ^ e ^ f ^ h), I(a ^ c ^ d ^ e ^ f ^ h), I(b ^ c ^ d ^ e ^ f ^ h), I(a ^ b ^ c ^ d ^ e ^ f ^ h), I(g ^ h), I(a ^ g ^ h), I(b ^ g ^ h), I(a ^ b ^ g ^ h), I(c ^ g ^ h), I(a ^ c ^ g ^ h), I(b ^ c ^ g ^ h), I(a ^ b ^ c ^ g ^ h), I(d ^ g ^ h), I(a ^ d ^ g ^ h), I(b ^ d ^ g ^ h), I(a ^ b ^ d ^ g ^ h), I(c ^ d ^ g ^ h), I(a ^ c ^ d ^ g ^ h), I(b ^ c ^ d ^ g ^ h), I(a ^ b ^ c ^ d ^ g ^ h), I(e ^ g ^ h), I(a ^ e ^ g ^ h), I(b ^ e ^ g ^ h), I(a ^ b ^ e ^ g ^ h), I(c ^ e ^ g ^ h), I(a ^ c ^ e ^ g ^ h), I(b ^ c ^ e ^ g ^ h), I(a ^ b ^ c ^ e ^ g ^ h), I(d ^ e ^ g ^ h), I(a ^ d ^ e ^ g ^ h), I(b ^ d ^ e ^ g ^ h), I(a ^ b ^ d ^ e ^ g ^ h), I(c ^ d ^ e ^ g ^ h), I(a ^ c ^ d ^ e ^ g ^ h), I(b ^ c ^ d ^ e ^ g ^ h), I(a ^ b ^ c ^ d ^ e ^ g ^ h), I(f ^ g ^ h), I(a ^ f ^ g ^ h), I(b^ f ^ g ^ h), I(a ^ b ^ f ^ g ^ h), I(c^ f ^ g ^ h), I(a ^ c ^ f ^ g ^ h), I(b ^ c ^ f ^ g ^ h), I(a ^ b ^ c ^ f ^ g ^ h), I(d ^ f ^ g ^ h), I(a ^ d ^ f ^ g ^ h), I(b ^ d ^ f ^ g ^ h), I(a ^ b ^ d ^ f ^ g ^ h), I(c ^ d ^ f ^ g ^ h), I(a ^ c ^ d ^ f ^ g ^ h), I(b ^ c ^ d ^ f ^ g ^ h), I(a ^ b ^ c ^ d ^ f ^ g ^ h), I(e ^ f ^ g ^ h), I(a ^ e ^ f ^ g ^ h), I(b ^ e ^ f ^ g ^ h), I(a ^ b ^ e ^ f ^ g ^ h), I(c ^ e ^ f ^ g ^ h), I(a ^ c ^ e ^ f ^ g ^ h), I(b ^ c ^ e ^ f ^ g ^ h), I(a ^ b ^ c ^ e ^ f ^ g ^ h), I(d ^ e ^ f ^ g ^ h), I(a ^ d ^ e ^ f ^ g ^ h), I(b ^ d ^ e ^ f ^ g ^ h), I(a ^ b ^ d ^ e ^ f ^ g ^ h), I(c ^ d ^ e ^ f ^ g ^ h), I(a ^ c ^ d ^ e ^ f ^ g ^ h), I(b ^ c ^ d ^ e ^ f ^ g ^ h), I(a ^ b ^ c ^ d ^ e ^ f ^ g ^ h)} {} 30 | 31 | /* Construct a transformation over 3 to 8 bits, using a pointer to the bit's images. */ 32 | constexpr LinTrans(const I* p, Num<2>) : LinTrans(I(p[0]), I(p[1])) {} 33 | constexpr LinTrans(const I* p, Num<3>) : LinTrans(I(p[0]), I(p[1]), I(p[2])) {} 34 | constexpr LinTrans(const I* p, Num<4>) : LinTrans(I(p[0]), I(p[1]), I(p[2]), I(p[3])) {} 35 | constexpr LinTrans(const I* p, Num<5>) : LinTrans(I(p[0]), I(p[1]), I(p[2]), I(p[3]), I(p[4])) {} 36 | constexpr LinTrans(const I* p, Num<6>) : LinTrans(I(p[0]), I(p[1]), I(p[2]), I(p[3]), I(p[4]), I(p[5])) {} 37 | constexpr LinTrans(const I* p, Num<7>) : LinTrans(I(p[0]), I(p[1]), I(p[2]), I(p[3]), I(p[4]), I(p[5]), I(p[6])) {} 38 | constexpr LinTrans(const I* p, Num<8>) : LinTrans(I(p[0]), I(p[1]), I(p[2]), I(p[3]), I(p[4]), I(p[5]), I(p[6]), I(p[7])) {} 39 | 40 | template 41 | inline I Build(Num<1>, I a) 42 | { 43 | table[0] = I(); table[1] = a; 44 | return a; 45 | } 46 | 47 | template 48 | inline I Build(Num<2>, I a) 49 | { 50 | I b = F(a); 51 | table[0] = I(); table[1] = a; table[2] = b; table[3] = a ^ b; 52 | return b; 53 | } 54 | 55 | template 56 | inline I Build(Num<3>, I a) 57 | { 58 | I b = F(a), c = F(b); 59 | table[0] = I(); table[1] = a; table[2] = b; table[3] = a ^ b; table[4] = c; table[5] = a ^ c; table[6] = b ^ c; table[7] = a ^ b ^ c; 60 | return c; 61 | } 62 | 63 | template 64 | inline I Build(Num<4>, I a) 65 | { 66 | I b = F(a), c = F(b), d = F(c); 67 | table[0] = I(); table[1] = a; table[2] = b; table[3] = a ^ b; table[4] = c; table[5] = a ^ c; table[6] = b ^ c; table[7] = a ^ b ^ c; 68 | table[8] = d; table[9] = a ^ d; table[10] = b ^ d; table[11] = a ^ b ^ d; table[12] = c ^ d; table[13] = a ^ c ^ d; table[14] = b ^ c ^ d; table[15] = a ^ b ^ c ^ d; 69 | return d; 70 | } 71 | 72 | template 73 | inline I Build(Num<5>, I a) 74 | { 75 | I b = F(a), c = F(b), d = F(c), e = F(d); 76 | table[0] = I(); table[1] = a; table[2] = b; table[3] = a ^ b; table[4] = c; table[5] = a ^ c; table[6] = b ^ c; table[7] = a ^ b ^ c; 77 | table[8] = d; table[9] = a ^ d; table[10] = b ^ d; table[11] = a ^ b ^ d; table[12] = c ^ d; table[13] = a ^ c ^ d; table[14] = b ^ c ^ d; table[15] = a ^ b ^ c ^ d; 78 | table[16] = e; table[17] = a ^ e; table[18] = b ^ e; table[19] = a ^ b ^ e; table[20] = c ^ e; table[21] = a ^ c ^ e; table[22] = b ^ c ^ e; table[23] = a ^ b ^ c ^ e; 79 | table[24] = d ^ e; table[25] = a ^ d ^ e; table[26] = b ^ d ^ e; table[27] = a ^ b ^ d ^ e; table[28] = c ^ d ^ e; table[29] = a ^ c ^ d ^ e; table[30] = b ^ c ^ d ^ e; table[31] = a ^ b ^ c ^ d ^ e; 80 | return e; 81 | } 82 | 83 | template 84 | inline I Build(Num<6>, I a) 85 | { 86 | I b = F(a), c = F(b), d = F(c), e = F(d), f = F(e); 87 | table[0] = I(); table[1] = a; table[2] = b; table[3] = a ^ b; table[4] = c; table[5] = a ^ c; table[6] = b ^ c; table[7] = a ^ b ^ c; 88 | table[8] = d; table[9] = a ^ d; table[10] = b ^ d; table[11] = a ^ b ^ d; table[12] = c ^ d; table[13] = a ^ c ^ d; table[14] = b ^ c ^ d; table[15] = a ^ b ^ c ^ d; 89 | table[16] = e; table[17] = a ^ e; table[18] = b ^ e; table[19] = a ^ b ^ e; table[20] = c ^ e; table[21] = a ^ c ^ e; table[22] = b ^ c ^ e; table[23] = a ^ b ^ c ^ e; 90 | table[24] = d ^ e; table[25] = a ^ d ^ e; table[26] = b ^ d ^ e; table[27] = a ^ b ^ d ^ e; table[28] = c ^ d ^ e; table[29] = a ^ c ^ d ^ e; table[30] = b ^ c ^ d ^ e; table[31] = a ^ b ^ c ^ d ^ e; 91 | table[32] = f; table[33] = a ^ f; table[34] = b ^ f; table[35] = a ^ b ^ f; table[36] = c ^ f; table[37] = a ^ c ^ f; table[38] = b ^ c ^ f; table[39] = a ^ b ^ c ^ f; 92 | table[40] = d ^ f; table[41] = a ^ d ^ f; table[42] = b ^ d ^ f; table[43] = a ^ b ^ d ^ f; table[44] = c ^ d ^ f; table[45] = a ^ c ^ d ^ f; table[46] = b ^ c ^ d ^ f; table[47] = a ^ b ^ c ^ d ^ f; 93 | table[48] = e ^ f; table[49] = a ^ e ^ f; table[50] = b ^ e ^ f; table[51] = a ^ b ^ e ^ f; table[52] = c ^ e ^ f; table[53] = a ^ c ^ e ^ f; table[54] = b ^ c ^ e ^ f; table[55] = a ^ b ^ c ^ e ^ f; 94 | table[56] = d ^ e ^ f; table[57] = a ^ d ^ e ^ f; table[58] = b ^ d ^ e ^ f; table[59] = a ^ b ^ d ^ e ^ f; table[60] = c ^ d ^ e ^ f; table[61] = a ^ c ^ d ^ e ^ f; table[62] = b ^ c ^ d ^ e ^ f; table[63] = a ^ b ^ c ^ d ^ e ^ f; 95 | return f; 96 | } 97 | 98 | template 99 | inline I constexpr Map(I a) const { return table[O::template MidBits(a)]; } 100 | 101 | template 102 | inline I constexpr TopMap(I a) const { static_assert(P + N == O::SIZE, "TopMap inconsistency"); return table[O::template TopBits(a)]; } 103 | }; 104 | 105 | 106 | /** A linear transformation constructed using LinTrans tables for sections of bits. */ 107 | template class RecLinTrans; 108 | 109 | template class RecLinTrans { 110 | LinTrans trans; 111 | public: 112 | static constexpr int BITS = N; 113 | constexpr RecLinTrans(const I* p, Num) : trans(p, Num()) {} 114 | constexpr RecLinTrans() = default; 115 | constexpr RecLinTrans(const I (&init)[BITS]) : RecLinTrans(init, Num()) {} 116 | 117 | template 118 | inline I constexpr Map(I a) const { return trans.template TopMap(a); } 119 | 120 | template 121 | inline void Build(I a) { trans.template Build(Num(), a); } 122 | }; 123 | 124 | template class RecLinTrans { 125 | LinTrans trans; 126 | RecLinTrans rec; 127 | public: 128 | static constexpr int BITS = RecLinTrans::BITS + N; 129 | constexpr RecLinTrans(const I* p, Num) : trans(p, Num()), rec(p + N, Num()) {} 130 | constexpr RecLinTrans() = default; 131 | constexpr RecLinTrans(const I (&init)[BITS]) : RecLinTrans(init, Num()) {} 132 | 133 | template 134 | inline I constexpr Map(I a) const { return trans.template Map(a) ^ rec.template Map(a); } 135 | 136 | template 137 | inline void Build(I a) { I n = trans.template Build(Num(), a); rec.template Build(F(n)); } 138 | }; 139 | 140 | /** The identity transformation. */ 141 | class IdTrans { 142 | public: 143 | template 144 | inline I constexpr Map(I a) const { return a; } 145 | }; 146 | 147 | /** A singleton for the identity transformation. */ 148 | constexpr IdTrans ID_TRANS{}; 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /src/minisketch.cpp: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | 8 | #include 9 | 10 | #define MINISKETCH_BUILD 11 | #ifdef _MINISKETCH_H_ 12 | # error "minisketch.h cannot be included before minisketch.cpp" 13 | #endif 14 | #include "../include/minisketch.h" 15 | 16 | #include "false_positives.h" 17 | #include "fielddefines.h" 18 | #include "sketch.h" 19 | 20 | #ifdef HAVE_CLMUL 21 | # ifdef _MSC_VER 22 | # include 23 | # else 24 | # include 25 | # endif 26 | #endif 27 | 28 | Sketch* ConstructGeneric1Byte(int bits, int implementation); 29 | Sketch* ConstructGeneric2Bytes(int bits, int implementation); 30 | Sketch* ConstructGeneric3Bytes(int bits, int implementation); 31 | Sketch* ConstructGeneric4Bytes(int bits, int implementation); 32 | Sketch* ConstructGeneric5Bytes(int bits, int implementation); 33 | Sketch* ConstructGeneric6Bytes(int bits, int implementation); 34 | Sketch* ConstructGeneric7Bytes(int bits, int implementation); 35 | Sketch* ConstructGeneric8Bytes(int bits, int implementation); 36 | 37 | #ifdef HAVE_CLMUL 38 | Sketch* ConstructClMul1Byte(int bits, int implementation); 39 | Sketch* ConstructClMul2Bytes(int bits, int implementation); 40 | Sketch* ConstructClMul3Bytes(int bits, int implementation); 41 | Sketch* ConstructClMul4Bytes(int bits, int implementation); 42 | Sketch* ConstructClMul5Bytes(int bits, int implementation); 43 | Sketch* ConstructClMul6Bytes(int bits, int implementation); 44 | Sketch* ConstructClMul7Bytes(int bits, int implementation); 45 | Sketch* ConstructClMul8Bytes(int bits, int implementation); 46 | Sketch* ConstructClMulTri1Byte(int bits, int implementation); 47 | Sketch* ConstructClMulTri2Bytes(int bits, int implementation); 48 | Sketch* ConstructClMulTri3Bytes(int bits, int implementation); 49 | Sketch* ConstructClMulTri4Bytes(int bits, int implementation); 50 | Sketch* ConstructClMulTri5Bytes(int bits, int implementation); 51 | Sketch* ConstructClMulTri6Bytes(int bits, int implementation); 52 | Sketch* ConstructClMulTri7Bytes(int bits, int implementation); 53 | Sketch* ConstructClMulTri8Bytes(int bits, int implementation); 54 | #endif 55 | 56 | namespace { 57 | 58 | enum class FieldImpl { 59 | GENERIC = 0, 60 | #ifdef HAVE_CLMUL 61 | CLMUL, 62 | CLMUL_TRI, 63 | #endif 64 | }; 65 | 66 | #ifdef HAVE_CLMUL 67 | static inline bool EnableClmul() 68 | { 69 | #ifdef _MSC_VER 70 | int regs[4]; 71 | __cpuid(regs, 1); 72 | return (regs[2] & 0x2); 73 | #else 74 | uint32_t eax, ebx, ecx, edx; 75 | return (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx & 0x2)); 76 | #endif 77 | } 78 | #endif 79 | 80 | Sketch* Construct(int bits, int impl) 81 | { 82 | switch (FieldImpl(impl)) { 83 | case FieldImpl::GENERIC: 84 | switch ((bits + 7) / 8) { 85 | case 1: 86 | return ConstructGeneric1Byte(bits, impl); 87 | case 2: 88 | return ConstructGeneric2Bytes(bits, impl); 89 | case 3: 90 | return ConstructGeneric3Bytes(bits, impl); 91 | case 4: 92 | return ConstructGeneric4Bytes(bits, impl); 93 | case 5: 94 | return ConstructGeneric5Bytes(bits, impl); 95 | case 6: 96 | return ConstructGeneric6Bytes(bits, impl); 97 | case 7: 98 | return ConstructGeneric7Bytes(bits, impl); 99 | case 8: 100 | return ConstructGeneric8Bytes(bits, impl); 101 | default: 102 | return nullptr; 103 | } 104 | break; 105 | #ifdef HAVE_CLMUL 106 | case FieldImpl::CLMUL: 107 | if (EnableClmul()) { 108 | switch ((bits + 7) / 8) { 109 | case 1: 110 | return ConstructClMul1Byte(bits, impl); 111 | case 2: 112 | return ConstructClMul2Bytes(bits, impl); 113 | case 3: 114 | return ConstructClMul3Bytes(bits, impl); 115 | case 4: 116 | return ConstructClMul4Bytes(bits, impl); 117 | case 5: 118 | return ConstructClMul5Bytes(bits, impl); 119 | case 6: 120 | return ConstructClMul6Bytes(bits, impl); 121 | case 7: 122 | return ConstructClMul7Bytes(bits, impl); 123 | case 8: 124 | return ConstructClMul8Bytes(bits, impl); 125 | default: 126 | return nullptr; 127 | } 128 | } 129 | break; 130 | case FieldImpl::CLMUL_TRI: 131 | if (EnableClmul()) { 132 | switch ((bits + 7) / 8) { 133 | case 1: 134 | return ConstructClMulTri1Byte(bits, impl); 135 | case 2: 136 | return ConstructClMulTri2Bytes(bits, impl); 137 | case 3: 138 | return ConstructClMulTri3Bytes(bits, impl); 139 | case 4: 140 | return ConstructClMulTri4Bytes(bits, impl); 141 | case 5: 142 | return ConstructClMulTri5Bytes(bits, impl); 143 | case 6: 144 | return ConstructClMulTri6Bytes(bits, impl); 145 | case 7: 146 | return ConstructClMulTri7Bytes(bits, impl); 147 | case 8: 148 | return ConstructClMulTri8Bytes(bits, impl); 149 | default: 150 | return nullptr; 151 | } 152 | } 153 | break; 154 | #endif 155 | } 156 | return nullptr; 157 | } 158 | 159 | } 160 | 161 | extern "C" { 162 | 163 | int minisketch_bits_supported(uint32_t bits) { 164 | #ifdef ENABLE_FIELD_INT_2 165 | if (bits == 2) return true; 166 | #endif 167 | #ifdef ENABLE_FIELD_INT_3 168 | if (bits == 3) return true; 169 | #endif 170 | #ifdef ENABLE_FIELD_INT_4 171 | if (bits == 4) return true; 172 | #endif 173 | #ifdef ENABLE_FIELD_INT_5 174 | if (bits == 5) return true; 175 | #endif 176 | #ifdef ENABLE_FIELD_INT_6 177 | if (bits == 6) return true; 178 | #endif 179 | #ifdef ENABLE_FIELD_INT_7 180 | if (bits == 7) return true; 181 | #endif 182 | #ifdef ENABLE_FIELD_INT_8 183 | if (bits == 8) return true; 184 | #endif 185 | #ifdef ENABLE_FIELD_INT_9 186 | if (bits == 9) return true; 187 | #endif 188 | #ifdef ENABLE_FIELD_INT_10 189 | if (bits == 10) return true; 190 | #endif 191 | #ifdef ENABLE_FIELD_INT_11 192 | if (bits == 11) return true; 193 | #endif 194 | #ifdef ENABLE_FIELD_INT_12 195 | if (bits == 12) return true; 196 | #endif 197 | #ifdef ENABLE_FIELD_INT_13 198 | if (bits == 13) return true; 199 | #endif 200 | #ifdef ENABLE_FIELD_INT_14 201 | if (bits == 14) return true; 202 | #endif 203 | #ifdef ENABLE_FIELD_INT_15 204 | if (bits == 15) return true; 205 | #endif 206 | #ifdef ENABLE_FIELD_INT_16 207 | if (bits == 16) return true; 208 | #endif 209 | #ifdef ENABLE_FIELD_INT_17 210 | if (bits == 17) return true; 211 | #endif 212 | #ifdef ENABLE_FIELD_INT_18 213 | if (bits == 18) return true; 214 | #endif 215 | #ifdef ENABLE_FIELD_INT_19 216 | if (bits == 19) return true; 217 | #endif 218 | #ifdef ENABLE_FIELD_INT_20 219 | if (bits == 20) return true; 220 | #endif 221 | #ifdef ENABLE_FIELD_INT_21 222 | if (bits == 21) return true; 223 | #endif 224 | #ifdef ENABLE_FIELD_INT_22 225 | if (bits == 22) return true; 226 | #endif 227 | #ifdef ENABLE_FIELD_INT_23 228 | if (bits == 23) return true; 229 | #endif 230 | #ifdef ENABLE_FIELD_INT_24 231 | if (bits == 24) return true; 232 | #endif 233 | #ifdef ENABLE_FIELD_INT_25 234 | if (bits == 25) return true; 235 | #endif 236 | #ifdef ENABLE_FIELD_INT_26 237 | if (bits == 26) return true; 238 | #endif 239 | #ifdef ENABLE_FIELD_INT_27 240 | if (bits == 27) return true; 241 | #endif 242 | #ifdef ENABLE_FIELD_INT_28 243 | if (bits == 28) return true; 244 | #endif 245 | #ifdef ENABLE_FIELD_INT_29 246 | if (bits == 29) return true; 247 | #endif 248 | #ifdef ENABLE_FIELD_INT_30 249 | if (bits == 30) return true; 250 | #endif 251 | #ifdef ENABLE_FIELD_INT_31 252 | if (bits == 31) return true; 253 | #endif 254 | #ifdef ENABLE_FIELD_INT_32 255 | if (bits == 32) return true; 256 | #endif 257 | #ifdef ENABLE_FIELD_INT_33 258 | if (bits == 33) return true; 259 | #endif 260 | #ifdef ENABLE_FIELD_INT_34 261 | if (bits == 34) return true; 262 | #endif 263 | #ifdef ENABLE_FIELD_INT_35 264 | if (bits == 35) return true; 265 | #endif 266 | #ifdef ENABLE_FIELD_INT_36 267 | if (bits == 36) return true; 268 | #endif 269 | #ifdef ENABLE_FIELD_INT_37 270 | if (bits == 37) return true; 271 | #endif 272 | #ifdef ENABLE_FIELD_INT_38 273 | if (bits == 38) return true; 274 | #endif 275 | #ifdef ENABLE_FIELD_INT_39 276 | if (bits == 39) return true; 277 | #endif 278 | #ifdef ENABLE_FIELD_INT_40 279 | if (bits == 40) return true; 280 | #endif 281 | #ifdef ENABLE_FIELD_INT_41 282 | if (bits == 41) return true; 283 | #endif 284 | #ifdef ENABLE_FIELD_INT_42 285 | if (bits == 42) return true; 286 | #endif 287 | #ifdef ENABLE_FIELD_INT_43 288 | if (bits == 43) return true; 289 | #endif 290 | #ifdef ENABLE_FIELD_INT_44 291 | if (bits == 44) return true; 292 | #endif 293 | #ifdef ENABLE_FIELD_INT_45 294 | if (bits == 45) return true; 295 | #endif 296 | #ifdef ENABLE_FIELD_INT_46 297 | if (bits == 46) return true; 298 | #endif 299 | #ifdef ENABLE_FIELD_INT_47 300 | if (bits == 47) return true; 301 | #endif 302 | #ifdef ENABLE_FIELD_INT_48 303 | if (bits == 48) return true; 304 | #endif 305 | #ifdef ENABLE_FIELD_INT_49 306 | if (bits == 49) return true; 307 | #endif 308 | #ifdef ENABLE_FIELD_INT_50 309 | if (bits == 50) return true; 310 | #endif 311 | #ifdef ENABLE_FIELD_INT_51 312 | if (bits == 51) return true; 313 | #endif 314 | #ifdef ENABLE_FIELD_INT_52 315 | if (bits == 52) return true; 316 | #endif 317 | #ifdef ENABLE_FIELD_INT_53 318 | if (bits == 53) return true; 319 | #endif 320 | #ifdef ENABLE_FIELD_INT_54 321 | if (bits == 54) return true; 322 | #endif 323 | #ifdef ENABLE_FIELD_INT_55 324 | if (bits == 55) return true; 325 | #endif 326 | #ifdef ENABLE_FIELD_INT_56 327 | if (bits == 56) return true; 328 | #endif 329 | #ifdef ENABLE_FIELD_INT_57 330 | if (bits == 57) return true; 331 | #endif 332 | #ifdef ENABLE_FIELD_INT_58 333 | if (bits == 58) return true; 334 | #endif 335 | #ifdef ENABLE_FIELD_INT_59 336 | if (bits == 59) return true; 337 | #endif 338 | #ifdef ENABLE_FIELD_INT_60 339 | if (bits == 60) return true; 340 | #endif 341 | #ifdef ENABLE_FIELD_INT_61 342 | if (bits == 61) return true; 343 | #endif 344 | #ifdef ENABLE_FIELD_INT_62 345 | if (bits == 62) return true; 346 | #endif 347 | #ifdef ENABLE_FIELD_INT_63 348 | if (bits == 63) return true; 349 | #endif 350 | #ifdef ENABLE_FIELD_INT_64 351 | if (bits == 64) return true; 352 | #endif 353 | return false; 354 | } 355 | 356 | uint32_t minisketch_implementation_max() { 357 | uint32_t ret = 0; 358 | #ifdef HAVE_CLMUL 359 | ret += 2; 360 | #endif 361 | return ret; 362 | } 363 | 364 | int minisketch_implementation_supported(uint32_t bits, uint32_t implementation) { 365 | if (!minisketch_bits_supported(bits) || implementation > minisketch_implementation_max()) { 366 | return 0; 367 | } 368 | try { 369 | Sketch* sketch = Construct(bits, implementation); 370 | if (sketch) { 371 | delete sketch; 372 | return 1; 373 | } 374 | } catch (const std::bad_alloc&) {} 375 | return 0; 376 | } 377 | 378 | minisketch* minisketch_create(uint32_t bits, uint32_t implementation, size_t capacity) { 379 | try { 380 | Sketch* sketch = Construct(bits, implementation); 381 | if (sketch) { 382 | try { 383 | sketch->Init(capacity); 384 | } catch (const std::bad_alloc&) { 385 | delete sketch; 386 | throw; 387 | } 388 | sketch->Ready(); 389 | } 390 | return (minisketch*)sketch; 391 | } catch (const std::bad_alloc&) { 392 | return nullptr; 393 | } 394 | } 395 | 396 | uint32_t minisketch_bits(const minisketch* sketch) { 397 | const Sketch* s = (const Sketch*)sketch; 398 | s->Check(); 399 | return s->Bits(); 400 | } 401 | 402 | size_t minisketch_capacity(const minisketch* sketch) { 403 | const Sketch* s = (const Sketch*)sketch; 404 | s->Check(); 405 | return s->Syndromes(); 406 | } 407 | 408 | uint32_t minisketch_implementation(const minisketch* sketch) { 409 | const Sketch* s = (const Sketch*)sketch; 410 | s->Check(); 411 | return s->Implementation(); 412 | } 413 | 414 | minisketch* minisketch_clone(const minisketch* sketch) { 415 | const Sketch* s = (const Sketch*)sketch; 416 | s->Check(); 417 | Sketch* r = (Sketch*) minisketch_create(s->Bits(), s->Implementation(), s->Syndromes()); 418 | if (r) { 419 | r->Merge(s); 420 | } 421 | return (minisketch*) r; 422 | } 423 | 424 | void minisketch_destroy(minisketch* sketch) { 425 | if (sketch) { 426 | Sketch* s = (Sketch*)sketch; 427 | s->UnReady(); 428 | delete s; 429 | } 430 | } 431 | 432 | size_t minisketch_serialized_size(const minisketch* sketch) { 433 | const Sketch* s = (const Sketch*)sketch; 434 | s->Check(); 435 | size_t bits = s->Bits(); 436 | size_t syndromes = s->Syndromes(); 437 | return (bits * syndromes + 7) / 8; 438 | } 439 | 440 | void minisketch_serialize(const minisketch* sketch, unsigned char* output) { 441 | const Sketch* s = (const Sketch*)sketch; 442 | s->Check(); 443 | s->Serialize(output); 444 | } 445 | 446 | void minisketch_deserialize(minisketch* sketch, const unsigned char* input) { 447 | Sketch* s = (Sketch*)sketch; 448 | s->Check(); 449 | s->Deserialize(input); 450 | } 451 | 452 | void minisketch_add_uint64(minisketch* sketch, uint64_t element) { 453 | Sketch* s = (Sketch*)sketch; 454 | s->Check(); 455 | s->Add(element); 456 | } 457 | 458 | size_t minisketch_merge(minisketch* sketch, const minisketch* other_sketch) { 459 | Sketch* s1 = (Sketch*)sketch; 460 | const Sketch* s2 = (const Sketch*)other_sketch; 461 | s1->Check(); 462 | s2->Check(); 463 | if (s1->Bits() != s2->Bits()) return 0; 464 | if (s1->Implementation() != s2->Implementation()) return 0; 465 | return s1->Merge(s2); 466 | } 467 | 468 | ssize_t minisketch_decode(const minisketch* sketch, size_t max_elements, uint64_t* output) { 469 | const Sketch* s = (const Sketch*)sketch; 470 | s->Check(); 471 | return s->Decode(static_cast(max_elements), output); 472 | } 473 | 474 | void minisketch_set_seed(minisketch* sketch, uint64_t seed) { 475 | Sketch* s = (Sketch*)sketch; 476 | s->Check(); 477 | s->SetSeed(seed); 478 | } 479 | 480 | size_t minisketch_compute_capacity(uint32_t bits, size_t max_elements, uint32_t fpbits) { 481 | return ComputeCapacity(bits, max_elements, fpbits); 482 | } 483 | 484 | size_t minisketch_compute_max_elements(uint32_t bits, size_t capacity, uint32_t fpbits) { 485 | return ComputeMaxElements(bits, capacity, fpbits); 486 | } 487 | 488 | } 489 | -------------------------------------------------------------------------------- /src/sketch.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_STATE_H_ 8 | #define _MINISKETCH_STATE_H_ 9 | 10 | #include 11 | #include 12 | 13 | /** Abstract class for internal representation of a minisketch object. */ 14 | class Sketch 15 | { 16 | uint64_t m_canary; 17 | const int m_implementation; 18 | const int m_bits; 19 | 20 | public: 21 | Sketch(int implementation, int bits) : m_implementation(implementation), m_bits(bits) {} 22 | 23 | void Ready() { m_canary = 0x6d496e536b65LU; } 24 | void Check() const { if (m_canary != 0x6d496e536b65LU) abort(); } 25 | void UnReady() { m_canary = 1; } 26 | int Implementation() const { return m_implementation; } 27 | int Bits() const { return m_bits; } 28 | 29 | virtual ~Sketch() {} 30 | virtual size_t Syndromes() const = 0; 31 | 32 | virtual void Init(size_t syndromes) = 0; 33 | virtual void Add(uint64_t element) = 0; 34 | virtual void Serialize(unsigned char*) const = 0; 35 | virtual void Deserialize(const unsigned char*) = 0; 36 | virtual size_t Merge(const Sketch* other_sketch) = 0; 37 | virtual void SetSeed(uint64_t seed) = 0; 38 | 39 | virtual int Decode(int max_count, uint64_t* roots) const = 0; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * Copyright (c) 2018 Pieter Wuille, Greg Maxwell, Gleb Naumenko * 3 | * Distributed under the MIT software license, see the accompanying * 4 | * file LICENSE or http://www.opensource.org/licenses/mit-license.php.* 5 | **********************************************************************/ 6 | 7 | #ifndef _MINISKETCH_UTIL_H_ 8 | #define _MINISKETCH_UTIL_H_ 9 | 10 | #ifdef MINISKETCH_VERIFY 11 | #include 12 | #endif 13 | 14 | #if !defined(__GNUC_PREREQ) 15 | # if defined(__GNUC__)&&defined(__GNUC_MINOR__) 16 | # define __GNUC_PREREQ(_maj,_min) \ 17 | ((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min)) 18 | # else 19 | # define __GNUC_PREREQ(_maj,_min) 0 20 | # endif 21 | #endif 22 | 23 | #if __GNUC_PREREQ(3, 0) 24 | #define EXPECT(x,c) __builtin_expect((x),(c)) 25 | #else 26 | #define EXPECT(x,c) (x) 27 | #endif 28 | 29 | /* Assertion macros */ 30 | 31 | /** 32 | * Unconditional failure on condition failure. 33 | * Primarily used in testing harnesses. 34 | */ 35 | #define CHECK(cond) do { \ 36 | if (EXPECT(!(cond), 0)) { \ 37 | fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, "Check condition failed: " #cond); \ 38 | abort(); \ 39 | } \ 40 | } while(0) 41 | 42 | /** 43 | * Check macro that does nothing in normal non-verify builds but crashes in verify builds. 44 | * This is used to test conditions at runtime that should always be true, but are either 45 | * expensive to test or in locations where returning on failure would be messy. 46 | */ 47 | #ifdef MINISKETCH_VERIFY 48 | #define CHECK_SAFE(cond) CHECK(cond) 49 | #else 50 | #define CHECK_SAFE(cond) 51 | #endif 52 | 53 | /** 54 | * Check a condition and return on failure in non-verify builds, crash in verify builds. 55 | * Used for inexpensive conditions which believed to be always true in locations where 56 | * a graceful exit is possible. 57 | */ 58 | #ifdef MINISKETCH_VERIFY 59 | #define CHECK_RETURN(cond, rvar) do { \ 60 | if (EXPECT(!(cond), 0)) { \ 61 | fprintf(stderr, "%s:%d: %s\n", __FILE__, __LINE__, "Check condition failed: " #cond); \ 62 | abort(); \ 63 | return rvar; /* Does nothing, but causes compile to warn on incorrect return types. */ \ 64 | } \ 65 | } while(0) 66 | #else 67 | #define CHECK_RETURN(cond, rvar) do { \ 68 | if (EXPECT(!(cond), 0)) { \ 69 | return rvar; \ 70 | } \ 71 | } while(0) 72 | #endif 73 | 74 | #endif 75 | --------------------------------------------------------------------------------