diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..3f4f773 --- /dev/null +++ b/.clang-format @@ -0,0 +1,178 @@ +--- +Language: Cpp +# BasedOnStyle: Chromium +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveBitFields: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: DontAlign +AlignOperands: DontAlign +AlignTrailingComments: false +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: false +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: false +AllowShortBlocksOnASingleLine: Empty +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: MultiLine + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: true + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: NonAssignment +BreakBeforeBraces: Custom +# BreakBeforeInheritanceComma: true +BreakInheritanceList: BeforeComma +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: true +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Regroup +IncludeCategories: + # Standard library headers come before anything else + - Regex: '^<[a-z_]+>' + Priority: -1 + - Regex: '^<.+\.h(pp)?>' + Priority: 1 + - Regex: '^<.*' + Priority: 2 + - Regex: '.*' + Priority: 3 +IncludeIsMainRegex: '' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: AfterHash +IndentExternBlock: NoIndent +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: Wrapped +JavaScriptQuotes: Double +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Left +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatementsExceptForEachMacros +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..f932a80 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,153 @@ +--- +# Enable ALL the things! Except not really +# misc-non-private-member-variables-in-classes: the options don't do anything +Checks: "*,\ + -google-readability-todo,\ + -altera-unroll-loops,\ + -fuchsia-*,\ + fuchsia-multiple-inheritance,\ + -llvm-header-guard,\ + -llvm-include-order,\ + -llvmlibc-*,\ + -misc-non-private-member-variables-in-classes" +WarningsAsErrors: '' +CheckOptions: + - key: 'bugprone-argument-comment.StrictMode' + value: 'true' +# Prefer using enum classes with 2 values for parameters instead of bools + - key: 'bugprone-argument-comment.CommentBoolLiterals' + value: 'true' + - key: 'bugprone-misplaced-widening-cast.CheckImplicitCasts' + value: 'true' + - key: 'bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression' + value: 'true' + - key: 'bugprone-suspicious-string-compare.WarnOnLogicalNotComparison' + value: 'true' + - key: 'readability-simplify-boolean-expr.ChainedConditionalReturn' + value: 'true' + - key: 'readability-simplify-boolean-expr.ChainedConditionalAssignment' + value: 'true' + - key: 'readability-uniqueptr-delete-release.PreferResetCall' + value: 'true' + - key: 'cppcoreguidelines-init-variables.MathHeader' + value: '' + - key: 'cppcoreguidelines-narrowing-conversions.PedanticMode' + value: 'true' + - key: 'readability-else-after-return.WarnOnUnfixable' + value: 'true' + - key: 'readability-else-after-return.WarnOnConditionVariables' + value: 'true' + - key: 'readability-inconsistent-declaration-parameter-name.Strict' + value: 'true' + - key: 'readability-qualified-auto.AddConstToQualified' + value: 'true' + - key: 'readability-redundant-access-specifiers.CheckFirstDeclaration' + value: 'true' +# These seem to be the most common identifier styles + - key: 'readability-identifier-naming.AbstractClassCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ClassCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ClassConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ClassMemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ClassMethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstantMemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstantParameterCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstantPointerParameterCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstexprFunctionCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstexprMethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ConstexprVariableCase' + value: 'lower_case' + - key: 'readability-identifier-naming.EnumCase' + value: 'lower_case' + - key: 'readability-identifier-naming.EnumConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.FunctionCase' + value: 'lower_case' + - key: 'readability-identifier-naming.GlobalConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.GlobalConstantPointerCase' + value: 'lower_case' + - key: 'readability-identifier-naming.GlobalFunctionCase' + value: 'lower_case' + - key: 'readability-identifier-naming.GlobalPointerCase' + value: 'lower_case' + - key: 'readability-identifier-naming.GlobalVariableCase' + value: 'lower_case' + - key: 'readability-identifier-naming.InlineNamespaceCase' + value: 'lower_case' + - key: 'readability-identifier-naming.LocalConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.LocalConstantPointerCase' + value: 'lower_case' + - key: 'readability-identifier-naming.LocalPointerCase' + value: 'lower_case' + - key: 'readability-identifier-naming.LocalVariableCase' + value: 'lower_case' + - key: 'readability-identifier-naming.MacroDefinitionCase' + value: 'UPPER_CASE' + - key: 'readability-identifier-naming.MemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.MethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.NamespaceCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ParameterCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ParameterPackCase' + value: 'lower_case' + - key: 'readability-identifier-naming.PointerParameterCase' + value: 'lower_case' + - key: 'readability-identifier-naming.PrivateMemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.PrivateMemberPrefix' + value: 'm_' + - key: 'readability-identifier-naming.PrivateMethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ProtectedMemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ProtectedMemberPrefix' + value: 'm_' + - key: 'readability-identifier-naming.ProtectedMethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.PublicMemberCase' + value: 'lower_case' + - key: 'readability-identifier-naming.PublicMethodCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ScopedEnumConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.StaticConstantCase' + value: 'lower_case' + - key: 'readability-identifier-naming.StaticVariableCase' + value: 'lower_case' + - key: 'readability-identifier-naming.StructCase' + value: 'lower_case' + - key: 'readability-identifier-naming.TemplateParameterCase' + value: 'CamelCase' + - key: 'readability-identifier-naming.TemplateTemplateParameterCase' + value: 'CamelCase' + - key: 'readability-identifier-naming.TypeAliasCase' + value: 'lower_case' + - key: 'readability-identifier-naming.TypedefCase' + value: 'lower_case' + - key: 'readability-identifier-naming.TypeTemplateParameterCase' + value: 'CamelCase' + - key: 'readability-identifier-naming.UnionCase' + value: 'lower_case' + - key: 'readability-identifier-naming.ValueTemplateParameterCase' + value: 'CamelCase' + - key: 'readability-identifier-naming.VariableCase' + value: 'lower_case' + - key: 'readability-identifier-naming.VirtualMethodCase' + value: 'lower_case' +... diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 0000000..5bf88c7 --- /dev/null +++ b/.codespellrc @@ -0,0 +1,6 @@ +[codespell] +builtin = clear,rare,en-GB_to_en-US,names,informal,code +check-filenames = +check-hidden = +skip = */.git,*/build,*/prefix +quiet-level = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e0a544e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,194 @@ +name: Continuous Integration + +on: + push: + branches: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "*" + workflow_dispatch: + +jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: "Checkout Code" + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 0 + + - uses: actions/setup-python@v2 + with: { python-version: "3.8" } + + - name: Install codespell + run: pip3 install codespell + + - name: Lint + run: cmake -D FORMAT_COMMAND=clang-format-11 -P cmake/lint.cmake + + - name: Spell check + if: always() + run: cmake -P cmake/spell.cmake + + coverage: + needs: [lint] + + runs-on: ubuntu-latest + + # To enable coverage, delete the last line from the conditional below and + # edit the "" placeholder to your GitHub name. + # If you do not wish to use codecov, then simply delete this job from the + # workflow. + if: github.repository_owner == 'stbrumme' + && false + + steps: + - name: "Checkout Code" + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Install LCov + run: sudo apt-get update -q + && sudo apt-get install lcov -q -y + + - name: Configure + run: cmake --preset=ci-coverage + + - name: Build + run: cmake --build build/coverage -j 2 + + - name: Test + working-directory: build/coverage + run: ctest --output-on-failure -j 2 + + - name: Process coverage info + run: cmake --build build/coverage -t coverage + + - name: Submit to codecov.io + uses: codecov/codecov-action@v1 + with: + file: build/coverage/coverage.info + + sanitize: + needs: [lint] + + runs-on: ubuntu-latest + + steps: + - name: "Checkout Code" + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Configure + env: { CXX: clang++-11 } + run: cmake --preset=ci-sanitize + + - name: Build + run: cmake --build build/sanitize -j 2 + + - name: Test + working-directory: build/sanitize + env: + ASAN_OPTIONS: "strict_string_checks=1:\ + detect_stack_use_after_return=1:\ + check_initialization_order=1:\ + strict_init_order=1:\ + detect_leaks=1" + UBSAN_OPTIONS: print_stacktrace=1 + run: ctest --output-on-failure -j 2 + + test: + needs: [lint] + + strategy: + fail-fast: false + matrix: + os: [macos-latest, ubuntu-latest, windows-2022] + + type: [shared, static] + + include: + - { type: shared, shared: YES } + - { type: static, shared: NO } + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v2 + + - name: Install static analyzers + if: matrix.os == 'ubuntu-latest' + run: sudo apt-get install clang-tidy cppcheck -y -q + + - name: Configure + shell: pwsh + run: cmake "--preset=ci-$("${{ matrix.os }}".split("-")[0])" + -D BUILD_SHARED_LIBS=${{ matrix.shared }} + + - name: Build + run: cmake --build build --config Release -j 2 + + - name: Install + run: cmake --install build --config Release --prefix prefix + + - name: Test + working-directory: build + run: ctest --output-on-failure -C Release -j 2 + + docs: + # Deploy docs only when builds succeed + needs: [sanitize, test] + + runs-on: ubuntu-latest + + # To enable, first you have to create an orphaned gh-pages branch: + # + # git switch --orphan gh-pages + # git commit --allow-empty -m "Initial commit" + # git push -u origin gh-pages + # + # Edit the placeholder below to your GitHub name, so this action + # runs only in your repository and no one else's fork. After these, delete + # this comment and the last line in the conditional below. + # If you do not wish to use GitHub Pages for deploying documentation, then + # simply delete this job similarly to the coverage one. + if: github.ref == 'refs/heads/master' + && github.event_name == 'push' + && github.repository_owner == 'stbrumme' + && false + + steps: + - name: "Checkout Code" + uses: actions/checkout@v3 + with: + submodules: "recursive" + fetch-depth: 0 + + - uses: actions/setup-python@v2 + with: { python-version: "3.8" } + + - name: Install m.css dependencies + run: pip3 install jinja2 Pygments + + - name: Install Doxygen + run: sudo apt-get update -q + && sudo apt-get install doxygen -q -y + + - name: Build docs + run: cmake "-DPROJECT_SOURCE_DIR=$PWD" "-DPROJECT_BINARY_DIR=$PWD/build" + -P cmake/docs-ci.cmake + + - name: Deploy docs + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: build/docs/html diff --git a/.github/workflows/dockcross.yml b/.github/workflows/dockcross.yml new file mode 100644 index 0000000..e27d85c --- /dev/null +++ b/.github/workflows/dockcross.yml @@ -0,0 +1,199 @@ +name: Dockcross CI + +on: + push: + branches: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "*" + workflow_dispatch: + +jobs: + build: + name: dockcross ${{ matrix.dockcross.image_name }} ${{ matrix.build_type }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + dockcross: + # Android images + - { image_name: android-arm, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { image_name: android-arm64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { image_name: android-x86, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { image_name: android-x86_64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Web images + - { image_name: web-wasm, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: web-wasi, + cmake_arg: "-DCMAKE_CXX_FLAGS='${CMAKE_CXX_FLAGS} -fno-exceptions'", + } + + # Linux ARMv5 images + - { image_name: linux-armv5, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-armv5-musl, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Linux ARMv6 images + - { image_name: linux-armv6, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-armv6-lts, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: linux-armv6-musl, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # linux ARMv7 images + - { image_name: linux-armv7, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-armv7-lts, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { image_name: linux-armv7a, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-armv7l-musl, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Linux ARMv8 (64 bit) images + - { image_name: linux-arm64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-arm64-lts, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: linux-arm64-full, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: linux-arm64-musl, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Linux x86 images + - { image_name: linux-x86, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { image_name: linux-x64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { + image_name: linux-x64-clang, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: linux-x64-tinycc, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: linux-x86_64-full, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Linux s390 images + - { image_name: linux-s390x, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Linux mips images + - { image_name: linux-mips, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Linux PowerPC 64 images + - { image_name: linux-ppc64le, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Linux xtensa images + - { + image_name: linux-xtensa-uclibc, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Linux riscv images + - { image_name: linux-riscv32, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + - { image_name: linux-riscv64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Linux m68k images + - { + image_name: linux-m68k-uclibc, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # ManyLinux images + - { image_name: manylinux1-x64, cmake_arg: "-DCMAKE_CXX_STANDARD=14 -D CMAKE_C_STANDARD=99" } + - { image_name: manylinux1-x86, cmake_arg: "-DCMAKE_CXX_STANDARD=14 -D CMAKE_C_STANDARD=99" } + - { + image_name: manylinux2010-x86, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: manylinux2010-x64, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: manylinux2014-x86, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: manylinux2014-x64, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + # - { image_name: manylinux2014-aarch64, cmake_arg: "-DCMAKE_CXX_STANDARD=17" } + + # Windows x86 images + - { + image_name: windows-static-x64, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-static-x64-posix, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-static-x86, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-shared-x64, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-shared-x64-posix, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-shared-x86, + cmake_arg: "-DCMAKE_CXX_STANDARD=17", + } + + # Windows ARM images + - { + image_name: windows-armv7, + cmake_arg: "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DCMAKE_CXX_STANDARD=17", + } + - { + image_name: windows-arm64, + cmake_arg: "-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON -DCMAKE_CXX_STANDARD=17", + } + + # Disable MinSizeRel RelWithDebInfo, Release, Debug + build_type: [Release] + steps: + - name: "Checkout Code" + uses: actions/checkout@v2 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: "Pull docker image: dockcross/${{ matrix.dockcross.image_name }}" + run: docker pull dockcross/${{ matrix.dockcross.image_name }}:latest + + - name: "Make dockcross script: dockcross-${{ matrix.dockcross.image_name }}" + run: | + docker run --rm dockcross/${{ matrix.dockcross.image_name }} > ./dockcross-${{ matrix.dockcross.image_name }} + chmod +x ./dockcross-${{ matrix.dockcross.image_name }} + + - name: "Config CMake build" + run: ./dockcross-${{ matrix.dockcross.image_name }} cmake -B build-${{ matrix.dockcross.image_name }} -S . -G Ninja -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} ${{ matrix.dockcross.cmake_arg }} + + - name: "Build" + run: ./dockcross-${{ matrix.dockcross.image_name }} ninja -C build-${{ matrix.dockcross.image_name }} diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml new file mode 100644 index 0000000..3a5005d --- /dev/null +++ b/.github/workflows/linux.yml @@ -0,0 +1,53 @@ +name: linux + +on: + push: + branches: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "*" + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + cxx_compiler: [g++, clang++] + cc_compiler: [gcc] + shared: [YES, NO] + standard: [11, 14, 17, 20] + build_type: [Debug, Release] + + steps: + - name: "Checkout Code" + uses: actions/checkout@v2 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: dependencies + run: | + sudo apt -y update + sudo apt -y install ninja-build + + - name: Configure + env: + CXX: ${{matrix.cxx_compiler}} + CC: ${{matrix.cc_compiler}} + run: | + cmake -S . -B build -D CMAKE_BUILD_TYPE=${{matrix.build_type}} \ + -D CMAKE_CXX_STANDARD=${{matrix.standard}} -G Ninja \ + -D BUILD_SHARED_LIBS=${{matrix.shared}} --preset=ci-coverage + + - name: Build + run: ninja -C build + + - name: Test + run: ctest --test-dir build --verbose --output-on-failure --parallel 2 + env: + CTEST_OUTPUT_ON_FAILURE: True diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml new file mode 100644 index 0000000..4971284 --- /dev/null +++ b/.github/workflows/macos.yml @@ -0,0 +1,46 @@ +name: macos + +on: + push: + branches: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "*" + workflow_dispatch: + +jobs: + build: + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + build_type: [Debug, Release] + shared: [YES, NO] + standard: [11, 14, 17, 20] + + steps: + - name: "Checkout Code" + uses: actions/checkout@v2 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Create Build Environment + run: cmake -E make_directory ${{runner.workspace}}/build + + - name: Configure + run: | + cmake -S . -B build -DCMAKE_BUILD_TYPE=${{matrix.build_type}} \ + -D BUILD_SHARED_LIBS=${{matrix.shared}} \ + -D CMAKE_CXX_STANDARD=${{matrix.standard}} --preset=ci-macos + + - name: Build + run: cmake --build build --config ${{matrix.build_type}} --parallel 2 + + - name: Test + run: ctest --test-dir build --verbose --output-on-failure --parallel 2 + env: + CTEST_OUTPUT_ON_FAILURE: True diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 0000000..1dd9d40 --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,45 @@ +name: windows + +on: + push: + branches: + - "*" + paths-ignore: + - "**.md" + pull_request: + branches: + - "*" + workflow_dispatch: + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + shared: [YES, NO] + standard: [11, 14, 17, 20] + platform: [Win32, x64] + build_type: [Debug, Release] + steps: + - name: "Checkout Code" + uses: actions/checkout@v2 + with: + submodules: "recursive" + fetch-depth: 0 + + - name: Create Build Environment + run: cmake -E make_directory ${{runner.workspace}}/build + + - name: Configure + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{matrix.build_type}} + -A ${{matrix.platform}} -D CMAKE_CXX_STANDARD=${{matrix.standard}} + -D BUILD_SHARED_LIBS=${{matrix.shared}} --preset=ci-windows + + - name: Build + run: cmake --build build --parallel 2 + + - name: Test + run: ctest --test-dir build --verbose --output-on-failure --parallel 2 + env: + CTEST_OUTPUT_ON_FAILURE: True diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..75622aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.idea/ +.vs/ +.vscode/ +build/ +cmake/open-cpp-coverage.cmake +cmake-build-*/ +prefix/ +CMakeLists.txt.user +CMakeUserPresets.json diff --git a/BUILDING.md b/BUILDING.md new file mode 100644 index 0000000..645c1c0 --- /dev/null +++ b/BUILDING.md @@ -0,0 +1,68 @@ +# Building with CMake + +## Build + +This project doesn't require any special command-line flags to build to keep +things simple. + +Here are the steps for building in release mode with a single-configuration +generator, like the Unix Makefiles one: + +```sh +cmake -S . -B build -D CMAKE_BUILD_TYPE=Release +cmake --build build +``` + +Here are the steps for building in release mode with a multi-configuration +generator, like the Visual Studio ones: + +```sh +cmake -S . -B build +cmake --build build --config Release +``` + +## Install + +This project doesn't require any special command-line flags to install to keep +things simple. As a prerequisite, the project has to be built with the above +commands already. + +The below commands require at least CMake 3.15 to run, because that is the +version in which [Install a Project][1] was added. + +Here is the command for installing the release mode artifacts with a +single-configuration generator, like the Unix Makefiles one: + +```sh +cmake --install build +``` + +Here is the command for installing the release mode artifacts with a +multi-configuration generator, like the Visual Studio ones: + +```sh +cmake --install build --config Release +``` + +### CMake package + +This project exports a CMake package to be used with the [`find_package`][2] +command of CMake: + +* Package name: `crc32` +* Target name: `crc32::crc32` + +Example usage: + +```cmake +find_package(crc32 REQUIRED) +# Declare the imported target as a build requirement using PRIVATE, where +# project_target is a target created in the consuming project +target_link_libraries( + project_target PRIVATE + crc32::crc32 +) +``` + +[1]: https://cmake.org/cmake/help/latest/manual/cmake.1.html#install-a-project +[2]: https://cmake.org/cmake/help/latest/command/find_package.html diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..765b47e --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,123 @@ +cmake_minimum_required(VERSION 3.14) + +include(cmake/prelude.cmake) + +project( + crc32 + VERSION 0.1.0 + DESCRIPTION "fast crc32 library" + HOMEPAGE_URL "https://create.stephan-brumme.com/" + LANGUAGES C CXX +) + +include(cmake/project-is-top-level.cmake) +include(cmake/variables.cmake) + +# ---- Library options ---- + +option(CRC32_USE_LOOKUP_TABLE_BYTE "Enable 1 byte crc32 function" ON) +option(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 "Enable 4 byte crc32 function" ON) +option(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 "Enable 8 byte crc32 function" ON) +option(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 "Enable 16 byte crc32 function" ON) + +# ---- Declare library ---- + +add_library( + crc32_crc32 + source/crc32.cpp + source/crc32.c + source/crc32_var.c +) +add_library(crc32::crc32 ALIAS crc32_crc32) + +include(GenerateExportHeader) +generate_export_header( + crc32_crc32 + BASE_NAME crc32 + EXPORT_FILE_NAME export/crc32/crc32_export.hpp + CUSTOM_CONTENT_FROM_VARIABLE pragma_suppress_c4251 +) + +# ---- Library variables ---- + +if(NOT BUILD_SHARED_LIBS) + target_compile_definitions(crc32_crc32 PUBLIC CRC32_STATIC_DEFINE) +endif() + +if(CRC32_USE_LOOKUP_TABLE_BYTE) + target_compile_definitions(crc32_crc32 PUBLIC CRC32_USE_LOOKUP_TABLE_BYTE) +else() + message(STATUS "CRC32_USE_LOOKUP_TABLE_BYTE is disable") +endif() + +if(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) + target_compile_definitions(crc32_crc32 PUBLIC CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) +else() + message(STATUS "DCRC32_USE_LOOKUP_TABLE_SLICING_BY_4 is disable") +endif() + +if(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) + target_compile_definitions(crc32_crc32 PUBLIC CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) +else() + message(STATUS "DCRC32_USE_LOOKUP_TABLE_SLICING_BY_8 is disable") +endif() + +if(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) +target_compile_definitions(crc32_crc32 PUBLIC CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) +else() + message(STATUS "DCRC32_USE_LOOKUP_TABLE_SLICING_BY_16 is disable") +endif() + +# ---- Library properties ---- + +set_target_properties( + crc32_crc32 PROPERTIES + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN YES + VERSION "${PROJECT_VERSION}" + SOVERSION "${PROJECT_VERSION_MAJOR}" + EXPORT_NAME crc32 + OUTPUT_NAME crc32 +) + +target_include_directories( + crc32_crc32 ${warning_guard} + PUBLIC + "$" +) + +target_include_directories( + crc32_crc32 SYSTEM + PUBLIC + "$" +) + +# target_compile_features(crc32_crc32 PUBLIC cxx_std_17) + +# ---- Install rules ---- + +if(NOT CMAKE_SKIP_INSTALL_RULES) + include(cmake/install-rules.cmake) +endif() + +# ---- Examples ---- + +if(PROJECT_IS_TOP_LEVEL) + option(BUILD_EXAMPLES "Build examples tree." "${crc32_DEVELOPER_MODE}") + if(BUILD_EXAMPLES) + add_subdirectory(example) + endif() +endif() + +# ---- Developer mode ---- + +if(NOT crc32_DEVELOPER_MODE) + return() +elseif(NOT PROJECT_IS_TOP_LEVEL) + message( + AUTHOR_WARNING + "Developer mode is intended for developers of crc32" + ) +endif() + +include(cmake/dev-mode.cmake) diff --git a/CMakePresets.json b/CMakePresets.json new file mode 100644 index 0000000..f512893 --- /dev/null +++ b/CMakePresets.json @@ -0,0 +1,137 @@ +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 14, + "patch": 0 + }, + "configurePresets": [ + { + "name": "cmake-pedantic", + "hidden": true, + "warnings": { + "dev": true, + "deprecated": true, + "uninitialized": true, + "unusedCli": true, + "systemVars": false + }, + "errors": { + "dev": false, + "deprecated": false + } + }, + { + "name": "dev-mode", + "hidden": true, + "inherits": "cmake-pedantic", + "cacheVariables": { + "crc32_DEVELOPER_MODE": "ON" + } + }, + { + "name": "cppcheck", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CPPCHECK": "cppcheck;--inline-suppr" + } + }, + { + "name": "clang-tidy", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_CLANG_TIDY": "clang-tidy;--header-filter=${sourceDir}/*" + } + }, + { + "name": "ci-std", + "description": "This preset makes sure the project actually builds with at least the specified standard", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_EXTENSIONS": "OFF", + "CMAKE_CXX_STANDARD": "17", + "CMAKE_CXX_STANDARD_REQUIRED": "ON", + "CMAKE_C_EXTENSIONS": "OFF", + "CMAKE_C_STANDARD": "99", + "CMAKE_C_STANDARD_REQUIRED": "ON" + } + }, + { + "name": "flags-unix", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wcast-qual -Wshadow -Wformat=2 -Wundef", + "CMAKE_C_FLAGS": "-Wall -Wextra -Wpedantic -Wshadow" + } + }, + { + "name": "flags-windows", + "hidden": true, + "cacheVariables": { + "CMAKE_CXX_FLAGS": "/W4 /permissive- /utf-8 /volatile:iso /EHsc /Zc:__cplusplus /Zc:throwingNew" + } + }, + { + "name": "ci-unix", + "generator": "Unix Makefiles", + "hidden": true, + "inherits": ["flags-unix", "ci-std"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "ci-win64", + "inherits": ["flags-windows", "ci-std"], + "generator": "Visual Studio 17 2022", + "architecture": "x64", + "hidden": true + }, + { + "name": "coverage-unix", + "binaryDir": "${sourceDir}/build/coverage", + "inherits": "ci-unix", + "hidden": true, + "cacheVariables": { + "ENABLE_COVERAGE": "ON", + "CMAKE_BUILD_TYPE": "Coverage", + "CMAKE_CXX_FLAGS_COVERAGE": "-Og -g --coverage -fkeep-inline-functions -fkeep-static-functions", + "CMAKE_EXE_LINKER_FLAGS_COVERAGE": "--coverage", + "CMAKE_SHARED_LINKER_FLAGS_COVERAGE": "--coverage" + } + }, + { + "name": "ci-coverage", + "inherits": ["coverage-unix", "dev-mode"], + "cacheVariables": { + "COVERAGE_HTML_COMMAND": "" + } + }, + { + "name": "ci-sanitize", + "binaryDir": "${sourceDir}/build/sanitize", + "inherits": ["ci-unix", "dev-mode"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Sanitize", + "CMAKE_CXX_FLAGS_SANITIZE": "-O2 -g -fsanitize=address,undefined -fno-omit-frame-pointer -fno-common" + } + }, + { + "name": "ci-build", + "binaryDir": "${sourceDir}/build", + "hidden": true + }, + { + "name": "ci-macos", + "inherits": ["ci-build", "ci-unix", "dev-mode"] + }, + { + "name": "ci-ubuntu", + "inherits": ["ci-build", "ci-unix", "clang-tidy", "cppcheck", "dev-mode"] + }, + { + "name": "ci-windows", + "inherits": ["ci-build", "ci-win64", "dev-mode"] + } + ] +} diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..d120231 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,5 @@ +# Code of Conduct + +* You will be judged by your contributions first, and your sense of humor + second. +* Nobody owes you anything. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..10cccf3 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,19 @@ +# Contributing + + + +## Code of Conduct + +Please see the [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) document. + +## Getting started + +Helpful notes for developers can be found in the [`HACKING.md`](HACKING.md) +document. + +In addition to he above, if you use the presets file as instructed, then you +should NOT check it into source control, just as the CMake documentation +suggests. diff --git a/Crc32.cpp b/Crc32.cpp deleted file mode 100644 index ca36519..0000000 --- a/Crc32.cpp +++ /dev/null @@ -1,1245 +0,0 @@ -// ////////////////////////////////////////////////////////// -// Crc32.cpp -// Copyright (c) 2011-2019 Stephan Brumme. All rights reserved. -// Slicing-by-16 contributed by Bulat Ziganshin -// Tableless bytewise CRC contributed by Hagai Gold -// see http://create.stephan-brumme.com/disclaimer.html -// - -// if running on an embedded system, you might consider shrinking the -// big Crc32Lookup table: -// - crc32_bitwise doesn't need it at all -// - crc32_halfbyte has its own small lookup table -// - crc32_1byte needs only Crc32Lookup[0] -// - crc32_4bytes needs only Crc32Lookup[0..3] -// - crc32_8bytes needs only Crc32Lookup[0..7] -// - crc32_4x8bytes needs only Crc32Lookup[0..7] -// - crc32_16bytes needs all of Crc32Lookup - - -#include "Crc32.h" - -#ifndef __LITTLE_ENDIAN - #define __LITTLE_ENDIAN 1234 -#endif -#ifndef __BIG_ENDIAN - #define __BIG_ENDIAN 4321 -#endif - -// define endianess and some integer data types -#if defined(_MSC_VER) || defined(__MINGW32__) - // Windows always little endian - #define __BYTE_ORDER __LITTLE_ENDIAN - - // intrinsics / prefetching - #if defined(__MINGW32__) || defined(__clang__) - #define PREFETCH(location) __builtin_prefetch(location) - #else - #if defined(__SSE2__) - #include - #define PREFETCH(location) _mm_prefetch(location, _MM_HINT_T0) - #else - #define PREFETCH(location) ; - #endif - #endif -#else - // defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN - #include - - // intrinsics / prefetching - #ifdef __GNUC__ - #define PREFETCH(location) __builtin_prefetch(location) - #else - // no prefetching - #define PREFETCH(location) ; - #endif -#endif - -// abort if byte order is undefined -#if !defined(__BYTE_ORDER) -#error undefined byte order, compile with -D__BYTE_ORDER=1234 (if little endian) or -D__BYTE_ORDER=4321 (big endian) -#endif - - -namespace -{ - /// zlib's CRC32 polynomial - const uint32_t Polynomial = 0xEDB88320; - -#if __BYTE_ORDER == __BIG_ENDIAN - /// swap endianess - static inline uint32_t swap(uint32_t x) - { - #if defined(__GNUC__) || defined(__clang__) - return __builtin_bswap32(x); - #else - return (x >> 24) | - ((x >> 8) & 0x0000FF00) | - ((x << 8) & 0x00FF0000) | - (x << 24); - #endif - } -#endif - - /// Slicing-By-16 - #ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 - const size_t MaxSlice = 16; - #elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) - const size_t MaxSlice = 8; - #elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) - const size_t MaxSlice = 4; - #elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) - const size_t MaxSlice = 1; - #else - #define NO_LUT // don't need Crc32Lookup at all - #endif - -} // anonymous namespace - -#ifndef NO_LUT -/// forward declaration, table is at the end of this file -extern const uint32_t Crc32Lookup[MaxSlice][256]; // extern is needed to keep compiler happy -#endif - - -/// compute CRC32 (bitwise algorithm) -uint32_t crc32_bitwise(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*) data; - - while (length-- != 0) - { - crc ^= *current++; - - for (int j = 0; j < 8; j++) - { - // branch-free - crc = (crc >> 1) ^ (-int32_t(crc & 1) & Polynomial); - - // branching, much slower: - //if (crc & 1) - // crc = (crc >> 1) ^ Polynomial; - //else - // crc = crc >> 1; - } - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (half-byte algoritm) -uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*) data; - - /// look-up table for half-byte, same as crc32Lookup[0][16*i] - static const uint32_t Crc32Lookup16[16] = - { - 0x00000000,0x1DB71064,0x3B6E20C8,0x26D930AC,0x76DC4190,0x6B6B51F4,0x4DB26158,0x5005713C, - 0xEDB88320,0xF00F9344,0xD6D6A3E8,0xCB61B38C,0x9B64C2B0,0x86D3D2D4,0xA00AE278,0xBDBDF21C - }; - - while (length-- != 0) - { - crc = Crc32Lookup16[(crc ^ *current ) & 0x0F] ^ (crc >> 4); - crc = Crc32Lookup16[(crc ^ (*current >> 4)) & 0x0F] ^ (crc >> 4); - current++; - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -#ifdef CRC32_USE_LOOKUP_TABLE_BYTE -/// compute CRC32 (standard algorithm) -uint32_t crc32_1byte(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*) data; - - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *current++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} -#endif - - -/// compute CRC32 (byte algorithm) without lookup tables -uint32_t crc32_1byte_tableless(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint8_t* current = (const uint8_t*) data; - - while (length-- != 0) - { - uint8_t s = uint8_t(crc) ^ *current++; - - // Hagai Gold made me aware of this table-less algorithm and send me code - - // polynomial 0xEDB88320 can be written in binary as 11101101101110001000001100100000b - // reverse the bits (or just assume bit 0 is the first one) - // and we have bits set at position 0, 1, 2, 4, 5, 7, 8, 10, 11, 12, 16, 22, 23, 26 - // => those are the shift offsets: - //crc = (crc >> 8) ^ - // t ^ - // (t >> 1) ^ (t >> 2) ^ (t >> 4) ^ (t >> 5) ^ // == y - // (t >> 7) ^ (t >> 8) ^ (t >> 10) ^ (t >> 11) ^ // == y >> 6 - // (t >> 12) ^ (t >> 16) ^ // == z - // (t >> 22) ^ (t >> 26) ^ // == z >> 10 - // (t >> 23); - - // the fastest I can come up with: - uint32_t low = (s ^ (s << 6)) & 0xFF; - uint32_t a = (low * ((1 << 23) + (1 << 14) + (1 << 2))); - crc = (crc >> 8) ^ - (low * ((1 << 24) + (1 << 16) + (1 << 8))) ^ - a ^ - (a >> 1) ^ - (low * ((1 << 20) + (1 << 12) )) ^ - (low << 19) ^ - (low << 17) ^ - (low >> 2); - - // Hagai's code: - /*uint32_t t = (s ^ (s << 6)) << 24; - - // some temporaries to optimize XOR - uint32_t x = (t >> 1) ^ (t >> 2); - uint32_t y = x ^ (x >> 3); - uint32_t z = (t >> 12) ^ (t >> 16); - - crc = (crc >> 8) ^ - t ^ (t >> 23) ^ - y ^ (y >> 6) ^ - z ^ (z >> 10);*/ - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (byte algorithm) without lookup tables -uint32_t crc32_1byte_tableless2(const void* data, size_t length, uint32_t previousCrc32) -{ - int32_t crc = ~previousCrc32; // note: signed integer, right shift distributes sign bit into lower bits - const uint8_t* current = (const uint8_t*) data; - - while (length-- != 0) - { - crc = crc ^ *current++; - - uint32_t c = (((crc << 31) >> 31) & ((Polynomial >> 7) ^ (Polynomial >> 1))) ^ - (((crc << 30) >> 31) & ((Polynomial >> 6) ^ Polynomial)) ^ - (((crc << 29) >> 31) & (Polynomial >> 5)) ^ - (((crc << 28) >> 31) & (Polynomial >> 4)) ^ - (((crc << 27) >> 31) & (Polynomial >> 3)) ^ - (((crc << 26) >> 31) & (Polynomial >> 2)) ^ - (((crc << 25) >> 31) & (Polynomial >> 1)) ^ - (((crc << 24) >> 31) & Polynomial); - - crc = ((uint32_t)crc >> 8) ^ c; // convert to unsigned integer before right shift - } - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 -/// compute CRC32 (Slicing-by-4 algorithm) -uint32_t crc32_4bytes(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*) data; - - // process four bytes at once (Slicing-by-4) - while (length >= 4) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - crc = Crc32Lookup[0][ one & 0xFF] ^ - Crc32Lookup[1][(one>> 8) & 0xFF] ^ - Crc32Lookup[2][(one>>16) & 0xFF] ^ - Crc32Lookup[3][(one>>24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - crc = Crc32Lookup[0][(one>>24) & 0xFF] ^ - Crc32Lookup[1][(one>>16) & 0xFF] ^ - Crc32Lookup[2][(one>> 8) & 0xFF] ^ - Crc32Lookup[3][ one & 0xFF]; -#endif - - length -= 4; - } - - const uint8_t* currentChar = (const uint8_t*) current; - // remaining 1 to 3 bytes (standard algorithm) - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} -#endif - - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 -/// compute CRC32 (Slicing-by-8 algorithm) -uint32_t crc32_8bytes(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*) data; - - // process eight bytes at once (Slicing-by-8) - while (length >= 8) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - crc = Crc32Lookup[0][ two & 0xFF] ^ - Crc32Lookup[1][(two>> 8) & 0xFF] ^ - Crc32Lookup[2][(two>>16) & 0xFF] ^ - Crc32Lookup[3][(two>>24) & 0xFF] ^ - Crc32Lookup[4][ one & 0xFF] ^ - Crc32Lookup[5][(one>> 8) & 0xFF] ^ - Crc32Lookup[6][(one>>16) & 0xFF] ^ - Crc32Lookup[7][(one>>24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - crc = Crc32Lookup[0][(two>>24) & 0xFF] ^ - Crc32Lookup[1][(two>>16) & 0xFF] ^ - Crc32Lookup[2][(two>> 8) & 0xFF] ^ - Crc32Lookup[3][ two & 0xFF] ^ - Crc32Lookup[4][(one>>24) & 0xFF] ^ - Crc32Lookup[5][(one>>16) & 0xFF] ^ - Crc32Lookup[6][(one>> 8) & 0xFF] ^ - Crc32Lookup[7][ one & 0xFF]; -#endif - - length -= 8; - } - - const uint8_t* currentChar = (const uint8_t*) current; - // remaining 1 to 7 bytes (standard algorithm) - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times -uint32_t crc32_4x8bytes(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*) data; - - // enabling optimization (at least -O2) automatically unrolls the inner for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 8 * Unroll; - - // process 4x eight bytes at once (Slicing-by-8) - while (length >= BytesAtOnce) - { - for (size_t unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - crc = Crc32Lookup[0][ two & 0xFF] ^ - Crc32Lookup[1][(two>> 8) & 0xFF] ^ - Crc32Lookup[2][(two>>16) & 0xFF] ^ - Crc32Lookup[3][(two>>24) & 0xFF] ^ - Crc32Lookup[4][ one & 0xFF] ^ - Crc32Lookup[5][(one>> 8) & 0xFF] ^ - Crc32Lookup[6][(one>>16) & 0xFF] ^ - Crc32Lookup[7][(one>>24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - crc = Crc32Lookup[0][(two>>24) & 0xFF] ^ - Crc32Lookup[1][(two>>16) & 0xFF] ^ - Crc32Lookup[2][(two>> 8) & 0xFF] ^ - Crc32Lookup[3][ two & 0xFF] ^ - Crc32Lookup[4][(one>>24) & 0xFF] ^ - Crc32Lookup[5][(one>>16) & 0xFF] ^ - Crc32Lookup[6][(one>> 8) & 0xFF] ^ - Crc32Lookup[7][ one & 0xFF]; -#endif - - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*) current; - // remaining 1 to 31 bytes (standard algorithm) - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 - - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 -/// compute CRC32 (Slicing-by-16 algorithm) -uint32_t crc32_16bytes(const void* data, size_t length, uint32_t previousCrc32) -{ - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*) data; - - // enabling optimization (at least -O2) automatically unrolls the inner for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 16 * Unroll; - - while (length >= BytesAtOnce) - { - for (size_t unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[ 0][ four & 0xFF] ^ - Crc32Lookup[ 1][(four >> 8) & 0xFF] ^ - Crc32Lookup[ 2][(four >> 16) & 0xFF] ^ - Crc32Lookup[ 3][(four >> 24) & 0xFF] ^ - Crc32Lookup[ 4][ three & 0xFF] ^ - Crc32Lookup[ 5][(three >> 8) & 0xFF] ^ - Crc32Lookup[ 6][(three >> 16) & 0xFF] ^ - Crc32Lookup[ 7][(three >> 24) & 0xFF] ^ - Crc32Lookup[ 8][ two & 0xFF] ^ - Crc32Lookup[ 9][(two >> 8) & 0xFF] ^ - Crc32Lookup[10][(two >> 16) & 0xFF] ^ - Crc32Lookup[11][(two >> 24) & 0xFF] ^ - Crc32Lookup[12][ one & 0xFF] ^ - Crc32Lookup[13][(one >> 8) & 0xFF] ^ - Crc32Lookup[14][(one >> 16) & 0xFF] ^ - Crc32Lookup[15][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[ 0][(four >> 24) & 0xFF] ^ - Crc32Lookup[ 1][(four >> 16) & 0xFF] ^ - Crc32Lookup[ 2][(four >> 8) & 0xFF] ^ - Crc32Lookup[ 3][ four & 0xFF] ^ - Crc32Lookup[ 4][(three >> 24) & 0xFF] ^ - Crc32Lookup[ 5][(three >> 16) & 0xFF] ^ - Crc32Lookup[ 6][(three >> 8) & 0xFF] ^ - Crc32Lookup[ 7][ three & 0xFF] ^ - Crc32Lookup[ 8][(two >> 24) & 0xFF] ^ - Crc32Lookup[ 9][(two >> 16) & 0xFF] ^ - Crc32Lookup[10][(two >> 8) & 0xFF] ^ - Crc32Lookup[11][ two & 0xFF] ^ - Crc32Lookup[12][(one >> 24) & 0xFF] ^ - Crc32Lookup[13][(one >> 16) & 0xFF] ^ - Crc32Lookup[14][(one >> 8) & 0xFF] ^ - Crc32Lookup[15][ one & 0xFF]; -#endif - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*) current; - // remaining 1 to 63 bytes (standard algorithm) - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} - - -/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) -uint32_t crc32_16bytes_prefetch(const void* data, size_t length, uint32_t previousCrc32, size_t prefetchAhead) -{ - // CRC code is identical to crc32_16bytes (including unrolling), only added prefetching - // 256 bytes look-ahead seems to be the sweet spot on Core i7 CPUs - - uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF - const uint32_t* current = (const uint32_t*) data; - - // enabling optimization (at least -O2) automatically unrolls the for-loop - const size_t Unroll = 4; - const size_t BytesAtOnce = 16 * Unroll; - - while (length >= BytesAtOnce + prefetchAhead) - { - PREFETCH(((const char*) current) + prefetchAhead); - - for (size_t unrolling = 0; unrolling < Unroll; unrolling++) - { -#if __BYTE_ORDER == __BIG_ENDIAN - uint32_t one = *current++ ^ swap(crc); - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[ 0][ four & 0xFF] ^ - Crc32Lookup[ 1][(four >> 8) & 0xFF] ^ - Crc32Lookup[ 2][(four >> 16) & 0xFF] ^ - Crc32Lookup[ 3][(four >> 24) & 0xFF] ^ - Crc32Lookup[ 4][ three & 0xFF] ^ - Crc32Lookup[ 5][(three >> 8) & 0xFF] ^ - Crc32Lookup[ 6][(three >> 16) & 0xFF] ^ - Crc32Lookup[ 7][(three >> 24) & 0xFF] ^ - Crc32Lookup[ 8][ two & 0xFF] ^ - Crc32Lookup[ 9][(two >> 8) & 0xFF] ^ - Crc32Lookup[10][(two >> 16) & 0xFF] ^ - Crc32Lookup[11][(two >> 24) & 0xFF] ^ - Crc32Lookup[12][ one & 0xFF] ^ - Crc32Lookup[13][(one >> 8) & 0xFF] ^ - Crc32Lookup[14][(one >> 16) & 0xFF] ^ - Crc32Lookup[15][(one >> 24) & 0xFF]; -#else - uint32_t one = *current++ ^ crc; - uint32_t two = *current++; - uint32_t three = *current++; - uint32_t four = *current++; - crc = Crc32Lookup[ 0][(four >> 24) & 0xFF] ^ - Crc32Lookup[ 1][(four >> 16) & 0xFF] ^ - Crc32Lookup[ 2][(four >> 8) & 0xFF] ^ - Crc32Lookup[ 3][ four & 0xFF] ^ - Crc32Lookup[ 4][(three >> 24) & 0xFF] ^ - Crc32Lookup[ 5][(three >> 16) & 0xFF] ^ - Crc32Lookup[ 6][(three >> 8) & 0xFF] ^ - Crc32Lookup[ 7][ three & 0xFF] ^ - Crc32Lookup[ 8][(two >> 24) & 0xFF] ^ - Crc32Lookup[ 9][(two >> 16) & 0xFF] ^ - Crc32Lookup[10][(two >> 8) & 0xFF] ^ - Crc32Lookup[11][ two & 0xFF] ^ - Crc32Lookup[12][(one >> 24) & 0xFF] ^ - Crc32Lookup[13][(one >> 16) & 0xFF] ^ - Crc32Lookup[14][(one >> 8) & 0xFF] ^ - Crc32Lookup[15][ one & 0xFF]; -#endif - } - - length -= BytesAtOnce; - } - - const uint8_t* currentChar = (const uint8_t*) current; - // remaining 1 to 63 bytes (standard algorithm) - while (length-- != 0) - crc = (crc >> 8) ^ Crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; - - return ~crc; // same as crc ^ 0xFFFFFFFF -} -#endif - - -/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs -uint32_t crc32_fast(const void* data, size_t length, uint32_t previousCrc32) -{ -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 - return crc32_16bytes (data, length, previousCrc32); -#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) - return crc32_8bytes (data, length, previousCrc32); -#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) - return crc32_4bytes (data, length, previousCrc32); -#elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) - return crc32_1byte (data, length, previousCrc32); -#else - return crc32_halfbyte(data, length, previousCrc32); -#endif -} - - -/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA)) -uint32_t crc32_combine(uint32_t crcA, uint32_t crcB, size_t lengthB) -{ - // based on Mark Adler's crc_combine from - // https://github.com/madler/pigz/blob/master/pigz.c - - // main idea: - // - if you have two equally-sized blocks A and B, - // then you can create a block C = A ^ B - // which has the property crc(C) = crc(A) ^ crc(B) - // - if you append length(B) zeros to A and call it A' (think of it as AAAA000) - // and prepend length(A) zeros to B and call it B' (think of it as 0000BBB) - // then exists a C' = A' ^ B' - // - remember: if you XOR someting with zero, it remains unchanged: X ^ 0 = X - // - that means C' = A concat B so that crc(A concat B) = crc(C') = crc(A') ^ crc(B') - // - the trick is to compute crc(A') based on crc(A) - // and crc(B') based on crc(B) - // - since B' starts with many zeros, the crc of those initial zeros is still zero - // - that means crc(B') = crc(B) - // - unfortunately the trailing zeros of A' change the crc, so usually crc(A') != crc(A) - // - the following code is a fast algorithm to compute crc(A') - // - starting with crc(A) and appending length(B) zeros, needing just log2(length(B)) iterations - // - the details are explained by the original author at - // https://stackoverflow.com/questions/23122312/crc-calculation-of-a-mostly-static-data-stream/23126768 - // - // notes: - // - I squeezed everything into one function to keep global namespace clean (original code two helper functions) - // - most original comments are still in place, I added comments where these helper functions where made inline code - // - performance-wise there isn't any differenze to the original zlib/pigz code - - // degenerated case - if (lengthB == 0) - return crcA; - - /// CRC32 => 32 bits - const uint32_t CrcBits = 32; - - uint32_t odd [CrcBits]; // odd-power-of-two zeros operator - uint32_t even[CrcBits]; // even-power-of-two zeros operator - - // put operator for one zero bit in odd - odd[0] = Polynomial; // CRC-32 polynomial - for (int i = 1; i < (int)CrcBits; i++) - odd[i] = 1 << (i - 1); - - // put operator for two zero bits in even - // same as gf2_matrix_square(even, odd); - for (int i = 0; i < (int)CrcBits; i++) - { - uint32_t vec = odd[i]; - even[i] = 0; - for (int j = 0; vec != 0; j++, vec >>= 1) - if (vec & 1) - even[i] ^= odd[j]; - } - // put operator for four zero bits in odd - // same as gf2_matrix_square(odd, even); - for (int i = 0; i < (int)CrcBits; i++) - { - uint32_t vec = even[i]; - odd[i] = 0; - for (int j = 0; vec != 0; j++, vec >>= 1) - if (vec & 1) - odd[i] ^= even[j]; - } - - // the following loop becomes much shorter if I keep swapping even and odd - uint32_t* a = even; - uint32_t* b = odd; - // apply secondLength zeros to firstCrc32 - for (; lengthB > 0; lengthB >>= 1) - { - // same as gf2_matrix_square(a, b); - for (int i = 0; i < (int)CrcBits; i++) - { - uint32_t vec = b[i]; - a[i] = 0; - for (int j = 0; vec != 0; j++, vec >>= 1) - if (vec & 1) - a[i] ^= b[j]; - } - - // apply zeros operator for this bit - if (lengthB & 1) - { - // same as firstCrc32 = gf2_matrix_times(a, firstCrc32); - uint32_t sum = 0; - for (int i = 0; crcA != 0; i++, crcA >>= 1) - if (crcA & 1) - sum ^= a[i]; - crcA = sum; - } - - // switch even and odd - uint32_t* t = a; a = b; b = t; - } - - // return combined crc - return crcA ^ crcB; -} - - -// ////////////////////////////////////////////////////////// -// constants - - -#ifndef NO_LUT -/// look-up table, already declared above -const uint32_t Crc32Lookup[MaxSlice][256] = -{ - //// same algorithm as crc32_bitwise - //for (int i = 0; i <= 0xFF; i++) - //{ - // uint32_t crc = i; - // for (int j = 0; j < 8; j++) - // crc = (crc >> 1) ^ ((crc & 1) * Polynomial); - // Crc32Lookup[0][i] = crc; - //} - //// ... and the following slicing-by-8 algorithm (from Intel): - //// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf - //// http://sourceforge.net/projects/slicing-by-8/ - //for (int slice = 1; slice < MaxSlice; slice++) - // Crc32Lookup[slice][i] = (Crc32Lookup[slice - 1][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[slice - 1][i] & 0xFF]; - { - // note: the first number of every second row corresponds to the half-byte look-up table ! - 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535,0x9E6495A3, - 0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD,0xE7B82D07,0x90BF1D91, - 0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D,0x6DDDE4EB,0xF4D4B551,0x83D385C7, - 0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC,0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5, - 0x3B6E20C8,0x4C69105E,0xD56041E4,0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B, - 0x35B5A8FA,0x42B2986C,0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59, - 0x26D930AC,0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, - 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB,0xB6662D3D, - 0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F,0x9FBFE4A5,0xE8B8D433, - 0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB,0x086D3D2D,0x91646C97,0xE6635C01, - 0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E,0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457, - 0x65B0D9C6,0x12B7E950,0x8BBEB8EA,0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65, - 0x4DB26158,0x3AB551CE,0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB, - 0x4369E96A,0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, - 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409,0xCE61E49F, - 0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81,0xB7BD5C3B,0xC0BA6CAD, - 0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739,0x9DD277AF,0x04DB2615,0x73DC1683, - 0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8,0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1, - 0xF00F9344,0x8708A3D2,0x1E01F268,0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7, - 0xFED41B76,0x89D32BE0,0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5, - 0xD6D6A3E8,0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, - 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF,0x4669BE79, - 0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703,0x220216B9,0x5505262F, - 0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7,0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D, - 0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A,0x9C0906A9,0xEB0E363F,0x72076785,0x05005713, - 0x95BF4A82,0xE2B87A14,0x7BB12BAE,0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21, - 0x86D3D2D4,0xF1D4E242,0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777, - 0x88085AE6,0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, - 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D,0x3E6E77DB, - 0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5,0x47B2CF7F,0x30B5FFE9, - 0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605,0xCDD70693,0x54DE5729,0x23D967BF, - 0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94,0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D, - } - -#if defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) - // beyond this point only relevant for Slicing-by-4, Slicing-by-8 and Slicing-by-16 - ,{ - 0x00000000,0x191B3141,0x32366282,0x2B2D53C3,0x646CC504,0x7D77F445,0x565AA786,0x4F4196C7, - 0xC8D98A08,0xD1C2BB49,0xFAEFE88A,0xE3F4D9CB,0xACB54F0C,0xB5AE7E4D,0x9E832D8E,0x87981CCF, - 0x4AC21251,0x53D92310,0x78F470D3,0x61EF4192,0x2EAED755,0x37B5E614,0x1C98B5D7,0x05838496, - 0x821B9859,0x9B00A918,0xB02DFADB,0xA936CB9A,0xE6775D5D,0xFF6C6C1C,0xD4413FDF,0xCD5A0E9E, - 0x958424A2,0x8C9F15E3,0xA7B24620,0xBEA97761,0xF1E8E1A6,0xE8F3D0E7,0xC3DE8324,0xDAC5B265, - 0x5D5DAEAA,0x44469FEB,0x6F6BCC28,0x7670FD69,0x39316BAE,0x202A5AEF,0x0B07092C,0x121C386D, - 0xDF4636F3,0xC65D07B2,0xED705471,0xF46B6530,0xBB2AF3F7,0xA231C2B6,0x891C9175,0x9007A034, - 0x179FBCFB,0x0E848DBA,0x25A9DE79,0x3CB2EF38,0x73F379FF,0x6AE848BE,0x41C51B7D,0x58DE2A3C, - 0xF0794F05,0xE9627E44,0xC24F2D87,0xDB541CC6,0x94158A01,0x8D0EBB40,0xA623E883,0xBF38D9C2, - 0x38A0C50D,0x21BBF44C,0x0A96A78F,0x138D96CE,0x5CCC0009,0x45D73148,0x6EFA628B,0x77E153CA, - 0xBABB5D54,0xA3A06C15,0x888D3FD6,0x91960E97,0xDED79850,0xC7CCA911,0xECE1FAD2,0xF5FACB93, - 0x7262D75C,0x6B79E61D,0x4054B5DE,0x594F849F,0x160E1258,0x0F152319,0x243870DA,0x3D23419B, - 0x65FD6BA7,0x7CE65AE6,0x57CB0925,0x4ED03864,0x0191AEA3,0x188A9FE2,0x33A7CC21,0x2ABCFD60, - 0xAD24E1AF,0xB43FD0EE,0x9F12832D,0x8609B26C,0xC94824AB,0xD05315EA,0xFB7E4629,0xE2657768, - 0x2F3F79F6,0x362448B7,0x1D091B74,0x04122A35,0x4B53BCF2,0x52488DB3,0x7965DE70,0x607EEF31, - 0xE7E6F3FE,0xFEFDC2BF,0xD5D0917C,0xCCCBA03D,0x838A36FA,0x9A9107BB,0xB1BC5478,0xA8A76539, - 0x3B83984B,0x2298A90A,0x09B5FAC9,0x10AECB88,0x5FEF5D4F,0x46F46C0E,0x6DD93FCD,0x74C20E8C, - 0xF35A1243,0xEA412302,0xC16C70C1,0xD8774180,0x9736D747,0x8E2DE606,0xA500B5C5,0xBC1B8484, - 0x71418A1A,0x685ABB5B,0x4377E898,0x5A6CD9D9,0x152D4F1E,0x0C367E5F,0x271B2D9C,0x3E001CDD, - 0xB9980012,0xA0833153,0x8BAE6290,0x92B553D1,0xDDF4C516,0xC4EFF457,0xEFC2A794,0xF6D996D5, - 0xAE07BCE9,0xB71C8DA8,0x9C31DE6B,0x852AEF2A,0xCA6B79ED,0xD37048AC,0xF85D1B6F,0xE1462A2E, - 0x66DE36E1,0x7FC507A0,0x54E85463,0x4DF36522,0x02B2F3E5,0x1BA9C2A4,0x30849167,0x299FA026, - 0xE4C5AEB8,0xFDDE9FF9,0xD6F3CC3A,0xCFE8FD7B,0x80A96BBC,0x99B25AFD,0xB29F093E,0xAB84387F, - 0x2C1C24B0,0x350715F1,0x1E2A4632,0x07317773,0x4870E1B4,0x516BD0F5,0x7A468336,0x635DB277, - 0xCBFAD74E,0xD2E1E60F,0xF9CCB5CC,0xE0D7848D,0xAF96124A,0xB68D230B,0x9DA070C8,0x84BB4189, - 0x03235D46,0x1A386C07,0x31153FC4,0x280E0E85,0x674F9842,0x7E54A903,0x5579FAC0,0x4C62CB81, - 0x8138C51F,0x9823F45E,0xB30EA79D,0xAA1596DC,0xE554001B,0xFC4F315A,0xD7626299,0xCE7953D8, - 0x49E14F17,0x50FA7E56,0x7BD72D95,0x62CC1CD4,0x2D8D8A13,0x3496BB52,0x1FBBE891,0x06A0D9D0, - 0x5E7EF3EC,0x4765C2AD,0x6C48916E,0x7553A02F,0x3A1236E8,0x230907A9,0x0824546A,0x113F652B, - 0x96A779E4,0x8FBC48A5,0xA4911B66,0xBD8A2A27,0xF2CBBCE0,0xEBD08DA1,0xC0FDDE62,0xD9E6EF23, - 0x14BCE1BD,0x0DA7D0FC,0x268A833F,0x3F91B27E,0x70D024B9,0x69CB15F8,0x42E6463B,0x5BFD777A, - 0xDC656BB5,0xC57E5AF4,0xEE530937,0xF7483876,0xB809AEB1,0xA1129FF0,0x8A3FCC33,0x9324FD72, - }, - - { - 0x00000000,0x01C26A37,0x0384D46E,0x0246BE59,0x0709A8DC,0x06CBC2EB,0x048D7CB2,0x054F1685, - 0x0E1351B8,0x0FD13B8F,0x0D9785D6,0x0C55EFE1,0x091AF964,0x08D89353,0x0A9E2D0A,0x0B5C473D, - 0x1C26A370,0x1DE4C947,0x1FA2771E,0x1E601D29,0x1B2F0BAC,0x1AED619B,0x18ABDFC2,0x1969B5F5, - 0x1235F2C8,0x13F798FF,0x11B126A6,0x10734C91,0x153C5A14,0x14FE3023,0x16B88E7A,0x177AE44D, - 0x384D46E0,0x398F2CD7,0x3BC9928E,0x3A0BF8B9,0x3F44EE3C,0x3E86840B,0x3CC03A52,0x3D025065, - 0x365E1758,0x379C7D6F,0x35DAC336,0x3418A901,0x3157BF84,0x3095D5B3,0x32D36BEA,0x331101DD, - 0x246BE590,0x25A98FA7,0x27EF31FE,0x262D5BC9,0x23624D4C,0x22A0277B,0x20E69922,0x2124F315, - 0x2A78B428,0x2BBADE1F,0x29FC6046,0x283E0A71,0x2D711CF4,0x2CB376C3,0x2EF5C89A,0x2F37A2AD, - 0x709A8DC0,0x7158E7F7,0x731E59AE,0x72DC3399,0x7793251C,0x76514F2B,0x7417F172,0x75D59B45, - 0x7E89DC78,0x7F4BB64F,0x7D0D0816,0x7CCF6221,0x798074A4,0x78421E93,0x7A04A0CA,0x7BC6CAFD, - 0x6CBC2EB0,0x6D7E4487,0x6F38FADE,0x6EFA90E9,0x6BB5866C,0x6A77EC5B,0x68315202,0x69F33835, - 0x62AF7F08,0x636D153F,0x612BAB66,0x60E9C151,0x65A6D7D4,0x6464BDE3,0x662203BA,0x67E0698D, - 0x48D7CB20,0x4915A117,0x4B531F4E,0x4A917579,0x4FDE63FC,0x4E1C09CB,0x4C5AB792,0x4D98DDA5, - 0x46C49A98,0x4706F0AF,0x45404EF6,0x448224C1,0x41CD3244,0x400F5873,0x4249E62A,0x438B8C1D, - 0x54F16850,0x55330267,0x5775BC3E,0x56B7D609,0x53F8C08C,0x523AAABB,0x507C14E2,0x51BE7ED5, - 0x5AE239E8,0x5B2053DF,0x5966ED86,0x58A487B1,0x5DEB9134,0x5C29FB03,0x5E6F455A,0x5FAD2F6D, - 0xE1351B80,0xE0F771B7,0xE2B1CFEE,0xE373A5D9,0xE63CB35C,0xE7FED96B,0xE5B86732,0xE47A0D05, - 0xEF264A38,0xEEE4200F,0xECA29E56,0xED60F461,0xE82FE2E4,0xE9ED88D3,0xEBAB368A,0xEA695CBD, - 0xFD13B8F0,0xFCD1D2C7,0xFE976C9E,0xFF5506A9,0xFA1A102C,0xFBD87A1B,0xF99EC442,0xF85CAE75, - 0xF300E948,0xF2C2837F,0xF0843D26,0xF1465711,0xF4094194,0xF5CB2BA3,0xF78D95FA,0xF64FFFCD, - 0xD9785D60,0xD8BA3757,0xDAFC890E,0xDB3EE339,0xDE71F5BC,0xDFB39F8B,0xDDF521D2,0xDC374BE5, - 0xD76B0CD8,0xD6A966EF,0xD4EFD8B6,0xD52DB281,0xD062A404,0xD1A0CE33,0xD3E6706A,0xD2241A5D, - 0xC55EFE10,0xC49C9427,0xC6DA2A7E,0xC7184049,0xC25756CC,0xC3953CFB,0xC1D382A2,0xC011E895, - 0xCB4DAFA8,0xCA8FC59F,0xC8C97BC6,0xC90B11F1,0xCC440774,0xCD866D43,0xCFC0D31A,0xCE02B92D, - 0x91AF9640,0x906DFC77,0x922B422E,0x93E92819,0x96A63E9C,0x976454AB,0x9522EAF2,0x94E080C5, - 0x9FBCC7F8,0x9E7EADCF,0x9C381396,0x9DFA79A1,0x98B56F24,0x99770513,0x9B31BB4A,0x9AF3D17D, - 0x8D893530,0x8C4B5F07,0x8E0DE15E,0x8FCF8B69,0x8A809DEC,0x8B42F7DB,0x89044982,0x88C623B5, - 0x839A6488,0x82580EBF,0x801EB0E6,0x81DCDAD1,0x8493CC54,0x8551A663,0x8717183A,0x86D5720D, - 0xA9E2D0A0,0xA820BA97,0xAA6604CE,0xABA46EF9,0xAEEB787C,0xAF29124B,0xAD6FAC12,0xACADC625, - 0xA7F18118,0xA633EB2F,0xA4755576,0xA5B73F41,0xA0F829C4,0xA13A43F3,0xA37CFDAA,0xA2BE979D, - 0xB5C473D0,0xB40619E7,0xB640A7BE,0xB782CD89,0xB2CDDB0C,0xB30FB13B,0xB1490F62,0xB08B6555, - 0xBBD72268,0xBA15485F,0xB853F606,0xB9919C31,0xBCDE8AB4,0xBD1CE083,0xBF5A5EDA,0xBE9834ED, - }, - - { - 0x00000000,0xB8BC6765,0xAA09C88B,0x12B5AFEE,0x8F629757,0x37DEF032,0x256B5FDC,0x9DD738B9, - 0xC5B428EF,0x7D084F8A,0x6FBDE064,0xD7018701,0x4AD6BFB8,0xF26AD8DD,0xE0DF7733,0x58631056, - 0x5019579F,0xE8A530FA,0xFA109F14,0x42ACF871,0xDF7BC0C8,0x67C7A7AD,0x75720843,0xCDCE6F26, - 0x95AD7F70,0x2D111815,0x3FA4B7FB,0x8718D09E,0x1ACFE827,0xA2738F42,0xB0C620AC,0x087A47C9, - 0xA032AF3E,0x188EC85B,0x0A3B67B5,0xB28700D0,0x2F503869,0x97EC5F0C,0x8559F0E2,0x3DE59787, - 0x658687D1,0xDD3AE0B4,0xCF8F4F5A,0x7733283F,0xEAE41086,0x525877E3,0x40EDD80D,0xF851BF68, - 0xF02BF8A1,0x48979FC4,0x5A22302A,0xE29E574F,0x7F496FF6,0xC7F50893,0xD540A77D,0x6DFCC018, - 0x359FD04E,0x8D23B72B,0x9F9618C5,0x272A7FA0,0xBAFD4719,0x0241207C,0x10F48F92,0xA848E8F7, - 0x9B14583D,0x23A83F58,0x311D90B6,0x89A1F7D3,0x1476CF6A,0xACCAA80F,0xBE7F07E1,0x06C36084, - 0x5EA070D2,0xE61C17B7,0xF4A9B859,0x4C15DF3C,0xD1C2E785,0x697E80E0,0x7BCB2F0E,0xC377486B, - 0xCB0D0FA2,0x73B168C7,0x6104C729,0xD9B8A04C,0x446F98F5,0xFCD3FF90,0xEE66507E,0x56DA371B, - 0x0EB9274D,0xB6054028,0xA4B0EFC6,0x1C0C88A3,0x81DBB01A,0x3967D77F,0x2BD27891,0x936E1FF4, - 0x3B26F703,0x839A9066,0x912F3F88,0x299358ED,0xB4446054,0x0CF80731,0x1E4DA8DF,0xA6F1CFBA, - 0xFE92DFEC,0x462EB889,0x549B1767,0xEC277002,0x71F048BB,0xC94C2FDE,0xDBF98030,0x6345E755, - 0x6B3FA09C,0xD383C7F9,0xC1366817,0x798A0F72,0xE45D37CB,0x5CE150AE,0x4E54FF40,0xF6E89825, - 0xAE8B8873,0x1637EF16,0x048240F8,0xBC3E279D,0x21E91F24,0x99557841,0x8BE0D7AF,0x335CB0CA, - 0xED59B63B,0x55E5D15E,0x47507EB0,0xFFEC19D5,0x623B216C,0xDA874609,0xC832E9E7,0x708E8E82, - 0x28ED9ED4,0x9051F9B1,0x82E4565F,0x3A58313A,0xA78F0983,0x1F336EE6,0x0D86C108,0xB53AA66D, - 0xBD40E1A4,0x05FC86C1,0x1749292F,0xAFF54E4A,0x322276F3,0x8A9E1196,0x982BBE78,0x2097D91D, - 0x78F4C94B,0xC048AE2E,0xD2FD01C0,0x6A4166A5,0xF7965E1C,0x4F2A3979,0x5D9F9697,0xE523F1F2, - 0x4D6B1905,0xF5D77E60,0xE762D18E,0x5FDEB6EB,0xC2098E52,0x7AB5E937,0x680046D9,0xD0BC21BC, - 0x88DF31EA,0x3063568F,0x22D6F961,0x9A6A9E04,0x07BDA6BD,0xBF01C1D8,0xADB46E36,0x15080953, - 0x1D724E9A,0xA5CE29FF,0xB77B8611,0x0FC7E174,0x9210D9CD,0x2AACBEA8,0x38191146,0x80A57623, - 0xD8C66675,0x607A0110,0x72CFAEFE,0xCA73C99B,0x57A4F122,0xEF189647,0xFDAD39A9,0x45115ECC, - 0x764DEE06,0xCEF18963,0xDC44268D,0x64F841E8,0xF92F7951,0x41931E34,0x5326B1DA,0xEB9AD6BF, - 0xB3F9C6E9,0x0B45A18C,0x19F00E62,0xA14C6907,0x3C9B51BE,0x842736DB,0x96929935,0x2E2EFE50, - 0x2654B999,0x9EE8DEFC,0x8C5D7112,0x34E11677,0xA9362ECE,0x118A49AB,0x033FE645,0xBB838120, - 0xE3E09176,0x5B5CF613,0x49E959FD,0xF1553E98,0x6C820621,0xD43E6144,0xC68BCEAA,0x7E37A9CF, - 0xD67F4138,0x6EC3265D,0x7C7689B3,0xC4CAEED6,0x591DD66F,0xE1A1B10A,0xF3141EE4,0x4BA87981, - 0x13CB69D7,0xAB770EB2,0xB9C2A15C,0x017EC639,0x9CA9FE80,0x241599E5,0x36A0360B,0x8E1C516E, - 0x866616A7,0x3EDA71C2,0x2C6FDE2C,0x94D3B949,0x090481F0,0xB1B8E695,0xA30D497B,0x1BB12E1E, - 0x43D23E48,0xFB6E592D,0xE9DBF6C3,0x516791A6,0xCCB0A91F,0x740CCE7A,0x66B96194,0xDE0506F1, - } -#endif // defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) -#if defined (CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) - // beyond this point only relevant for Slicing-by-8 and Slicing-by-16 - ,{ - 0x00000000,0x3D6029B0,0x7AC05360,0x47A07AD0,0xF580A6C0,0xC8E08F70,0x8F40F5A0,0xB220DC10, - 0x30704BC1,0x0D106271,0x4AB018A1,0x77D03111,0xC5F0ED01,0xF890C4B1,0xBF30BE61,0x825097D1, - 0x60E09782,0x5D80BE32,0x1A20C4E2,0x2740ED52,0x95603142,0xA80018F2,0xEFA06222,0xD2C04B92, - 0x5090DC43,0x6DF0F5F3,0x2A508F23,0x1730A693,0xA5107A83,0x98705333,0xDFD029E3,0xE2B00053, - 0xC1C12F04,0xFCA106B4,0xBB017C64,0x866155D4,0x344189C4,0x0921A074,0x4E81DAA4,0x73E1F314, - 0xF1B164C5,0xCCD14D75,0x8B7137A5,0xB6111E15,0x0431C205,0x3951EBB5,0x7EF19165,0x4391B8D5, - 0xA121B886,0x9C419136,0xDBE1EBE6,0xE681C256,0x54A11E46,0x69C137F6,0x2E614D26,0x13016496, - 0x9151F347,0xAC31DAF7,0xEB91A027,0xD6F18997,0x64D15587,0x59B17C37,0x1E1106E7,0x23712F57, - 0x58F35849,0x659371F9,0x22330B29,0x1F532299,0xAD73FE89,0x9013D739,0xD7B3ADE9,0xEAD38459, - 0x68831388,0x55E33A38,0x124340E8,0x2F236958,0x9D03B548,0xA0639CF8,0xE7C3E628,0xDAA3CF98, - 0x3813CFCB,0x0573E67B,0x42D39CAB,0x7FB3B51B,0xCD93690B,0xF0F340BB,0xB7533A6B,0x8A3313DB, - 0x0863840A,0x3503ADBA,0x72A3D76A,0x4FC3FEDA,0xFDE322CA,0xC0830B7A,0x872371AA,0xBA43581A, - 0x9932774D,0xA4525EFD,0xE3F2242D,0xDE920D9D,0x6CB2D18D,0x51D2F83D,0x167282ED,0x2B12AB5D, - 0xA9423C8C,0x9422153C,0xD3826FEC,0xEEE2465C,0x5CC29A4C,0x61A2B3FC,0x2602C92C,0x1B62E09C, - 0xF9D2E0CF,0xC4B2C97F,0x8312B3AF,0xBE729A1F,0x0C52460F,0x31326FBF,0x7692156F,0x4BF23CDF, - 0xC9A2AB0E,0xF4C282BE,0xB362F86E,0x8E02D1DE,0x3C220DCE,0x0142247E,0x46E25EAE,0x7B82771E, - 0xB1E6B092,0x8C869922,0xCB26E3F2,0xF646CA42,0x44661652,0x79063FE2,0x3EA64532,0x03C66C82, - 0x8196FB53,0xBCF6D2E3,0xFB56A833,0xC6368183,0x74165D93,0x49767423,0x0ED60EF3,0x33B62743, - 0xD1062710,0xEC660EA0,0xABC67470,0x96A65DC0,0x248681D0,0x19E6A860,0x5E46D2B0,0x6326FB00, - 0xE1766CD1,0xDC164561,0x9BB63FB1,0xA6D61601,0x14F6CA11,0x2996E3A1,0x6E369971,0x5356B0C1, - 0x70279F96,0x4D47B626,0x0AE7CCF6,0x3787E546,0x85A73956,0xB8C710E6,0xFF676A36,0xC2074386, - 0x4057D457,0x7D37FDE7,0x3A978737,0x07F7AE87,0xB5D77297,0x88B75B27,0xCF1721F7,0xF2770847, - 0x10C70814,0x2DA721A4,0x6A075B74,0x576772C4,0xE547AED4,0xD8278764,0x9F87FDB4,0xA2E7D404, - 0x20B743D5,0x1DD76A65,0x5A7710B5,0x67173905,0xD537E515,0xE857CCA5,0xAFF7B675,0x92979FC5, - 0xE915E8DB,0xD475C16B,0x93D5BBBB,0xAEB5920B,0x1C954E1B,0x21F567AB,0x66551D7B,0x5B3534CB, - 0xD965A31A,0xE4058AAA,0xA3A5F07A,0x9EC5D9CA,0x2CE505DA,0x11852C6A,0x562556BA,0x6B457F0A, - 0x89F57F59,0xB49556E9,0xF3352C39,0xCE550589,0x7C75D999,0x4115F029,0x06B58AF9,0x3BD5A349, - 0xB9853498,0x84E51D28,0xC34567F8,0xFE254E48,0x4C059258,0x7165BBE8,0x36C5C138,0x0BA5E888, - 0x28D4C7DF,0x15B4EE6F,0x521494BF,0x6F74BD0F,0xDD54611F,0xE03448AF,0xA794327F,0x9AF41BCF, - 0x18A48C1E,0x25C4A5AE,0x6264DF7E,0x5F04F6CE,0xED242ADE,0xD044036E,0x97E479BE,0xAA84500E, - 0x4834505D,0x755479ED,0x32F4033D,0x0F942A8D,0xBDB4F69D,0x80D4DF2D,0xC774A5FD,0xFA148C4D, - 0x78441B9C,0x4524322C,0x028448FC,0x3FE4614C,0x8DC4BD5C,0xB0A494EC,0xF704EE3C,0xCA64C78C, - }, - - { - 0x00000000,0xCB5CD3A5,0x4DC8A10B,0x869472AE,0x9B914216,0x50CD91B3,0xD659E31D,0x1D0530B8, - 0xEC53826D,0x270F51C8,0xA19B2366,0x6AC7F0C3,0x77C2C07B,0xBC9E13DE,0x3A0A6170,0xF156B2D5, - 0x03D6029B,0xC88AD13E,0x4E1EA390,0x85427035,0x9847408D,0x531B9328,0xD58FE186,0x1ED33223, - 0xEF8580F6,0x24D95353,0xA24D21FD,0x6911F258,0x7414C2E0,0xBF481145,0x39DC63EB,0xF280B04E, - 0x07AC0536,0xCCF0D693,0x4A64A43D,0x81387798,0x9C3D4720,0x57619485,0xD1F5E62B,0x1AA9358E, - 0xEBFF875B,0x20A354FE,0xA6372650,0x6D6BF5F5,0x706EC54D,0xBB3216E8,0x3DA66446,0xF6FAB7E3, - 0x047A07AD,0xCF26D408,0x49B2A6A6,0x82EE7503,0x9FEB45BB,0x54B7961E,0xD223E4B0,0x197F3715, - 0xE82985C0,0x23755665,0xA5E124CB,0x6EBDF76E,0x73B8C7D6,0xB8E41473,0x3E7066DD,0xF52CB578, - 0x0F580A6C,0xC404D9C9,0x4290AB67,0x89CC78C2,0x94C9487A,0x5F959BDF,0xD901E971,0x125D3AD4, - 0xE30B8801,0x28575BA4,0xAEC3290A,0x659FFAAF,0x789ACA17,0xB3C619B2,0x35526B1C,0xFE0EB8B9, - 0x0C8E08F7,0xC7D2DB52,0x4146A9FC,0x8A1A7A59,0x971F4AE1,0x5C439944,0xDAD7EBEA,0x118B384F, - 0xE0DD8A9A,0x2B81593F,0xAD152B91,0x6649F834,0x7B4CC88C,0xB0101B29,0x36846987,0xFDD8BA22, - 0x08F40F5A,0xC3A8DCFF,0x453CAE51,0x8E607DF4,0x93654D4C,0x58399EE9,0xDEADEC47,0x15F13FE2, - 0xE4A78D37,0x2FFB5E92,0xA96F2C3C,0x6233FF99,0x7F36CF21,0xB46A1C84,0x32FE6E2A,0xF9A2BD8F, - 0x0B220DC1,0xC07EDE64,0x46EAACCA,0x8DB67F6F,0x90B34FD7,0x5BEF9C72,0xDD7BEEDC,0x16273D79, - 0xE7718FAC,0x2C2D5C09,0xAAB92EA7,0x61E5FD02,0x7CE0CDBA,0xB7BC1E1F,0x31286CB1,0xFA74BF14, - 0x1EB014D8,0xD5ECC77D,0x5378B5D3,0x98246676,0x852156CE,0x4E7D856B,0xC8E9F7C5,0x03B52460, - 0xF2E396B5,0x39BF4510,0xBF2B37BE,0x7477E41B,0x6972D4A3,0xA22E0706,0x24BA75A8,0xEFE6A60D, - 0x1D661643,0xD63AC5E6,0x50AEB748,0x9BF264ED,0x86F75455,0x4DAB87F0,0xCB3FF55E,0x006326FB, - 0xF135942E,0x3A69478B,0xBCFD3525,0x77A1E680,0x6AA4D638,0xA1F8059D,0x276C7733,0xEC30A496, - 0x191C11EE,0xD240C24B,0x54D4B0E5,0x9F886340,0x828D53F8,0x49D1805D,0xCF45F2F3,0x04192156, - 0xF54F9383,0x3E134026,0xB8873288,0x73DBE12D,0x6EDED195,0xA5820230,0x2316709E,0xE84AA33B, - 0x1ACA1375,0xD196C0D0,0x5702B27E,0x9C5E61DB,0x815B5163,0x4A0782C6,0xCC93F068,0x07CF23CD, - 0xF6999118,0x3DC542BD,0xBB513013,0x700DE3B6,0x6D08D30E,0xA65400AB,0x20C07205,0xEB9CA1A0, - 0x11E81EB4,0xDAB4CD11,0x5C20BFBF,0x977C6C1A,0x8A795CA2,0x41258F07,0xC7B1FDA9,0x0CED2E0C, - 0xFDBB9CD9,0x36E74F7C,0xB0733DD2,0x7B2FEE77,0x662ADECF,0xAD760D6A,0x2BE27FC4,0xE0BEAC61, - 0x123E1C2F,0xD962CF8A,0x5FF6BD24,0x94AA6E81,0x89AF5E39,0x42F38D9C,0xC467FF32,0x0F3B2C97, - 0xFE6D9E42,0x35314DE7,0xB3A53F49,0x78F9ECEC,0x65FCDC54,0xAEA00FF1,0x28347D5F,0xE368AEFA, - 0x16441B82,0xDD18C827,0x5B8CBA89,0x90D0692C,0x8DD55994,0x46898A31,0xC01DF89F,0x0B412B3A, - 0xFA1799EF,0x314B4A4A,0xB7DF38E4,0x7C83EB41,0x6186DBF9,0xAADA085C,0x2C4E7AF2,0xE712A957, - 0x15921919,0xDECECABC,0x585AB812,0x93066BB7,0x8E035B0F,0x455F88AA,0xC3CBFA04,0x089729A1, - 0xF9C19B74,0x329D48D1,0xB4093A7F,0x7F55E9DA,0x6250D962,0xA90C0AC7,0x2F987869,0xE4C4ABCC, - }, - - { - 0x00000000,0xA6770BB4,0x979F1129,0x31E81A9D,0xF44F2413,0x52382FA7,0x63D0353A,0xC5A73E8E, - 0x33EF4E67,0x959845D3,0xA4705F4E,0x020754FA,0xC7A06A74,0x61D761C0,0x503F7B5D,0xF64870E9, - 0x67DE9CCE,0xC1A9977A,0xF0418DE7,0x56368653,0x9391B8DD,0x35E6B369,0x040EA9F4,0xA279A240, - 0x5431D2A9,0xF246D91D,0xC3AEC380,0x65D9C834,0xA07EF6BA,0x0609FD0E,0x37E1E793,0x9196EC27, - 0xCFBD399C,0x69CA3228,0x582228B5,0xFE552301,0x3BF21D8F,0x9D85163B,0xAC6D0CA6,0x0A1A0712, - 0xFC5277FB,0x5A257C4F,0x6BCD66D2,0xCDBA6D66,0x081D53E8,0xAE6A585C,0x9F8242C1,0x39F54975, - 0xA863A552,0x0E14AEE6,0x3FFCB47B,0x998BBFCF,0x5C2C8141,0xFA5B8AF5,0xCBB39068,0x6DC49BDC, - 0x9B8CEB35,0x3DFBE081,0x0C13FA1C,0xAA64F1A8,0x6FC3CF26,0xC9B4C492,0xF85CDE0F,0x5E2BD5BB, - 0x440B7579,0xE27C7ECD,0xD3946450,0x75E36FE4,0xB044516A,0x16335ADE,0x27DB4043,0x81AC4BF7, - 0x77E43B1E,0xD19330AA,0xE07B2A37,0x460C2183,0x83AB1F0D,0x25DC14B9,0x14340E24,0xB2430590, - 0x23D5E9B7,0x85A2E203,0xB44AF89E,0x123DF32A,0xD79ACDA4,0x71EDC610,0x4005DC8D,0xE672D739, - 0x103AA7D0,0xB64DAC64,0x87A5B6F9,0x21D2BD4D,0xE47583C3,0x42028877,0x73EA92EA,0xD59D995E, - 0x8BB64CE5,0x2DC14751,0x1C295DCC,0xBA5E5678,0x7FF968F6,0xD98E6342,0xE86679DF,0x4E11726B, - 0xB8590282,0x1E2E0936,0x2FC613AB,0x89B1181F,0x4C162691,0xEA612D25,0xDB8937B8,0x7DFE3C0C, - 0xEC68D02B,0x4A1FDB9F,0x7BF7C102,0xDD80CAB6,0x1827F438,0xBE50FF8C,0x8FB8E511,0x29CFEEA5, - 0xDF879E4C,0x79F095F8,0x48188F65,0xEE6F84D1,0x2BC8BA5F,0x8DBFB1EB,0xBC57AB76,0x1A20A0C2, - 0x8816EAF2,0x2E61E146,0x1F89FBDB,0xB9FEF06F,0x7C59CEE1,0xDA2EC555,0xEBC6DFC8,0x4DB1D47C, - 0xBBF9A495,0x1D8EAF21,0x2C66B5BC,0x8A11BE08,0x4FB68086,0xE9C18B32,0xD82991AF,0x7E5E9A1B, - 0xEFC8763C,0x49BF7D88,0x78576715,0xDE206CA1,0x1B87522F,0xBDF0599B,0x8C184306,0x2A6F48B2, - 0xDC27385B,0x7A5033EF,0x4BB82972,0xEDCF22C6,0x28681C48,0x8E1F17FC,0xBFF70D61,0x198006D5, - 0x47ABD36E,0xE1DCD8DA,0xD034C247,0x7643C9F3,0xB3E4F77D,0x1593FCC9,0x247BE654,0x820CEDE0, - 0x74449D09,0xD23396BD,0xE3DB8C20,0x45AC8794,0x800BB91A,0x267CB2AE,0x1794A833,0xB1E3A387, - 0x20754FA0,0x86024414,0xB7EA5E89,0x119D553D,0xD43A6BB3,0x724D6007,0x43A57A9A,0xE5D2712E, - 0x139A01C7,0xB5ED0A73,0x840510EE,0x22721B5A,0xE7D525D4,0x41A22E60,0x704A34FD,0xD63D3F49, - 0xCC1D9F8B,0x6A6A943F,0x5B828EA2,0xFDF58516,0x3852BB98,0x9E25B02C,0xAFCDAAB1,0x09BAA105, - 0xFFF2D1EC,0x5985DA58,0x686DC0C5,0xCE1ACB71,0x0BBDF5FF,0xADCAFE4B,0x9C22E4D6,0x3A55EF62, - 0xABC30345,0x0DB408F1,0x3C5C126C,0x9A2B19D8,0x5F8C2756,0xF9FB2CE2,0xC813367F,0x6E643DCB, - 0x982C4D22,0x3E5B4696,0x0FB35C0B,0xA9C457BF,0x6C636931,0xCA146285,0xFBFC7818,0x5D8B73AC, - 0x03A0A617,0xA5D7ADA3,0x943FB73E,0x3248BC8A,0xF7EF8204,0x519889B0,0x6070932D,0xC6079899, - 0x304FE870,0x9638E3C4,0xA7D0F959,0x01A7F2ED,0xC400CC63,0x6277C7D7,0x539FDD4A,0xF5E8D6FE, - 0x647E3AD9,0xC209316D,0xF3E12BF0,0x55962044,0x90311ECA,0x3646157E,0x07AE0FE3,0xA1D90457, - 0x579174BE,0xF1E67F0A,0xC00E6597,0x66796E23,0xA3DE50AD,0x05A95B19,0x34414184,0x92364A30, - }, - - { - 0x00000000,0xCCAA009E,0x4225077D,0x8E8F07E3,0x844A0EFA,0x48E00E64,0xC66F0987,0x0AC50919, - 0xD3E51BB5,0x1F4F1B2B,0x91C01CC8,0x5D6A1C56,0x57AF154F,0x9B0515D1,0x158A1232,0xD92012AC, - 0x7CBB312B,0xB01131B5,0x3E9E3656,0xF23436C8,0xF8F13FD1,0x345B3F4F,0xBAD438AC,0x767E3832, - 0xAF5E2A9E,0x63F42A00,0xED7B2DE3,0x21D12D7D,0x2B142464,0xE7BE24FA,0x69312319,0xA59B2387, - 0xF9766256,0x35DC62C8,0xBB53652B,0x77F965B5,0x7D3C6CAC,0xB1966C32,0x3F196BD1,0xF3B36B4F, - 0x2A9379E3,0xE639797D,0x68B67E9E,0xA41C7E00,0xAED97719,0x62737787,0xECFC7064,0x205670FA, - 0x85CD537D,0x496753E3,0xC7E85400,0x0B42549E,0x01875D87,0xCD2D5D19,0x43A25AFA,0x8F085A64, - 0x562848C8,0x9A824856,0x140D4FB5,0xD8A74F2B,0xD2624632,0x1EC846AC,0x9047414F,0x5CED41D1, - 0x299DC2ED,0xE537C273,0x6BB8C590,0xA712C50E,0xADD7CC17,0x617DCC89,0xEFF2CB6A,0x2358CBF4, - 0xFA78D958,0x36D2D9C6,0xB85DDE25,0x74F7DEBB,0x7E32D7A2,0xB298D73C,0x3C17D0DF,0xF0BDD041, - 0x5526F3C6,0x998CF358,0x1703F4BB,0xDBA9F425,0xD16CFD3C,0x1DC6FDA2,0x9349FA41,0x5FE3FADF, - 0x86C3E873,0x4A69E8ED,0xC4E6EF0E,0x084CEF90,0x0289E689,0xCE23E617,0x40ACE1F4,0x8C06E16A, - 0xD0EBA0BB,0x1C41A025,0x92CEA7C6,0x5E64A758,0x54A1AE41,0x980BAEDF,0x1684A93C,0xDA2EA9A2, - 0x030EBB0E,0xCFA4BB90,0x412BBC73,0x8D81BCED,0x8744B5F4,0x4BEEB56A,0xC561B289,0x09CBB217, - 0xAC509190,0x60FA910E,0xEE7596ED,0x22DF9673,0x281A9F6A,0xE4B09FF4,0x6A3F9817,0xA6959889, - 0x7FB58A25,0xB31F8ABB,0x3D908D58,0xF13A8DC6,0xFBFF84DF,0x37558441,0xB9DA83A2,0x7570833C, - 0x533B85DA,0x9F918544,0x111E82A7,0xDDB48239,0xD7718B20,0x1BDB8BBE,0x95548C5D,0x59FE8CC3, - 0x80DE9E6F,0x4C749EF1,0xC2FB9912,0x0E51998C,0x04949095,0xC83E900B,0x46B197E8,0x8A1B9776, - 0x2F80B4F1,0xE32AB46F,0x6DA5B38C,0xA10FB312,0xABCABA0B,0x6760BA95,0xE9EFBD76,0x2545BDE8, - 0xFC65AF44,0x30CFAFDA,0xBE40A839,0x72EAA8A7,0x782FA1BE,0xB485A120,0x3A0AA6C3,0xF6A0A65D, - 0xAA4DE78C,0x66E7E712,0xE868E0F1,0x24C2E06F,0x2E07E976,0xE2ADE9E8,0x6C22EE0B,0xA088EE95, - 0x79A8FC39,0xB502FCA7,0x3B8DFB44,0xF727FBDA,0xFDE2F2C3,0x3148F25D,0xBFC7F5BE,0x736DF520, - 0xD6F6D6A7,0x1A5CD639,0x94D3D1DA,0x5879D144,0x52BCD85D,0x9E16D8C3,0x1099DF20,0xDC33DFBE, - 0x0513CD12,0xC9B9CD8C,0x4736CA6F,0x8B9CCAF1,0x8159C3E8,0x4DF3C376,0xC37CC495,0x0FD6C40B, - 0x7AA64737,0xB60C47A9,0x3883404A,0xF42940D4,0xFEEC49CD,0x32464953,0xBCC94EB0,0x70634E2E, - 0xA9435C82,0x65E95C1C,0xEB665BFF,0x27CC5B61,0x2D095278,0xE1A352E6,0x6F2C5505,0xA386559B, - 0x061D761C,0xCAB77682,0x44387161,0x889271FF,0x825778E6,0x4EFD7878,0xC0727F9B,0x0CD87F05, - 0xD5F86DA9,0x19526D37,0x97DD6AD4,0x5B776A4A,0x51B26353,0x9D1863CD,0x1397642E,0xDF3D64B0, - 0x83D02561,0x4F7A25FF,0xC1F5221C,0x0D5F2282,0x079A2B9B,0xCB302B05,0x45BF2CE6,0x89152C78, - 0x50353ED4,0x9C9F3E4A,0x121039A9,0xDEBA3937,0xD47F302E,0x18D530B0,0x965A3753,0x5AF037CD, - 0xFF6B144A,0x33C114D4,0xBD4E1337,0x71E413A9,0x7B211AB0,0xB78B1A2E,0x39041DCD,0xF5AE1D53, - 0x2C8E0FFF,0xE0240F61,0x6EAB0882,0xA201081C,0xA8C40105,0x646E019B,0xEAE10678,0x264B06E6, - } -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 || CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 - // beyond this point only relevant for Slicing-by-16 - ,{ - 0x00000000,0x177B1443,0x2EF62886,0x398D3CC5,0x5DEC510C,0x4A97454F,0x731A798A,0x64616DC9, - 0xBBD8A218,0xACA3B65B,0x952E8A9E,0x82559EDD,0xE634F314,0xF14FE757,0xC8C2DB92,0xDFB9CFD1, - 0xACC04271,0xBBBB5632,0x82366AF7,0x954D7EB4,0xF12C137D,0xE657073E,0xDFDA3BFB,0xC8A12FB8, - 0x1718E069,0x0063F42A,0x39EEC8EF,0x2E95DCAC,0x4AF4B165,0x5D8FA526,0x640299E3,0x73798DA0, - 0x82F182A3,0x958A96E0,0xAC07AA25,0xBB7CBE66,0xDF1DD3AF,0xC866C7EC,0xF1EBFB29,0xE690EF6A, - 0x392920BB,0x2E5234F8,0x17DF083D,0x00A41C7E,0x64C571B7,0x73BE65F4,0x4A335931,0x5D484D72, - 0x2E31C0D2,0x394AD491,0x00C7E854,0x17BCFC17,0x73DD91DE,0x64A6859D,0x5D2BB958,0x4A50AD1B, - 0x95E962CA,0x82927689,0xBB1F4A4C,0xAC645E0F,0xC80533C6,0xDF7E2785,0xE6F31B40,0xF1880F03, - 0xDE920307,0xC9E91744,0xF0642B81,0xE71F3FC2,0x837E520B,0x94054648,0xAD887A8D,0xBAF36ECE, - 0x654AA11F,0x7231B55C,0x4BBC8999,0x5CC79DDA,0x38A6F013,0x2FDDE450,0x1650D895,0x012BCCD6, - 0x72524176,0x65295535,0x5CA469F0,0x4BDF7DB3,0x2FBE107A,0x38C50439,0x014838FC,0x16332CBF, - 0xC98AE36E,0xDEF1F72D,0xE77CCBE8,0xF007DFAB,0x9466B262,0x831DA621,0xBA909AE4,0xADEB8EA7, - 0x5C6381A4,0x4B1895E7,0x7295A922,0x65EEBD61,0x018FD0A8,0x16F4C4EB,0x2F79F82E,0x3802EC6D, - 0xE7BB23BC,0xF0C037FF,0xC94D0B3A,0xDE361F79,0xBA5772B0,0xAD2C66F3,0x94A15A36,0x83DA4E75, - 0xF0A3C3D5,0xE7D8D796,0xDE55EB53,0xC92EFF10,0xAD4F92D9,0xBA34869A,0x83B9BA5F,0x94C2AE1C, - 0x4B7B61CD,0x5C00758E,0x658D494B,0x72F65D08,0x169730C1,0x01EC2482,0x38611847,0x2F1A0C04, - 0x6655004F,0x712E140C,0x48A328C9,0x5FD83C8A,0x3BB95143,0x2CC24500,0x154F79C5,0x02346D86, - 0xDD8DA257,0xCAF6B614,0xF37B8AD1,0xE4009E92,0x8061F35B,0x971AE718,0xAE97DBDD,0xB9ECCF9E, - 0xCA95423E,0xDDEE567D,0xE4636AB8,0xF3187EFB,0x97791332,0x80020771,0xB98F3BB4,0xAEF42FF7, - 0x714DE026,0x6636F465,0x5FBBC8A0,0x48C0DCE3,0x2CA1B12A,0x3BDAA569,0x025799AC,0x152C8DEF, - 0xE4A482EC,0xF3DF96AF,0xCA52AA6A,0xDD29BE29,0xB948D3E0,0xAE33C7A3,0x97BEFB66,0x80C5EF25, - 0x5F7C20F4,0x480734B7,0x718A0872,0x66F11C31,0x029071F8,0x15EB65BB,0x2C66597E,0x3B1D4D3D, - 0x4864C09D,0x5F1FD4DE,0x6692E81B,0x71E9FC58,0x15889191,0x02F385D2,0x3B7EB917,0x2C05AD54, - 0xF3BC6285,0xE4C776C6,0xDD4A4A03,0xCA315E40,0xAE503389,0xB92B27CA,0x80A61B0F,0x97DD0F4C, - 0xB8C70348,0xAFBC170B,0x96312BCE,0x814A3F8D,0xE52B5244,0xF2504607,0xCBDD7AC2,0xDCA66E81, - 0x031FA150,0x1464B513,0x2DE989D6,0x3A929D95,0x5EF3F05C,0x4988E41F,0x7005D8DA,0x677ECC99, - 0x14074139,0x037C557A,0x3AF169BF,0x2D8A7DFC,0x49EB1035,0x5E900476,0x671D38B3,0x70662CF0, - 0xAFDFE321,0xB8A4F762,0x8129CBA7,0x9652DFE4,0xF233B22D,0xE548A66E,0xDCC59AAB,0xCBBE8EE8, - 0x3A3681EB,0x2D4D95A8,0x14C0A96D,0x03BBBD2E,0x67DAD0E7,0x70A1C4A4,0x492CF861,0x5E57EC22, - 0x81EE23F3,0x969537B0,0xAF180B75,0xB8631F36,0xDC0272FF,0xCB7966BC,0xF2F45A79,0xE58F4E3A, - 0x96F6C39A,0x818DD7D9,0xB800EB1C,0xAF7BFF5F,0xCB1A9296,0xDC6186D5,0xE5ECBA10,0xF297AE53, - 0x2D2E6182,0x3A5575C1,0x03D84904,0x14A35D47,0x70C2308E,0x67B924CD,0x5E341808,0x494F0C4B, - }, - - { - 0x00000000,0xEFC26B3E,0x04F5D03D,0xEB37BB03,0x09EBA07A,0xE629CB44,0x0D1E7047,0xE2DC1B79, - 0x13D740F4,0xFC152BCA,0x172290C9,0xF8E0FBF7,0x1A3CE08E,0xF5FE8BB0,0x1EC930B3,0xF10B5B8D, - 0x27AE81E8,0xC86CEAD6,0x235B51D5,0xCC993AEB,0x2E452192,0xC1874AAC,0x2AB0F1AF,0xC5729A91, - 0x3479C11C,0xDBBBAA22,0x308C1121,0xDF4E7A1F,0x3D926166,0xD2500A58,0x3967B15B,0xD6A5DA65, - 0x4F5D03D0,0xA09F68EE,0x4BA8D3ED,0xA46AB8D3,0x46B6A3AA,0xA974C894,0x42437397,0xAD8118A9, - 0x5C8A4324,0xB348281A,0x587F9319,0xB7BDF827,0x5561E35E,0xBAA38860,0x51943363,0xBE56585D, - 0x68F38238,0x8731E906,0x6C065205,0x83C4393B,0x61182242,0x8EDA497C,0x65EDF27F,0x8A2F9941, - 0x7B24C2CC,0x94E6A9F2,0x7FD112F1,0x901379CF,0x72CF62B6,0x9D0D0988,0x763AB28B,0x99F8D9B5, - 0x9EBA07A0,0x71786C9E,0x9A4FD79D,0x758DBCA3,0x9751A7DA,0x7893CCE4,0x93A477E7,0x7C661CD9, - 0x8D6D4754,0x62AF2C6A,0x89989769,0x665AFC57,0x8486E72E,0x6B448C10,0x80733713,0x6FB15C2D, - 0xB9148648,0x56D6ED76,0xBDE15675,0x52233D4B,0xB0FF2632,0x5F3D4D0C,0xB40AF60F,0x5BC89D31, - 0xAAC3C6BC,0x4501AD82,0xAE361681,0x41F47DBF,0xA32866C6,0x4CEA0DF8,0xA7DDB6FB,0x481FDDC5, - 0xD1E70470,0x3E256F4E,0xD512D44D,0x3AD0BF73,0xD80CA40A,0x37CECF34,0xDCF97437,0x333B1F09, - 0xC2304484,0x2DF22FBA,0xC6C594B9,0x2907FF87,0xCBDBE4FE,0x24198FC0,0xCF2E34C3,0x20EC5FFD, - 0xF6498598,0x198BEEA6,0xF2BC55A5,0x1D7E3E9B,0xFFA225E2,0x10604EDC,0xFB57F5DF,0x14959EE1, - 0xE59EC56C,0x0A5CAE52,0xE16B1551,0x0EA97E6F,0xEC756516,0x03B70E28,0xE880B52B,0x0742DE15, - 0xE6050901,0x09C7623F,0xE2F0D93C,0x0D32B202,0xEFEEA97B,0x002CC245,0xEB1B7946,0x04D91278, - 0xF5D249F5,0x1A1022CB,0xF12799C8,0x1EE5F2F6,0xFC39E98F,0x13FB82B1,0xF8CC39B2,0x170E528C, - 0xC1AB88E9,0x2E69E3D7,0xC55E58D4,0x2A9C33EA,0xC8402893,0x278243AD,0xCCB5F8AE,0x23779390, - 0xD27CC81D,0x3DBEA323,0xD6891820,0x394B731E,0xDB976867,0x34550359,0xDF62B85A,0x30A0D364, - 0xA9580AD1,0x469A61EF,0xADADDAEC,0x426FB1D2,0xA0B3AAAB,0x4F71C195,0xA4467A96,0x4B8411A8, - 0xBA8F4A25,0x554D211B,0xBE7A9A18,0x51B8F126,0xB364EA5F,0x5CA68161,0xB7913A62,0x5853515C, - 0x8EF68B39,0x6134E007,0x8A035B04,0x65C1303A,0x871D2B43,0x68DF407D,0x83E8FB7E,0x6C2A9040, - 0x9D21CBCD,0x72E3A0F3,0x99D41BF0,0x761670CE,0x94CA6BB7,0x7B080089,0x903FBB8A,0x7FFDD0B4, - 0x78BF0EA1,0x977D659F,0x7C4ADE9C,0x9388B5A2,0x7154AEDB,0x9E96C5E5,0x75A17EE6,0x9A6315D8, - 0x6B684E55,0x84AA256B,0x6F9D9E68,0x805FF556,0x6283EE2F,0x8D418511,0x66763E12,0x89B4552C, - 0x5F118F49,0xB0D3E477,0x5BE45F74,0xB426344A,0x56FA2F33,0xB938440D,0x520FFF0E,0xBDCD9430, - 0x4CC6CFBD,0xA304A483,0x48331F80,0xA7F174BE,0x452D6FC7,0xAAEF04F9,0x41D8BFFA,0xAE1AD4C4, - 0x37E20D71,0xD820664F,0x3317DD4C,0xDCD5B672,0x3E09AD0B,0xD1CBC635,0x3AFC7D36,0xD53E1608, - 0x24354D85,0xCBF726BB,0x20C09DB8,0xCF02F686,0x2DDEEDFF,0xC21C86C1,0x292B3DC2,0xC6E956FC, - 0x104C8C99,0xFF8EE7A7,0x14B95CA4,0xFB7B379A,0x19A72CE3,0xF66547DD,0x1D52FCDE,0xF29097E0, - 0x039BCC6D,0xEC59A753,0x076E1C50,0xE8AC776E,0x0A706C17,0xE5B20729,0x0E85BC2A,0xE147D714, - }, - - { - 0x00000000,0xC18EDFC0,0x586CB9C1,0x99E26601,0xB0D97382,0x7157AC42,0xE8B5CA43,0x293B1583, - 0xBAC3E145,0x7B4D3E85,0xE2AF5884,0x23218744,0x0A1A92C7,0xCB944D07,0x52762B06,0x93F8F4C6, - 0xAEF6C4CB,0x6F781B0B,0xF69A7D0A,0x3714A2CA,0x1E2FB749,0xDFA16889,0x46430E88,0x87CDD148, - 0x1435258E,0xD5BBFA4E,0x4C599C4F,0x8DD7438F,0xA4EC560C,0x656289CC,0xFC80EFCD,0x3D0E300D, - 0x869C8FD7,0x47125017,0xDEF03616,0x1F7EE9D6,0x3645FC55,0xF7CB2395,0x6E294594,0xAFA79A54, - 0x3C5F6E92,0xFDD1B152,0x6433D753,0xA5BD0893,0x8C861D10,0x4D08C2D0,0xD4EAA4D1,0x15647B11, - 0x286A4B1C,0xE9E494DC,0x7006F2DD,0xB1882D1D,0x98B3389E,0x593DE75E,0xC0DF815F,0x01515E9F, - 0x92A9AA59,0x53277599,0xCAC51398,0x0B4BCC58,0x2270D9DB,0xE3FE061B,0x7A1C601A,0xBB92BFDA, - 0xD64819EF,0x17C6C62F,0x8E24A02E,0x4FAA7FEE,0x66916A6D,0xA71FB5AD,0x3EFDD3AC,0xFF730C6C, - 0x6C8BF8AA,0xAD05276A,0x34E7416B,0xF5699EAB,0xDC528B28,0x1DDC54E8,0x843E32E9,0x45B0ED29, - 0x78BEDD24,0xB93002E4,0x20D264E5,0xE15CBB25,0xC867AEA6,0x09E97166,0x900B1767,0x5185C8A7, - 0xC27D3C61,0x03F3E3A1,0x9A1185A0,0x5B9F5A60,0x72A44FE3,0xB32A9023,0x2AC8F622,0xEB4629E2, - 0x50D49638,0x915A49F8,0x08B82FF9,0xC936F039,0xE00DE5BA,0x21833A7A,0xB8615C7B,0x79EF83BB, - 0xEA17777D,0x2B99A8BD,0xB27BCEBC,0x73F5117C,0x5ACE04FF,0x9B40DB3F,0x02A2BD3E,0xC32C62FE, - 0xFE2252F3,0x3FAC8D33,0xA64EEB32,0x67C034F2,0x4EFB2171,0x8F75FEB1,0x169798B0,0xD7194770, - 0x44E1B3B6,0x856F6C76,0x1C8D0A77,0xDD03D5B7,0xF438C034,0x35B61FF4,0xAC5479F5,0x6DDAA635, - 0x77E1359F,0xB66FEA5F,0x2F8D8C5E,0xEE03539E,0xC738461D,0x06B699DD,0x9F54FFDC,0x5EDA201C, - 0xCD22D4DA,0x0CAC0B1A,0x954E6D1B,0x54C0B2DB,0x7DFBA758,0xBC757898,0x25971E99,0xE419C159, - 0xD917F154,0x18992E94,0x817B4895,0x40F59755,0x69CE82D6,0xA8405D16,0x31A23B17,0xF02CE4D7, - 0x63D41011,0xA25ACFD1,0x3BB8A9D0,0xFA367610,0xD30D6393,0x1283BC53,0x8B61DA52,0x4AEF0592, - 0xF17DBA48,0x30F36588,0xA9110389,0x689FDC49,0x41A4C9CA,0x802A160A,0x19C8700B,0xD846AFCB, - 0x4BBE5B0D,0x8A3084CD,0x13D2E2CC,0xD25C3D0C,0xFB67288F,0x3AE9F74F,0xA30B914E,0x62854E8E, - 0x5F8B7E83,0x9E05A143,0x07E7C742,0xC6691882,0xEF520D01,0x2EDCD2C1,0xB73EB4C0,0x76B06B00, - 0xE5489FC6,0x24C64006,0xBD242607,0x7CAAF9C7,0x5591EC44,0x941F3384,0x0DFD5585,0xCC738A45, - 0xA1A92C70,0x6027F3B0,0xF9C595B1,0x384B4A71,0x11705FF2,0xD0FE8032,0x491CE633,0x889239F3, - 0x1B6ACD35,0xDAE412F5,0x430674F4,0x8288AB34,0xABB3BEB7,0x6A3D6177,0xF3DF0776,0x3251D8B6, - 0x0F5FE8BB,0xCED1377B,0x5733517A,0x96BD8EBA,0xBF869B39,0x7E0844F9,0xE7EA22F8,0x2664FD38, - 0xB59C09FE,0x7412D63E,0xEDF0B03F,0x2C7E6FFF,0x05457A7C,0xC4CBA5BC,0x5D29C3BD,0x9CA71C7D, - 0x2735A3A7,0xE6BB7C67,0x7F591A66,0xBED7C5A6,0x97ECD025,0x56620FE5,0xCF8069E4,0x0E0EB624, - 0x9DF642E2,0x5C789D22,0xC59AFB23,0x041424E3,0x2D2F3160,0xECA1EEA0,0x754388A1,0xB4CD5761, - 0x89C3676C,0x484DB8AC,0xD1AFDEAD,0x1021016D,0x391A14EE,0xF894CB2E,0x6176AD2F,0xA0F872EF, - 0x33008629,0xF28E59E9,0x6B6C3FE8,0xAAE2E028,0x83D9F5AB,0x42572A6B,0xDBB54C6A,0x1A3B93AA, - }, - - { - 0x00000000,0x9BA54C6F,0xEC3B9E9F,0x779ED2F0,0x03063B7F,0x98A37710,0xEF3DA5E0,0x7498E98F, - 0x060C76FE,0x9DA93A91,0xEA37E861,0x7192A40E,0x050A4D81,0x9EAF01EE,0xE931D31E,0x72949F71, - 0x0C18EDFC,0x97BDA193,0xE0237363,0x7B863F0C,0x0F1ED683,0x94BB9AEC,0xE325481C,0x78800473, - 0x0A149B02,0x91B1D76D,0xE62F059D,0x7D8A49F2,0x0912A07D,0x92B7EC12,0xE5293EE2,0x7E8C728D, - 0x1831DBF8,0x83949797,0xF40A4567,0x6FAF0908,0x1B37E087,0x8092ACE8,0xF70C7E18,0x6CA93277, - 0x1E3DAD06,0x8598E169,0xF2063399,0x69A37FF6,0x1D3B9679,0x869EDA16,0xF10008E6,0x6AA54489, - 0x14293604,0x8F8C7A6B,0xF812A89B,0x63B7E4F4,0x172F0D7B,0x8C8A4114,0xFB1493E4,0x60B1DF8B, - 0x122540FA,0x89800C95,0xFE1EDE65,0x65BB920A,0x11237B85,0x8A8637EA,0xFD18E51A,0x66BDA975, - 0x3063B7F0,0xABC6FB9F,0xDC58296F,0x47FD6500,0x33658C8F,0xA8C0C0E0,0xDF5E1210,0x44FB5E7F, - 0x366FC10E,0xADCA8D61,0xDA545F91,0x41F113FE,0x3569FA71,0xAECCB61E,0xD95264EE,0x42F72881, - 0x3C7B5A0C,0xA7DE1663,0xD040C493,0x4BE588FC,0x3F7D6173,0xA4D82D1C,0xD346FFEC,0x48E3B383, - 0x3A772CF2,0xA1D2609D,0xD64CB26D,0x4DE9FE02,0x3971178D,0xA2D45BE2,0xD54A8912,0x4EEFC57D, - 0x28526C08,0xB3F72067,0xC469F297,0x5FCCBEF8,0x2B545777,0xB0F11B18,0xC76FC9E8,0x5CCA8587, - 0x2E5E1AF6,0xB5FB5699,0xC2658469,0x59C0C806,0x2D582189,0xB6FD6DE6,0xC163BF16,0x5AC6F379, - 0x244A81F4,0xBFEFCD9B,0xC8711F6B,0x53D45304,0x274CBA8B,0xBCE9F6E4,0xCB772414,0x50D2687B, - 0x2246F70A,0xB9E3BB65,0xCE7D6995,0x55D825FA,0x2140CC75,0xBAE5801A,0xCD7B52EA,0x56DE1E85, - 0x60C76FE0,0xFB62238F,0x8CFCF17F,0x1759BD10,0x63C1549F,0xF86418F0,0x8FFACA00,0x145F866F, - 0x66CB191E,0xFD6E5571,0x8AF08781,0x1155CBEE,0x65CD2261,0xFE686E0E,0x89F6BCFE,0x1253F091, - 0x6CDF821C,0xF77ACE73,0x80E41C83,0x1B4150EC,0x6FD9B963,0xF47CF50C,0x83E227FC,0x18476B93, - 0x6AD3F4E2,0xF176B88D,0x86E86A7D,0x1D4D2612,0x69D5CF9D,0xF27083F2,0x85EE5102,0x1E4B1D6D, - 0x78F6B418,0xE353F877,0x94CD2A87,0x0F6866E8,0x7BF08F67,0xE055C308,0x97CB11F8,0x0C6E5D97, - 0x7EFAC2E6,0xE55F8E89,0x92C15C79,0x09641016,0x7DFCF999,0xE659B5F6,0x91C76706,0x0A622B69, - 0x74EE59E4,0xEF4B158B,0x98D5C77B,0x03708B14,0x77E8629B,0xEC4D2EF4,0x9BD3FC04,0x0076B06B, - 0x72E22F1A,0xE9476375,0x9ED9B185,0x057CFDEA,0x71E41465,0xEA41580A,0x9DDF8AFA,0x067AC695, - 0x50A4D810,0xCB01947F,0xBC9F468F,0x273A0AE0,0x53A2E36F,0xC807AF00,0xBF997DF0,0x243C319F, - 0x56A8AEEE,0xCD0DE281,0xBA933071,0x21367C1E,0x55AE9591,0xCE0BD9FE,0xB9950B0E,0x22304761, - 0x5CBC35EC,0xC7197983,0xB087AB73,0x2B22E71C,0x5FBA0E93,0xC41F42FC,0xB381900C,0x2824DC63, - 0x5AB04312,0xC1150F7D,0xB68BDD8D,0x2D2E91E2,0x59B6786D,0xC2133402,0xB58DE6F2,0x2E28AA9D, - 0x489503E8,0xD3304F87,0xA4AE9D77,0x3F0BD118,0x4B933897,0xD03674F8,0xA7A8A608,0x3C0DEA67, - 0x4E997516,0xD53C3979,0xA2A2EB89,0x3907A7E6,0x4D9F4E69,0xD63A0206,0xA1A4D0F6,0x3A019C99, - 0x448DEE14,0xDF28A27B,0xA8B6708B,0x33133CE4,0x478BD56B,0xDC2E9904,0xABB04BF4,0x3015079B, - 0x428198EA,0xD924D485,0xAEBA0675,0x351F4A1A,0x4187A395,0xDA22EFFA,0xADBC3D0A,0x36197165, - }, - - { - 0x00000000,0xDD96D985,0x605CB54B,0xBDCA6CCE,0xC0B96A96,0x1D2FB313,0xA0E5DFDD,0x7D730658, - 0x5A03D36D,0x87950AE8,0x3A5F6626,0xE7C9BFA3,0x9ABAB9FB,0x472C607E,0xFAE60CB0,0x2770D535, - 0xB407A6DA,0x69917F5F,0xD45B1391,0x09CDCA14,0x74BECC4C,0xA92815C9,0x14E27907,0xC974A082, - 0xEE0475B7,0x3392AC32,0x8E58C0FC,0x53CE1979,0x2EBD1F21,0xF32BC6A4,0x4EE1AA6A,0x937773EF, - 0xB37E4BF5,0x6EE89270,0xD322FEBE,0x0EB4273B,0x73C72163,0xAE51F8E6,0x139B9428,0xCE0D4DAD, - 0xE97D9898,0x34EB411D,0x89212DD3,0x54B7F456,0x29C4F20E,0xF4522B8B,0x49984745,0x940E9EC0, - 0x0779ED2F,0xDAEF34AA,0x67255864,0xBAB381E1,0xC7C087B9,0x1A565E3C,0xA79C32F2,0x7A0AEB77, - 0x5D7A3E42,0x80ECE7C7,0x3D268B09,0xE0B0528C,0x9DC354D4,0x40558D51,0xFD9FE19F,0x2009381A, - 0xBD8D91AB,0x601B482E,0xDDD124E0,0x0047FD65,0x7D34FB3D,0xA0A222B8,0x1D684E76,0xC0FE97F3, - 0xE78E42C6,0x3A189B43,0x87D2F78D,0x5A442E08,0x27372850,0xFAA1F1D5,0x476B9D1B,0x9AFD449E, - 0x098A3771,0xD41CEEF4,0x69D6823A,0xB4405BBF,0xC9335DE7,0x14A58462,0xA96FE8AC,0x74F93129, - 0x5389E41C,0x8E1F3D99,0x33D55157,0xEE4388D2,0x93308E8A,0x4EA6570F,0xF36C3BC1,0x2EFAE244, - 0x0EF3DA5E,0xD36503DB,0x6EAF6F15,0xB339B690,0xCE4AB0C8,0x13DC694D,0xAE160583,0x7380DC06, - 0x54F00933,0x8966D0B6,0x34ACBC78,0xE93A65FD,0x944963A5,0x49DFBA20,0xF415D6EE,0x29830F6B, - 0xBAF47C84,0x6762A501,0xDAA8C9CF,0x073E104A,0x7A4D1612,0xA7DBCF97,0x1A11A359,0xC7877ADC, - 0xE0F7AFE9,0x3D61766C,0x80AB1AA2,0x5D3DC327,0x204EC57F,0xFDD81CFA,0x40127034,0x9D84A9B1, - 0xA06A2517,0x7DFCFC92,0xC036905C,0x1DA049D9,0x60D34F81,0xBD459604,0x008FFACA,0xDD19234F, - 0xFA69F67A,0x27FF2FFF,0x9A354331,0x47A39AB4,0x3AD09CEC,0xE7464569,0x5A8C29A7,0x871AF022, - 0x146D83CD,0xC9FB5A48,0x74313686,0xA9A7EF03,0xD4D4E95B,0x094230DE,0xB4885C10,0x691E8595, - 0x4E6E50A0,0x93F88925,0x2E32E5EB,0xF3A43C6E,0x8ED73A36,0x5341E3B3,0xEE8B8F7D,0x331D56F8, - 0x13146EE2,0xCE82B767,0x7348DBA9,0xAEDE022C,0xD3AD0474,0x0E3BDDF1,0xB3F1B13F,0x6E6768BA, - 0x4917BD8F,0x9481640A,0x294B08C4,0xF4DDD141,0x89AED719,0x54380E9C,0xE9F26252,0x3464BBD7, - 0xA713C838,0x7A8511BD,0xC74F7D73,0x1AD9A4F6,0x67AAA2AE,0xBA3C7B2B,0x07F617E5,0xDA60CE60, - 0xFD101B55,0x2086C2D0,0x9D4CAE1E,0x40DA779B,0x3DA971C3,0xE03FA846,0x5DF5C488,0x80631D0D, - 0x1DE7B4BC,0xC0716D39,0x7DBB01F7,0xA02DD872,0xDD5EDE2A,0x00C807AF,0xBD026B61,0x6094B2E4, - 0x47E467D1,0x9A72BE54,0x27B8D29A,0xFA2E0B1F,0x875D0D47,0x5ACBD4C2,0xE701B80C,0x3A976189, - 0xA9E01266,0x7476CBE3,0xC9BCA72D,0x142A7EA8,0x695978F0,0xB4CFA175,0x0905CDBB,0xD493143E, - 0xF3E3C10B,0x2E75188E,0x93BF7440,0x4E29ADC5,0x335AAB9D,0xEECC7218,0x53061ED6,0x8E90C753, - 0xAE99FF49,0x730F26CC,0xCEC54A02,0x13539387,0x6E2095DF,0xB3B64C5A,0x0E7C2094,0xD3EAF911, - 0xF49A2C24,0x290CF5A1,0x94C6996F,0x495040EA,0x342346B2,0xE9B59F37,0x547FF3F9,0x89E92A7C, - 0x1A9E5993,0xC7088016,0x7AC2ECD8,0xA754355D,0xDA273305,0x07B1EA80,0xBA7B864E,0x67ED5FCB, - 0x409D8AFE,0x9D0B537B,0x20C13FB5,0xFD57E630,0x8024E068,0x5DB239ED,0xE0785523,0x3DEE8CA6, - }, - - { - 0x00000000,0x9D0FE176,0xE16EC4AD,0x7C6125DB,0x19AC8F1B,0x84A36E6D,0xF8C24BB6,0x65CDAAC0, - 0x33591E36,0xAE56FF40,0xD237DA9B,0x4F383BED,0x2AF5912D,0xB7FA705B,0xCB9B5580,0x5694B4F6, - 0x66B23C6C,0xFBBDDD1A,0x87DCF8C1,0x1AD319B7,0x7F1EB377,0xE2115201,0x9E7077DA,0x037F96AC, - 0x55EB225A,0xC8E4C32C,0xB485E6F7,0x298A0781,0x4C47AD41,0xD1484C37,0xAD2969EC,0x3026889A, - 0xCD6478D8,0x506B99AE,0x2C0ABC75,0xB1055D03,0xD4C8F7C3,0x49C716B5,0x35A6336E,0xA8A9D218, - 0xFE3D66EE,0x63328798,0x1F53A243,0x825C4335,0xE791E9F5,0x7A9E0883,0x06FF2D58,0x9BF0CC2E, - 0xABD644B4,0x36D9A5C2,0x4AB88019,0xD7B7616F,0xB27ACBAF,0x2F752AD9,0x53140F02,0xCE1BEE74, - 0x988F5A82,0x0580BBF4,0x79E19E2F,0xE4EE7F59,0x8123D599,0x1C2C34EF,0x604D1134,0xFD42F042, - 0x41B9F7F1,0xDCB61687,0xA0D7335C,0x3DD8D22A,0x581578EA,0xC51A999C,0xB97BBC47,0x24745D31, - 0x72E0E9C7,0xEFEF08B1,0x938E2D6A,0x0E81CC1C,0x6B4C66DC,0xF64387AA,0x8A22A271,0x172D4307, - 0x270BCB9D,0xBA042AEB,0xC6650F30,0x5B6AEE46,0x3EA74486,0xA3A8A5F0,0xDFC9802B,0x42C6615D, - 0x1452D5AB,0x895D34DD,0xF53C1106,0x6833F070,0x0DFE5AB0,0x90F1BBC6,0xEC909E1D,0x719F7F6B, - 0x8CDD8F29,0x11D26E5F,0x6DB34B84,0xF0BCAAF2,0x95710032,0x087EE144,0x741FC49F,0xE91025E9, - 0xBF84911F,0x228B7069,0x5EEA55B2,0xC3E5B4C4,0xA6281E04,0x3B27FF72,0x4746DAA9,0xDA493BDF, - 0xEA6FB345,0x77605233,0x0B0177E8,0x960E969E,0xF3C33C5E,0x6ECCDD28,0x12ADF8F3,0x8FA21985, - 0xD936AD73,0x44394C05,0x385869DE,0xA55788A8,0xC09A2268,0x5D95C31E,0x21F4E6C5,0xBCFB07B3, - 0x8373EFE2,0x1E7C0E94,0x621D2B4F,0xFF12CA39,0x9ADF60F9,0x07D0818F,0x7BB1A454,0xE6BE4522, - 0xB02AF1D4,0x2D2510A2,0x51443579,0xCC4BD40F,0xA9867ECF,0x34899FB9,0x48E8BA62,0xD5E75B14, - 0xE5C1D38E,0x78CE32F8,0x04AF1723,0x99A0F655,0xFC6D5C95,0x6162BDE3,0x1D039838,0x800C794E, - 0xD698CDB8,0x4B972CCE,0x37F60915,0xAAF9E863,0xCF3442A3,0x523BA3D5,0x2E5A860E,0xB3556778, - 0x4E17973A,0xD318764C,0xAF795397,0x3276B2E1,0x57BB1821,0xCAB4F957,0xB6D5DC8C,0x2BDA3DFA, - 0x7D4E890C,0xE041687A,0x9C204DA1,0x012FACD7,0x64E20617,0xF9EDE761,0x858CC2BA,0x188323CC, - 0x28A5AB56,0xB5AA4A20,0xC9CB6FFB,0x54C48E8D,0x3109244D,0xAC06C53B,0xD067E0E0,0x4D680196, - 0x1BFCB560,0x86F35416,0xFA9271CD,0x679D90BB,0x02503A7B,0x9F5FDB0D,0xE33EFED6,0x7E311FA0, - 0xC2CA1813,0x5FC5F965,0x23A4DCBE,0xBEAB3DC8,0xDB669708,0x4669767E,0x3A0853A5,0xA707B2D3, - 0xF1930625,0x6C9CE753,0x10FDC288,0x8DF223FE,0xE83F893E,0x75306848,0x09514D93,0x945EACE5, - 0xA478247F,0x3977C509,0x4516E0D2,0xD81901A4,0xBDD4AB64,0x20DB4A12,0x5CBA6FC9,0xC1B58EBF, - 0x97213A49,0x0A2EDB3F,0x764FFEE4,0xEB401F92,0x8E8DB552,0x13825424,0x6FE371FF,0xF2EC9089, - 0x0FAE60CB,0x92A181BD,0xEEC0A466,0x73CF4510,0x1602EFD0,0x8B0D0EA6,0xF76C2B7D,0x6A63CA0B, - 0x3CF77EFD,0xA1F89F8B,0xDD99BA50,0x40965B26,0x255BF1E6,0xB8541090,0xC435354B,0x593AD43D, - 0x691C5CA7,0xF413BDD1,0x8872980A,0x157D797C,0x70B0D3BC,0xEDBF32CA,0x91DE1711,0x0CD1F667, - 0x5A454291,0xC74AA3E7,0xBB2B863C,0x2624674A,0x43E9CD8A,0xDEE62CFC,0xA2870927,0x3F88E851, - }, - - { - 0x00000000,0xB9FBDBE8,0xA886B191,0x117D6A79,0x8A7C6563,0x3387BE8B,0x22FAD4F2,0x9B010F1A, - 0xCF89CC87,0x7672176F,0x670F7D16,0xDEF4A6FE,0x45F5A9E4,0xFC0E720C,0xED731875,0x5488C39D, - 0x44629F4F,0xFD9944A7,0xECE42EDE,0x551FF536,0xCE1EFA2C,0x77E521C4,0x66984BBD,0xDF639055, - 0x8BEB53C8,0x32108820,0x236DE259,0x9A9639B1,0x019736AB,0xB86CED43,0xA911873A,0x10EA5CD2, - 0x88C53E9E,0x313EE576,0x20438F0F,0x99B854E7,0x02B95BFD,0xBB428015,0xAA3FEA6C,0x13C43184, - 0x474CF219,0xFEB729F1,0xEFCA4388,0x56319860,0xCD30977A,0x74CB4C92,0x65B626EB,0xDC4DFD03, - 0xCCA7A1D1,0x755C7A39,0x64211040,0xDDDACBA8,0x46DBC4B2,0xFF201F5A,0xEE5D7523,0x57A6AECB, - 0x032E6D56,0xBAD5B6BE,0xABA8DCC7,0x1253072F,0x89520835,0x30A9D3DD,0x21D4B9A4,0x982F624C, - 0xCAFB7B7D,0x7300A095,0x627DCAEC,0xDB861104,0x40871E1E,0xF97CC5F6,0xE801AF8F,0x51FA7467, - 0x0572B7FA,0xBC896C12,0xADF4066B,0x140FDD83,0x8F0ED299,0x36F50971,0x27886308,0x9E73B8E0, - 0x8E99E432,0x37623FDA,0x261F55A3,0x9FE48E4B,0x04E58151,0xBD1E5AB9,0xAC6330C0,0x1598EB28, - 0x411028B5,0xF8EBF35D,0xE9969924,0x506D42CC,0xCB6C4DD6,0x7297963E,0x63EAFC47,0xDA1127AF, - 0x423E45E3,0xFBC59E0B,0xEAB8F472,0x53432F9A,0xC8422080,0x71B9FB68,0x60C49111,0xD93F4AF9, - 0x8DB78964,0x344C528C,0x253138F5,0x9CCAE31D,0x07CBEC07,0xBE3037EF,0xAF4D5D96,0x16B6867E, - 0x065CDAAC,0xBFA70144,0xAEDA6B3D,0x1721B0D5,0x8C20BFCF,0x35DB6427,0x24A60E5E,0x9D5DD5B6, - 0xC9D5162B,0x702ECDC3,0x6153A7BA,0xD8A87C52,0x43A97348,0xFA52A8A0,0xEB2FC2D9,0x52D41931, - 0x4E87F0BB,0xF77C2B53,0xE601412A,0x5FFA9AC2,0xC4FB95D8,0x7D004E30,0x6C7D2449,0xD586FFA1, - 0x810E3C3C,0x38F5E7D4,0x29888DAD,0x90735645,0x0B72595F,0xB28982B7,0xA3F4E8CE,0x1A0F3326, - 0x0AE56FF4,0xB31EB41C,0xA263DE65,0x1B98058D,0x80990A97,0x3962D17F,0x281FBB06,0x91E460EE, - 0xC56CA373,0x7C97789B,0x6DEA12E2,0xD411C90A,0x4F10C610,0xF6EB1DF8,0xE7967781,0x5E6DAC69, - 0xC642CE25,0x7FB915CD,0x6EC47FB4,0xD73FA45C,0x4C3EAB46,0xF5C570AE,0xE4B81AD7,0x5D43C13F, - 0x09CB02A2,0xB030D94A,0xA14DB333,0x18B668DB,0x83B767C1,0x3A4CBC29,0x2B31D650,0x92CA0DB8, - 0x8220516A,0x3BDB8A82,0x2AA6E0FB,0x935D3B13,0x085C3409,0xB1A7EFE1,0xA0DA8598,0x19215E70, - 0x4DA99DED,0xF4524605,0xE52F2C7C,0x5CD4F794,0xC7D5F88E,0x7E2E2366,0x6F53491F,0xD6A892F7, - 0x847C8BC6,0x3D87502E,0x2CFA3A57,0x9501E1BF,0x0E00EEA5,0xB7FB354D,0xA6865F34,0x1F7D84DC, - 0x4BF54741,0xF20E9CA9,0xE373F6D0,0x5A882D38,0xC1892222,0x7872F9CA,0x690F93B3,0xD0F4485B, - 0xC01E1489,0x79E5CF61,0x6898A518,0xD1637EF0,0x4A6271EA,0xF399AA02,0xE2E4C07B,0x5B1F1B93, - 0x0F97D80E,0xB66C03E6,0xA711699F,0x1EEAB277,0x85EBBD6D,0x3C106685,0x2D6D0CFC,0x9496D714, - 0x0CB9B558,0xB5426EB0,0xA43F04C9,0x1DC4DF21,0x86C5D03B,0x3F3E0BD3,0x2E4361AA,0x97B8BA42, - 0xC33079DF,0x7ACBA237,0x6BB6C84E,0xD24D13A6,0x494C1CBC,0xF0B7C754,0xE1CAAD2D,0x583176C5, - 0x48DB2A17,0xF120F1FF,0xE05D9B86,0x59A6406E,0xC2A74F74,0x7B5C949C,0x6A21FEE5,0xD3DA250D, - 0x8752E690,0x3EA93D78,0x2FD45701,0x962F8CE9,0x0D2E83F3,0xB4D5581B,0xA5A83262,0x1C53E98A, - }, - - { - 0x00000000,0xAE689191,0x87A02563,0x29C8B4F2,0xD4314C87,0x7A59DD16,0x539169E4,0xFDF9F875, - 0x73139F4F,0xDD7B0EDE,0xF4B3BA2C,0x5ADB2BBD,0xA722D3C8,0x094A4259,0x2082F6AB,0x8EEA673A, - 0xE6273E9E,0x484FAF0F,0x61871BFD,0xCFEF8A6C,0x32167219,0x9C7EE388,0xB5B6577A,0x1BDEC6EB, - 0x9534A1D1,0x3B5C3040,0x129484B2,0xBCFC1523,0x4105ED56,0xEF6D7CC7,0xC6A5C835,0x68CD59A4, - 0x173F7B7D,0xB957EAEC,0x909F5E1E,0x3EF7CF8F,0xC30E37FA,0x6D66A66B,0x44AE1299,0xEAC68308, - 0x642CE432,0xCA4475A3,0xE38CC151,0x4DE450C0,0xB01DA8B5,0x1E753924,0x37BD8DD6,0x99D51C47, - 0xF11845E3,0x5F70D472,0x76B86080,0xD8D0F111,0x25290964,0x8B4198F5,0xA2892C07,0x0CE1BD96, - 0x820BDAAC,0x2C634B3D,0x05ABFFCF,0xABC36E5E,0x563A962B,0xF85207BA,0xD19AB348,0x7FF222D9, - 0x2E7EF6FA,0x8016676B,0xA9DED399,0x07B64208,0xFA4FBA7D,0x54272BEC,0x7DEF9F1E,0xD3870E8F, - 0x5D6D69B5,0xF305F824,0xDACD4CD6,0x74A5DD47,0x895C2532,0x2734B4A3,0x0EFC0051,0xA09491C0, - 0xC859C864,0x663159F5,0x4FF9ED07,0xE1917C96,0x1C6884E3,0xB2001572,0x9BC8A180,0x35A03011, - 0xBB4A572B,0x1522C6BA,0x3CEA7248,0x9282E3D9,0x6F7B1BAC,0xC1138A3D,0xE8DB3ECF,0x46B3AF5E, - 0x39418D87,0x97291C16,0xBEE1A8E4,0x10893975,0xED70C100,0x43185091,0x6AD0E463,0xC4B875F2, - 0x4A5212C8,0xE43A8359,0xCDF237AB,0x639AA63A,0x9E635E4F,0x300BCFDE,0x19C37B2C,0xB7ABEABD, - 0xDF66B319,0x710E2288,0x58C6967A,0xF6AE07EB,0x0B57FF9E,0xA53F6E0F,0x8CF7DAFD,0x229F4B6C, - 0xAC752C56,0x021DBDC7,0x2BD50935,0x85BD98A4,0x784460D1,0xD62CF140,0xFFE445B2,0x518CD423, - 0x5CFDEDF4,0xF2957C65,0xDB5DC897,0x75355906,0x88CCA173,0x26A430E2,0x0F6C8410,0xA1041581, - 0x2FEE72BB,0x8186E32A,0xA84E57D8,0x0626C649,0xFBDF3E3C,0x55B7AFAD,0x7C7F1B5F,0xD2178ACE, - 0xBADAD36A,0x14B242FB,0x3D7AF609,0x93126798,0x6EEB9FED,0xC0830E7C,0xE94BBA8E,0x47232B1F, - 0xC9C94C25,0x67A1DDB4,0x4E696946,0xE001F8D7,0x1DF800A2,0xB3909133,0x9A5825C1,0x3430B450, - 0x4BC29689,0xE5AA0718,0xCC62B3EA,0x620A227B,0x9FF3DA0E,0x319B4B9F,0x1853FF6D,0xB63B6EFC, - 0x38D109C6,0x96B99857,0xBF712CA5,0x1119BD34,0xECE04541,0x4288D4D0,0x6B406022,0xC528F1B3, - 0xADE5A817,0x038D3986,0x2A458D74,0x842D1CE5,0x79D4E490,0xD7BC7501,0xFE74C1F3,0x501C5062, - 0xDEF63758,0x709EA6C9,0x5956123B,0xF73E83AA,0x0AC77BDF,0xA4AFEA4E,0x8D675EBC,0x230FCF2D, - 0x72831B0E,0xDCEB8A9F,0xF5233E6D,0x5B4BAFFC,0xA6B25789,0x08DAC618,0x211272EA,0x8F7AE37B, - 0x01908441,0xAFF815D0,0x8630A122,0x285830B3,0xD5A1C8C6,0x7BC95957,0x5201EDA5,0xFC697C34, - 0x94A42590,0x3ACCB401,0x130400F3,0xBD6C9162,0x40956917,0xEEFDF886,0xC7354C74,0x695DDDE5, - 0xE7B7BADF,0x49DF2B4E,0x60179FBC,0xCE7F0E2D,0x3386F658,0x9DEE67C9,0xB426D33B,0x1A4E42AA, - 0x65BC6073,0xCBD4F1E2,0xE21C4510,0x4C74D481,0xB18D2CF4,0x1FE5BD65,0x362D0997,0x98459806, - 0x16AFFF3C,0xB8C76EAD,0x910FDA5F,0x3F674BCE,0xC29EB3BB,0x6CF6222A,0x453E96D8,0xEB560749, - 0x839B5EED,0x2DF3CF7C,0x043B7B8E,0xAA53EA1F,0x57AA126A,0xF9C283FB,0xD00A3709,0x7E62A698, - 0xF088C1A2,0x5EE05033,0x7728E4C1,0xD9407550,0x24B98D25,0x8AD11CB4,0xA319A846,0x0D7139D7, - } -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 -}; -#endif // NO_LUT diff --git a/Crc32.h b/Crc32.h deleted file mode 100644 index cf60e0b..0000000 --- a/Crc32.h +++ /dev/null @@ -1,69 +0,0 @@ -// ////////////////////////////////////////////////////////// -// Crc32.h -// Copyright (c) 2011-2019 Stephan Brumme. All rights reserved. -// Slicing-by-16 contributed by Bulat Ziganshin -// Tableless bytewise CRC contributed by Hagai Gold -// see http://create.stephan-brumme.com/disclaimer.html -// - -// if running on an embedded system, you might consider shrinking the -// big Crc32Lookup table by undefining these lines: -#define CRC32_USE_LOOKUP_TABLE_BYTE -#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 -#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 -#define CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 -// - crc32_bitwise doesn't need it at all -// - crc32_halfbyte has its own small lookup table -// - crc32_1byte_tableless and crc32_1byte_tableless2 don't need it at all -// - crc32_1byte needs only Crc32Lookup[0] -// - crc32_4bytes needs only Crc32Lookup[0..3] -// - crc32_8bytes needs only Crc32Lookup[0..7] -// - crc32_4x8bytes needs only Crc32Lookup[0..7] -// - crc32_16bytes needs all of Crc32Lookup -// using the aforementioned #defines the table is automatically fitted to your needs - -// uint8_t, uint32_t, int32_t -#include -// size_t -#include - -// crc32_fast selects the fastest algorithm depending on flags (CRC32_USE_LOOKUP_...) -/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs -uint32_t crc32_fast (const void* data, size_t length, uint32_t previousCrc32 = 0); - -/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, lengthA)) -uint32_t crc32_combine (uint32_t crcA, uint32_t crcB, size_t lengthB); - -/// compute CRC32 (bitwise algorithm) -uint32_t crc32_bitwise (const void* data, size_t length, uint32_t previousCrc32 = 0); -/// compute CRC32 (half-byte algoritm) -uint32_t crc32_halfbyte(const void* data, size_t length, uint32_t previousCrc32 = 0); - -#ifdef CRC32_USE_LOOKUP_TABLE_BYTE -/// compute CRC32 (standard algorithm) -uint32_t crc32_1byte (const void* data, size_t length, uint32_t previousCrc32 = 0); -#endif - -/// compute CRC32 (byte algorithm) without lookup tables -uint32_t crc32_1byte_tableless (const void* data, size_t length, uint32_t previousCrc32 = 0); -/// compute CRC32 (byte algorithm) without lookup tables -uint32_t crc32_1byte_tableless2(const void* data, size_t length, uint32_t previousCrc32 = 0); - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 -/// compute CRC32 (Slicing-by-4 algorithm) -uint32_t crc32_4bytes (const void* data, size_t length, uint32_t previousCrc32 = 0); -#endif - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 -/// compute CRC32 (Slicing-by-8 algorithm) -uint32_t crc32_8bytes (const void* data, size_t length, uint32_t previousCrc32 = 0); -/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times -uint32_t crc32_4x8bytes(const void* data, size_t length, uint32_t previousCrc32 = 0); -#endif - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 -/// compute CRC32 (Slicing-by-16 algorithm) -uint32_t crc32_16bytes (const void* data, size_t length, uint32_t previousCrc32 = 0); -/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) -uint32_t crc32_16bytes_prefetch(const void* data, size_t length, uint32_t previousCrc32 = 0, size_t prefetchAhead = 256); -#endif diff --git a/Crc32Test.cpp b/Crc32Test.cpp deleted file mode 100644 index 3a4eb01..0000000 --- a/Crc32Test.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// ////////////////////////////////////////////////////////// -// Crc32Test.cpp -// Copyright (c) 2016-2019 Stephan Brumme. All rights reserved. -// see http://create.stephan-brumme.com/disclaimer.html -// - -#include "Crc32.h" -#include -#include - -// the slicing-by-4/8/16 tests are only performed if the corresponding -// preprocessor symbol is defined in Crc32.h -// simpler algorithms can be enabled/disabled right here: -#define CRC32_TEST_BITWISE -#define CRC32_TEST_HALFBYTE -#define CRC32_TEST_TABLELESS - -// ////////////////////////////////////////////////////////// -// test code - -/// one gigabyte -const size_t NumBytes = 1024*1024*1024; -/// 4k chunks during last test -const size_t DefaultChunkSize = 4*1024; - - -#if defined(_WIN32) || defined(_WIN64) -#include -#else -#include -#endif - -// timing -static double seconds() -{ -#if defined(_WIN32) || defined(_WIN64) - LARGE_INTEGER frequency, now; - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter (&now); - return now.QuadPart / double(frequency.QuadPart); -#else - timespec now; - clock_gettime(CLOCK_REALTIME, &now); - return now.tv_sec + now.tv_nsec / 1000000000.0; -#endif -} - - -int main(int, char**) -{ - printf("Please wait ...\n"); - - uint32_t randomNumber = 0x27121978; - // initialize - char* data = new char[NumBytes]; - for (size_t i = 0; i < NumBytes; i++) - { - data[i] = char(randomNumber & 0xFF); - // simple LCG, see http://en.wikipedia.org/wiki/Linear_congruential_generator - randomNumber = 1664525 * randomNumber + 1013904223; - } - - // re-use variables - double startTime, duration; - uint32_t crc; - -#ifdef CRC32_TEST_BITWISE - // bitwise - startTime = seconds(); - crc = crc32_bitwise(data, NumBytes); - duration = seconds() - startTime; - printf("bitwise : CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_TEST_BITWISE - -#ifdef CRC32_TEST_HALFBYTE - // half-byte - startTime = seconds(); - crc = crc32_halfbyte(data, NumBytes); - duration = seconds() - startTime; - printf("half-byte : CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_TEST_HALFBYTE - -#ifdef CRC32_TEST_TABLELESS - // one byte at once (without lookup tables) - startTime = seconds(); - crc = crc32_1byte_tableless(data, NumBytes); - duration = seconds() - startTime; - printf("tableless (byte) : CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); - - // one byte at once (without lookup tables) - startTime = seconds(); - crc = crc32_1byte_tableless2(data, NumBytes); - duration = seconds() - startTime; - printf("tableless (byte2): CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_TEST_TABLELESS - -#ifdef CRC32_USE_LOOKUP_TABLE_BYTE - // one byte at once - startTime = seconds(); - crc = crc32_1byte(data, NumBytes); - duration = seconds() - startTime; - printf(" 1 byte at once: CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_USE_LOOKUP_TABLE_BYTE - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 - // four bytes at once - startTime = seconds(); - crc = crc32_4bytes(data, NumBytes); - duration = seconds() - startTime; - printf(" 4 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 - // eight bytes at once - startTime = seconds(); - crc = crc32_8bytes(data, NumBytes); - duration = seconds() - startTime; - printf(" 8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); - - // eight bytes at once, unrolled 4 times (=> 32 bytes per loop) - startTime = seconds(); - crc = crc32_4x8bytes(data, NumBytes); - duration = seconds() - startTime; - printf("4x8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 - -#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 - // sixteen bytes at once - startTime = seconds(); - crc = crc32_16bytes(data, NumBytes); - duration = seconds() - startTime; - printf(" 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); - - // sixteen bytes at once - startTime = seconds(); - crc = crc32_16bytes_prefetch(data, NumBytes, 0, 256); - duration = seconds() - startTime; - printf(" 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s (including prefetching)\n", - crc, duration, (NumBytes / (1024*1024)) / duration); -#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 - - // process in 4k chunks - startTime = seconds(); - crc = 0; // also default parameter of crc32_xx functions - size_t bytesProcessed = 0; - while (bytesProcessed < NumBytes) - { - size_t bytesLeft = NumBytes - bytesProcessed; - size_t chunkSize = (DefaultChunkSize < bytesLeft) ? DefaultChunkSize : bytesLeft; - - crc = crc32_fast(data + bytesProcessed, chunkSize, crc); - - bytesProcessed += chunkSize; - } - duration = seconds() - startTime; - printf(" chunked : CRC=%08X, %.3fs, %.3f MB/s\n", - crc, duration, (NumBytes / (1024*1024)) / duration); - - delete[] data; - return 0; -} diff --git a/Crc32TestMultithreaded.cpp b/Crc32TestMultithreaded.cpp deleted file mode 100644 index 0878801..0000000 --- a/Crc32TestMultithreaded.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// ////////////////////////////////////////////////////////// -// Crc32TestMultithreaded.cpp -// Copyright (c) 2019 Stephan Brumme. All rights reserved. -// see http://create.stephan-brumme.com/disclaimer.html -// - -#include "Crc32.h" -#include -#include - -#include -#include - -// C++11 multithreading -#include -#include - -// ////////////////////////////////////////////////////////// -// test code - -/// one gigabyte -const size_t NumBytes = 1024*1024*1024; - - -#if defined(_WIN32) || defined(_WIN64) -#include -#else -#include -#endif - -// timing -static double seconds() -{ -#if defined(_WIN32) || defined(_WIN64) - LARGE_INTEGER frequency, now; - QueryPerformanceFrequency(&frequency); - QueryPerformanceCounter (&now); - return now.QuadPart / double(frequency.QuadPart); -#else - timespec now; - clock_gettime(CLOCK_REALTIME, &now); - return now.tv_sec + now.tv_nsec / 1000000000.0; -#endif -} - -// ////////////////////////////////////////////////////////// -// run a CRC32 algorithm on multiple threads -typedef uint32_t (*Crc32Algorithm)(const void* data, size_t length, uint32_t previousCrc32); -// compute CRC32 of up to maxBlockSize bytes and start recursively a new thread for excess data -uint32_t asyncCrc32(Crc32Algorithm myCrc32, const void* data, size_t numBytes, size_t maxBlockSize) -{ - // last block ? - if (numBytes <= maxBlockSize) - return myCrc32(data, numBytes, 0); // we're done - - // compute CRC of the remaining bytes in a separate thread - auto dataLeft = (const char*)data + maxBlockSize; - auto bytesLeft = numBytes - maxBlockSize; - auto remainder = std::async(std::launch::async, asyncCrc32, myCrc32, dataLeft, bytesLeft, maxBlockSize); - - // compute CRC of the current block - auto currentCrc = myCrc32(data, maxBlockSize, 0); - // get CRC of the remainder - auto remainderCrc = remainder.get(); - // and merge both - return crc32_combine(currentCrc, remainderCrc, bytesLeft); -} -// call: run(crc32_8bytes, data, NumBytes, 8) if you have an octocore CPU -uint32_t run(Crc32Algorithm myCrc32, const void* data, size_t numBytes, size_t numThreads = 0) -{ - // run on all cores - if (numThreads == 0) - numThreads = std::thread::hardware_concurrency(); - - // split data evenly, rounding up - auto defaultBlocksize = (numBytes + numThreads - 1) / numThreads; - - return asyncCrc32(myCrc32, data, numBytes, defaultBlocksize); -} - - -// test original sequential CRC32 algorithm against crc32_combine -bool testCombine(const char* data, size_t maxBytes = 1024) -{ - bool ok = true; - for (size_t lengthA = 1; lengthA < maxBytes; lengthA++) - { - // split bytes into two blocks of lengthA and lengthB - auto lengthB = maxBytes - lengthA; - - // compute CRC of both blocks - auto crcA = crc32_1byte(data, lengthA); - auto crcB = crc32_1byte(data + lengthA, lengthB); - - // CRC of the whole block - auto crcAtOnce = crc32_1byte(data, maxBytes); - // CRC of both blocks in a sequential fashion - auto crcSequential = crc32_1byte(data + lengthA, lengthB, crcA); - - // CRC using the new crc32_combine function - auto crcCombined = crc32_combine(crcA, crcB, lengthB); - - // check results - if (crcAtOnce != crcSequential || crcAtOnce != crcCombined) - { - printf("FAILED @ %d: %08X %08X %08X %08X %08X\n", lengthA, crcA, crcB, crcAtOnce, crcSequential, crcCombined); - ok = false; - } - } - return ok; -} - - -int main(int argc, char* argv[]) -{ - // ////////////////////////////////////////////////////////// - printf("Please wait ...\n"); - - uint32_t randomNumber = 0x27121978; - // initialize - char* data = new char[NumBytes]; - for (size_t i = 0; i < NumBytes; i++) - { - data[i] = char(randomNumber & 0xFF); - // simple LCG, see http://en.wikipedia.org/wiki/Linear_congruential_generator - randomNumber = 1664525 * randomNumber + 1013904223; - } - - // re-use variables - double startTime, duration; - uint32_t crc; - std::vector> futures; - - // number of threads: use all cores by default or set number as command-line parameter - auto numThreads = 0; - if (argc == 2) - numThreads = std::stoi(argv[1]); - if (numThreads <= 0) - numThreads = std::thread::hardware_concurrency(); - printf("use %d threads:\n", numThreads); - - // ////////////////////////////////////////////////////////// - // one byte at once - startTime = seconds(); - crc = run(crc32_1byte, data, NumBytes, numThreads); - duration = seconds() - startTime; - printf(" 1 byte at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - numThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - - // four bytes at once - startTime = seconds(); - crc = run(crc32_4bytes, data, NumBytes, numThreads); - duration = seconds() - startTime; - printf(" 4 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - numThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - - // eight bytes at once - startTime = seconds(); - crc = run(crc32_8bytes, data, NumBytes, numThreads); - duration = seconds() - startTime; - printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - numThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - - // eight bytes at once, unrolled 4 times (=> 32 bytes per loop) - startTime = seconds(); - crc = run(crc32_4x8bytes, data, NumBytes, numThreads); - duration = seconds() - startTime; - printf("4x8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - numThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - - // sixteen bytes at once - startTime = seconds(); - crc = run(crc32_16bytes, data, NumBytes, numThreads); - duration = seconds() - startTime; - printf(" 16 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - numThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - - // ////////////////////////////////////////////////////////// - // slowly increment number of threads to determine scalability - printf("run slicing-by-8 algorithm with 1 to %d threads:\n", numThreads); - for (auto scaleThreads = 1; scaleThreads <= numThreads; scaleThreads++) - { - // eight bytes at once - startTime = seconds(); - - if (scaleThreads == 1) - crc = crc32_8bytes (data, NumBytes); // single-threaded - else - crc = run(crc32_8bytes, data, NumBytes, scaleThreads); // multi-threaded - - duration = seconds() - startTime; - printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", - scaleThreads, crc, duration, (NumBytes / (1024*1024)) / duration); - } - - // ////////////////////////////////////////////////////////// - // verify crc32_combine - if (!testCombine(data, 1024)) - printf("ERROR in crc32_combine !!!\n"); - - delete[] data; - return 0; -} diff --git a/HACKING.md b/HACKING.md new file mode 100644 index 0000000..64bd71a --- /dev/null +++ b/HACKING.md @@ -0,0 +1,96 @@ +# Hacking + +Here is some wisdom to help you build and test this project as a developer and +potential contributor. + +If you plan to contribute, please read the [CONTRIBUTING](CONTRIBUTING.md) +guide. + +## Developer mode + +Build system targets that are only useful for developers of this project are +hidden if the `crc32_DEVELOPER_MODE` option is disabled. Enabling this +option makes tests and other developer targets and options available. Not +enabling this option means that you are a consumer of this project and thus you +have no need for these targets and options. + +Developer mode is always set to on in CI workflows. + +### Presets + +This project makes use of [presets][1] to simplify the process of configuring +the project. As a developer, you are recommended to always have the [latest +CMake version][2] installed to make use of the latest Quality-of-Life +additions. + +You have a few options to pass `crc32_DEVELOPER_MODE` to the configure +command, but this project prefers to use presets. + +As a developer, you should create a `CMakeUserPresets.json` file at the root of +the project: + +```json +{ + "version": 2, + "cmakeMinimumRequired": { + "major": 3, + "minor": 14, + "patch": 0 + }, + "configurePresets": [ + { + "name": "dev", + "binaryDir": "${sourceDir}/build/dev", + "inherits": ["dev-mode", "ci-"], + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + } + ], + "buildPresets": [ + { + "name": "dev", + "configurePreset": "dev", + "configuration": "Debug" + } + ], + "testPresets": [ + { + "name": "dev", + "configurePreset": "dev", + "configuration": "Debug", + "output": { + "outputOnFailure": true + } + } + ] +} +``` + +You should replace `` in your newly created presets file with the name of +the operating system you have, which may be `win64` or `unix`. You can see what +these correspond to in the [`CMakePresets.json`](CMakePresets.json) file. + +`CMakeUserPresets.json` is also the perfect place in which you can put all +sorts of things that you would otherwise want to pass to the configure command +in the terminal. + +### Configure, build and test + +If you followed the above instructions, then you can configure, build and test +the project respectively with the following commands from the project root on +any operating system with any build system: + +```sh +cmake --preset=dev +cmake --build --preset=dev +ctest --preset=dev +``` + +Please note that both the build and test command accepts a `-j` flag to specify +the number of jobs to use, which should ideally be specified to the number of +threads your CPU has. You may also want to add that to your preset using the +`jobs` property, see the [presets documentation][1] for more details. + +[1]: https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html +[2]: https://cmake.org/download/ diff --git a/Makefile b/Makefile deleted file mode 100644 index 066c3a0..0000000 --- a/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# simple Makefile -#CXX = g++ - -# files -PROGRAM = Crc32Test -LIBS = -lrt -HEADERS = Crc32.h -OBJECTS = Crc32.o Crc32Test.o - -# flags -FLAGS = -O3 -Wall -Wextra -pedantic -s - -default: $(PROGRAM) -all: default - -$(PROGRAM): $(OBJECTS) Makefile - $(CXX) $(OBJECTS) $(FLAGS) $(LIBS) -o $(PROGRAM) - -%.o: %.cpp $(HEADERS) Makefile - $(CXX) $(FLAGS) -c $< -o $@ - -clean: - -rm -f $(OBJECTS) $(PROGRAM) - -run: $(PROGRAM) - ./$(PROGRAM) diff --git a/README.md b/README.md new file mode 100644 index 0000000..002905e --- /dev/null +++ b/README.md @@ -0,0 +1,75 @@ +# Fast CRC32 + +Fast CRC32 library, based on the work of Stephan Brumme (https://create.stephan-brumme.com/crc32/). + +[![Continuous Integration](https://github.com/bensuperpc/crc32/actions/workflows/base.yml/badge.svg)](https://github.com/bensuperpc/crc32/actions/workflows/base.yml) [![Dockcross CI](https://github.com/bensuperpc/crc32/actions/workflows/dockcross.yml/badge.svg)](https://github.com/bensuperpc/crc32/actions/workflows/dockcross.yml) + +[![linux](https://github.com/bensuperpc/crc32/actions/workflows/linux.yml/badge.svg)](https://github.com/bensuperpc/crc32/actions/workflows/linux.yml) [![windows](https://github.com/bensuperpc/crc32/actions/workflows/windows.yml/badge.svg)](https://github.com/bensuperpc/crc32/actions/workflows/windows.yml) [![macos](https://github.com/bensuperpc/crc32/actions/workflows/macos.yml/badge.svg)](https://github.com/bensuperpc/crc32/actions/workflows/macos.yml) + +## Features + +- C99 and C++11 support (C++17 recommended, eg **std::string_view** ...) +- CMake support (3.14 minimal or 3.19 with preset) +- The fastest algorithms need about 1 CPU cycle per byte +- Endian-aware +- Support for [multi-threaded computation](example/crc32_test_multithreaded.cpp) +- Multi OS support: Linux 32/64, MacOS, Windows 32/64, Android 32/64 +- Cross-plateform support: AMD64, I386, ARMv8, ARMv7, ARMv6, ARMv5, RISC-V 32/64, PPC64le, Mips, m68k.. +- Runs even on [Arduino](Crc32Best.ino), Raspberry Pi, etc. +- Quite long posting about it on https://create.stephan-brumme.com/crc32/, describing each implemented algorithm in detail + +## Algorithms + +| Functions | version | Published by | CPU cycles/byte | Bits/iter | Table size | MB/s | +| ------------------------------------------------------ | ------- | ---------------- | --------------- | --------- | ---------- | ------ | +| bitwise_branch / crc32::bitwise_branch | 1.0.0 | unknown | 100 | 1 | - | 170 | +| bitwise / crc32::bitwise | 1.0.0 | unknown | 50 or 40 | 1 | - | 190 | +| half-byte / crc32::half-byte | 1.0.0 | unknown | 14 | 4 | 64 bytes | 263 | +| crc32_1byte / crc32::crc32_1byte | 1.0.0 | Hagai Gold | 8 | 8 | 1 KB | 522 | +| crc32_1byte_tableless / crc32::crc32_1byte_tableless | 1.0.0 | Henry S. Warren | 18 | 8 | - | 300 | +| crc32_1byte_tableless2 / crc32::crc32_1byte_tableless2 | 1.0.0 | Dilip V. Sarwate | 19 | 8 | - | 170 | +| crc32_4bytes / crc32::crc32_4bytes | 1.0.0 | Intel Corp. | 3 or 4 | 32 | 4 KB | 1458 | +| crc32_8bytes / crc32::crc32_8bytes | 1.0.0 | Intel Corp. | 3 or 4 | 64 | 8 KB | 2629 | +| crc32_4x8bytes / crc32::crc32_4x8bytes | 1.0.0 | ? | 1.75 or 2.25 | 256 | 8 KB | 3003 | +| crc32_16bytes / crc32::crc32_16bytes | 1.0.0 | Bulat Ziganshin | 1.1 or 1.5 | 128 | 16 KB | 6027 | +| crc32_16bytes_prefetch / crc32::crc32_16bytes_prefetch | 1.0.0 | Bulat Ziganshin | 1 or 1.5 | 512 | 16 KB | 6102 | +| crc32_fast / crc32::crc32_fast | 1.0.0 | None | varies | varies | varies | varies | + +Tested on Lenovo Legion 5 Pro: +- Manjaro 21.1.6 +- Clang 12.0.1 +- Build type: Release +- CPU: AMD R7 5800H +- RAM: 32 GB DDR4 3200Mhz 22CL 8x +- Data: 1 GB + +### Others function +- crc32_combine() "merges" two indepedently computed CRC32 values which is the basis for even faster multi-threaded calculation + +See my website https://create.stephan-brumme.com/crc32/ for documentation, code examples and a benchmark. + +# Building and installing + +See the [BUILDING](BUILDING.md) document. + +# Contributing + +See the [CONTRIBUTING](CONTRIBUTING.md) document. + +# Open source projects used + +- [crc32](https://github.com/stbrumme/crc32) +- [dockcross](https://github.com/dockcross/dockcross) +- [crosstool-ng](https://github.com/crosstool-ng/crosstool-ng) +- [git](https://github.com/git/git) +- [cmake-init](https://github.com/friendlyanon/cmake-init) +- [buildroot](https://github.com/buildroot/buildroot) +- [CMake](https://github.com/Kitware/CMake) +- [llvm-project](https://github.com/llvm/llvm-project) +- [gcc](https://github.com/gcc-mirror/gcc) +- [docker](https://github.com/docker/docker) +- [actions](https://github.com/actions/virtual-environments) + +# Licensing + +See the [LICENSE](LICENSE) document. diff --git a/cmake/coverage.cmake b/cmake/coverage.cmake new file mode 100644 index 0000000..c89cc16 --- /dev/null +++ b/cmake/coverage.cmake @@ -0,0 +1,33 @@ +# ---- Variables ---- + +# We use variables separate from what CTest uses, because those have +# customization issues +set( + COVERAGE_TRACE_COMMAND + lcov -c -q + -o "${PROJECT_BINARY_DIR}/coverage.info" + -d "${PROJECT_BINARY_DIR}" + --include "${PROJECT_SOURCE_DIR}/*" + CACHE STRING + "; separated command to generate a trace for the 'coverage' target" +) + +set( + COVERAGE_HTML_COMMAND + genhtml --legend -f -q + "${PROJECT_BINARY_DIR}/coverage.info" + -p "${PROJECT_SOURCE_DIR}" + -o "${PROJECT_BINARY_DIR}/coverage_html" + CACHE STRING + "; separated command to generate an HTML report for the 'coverage' target" +) + +# ---- Coverage target ---- + +add_custom_target( + coverage + COMMAND ${COVERAGE_TRACE_COMMAND} + COMMAND ${COVERAGE_HTML_COMMAND} + COMMENT "Generating coverage report" + VERBATIM +) diff --git a/cmake/dev-mode.cmake b/cmake/dev-mode.cmake new file mode 100644 index 0000000..cfffaa6 --- /dev/null +++ b/cmake/dev-mode.cmake @@ -0,0 +1,25 @@ +include(cmake/folders.cmake) + +include(CTest) +if(BUILD_TESTING) + add_subdirectory(test) +endif() + +option(BUILD_MCSS_DOCS "Build documentation using Doxygen and m.css" OFF) +if(BUILD_MCSS_DOCS) + include(cmake/docs.cmake) +endif() + +option(ENABLE_COVERAGE "Enable coverage support separate from CTest's" OFF) +if(ENABLE_COVERAGE) + include(cmake/coverage.cmake) +endif() + +if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + include(cmake/open-cpp-coverage.cmake OPTIONAL) +endif() + +include(cmake/lint-targets.cmake) +include(cmake/spell-targets.cmake) + +add_folders(Project) diff --git a/cmake/docs-ci.cmake b/cmake/docs-ci.cmake new file mode 100644 index 0000000..ae7f0c7 --- /dev/null +++ b/cmake/docs-ci.cmake @@ -0,0 +1,112 @@ +cmake_minimum_required(VERSION 3.14) + +foreach(var IN ITEMS PROJECT_BINARY_DIR PROJECT_SOURCE_DIR) + if(NOT DEFINED "${var}") + message(FATAL_ERROR "${var} must be defined") + endif() +endforeach() +set(bin "${PROJECT_BINARY_DIR}") +set(src "${PROJECT_SOURCE_DIR}") + +# ---- Dependencies ---- + +set(mcss_SOURCE_DIR "${bin}/docs/.ci") +if(NOT IS_DIRECTORY "${mcss_SOURCE_DIR}") + file(MAKE_DIRECTORY "${mcss_SOURCE_DIR}") + file( + DOWNLOAD + https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip + "${mcss_SOURCE_DIR}/mcss.zip" + STATUS status + EXPECTED_MD5 00cd2757ebafb9bcba7f5d399b3bec7f + ) + if(NOT status MATCHES "^0;") + message(FATAL_ERROR "Download failed with ${status}") + endif() + execute_process( + COMMAND "${CMAKE_COMMAND}" -E tar xf mcss.zip + WORKING_DIRECTORY "${mcss_SOURCE_DIR}" + RESULT_VARIABLE result + ) + if(NOT result EQUAL "0") + message(FATAL_ERROR "Extraction failed with ${result}") + endif() + file(REMOVE "${mcss_SOURCE_DIR}/mcss.zip") +endif() + +find_program(Python3_EXECUTABLE NAMES python3 python) +if(NOT Python3_EXECUTABLE) + message(FATAL_ERROR "Python executable was not found") +endif() + +# ---- Process project() call in CMakeLists.txt ---- + +file(READ "${src}/CMakeLists.txt" content) + +string(FIND "${content}" "project(" index) +if(index EQUAL "-1") + message(FATAL_ERROR "Could not find \"project(\"") +endif() +string(SUBSTRING "${content}" "${index}" -1 content) + +string(FIND "${content}" "\n)\n" index) +if(index EQUAL "-1") + message(FATAL_ERROR "Could not find \"\\n)\\n\"") +endif() +string(SUBSTRING "${content}" 0 "${index}" content) + +file(WRITE "${bin}/docs-ci.project.cmake" "docs_${content}\n)\n") + +macro(list_pop_front list out) + list(GET "${list}" 0 "${out}") + list(REMOVE_AT "${list}" 0) +endmacro() + +function(docs_project name) + cmake_parse_arguments(PARSE_ARGV 1 "" "" "VERSION;DESCRIPTION;HOMEPAGE_URL" LANGUAGES) + set(PROJECT_NAME "${name}" PARENT_SCOPE) + if(DEFINED _VERSION) + set(PROJECT_VERSION "${_VERSION}" PARENT_SCOPE) + string(REGEX MATCH "^[0-9]+(\\.[0-9]+)*" versions "${_VERSION}") + string(REPLACE . ";" versions "${versions}") + set(suffixes MAJOR MINOR PATCH TWEAK) + while(NOT versions STREQUAL "" AND NOT suffixes STREQUAL "") + list_pop_front(versions version) + list_pop_front(suffixes suffix) + set("PROJECT_VERSION_${suffix}" "${version}" PARENT_SCOPE) + endwhile() + endif() + if(DEFINED _DESCRIPTION) + set(PROJECT_DESCRIPTION "${_DESCRIPTION}" PARENT_SCOPE) + endif() + if(DEFINED _HOMEPAGE_URL) + set(PROJECT_HOMEPAGE_URL "${_HOMEPAGE_URL}" PARENT_SCOPE) + endif() +endfunction() + +include("${bin}/docs-ci.project.cmake") + +# ---- Generate docs ---- + +if(NOT DEFINED DOXYGEN_OUTPUT_DIRECTORY) + set(DOXYGEN_OUTPUT_DIRECTORY "${bin}/docs") +endif() +set(out "${DOXYGEN_OUTPUT_DIRECTORY}") + +foreach(file IN ITEMS Doxyfile conf.py) + configure_file("${src}/docs/${file}.in" "${bin}/docs/${file}" @ONLY) +endforeach() + +set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py") +set(config "${bin}/docs/conf.py") + +file(REMOVE_RECURSE "${out}/html" "${out}/xml") + +execute_process( + COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}" + WORKING_DIRECTORY "${bin}/docs" + RESULT_VARIABLE result +) +if(NOT result EQUAL "0") + message(FATAL_ERROR "m.css returned with ${result}") +endif() diff --git a/cmake/docs.cmake b/cmake/docs.cmake new file mode 100644 index 0000000..e0e9939 --- /dev/null +++ b/cmake/docs.cmake @@ -0,0 +1,40 @@ +# ---- Dependencies ---- + +include(FetchContent) +FetchContent_Declare( + mcss URL + https://github.com/friendlyanon/m.css/releases/download/release-1/mcss.zip + URL_MD5 00cd2757ebafb9bcba7f5d399b3bec7f + SOURCE_DIR "${PROJECT_BINARY_DIR}/mcss" + UPDATE_DISCONNECTED YES +) +FetchContent_MakeAvailable(mcss) + +find_package(Python3 3.6 REQUIRED) + +# ---- Declare documentation target ---- + +set( + DOXYGEN_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/docs" + CACHE PATH "Path for the generated Doxygen documentation" +) + +set(working_dir "${PROJECT_BINARY_DIR}/docs") + +foreach(file IN ITEMS Doxyfile conf.py) + configure_file("docs/${file}.in" "${working_dir}/${file}" @ONLY) +endforeach() + +set(mcss_script "${mcss_SOURCE_DIR}/documentation/doxygen.py") +set(config "${working_dir}/conf.py") + +add_custom_target( + docs + COMMAND "${CMAKE_COMMAND}" -E remove_directory + "${DOXYGEN_OUTPUT_DIRECTORY}/html" + "${DOXYGEN_OUTPUT_DIRECTORY}/xml" + COMMAND "${Python3_EXECUTABLE}" "${mcss_script}" "${config}" + COMMENT "Building documentation using Doxygen and m.css" + WORKING_DIRECTORY "${working_dir}" + VERBATIM +) diff --git a/cmake/folders.cmake b/cmake/folders.cmake new file mode 100644 index 0000000..da7bd33 --- /dev/null +++ b/cmake/folders.cmake @@ -0,0 +1,21 @@ +set_property(GLOBAL PROPERTY USE_FOLDERS YES) + +# Call this function at the end of a directory scope to assign a folder to +# targets created in that directory. Utility targets will be assigned to the +# UtilityTargets folder, otherwise to the ${name}Targets folder. If a target +# already has a folder assigned, then that target will be skipped. +function(add_folders name) + get_property(targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) + foreach(target IN LISTS targets) + get_property(folder TARGET "${target}" PROPERTY FOLDER) + if(DEFINED folder) + continue() + endif() + set(folder Utility) + get_property(type TARGET "${target}" PROPERTY TYPE) + if(NOT type STREQUAL "UTILITY") + set(folder "${name}") + endif() + set_property(TARGET "${target}" PROPERTY FOLDER "${folder}Targets") + endforeach() +endfunction() diff --git a/cmake/install-config.cmake b/cmake/install-config.cmake new file mode 100644 index 0000000..1b569da --- /dev/null +++ b/cmake/install-config.cmake @@ -0,0 +1 @@ +include("${CMAKE_CURRENT_LIST_DIR}/crc32Targets.cmake") diff --git a/cmake/install-rules.cmake b/cmake/install-rules.cmake new file mode 100644 index 0000000..d59cd76 --- /dev/null +++ b/cmake/install-rules.cmake @@ -0,0 +1,67 @@ +if(PROJECT_IS_TOP_LEVEL) + set(CMAKE_INSTALL_INCLUDEDIR include/crc32 CACHE PATH "") +endif() + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) + +# find_package() call for consumers to find this project +set(package crc32) + +install( + DIRECTORY + include/ + "${PROJECT_BINARY_DIR}/export/" + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" + COMPONENT crc32_Development +) + +install( + TARGETS crc32_crc32 + EXPORT crc32Targets + RUNTIME # + COMPONENT crc32_Runtime + LIBRARY # + COMPONENT crc32_Runtime + NAMELINK_COMPONENT crc32_Development + ARCHIVE # + COMPONENT crc32_Development + INCLUDES # + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" +) + +write_basic_package_version_file( + "${package}ConfigVersion.cmake" + COMPATIBILITY SameMajorVersion +) + +# Allow package maintainers to freely override the path for the configs +set( + crc32_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/${package}" + CACHE PATH "CMake package config location relative to the install prefix" +) +mark_as_advanced(crc32_INSTALL_CMAKEDIR) + +install( + FILES cmake/install-config.cmake + DESTINATION "${crc32_INSTALL_CMAKEDIR}" + RENAME "${package}Config.cmake" + COMPONENT crc32_Development +) + +install( + FILES "${PROJECT_BINARY_DIR}/${package}ConfigVersion.cmake" + DESTINATION "${crc32_INSTALL_CMAKEDIR}" + COMPONENT crc32_Development +) + +install( + EXPORT crc32Targets + NAMESPACE crc32:: + DESTINATION "${crc32_INSTALL_CMAKEDIR}" + COMPONENT crc32_Development +) + +if(PROJECT_IS_TOP_LEVEL) + include(CPack) +endif() diff --git a/cmake/lint-targets.cmake b/cmake/lint-targets.cmake new file mode 100644 index 0000000..244d521 --- /dev/null +++ b/cmake/lint-targets.cmake @@ -0,0 +1,34 @@ +set( + FORMAT_PATTERNS + source/*.cpp source/*.hpp + include/*.hpp + test/*.cpp test/*.hpp + example/*.cpp example/*.hpp + CACHE STRING + "; separated patterns relative to the project source dir to format" +) + +set(FORMAT_COMMAND clang-format CACHE STRING "Formatter to use") + +add_custom_target( + format-check + COMMAND "${CMAKE_COMMAND}" + -D "FORMAT_COMMAND=${FORMAT_COMMAND}" + -D "PATTERNS=${FORMAT_PATTERNS}" + -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Linting the code" + VERBATIM +) + +add_custom_target( + format-fix + COMMAND "${CMAKE_COMMAND}" + -D "FORMAT_COMMAND=${FORMAT_COMMAND}" + -D "PATTERNS=${FORMAT_PATTERNS}" + -D FIX=YES + -P "${PROJECT_SOURCE_DIR}/cmake/lint.cmake" + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + COMMENT "Fixing the code" + VERBATIM +) diff --git a/cmake/lint.cmake b/cmake/lint.cmake new file mode 100644 index 0000000..c0d2725 --- /dev/null +++ b/cmake/lint.cmake @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.14) + +macro(default name) + if(NOT DEFINED "${name}") + set("${name}" "${ARGN}") + endif() +endmacro() + +default(FORMAT_COMMAND clang-format) +default( + PATTERNS + source/*.cpp source/*.hpp + include/*.hpp + test/*.cpp test/*.hpp + example/*.cpp example/*.hpp +) +default(FIX NO) + +set(flag --output-replacements-xml) +set(args OUTPUT_VARIABLE output) +if(FIX) + set(flag -i) + set(args "") +endif() + +file(GLOB_RECURSE files ${PATTERNS}) +set(badly_formatted "") +set(output "") +string(LENGTH "${CMAKE_SOURCE_DIR}/" path_prefix_length) + +foreach(file IN LISTS files) + execute_process( + COMMAND "${FORMAT_COMMAND}" --style=file "${flag}" "${file}" + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" + RESULT_VARIABLE result + ${args} + ) + if(NOT result EQUAL "0") + message(FATAL_ERROR "'${file}': formatter returned with ${result}") + endif() + if(NOT FIX AND output MATCHES "\n ...) +function(windows_set_path TEST) + if(NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + return() + endif() + + set(path "") + set(glue "") + foreach(target IN LISTS ARGN) + if(TARGET "${target}") + get_target_property(type "${target}" TYPE) + if(type STREQUAL "SHARED_LIBRARY") + set(path "${path}${glue}$") + set(glue "\;") # backslash is important + endif() + endif() + endforeach() + if(NOT path STREQUAL "") + set_property(TEST "${TEST}" PROPERTY ENVIRONMENT "PATH=${path}") + endif() +endfunction() diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in new file mode 100644 index 0000000..dc37a2a --- /dev/null +++ b/docs/Doxyfile.in @@ -0,0 +1,32 @@ +# Configuration for Doxygen for use with CMake +# Only options that deviate from the default are included +# To create a new Doxyfile containing all available options, call `doxygen -g` + +# Get Project name and version from CMake +PROJECT_NAME = "@PROJECT_NAME@" +PROJECT_NUMBER = "@PROJECT_VERSION@" + +# Add sources +INPUT = "@PROJECT_SOURCE_DIR@/README.md" "@PROJECT_SOURCE_DIR@/include" "@PROJECT_SOURCE_DIR@/docs/pages" +EXTRACT_ALL = YES +RECURSIVE = YES +OUTPUT_DIRECTORY = "@DOXYGEN_OUTPUT_DIRECTORY@" + +# Use the README as a main page +USE_MDFILE_AS_MAINPAGE = "@PROJECT_SOURCE_DIR@/README.md" + +# set relative include paths +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = "@PROJECT_SOURCE_DIR@/include" "@PROJECT_SOURCE_DIR@" +STRIP_FROM_INC_PATH = + +# We use m.css to generate the html documentation, so we only need XML output +GENERATE_XML = YES +GENERATE_HTML = NO +GENERATE_LATEX = NO +XML_PROGRAMLISTING = NO +CREATE_SUBDIRS = NO + +# Include all directories, files and namespaces in the documentation +# Disable to include only explicitly documented objects +M_SHOW_UNDOCUMENTED = YES diff --git a/docs/conf.py.in b/docs/conf.py.in new file mode 100644 index 0000000..b81e3d9 --- /dev/null +++ b/docs/conf.py.in @@ -0,0 +1,6 @@ +DOXYFILE = 'Doxyfile' + +LINKS_NAVBAR1 = [ + (None, 'pages', [(None, 'about')]), + (None, 'namespaces', []), +] diff --git a/docs/pages/about.dox b/docs/pages/about.dox new file mode 100644 index 0000000..2efbda9 --- /dev/null +++ b/docs/pages/about.dox @@ -0,0 +1,7 @@ +/** + * @page about About + * @section about-doxygen Doxygen documentation + * This page is auto generated using + * Doxygen, making use of some useful + * special commands. + */ diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 0000000..eba802e --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.14) + +project(crc32Examples C CXX) + +include(../cmake/project-is-top-level.cmake) +include(../cmake/folders.cmake) + +if(PROJECT_IS_TOP_LEVEL) + find_package(crc32 REQUIRED) +endif() + +add_custom_target(run-examples) + +function(add_example NAME) + add_executable("${NAME}" "${NAME}.cpp") + target_link_libraries("${NAME}" PRIVATE crc32::crc32) +# target_compile_features("${NAME}" PRIVATE cxx_std_17) + add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM) + add_dependencies("run_${NAME}" "${NAME}") + add_dependencies(run-examples "run_${NAME}") +endfunction() + +function(add_c_example NAME) + add_executable("${NAME}" "${NAME}.c") + target_link_libraries("${NAME}" PRIVATE crc32::crc32) + add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM) + add_dependencies("run_${NAME}" "${NAME}") + add_dependencies(run-examples "run_${NAME}") +endfunction() + +function(add_example_thread NAME) + add_executable("${NAME}" "${NAME}.cpp") + target_link_libraries("${NAME}" PRIVATE crc32::crc32 Threads::Threads) +# target_compile_features("${NAME}" PRIVATE cxx_std_17) + add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM) + add_dependencies("run_${NAME}" "${NAME}") + add_dependencies(run-examples "run_${NAME}") +endfunction() + +add_example(crc32_test_singlethreaded) + +add_example(simple_example) +add_c_example(simple_c_example) + + +set(CMAKE_THREAD_PREFER_PTHREAD TRUE) +set(THREADS_PREFER_PTHREAD_FLAG TRUE) +find_package(Threads) + +if(Threads_FOUND) + add_example_thread(crc32_test_multithreaded) +else() +message(WARNING "Threads not found ! Disable crc32_test_multithreaded example." ) +endif() + +add_folders(Example) diff --git a/example/crc32_test_multithreaded.cpp b/example/crc32_test_multithreaded.cpp new file mode 100644 index 0000000..25be93d --- /dev/null +++ b/example/crc32_test_multithreaded.cpp @@ -0,0 +1,295 @@ +// ////////////////////////////////////////////////////////// +// Crc32TestMultithreaded.cpp +// Copyright (c) 2021 Stephan Brumme. All rights reserved. +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include // std::chrono +#include +#include +#include +#include + +#include "crc32/crc32.hpp" + +// C++11 multithreading +#include +#include + +// ////////////////////////////////////////////////////////// +// test code + +/// one gigabyte +const size_t NumBytes = 1024 * 1024 * 1024; + +using cpp_clock = std::chrono::high_resolution_clock; + +// ////////////////////////////////////////////////////////// +// run a CRC32 algorithm on multiple threads +typedef uint32_t (*Crc32Algorithm)(const void* data, + size_t length, + uint32_t previousCrc32); +// compute CRC32 of up to maxBlockSize bytes and start recursively a new thread +// for excess data +uint32_t asyncCrc32(Crc32Algorithm myCrc32, + const void* data, + size_t numBytes, + size_t maxBlockSize) +{ + // last block ? + if (numBytes <= maxBlockSize) + return myCrc32(data, numBytes, 0); // we're done + + // compute CRC of the remaining bytes in a separate thread + auto dataLeft = reinterpret_cast(data) + maxBlockSize; + auto bytesLeft = numBytes - maxBlockSize; + auto remainder = std::async(std::launch::async, + asyncCrc32, + myCrc32, + dataLeft, + bytesLeft, + maxBlockSize); + + // compute CRC of the current block + auto currentCrc = myCrc32(data, maxBlockSize, 0); + // get CRC of the remainder + auto remainderCrc = remainder.get(); + // and merge both + return crc32::crc32_combine(currentCrc, remainderCrc, bytesLeft); +} +// call: run(crc32_8bytes, data, NumBytes, 8) if you have an octocore CPU +uint32_t run(Crc32Algorithm myCrc32, + const void* data, + size_t numBytes, + size_t numThreads = 0) +{ + // run on all cores + if (numThreads == 0) + numThreads = std::thread::hardware_concurrency(); + + // split data evenly, rounding up + auto defaultBlocksize = (numBytes + numThreads - 1) / numThreads; + + return asyncCrc32(myCrc32, data, numBytes, defaultBlocksize); +} + +// test original sequential CRC32 algorithm against crc32_combine +bool testCombine(const char* data, size_t maxBytes = 1024) +{ + bool ok = true; + for (size_t lengthA = 1; lengthA < maxBytes; lengthA++) { + // split bytes into two blocks of lengthA and lengthB + auto lengthB = maxBytes - lengthA; + +// compute CRC of both blocks +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + auto crcA = crc32::crc32_1byte(data, lengthA); + auto crcB = crc32::crc32_1byte(data + lengthA, lengthB); + + // CRC of the whole block + auto crcAtOnce = crc32::crc32_1byte(data, maxBytes); + // CRC of both blocks in a sequential fashion + auto crcSequential = crc32::crc32_1byte(data + lengthA, lengthB, crcA); + + // CRC using the new crc32_combine function + auto crcCombined = crc32::crc32_combine(crcA, crcB, lengthB); + + // check results + if (crcAtOnce != crcSequential || crcAtOnce != crcCombined) { + printf("FAILED @ %zu: %08X %08X %08X %08X %08X\n", + lengthA, + crcA, + crcB, + crcAtOnce, + crcSequential, + crcCombined); + ok = false; + } +#else + auto crcA = crc32::crc32_halfbyte(data, lengthA); + auto crcB = crc32::crc32_halfbyte(data + lengthA, lengthB); + + // CRC of the whole block + auto crcAtOnce = crc32::crc32_halfbyte(data, maxBytes); + // CRC of both blocks in a sequential fashion + auto crcSequential = crc32::crc32_halfbyte(data + lengthA, lengthB, crcA); + + // CRC using the new crc32_combine function + auto crcCombined = crc32::crc32_combine(crcA, crcB, lengthB); + + // check results + if (crcAtOnce != crcSequential || crcAtOnce != crcCombined) { + printf("FAILED @ %zu: %08X %08X %08X %08X %08X\n", + lengthA, + crcA, + crcB, + crcAtOnce, + crcSequential, + crcCombined); + ok = false; + } +#endif + } + return ok; +} + +int main(int argc, char* argv[]) +{ + // ////////////////////////////////////////////////////////// + printf("Please wait ...\n"); + + uint32_t randomNumber = 0x27121978; + // initialize + char* data = new char[NumBytes]; + for (size_t i = 0; i < NumBytes; i++) { + data[i] = char(randomNumber & 0xFF); + // simple LCG, see + // http://en.wikipedia.org/wiki/Linear_congruential_generator + randomNumber = 1664525 * randomNumber + 1013904223; + } + + // re-use variables + auto start_time = cpp_clock::now(); + + double duration = 0.0; + uint32_t crc = 0; + + // number of threads: use all cores by default or set number as command-line + // parameter + auto numThreads = 0; + if (argc == 2) { + numThreads = std::stoi(argv[1]); + } + if (numThreads <= 0) { + numThreads = std::thread::hardware_concurrency(); + } + printf("use %d threads:\n", numThreads); + +// ////////////////////////////////////////////////////////// +// one byte at once +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + start_time = cpp_clock::now(); + crc = run(crc32::crc32_1byte, data, NumBytes, numThreads); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 1 byte at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + numThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif + +// four bytes at once +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + start_time = cpp_clock::now(); + crc = run(crc32::crc32_4bytes, data, NumBytes, numThreads); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 4 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + numThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif + +// eight bytes at once +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + start_time = cpp_clock::now(); + crc = run(crc32::crc32_8bytes, data, NumBytes, numThreads); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + numThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); + +#endif + +// eight bytes at once, unrolled 4 times (=> 32 bytes per loop) +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + start_time = cpp_clock::now(); + crc = run(crc32::crc32_4x8bytes, data, NumBytes, numThreads); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("4x8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + numThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif + +// sixteen bytes at once +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + start_time = cpp_clock::now(); + crc = run(crc32::crc32_16bytes, data, NumBytes, numThreads); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 16 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + numThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif + +// ////////////////////////////////////////////////////////// +// slowly increment number of threads to determine scalability +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + printf("run slicing-by-8 algorithm with 1 to %d threads:\n", numThreads); +#else + printf("run crc32_halfbyte algorithm with 1 to %d threads:\n", numThreads); +#endif + + for (auto scaleThreads = 1; scaleThreads <= numThreads; scaleThreads++) { + // eight bytes at once + start_time = cpp_clock::now(); +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + if (scaleThreads == 1) { + crc = crc32::crc32_8bytes(data, NumBytes); // single-threaded + } else { + crc = run( + crc32::crc32_8bytes, data, NumBytes, scaleThreads); // multi-threaded + } +#else + if (scaleThreads == 1) { + crc = crc32::crc32_halfbyte(data, NumBytes); // single-threaded + } else { + crc = run(crc32::crc32_halfbyte, + data, + NumBytes, + scaleThreads); // multi-threaded + } +#endif + + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + printf(" 8 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + scaleThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#else + printf(" 0.5 bytes at once / %d threads: CRC=%08X, %.3fs, %.3f MB/s\n", + scaleThreads, + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif + + // ////////////////////////////////////////////////////////// + // verify crc32_combine + if (!testCombine(data, 1024)) { + printf("ERROR in crc32_combine !!!\n"); + } + + delete[] data; + return 0; + } +} diff --git a/example/crc32_test_singlethreaded.cpp b/example/crc32_test_singlethreaded.cpp new file mode 100644 index 0000000..20ce8bd --- /dev/null +++ b/example/crc32_test_singlethreaded.cpp @@ -0,0 +1,198 @@ +// ////////////////////////////////////////////////////////// +// test_example.cpp +// Copyright (c) 2016-2021 Stephan Brumme. All rights reserved. +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include // std::chrono +#include +#include + +#include "crc32/crc32.hpp" + +// the slicing-by-4/8/16 tests are only performed if the corresponding +// preprocessor symbol is defined in crc32.hpp +// simpler algorithms can be enabled/disabled right here: +#define CRC32_TEST_BITWISE +#define CRC32_TEST_HALFBYTE +#define CRC32_TEST_TABLELESS + +using cpp_clock = std::chrono::high_resolution_clock; + +// ////////////////////////////////////////////////////////// +// test code + +/// one gigabyte +const size_t NumBytes = 1024 * 1024 * 1024; +/// 4k chunks during last test +const size_t DefaultChunkSize = 4 * 1024; + +auto main(int argc, char* argv[]) -> int +{ + printf("Please wait ...\n"); + + uint32_t randomNumber = 0x27121978; + // initialize + char* data = new char[NumBytes]; + for (size_t i = 0; i < NumBytes; i++) { + data[i] = char(randomNumber & 0xFF); + // simple LCG, see + // http://en.wikipedia.org/wiki/Linear_congruential_generator + randomNumber = 1664525 * randomNumber + 1013904223; + } + + // re-use variables + auto start_time = cpp_clock::now(); + + double duration = 0.0; + uint32_t crc = 0; + +#ifdef CRC32_TEST_BITWISE + // bitwise + start_time = cpp_clock::now(); + crc = crc32::crc32_bitwise(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("bitwise : CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_TEST_BITWISE + +#ifdef CRC32_TEST_HALFBYTE + // half-byte + start_time = cpp_clock::now(); + crc = crc32::crc32_halfbyte(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("half-byte : CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_TEST_HALFBYTE + +#ifdef CRC32_TEST_TABLELESS + // one byte at once (without lookup tables) + start_time = cpp_clock::now(); + crc = crc32::crc32_1byte_tableless(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("tableless (byte) : CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); + + // one byte at once (without lookup tables) + start_time = cpp_clock::now(); + crc = crc32::crc32_1byte_tableless2(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("tableless (byte2): CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_TEST_TABLELESS + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + // one byte at once + start_time = cpp_clock::now(); + crc = crc32::crc32_1byte(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 1 byte at once: CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_USE_LOOKUP_TABLE_BYTE + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + // four bytes at once + start_time = cpp_clock::now(); + crc = crc32::crc32_4bytes(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 4 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + // eight bytes at once + start_time = cpp_clock::now(); + crc = crc32::crc32_8bytes(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); + + // eight bytes at once, unrolled 4 times (=> 32 bytes per loop) + start_time = cpp_clock::now(); + crc = crc32::crc32_4x8bytes(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf("4x8 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + // sixteen bytes at once + start_time = cpp_clock::now(); + crc = crc32::crc32_16bytes(data, NumBytes); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); + + // sixteen bytes at once + start_time = cpp_clock::now(); + crc = crc32::crc32_16bytes_prefetch(data, NumBytes, 0, 256); + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf( + " 16 bytes at once: CRC=%08X, %.3fs, %.3f MB/s (including prefetching)\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + // process in 4k chunks + start_time = cpp_clock::now(); + crc = 0; // also default parameter of crc32_xx functions + size_t bytesProcessed = 0; + while (bytesProcessed < NumBytes) { + size_t bytesLeft = NumBytes - bytesProcessed; + size_t chunkSize = + (DefaultChunkSize < bytesLeft) ? DefaultChunkSize : bytesLeft; + + crc = crc32::crc32_fast(data + bytesProcessed, chunkSize, crc); + + bytesProcessed += chunkSize; + } + duration = std::chrono::duration_cast>( + cpp_clock::now() - start_time) + .count(); + printf(" chunked : CRC=%08X, %.3fs, %.3f MB/s\n", + crc, + duration, + (NumBytes / (1024 * 1024)) / duration); + + delete[] data; + return 0; +} diff --git a/example/simple_c_example.c b/example/simple_c_example.c new file mode 100644 index 0000000..4bb584f --- /dev/null +++ b/example/simple_c_example.c @@ -0,0 +1,26 @@ +// ////////////////////////////////////////////////////////// +// simple_example.c +// Copyright (c) 2021-2021 Stephan Brumme. All rights reserved. +// Simple example contributed by Bensuperpc +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include +#include + +#include "crc32/crc32.h" + +int main() +{ + char str[5] = {'L', 'i', 'n', 'u', 'x'}; + + const uint32_t result = crc32_halfbyte(str, 5, 0); + + if (result == 0x53d0684b) { + printf("0x%.4X\n", result); + } else { + printf("Error: wrong CRC32 value"); + return 1; + } + return 0; +} diff --git a/example/simple_example.cpp b/example/simple_example.cpp new file mode 100644 index 0000000..e4f7254 --- /dev/null +++ b/example/simple_example.cpp @@ -0,0 +1,28 @@ +// ////////////////////////////////////////////////////////// +// simple_example.cpp +// Copyright (c) 2021-2021 Stephan Brumme. All rights reserved. +// Simple example contributed by Bensuperpc +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include +#include + +#include "crc32/crc32.hpp" + +auto main() -> int +{ + const std::string str1 = "Linux"; + const auto result1 = + crc32::crc32_halfbyte(str1.data(), str1.size(), 0); // Use void* for data + std::cout << "CRC32 of: " << str1 << " = 0x" << std::hex << result1 + << std::endl; + + const std::string str2 = "Linux"; + const auto result2 = crc32::crc32_halfbyte( + str2, 0); // Use std::string_view or std::string for data + std::cout << "CRC32 of: " << str2 << " = 0x" << std::hex << result2 + << std::endl; + + return 0; +} diff --git a/include/crc32/crc32.h b/include/crc32/crc32.h new file mode 100644 index 0000000..4a1d5f5 --- /dev/null +++ b/include/crc32/crc32.h @@ -0,0 +1,101 @@ +// ////////////////////////////////////////////////////////// +// crc32.h +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +#ifndef CRC32_H_INCLUDED +#define CRC32_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +// uint8_t, uint32_t, int32_t +#include + +#include "crc32/crc32_var.h" + +// Needed, add CRC32_EXPORT before each function +#include "crc32/crc32_export.hpp" + +// crc32_fast selects the fastest algorithm depending on flags +// (CRC32_USE_LOOKUP_...) +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +CRC32_EXPORT uint32_t crc32_fast(const void* data, + size_t length, + const uint32_t); + +/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, +/// lengthA)) +CRC32_EXPORT uint32_t crc32_combine(uint32_t crcA, + uint32_t crcB, + size_t lengthB); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise(const void* data, + size_t length, + const uint32_t); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise_branch(const void* data, + size_t length, + const uint32_t); + +/// compute CRC32 (half-byte algorithm) +CRC32_EXPORT uint32_t crc32_halfbyte(const void* data, + size_t length, + const uint32_t); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +CRC32_EXPORT uint32_t crc32_1byte(const void* data, + size_t length, + const uint32_t); +#endif + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless(const void* data, + size_t length, + const uint32_t); +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless2(const void* data, + size_t length, + const uint32_t); + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +CRC32_EXPORT uint32_t crc32_4bytes(const void* data, + size_t length, + const uint32_t); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +CRC32_EXPORT uint32_t crc32_8bytes(const void* data, + size_t length, + const uint32_t); +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +CRC32_EXPORT uint32_t crc32_4x8bytes(const void* data, + size_t length, + const uint32_t); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +CRC32_EXPORT uint32_t crc32_16bytes(const void* data, + size_t length, + const uint32_t); +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +CRC32_EXPORT uint32_t crc32_16bytes_prefetch(const void* data, + size_t length, + const uint32_t, + size_t prefetchAhead); +#endif + +#ifdef __cplusplus +} +#endif +#endif // CRC32_H_INCLUDED diff --git a/include/crc32/crc32.hpp b/include/crc32/crc32.hpp new file mode 100644 index 0000000..c541b6a --- /dev/null +++ b/include/crc32/crc32.hpp @@ -0,0 +1,234 @@ +// ////////////////////////////////////////////////////////// +// crc32.hpp +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +#pragma once + +// uint8_t, uint32_t, int32_t +extern "C" { +#include + +#include "crc32/crc32.h" +#include "crc32/crc32_var.h" +} + +#include // size_t + +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +# include +#else +# include +#endif + +// Needed, add CRC32_EXPORT before each function +#include "crc32/crc32_export.hpp" + +namespace crc32 +{ +// crc32_fast selects the fastest algorithm depending on flags +// (CRC32_USE_LOOKUP_...) +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +CRC32_EXPORT uint32_t crc32_fast(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); + +/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, +/// lengthA)) +CRC32_EXPORT uint32_t crc32_combine(uint32_t crcA, + uint32_t crcB, + size_t lengthB); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise_branch(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (half-byte algorithm) +CRC32_EXPORT uint32_t crc32_halfbyte(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +CRC32_EXPORT uint32_t crc32_1byte(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +#endif + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless2(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +CRC32_EXPORT uint32_t crc32_4bytes(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +CRC32_EXPORT uint32_t crc32_8bytes(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +CRC32_EXPORT uint32_t crc32_4x8bytes(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +CRC32_EXPORT uint32_t crc32_16bytes(const void* data, + size_t length, + const uint32_t previousCrc32 = 0); +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +CRC32_EXPORT uint32_t crc32_16bytes_prefetch(const void* data, + size_t length, + const uint32_t previousCrc32 = 0, + size_t prefetchAhead = 256); +#endif + +// ////////////////////////////////////////////////////////// +// C++ functions +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) + +// crc32_fast selects the fastest algorithm depending on flags +// (CRC32_USE_LOOKUP_...) +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +CRC32_EXPORT uint32_t crc32_fast(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise_branch(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (half-byte algorithm) +CRC32_EXPORT uint32_t crc32_halfbyte(std::string_view data, + const uint32_t previousCrc32 = 0); + +# ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +CRC32_EXPORT uint32_t crc32_1byte(std::string_view data, + const uint32_t previousCrc32 = 0); +# endif + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless2(std::string_view data, + const uint32_t previousCrc32 = 0); + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +CRC32_EXPORT uint32_t crc32_4bytes(std::string_view data, + const uint32_t previousCrc32 = 0); +# endif + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +CRC32_EXPORT uint32_t crc32_8bytes(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +CRC32_EXPORT uint32_t crc32_4x8bytes(std::string_view data, + const uint32_t previousCrc32 = 0); +# endif + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +CRC32_EXPORT uint32_t crc32_16bytes(std::string_view data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +CRC32_EXPORT uint32_t crc32_16bytes_prefetch(std::string_view data, + const uint32_t previousCrc32 = 0, + size_t prefetchAhead = 256); +# endif + +#else + +// crc32_fast selects the fastest algorithm depending on flags +// (CRC32_USE_LOOKUP_...) +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +CRC32_EXPORT uint32_t crc32_fast(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (bitwise algorithm) +CRC32_EXPORT uint32_t crc32_bitwise_branch(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (half-byte algorithm) +CRC32_EXPORT uint32_t crc32_halfbyte(const std::string& data, + const uint32_t previousCrc32 = 0); + +# ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +CRC32_EXPORT uint32_t crc32_1byte(const std::string& data, + const uint32_t previousCrc32 = 0); +# endif + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (byte algorithm) without lookup tables +CRC32_EXPORT uint32_t crc32_1byte_tableless2(const std::string& data, + const uint32_t previousCrc32 = 0); + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +CRC32_EXPORT uint32_t crc32_4bytes(const std::string& data, + const uint32_t previousCrc32 = 0); +# endif + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +CRC32_EXPORT uint32_t crc32_8bytes(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +CRC32_EXPORT uint32_t crc32_4x8bytes(const std::string& data, + const uint32_t previousCrc32 = 0); +# endif + +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +CRC32_EXPORT uint32_t crc32_16bytes(const std::string& data, + const uint32_t previousCrc32 = 0); + +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +CRC32_EXPORT uint32_t crc32_16bytes_prefetch(const std::string& data, + const uint32_t previousCrc32 = 0, + size_t prefetchAhead = 256); +# endif + +#endif + +// Only on private function CRC32_SUPPRESS_C4251 + +} // namespace crc32 diff --git a/include/crc32/crc32_var.h b/include/crc32/crc32_var.h new file mode 100644 index 0000000..67b0940 --- /dev/null +++ b/include/crc32/crc32_var.h @@ -0,0 +1,117 @@ +// ////////////////////////////////////////////////////////// +// crc32_var.h +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +#ifndef CRC32_VAR_H_INCLUDED +#define CRC32_VAR_H_INCLUDED + +// if running on an embedded system, you might consider shrinking the +// big crc32_global_crc32Lookup table by undefining these lines: + +// #define CRC32_USE_LOOKUP_TABLE_BYTE +// #define CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +// #define CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +// #define CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + +// - crc32_bitwise doesn't need it at all +// - crc32_bitwise_branch doesn't need it at all +// - crc32_halfbyte has its own small lookup table +// - crc32_1byte_tableless and crc32_1byte_tableless2 don't need it at all +// - crc32_1byte needs only crc32_global_crc32Lookup[0] +// - crc32_4bytes needs only crc32_global_crc32Lookup[0..3] +// - crc32_8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_4x8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_16bytes needs all of crc32_global_crc32Lookup +// using the aforementioned #defines the table is automatically fitted to your +// needs + +// Needed, add CRC32_EXPORT before each function +#include "crc32/crc32_export.hpp" + +// uint8_t, uint32_t, int32_t +#include + +#ifndef __LITTLE_ENDIAN +# define __LITTLE_ENDIAN 1234 +#endif +#ifndef __BIG_ENDIAN +# define __BIG_ENDIAN 4321 +#endif + +// define endianness and some integer data types +#if defined(_MSC_VER) || defined(__MINGW32__) +// Windows always little endian +# define __BYTE_ORDER __LITTLE_ENDIAN + +// intrinsics / prefetching +# if defined(__MINGW32__) || defined(__clang__) +# define PREFETCH(location) __builtin_prefetch(location) +# else +# if defined(__SSE2__) +# include +# define PREFETCH(location) _mm_prefetch(location, _MM_HINT_T0) +# else +# define PREFETCH(location) ; +# endif +# endif +#else +// defines __BYTE_ORDER as __LITTLE_ENDIAN or __BIG_ENDIAN +# include + +// intrinsics / prefetching +# ifdef __GNUC__ +# define PREFETCH(location) __builtin_prefetch(location) +# else +// no prefetching +# define PREFETCH(location) ; +# endif +#endif + +// abort if byte order is undefined +#if !defined(__BYTE_ORDER) + +# if _MSC_VER && !__INTEL_COMPILER +# pragma message( \ + "undefined byte order, compile with -D__BYTE_ORDER=1234 (if little endian) or -D__BYTE_ORDER=4321 (big endian)") +# pragma message("use default byte order: little endian (x86 and ARM CPUs)") +# else +# warning undefined byte order, compile with -D__BYTE_ORDER=1234 (if little endian) or -D__BYTE_ORDER=4321 (big endian) +# warning use default byte order: little endian (x86 and ARM CPUs) +# endif +#endif + +#if __BYTE_ORDER == __BIG_ENDIAN +/// swap endianness +static inline uint32_t swap(uint32_t x) +{ +# if defined(__GNUC__) || defined(__clang__) + return __builtin_bswap32(x); +# else + return (x >> 24) | ((x >> 8) & 0x0000FF00) | ((x << 8) & 0x00FF0000) + | (x << 24); +# endif +} +#endif + +// ////////////////////////////////////////////////////////// +// constants + +/// zlib's CRC32 polynomial +extern const uint32_t crc32_global_polynomial; + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +extern const uint32_t crc32_global_crc32Lookup[16][256]; +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) +extern const uint32_t crc32_global_crc32Lookup[8][256]; +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) +extern const uint32_t crc32_global_crc32Lookup[4][256]; +#elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) +extern const uint32_t crc32_global_crc32Lookup[1][256]; +#else +# define NO_LUT // don't need crc32_global_crc32Lookup at all +#endif +#endif // CRC32_VAR_H_INCLUDED diff --git a/readme.md b/readme.md deleted file mode 100644 index a8a84c6..0000000 --- a/readme.md +++ /dev/null @@ -1,25 +0,0 @@ -# Fast CRC32 - -This is a mirror of my CRC32 library hosted at https://create.stephan-brumme.com/crc32/ - -Features in a nutshell: -- C++ code, single file -- the fastest algorithms need about 1 CPU cycle per byte -- endian-aware -- support for multi-threaded computation -- runs even on Arduino, Raspberry Pi, etc. -- quite long posting about it on https://create.stephan-brumme.com/crc32/, describing each implemented algorithm in detail - -Algorithms: -- bitwise -- branch-free bitwise -- half-byte -- tableless full-byte -- Sarwate's original algorithm -- slicing-by-4 -- slicing-by-8 -- slicing-by-16 - -- crc32_combine() "merges" two indepedently computed CRC32 values which is the basis for even faster multi-threaded calculation - -See my website https://create.stephan-brumme.com/crc32/ for documentation, code examples and a benchmark. diff --git a/source/crc32.c b/source/crc32.c new file mode 100644 index 0000000..b12c445 --- /dev/null +++ b/source/crc32.c @@ -0,0 +1,614 @@ +// ////////////////////////////////////////////////////////// +// crc32.cpp +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +// if running on an embedded system, you might consider shrinking the +// big crc32_global_crc32Lookup table: +// - crc32_bitwise doesn't need it at all +// - crc32_bitwise_banch doesn't need it at all +// - crc32_halfbyte has its own small lookup table +// - crc32_1byte needs only crc32_global_crc32Lookup[0] +// - crc32_4bytes needs only crc32_global_crc32Lookup[0..3] +// - crc32_8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_4x8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_16bytes needs all of crc32_global_crc32Lookup + +#include "crc32/crc32.h" + +/// compute CRC32 (bitwise algorithm) +uint32_t crc32_bitwise(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = (const uint8_t*)data; + + while (length-- != 0) { + crc ^= *current++; + + for (int j = 0; j < 8; j++) { + // branch-free + crc = (crc >> 1) ^ (-(int32_t)(crc & 1) & crc32_global_polynomial); + } + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (bitwise algorithm with branching) +uint32_t crc32_bitwise_branch(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = (const uint8_t*)data; + + while (length-- != 0) { + crc ^= *current++; + + for (int j = 0; j < 8; j++) { + // branching, much slower + if (crc & 1) { + crc = (crc >> 1) ^ crc32_global_polynomial; + } else { + crc = crc >> 1; + } + } + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (half-byte algorithm) +uint32_t crc32_halfbyte(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = (const uint8_t*)data; + + /// look-up table for half-byte, same as crc32Lookup[0][16*i] + static const uint32_t _crc32_global_crc32Lookup16[16] = {0x00000000, + 0x1DB71064, + 0x3B6E20C8, + 0x26D930AC, + 0x76DC4190, + 0x6B6B51F4, + 0x4DB26158, + 0x5005713C, + 0xEDB88320, + 0xF00F9344, + 0xD6D6A3E8, + 0xCB61B38C, + 0x9B64C2B0, + 0x86D3D2D4, + 0xA00AE278, + 0xBDBDF21C}; + + while (length-- != 0) { + crc = _crc32_global_crc32Lookup16[(crc ^ *current) & 0x0F] ^ (crc >> 4); + crc = _crc32_global_crc32Lookup16[(crc ^ (*current >> 4)) & 0x0F] + ^ (crc >> 4); + current++; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +uint32_t crc32_1byte(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = (const uint8_t*)data; + + while (length-- != 0) + crc = (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *current++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +/// compute CRC32 (byte algorithm) without lookup tables +uint32_t crc32_1byte_tableless(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = (const uint8_t*)data; + + while (length-- != 0) { + uint8_t s = (uint8_t)crc ^ *current++; + + // Hagai Gold made me aware of this table-less algorithm and send me code + + // polynomial 0xEDB88320 can be written in binary as + // 11101101101110001000001100100000b reverse the bits (or just assume bit 0 + // is the first one) and we have bits set at position 0, 1, 2, 4, 5, 7, 8, + // 10, 11, 12, 16, 22, 23, 26 + // => those are the shift offsets: + // crc = (crc >> 8) ^ + // t ^ + // (t >> 1) ^ (t >> 2) ^ (t >> 4) ^ (t >> 5) ^ // == y + // (t >> 7) ^ (t >> 8) ^ (t >> 10) ^ (t >> 11) ^ // == y >> 6 + // (t >> 12) ^ (t >> 16) ^ // == z + // (t >> 22) ^ (t >> 26) ^ // == z >> 10 + // (t >> 23); + + // the fastest I can come up with: + uint32_t low = (s ^ (s << 6)) & 0xFF; + uint32_t a = (low * ((1 << 23) + (1 << 14) + (1 << 2))); + crc = (crc >> 8) ^ (low * ((1 << 24) + (1 << 16) + (1 << 8))) ^ a ^ (a >> 1) + ^ (low * ((1 << 20) + (1 << 12))) ^ (low << 19) ^ (low << 17) + ^ (low >> 2); + + // Hagai's code: + /*uint32_t t = (s ^ (s << 6)) << 24; + + // some temporaries to optimize XOR + uint32_t x = (t >> 1) ^ (t >> 2); + uint32_t y = x ^ (x >> 3); + uint32_t z = (t >> 12) ^ (t >> 16); + + crc = (crc >> 8) ^ + t ^ (t >> 23) ^ + y ^ (y >> 6) ^ + z ^ (z >> 10);*/ + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (byte algorithm) without lookup tables +uint32_t crc32_1byte_tableless2(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + int32_t crc = ~previousCrc32; // note: signed integer, right shift + // distributes sign bit into lower bits + const uint8_t* current = (const uint8_t*)data; + + while (length-- != 0) { + crc = crc ^ *current++; + + uint32_t c = + (((crc << 31) >> 31) + & ((crc32_global_polynomial >> 7) ^ (crc32_global_polynomial >> 1))) + ^ (((crc << 30) >> 31) + & ((crc32_global_polynomial >> 6) ^ crc32_global_polynomial)) + ^ (((crc << 29) >> 31) & (crc32_global_polynomial >> 5)) + ^ (((crc << 28) >> 31) & (crc32_global_polynomial >> 4)) + ^ (((crc << 27) >> 31) & (crc32_global_polynomial >> 3)) + ^ (((crc << 26) >> 31) & (crc32_global_polynomial >> 2)) + ^ (((crc << 25) >> 31) & (crc32_global_polynomial >> 1)) + ^ (((crc << 24) >> 31) & crc32_global_polynomial); + + crc = ((uint32_t)crc >> 8) + ^ c; // convert to unsigned integer before right shift + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +uint32_t crc32_4bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = (const uint32_t*)data; + + // process four bytes at once (Slicing-by-4) + while (length >= 4) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + crc = crc32_global_crc32Lookup[0][one & 0xFF] + ^ crc32_global_crc32Lookup[1][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + crc = crc32_global_crc32Lookup[0][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][one & 0xFF]; +# endif + + length -= 4; + } + + const uint8_t* currentChar = (const uint8_t*)current; + // remaining 1 to 3 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +uint32_t crc32_8bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = (const uint32_t*)data; + + // process eight bytes at once (Slicing-by-8) + while (length >= 8) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][two & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][one & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][two & 0xFF] + ^ crc32_global_crc32Lookup[4][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][one & 0xFF]; +# endif + + length -= 8; + } + + const uint8_t* currentChar = (const uint8_t*)current; + // remaining 1 to 7 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +uint32_t crc32_4x8bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = (const uint32_t*)data; + + // enabling optimization (at least -O2) automatically unrolls the inner + // for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 8 * Unroll; + + // process 4x eight bytes at once (Slicing-by-8) + while (length >= BytesAtOnce) { + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][two & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][one & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][two & 0xFF] + ^ crc32_global_crc32Lookup[4][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = (const uint8_t*)current; + // remaining 1 to 31 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +uint32_t crc32_16bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = (const uint32_t*)data; + + // enabling optimization (at least -O2) automatically unrolls the inner + // for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 16 * Unroll; + + while (length >= BytesAtOnce) { + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][four & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][three & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[8][two & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[11][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[12][one & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[15][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][four & 0xFF] + ^ crc32_global_crc32Lookup[4][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][three & 0xFF] + ^ crc32_global_crc32Lookup[8][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[11][two & 0xFF] + ^ crc32_global_crc32Lookup[12][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[15][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = (const uint8_t*)current; + // remaining 1 to 63 bytes (standard algorithm) + while (length-- != 0) { + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +uint32_t crc32_16bytes_prefetch(const void* data, + size_t length, + const uint32_t previousCrc32, + size_t prefetchAhead) +{ + // CRC code is identical to crc32_16bytes (including unrolling), only added + // prefetching 256 bytes look-ahead seems to be the sweet spot on Core i7 CPUs + + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = (const uint32_t*)data; + + // enabling optimization (at least -O2) automatically unrolls the for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 16 * Unroll; + + while (length >= BytesAtOnce + prefetchAhead) { + PREFETCH((const char*)current + prefetchAhead); + + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][four & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][three & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[8][two & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[11][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[12][one & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[15][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][four & 0xFF] + ^ crc32_global_crc32Lookup[4][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][three & 0xFF] + ^ crc32_global_crc32Lookup[8][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[11][two & 0xFF] + ^ crc32_global_crc32Lookup[12][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[15][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = (const uint8_t*)current; + // remaining 1 to 63 bytes (standard algorithm) + while (length-- != 0) { + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +uint32_t crc32_fast(const void* data, + size_t length, + const uint32_t previousCrc32) +{ +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + return crc32_16bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) + return crc32_8bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) + return crc32_4bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) + return crc32_1byte(data, length, previousCrc32); +#else + return crc32_halfbyte(data, length, previousCrc32); +#endif +} + +/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, +/// lengthA)) +uint32_t crc32_combine(uint32_t crcA, uint32_t crcB, size_t lengthB) +{ + // based on Mark Adler's crc_combine from + // https://github.com/madler/pigz/blob/master/pigz.c + + // main idea: + // - if you have two equally-sized blocks A and B, + // then you can create a block C = A ^ B + // which has the property crc(C) = crc(A) ^ crc(B) + // - if you append length(B) zeros to A and call it A' (think of it as + // AAAA000) + // and prepend length(A) zeros to B and call it B' (think of it as + // 0000BBB) then exists a C' = A' ^ B' + // - remember: if you XOR something with zero, it remains unchanged: X ^ 0 = X + // - that means C' = A concat B so that crc(A concat B) = crc(C') = crc(A') ^ + // crc(B') + // - the trick is to compute crc(A') based on crc(A) + // and crc(B') based on crc(B) + // - since B' starts with many zeros, the crc of those initial zeros is still + // zero + // - that means crc(B') = crc(B) + // - unfortunately the trailing zeros of A' change the crc, so usually crc(A') + // != crc(A) + // - the following code is a fast algorithm to compute crc(A') + // - starting with crc(A) and appending length(B) zeros, needing just + // log2(length(B)) iterations + // - the details are explained by the original author at + // https://stackoverflow.com/questions/23122312/crc-calculation-of-a-mostly-static-data-stream/23126768 + // + // notes: + // - I squeezed everything into one function to keep global namespace clean + // (original code two helper functions) + // - most original comments are still in place, I added comments where these + // helper functions where made inline code + // - performance-wise there isn't any differenze to the original zlib/pigz + // code + + // degenerated case + if (lengthB == 0) + return crcA; + + /// CRC32 => 32 bits + // const uint32_t CrcBits = 32; + + uint32_t odd[32]; // odd-power-of-two zeros operator + uint32_t even[32]; // even-power-of-two zeros operator + + // put operator for one zero bit in odd + odd[0] = crc32_global_polynomial; // CRC-32 polynomial + for (int i = 1; i < (int)32; i++) + odd[i] = 1 << (i - 1); + + // put operator for two zero bits in even + // same as gf2_matrix_square(even, odd); + for (int i = 0; i < (int)32; i++) { + uint32_t vec = odd[i]; + even[i] = 0; + for (int j = 0; vec != 0; j++, vec >>= 1) + if (vec & 1) + even[i] ^= odd[j]; + } + // put operator for four zero bits in odd + // same as gf2_matrix_square(odd, even); + for (int i = 0; i < (int)32; i++) { + uint32_t vec = even[i]; + odd[i] = 0; + for (int j = 0; vec != 0; j++, vec >>= 1) + if (vec & 1) + odd[i] ^= even[j]; + } + + // the following loop becomes much shorter if I keep swapping even and odd + uint32_t* a = even; + uint32_t* b = odd; + // apply secondLength zeros to firstCrc32 + for (; lengthB > 0; lengthB >>= 1) { + // same as gf2_matrix_square(a, b); + for (int i = 0; i < (int)32; i++) { + uint32_t vec = b[i]; + a[i] = 0; + for (int j = 0; vec != 0; j++, vec >>= 1) + if (vec & 1) + a[i] ^= b[j]; + } + + // apply zeros operator for this bit + if (lengthB & 1) { + // same as firstCrc32 = gf2_matrix_times(a, firstCrc32); + uint32_t sum = 0; + for (int i = 0; crcA != 0; i++, crcA >>= 1) + if (crcA & 1) + sum ^= a[i]; + crcA = sum; + } + + // switch even and odd + uint32_t* t = a; + a = b; + b = t; + } + + // return combined crc + return crcA ^ crcB; +} diff --git a/source/crc32.cpp b/source/crc32.cpp new file mode 100644 index 0000000..56c0dbd --- /dev/null +++ b/source/crc32.cpp @@ -0,0 +1,688 @@ +// ////////////////////////////////////////////////////////// +// crc32.cpp +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +// if running on an embedded system, you might consider shrinking the +// big crc32_global_crc32Lookup table: +// - crc32_bitwise doesn't need it at all +// - crc32_bitwise_banch doesn't need it at all +// - crc32_halfbyte has its own small lookup table +// - crc32_1byte needs only crc32_global_crc32Lookup[0] +// - crc32_4bytes needs only crc32_global_crc32Lookup[0..3] +// - crc32_8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_4x8bytes needs only crc32_global_crc32Lookup[0..7] +// - crc32_16bytes needs all of crc32_global_crc32Lookup + +#include "crc32/crc32.hpp" + +/// compute CRC32 (bitwise algorithm) +uint32_t crc32::crc32_bitwise(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_bitwise(data, length, previousCrc32); +} + +/// compute CRC32 (bitwise algorithm with branching) +uint32_t crc32::crc32_bitwise_branch(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_bitwise_branch(data, length, previousCrc32); +} + +/// compute CRC32 (half-byte algorithm) +uint32_t crc32::crc32_halfbyte(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_halfbyte(data, length, previousCrc32); +} + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +uint32_t crc32::crc32_1byte(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_1byte(data, length, previousCrc32); +} +#endif + +/// compute CRC32 (byte algorithm) without lookup tables +uint32_t crc32::crc32_1byte_tableless(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_1byte_tableless(data, length, previousCrc32); +} + +/// compute CRC32 (byte algorithm) without lookup tables +uint32_t crc32::crc32_1byte_tableless2(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_1byte_tableless2(data, length, previousCrc32); +} + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +uint32_t crc32::crc32_4bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_4bytes(data, length, previousCrc32); +} +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +uint32_t crc32::crc32_8bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_8bytes(data, length, previousCrc32); +} + +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +uint32_t crc32::crc32_4x8bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_4x8bytes(data, length, previousCrc32); +} +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +uint32_t crc32::crc32_16bytes(const void* data, + size_t length, + const uint32_t previousCrc32) +{ + return ::crc32_16bytes(data, length, previousCrc32); +} + +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +uint32_t crc32::crc32_16bytes_prefetch(const void* data, + size_t length, + const uint32_t previousCrc32, + size_t prefetchAhead) +{ + return ::crc32_16bytes_prefetch(data, length, previousCrc32, prefetchAhead); +} +#endif + +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +uint32_t crc32::crc32_fast(const void* data, + size_t length, + const uint32_t previousCrc32) +{ +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + return crc32_16bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) + return crc32_8bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) + return crc32_4bytes(data, length, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) + return crc32_1byte(data, length, previousCrc32); +#else + return crc32::crc32_halfbyte(data, length, previousCrc32); +#endif +} + +/// merge two CRC32 such that result = crc32(dataB, lengthB, crc32(dataA, +/// lengthA)) +uint32_t crc32::crc32_combine(uint32_t crcA, uint32_t crcB, size_t lengthB) +{ + return ::crc32_combine(crcA, crcB, lengthB); +} + +/// compute CRC32 (bitwise algorithm) +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_bitwise(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_bitwise(const std::string& data, + const uint32_t previousCrc32) +#endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + while (length-- != 0) { + crc ^= *current++; + + for (int j = 0; j < 8; j++) { + // branch-free + crc = (crc >> 1) ^ (-int32_t(crc & 1) & crc32_global_polynomial); + } + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (bitwise algorithm with branching) +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_bitwise_branch(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_bitwise_branch(const std::string& data, + const uint32_t previousCrc32) +#endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + while (length-- != 0) { + crc ^= *current++; + + for (int j = 0; j < 8; j++) { + // branching, much slower + if (crc & 1) { + crc = (crc >> 1) ^ crc32_global_polynomial; + } else { + crc = crc >> 1; + } + } + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (half-byte algorithm) +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_halfbyte(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_halfbyte(const std::string& data, + const uint32_t previousCrc32) +#endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + /// look-up table for half-byte, same as crc32Lookup[0][16*i] + static const uint32_t _crc32_global_crc32Lookup16[16] = {0x00000000, + 0x1DB71064, + 0x3B6E20C8, + 0x26D930AC, + 0x76DC4190, + 0x6B6B51F4, + 0x4DB26158, + 0x5005713C, + 0xEDB88320, + 0xF00F9344, + 0xD6D6A3E8, + 0xCB61B38C, + 0x9B64C2B0, + 0x86D3D2D4, + 0xA00AE278, + 0xBDBDF21C}; + + while (length-- != 0) { + crc = _crc32_global_crc32Lookup16[(crc ^ *current) & 0x0F] ^ (crc >> 4); + crc = _crc32_global_crc32Lookup16[(crc ^ (*current >> 4)) & 0x0F] + ^ (crc >> 4); + current++; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE +/// compute CRC32 (standard algorithm) +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_1byte(std::string_view data, + const uint32_t previousCrc32) +# else +std::uint32_t crc32::crc32_1byte(const std::string& data, + const uint32_t previousCrc32) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + while (length-- != 0) + crc = (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *current++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +/// compute CRC32 (byte algorithm) without lookup tables +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_1byte_tableless(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_1byte_tableless(const std::string& data, + const uint32_t previousCrc32) +#endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + while (length-- != 0) { + uint8_t s = uint8_t(crc) ^ *current++; + + // Hagai Gold made me aware of this table-less algorithm and send me code + + // polynomial 0xEDB88320 can be written in binary as + // 11101101101110001000001100100000b reverse the bits (or just assume bit 0 + // is the first one) and we have bits set at position 0, 1, 2, 4, 5, 7, 8, + // 10, 11, 12, 16, 22, 23, 26 + // => those are the shift offsets: + // crc = (crc >> 8) ^ + // t ^ + // (t >> 1) ^ (t >> 2) ^ (t >> 4) ^ (t >> 5) ^ // == y + // (t >> 7) ^ (t >> 8) ^ (t >> 10) ^ (t >> 11) ^ // == y >> 6 + // (t >> 12) ^ (t >> 16) ^ // == z + // (t >> 22) ^ (t >> 26) ^ // == z >> 10 + // (t >> 23); + + // the fastest I can come up with: + uint32_t low = (s ^ (s << 6)) & 0xFF; + uint32_t a = (low * ((1 << 23) + (1 << 14) + (1 << 2))); + crc = (crc >> 8) ^ (low * ((1 << 24) + (1 << 16) + (1 << 8))) ^ a ^ (a >> 1) + ^ (low * ((1 << 20) + (1 << 12))) ^ (low << 19) ^ (low << 17) + ^ (low >> 2); + + // Hagai's code: + /*uint32_t t = (s ^ (s << 6)) << 24; + + // some temporaries to optimize XOR + uint32_t x = (t >> 1) ^ (t >> 2); + uint32_t y = x ^ (x >> 3); + uint32_t z = (t >> 12) ^ (t >> 16); + + crc = (crc >> 8) ^ + t ^ (t >> 23) ^ + y ^ (y >> 6) ^ + z ^ (z >> 10);*/ + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (byte algorithm) without lookup tables +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_1byte_tableless2(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_1byte_tableless2(const std::string& data, + const uint32_t previousCrc32) +#endif +{ + int32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + while (length-- != 0) { + crc = crc ^ *current++; + + uint32_t c = + (((crc << 31) >> 31) + & ((crc32_global_polynomial >> 7) ^ (crc32_global_polynomial >> 1))) + ^ (((crc << 30) >> 31) + & ((crc32_global_polynomial >> 6) ^ crc32_global_polynomial)) + ^ (((crc << 29) >> 31) & (crc32_global_polynomial >> 5)) + ^ (((crc << 28) >> 31) & (crc32_global_polynomial >> 4)) + ^ (((crc << 27) >> 31) & (crc32_global_polynomial >> 3)) + ^ (((crc << 26) >> 31) & (crc32_global_polynomial >> 2)) + ^ (((crc << 25) >> 31) & (crc32_global_polynomial >> 1)) + ^ (((crc << 24) >> 31) & crc32_global_polynomial); + + crc = (static_cast(crc) >> 8) + ^ c; // convert to unsigned integer before right shift + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 +/// compute CRC32 (Slicing-by-4 algorithm) +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_4bytes(std::string_view data, + const uint32_t previousCrc32) +# else +std::uint32_t crc32::crc32_4bytes(const std::string& data, + const uint32_t previousCrc32) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + // process four bytes at once (Slicing-by-4) + while (length >= 4) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + crc = crc32_global_crc32Lookup[0][one & 0xFF] + ^ crc32_global_crc32Lookup[1][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + crc = crc32_global_crc32Lookup[0][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][one & 0xFF]; +# endif + + length -= 4; + } + + const uint8_t* currentChar = reinterpret_cast(current); + // remaining 1 to 3 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 +/// compute CRC32 (Slicing-by-8 algorithm) +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_8bytes(std::string_view data, + const uint32_t previousCrc32) +# else +std::uint32_t crc32::crc32_8bytes(const std::string& data, + const uint32_t previousCrc32) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint32_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + // process eight bytes at once (Slicing-by-8) + while (length >= 8) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][two & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][one & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][two & 0xFF] + ^ crc32_global_crc32Lookup[4][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][one & 0xFF]; +# endif + + length -= 8; + } + + const uint8_t* currentChar = reinterpret_cast(current); + // remaining 1 to 7 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (Slicing-by-8 algorithm), unroll inner loop 4 times +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_4x8bytes(std::string_view data, + const uint32_t previousCrc32) +# else +std::uint32_t crc32::crc32_4x8bytes(const std::string& data, + const uint32_t previousCrc32) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + // enabling optimization (at least -O2) automatically unrolls the inner + // for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 8 * Unroll; + + // process 4x eight bytes at once (Slicing-by-8) + while (length >= BytesAtOnce) { + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][two & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][one & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + crc = crc32_global_crc32Lookup[0][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][two & 0xFF] + ^ crc32_global_crc32Lookup[4][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = reinterpret_cast(current); + // remaining 1 to 31 bytes (standard algorithm) + while (length-- != 0) + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +/// compute CRC32 (Slicing-by-16 algorithm) +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_16bytes(std::string_view data, + const uint32_t previousCrc32) +# else +std::uint32_t crc32::crc32_16bytes(const std::string& data, + const uint32_t previousCrc32) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + // enabling optimization (at least -O2) automatically unrolls the inner + // for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 16 * Unroll; + + while (length >= BytesAtOnce) { + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][four & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][three & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[8][two & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[11][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[12][one & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[15][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][four & 0xFF] + ^ crc32_global_crc32Lookup[4][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][three & 0xFF] + ^ crc32_global_crc32Lookup[8][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[11][two & 0xFF] + ^ crc32_global_crc32Lookup[12][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[15][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = reinterpret_cast(current); + // remaining 1 to 63 bytes (standard algorithm) + while (length-- != 0) { + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} + +/// compute CRC32 (Slicing-by-16 algorithm, prefetch upcoming data blocks) +# if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_16bytes_prefetch(std::string_view data, + const uint32_t previousCrc32, + size_t prefetchAhead) +# else +std::uint32_t crc32::crc32_16bytes_prefetch(const std::string& data, + const uint32_t previousCrc32, + size_t prefetchAhead) +# endif +{ + uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF + const uint8_t* current = reinterpret_cast(data.data()); + uint64_t length = data.length(); + + // CRC code is identical to crc32_16bytes (including unrolling), only added + // prefetching 256 bytes look-ahead seems to be the sweet spot on Core i7 CPUs + + // enabling optimization (at least -O2) automatically unrolls the for-loop + const size_t Unroll = 4; + const size_t BytesAtOnce = 16 * Unroll; + + while (length >= BytesAtOnce + prefetchAhead) { + PREFETCH((reinterpret_cast(current)) + prefetchAhead); + + for (size_t unrolling = 0; unrolling < Unroll; unrolling++) { +# if __BYTE_ORDER == __BIG_ENDIAN + uint32_t one = *current++ ^ swap(crc); + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][four & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[3][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[4][three & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[7][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[8][two & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[11][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[12][one & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[15][(one >> 24) & 0xFF]; +# else + uint32_t one = *current++ ^ crc; + uint32_t two = *current++; + uint32_t three = *current++; + uint32_t four = *current++; + crc = crc32_global_crc32Lookup[0][(four >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[1][(four >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[2][(four >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[3][four & 0xFF] + ^ crc32_global_crc32Lookup[4][(three >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[5][(three >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[6][(three >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[7][three & 0xFF] + ^ crc32_global_crc32Lookup[8][(two >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[9][(two >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[10][(two >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[11][two & 0xFF] + ^ crc32_global_crc32Lookup[12][(one >> 24) & 0xFF] + ^ crc32_global_crc32Lookup[13][(one >> 16) & 0xFF] + ^ crc32_global_crc32Lookup[14][(one >> 8) & 0xFF] + ^ crc32_global_crc32Lookup[15][one & 0xFF]; +# endif + } + + length -= BytesAtOnce; + } + + const uint8_t* currentChar = reinterpret_cast(current); + // remaining 1 to 63 bytes (standard algorithm) + while (length-- != 0) { + crc = + (crc >> 8) ^ crc32_global_crc32Lookup[0][(crc & 0xFF) ^ *currentChar++]; + } + + return ~crc; // same as crc ^ 0xFFFFFFFF +} +#endif + +/// compute CRC32 using the fastest algorithm for large datasets on modern CPUs +#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L) +std::uint32_t crc32::crc32_fast(std::string_view data, + const uint32_t previousCrc32) +#else +std::uint32_t crc32::crc32_fast(const std::string& data, + const uint32_t previousCrc32) +#endif +{ +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + return crc32_16bytes(data, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) + return crc32_8bytes(data, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) + return crc32_4bytes(data, previousCrc32); +#elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) + return crc32_1byte(data, previousCrc32); +#else + return crc32::crc32_halfbyte(data, previousCrc32); +#endif +} diff --git a/source/crc32_var.c b/source/crc32_var.c new file mode 100644 index 0000000..c894379 --- /dev/null +++ b/source/crc32_var.c @@ -0,0 +1,840 @@ +// ////////////////////////////////////////////////////////// +// crc32_var.c +// Copyright (c) 2021-2021 Stephan Brumme. All rights reserved. +// Slicing-by-16 contributed by Bulat Ziganshin +// Tableless bytewise CRC contributed by Hagai Gold +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include "crc32/crc32_var.h" + +// ////////////////////////////////////////////////////////// +// constants + +/* CRC-32C (iSCSI) polynomial in reversed bit order. */ +// const uint32_t crc32_global_polynomial = 0x82F63B78; // you need to update +// crc32_global_crc32Lookup if you change this value + +/* CRC-32 (Ethernet, ZIP, etc.) polynomial in reversed bit order. */ +const uint32_t crc32_global_polynomial = + 0xEDB88320; // you need to update crc32_global_crc32Lookup if you change + // this value + +#ifndef NO_LUT +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +const uint32_t crc32_global_crc32Lookup[16][256] = { +# elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) +const uint32_t crc32_global_crc32Lookup[8][256] = { +# elif defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) +const uint32_t crc32_global_crc32Lookup[4][256] = { +# elif defined(CRC32_USE_LOOKUP_TABLE_BYTE) +const uint32_t crc32_global_crc32Lookup[1][256] = { +# endif + /// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf + //// http://sourceforge.net/projects/slicing-by-8/ + /* + // Full function + uint32_t crc = Crc32Lookup[0][0x80] = Polynomial; + for (unsigned int next = 0x40; next != 0; next >>= 1) { + crc = (crc >> 1) ^ ((crc & 1) * Polynomial); + Crc32Lookup[0][next] = crc; + } + + for (unsigned int powerOfTwo = 2; powerOfTwo <= 0x80; powerOfTwo <<= 1) { + uint32_t crcExtraBit = Crc32Lookup[0][powerOfTwo]; + for (unsigned int i = 1; i < powerOfTwo; i++) + Crc32Lookup[0][i + powerOfTwo] = Crc32Lookup[0][i] ^ crcExtraBit; + } + + for (unsigned int i = 0; i <= 0xFF; i++) { + // for Slicing-by-4 and Slicing-by-8 + Crc32Lookup[1][i] = + (Crc32Lookup[0][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[0][i] & 0xFF]; + Crc32Lookup[2][i] = + (Crc32Lookup[1][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[1][i] & 0xFF]; + Crc32Lookup[3][i] = + (Crc32Lookup[2][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[2][i] & 0xFF]; + // only Slicing-by-8 + Crc32Lookup[4][i] = + (Crc32Lookup[3][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[3][i] & 0xFF]; + Crc32Lookup[5][i] = + (Crc32Lookup[4][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[4][i] & 0xFF]; + Crc32Lookup[6][i] = + (Crc32Lookup[5][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[5][i] & 0xFF]; + Crc32Lookup[7][i] = + (Crc32Lookup[6][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[6][i] & 0xFF]; + + // only Slicing-by-16 + Crc32Lookup[8][i] = + (Crc32Lookup[7][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[7][i] & 0xFF]; + Crc32Lookup[9][i] = + (Crc32Lookup[8][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[8][i] & 0xFF]; + Crc32Lookup[10][i] = + (Crc32Lookup[9][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[9][i] & 0xFF]; + Crc32Lookup[11][i] = + (Crc32Lookup[10][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[10][i] & + 0xFF]; Crc32Lookup[12][i] = (Crc32Lookup[11][i] >> 8) ^ + Crc32Lookup[0][Crc32Lookup[11][i] & 0xFF]; Crc32Lookup[13][i] = + (Crc32Lookup[12][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[12][i] & + 0xFF]; Crc32Lookup[14][i] = (Crc32Lookup[13][i] >> 8) ^ + Crc32Lookup[0][Crc32Lookup[13][i] & 0xFF]; Crc32Lookup[15][i] = + (Crc32Lookup[14][i] >> 8) ^ Crc32Lookup[0][Crc32Lookup[14][i] & + 0xFF]; + } + */ + { + // note: the first number of every second row corresponds to the + // half-byte look-up table ! + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, + } + +# if defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) \ + || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) \ + || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) + // beyond this point only relevant for Slicing-by-4, Slicing-by-8 and + // Slicing-by-16 + , + { + 0x00000000, 0x191B3141, 0x32366282, 0x2B2D53C3, 0x646CC504, 0x7D77F445, + 0x565AA786, 0x4F4196C7, 0xC8D98A08, 0xD1C2BB49, 0xFAEFE88A, 0xE3F4D9CB, + 0xACB54F0C, 0xB5AE7E4D, 0x9E832D8E, 0x87981CCF, 0x4AC21251, 0x53D92310, + 0x78F470D3, 0x61EF4192, 0x2EAED755, 0x37B5E614, 0x1C98B5D7, 0x05838496, + 0x821B9859, 0x9B00A918, 0xB02DFADB, 0xA936CB9A, 0xE6775D5D, 0xFF6C6C1C, + 0xD4413FDF, 0xCD5A0E9E, 0x958424A2, 0x8C9F15E3, 0xA7B24620, 0xBEA97761, + 0xF1E8E1A6, 0xE8F3D0E7, 0xC3DE8324, 0xDAC5B265, 0x5D5DAEAA, 0x44469FEB, + 0x6F6BCC28, 0x7670FD69, 0x39316BAE, 0x202A5AEF, 0x0B07092C, 0x121C386D, + 0xDF4636F3, 0xC65D07B2, 0xED705471, 0xF46B6530, 0xBB2AF3F7, 0xA231C2B6, + 0x891C9175, 0x9007A034, 0x179FBCFB, 0x0E848DBA, 0x25A9DE79, 0x3CB2EF38, + 0x73F379FF, 0x6AE848BE, 0x41C51B7D, 0x58DE2A3C, 0xF0794F05, 0xE9627E44, + 0xC24F2D87, 0xDB541CC6, 0x94158A01, 0x8D0EBB40, 0xA623E883, 0xBF38D9C2, + 0x38A0C50D, 0x21BBF44C, 0x0A96A78F, 0x138D96CE, 0x5CCC0009, 0x45D73148, + 0x6EFA628B, 0x77E153CA, 0xBABB5D54, 0xA3A06C15, 0x888D3FD6, 0x91960E97, + 0xDED79850, 0xC7CCA911, 0xECE1FAD2, 0xF5FACB93, 0x7262D75C, 0x6B79E61D, + 0x4054B5DE, 0x594F849F, 0x160E1258, 0x0F152319, 0x243870DA, 0x3D23419B, + 0x65FD6BA7, 0x7CE65AE6, 0x57CB0925, 0x4ED03864, 0x0191AEA3, 0x188A9FE2, + 0x33A7CC21, 0x2ABCFD60, 0xAD24E1AF, 0xB43FD0EE, 0x9F12832D, 0x8609B26C, + 0xC94824AB, 0xD05315EA, 0xFB7E4629, 0xE2657768, 0x2F3F79F6, 0x362448B7, + 0x1D091B74, 0x04122A35, 0x4B53BCF2, 0x52488DB3, 0x7965DE70, 0x607EEF31, + 0xE7E6F3FE, 0xFEFDC2BF, 0xD5D0917C, 0xCCCBA03D, 0x838A36FA, 0x9A9107BB, + 0xB1BC5478, 0xA8A76539, 0x3B83984B, 0x2298A90A, 0x09B5FAC9, 0x10AECB88, + 0x5FEF5D4F, 0x46F46C0E, 0x6DD93FCD, 0x74C20E8C, 0xF35A1243, 0xEA412302, + 0xC16C70C1, 0xD8774180, 0x9736D747, 0x8E2DE606, 0xA500B5C5, 0xBC1B8484, + 0x71418A1A, 0x685ABB5B, 0x4377E898, 0x5A6CD9D9, 0x152D4F1E, 0x0C367E5F, + 0x271B2D9C, 0x3E001CDD, 0xB9980012, 0xA0833153, 0x8BAE6290, 0x92B553D1, + 0xDDF4C516, 0xC4EFF457, 0xEFC2A794, 0xF6D996D5, 0xAE07BCE9, 0xB71C8DA8, + 0x9C31DE6B, 0x852AEF2A, 0xCA6B79ED, 0xD37048AC, 0xF85D1B6F, 0xE1462A2E, + 0x66DE36E1, 0x7FC507A0, 0x54E85463, 0x4DF36522, 0x02B2F3E5, 0x1BA9C2A4, + 0x30849167, 0x299FA026, 0xE4C5AEB8, 0xFDDE9FF9, 0xD6F3CC3A, 0xCFE8FD7B, + 0x80A96BBC, 0x99B25AFD, 0xB29F093E, 0xAB84387F, 0x2C1C24B0, 0x350715F1, + 0x1E2A4632, 0x07317773, 0x4870E1B4, 0x516BD0F5, 0x7A468336, 0x635DB277, + 0xCBFAD74E, 0xD2E1E60F, 0xF9CCB5CC, 0xE0D7848D, 0xAF96124A, 0xB68D230B, + 0x9DA070C8, 0x84BB4189, 0x03235D46, 0x1A386C07, 0x31153FC4, 0x280E0E85, + 0x674F9842, 0x7E54A903, 0x5579FAC0, 0x4C62CB81, 0x8138C51F, 0x9823F45E, + 0xB30EA79D, 0xAA1596DC, 0xE554001B, 0xFC4F315A, 0xD7626299, 0xCE7953D8, + 0x49E14F17, 0x50FA7E56, 0x7BD72D95, 0x62CC1CD4, 0x2D8D8A13, 0x3496BB52, + 0x1FBBE891, 0x06A0D9D0, 0x5E7EF3EC, 0x4765C2AD, 0x6C48916E, 0x7553A02F, + 0x3A1236E8, 0x230907A9, 0x0824546A, 0x113F652B, 0x96A779E4, 0x8FBC48A5, + 0xA4911B66, 0xBD8A2A27, 0xF2CBBCE0, 0xEBD08DA1, 0xC0FDDE62, 0xD9E6EF23, + 0x14BCE1BD, 0x0DA7D0FC, 0x268A833F, 0x3F91B27E, 0x70D024B9, 0x69CB15F8, + 0x42E6463B, 0x5BFD777A, 0xDC656BB5, 0xC57E5AF4, 0xEE530937, 0xF7483876, + 0xB809AEB1, 0xA1129FF0, 0x8A3FCC33, 0x9324FD72, + }, + + { + 0x00000000, 0x01C26A37, 0x0384D46E, 0x0246BE59, 0x0709A8DC, 0x06CBC2EB, + 0x048D7CB2, 0x054F1685, 0x0E1351B8, 0x0FD13B8F, 0x0D9785D6, 0x0C55EFE1, + 0x091AF964, 0x08D89353, 0x0A9E2D0A, 0x0B5C473D, 0x1C26A370, 0x1DE4C947, + 0x1FA2771E, 0x1E601D29, 0x1B2F0BAC, 0x1AED619B, 0x18ABDFC2, 0x1969B5F5, + 0x1235F2C8, 0x13F798FF, 0x11B126A6, 0x10734C91, 0x153C5A14, 0x14FE3023, + 0x16B88E7A, 0x177AE44D, 0x384D46E0, 0x398F2CD7, 0x3BC9928E, 0x3A0BF8B9, + 0x3F44EE3C, 0x3E86840B, 0x3CC03A52, 0x3D025065, 0x365E1758, 0x379C7D6F, + 0x35DAC336, 0x3418A901, 0x3157BF84, 0x3095D5B3, 0x32D36BEA, 0x331101DD, + 0x246BE590, 0x25A98FA7, 0x27EF31FE, 0x262D5BC9, 0x23624D4C, 0x22A0277B, + 0x20E69922, 0x2124F315, 0x2A78B428, 0x2BBADE1F, 0x29FC6046, 0x283E0A71, + 0x2D711CF4, 0x2CB376C3, 0x2EF5C89A, 0x2F37A2AD, 0x709A8DC0, 0x7158E7F7, + 0x731E59AE, 0x72DC3399, 0x7793251C, 0x76514F2B, 0x7417F172, 0x75D59B45, + 0x7E89DC78, 0x7F4BB64F, 0x7D0D0816, 0x7CCF6221, 0x798074A4, 0x78421E93, + 0x7A04A0CA, 0x7BC6CAFD, 0x6CBC2EB0, 0x6D7E4487, 0x6F38FADE, 0x6EFA90E9, + 0x6BB5866C, 0x6A77EC5B, 0x68315202, 0x69F33835, 0x62AF7F08, 0x636D153F, + 0x612BAB66, 0x60E9C151, 0x65A6D7D4, 0x6464BDE3, 0x662203BA, 0x67E0698D, + 0x48D7CB20, 0x4915A117, 0x4B531F4E, 0x4A917579, 0x4FDE63FC, 0x4E1C09CB, + 0x4C5AB792, 0x4D98DDA5, 0x46C49A98, 0x4706F0AF, 0x45404EF6, 0x448224C1, + 0x41CD3244, 0x400F5873, 0x4249E62A, 0x438B8C1D, 0x54F16850, 0x55330267, + 0x5775BC3E, 0x56B7D609, 0x53F8C08C, 0x523AAABB, 0x507C14E2, 0x51BE7ED5, + 0x5AE239E8, 0x5B2053DF, 0x5966ED86, 0x58A487B1, 0x5DEB9134, 0x5C29FB03, + 0x5E6F455A, 0x5FAD2F6D, 0xE1351B80, 0xE0F771B7, 0xE2B1CFEE, 0xE373A5D9, + 0xE63CB35C, 0xE7FED96B, 0xE5B86732, 0xE47A0D05, 0xEF264A38, 0xEEE4200F, + 0xECA29E56, 0xED60F461, 0xE82FE2E4, 0xE9ED88D3, 0xEBAB368A, 0xEA695CBD, + 0xFD13B8F0, 0xFCD1D2C7, 0xFE976C9E, 0xFF5506A9, 0xFA1A102C, 0xFBD87A1B, + 0xF99EC442, 0xF85CAE75, 0xF300E948, 0xF2C2837F, 0xF0843D26, 0xF1465711, + 0xF4094194, 0xF5CB2BA3, 0xF78D95FA, 0xF64FFFCD, 0xD9785D60, 0xD8BA3757, + 0xDAFC890E, 0xDB3EE339, 0xDE71F5BC, 0xDFB39F8B, 0xDDF521D2, 0xDC374BE5, + 0xD76B0CD8, 0xD6A966EF, 0xD4EFD8B6, 0xD52DB281, 0xD062A404, 0xD1A0CE33, + 0xD3E6706A, 0xD2241A5D, 0xC55EFE10, 0xC49C9427, 0xC6DA2A7E, 0xC7184049, + 0xC25756CC, 0xC3953CFB, 0xC1D382A2, 0xC011E895, 0xCB4DAFA8, 0xCA8FC59F, + 0xC8C97BC6, 0xC90B11F1, 0xCC440774, 0xCD866D43, 0xCFC0D31A, 0xCE02B92D, + 0x91AF9640, 0x906DFC77, 0x922B422E, 0x93E92819, 0x96A63E9C, 0x976454AB, + 0x9522EAF2, 0x94E080C5, 0x9FBCC7F8, 0x9E7EADCF, 0x9C381396, 0x9DFA79A1, + 0x98B56F24, 0x99770513, 0x9B31BB4A, 0x9AF3D17D, 0x8D893530, 0x8C4B5F07, + 0x8E0DE15E, 0x8FCF8B69, 0x8A809DEC, 0x8B42F7DB, 0x89044982, 0x88C623B5, + 0x839A6488, 0x82580EBF, 0x801EB0E6, 0x81DCDAD1, 0x8493CC54, 0x8551A663, + 0x8717183A, 0x86D5720D, 0xA9E2D0A0, 0xA820BA97, 0xAA6604CE, 0xABA46EF9, + 0xAEEB787C, 0xAF29124B, 0xAD6FAC12, 0xACADC625, 0xA7F18118, 0xA633EB2F, + 0xA4755576, 0xA5B73F41, 0xA0F829C4, 0xA13A43F3, 0xA37CFDAA, 0xA2BE979D, + 0xB5C473D0, 0xB40619E7, 0xB640A7BE, 0xB782CD89, 0xB2CDDB0C, 0xB30FB13B, + 0xB1490F62, 0xB08B6555, 0xBBD72268, 0xBA15485F, 0xB853F606, 0xB9919C31, + 0xBCDE8AB4, 0xBD1CE083, 0xBF5A5EDA, 0xBE9834ED, + }, + + { + 0x00000000, 0xB8BC6765, 0xAA09C88B, 0x12B5AFEE, 0x8F629757, 0x37DEF032, + 0x256B5FDC, 0x9DD738B9, 0xC5B428EF, 0x7D084F8A, 0x6FBDE064, 0xD7018701, + 0x4AD6BFB8, 0xF26AD8DD, 0xE0DF7733, 0x58631056, 0x5019579F, 0xE8A530FA, + 0xFA109F14, 0x42ACF871, 0xDF7BC0C8, 0x67C7A7AD, 0x75720843, 0xCDCE6F26, + 0x95AD7F70, 0x2D111815, 0x3FA4B7FB, 0x8718D09E, 0x1ACFE827, 0xA2738F42, + 0xB0C620AC, 0x087A47C9, 0xA032AF3E, 0x188EC85B, 0x0A3B67B5, 0xB28700D0, + 0x2F503869, 0x97EC5F0C, 0x8559F0E2, 0x3DE59787, 0x658687D1, 0xDD3AE0B4, + 0xCF8F4F5A, 0x7733283F, 0xEAE41086, 0x525877E3, 0x40EDD80D, 0xF851BF68, + 0xF02BF8A1, 0x48979FC4, 0x5A22302A, 0xE29E574F, 0x7F496FF6, 0xC7F50893, + 0xD540A77D, 0x6DFCC018, 0x359FD04E, 0x8D23B72B, 0x9F9618C5, 0x272A7FA0, + 0xBAFD4719, 0x0241207C, 0x10F48F92, 0xA848E8F7, 0x9B14583D, 0x23A83F58, + 0x311D90B6, 0x89A1F7D3, 0x1476CF6A, 0xACCAA80F, 0xBE7F07E1, 0x06C36084, + 0x5EA070D2, 0xE61C17B7, 0xF4A9B859, 0x4C15DF3C, 0xD1C2E785, 0x697E80E0, + 0x7BCB2F0E, 0xC377486B, 0xCB0D0FA2, 0x73B168C7, 0x6104C729, 0xD9B8A04C, + 0x446F98F5, 0xFCD3FF90, 0xEE66507E, 0x56DA371B, 0x0EB9274D, 0xB6054028, + 0xA4B0EFC6, 0x1C0C88A3, 0x81DBB01A, 0x3967D77F, 0x2BD27891, 0x936E1FF4, + 0x3B26F703, 0x839A9066, 0x912F3F88, 0x299358ED, 0xB4446054, 0x0CF80731, + 0x1E4DA8DF, 0xA6F1CFBA, 0xFE92DFEC, 0x462EB889, 0x549B1767, 0xEC277002, + 0x71F048BB, 0xC94C2FDE, 0xDBF98030, 0x6345E755, 0x6B3FA09C, 0xD383C7F9, + 0xC1366817, 0x798A0F72, 0xE45D37CB, 0x5CE150AE, 0x4E54FF40, 0xF6E89825, + 0xAE8B8873, 0x1637EF16, 0x048240F8, 0xBC3E279D, 0x21E91F24, 0x99557841, + 0x8BE0D7AF, 0x335CB0CA, 0xED59B63B, 0x55E5D15E, 0x47507EB0, 0xFFEC19D5, + 0x623B216C, 0xDA874609, 0xC832E9E7, 0x708E8E82, 0x28ED9ED4, 0x9051F9B1, + 0x82E4565F, 0x3A58313A, 0xA78F0983, 0x1F336EE6, 0x0D86C108, 0xB53AA66D, + 0xBD40E1A4, 0x05FC86C1, 0x1749292F, 0xAFF54E4A, 0x322276F3, 0x8A9E1196, + 0x982BBE78, 0x2097D91D, 0x78F4C94B, 0xC048AE2E, 0xD2FD01C0, 0x6A4166A5, + 0xF7965E1C, 0x4F2A3979, 0x5D9F9697, 0xE523F1F2, 0x4D6B1905, 0xF5D77E60, + 0xE762D18E, 0x5FDEB6EB, 0xC2098E52, 0x7AB5E937, 0x680046D9, 0xD0BC21BC, + 0x88DF31EA, 0x3063568F, 0x22D6F961, 0x9A6A9E04, 0x07BDA6BD, 0xBF01C1D8, + 0xADB46E36, 0x15080953, 0x1D724E9A, 0xA5CE29FF, 0xB77B8611, 0x0FC7E174, + 0x9210D9CD, 0x2AACBEA8, 0x38191146, 0x80A57623, 0xD8C66675, 0x607A0110, + 0x72CFAEFE, 0xCA73C99B, 0x57A4F122, 0xEF189647, 0xFDAD39A9, 0x45115ECC, + 0x764DEE06, 0xCEF18963, 0xDC44268D, 0x64F841E8, 0xF92F7951, 0x41931E34, + 0x5326B1DA, 0xEB9AD6BF, 0xB3F9C6E9, 0x0B45A18C, 0x19F00E62, 0xA14C6907, + 0x3C9B51BE, 0x842736DB, 0x96929935, 0x2E2EFE50, 0x2654B999, 0x9EE8DEFC, + 0x8C5D7112, 0x34E11677, 0xA9362ECE, 0x118A49AB, 0x033FE645, 0xBB838120, + 0xE3E09176, 0x5B5CF613, 0x49E959FD, 0xF1553E98, 0x6C820621, 0xD43E6144, + 0xC68BCEAA, 0x7E37A9CF, 0xD67F4138, 0x6EC3265D, 0x7C7689B3, 0xC4CAEED6, + 0x591DD66F, 0xE1A1B10A, 0xF3141EE4, 0x4BA87981, 0x13CB69D7, 0xAB770EB2, + 0xB9C2A15C, 0x017EC639, 0x9CA9FE80, 0x241599E5, 0x36A0360B, 0x8E1C516E, + 0x866616A7, 0x3EDA71C2, 0x2C6FDE2C, 0x94D3B949, 0x090481F0, 0xB1B8E695, + 0xA30D497B, 0x1BB12E1E, 0x43D23E48, 0xFB6E592D, 0xE9DBF6C3, 0x516791A6, + 0xCCB0A91F, 0x740CCE7A, 0x66B96194, 0xDE0506F1, + } +# endif // defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_4) || + // defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) || + // defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) +# if defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_8) \ + || defined(CRC32_USE_LOOKUP_TABLE_SLICING_BY_16) + // beyond this point only relevant for Slicing-by-8 and Slicing-by-16 + , + { + 0x00000000, 0x3D6029B0, 0x7AC05360, 0x47A07AD0, 0xF580A6C0, 0xC8E08F70, + 0x8F40F5A0, 0xB220DC10, 0x30704BC1, 0x0D106271, 0x4AB018A1, 0x77D03111, + 0xC5F0ED01, 0xF890C4B1, 0xBF30BE61, 0x825097D1, 0x60E09782, 0x5D80BE32, + 0x1A20C4E2, 0x2740ED52, 0x95603142, 0xA80018F2, 0xEFA06222, 0xD2C04B92, + 0x5090DC43, 0x6DF0F5F3, 0x2A508F23, 0x1730A693, 0xA5107A83, 0x98705333, + 0xDFD029E3, 0xE2B00053, 0xC1C12F04, 0xFCA106B4, 0xBB017C64, 0x866155D4, + 0x344189C4, 0x0921A074, 0x4E81DAA4, 0x73E1F314, 0xF1B164C5, 0xCCD14D75, + 0x8B7137A5, 0xB6111E15, 0x0431C205, 0x3951EBB5, 0x7EF19165, 0x4391B8D5, + 0xA121B886, 0x9C419136, 0xDBE1EBE6, 0xE681C256, 0x54A11E46, 0x69C137F6, + 0x2E614D26, 0x13016496, 0x9151F347, 0xAC31DAF7, 0xEB91A027, 0xD6F18997, + 0x64D15587, 0x59B17C37, 0x1E1106E7, 0x23712F57, 0x58F35849, 0x659371F9, + 0x22330B29, 0x1F532299, 0xAD73FE89, 0x9013D739, 0xD7B3ADE9, 0xEAD38459, + 0x68831388, 0x55E33A38, 0x124340E8, 0x2F236958, 0x9D03B548, 0xA0639CF8, + 0xE7C3E628, 0xDAA3CF98, 0x3813CFCB, 0x0573E67B, 0x42D39CAB, 0x7FB3B51B, + 0xCD93690B, 0xF0F340BB, 0xB7533A6B, 0x8A3313DB, 0x0863840A, 0x3503ADBA, + 0x72A3D76A, 0x4FC3FEDA, 0xFDE322CA, 0xC0830B7A, 0x872371AA, 0xBA43581A, + 0x9932774D, 0xA4525EFD, 0xE3F2242D, 0xDE920D9D, 0x6CB2D18D, 0x51D2F83D, + 0x167282ED, 0x2B12AB5D, 0xA9423C8C, 0x9422153C, 0xD3826FEC, 0xEEE2465C, + 0x5CC29A4C, 0x61A2B3FC, 0x2602C92C, 0x1B62E09C, 0xF9D2E0CF, 0xC4B2C97F, + 0x8312B3AF, 0xBE729A1F, 0x0C52460F, 0x31326FBF, 0x7692156F, 0x4BF23CDF, + 0xC9A2AB0E, 0xF4C282BE, 0xB362F86E, 0x8E02D1DE, 0x3C220DCE, 0x0142247E, + 0x46E25EAE, 0x7B82771E, 0xB1E6B092, 0x8C869922, 0xCB26E3F2, 0xF646CA42, + 0x44661652, 0x79063FE2, 0x3EA64532, 0x03C66C82, 0x8196FB53, 0xBCF6D2E3, + 0xFB56A833, 0xC6368183, 0x74165D93, 0x49767423, 0x0ED60EF3, 0x33B62743, + 0xD1062710, 0xEC660EA0, 0xABC67470, 0x96A65DC0, 0x248681D0, 0x19E6A860, + 0x5E46D2B0, 0x6326FB00, 0xE1766CD1, 0xDC164561, 0x9BB63FB1, 0xA6D61601, + 0x14F6CA11, 0x2996E3A1, 0x6E369971, 0x5356B0C1, 0x70279F96, 0x4D47B626, + 0x0AE7CCF6, 0x3787E546, 0x85A73956, 0xB8C710E6, 0xFF676A36, 0xC2074386, + 0x4057D457, 0x7D37FDE7, 0x3A978737, 0x07F7AE87, 0xB5D77297, 0x88B75B27, + 0xCF1721F7, 0xF2770847, 0x10C70814, 0x2DA721A4, 0x6A075B74, 0x576772C4, + 0xE547AED4, 0xD8278764, 0x9F87FDB4, 0xA2E7D404, 0x20B743D5, 0x1DD76A65, + 0x5A7710B5, 0x67173905, 0xD537E515, 0xE857CCA5, 0xAFF7B675, 0x92979FC5, + 0xE915E8DB, 0xD475C16B, 0x93D5BBBB, 0xAEB5920B, 0x1C954E1B, 0x21F567AB, + 0x66551D7B, 0x5B3534CB, 0xD965A31A, 0xE4058AAA, 0xA3A5F07A, 0x9EC5D9CA, + 0x2CE505DA, 0x11852C6A, 0x562556BA, 0x6B457F0A, 0x89F57F59, 0xB49556E9, + 0xF3352C39, 0xCE550589, 0x7C75D999, 0x4115F029, 0x06B58AF9, 0x3BD5A349, + 0xB9853498, 0x84E51D28, 0xC34567F8, 0xFE254E48, 0x4C059258, 0x7165BBE8, + 0x36C5C138, 0x0BA5E888, 0x28D4C7DF, 0x15B4EE6F, 0x521494BF, 0x6F74BD0F, + 0xDD54611F, 0xE03448AF, 0xA794327F, 0x9AF41BCF, 0x18A48C1E, 0x25C4A5AE, + 0x6264DF7E, 0x5F04F6CE, 0xED242ADE, 0xD044036E, 0x97E479BE, 0xAA84500E, + 0x4834505D, 0x755479ED, 0x32F4033D, 0x0F942A8D, 0xBDB4F69D, 0x80D4DF2D, + 0xC774A5FD, 0xFA148C4D, 0x78441B9C, 0x4524322C, 0x028448FC, 0x3FE4614C, + 0x8DC4BD5C, 0xB0A494EC, 0xF704EE3C, 0xCA64C78C, + }, + + { + 0x00000000, 0xCB5CD3A5, 0x4DC8A10B, 0x869472AE, 0x9B914216, 0x50CD91B3, + 0xD659E31D, 0x1D0530B8, 0xEC53826D, 0x270F51C8, 0xA19B2366, 0x6AC7F0C3, + 0x77C2C07B, 0xBC9E13DE, 0x3A0A6170, 0xF156B2D5, 0x03D6029B, 0xC88AD13E, + 0x4E1EA390, 0x85427035, 0x9847408D, 0x531B9328, 0xD58FE186, 0x1ED33223, + 0xEF8580F6, 0x24D95353, 0xA24D21FD, 0x6911F258, 0x7414C2E0, 0xBF481145, + 0x39DC63EB, 0xF280B04E, 0x07AC0536, 0xCCF0D693, 0x4A64A43D, 0x81387798, + 0x9C3D4720, 0x57619485, 0xD1F5E62B, 0x1AA9358E, 0xEBFF875B, 0x20A354FE, + 0xA6372650, 0x6D6BF5F5, 0x706EC54D, 0xBB3216E8, 0x3DA66446, 0xF6FAB7E3, + 0x047A07AD, 0xCF26D408, 0x49B2A6A6, 0x82EE7503, 0x9FEB45BB, 0x54B7961E, + 0xD223E4B0, 0x197F3715, 0xE82985C0, 0x23755665, 0xA5E124CB, 0x6EBDF76E, + 0x73B8C7D6, 0xB8E41473, 0x3E7066DD, 0xF52CB578, 0x0F580A6C, 0xC404D9C9, + 0x4290AB67, 0x89CC78C2, 0x94C9487A, 0x5F959BDF, 0xD901E971, 0x125D3AD4, + 0xE30B8801, 0x28575BA4, 0xAEC3290A, 0x659FFAAF, 0x789ACA17, 0xB3C619B2, + 0x35526B1C, 0xFE0EB8B9, 0x0C8E08F7, 0xC7D2DB52, 0x4146A9FC, 0x8A1A7A59, + 0x971F4AE1, 0x5C439944, 0xDAD7EBEA, 0x118B384F, 0xE0DD8A9A, 0x2B81593F, + 0xAD152B91, 0x6649F834, 0x7B4CC88C, 0xB0101B29, 0x36846987, 0xFDD8BA22, + 0x08F40F5A, 0xC3A8DCFF, 0x453CAE51, 0x8E607DF4, 0x93654D4C, 0x58399EE9, + 0xDEADEC47, 0x15F13FE2, 0xE4A78D37, 0x2FFB5E92, 0xA96F2C3C, 0x6233FF99, + 0x7F36CF21, 0xB46A1C84, 0x32FE6E2A, 0xF9A2BD8F, 0x0B220DC1, 0xC07EDE64, + 0x46EAACCA, 0x8DB67F6F, 0x90B34FD7, 0x5BEF9C72, 0xDD7BEEDC, 0x16273D79, + 0xE7718FAC, 0x2C2D5C09, 0xAAB92EA7, 0x61E5FD02, 0x7CE0CDBA, 0xB7BC1E1F, + 0x31286CB1, 0xFA74BF14, 0x1EB014D8, 0xD5ECC77D, 0x5378B5D3, 0x98246676, + 0x852156CE, 0x4E7D856B, 0xC8E9F7C5, 0x03B52460, 0xF2E396B5, 0x39BF4510, + 0xBF2B37BE, 0x7477E41B, 0x6972D4A3, 0xA22E0706, 0x24BA75A8, 0xEFE6A60D, + 0x1D661643, 0xD63AC5E6, 0x50AEB748, 0x9BF264ED, 0x86F75455, 0x4DAB87F0, + 0xCB3FF55E, 0x006326FB, 0xF135942E, 0x3A69478B, 0xBCFD3525, 0x77A1E680, + 0x6AA4D638, 0xA1F8059D, 0x276C7733, 0xEC30A496, 0x191C11EE, 0xD240C24B, + 0x54D4B0E5, 0x9F886340, 0x828D53F8, 0x49D1805D, 0xCF45F2F3, 0x04192156, + 0xF54F9383, 0x3E134026, 0xB8873288, 0x73DBE12D, 0x6EDED195, 0xA5820230, + 0x2316709E, 0xE84AA33B, 0x1ACA1375, 0xD196C0D0, 0x5702B27E, 0x9C5E61DB, + 0x815B5163, 0x4A0782C6, 0xCC93F068, 0x07CF23CD, 0xF6999118, 0x3DC542BD, + 0xBB513013, 0x700DE3B6, 0x6D08D30E, 0xA65400AB, 0x20C07205, 0xEB9CA1A0, + 0x11E81EB4, 0xDAB4CD11, 0x5C20BFBF, 0x977C6C1A, 0x8A795CA2, 0x41258F07, + 0xC7B1FDA9, 0x0CED2E0C, 0xFDBB9CD9, 0x36E74F7C, 0xB0733DD2, 0x7B2FEE77, + 0x662ADECF, 0xAD760D6A, 0x2BE27FC4, 0xE0BEAC61, 0x123E1C2F, 0xD962CF8A, + 0x5FF6BD24, 0x94AA6E81, 0x89AF5E39, 0x42F38D9C, 0xC467FF32, 0x0F3B2C97, + 0xFE6D9E42, 0x35314DE7, 0xB3A53F49, 0x78F9ECEC, 0x65FCDC54, 0xAEA00FF1, + 0x28347D5F, 0xE368AEFA, 0x16441B82, 0xDD18C827, 0x5B8CBA89, 0x90D0692C, + 0x8DD55994, 0x46898A31, 0xC01DF89F, 0x0B412B3A, 0xFA1799EF, 0x314B4A4A, + 0xB7DF38E4, 0x7C83EB41, 0x6186DBF9, 0xAADA085C, 0x2C4E7AF2, 0xE712A957, + 0x15921919, 0xDECECABC, 0x585AB812, 0x93066BB7, 0x8E035B0F, 0x455F88AA, + 0xC3CBFA04, 0x089729A1, 0xF9C19B74, 0x329D48D1, 0xB4093A7F, 0x7F55E9DA, + 0x6250D962, 0xA90C0AC7, 0x2F987869, 0xE4C4ABCC, + }, + + { + 0x00000000, 0xA6770BB4, 0x979F1129, 0x31E81A9D, 0xF44F2413, 0x52382FA7, + 0x63D0353A, 0xC5A73E8E, 0x33EF4E67, 0x959845D3, 0xA4705F4E, 0x020754FA, + 0xC7A06A74, 0x61D761C0, 0x503F7B5D, 0xF64870E9, 0x67DE9CCE, 0xC1A9977A, + 0xF0418DE7, 0x56368653, 0x9391B8DD, 0x35E6B369, 0x040EA9F4, 0xA279A240, + 0x5431D2A9, 0xF246D91D, 0xC3AEC380, 0x65D9C834, 0xA07EF6BA, 0x0609FD0E, + 0x37E1E793, 0x9196EC27, 0xCFBD399C, 0x69CA3228, 0x582228B5, 0xFE552301, + 0x3BF21D8F, 0x9D85163B, 0xAC6D0CA6, 0x0A1A0712, 0xFC5277FB, 0x5A257C4F, + 0x6BCD66D2, 0xCDBA6D66, 0x081D53E8, 0xAE6A585C, 0x9F8242C1, 0x39F54975, + 0xA863A552, 0x0E14AEE6, 0x3FFCB47B, 0x998BBFCF, 0x5C2C8141, 0xFA5B8AF5, + 0xCBB39068, 0x6DC49BDC, 0x9B8CEB35, 0x3DFBE081, 0x0C13FA1C, 0xAA64F1A8, + 0x6FC3CF26, 0xC9B4C492, 0xF85CDE0F, 0x5E2BD5BB, 0x440B7579, 0xE27C7ECD, + 0xD3946450, 0x75E36FE4, 0xB044516A, 0x16335ADE, 0x27DB4043, 0x81AC4BF7, + 0x77E43B1E, 0xD19330AA, 0xE07B2A37, 0x460C2183, 0x83AB1F0D, 0x25DC14B9, + 0x14340E24, 0xB2430590, 0x23D5E9B7, 0x85A2E203, 0xB44AF89E, 0x123DF32A, + 0xD79ACDA4, 0x71EDC610, 0x4005DC8D, 0xE672D739, 0x103AA7D0, 0xB64DAC64, + 0x87A5B6F9, 0x21D2BD4D, 0xE47583C3, 0x42028877, 0x73EA92EA, 0xD59D995E, + 0x8BB64CE5, 0x2DC14751, 0x1C295DCC, 0xBA5E5678, 0x7FF968F6, 0xD98E6342, + 0xE86679DF, 0x4E11726B, 0xB8590282, 0x1E2E0936, 0x2FC613AB, 0x89B1181F, + 0x4C162691, 0xEA612D25, 0xDB8937B8, 0x7DFE3C0C, 0xEC68D02B, 0x4A1FDB9F, + 0x7BF7C102, 0xDD80CAB6, 0x1827F438, 0xBE50FF8C, 0x8FB8E511, 0x29CFEEA5, + 0xDF879E4C, 0x79F095F8, 0x48188F65, 0xEE6F84D1, 0x2BC8BA5F, 0x8DBFB1EB, + 0xBC57AB76, 0x1A20A0C2, 0x8816EAF2, 0x2E61E146, 0x1F89FBDB, 0xB9FEF06F, + 0x7C59CEE1, 0xDA2EC555, 0xEBC6DFC8, 0x4DB1D47C, 0xBBF9A495, 0x1D8EAF21, + 0x2C66B5BC, 0x8A11BE08, 0x4FB68086, 0xE9C18B32, 0xD82991AF, 0x7E5E9A1B, + 0xEFC8763C, 0x49BF7D88, 0x78576715, 0xDE206CA1, 0x1B87522F, 0xBDF0599B, + 0x8C184306, 0x2A6F48B2, 0xDC27385B, 0x7A5033EF, 0x4BB82972, 0xEDCF22C6, + 0x28681C48, 0x8E1F17FC, 0xBFF70D61, 0x198006D5, 0x47ABD36E, 0xE1DCD8DA, + 0xD034C247, 0x7643C9F3, 0xB3E4F77D, 0x1593FCC9, 0x247BE654, 0x820CEDE0, + 0x74449D09, 0xD23396BD, 0xE3DB8C20, 0x45AC8794, 0x800BB91A, 0x267CB2AE, + 0x1794A833, 0xB1E3A387, 0x20754FA0, 0x86024414, 0xB7EA5E89, 0x119D553D, + 0xD43A6BB3, 0x724D6007, 0x43A57A9A, 0xE5D2712E, 0x139A01C7, 0xB5ED0A73, + 0x840510EE, 0x22721B5A, 0xE7D525D4, 0x41A22E60, 0x704A34FD, 0xD63D3F49, + 0xCC1D9F8B, 0x6A6A943F, 0x5B828EA2, 0xFDF58516, 0x3852BB98, 0x9E25B02C, + 0xAFCDAAB1, 0x09BAA105, 0xFFF2D1EC, 0x5985DA58, 0x686DC0C5, 0xCE1ACB71, + 0x0BBDF5FF, 0xADCAFE4B, 0x9C22E4D6, 0x3A55EF62, 0xABC30345, 0x0DB408F1, + 0x3C5C126C, 0x9A2B19D8, 0x5F8C2756, 0xF9FB2CE2, 0xC813367F, 0x6E643DCB, + 0x982C4D22, 0x3E5B4696, 0x0FB35C0B, 0xA9C457BF, 0x6C636931, 0xCA146285, + 0xFBFC7818, 0x5D8B73AC, 0x03A0A617, 0xA5D7ADA3, 0x943FB73E, 0x3248BC8A, + 0xF7EF8204, 0x519889B0, 0x6070932D, 0xC6079899, 0x304FE870, 0x9638E3C4, + 0xA7D0F959, 0x01A7F2ED, 0xC400CC63, 0x6277C7D7, 0x539FDD4A, 0xF5E8D6FE, + 0x647E3AD9, 0xC209316D, 0xF3E12BF0, 0x55962044, 0x90311ECA, 0x3646157E, + 0x07AE0FE3, 0xA1D90457, 0x579174BE, 0xF1E67F0A, 0xC00E6597, 0x66796E23, + 0xA3DE50AD, 0x05A95B19, 0x34414184, 0x92364A30, + }, + + { + 0x00000000, 0xCCAA009E, 0x4225077D, 0x8E8F07E3, 0x844A0EFA, 0x48E00E64, + 0xC66F0987, 0x0AC50919, 0xD3E51BB5, 0x1F4F1B2B, 0x91C01CC8, 0x5D6A1C56, + 0x57AF154F, 0x9B0515D1, 0x158A1232, 0xD92012AC, 0x7CBB312B, 0xB01131B5, + 0x3E9E3656, 0xF23436C8, 0xF8F13FD1, 0x345B3F4F, 0xBAD438AC, 0x767E3832, + 0xAF5E2A9E, 0x63F42A00, 0xED7B2DE3, 0x21D12D7D, 0x2B142464, 0xE7BE24FA, + 0x69312319, 0xA59B2387, 0xF9766256, 0x35DC62C8, 0xBB53652B, 0x77F965B5, + 0x7D3C6CAC, 0xB1966C32, 0x3F196BD1, 0xF3B36B4F, 0x2A9379E3, 0xE639797D, + 0x68B67E9E, 0xA41C7E00, 0xAED97719, 0x62737787, 0xECFC7064, 0x205670FA, + 0x85CD537D, 0x496753E3, 0xC7E85400, 0x0B42549E, 0x01875D87, 0xCD2D5D19, + 0x43A25AFA, 0x8F085A64, 0x562848C8, 0x9A824856, 0x140D4FB5, 0xD8A74F2B, + 0xD2624632, 0x1EC846AC, 0x9047414F, 0x5CED41D1, 0x299DC2ED, 0xE537C273, + 0x6BB8C590, 0xA712C50E, 0xADD7CC17, 0x617DCC89, 0xEFF2CB6A, 0x2358CBF4, + 0xFA78D958, 0x36D2D9C6, 0xB85DDE25, 0x74F7DEBB, 0x7E32D7A2, 0xB298D73C, + 0x3C17D0DF, 0xF0BDD041, 0x5526F3C6, 0x998CF358, 0x1703F4BB, 0xDBA9F425, + 0xD16CFD3C, 0x1DC6FDA2, 0x9349FA41, 0x5FE3FADF, 0x86C3E873, 0x4A69E8ED, + 0xC4E6EF0E, 0x084CEF90, 0x0289E689, 0xCE23E617, 0x40ACE1F4, 0x8C06E16A, + 0xD0EBA0BB, 0x1C41A025, 0x92CEA7C6, 0x5E64A758, 0x54A1AE41, 0x980BAEDF, + 0x1684A93C, 0xDA2EA9A2, 0x030EBB0E, 0xCFA4BB90, 0x412BBC73, 0x8D81BCED, + 0x8744B5F4, 0x4BEEB56A, 0xC561B289, 0x09CBB217, 0xAC509190, 0x60FA910E, + 0xEE7596ED, 0x22DF9673, 0x281A9F6A, 0xE4B09FF4, 0x6A3F9817, 0xA6959889, + 0x7FB58A25, 0xB31F8ABB, 0x3D908D58, 0xF13A8DC6, 0xFBFF84DF, 0x37558441, + 0xB9DA83A2, 0x7570833C, 0x533B85DA, 0x9F918544, 0x111E82A7, 0xDDB48239, + 0xD7718B20, 0x1BDB8BBE, 0x95548C5D, 0x59FE8CC3, 0x80DE9E6F, 0x4C749EF1, + 0xC2FB9912, 0x0E51998C, 0x04949095, 0xC83E900B, 0x46B197E8, 0x8A1B9776, + 0x2F80B4F1, 0xE32AB46F, 0x6DA5B38C, 0xA10FB312, 0xABCABA0B, 0x6760BA95, + 0xE9EFBD76, 0x2545BDE8, 0xFC65AF44, 0x30CFAFDA, 0xBE40A839, 0x72EAA8A7, + 0x782FA1BE, 0xB485A120, 0x3A0AA6C3, 0xF6A0A65D, 0xAA4DE78C, 0x66E7E712, + 0xE868E0F1, 0x24C2E06F, 0x2E07E976, 0xE2ADE9E8, 0x6C22EE0B, 0xA088EE95, + 0x79A8FC39, 0xB502FCA7, 0x3B8DFB44, 0xF727FBDA, 0xFDE2F2C3, 0x3148F25D, + 0xBFC7F5BE, 0x736DF520, 0xD6F6D6A7, 0x1A5CD639, 0x94D3D1DA, 0x5879D144, + 0x52BCD85D, 0x9E16D8C3, 0x1099DF20, 0xDC33DFBE, 0x0513CD12, 0xC9B9CD8C, + 0x4736CA6F, 0x8B9CCAF1, 0x8159C3E8, 0x4DF3C376, 0xC37CC495, 0x0FD6C40B, + 0x7AA64737, 0xB60C47A9, 0x3883404A, 0xF42940D4, 0xFEEC49CD, 0x32464953, + 0xBCC94EB0, 0x70634E2E, 0xA9435C82, 0x65E95C1C, 0xEB665BFF, 0x27CC5B61, + 0x2D095278, 0xE1A352E6, 0x6F2C5505, 0xA386559B, 0x061D761C, 0xCAB77682, + 0x44387161, 0x889271FF, 0x825778E6, 0x4EFD7878, 0xC0727F9B, 0x0CD87F05, + 0xD5F86DA9, 0x19526D37, 0x97DD6AD4, 0x5B776A4A, 0x51B26353, 0x9D1863CD, + 0x1397642E, 0xDF3D64B0, 0x83D02561, 0x4F7A25FF, 0xC1F5221C, 0x0D5F2282, + 0x079A2B9B, 0xCB302B05, 0x45BF2CE6, 0x89152C78, 0x50353ED4, 0x9C9F3E4A, + 0x121039A9, 0xDEBA3937, 0xD47F302E, 0x18D530B0, 0x965A3753, 0x5AF037CD, + 0xFF6B144A, 0x33C114D4, 0xBD4E1337, 0x71E413A9, 0x7B211AB0, 0xB78B1A2E, + 0x39041DCD, 0xF5AE1D53, 0x2C8E0FFF, 0xE0240F61, 0x6EAB0882, 0xA201081C, + 0xA8C40105, 0x646E019B, 0xEAE10678, 0x264B06E6, + } +# endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 || + // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +# ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + // beyond this point only relevant for Slicing-by-16 + , + { + 0x00000000, 0x177B1443, 0x2EF62886, 0x398D3CC5, 0x5DEC510C, 0x4A97454F, + 0x731A798A, 0x64616DC9, 0xBBD8A218, 0xACA3B65B, 0x952E8A9E, 0x82559EDD, + 0xE634F314, 0xF14FE757, 0xC8C2DB92, 0xDFB9CFD1, 0xACC04271, 0xBBBB5632, + 0x82366AF7, 0x954D7EB4, 0xF12C137D, 0xE657073E, 0xDFDA3BFB, 0xC8A12FB8, + 0x1718E069, 0x0063F42A, 0x39EEC8EF, 0x2E95DCAC, 0x4AF4B165, 0x5D8FA526, + 0x640299E3, 0x73798DA0, 0x82F182A3, 0x958A96E0, 0xAC07AA25, 0xBB7CBE66, + 0xDF1DD3AF, 0xC866C7EC, 0xF1EBFB29, 0xE690EF6A, 0x392920BB, 0x2E5234F8, + 0x17DF083D, 0x00A41C7E, 0x64C571B7, 0x73BE65F4, 0x4A335931, 0x5D484D72, + 0x2E31C0D2, 0x394AD491, 0x00C7E854, 0x17BCFC17, 0x73DD91DE, 0x64A6859D, + 0x5D2BB958, 0x4A50AD1B, 0x95E962CA, 0x82927689, 0xBB1F4A4C, 0xAC645E0F, + 0xC80533C6, 0xDF7E2785, 0xE6F31B40, 0xF1880F03, 0xDE920307, 0xC9E91744, + 0xF0642B81, 0xE71F3FC2, 0x837E520B, 0x94054648, 0xAD887A8D, 0xBAF36ECE, + 0x654AA11F, 0x7231B55C, 0x4BBC8999, 0x5CC79DDA, 0x38A6F013, 0x2FDDE450, + 0x1650D895, 0x012BCCD6, 0x72524176, 0x65295535, 0x5CA469F0, 0x4BDF7DB3, + 0x2FBE107A, 0x38C50439, 0x014838FC, 0x16332CBF, 0xC98AE36E, 0xDEF1F72D, + 0xE77CCBE8, 0xF007DFAB, 0x9466B262, 0x831DA621, 0xBA909AE4, 0xADEB8EA7, + 0x5C6381A4, 0x4B1895E7, 0x7295A922, 0x65EEBD61, 0x018FD0A8, 0x16F4C4EB, + 0x2F79F82E, 0x3802EC6D, 0xE7BB23BC, 0xF0C037FF, 0xC94D0B3A, 0xDE361F79, + 0xBA5772B0, 0xAD2C66F3, 0x94A15A36, 0x83DA4E75, 0xF0A3C3D5, 0xE7D8D796, + 0xDE55EB53, 0xC92EFF10, 0xAD4F92D9, 0xBA34869A, 0x83B9BA5F, 0x94C2AE1C, + 0x4B7B61CD, 0x5C00758E, 0x658D494B, 0x72F65D08, 0x169730C1, 0x01EC2482, + 0x38611847, 0x2F1A0C04, 0x6655004F, 0x712E140C, 0x48A328C9, 0x5FD83C8A, + 0x3BB95143, 0x2CC24500, 0x154F79C5, 0x02346D86, 0xDD8DA257, 0xCAF6B614, + 0xF37B8AD1, 0xE4009E92, 0x8061F35B, 0x971AE718, 0xAE97DBDD, 0xB9ECCF9E, + 0xCA95423E, 0xDDEE567D, 0xE4636AB8, 0xF3187EFB, 0x97791332, 0x80020771, + 0xB98F3BB4, 0xAEF42FF7, 0x714DE026, 0x6636F465, 0x5FBBC8A0, 0x48C0DCE3, + 0x2CA1B12A, 0x3BDAA569, 0x025799AC, 0x152C8DEF, 0xE4A482EC, 0xF3DF96AF, + 0xCA52AA6A, 0xDD29BE29, 0xB948D3E0, 0xAE33C7A3, 0x97BEFB66, 0x80C5EF25, + 0x5F7C20F4, 0x480734B7, 0x718A0872, 0x66F11C31, 0x029071F8, 0x15EB65BB, + 0x2C66597E, 0x3B1D4D3D, 0x4864C09D, 0x5F1FD4DE, 0x6692E81B, 0x71E9FC58, + 0x15889191, 0x02F385D2, 0x3B7EB917, 0x2C05AD54, 0xF3BC6285, 0xE4C776C6, + 0xDD4A4A03, 0xCA315E40, 0xAE503389, 0xB92B27CA, 0x80A61B0F, 0x97DD0F4C, + 0xB8C70348, 0xAFBC170B, 0x96312BCE, 0x814A3F8D, 0xE52B5244, 0xF2504607, + 0xCBDD7AC2, 0xDCA66E81, 0x031FA150, 0x1464B513, 0x2DE989D6, 0x3A929D95, + 0x5EF3F05C, 0x4988E41F, 0x7005D8DA, 0x677ECC99, 0x14074139, 0x037C557A, + 0x3AF169BF, 0x2D8A7DFC, 0x49EB1035, 0x5E900476, 0x671D38B3, 0x70662CF0, + 0xAFDFE321, 0xB8A4F762, 0x8129CBA7, 0x9652DFE4, 0xF233B22D, 0xE548A66E, + 0xDCC59AAB, 0xCBBE8EE8, 0x3A3681EB, 0x2D4D95A8, 0x14C0A96D, 0x03BBBD2E, + 0x67DAD0E7, 0x70A1C4A4, 0x492CF861, 0x5E57EC22, 0x81EE23F3, 0x969537B0, + 0xAF180B75, 0xB8631F36, 0xDC0272FF, 0xCB7966BC, 0xF2F45A79, 0xE58F4E3A, + 0x96F6C39A, 0x818DD7D9, 0xB800EB1C, 0xAF7BFF5F, 0xCB1A9296, 0xDC6186D5, + 0xE5ECBA10, 0xF297AE53, 0x2D2E6182, 0x3A5575C1, 0x03D84904, 0x14A35D47, + 0x70C2308E, 0x67B924CD, 0x5E341808, 0x494F0C4B, + }, + + { + 0x00000000, 0xEFC26B3E, 0x04F5D03D, 0xEB37BB03, 0x09EBA07A, 0xE629CB44, + 0x0D1E7047, 0xE2DC1B79, 0x13D740F4, 0xFC152BCA, 0x172290C9, 0xF8E0FBF7, + 0x1A3CE08E, 0xF5FE8BB0, 0x1EC930B3, 0xF10B5B8D, 0x27AE81E8, 0xC86CEAD6, + 0x235B51D5, 0xCC993AEB, 0x2E452192, 0xC1874AAC, 0x2AB0F1AF, 0xC5729A91, + 0x3479C11C, 0xDBBBAA22, 0x308C1121, 0xDF4E7A1F, 0x3D926166, 0xD2500A58, + 0x3967B15B, 0xD6A5DA65, 0x4F5D03D0, 0xA09F68EE, 0x4BA8D3ED, 0xA46AB8D3, + 0x46B6A3AA, 0xA974C894, 0x42437397, 0xAD8118A9, 0x5C8A4324, 0xB348281A, + 0x587F9319, 0xB7BDF827, 0x5561E35E, 0xBAA38860, 0x51943363, 0xBE56585D, + 0x68F38238, 0x8731E906, 0x6C065205, 0x83C4393B, 0x61182242, 0x8EDA497C, + 0x65EDF27F, 0x8A2F9941, 0x7B24C2CC, 0x94E6A9F2, 0x7FD112F1, 0x901379CF, + 0x72CF62B6, 0x9D0D0988, 0x763AB28B, 0x99F8D9B5, 0x9EBA07A0, 0x71786C9E, + 0x9A4FD79D, 0x758DBCA3, 0x9751A7DA, 0x7893CCE4, 0x93A477E7, 0x7C661CD9, + 0x8D6D4754, 0x62AF2C6A, 0x89989769, 0x665AFC57, 0x8486E72E, 0x6B448C10, + 0x80733713, 0x6FB15C2D, 0xB9148648, 0x56D6ED76, 0xBDE15675, 0x52233D4B, + 0xB0FF2632, 0x5F3D4D0C, 0xB40AF60F, 0x5BC89D31, 0xAAC3C6BC, 0x4501AD82, + 0xAE361681, 0x41F47DBF, 0xA32866C6, 0x4CEA0DF8, 0xA7DDB6FB, 0x481FDDC5, + 0xD1E70470, 0x3E256F4E, 0xD512D44D, 0x3AD0BF73, 0xD80CA40A, 0x37CECF34, + 0xDCF97437, 0x333B1F09, 0xC2304484, 0x2DF22FBA, 0xC6C594B9, 0x2907FF87, + 0xCBDBE4FE, 0x24198FC0, 0xCF2E34C3, 0x20EC5FFD, 0xF6498598, 0x198BEEA6, + 0xF2BC55A5, 0x1D7E3E9B, 0xFFA225E2, 0x10604EDC, 0xFB57F5DF, 0x14959EE1, + 0xE59EC56C, 0x0A5CAE52, 0xE16B1551, 0x0EA97E6F, 0xEC756516, 0x03B70E28, + 0xE880B52B, 0x0742DE15, 0xE6050901, 0x09C7623F, 0xE2F0D93C, 0x0D32B202, + 0xEFEEA97B, 0x002CC245, 0xEB1B7946, 0x04D91278, 0xF5D249F5, 0x1A1022CB, + 0xF12799C8, 0x1EE5F2F6, 0xFC39E98F, 0x13FB82B1, 0xF8CC39B2, 0x170E528C, + 0xC1AB88E9, 0x2E69E3D7, 0xC55E58D4, 0x2A9C33EA, 0xC8402893, 0x278243AD, + 0xCCB5F8AE, 0x23779390, 0xD27CC81D, 0x3DBEA323, 0xD6891820, 0x394B731E, + 0xDB976867, 0x34550359, 0xDF62B85A, 0x30A0D364, 0xA9580AD1, 0x469A61EF, + 0xADADDAEC, 0x426FB1D2, 0xA0B3AAAB, 0x4F71C195, 0xA4467A96, 0x4B8411A8, + 0xBA8F4A25, 0x554D211B, 0xBE7A9A18, 0x51B8F126, 0xB364EA5F, 0x5CA68161, + 0xB7913A62, 0x5853515C, 0x8EF68B39, 0x6134E007, 0x8A035B04, 0x65C1303A, + 0x871D2B43, 0x68DF407D, 0x83E8FB7E, 0x6C2A9040, 0x9D21CBCD, 0x72E3A0F3, + 0x99D41BF0, 0x761670CE, 0x94CA6BB7, 0x7B080089, 0x903FBB8A, 0x7FFDD0B4, + 0x78BF0EA1, 0x977D659F, 0x7C4ADE9C, 0x9388B5A2, 0x7154AEDB, 0x9E96C5E5, + 0x75A17EE6, 0x9A6315D8, 0x6B684E55, 0x84AA256B, 0x6F9D9E68, 0x805FF556, + 0x6283EE2F, 0x8D418511, 0x66763E12, 0x89B4552C, 0x5F118F49, 0xB0D3E477, + 0x5BE45F74, 0xB426344A, 0x56FA2F33, 0xB938440D, 0x520FFF0E, 0xBDCD9430, + 0x4CC6CFBD, 0xA304A483, 0x48331F80, 0xA7F174BE, 0x452D6FC7, 0xAAEF04F9, + 0x41D8BFFA, 0xAE1AD4C4, 0x37E20D71, 0xD820664F, 0x3317DD4C, 0xDCD5B672, + 0x3E09AD0B, 0xD1CBC635, 0x3AFC7D36, 0xD53E1608, 0x24354D85, 0xCBF726BB, + 0x20C09DB8, 0xCF02F686, 0x2DDEEDFF, 0xC21C86C1, 0x292B3DC2, 0xC6E956FC, + 0x104C8C99, 0xFF8EE7A7, 0x14B95CA4, 0xFB7B379A, 0x19A72CE3, 0xF66547DD, + 0x1D52FCDE, 0xF29097E0, 0x039BCC6D, 0xEC59A753, 0x076E1C50, 0xE8AC776E, + 0x0A706C17, 0xE5B20729, 0x0E85BC2A, 0xE147D714, + }, + + { + 0x00000000, 0xC18EDFC0, 0x586CB9C1, 0x99E26601, 0xB0D97382, 0x7157AC42, + 0xE8B5CA43, 0x293B1583, 0xBAC3E145, 0x7B4D3E85, 0xE2AF5884, 0x23218744, + 0x0A1A92C7, 0xCB944D07, 0x52762B06, 0x93F8F4C6, 0xAEF6C4CB, 0x6F781B0B, + 0xF69A7D0A, 0x3714A2CA, 0x1E2FB749, 0xDFA16889, 0x46430E88, 0x87CDD148, + 0x1435258E, 0xD5BBFA4E, 0x4C599C4F, 0x8DD7438F, 0xA4EC560C, 0x656289CC, + 0xFC80EFCD, 0x3D0E300D, 0x869C8FD7, 0x47125017, 0xDEF03616, 0x1F7EE9D6, + 0x3645FC55, 0xF7CB2395, 0x6E294594, 0xAFA79A54, 0x3C5F6E92, 0xFDD1B152, + 0x6433D753, 0xA5BD0893, 0x8C861D10, 0x4D08C2D0, 0xD4EAA4D1, 0x15647B11, + 0x286A4B1C, 0xE9E494DC, 0x7006F2DD, 0xB1882D1D, 0x98B3389E, 0x593DE75E, + 0xC0DF815F, 0x01515E9F, 0x92A9AA59, 0x53277599, 0xCAC51398, 0x0B4BCC58, + 0x2270D9DB, 0xE3FE061B, 0x7A1C601A, 0xBB92BFDA, 0xD64819EF, 0x17C6C62F, + 0x8E24A02E, 0x4FAA7FEE, 0x66916A6D, 0xA71FB5AD, 0x3EFDD3AC, 0xFF730C6C, + 0x6C8BF8AA, 0xAD05276A, 0x34E7416B, 0xF5699EAB, 0xDC528B28, 0x1DDC54E8, + 0x843E32E9, 0x45B0ED29, 0x78BEDD24, 0xB93002E4, 0x20D264E5, 0xE15CBB25, + 0xC867AEA6, 0x09E97166, 0x900B1767, 0x5185C8A7, 0xC27D3C61, 0x03F3E3A1, + 0x9A1185A0, 0x5B9F5A60, 0x72A44FE3, 0xB32A9023, 0x2AC8F622, 0xEB4629E2, + 0x50D49638, 0x915A49F8, 0x08B82FF9, 0xC936F039, 0xE00DE5BA, 0x21833A7A, + 0xB8615C7B, 0x79EF83BB, 0xEA17777D, 0x2B99A8BD, 0xB27BCEBC, 0x73F5117C, + 0x5ACE04FF, 0x9B40DB3F, 0x02A2BD3E, 0xC32C62FE, 0xFE2252F3, 0x3FAC8D33, + 0xA64EEB32, 0x67C034F2, 0x4EFB2171, 0x8F75FEB1, 0x169798B0, 0xD7194770, + 0x44E1B3B6, 0x856F6C76, 0x1C8D0A77, 0xDD03D5B7, 0xF438C034, 0x35B61FF4, + 0xAC5479F5, 0x6DDAA635, 0x77E1359F, 0xB66FEA5F, 0x2F8D8C5E, 0xEE03539E, + 0xC738461D, 0x06B699DD, 0x9F54FFDC, 0x5EDA201C, 0xCD22D4DA, 0x0CAC0B1A, + 0x954E6D1B, 0x54C0B2DB, 0x7DFBA758, 0xBC757898, 0x25971E99, 0xE419C159, + 0xD917F154, 0x18992E94, 0x817B4895, 0x40F59755, 0x69CE82D6, 0xA8405D16, + 0x31A23B17, 0xF02CE4D7, 0x63D41011, 0xA25ACFD1, 0x3BB8A9D0, 0xFA367610, + 0xD30D6393, 0x1283BC53, 0x8B61DA52, 0x4AEF0592, 0xF17DBA48, 0x30F36588, + 0xA9110389, 0x689FDC49, 0x41A4C9CA, 0x802A160A, 0x19C8700B, 0xD846AFCB, + 0x4BBE5B0D, 0x8A3084CD, 0x13D2E2CC, 0xD25C3D0C, 0xFB67288F, 0x3AE9F74F, + 0xA30B914E, 0x62854E8E, 0x5F8B7E83, 0x9E05A143, 0x07E7C742, 0xC6691882, + 0xEF520D01, 0x2EDCD2C1, 0xB73EB4C0, 0x76B06B00, 0xE5489FC6, 0x24C64006, + 0xBD242607, 0x7CAAF9C7, 0x5591EC44, 0x941F3384, 0x0DFD5585, 0xCC738A45, + 0xA1A92C70, 0x6027F3B0, 0xF9C595B1, 0x384B4A71, 0x11705FF2, 0xD0FE8032, + 0x491CE633, 0x889239F3, 0x1B6ACD35, 0xDAE412F5, 0x430674F4, 0x8288AB34, + 0xABB3BEB7, 0x6A3D6177, 0xF3DF0776, 0x3251D8B6, 0x0F5FE8BB, 0xCED1377B, + 0x5733517A, 0x96BD8EBA, 0xBF869B39, 0x7E0844F9, 0xE7EA22F8, 0x2664FD38, + 0xB59C09FE, 0x7412D63E, 0xEDF0B03F, 0x2C7E6FFF, 0x05457A7C, 0xC4CBA5BC, + 0x5D29C3BD, 0x9CA71C7D, 0x2735A3A7, 0xE6BB7C67, 0x7F591A66, 0xBED7C5A6, + 0x97ECD025, 0x56620FE5, 0xCF8069E4, 0x0E0EB624, 0x9DF642E2, 0x5C789D22, + 0xC59AFB23, 0x041424E3, 0x2D2F3160, 0xECA1EEA0, 0x754388A1, 0xB4CD5761, + 0x89C3676C, 0x484DB8AC, 0xD1AFDEAD, 0x1021016D, 0x391A14EE, 0xF894CB2E, + 0x6176AD2F, 0xA0F872EF, 0x33008629, 0xF28E59E9, 0x6B6C3FE8, 0xAAE2E028, + 0x83D9F5AB, 0x42572A6B, 0xDBB54C6A, 0x1A3B93AA, + }, + + { + 0x00000000, 0x9BA54C6F, 0xEC3B9E9F, 0x779ED2F0, 0x03063B7F, 0x98A37710, + 0xEF3DA5E0, 0x7498E98F, 0x060C76FE, 0x9DA93A91, 0xEA37E861, 0x7192A40E, + 0x050A4D81, 0x9EAF01EE, 0xE931D31E, 0x72949F71, 0x0C18EDFC, 0x97BDA193, + 0xE0237363, 0x7B863F0C, 0x0F1ED683, 0x94BB9AEC, 0xE325481C, 0x78800473, + 0x0A149B02, 0x91B1D76D, 0xE62F059D, 0x7D8A49F2, 0x0912A07D, 0x92B7EC12, + 0xE5293EE2, 0x7E8C728D, 0x1831DBF8, 0x83949797, 0xF40A4567, 0x6FAF0908, + 0x1B37E087, 0x8092ACE8, 0xF70C7E18, 0x6CA93277, 0x1E3DAD06, 0x8598E169, + 0xF2063399, 0x69A37FF6, 0x1D3B9679, 0x869EDA16, 0xF10008E6, 0x6AA54489, + 0x14293604, 0x8F8C7A6B, 0xF812A89B, 0x63B7E4F4, 0x172F0D7B, 0x8C8A4114, + 0xFB1493E4, 0x60B1DF8B, 0x122540FA, 0x89800C95, 0xFE1EDE65, 0x65BB920A, + 0x11237B85, 0x8A8637EA, 0xFD18E51A, 0x66BDA975, 0x3063B7F0, 0xABC6FB9F, + 0xDC58296F, 0x47FD6500, 0x33658C8F, 0xA8C0C0E0, 0xDF5E1210, 0x44FB5E7F, + 0x366FC10E, 0xADCA8D61, 0xDA545F91, 0x41F113FE, 0x3569FA71, 0xAECCB61E, + 0xD95264EE, 0x42F72881, 0x3C7B5A0C, 0xA7DE1663, 0xD040C493, 0x4BE588FC, + 0x3F7D6173, 0xA4D82D1C, 0xD346FFEC, 0x48E3B383, 0x3A772CF2, 0xA1D2609D, + 0xD64CB26D, 0x4DE9FE02, 0x3971178D, 0xA2D45BE2, 0xD54A8912, 0x4EEFC57D, + 0x28526C08, 0xB3F72067, 0xC469F297, 0x5FCCBEF8, 0x2B545777, 0xB0F11B18, + 0xC76FC9E8, 0x5CCA8587, 0x2E5E1AF6, 0xB5FB5699, 0xC2658469, 0x59C0C806, + 0x2D582189, 0xB6FD6DE6, 0xC163BF16, 0x5AC6F379, 0x244A81F4, 0xBFEFCD9B, + 0xC8711F6B, 0x53D45304, 0x274CBA8B, 0xBCE9F6E4, 0xCB772414, 0x50D2687B, + 0x2246F70A, 0xB9E3BB65, 0xCE7D6995, 0x55D825FA, 0x2140CC75, 0xBAE5801A, + 0xCD7B52EA, 0x56DE1E85, 0x60C76FE0, 0xFB62238F, 0x8CFCF17F, 0x1759BD10, + 0x63C1549F, 0xF86418F0, 0x8FFACA00, 0x145F866F, 0x66CB191E, 0xFD6E5571, + 0x8AF08781, 0x1155CBEE, 0x65CD2261, 0xFE686E0E, 0x89F6BCFE, 0x1253F091, + 0x6CDF821C, 0xF77ACE73, 0x80E41C83, 0x1B4150EC, 0x6FD9B963, 0xF47CF50C, + 0x83E227FC, 0x18476B93, 0x6AD3F4E2, 0xF176B88D, 0x86E86A7D, 0x1D4D2612, + 0x69D5CF9D, 0xF27083F2, 0x85EE5102, 0x1E4B1D6D, 0x78F6B418, 0xE353F877, + 0x94CD2A87, 0x0F6866E8, 0x7BF08F67, 0xE055C308, 0x97CB11F8, 0x0C6E5D97, + 0x7EFAC2E6, 0xE55F8E89, 0x92C15C79, 0x09641016, 0x7DFCF999, 0xE659B5F6, + 0x91C76706, 0x0A622B69, 0x74EE59E4, 0xEF4B158B, 0x98D5C77B, 0x03708B14, + 0x77E8629B, 0xEC4D2EF4, 0x9BD3FC04, 0x0076B06B, 0x72E22F1A, 0xE9476375, + 0x9ED9B185, 0x057CFDEA, 0x71E41465, 0xEA41580A, 0x9DDF8AFA, 0x067AC695, + 0x50A4D810, 0xCB01947F, 0xBC9F468F, 0x273A0AE0, 0x53A2E36F, 0xC807AF00, + 0xBF997DF0, 0x243C319F, 0x56A8AEEE, 0xCD0DE281, 0xBA933071, 0x21367C1E, + 0x55AE9591, 0xCE0BD9FE, 0xB9950B0E, 0x22304761, 0x5CBC35EC, 0xC7197983, + 0xB087AB73, 0x2B22E71C, 0x5FBA0E93, 0xC41F42FC, 0xB381900C, 0x2824DC63, + 0x5AB04312, 0xC1150F7D, 0xB68BDD8D, 0x2D2E91E2, 0x59B6786D, 0xC2133402, + 0xB58DE6F2, 0x2E28AA9D, 0x489503E8, 0xD3304F87, 0xA4AE9D77, 0x3F0BD118, + 0x4B933897, 0xD03674F8, 0xA7A8A608, 0x3C0DEA67, 0x4E997516, 0xD53C3979, + 0xA2A2EB89, 0x3907A7E6, 0x4D9F4E69, 0xD63A0206, 0xA1A4D0F6, 0x3A019C99, + 0x448DEE14, 0xDF28A27B, 0xA8B6708B, 0x33133CE4, 0x478BD56B, 0xDC2E9904, + 0xABB04BF4, 0x3015079B, 0x428198EA, 0xD924D485, 0xAEBA0675, 0x351F4A1A, + 0x4187A395, 0xDA22EFFA, 0xADBC3D0A, 0x36197165, + }, + + { + 0x00000000, 0xDD96D985, 0x605CB54B, 0xBDCA6CCE, 0xC0B96A96, 0x1D2FB313, + 0xA0E5DFDD, 0x7D730658, 0x5A03D36D, 0x87950AE8, 0x3A5F6626, 0xE7C9BFA3, + 0x9ABAB9FB, 0x472C607E, 0xFAE60CB0, 0x2770D535, 0xB407A6DA, 0x69917F5F, + 0xD45B1391, 0x09CDCA14, 0x74BECC4C, 0xA92815C9, 0x14E27907, 0xC974A082, + 0xEE0475B7, 0x3392AC32, 0x8E58C0FC, 0x53CE1979, 0x2EBD1F21, 0xF32BC6A4, + 0x4EE1AA6A, 0x937773EF, 0xB37E4BF5, 0x6EE89270, 0xD322FEBE, 0x0EB4273B, + 0x73C72163, 0xAE51F8E6, 0x139B9428, 0xCE0D4DAD, 0xE97D9898, 0x34EB411D, + 0x89212DD3, 0x54B7F456, 0x29C4F20E, 0xF4522B8B, 0x49984745, 0x940E9EC0, + 0x0779ED2F, 0xDAEF34AA, 0x67255864, 0xBAB381E1, 0xC7C087B9, 0x1A565E3C, + 0xA79C32F2, 0x7A0AEB77, 0x5D7A3E42, 0x80ECE7C7, 0x3D268B09, 0xE0B0528C, + 0x9DC354D4, 0x40558D51, 0xFD9FE19F, 0x2009381A, 0xBD8D91AB, 0x601B482E, + 0xDDD124E0, 0x0047FD65, 0x7D34FB3D, 0xA0A222B8, 0x1D684E76, 0xC0FE97F3, + 0xE78E42C6, 0x3A189B43, 0x87D2F78D, 0x5A442E08, 0x27372850, 0xFAA1F1D5, + 0x476B9D1B, 0x9AFD449E, 0x098A3771, 0xD41CEEF4, 0x69D6823A, 0xB4405BBF, + 0xC9335DE7, 0x14A58462, 0xA96FE8AC, 0x74F93129, 0x5389E41C, 0x8E1F3D99, + 0x33D55157, 0xEE4388D2, 0x93308E8A, 0x4EA6570F, 0xF36C3BC1, 0x2EFAE244, + 0x0EF3DA5E, 0xD36503DB, 0x6EAF6F15, 0xB339B690, 0xCE4AB0C8, 0x13DC694D, + 0xAE160583, 0x7380DC06, 0x54F00933, 0x8966D0B6, 0x34ACBC78, 0xE93A65FD, + 0x944963A5, 0x49DFBA20, 0xF415D6EE, 0x29830F6B, 0xBAF47C84, 0x6762A501, + 0xDAA8C9CF, 0x073E104A, 0x7A4D1612, 0xA7DBCF97, 0x1A11A359, 0xC7877ADC, + 0xE0F7AFE9, 0x3D61766C, 0x80AB1AA2, 0x5D3DC327, 0x204EC57F, 0xFDD81CFA, + 0x40127034, 0x9D84A9B1, 0xA06A2517, 0x7DFCFC92, 0xC036905C, 0x1DA049D9, + 0x60D34F81, 0xBD459604, 0x008FFACA, 0xDD19234F, 0xFA69F67A, 0x27FF2FFF, + 0x9A354331, 0x47A39AB4, 0x3AD09CEC, 0xE7464569, 0x5A8C29A7, 0x871AF022, + 0x146D83CD, 0xC9FB5A48, 0x74313686, 0xA9A7EF03, 0xD4D4E95B, 0x094230DE, + 0xB4885C10, 0x691E8595, 0x4E6E50A0, 0x93F88925, 0x2E32E5EB, 0xF3A43C6E, + 0x8ED73A36, 0x5341E3B3, 0xEE8B8F7D, 0x331D56F8, 0x13146EE2, 0xCE82B767, + 0x7348DBA9, 0xAEDE022C, 0xD3AD0474, 0x0E3BDDF1, 0xB3F1B13F, 0x6E6768BA, + 0x4917BD8F, 0x9481640A, 0x294B08C4, 0xF4DDD141, 0x89AED719, 0x54380E9C, + 0xE9F26252, 0x3464BBD7, 0xA713C838, 0x7A8511BD, 0xC74F7D73, 0x1AD9A4F6, + 0x67AAA2AE, 0xBA3C7B2B, 0x07F617E5, 0xDA60CE60, 0xFD101B55, 0x2086C2D0, + 0x9D4CAE1E, 0x40DA779B, 0x3DA971C3, 0xE03FA846, 0x5DF5C488, 0x80631D0D, + 0x1DE7B4BC, 0xC0716D39, 0x7DBB01F7, 0xA02DD872, 0xDD5EDE2A, 0x00C807AF, + 0xBD026B61, 0x6094B2E4, 0x47E467D1, 0x9A72BE54, 0x27B8D29A, 0xFA2E0B1F, + 0x875D0D47, 0x5ACBD4C2, 0xE701B80C, 0x3A976189, 0xA9E01266, 0x7476CBE3, + 0xC9BCA72D, 0x142A7EA8, 0x695978F0, 0xB4CFA175, 0x0905CDBB, 0xD493143E, + 0xF3E3C10B, 0x2E75188E, 0x93BF7440, 0x4E29ADC5, 0x335AAB9D, 0xEECC7218, + 0x53061ED6, 0x8E90C753, 0xAE99FF49, 0x730F26CC, 0xCEC54A02, 0x13539387, + 0x6E2095DF, 0xB3B64C5A, 0x0E7C2094, 0xD3EAF911, 0xF49A2C24, 0x290CF5A1, + 0x94C6996F, 0x495040EA, 0x342346B2, 0xE9B59F37, 0x547FF3F9, 0x89E92A7C, + 0x1A9E5993, 0xC7088016, 0x7AC2ECD8, 0xA754355D, 0xDA273305, 0x07B1EA80, + 0xBA7B864E, 0x67ED5FCB, 0x409D8AFE, 0x9D0B537B, 0x20C13FB5, 0xFD57E630, + 0x8024E068, 0x5DB239ED, 0xE0785523, 0x3DEE8CA6, + }, + + { + 0x00000000, 0x9D0FE176, 0xE16EC4AD, 0x7C6125DB, 0x19AC8F1B, 0x84A36E6D, + 0xF8C24BB6, 0x65CDAAC0, 0x33591E36, 0xAE56FF40, 0xD237DA9B, 0x4F383BED, + 0x2AF5912D, 0xB7FA705B, 0xCB9B5580, 0x5694B4F6, 0x66B23C6C, 0xFBBDDD1A, + 0x87DCF8C1, 0x1AD319B7, 0x7F1EB377, 0xE2115201, 0x9E7077DA, 0x037F96AC, + 0x55EB225A, 0xC8E4C32C, 0xB485E6F7, 0x298A0781, 0x4C47AD41, 0xD1484C37, + 0xAD2969EC, 0x3026889A, 0xCD6478D8, 0x506B99AE, 0x2C0ABC75, 0xB1055D03, + 0xD4C8F7C3, 0x49C716B5, 0x35A6336E, 0xA8A9D218, 0xFE3D66EE, 0x63328798, + 0x1F53A243, 0x825C4335, 0xE791E9F5, 0x7A9E0883, 0x06FF2D58, 0x9BF0CC2E, + 0xABD644B4, 0x36D9A5C2, 0x4AB88019, 0xD7B7616F, 0xB27ACBAF, 0x2F752AD9, + 0x53140F02, 0xCE1BEE74, 0x988F5A82, 0x0580BBF4, 0x79E19E2F, 0xE4EE7F59, + 0x8123D599, 0x1C2C34EF, 0x604D1134, 0xFD42F042, 0x41B9F7F1, 0xDCB61687, + 0xA0D7335C, 0x3DD8D22A, 0x581578EA, 0xC51A999C, 0xB97BBC47, 0x24745D31, + 0x72E0E9C7, 0xEFEF08B1, 0x938E2D6A, 0x0E81CC1C, 0x6B4C66DC, 0xF64387AA, + 0x8A22A271, 0x172D4307, 0x270BCB9D, 0xBA042AEB, 0xC6650F30, 0x5B6AEE46, + 0x3EA74486, 0xA3A8A5F0, 0xDFC9802B, 0x42C6615D, 0x1452D5AB, 0x895D34DD, + 0xF53C1106, 0x6833F070, 0x0DFE5AB0, 0x90F1BBC6, 0xEC909E1D, 0x719F7F6B, + 0x8CDD8F29, 0x11D26E5F, 0x6DB34B84, 0xF0BCAAF2, 0x95710032, 0x087EE144, + 0x741FC49F, 0xE91025E9, 0xBF84911F, 0x228B7069, 0x5EEA55B2, 0xC3E5B4C4, + 0xA6281E04, 0x3B27FF72, 0x4746DAA9, 0xDA493BDF, 0xEA6FB345, 0x77605233, + 0x0B0177E8, 0x960E969E, 0xF3C33C5E, 0x6ECCDD28, 0x12ADF8F3, 0x8FA21985, + 0xD936AD73, 0x44394C05, 0x385869DE, 0xA55788A8, 0xC09A2268, 0x5D95C31E, + 0x21F4E6C5, 0xBCFB07B3, 0x8373EFE2, 0x1E7C0E94, 0x621D2B4F, 0xFF12CA39, + 0x9ADF60F9, 0x07D0818F, 0x7BB1A454, 0xE6BE4522, 0xB02AF1D4, 0x2D2510A2, + 0x51443579, 0xCC4BD40F, 0xA9867ECF, 0x34899FB9, 0x48E8BA62, 0xD5E75B14, + 0xE5C1D38E, 0x78CE32F8, 0x04AF1723, 0x99A0F655, 0xFC6D5C95, 0x6162BDE3, + 0x1D039838, 0x800C794E, 0xD698CDB8, 0x4B972CCE, 0x37F60915, 0xAAF9E863, + 0xCF3442A3, 0x523BA3D5, 0x2E5A860E, 0xB3556778, 0x4E17973A, 0xD318764C, + 0xAF795397, 0x3276B2E1, 0x57BB1821, 0xCAB4F957, 0xB6D5DC8C, 0x2BDA3DFA, + 0x7D4E890C, 0xE041687A, 0x9C204DA1, 0x012FACD7, 0x64E20617, 0xF9EDE761, + 0x858CC2BA, 0x188323CC, 0x28A5AB56, 0xB5AA4A20, 0xC9CB6FFB, 0x54C48E8D, + 0x3109244D, 0xAC06C53B, 0xD067E0E0, 0x4D680196, 0x1BFCB560, 0x86F35416, + 0xFA9271CD, 0x679D90BB, 0x02503A7B, 0x9F5FDB0D, 0xE33EFED6, 0x7E311FA0, + 0xC2CA1813, 0x5FC5F965, 0x23A4DCBE, 0xBEAB3DC8, 0xDB669708, 0x4669767E, + 0x3A0853A5, 0xA707B2D3, 0xF1930625, 0x6C9CE753, 0x10FDC288, 0x8DF223FE, + 0xE83F893E, 0x75306848, 0x09514D93, 0x945EACE5, 0xA478247F, 0x3977C509, + 0x4516E0D2, 0xD81901A4, 0xBDD4AB64, 0x20DB4A12, 0x5CBA6FC9, 0xC1B58EBF, + 0x97213A49, 0x0A2EDB3F, 0x764FFEE4, 0xEB401F92, 0x8E8DB552, 0x13825424, + 0x6FE371FF, 0xF2EC9089, 0x0FAE60CB, 0x92A181BD, 0xEEC0A466, 0x73CF4510, + 0x1602EFD0, 0x8B0D0EA6, 0xF76C2B7D, 0x6A63CA0B, 0x3CF77EFD, 0xA1F89F8B, + 0xDD99BA50, 0x40965B26, 0x255BF1E6, 0xB8541090, 0xC435354B, 0x593AD43D, + 0x691C5CA7, 0xF413BDD1, 0x8872980A, 0x157D797C, 0x70B0D3BC, 0xEDBF32CA, + 0x91DE1711, 0x0CD1F667, 0x5A454291, 0xC74AA3E7, 0xBB2B863C, 0x2624674A, + 0x43E9CD8A, 0xDEE62CFC, 0xA2870927, 0x3F88E851, + }, + + { + 0x00000000, 0xB9FBDBE8, 0xA886B191, 0x117D6A79, 0x8A7C6563, 0x3387BE8B, + 0x22FAD4F2, 0x9B010F1A, 0xCF89CC87, 0x7672176F, 0x670F7D16, 0xDEF4A6FE, + 0x45F5A9E4, 0xFC0E720C, 0xED731875, 0x5488C39D, 0x44629F4F, 0xFD9944A7, + 0xECE42EDE, 0x551FF536, 0xCE1EFA2C, 0x77E521C4, 0x66984BBD, 0xDF639055, + 0x8BEB53C8, 0x32108820, 0x236DE259, 0x9A9639B1, 0x019736AB, 0xB86CED43, + 0xA911873A, 0x10EA5CD2, 0x88C53E9E, 0x313EE576, 0x20438F0F, 0x99B854E7, + 0x02B95BFD, 0xBB428015, 0xAA3FEA6C, 0x13C43184, 0x474CF219, 0xFEB729F1, + 0xEFCA4388, 0x56319860, 0xCD30977A, 0x74CB4C92, 0x65B626EB, 0xDC4DFD03, + 0xCCA7A1D1, 0x755C7A39, 0x64211040, 0xDDDACBA8, 0x46DBC4B2, 0xFF201F5A, + 0xEE5D7523, 0x57A6AECB, 0x032E6D56, 0xBAD5B6BE, 0xABA8DCC7, 0x1253072F, + 0x89520835, 0x30A9D3DD, 0x21D4B9A4, 0x982F624C, 0xCAFB7B7D, 0x7300A095, + 0x627DCAEC, 0xDB861104, 0x40871E1E, 0xF97CC5F6, 0xE801AF8F, 0x51FA7467, + 0x0572B7FA, 0xBC896C12, 0xADF4066B, 0x140FDD83, 0x8F0ED299, 0x36F50971, + 0x27886308, 0x9E73B8E0, 0x8E99E432, 0x37623FDA, 0x261F55A3, 0x9FE48E4B, + 0x04E58151, 0xBD1E5AB9, 0xAC6330C0, 0x1598EB28, 0x411028B5, 0xF8EBF35D, + 0xE9969924, 0x506D42CC, 0xCB6C4DD6, 0x7297963E, 0x63EAFC47, 0xDA1127AF, + 0x423E45E3, 0xFBC59E0B, 0xEAB8F472, 0x53432F9A, 0xC8422080, 0x71B9FB68, + 0x60C49111, 0xD93F4AF9, 0x8DB78964, 0x344C528C, 0x253138F5, 0x9CCAE31D, + 0x07CBEC07, 0xBE3037EF, 0xAF4D5D96, 0x16B6867E, 0x065CDAAC, 0xBFA70144, + 0xAEDA6B3D, 0x1721B0D5, 0x8C20BFCF, 0x35DB6427, 0x24A60E5E, 0x9D5DD5B6, + 0xC9D5162B, 0x702ECDC3, 0x6153A7BA, 0xD8A87C52, 0x43A97348, 0xFA52A8A0, + 0xEB2FC2D9, 0x52D41931, 0x4E87F0BB, 0xF77C2B53, 0xE601412A, 0x5FFA9AC2, + 0xC4FB95D8, 0x7D004E30, 0x6C7D2449, 0xD586FFA1, 0x810E3C3C, 0x38F5E7D4, + 0x29888DAD, 0x90735645, 0x0B72595F, 0xB28982B7, 0xA3F4E8CE, 0x1A0F3326, + 0x0AE56FF4, 0xB31EB41C, 0xA263DE65, 0x1B98058D, 0x80990A97, 0x3962D17F, + 0x281FBB06, 0x91E460EE, 0xC56CA373, 0x7C97789B, 0x6DEA12E2, 0xD411C90A, + 0x4F10C610, 0xF6EB1DF8, 0xE7967781, 0x5E6DAC69, 0xC642CE25, 0x7FB915CD, + 0x6EC47FB4, 0xD73FA45C, 0x4C3EAB46, 0xF5C570AE, 0xE4B81AD7, 0x5D43C13F, + 0x09CB02A2, 0xB030D94A, 0xA14DB333, 0x18B668DB, 0x83B767C1, 0x3A4CBC29, + 0x2B31D650, 0x92CA0DB8, 0x8220516A, 0x3BDB8A82, 0x2AA6E0FB, 0x935D3B13, + 0x085C3409, 0xB1A7EFE1, 0xA0DA8598, 0x19215E70, 0x4DA99DED, 0xF4524605, + 0xE52F2C7C, 0x5CD4F794, 0xC7D5F88E, 0x7E2E2366, 0x6F53491F, 0xD6A892F7, + 0x847C8BC6, 0x3D87502E, 0x2CFA3A57, 0x9501E1BF, 0x0E00EEA5, 0xB7FB354D, + 0xA6865F34, 0x1F7D84DC, 0x4BF54741, 0xF20E9CA9, 0xE373F6D0, 0x5A882D38, + 0xC1892222, 0x7872F9CA, 0x690F93B3, 0xD0F4485B, 0xC01E1489, 0x79E5CF61, + 0x6898A518, 0xD1637EF0, 0x4A6271EA, 0xF399AA02, 0xE2E4C07B, 0x5B1F1B93, + 0x0F97D80E, 0xB66C03E6, 0xA711699F, 0x1EEAB277, 0x85EBBD6D, 0x3C106685, + 0x2D6D0CFC, 0x9496D714, 0x0CB9B558, 0xB5426EB0, 0xA43F04C9, 0x1DC4DF21, + 0x86C5D03B, 0x3F3E0BD3, 0x2E4361AA, 0x97B8BA42, 0xC33079DF, 0x7ACBA237, + 0x6BB6C84E, 0xD24D13A6, 0x494C1CBC, 0xF0B7C754, 0xE1CAAD2D, 0x583176C5, + 0x48DB2A17, 0xF120F1FF, 0xE05D9B86, 0x59A6406E, 0xC2A74F74, 0x7B5C949C, + 0x6A21FEE5, 0xD3DA250D, 0x8752E690, 0x3EA93D78, 0x2FD45701, 0x962F8CE9, + 0x0D2E83F3, 0xB4D5581B, 0xA5A83262, 0x1C53E98A, + }, + + { + 0x00000000, 0xAE689191, 0x87A02563, 0x29C8B4F2, 0xD4314C87, 0x7A59DD16, + 0x539169E4, 0xFDF9F875, 0x73139F4F, 0xDD7B0EDE, 0xF4B3BA2C, 0x5ADB2BBD, + 0xA722D3C8, 0x094A4259, 0x2082F6AB, 0x8EEA673A, 0xE6273E9E, 0x484FAF0F, + 0x61871BFD, 0xCFEF8A6C, 0x32167219, 0x9C7EE388, 0xB5B6577A, 0x1BDEC6EB, + 0x9534A1D1, 0x3B5C3040, 0x129484B2, 0xBCFC1523, 0x4105ED56, 0xEF6D7CC7, + 0xC6A5C835, 0x68CD59A4, 0x173F7B7D, 0xB957EAEC, 0x909F5E1E, 0x3EF7CF8F, + 0xC30E37FA, 0x6D66A66B, 0x44AE1299, 0xEAC68308, 0x642CE432, 0xCA4475A3, + 0xE38CC151, 0x4DE450C0, 0xB01DA8B5, 0x1E753924, 0x37BD8DD6, 0x99D51C47, + 0xF11845E3, 0x5F70D472, 0x76B86080, 0xD8D0F111, 0x25290964, 0x8B4198F5, + 0xA2892C07, 0x0CE1BD96, 0x820BDAAC, 0x2C634B3D, 0x05ABFFCF, 0xABC36E5E, + 0x563A962B, 0xF85207BA, 0xD19AB348, 0x7FF222D9, 0x2E7EF6FA, 0x8016676B, + 0xA9DED399, 0x07B64208, 0xFA4FBA7D, 0x54272BEC, 0x7DEF9F1E, 0xD3870E8F, + 0x5D6D69B5, 0xF305F824, 0xDACD4CD6, 0x74A5DD47, 0x895C2532, 0x2734B4A3, + 0x0EFC0051, 0xA09491C0, 0xC859C864, 0x663159F5, 0x4FF9ED07, 0xE1917C96, + 0x1C6884E3, 0xB2001572, 0x9BC8A180, 0x35A03011, 0xBB4A572B, 0x1522C6BA, + 0x3CEA7248, 0x9282E3D9, 0x6F7B1BAC, 0xC1138A3D, 0xE8DB3ECF, 0x46B3AF5E, + 0x39418D87, 0x97291C16, 0xBEE1A8E4, 0x10893975, 0xED70C100, 0x43185091, + 0x6AD0E463, 0xC4B875F2, 0x4A5212C8, 0xE43A8359, 0xCDF237AB, 0x639AA63A, + 0x9E635E4F, 0x300BCFDE, 0x19C37B2C, 0xB7ABEABD, 0xDF66B319, 0x710E2288, + 0x58C6967A, 0xF6AE07EB, 0x0B57FF9E, 0xA53F6E0F, 0x8CF7DAFD, 0x229F4B6C, + 0xAC752C56, 0x021DBDC7, 0x2BD50935, 0x85BD98A4, 0x784460D1, 0xD62CF140, + 0xFFE445B2, 0x518CD423, 0x5CFDEDF4, 0xF2957C65, 0xDB5DC897, 0x75355906, + 0x88CCA173, 0x26A430E2, 0x0F6C8410, 0xA1041581, 0x2FEE72BB, 0x8186E32A, + 0xA84E57D8, 0x0626C649, 0xFBDF3E3C, 0x55B7AFAD, 0x7C7F1B5F, 0xD2178ACE, + 0xBADAD36A, 0x14B242FB, 0x3D7AF609, 0x93126798, 0x6EEB9FED, 0xC0830E7C, + 0xE94BBA8E, 0x47232B1F, 0xC9C94C25, 0x67A1DDB4, 0x4E696946, 0xE001F8D7, + 0x1DF800A2, 0xB3909133, 0x9A5825C1, 0x3430B450, 0x4BC29689, 0xE5AA0718, + 0xCC62B3EA, 0x620A227B, 0x9FF3DA0E, 0x319B4B9F, 0x1853FF6D, 0xB63B6EFC, + 0x38D109C6, 0x96B99857, 0xBF712CA5, 0x1119BD34, 0xECE04541, 0x4288D4D0, + 0x6B406022, 0xC528F1B3, 0xADE5A817, 0x038D3986, 0x2A458D74, 0x842D1CE5, + 0x79D4E490, 0xD7BC7501, 0xFE74C1F3, 0x501C5062, 0xDEF63758, 0x709EA6C9, + 0x5956123B, 0xF73E83AA, 0x0AC77BDF, 0xA4AFEA4E, 0x8D675EBC, 0x230FCF2D, + 0x72831B0E, 0xDCEB8A9F, 0xF5233E6D, 0x5B4BAFFC, 0xA6B25789, 0x08DAC618, + 0x211272EA, 0x8F7AE37B, 0x01908441, 0xAFF815D0, 0x8630A122, 0x285830B3, + 0xD5A1C8C6, 0x7BC95957, 0x5201EDA5, 0xFC697C34, 0x94A42590, 0x3ACCB401, + 0x130400F3, 0xBD6C9162, 0x40956917, 0xEEFDF886, 0xC7354C74, 0x695DDDE5, + 0xE7B7BADF, 0x49DF2B4E, 0x60179FBC, 0xCE7F0E2D, 0x3386F658, 0x9DEE67C9, + 0xB426D33B, 0x1A4E42AA, 0x65BC6073, 0xCBD4F1E2, 0xE21C4510, 0x4C74D481, + 0xB18D2CF4, 0x1FE5BD65, 0x362D0997, 0x98459806, 0x16AFFF3C, 0xB8C76EAD, + 0x910FDA5F, 0x3F674BCE, 0xC29EB3BB, 0x6CF6222A, 0x453E96D8, 0xEB560749, + 0x839B5EED, 0x2DF3CF7C, 0x043B7B8E, 0xAA53EA1F, 0x57AA126A, 0xF9C283FB, + 0xD00A3709, 0x7E62A698, 0xF088C1A2, 0x5EE05033, 0x7728E4C1, 0xD9407550, + 0x24B98D25, 0x8AD11CB4, 0xA319A846, 0x0D7139D7, + } +# endif // CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 +}; +#endif // NO_LUT diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..cc643e1 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,94 @@ +cmake_minimum_required(VERSION 3.14) + +project(crc32Tests LANGUAGES C CXX) + +include(../cmake/project-is-top-level.cmake) +include(../cmake/folders.cmake) +include(../cmake/windows-set-path.cmake) + +if(PROJECT_IS_TOP_LEVEL) + find_package(crc32 REQUIRED) + enable_testing() +endif() + +if(NOT WIN32) + include(FetchContent) + + # Externally provided libraries + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG main) + + FetchContent_Declare( + googlebenchmark + GIT_REPOSITORY https://github.com/google/benchmark.git + GIT_TAG main) + + # set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + set(FOLDER_benchmark + "gbenchmark" + CACHE STRING "" FORCE) + set(FOLDER_gtest + "gtest" + CACHE STRING "" FORCE) + set(FOLDER_gmock + "gmock" + CACHE STRING "" FORCE) + set(FOLDER_googletest-distribution + "googletest-distribution" + CACHE STRING "" FORCE) + + # Disable tests on gtest + set(gtest_build_tests + OFF + CACHE BOOL "" FORCE) + set(gtest_build_samples + OFF + CACHE BOOL "" FORCE) + + # Disable tests on google benchmark + set(BENCHMARK_ENABLE_TESTING + OFF + CACHE BOOL "" FORCE) + set(BENCHMARK_ENABLE_WERROR + OFF + CACHE BOOL "" FORCE) + + set(BENCHMARK_ENABLE_INSTALL + OFF + CACHE BOOL "" FORCE) + + set(BENCHMARK_DOWNLOAD_DEPENDENCIES + ON + CACHE BOOL "" FORCE) + + set(CMAKE_CXX_CLANG_TIDY "") + + FetchContent_MakeAvailable(googletest googlebenchmark) + # Lib: gtest_main benchmark::benchmark benchmark::benchmark_main + # target_compile_features(crc32_test PRIVATE cxx_std_17) + + add_executable(crc32_bench source/crc32_bench.cpp) + target_link_libraries(crc32_bench PRIVATE crc32::crc32 + benchmark::benchmark_main) + option(BENCHMARK_TEST "RUN bench test with tests" OFF) + + if(BENCHMARK_TEST) + add_test(NAME crc32_bench COMMAND crc32_bench) + elseif() + message(STATUS "Disable crc32_bench, Performance benchmark test only run on Release/RelWithDebInfo/MinSizeRel") + endif() + + # windows_set_path(crc32_bench crc32::crc32 benchmark::benchmark_main) + + add_executable(crc32_test source/crc32_test.cpp) + target_link_libraries(crc32_test PRIVATE crc32::crc32 gtest_main) + add_test(NAME crc32_test COMMAND crc32_test) + # windows_set_path(crc32_test crc32::crc32 gtest_main) + + add_folders(Test) +else() + message(WARNING "Disable tests, only tested on Linux and MacOS x86_64") +endif() diff --git a/test/source/crc32_bench.cpp b/test/source/crc32_bench.cpp new file mode 100644 index 0000000..3f8d0fe --- /dev/null +++ b/test/source/crc32_bench.cpp @@ -0,0 +1,546 @@ +// ////////////////////////////////////////////////////////// +// crc32_bench.cpp +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Google benchmark contributed by Bensuperpc +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include +#include +#include +#include + +#include "crc32/crc32.hpp" + +extern "C" { +#include "crc32/crc32.h" +} + +#include + +static std::unique_ptr generate(const std::uint64_t length); + +static std::unique_ptr generate(const std::uint64_t length) +{ + uint32_t randomNumber = 0x27121978; + // initialize + std::unique_ptr data(new char[length]); + for (std::uint64_t i = 0; i < length; i++) { + data[i] = char(randomNumber & 0xFF); + // simple LCG, see + // http://en.wikipedia.org/wiki/Linear_congruential_generator + randomNumber = 1664525 * randomNumber + 1013904223; + } + return data; +} + +std::string random_string(std::string::size_type length) +{ + static auto& chrs = + "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + thread_local static std::mt19937 rg {std::random_device {}()}; + thread_local static std::uniform_int_distribution + pick(0, sizeof(chrs) - 2); + + std::string s; + + s.reserve(length); + + while (length--) + s += chrs[pick(rg)]; + + return s; +} + +static void crc32_fast_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_fast(str.get(), size, 0); + + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_fast_c_bench) + ->Name("crc32_c_fast") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_fast_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_fast(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_fast_bench) + ->Name("crc32_fast") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_bitwise_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_bitwise(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_bitwise_c_bench) + ->Name("crc32_bitwise_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_bitwise_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_bitwise(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_bitwise_bench) + ->Name("crc32_bitwise") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_bitwise_branch_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_bitwise_branch(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_bitwise_branch_c_bench) + ->Name("crc32_bitwise_c_branch") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_bitwise_branch_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_bitwise_branch(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_bitwise_branch_bench) + ->Name("crc32_bitwise_branch") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_halfbyte_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_halfbyte(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_halfbyte_c_bench) + ->Name("crc32_halfbyte_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_halfbyte_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_halfbyte(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_halfbyte_bench) + ->Name("crc32_halfbyte") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + +static void crc32_1byte_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_1byte_c_bench) + ->Name("crc32_1byte_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_1byte_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_1byte_bench) + ->Name("crc32_1byte") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_1byte_tableless_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte_tableless(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_1byte_tableless_c_bench) + ->Name("crc32_1byte_tableless_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_1byte_tableless_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte_tableless(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); + + // state.SetLabel("OK"); +} +BENCHMARK(crc32_1byte_tableless_bench) + ->Name("crc32_1byte_tableless") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_1byte_tableless2_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte_tableless2(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_1byte_tableless2_c_bench) + ->Name("crc32_1byte_tableless2_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_1byte_tableless2_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_1byte_tableless2(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_1byte_tableless2_bench) + ->Name("crc32_1byte_tableless2") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + +static void crc32_4bytes_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_4bytes(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_4bytes_c_bench) + ->Name("crc32_4bytes_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_4bytes_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_4bytes(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_4bytes_bench) + ->Name("crc32_4bytes") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + +static void crc32_8bytes_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_8bytes(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_8bytes_c_bench) + ->Name("crc32_8bytes_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_8bytes_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_8bytes(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_8bytes_bench) + ->Name("crc32_8bytes") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_4x8bytes_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_4x8bytes(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_4x8bytes_c_bench) + ->Name("crc32_4x8bytes_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_4x8bytes_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_4x8bytes(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_4x8bytes_bench) + ->Name("crc32_4x8bytes") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + +static void crc32_16bytes_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_16bytes(str.get(), size, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_16bytes_c_bench) + ->Name("crc32_16bytes_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_16bytes_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_16bytes(str, 0); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_16bytes_bench) + ->Name("crc32_16bytes") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_16bytes_prefetch_c_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + auto str = generate(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_16bytes_prefetch(str.get(), size, 0, 256); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_16bytes_prefetch_c_bench) + ->Name("crc32_16bytes_prefetch_c") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +static void crc32_16bytes_prefetch_bench(benchmark::State& state) +{ + // Code inside this loop is measured repeatedly + const auto size = state.range(0); + const std::string&& str = random_string(size); + + for (auto _ : state) { + benchmark::DoNotOptimize(str); + crc32::crc32_16bytes_prefetch(str, 0, 256); + benchmark::ClobberMemory(); + } + state.SetItemsProcessed(state.iterations()); + state.SetBytesProcessed(state.iterations() * size * sizeof(char)); +} +BENCHMARK(crc32_16bytes_prefetch_bench) + ->Name("crc32_16bytes_prefetch") + ->RangeMultiplier(100) + ->Range(1, 1000000000); + +#endif + +// Run the benchmark if not link with benchmark::benchmark_main +// BENCHMARK_MAIN(); diff --git a/test/source/crc32_test.cpp b/test/source/crc32_test.cpp new file mode 100644 index 0000000..e2ecd07 --- /dev/null +++ b/test/source/crc32_test.cpp @@ -0,0 +1,2159 @@ +// ////////////////////////////////////////////////////////// +// crc32_test.cpp +// Copyright (c) 2011-2021 Stephan Brumme. All rights reserved. +// Google test contributed by Bensuperpc +// see http://create.stephan-brumme.com/disclaimer.html +// + +#include // std::function +#include // std::string +#include // std::vector + +#include "crc32/crc32.hpp" + +#include "gtest/gtest.h" + +extern "C" { +#include "crc32/crc32.h" +} + +TEST(crc32, empty) +{ + const std::string str = ""; + const uint32_t expected_result = 0; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic1) +{ + const std::string str = "SHA3-512"; + const uint32_t expected_result = 0x95980D67; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic2) +{ + const std::string str = "Linux"; + const uint32_t expected_result = 0x53D0684B; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic3) +{ + const std::string str = "CRC32"; + const uint32_t expected_result = 0xF6151584; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic4) +{ + const std::string str = "0123456789"; + const uint32_t expected_result = 0xA684C7C6; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic5) +{ + const std::string str = "LGBTQIA+"; + const uint32_t expected_result = 0x5C9BD8DC; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, basic6) +{ + const std::string str = "Intergouvernementalisations"; + const uint32_t expected_result = 0x5DD186B5; + + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_bitwise_branch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_bitwise_branch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_bitwise_branch(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_halfbyte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_halfbyte(str.data(), str.size(), 0)); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + + EXPECT_EQ(expected_result, crc32::crc32_1byte(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_1byte_tableless2(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_1byte_tableless2(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_1byte_tableless2(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_8bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_4x8bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_4x8bytes(str.data(), str.size(), 0)); +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32_16bytes(str.data(), str.size(), 0)); + + EXPECT_EQ(expected_result, + crc32::crc32_16bytes_prefetch(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_16bytes_prefetch(str, 0)); + + // C functions + EXPECT_EQ(expected_result, + crc32_16bytes_prefetch(str.data(), str.size(), 0, 256)); +#endif + + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); + EXPECT_EQ(expected_result, crc32::crc32_fast(str, 0)); + + // C functions + EXPECT_EQ(expected_result, crc32::crc32_fast(str.data(), str.size(), 0)); +} + +TEST(crc32, advanced1) +{ + const std::string str = "git"; + const uint32_t expected_result = 0x518E617C; + + uint32_t result = 0; + + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes_prefetch(s.data(), 1, result, 256); + } + EXPECT_EQ(expected_result, result); + +#endif + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} + +TEST(crc32, advanced2) +{ + const std::string str = "ubuntu"; + const uint32_t expected_result = 0x7C4B9639; + + uint32_t result = 0; + + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes_prefetch(s.data(), 1, result, 256); + } + EXPECT_EQ(expected_result, result); + +#endif + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} + +TEST(crc32, advanced3) +{ + const std::string str = "Pneumonoultramicroscopicsilicovolcanoconiosis"; + const uint32_t expected_result = 0xD57FFD71; + + uint32_t result = 0; + + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes_prefetch(s.data(), 1, result, 256); + } + EXPECT_EQ(expected_result, result); + +#endif + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} + +TEST(crc32, advanced4) +{ + const std::string str = "azertyuiopqsdfghjklmwxcvbn"; + const uint32_t expected_result = 0xF36868CC; + + uint32_t result = 0; + + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes_prefetch(s.data(), 1, result, 256); + } + EXPECT_EQ(expected_result, result); + +#endif + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} + +TEST(crc32, advanced5) +{ + const std::string str = "+-*/#~|{}()=.,[]?;:!"; + const uint32_t expected_result = 0x98783B28; + + uint32_t result = 0; + + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_bitwise_branch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_bitwise_branch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_halfbyte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_halfbyte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_1byte_tableless2(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_1byte_tableless2(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_4x8bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_4x8bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + +#endif + +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_16bytes_prefetch(s.data(), 1, result, 256); + } + EXPECT_EQ(expected_result, result); + +#endif + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_fast(s, result); + } + EXPECT_EQ(expected_result, result); + + // C functions + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32_fast(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} + +/* +TEST(crc32, advanced_test1) +{ + const std::string str = "windows11"; + const uint32_t expected_result = 0xD93DD2EE; + + uint32_t result = 0; + + const std::vector> crc32_function = {crc32::crc32_bitwise, crc32::crc32_bitwise_branch, + crc32::crc32_halfbyte, +#ifdef CRC32_USE_LOOKUP_TABLE_BYTE + crc32::crc32_1byte, + crc32::crc32_1byte_tableless, + crc32::crc32_1byte_tableless2, +#endif +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_4 + crc32::crc32_4bytes, +#endif +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_8 + crc32::crc32_8bytes, + crc32::crc32_4x8bytes, +#endif +#ifdef CRC32_USE_LOOKUP_TABLE_SLICING_BY_16 + crc32::crc32_16bytes, +#endif + crc32::crc32_fast}; + + for (const auto& function : crc32_function) { + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = function(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); + } + + result = 0; + for (const char& c : str) { + const std::string s(1, c); + result = crc32::crc32_16bytes_prefetch(s.data(), 1, result); + } + EXPECT_EQ(expected_result, result); +} +*/ diff --git a/tools/dockcross-cmake-builder.sh b/tools/dockcross-cmake-builder.sh new file mode 100644 index 0000000..7175ecc --- /dev/null +++ b/tools/dockcross-cmake-builder.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +if (($# >= 1)); then + image_complet=$1 + image=${image_complet%:*} + tag=${image_complet#*:} + build_file=build-$image + shift 1 + + cmake_arg=$* + echo "cmake arg: $cmake_arg" + + echo "Pulling dockcross/$image" + if [ -z "${tag}" ]; then + docker pull "dockcross/$image:latest" + else + docker pull "dockcross/$image:$tag" + fi + + echo "Make script dockcross-$image" + docker run --rm dockcross/"$image" >./dockcross-"$image" + chmod +x ./dockcross-"$image" + + echo "Build $build_file" + ./dockcross-"$image" cmake -B "$build_file" -S . -G Ninja $cmake_arg + ./dockcross-"$image" ninja -C "$build_file" +else + echo "Usage: ${0##*/} " + exit 1 +fi diff --git a/tools/graphic.py b/tools/graphic.py new file mode 100644 index 0000000..fcca1b5 --- /dev/null +++ b/tools/graphic.py @@ -0,0 +1,64 @@ +# Based on work: https://int-i.github.io/python/2021-11-07/matplotlib-google-benchmark-visualization/ + +from argparse import ArgumentParser +from itertools import groupby +from cycler import cycler +from random import randint +import json +import math +import operator +import matplotlib as mpl +import matplotlib.pyplot as plt + + +def generate_color(size): + colors = [] + + for i in range(size): + colors.append('#%06X' % randint(0, 0xFFFFFF)) + + colors = sorted(set(colors), key=colors.index) # Remove all same elements + return colors + + +def extract_label_from_benchmark(benchmark): + bench_full_name = benchmark['name'] + bench_name = bench_full_name.split('/')[0] # Remove all after / + if (bench_name.startswith('BM_')): # Remove if string start with BM_ + return bench_name[3:] # Remove BM_ + else: + return bench_name + + +def extract_size_from_benchmark(benchmark): + bench_name = benchmark['name'] + return bench_name.split('/')[1] # Remove all before / + + +if __name__ == "__main__": + plt.rcParams['figure.figsize'] = [21, 12] + mpl.rcParams['axes.prop_cycle'] = cycler(color=generate_color(200)) + + parser = ArgumentParser() + parser.add_argument('path', help='benchmark result json file') + args = parser.parse_args() + + with open(args.path) as file: + benchmark_result = json.load(file) + benchmarks = benchmark_result['benchmarks'] + elapsed_times = groupby(benchmarks, extract_label_from_benchmark) + for key, group in elapsed_times: + benchmark = list(group) + x = list(map(extract_size_from_benchmark, benchmark)) + y = list(map(operator.itemgetter('bytes_per_second'), benchmark)) + #log_y = list(map(math.log, y)) + plt.plot(x, y, label=key, marker=None) + + plt.grid(color='green', linestyle='--', linewidth=0.2) # Add grid + plt.xlabel('Array size') + plt.ylabel('Gigabyte per second (GB/s)') + plt.title('CRC32 Algorithm Benchmark') + plt.legend() + plt.savefig('benchmark.png', bbox_inches='tight', dpi=300) + # plt.savefig('benchmark.svg') + plt.show() diff --git a/tools/ninja-builder.sh b/tools/ninja-builder.sh new file mode 100644 index 0000000..e4b92cf --- /dev/null +++ b/tools/ninja-builder.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +#export CC=/usr/bin/clang +#export CXX=/usr/bin/clang++ + +#--preset=dev --preset=dev-coverage -D CMAKE_BUILD_TYPE=Release -D CMAKE_CXX_STANDARD=17 + +cmake -S . -B build -G Ninja $* + +ninja -C build + +ctest --verbose --parallel $(nproc) --test-dir build