General refactor and cleanup.

This commit is contained in:
2024-04-30 15:12:48 +01:00
parent 552aa9da02
commit bd5051ce18
48 changed files with 1157 additions and 1290 deletions

View File

@@ -17,40 +17,40 @@ cmake_minimum_required(VERSION 3.15)
# License along with this library; if not, see <http://www.gnu.org/licenses/>. # License along with this library; if not, see <http://www.gnu.org/licenses/>.
if (APPLE) if (APPLE)
# Too early cmake has not yet set it # Too early cmake has not yet set it
if ((NOT DEFINED CMAKE_SYSTEM_PROCESSOR) AND (NOT DEFINED AARU_MACOS_TARGET_ARCH)) if ((NOT DEFINED CMAKE_SYSTEM_PROCESSOR) AND (NOT DEFINED AARU_MACOS_TARGET_ARCH))
execute_process(COMMAND uname -m OUTPUT_VARIABLE AARU_MACOS_TARGET_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND uname -m OUTPUT_VARIABLE AARU_MACOS_TARGET_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
endif () endif ()
if (NOT DEFINED AARU_MACOS_TARGET_ARCH) if (NOT DEFINED AARU_MACOS_TARGET_ARCH)
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Build architectures for macOS" FORCE) set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Build architectures for macOS" FORCE)
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm64")
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Build architectures for macOS" FORCE) set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Build architectures for macOS" FORCE)
else ()
message(FATAL_ERROR "Unknown system processor ${CMAKE_SYSTEM_PROCESSOR} for macOS")
endif ()
elseif (AARU_MACOS_TARGET_ARCH STREQUAL "x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Build architectures for macOS" FORCE)
elseif (AARU_MACOS_TARGET_ARCH STREQUAL "arm64")
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Build architectures for macOS" FORCE)
else () else ()
message(FATAL_ERROR "Unknown Aaru target architecture ${AARU_MACOS_TARGET_ARCH} for macOS") message(FATAL_ERROR "Unknown system processor ${CMAKE_SYSTEM_PROCESSOR} for macOS")
endif () endif ()
elseif (AARU_MACOS_TARGET_ARCH STREQUAL "x86_64")
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "Build architectures for macOS" FORCE)
elseif (AARU_MACOS_TARGET_ARCH STREQUAL "arm64")
set(CMAKE_OSX_ARCHITECTURES "arm64" CACHE STRING "Build architectures for macOS" FORCE)
else ()
message(FATAL_ERROR "Unknown Aaru target architecture ${AARU_MACOS_TARGET_ARCH} for macOS")
endif ()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version") set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
endif (APPLE) endif (APPLE)
project("Aaru.Checksums.Native" C) project("Aaru.Checksums.Native" C)
if ("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC" AND "${CMAKE_C_COMPILER_ARCHITECTURE_ID}" MATCHES "ARMV7") if ("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC" AND "${CMAKE_C_COMPILER_ARCHITECTURE_ID}" MATCHES "ARMV7")
set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD 11)
else () else ()
set(CMAKE_C_STANDARD 90) set(CMAKE_C_STANDARD 90)
endif () endif ()
if (DEFINED AARU_MACOS_TARGET_ARCH) if (DEFINED AARU_MACOS_TARGET_ARCH)
message("Requested target architecture: ${AARU_MACOS_TARGET_ARCH}") message("Requested target architecture: ${AARU_MACOS_TARGET_ARCH}")
endif () endif ()
message("Detected system processor: ${CMAKE_SYSTEM_PROCESSOR}") message("Detected system processor: ${CMAKE_SYSTEM_PROCESSOR}")
message("Detected vs platform name: ${CMAKE_C_COMPILER_ARCHITECTURE_ID}") message("Detected vs platform name: ${CMAKE_C_COMPILER_ARCHITECTURE_ID}")
@@ -59,57 +59,57 @@ message("Detected build type: ${CMAKE_BUILD_TYPE}")
message("Detected platform: ${CMAKE_C_PLATFORM_ID}") message("Detected platform: ${CMAKE_C_PLATFORM_ID}")
if ("${CMAKE_BUILD_TYPE}" MATCHES "Release" OR "${CMAKE_BUILD_TYPE}" MATCHES "RelWithDebInfo" OR "${CMAKE_BUILD_TYPE}" MATCHES "MinSizeRel") if ("${CMAKE_BUILD_TYPE}" MATCHES "Release" OR "${CMAKE_BUILD_TYPE}" MATCHES "RelWithDebInfo" OR "${CMAKE_BUILD_TYPE}" MATCHES "MinSizeRel")
if ("${CMAKE_BUILD_TYPE}" MATCHES "Release") if ("${CMAKE_BUILD_TYPE}" MATCHES "Release")
add_compile_definitions(NDEBUG) add_compile_definitions(NDEBUG)
endif ()
if ("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC")
add_compile_options("/O2 /Ob2 /Oi /Ot /Oy /Og /fp:fast")
if (${CMAKE_C_COMPILER_ARCHITECTURE_ID} MATCHES "X86")
add_compile_options("/arch:SSE2")
elseif (${CMAKE_C_COMPILER_ARCHITECTURE_ID} MATCHES "ARM")
add_compile_options("/arch:VFPv4")
endif ()
else ()
add_compile_options(-ffast-math -Ofast)
if ("${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang")
if (${AARU_MACOS_TARGET_ARCH} MATCHES "x86_64")
add_compile_options(-march=ivybridge -mtune=westmere -msse4.2)
elseif (${AARU_MACOS_TARGET_ARCH} MATCHES "arm64")
add_compile_options(-mcpu=apple-m1 -mtune=apple-m1)
endif ()
endif () endif ()
if ("${CMAKE_C_COMPILER_ID}" MATCHES "MSVC") if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i686" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64")
add_compile_options("/O2 /Ob2 /Oi /Ot /Oy /Og /fp:fast") if (NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang")
if (${CMAKE_C_COMPILER_ARCHITECTURE_ID} MATCHES "X86") add_compile_options(-march=westmere -mtune=skylake -mfpmath=sse)
add_compile_options("/arch:SSE2") add_compile_options(-msse4.2)
elseif (${CMAKE_C_COMPILER_ARCHITECTURE_ID} MATCHES "ARM") endif ()
add_compile_options("/arch:VFPv4")
endif ()
else ()
add_compile_options(-ffast-math -Ofast)
if ("${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang") if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
if (${AARU_MACOS_TARGET_ARCH} MATCHES "x86_64") add_compile_options(-flto)
add_compile_options(-march=ivybridge -mtune=westmere -msse4.2) endif ()
elseif (${AARU_MACOS_TARGET_ARCH} MATCHES "arm64") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64")
add_compile_options(-mcpu=apple-m1 -mtune=apple-m1) if (NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang")
endif () add_compile_options(-mtune=cortex-a53)
endif () endif ()
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i686" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
if (NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang") add_compile_options(-flto)
add_compile_options(-march=westmere -mtune=skylake -mfpmath=sse) endif ()
add_compile_options(-msse4.2) elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv7l" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm" AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang")
endif () if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
add_compile_options(-mtune=cortex-a53 -mcpu=cortex-a7)
if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW") else ()
add_compile_options(-flto) add_compile_options(-mtune=cortex-a53 -march=armv7-a+neon-vfpv4)
endif () endif ()
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips")
if (NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang") if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
add_compile_options(-mtune=cortex-a53) add_compile_options(-flto)
endif () endif ()
if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
add_compile_options(-flto)
endif ()
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv7l" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm" AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "AppleClang")
if ("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
add_compile_options(-mtune=cortex-a53 -mcpu=cortex-a7)
else ()
add_compile_options(-mtune=cortex-a53 -march=armv7-a+neon-vfpv4)
endif ()
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips")
if (NOT "${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW")
add_compile_options(-flto)
endif ()
endif ()
endif () endif ()
endif ()
endif () endif ()
add_library("Aaru.Checksums.Native" SHARED adler32.h adler32.c crc16.h crc16.c crc16_ccitt.h crc16_ccitt.c crc32.c crc32.h crc64.c crc64.h fletcher16.h fletcher16.c fletcher16_avx2.c fletcher16_neon.c fletcher16_ssse3.c fletcher32.h fletcher32.c fletcher32_avx2.c fletcher32_neon.c fletcher32_ssse3.c library.h spamsum.c spamsum.h crc32_clmul.c crc64_clmul.c simd.c simd.h adler32_ssse3.c adler32_avx2.c adler32_neon.c crc32_arm_simd.c crc32_vmull.c crc32_simd.h arm_vmull.c arm_vmull.h crc64_vmull.c library.c) add_library("Aaru.Checksums.Native" SHARED adler32.h adler32.c crc16.h crc16.c crc16_ccitt.h crc16_ccitt.c crc32.c crc32.h crc64.c crc64.h fletcher16.h fletcher16.c fletcher16_avx2.c fletcher16_neon.c fletcher16_ssse3.c fletcher32.h fletcher32.c fletcher32_avx2.c fletcher32_neon.c fletcher32_ssse3.c library.h spamsum.c spamsum.h crc32_clmul.c crc64_clmul.c simd.c simd.h adler32_ssse3.c adler32_avx2.c adler32_neon.c crc32_arm_simd.c crc32_vmull.c crc32_simd.h arm_vmull.c arm_vmull.h crc64_vmull.c library.c)

View File

@@ -1,51 +1,51 @@
{ {
"configurations": [ "configurations": [
{ {
"name": "x64-Debug", "name": "x64-Debug",
"generator": "Ninja", "generator": "Ninja",
"configurationType": "Debug", "configurationType": "Debug",
"inheritEnvironments": [ "msvc_x64_x64" ], "inheritEnvironments": ["msvc_x64_x64"],
"buildRoot": "${projectDir}\\out\\build\\${name}", "buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "", "cmakeCommandArgs": "",
"buildCommandArgs": "", "buildCommandArgs": "",
"ctestCommandArgs": "" "ctestCommandArgs": ""
}, },
{ {
"name": "arm-Debug", "name": "arm-Debug",
"generator": "Ninja", "generator": "Ninja",
"configurationType": "Debug", "configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}", "buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "", "cmakeCommandArgs": "",
"buildCommandArgs": "", "buildCommandArgs": "",
"ctestCommandArgs": "", "ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_arm_x64" ], "inheritEnvironments": ["msvc_arm_x64"],
"variables": [] "variables": []
}, },
{ {
"name": "arm64-Debug", "name": "arm64-Debug",
"generator": "Ninja", "generator": "Ninja",
"configurationType": "Debug", "configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}", "buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "", "cmakeCommandArgs": "",
"buildCommandArgs": "", "buildCommandArgs": "",
"ctestCommandArgs": "", "ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_arm64_x64" ], "inheritEnvironments": ["msvc_arm64_x64"],
"variables": [] "variables": []
}, },
{ {
"name": "x86-Debug", "name": "x86-Debug",
"generator": "Ninja", "generator": "Ninja",
"configurationType": "Debug", "configurationType": "Debug",
"buildRoot": "${projectDir}\\out\\build\\${name}", "buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "", "cmakeCommandArgs": "",
"buildCommandArgs": "", "buildCommandArgs": "",
"ctestCommandArgs": "", "ctestCommandArgs": "",
"inheritEnvironments": [ "msvc_x86_x64" ], "inheritEnvironments": ["msvc_x86_x64"],
"variables": [] "variables": []
} }
] ]
} }

View File

@@ -6,9 +6,11 @@ The purpose of this library is to provide checksums and hashing algorithms for A
No archiver processing code should fall here, those go in [Aaru.Checksums](https://github.com/aaru-dps/Aaru.Checksums). No archiver processing code should fall here, those go in [Aaru.Checksums](https://github.com/aaru-dps/Aaru.Checksums).
To build you just need Docker on Linux and run `build.sh`, that will generate a NuGet package for use with Aaru.Checksums. To build you just need Docker on Linux and run `build.sh`, that will generate a NuGet package for use with
Aaru.Checksums.
Currently implemented algorithms are: Currently implemented algorithms are:
- Adler-32 - Adler-32
- CRC-16 (CCITT and IBM polynomials) - CRC-16 (CCITT and IBM polynomials)
- CRC-32 (ISO polynomial) - CRC-32 (ISO polynomial)

View File

@@ -147,8 +147,7 @@ AARU_EXPORT void AARU_CALL adler32_slicing(uint16_t *sum1, uint16_t *sum2, const
{ {
len -= NMAX; len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */ n = NMAX / 16; /* NMAX is divisible by 16 */
do do {
{
s1 += data[0]; s1 += data[0];
s2 += s1; s2 += s1;
s1 += data[0 + 1]; s1 += data[0 + 1];
@@ -184,8 +183,7 @@ AARU_EXPORT void AARU_CALL adler32_slicing(uint16_t *sum1, uint16_t *sum2, const
/* 16 sums unrolled */ /* 16 sums unrolled */
data += 16; data += 16;
} } while(--n);
while(--n);
s1 %= ADLER_MODULE; s1 %= ADLER_MODULE;
s2 %= ADLER_MODULE; s2 %= ADLER_MODULE;
} }

View File

@@ -21,7 +21,7 @@
#define ADLER_MODULE 65521 #define ADLER_MODULE 65521
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(ADLER_MODULE-1) <= 2^32-1 */ /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(ADLER_MODULE-1) <= 2^32-1 */
#define NMAX 5552 #define NMAX 5552
typedef struct typedef struct
{ {
@@ -30,16 +30,16 @@ typedef struct
} adler32_ctx; } adler32_ctx;
AARU_EXPORT adler32_ctx *AARU_CALL adler32_init(); AARU_EXPORT adler32_ctx *AARU_CALL adler32_init();
AARU_EXPORT int AARU_CALL adler32_update(adler32_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL adler32_update(adler32_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL adler32_final(adler32_ctx *ctx, uint32_t *checksum); AARU_EXPORT int AARU_CALL adler32_final(adler32_ctx *ctx, uint32_t *checksum);
AARU_EXPORT void AARU_CALL adler32_free(adler32_ctx *ctx); AARU_EXPORT void AARU_CALL adler32_free(adler32_ctx *ctx);
AARU_EXPORT void AARU_CALL adler32_slicing(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len); AARU_EXPORT void AARU_CALL adler32_slicing(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len); long len);
AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len); AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len);
#endif #endif
@@ -50,4 +50,4 @@ AARU_EXPORT void AARU_CALL adler32_neon(uint16_t *sum1, uint16_t *sum2, const ui
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_ADLER32_H #endif // AARU_CHECKSUMS_NATIVE_ADLER32_H

View File

@@ -63,38 +63,8 @@ AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_
if(n > blocks) n = (unsigned)blocks; if(n > blocks) n = (unsigned)blocks;
blocks -= n; blocks -= n;
const __m256i tap = _mm256_set_epi8(1, const __m256i tap = _mm256_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32);
const __m256i zero = _mm256_setzero_si256(); const __m256i zero = _mm256_setzero_si256();
const __m256i ones = _mm256_set1_epi16(1); const __m256i ones = _mm256_set1_epi16(1);
@@ -105,8 +75,7 @@ AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_
__m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n)); __m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n));
__m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2); __m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2);
__m256i v_s1 = _mm256_setzero_si256(); __m256i v_s1 = _mm256_setzero_si256();
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -115,24 +84,23 @@ AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm256_add_epi32(v_ps, v_s1); v_ps = _mm256_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero)); v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero));
const __m256i mad = _mm256_maddubs_epi16(bytes, tap); const __m256i mad = _mm256_maddubs_epi16(bytes, tap);
v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones)); v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n);
__m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1)); __m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1));
__m128i hi = _mm_unpackhi_epi64(sum, sum); __m128i hi = _mm_unpackhi_epi64(sum, sum);
sum = _mm_add_epi32(hi, sum); sum = _mm_add_epi32(hi, sum);
hi = _mm_shuffle_epi32(sum, 177); hi = _mm_shuffle_epi32(sum, 177);
sum = _mm_add_epi32(sum, hi); sum = _mm_add_epi32(sum, hi);
s1 += _mm_cvtsi128_si32(sum); s1 += _mm_cvtsi128_si32(sum);
v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5)); v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5));
@@ -176,8 +144,7 @@ AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL adler32_avx2(uint16_t *sum1, uint16_
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE; if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE;
s2 %= ADLER_MODULE; s2 %= ADLER_MODULE;
} }

View File

@@ -88,8 +88,12 @@ TARGET_WITH_NEON void adler32_neon(uint16_t *sum1, uint16_t *sum2, const uint8_t
* processed before s2 must be reduced modulo ADLER_MODULE. * processed before s2 must be reduced modulo ADLER_MODULE.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
uint32x4_t v_s2 = {.n128_u32 = {0, 0, 0, s1 * n}}; uint32x4_t v_s2 = {
uint32x4_t v_s1 = {.n128_u32 = {0, 0, 0, 0}}; .n128_u32 = {0, 0, 0, s1 * n}
};
uint32x4_t v_s1 = {
.n128_u32 = {0, 0, 0, 0}
};
#else #else
uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n}; uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n};
uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0}; uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0};
@@ -98,8 +102,7 @@ TARGET_WITH_NEON void adler32_neon(uint16_t *sum1, uint16_t *sum2, const uint8_t
uint16x8_t v_column_sum_2 = vdupq_n_u16(0); uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
uint16x8_t v_column_sum_3 = vdupq_n_u16(0); uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
uint16x8_t v_column_sum_4 = vdupq_n_u16(0); uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -108,22 +111,21 @@ TARGET_WITH_NEON void adler32_neon(uint16_t *sum1, uint16_t *sum2, const uint8_t
/* /*
* Add previous block byte sum to v_s2. * Add previous block byte sum to v_s2.
*/ */
v_s2 = vaddq_u32(v_s2, v_s1); v_s2 = vaddq_u32(v_s2, v_s1);
/* /*
* Horizontally add the bytes for s1. * Horizontally add the bytes for s1.
*/ */
v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
/* /*
* Vertically add the bytes for s2. * Vertically add the bytes for s2.
*/ */
v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1)); v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1));
v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2)); v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2));
v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = vshlq_n_u32(v_s2, 5);
v_s2 = vshlq_n_u32(v_s2, 5);
/* /*
* Multiply-add bytes by [ 32, 31, 30, ... ] for s2. * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
*/ */
@@ -198,8 +200,7 @@ TARGET_WITH_NEON void adler32_neon(uint16_t *sum1, uint16_t *sum2, const uint8_t
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE; if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE;
s2 %= ADLER_MODULE; s2 %= ADLER_MODULE;
} }

View File

@@ -39,7 +39,6 @@
#include "library.h" #include "library.h"
#include "adler32.h" #include "adler32.h"
/** /**
* @brief Calculate Adler-32 checksum for a given data using SSSE3 instructions. * @brief Calculate Adler-32 checksum for a given data using SSSE3 instructions.
* *
@@ -50,8 +49,8 @@
* @param data Pointer to the data buffer. * @param data Pointer to the data buffer.
* @param len Length of the data buffer in bytes. * @param len Length of the data buffer in bytes.
*/ */
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len) long len)
{ {
uint32_t s1 = *sum1; uint32_t s1 = *sum1;
uint32_t s2 = *sum2; uint32_t s2 = *sum2;
@@ -80,8 +79,7 @@ adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
__m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n); __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
__m128i v_s2 = _mm_set_epi32(0, 0, 0, s2); __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
__m128i v_s1 = _mm_set_epi32(0, 0, 0, 0); __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -90,21 +88,20 @@ adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm_add_epi32(v_ps, v_s1); v_ps = _mm_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1); const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2); const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
/* /*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2). * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/ */
@@ -151,8 +148,7 @@ adler32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE; if(s1 >= ADLER_MODULE) s1 -= ADLER_MODULE;
s2 %= ADLER_MODULE; s2 %= ADLER_MODULE;
} }

View File

@@ -73,19 +73,19 @@ TARGET_WITH_NEON uint64x2_t sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff), vcreate_u8(0x0000000000000000)); uint8x16_t k16_00 = vcombine_u8(vcreate_u8(0x000000000000ffff), vcreate_u8(0x0000000000000000));
// Do the multiplies, rotating with vext to get all combinations // Do the multiplies, rotating with vext to get all combinations
uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0 uint8x16_t d = vreinterpretq_u8_p16(vmull_p8(a, b)); // D = A0 * B0
uint8x16_t e = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1 uint8x16_t e = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 1))); // E = A0 * B1
uint8x16_t f = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0 uint8x16_t f = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 1), b)); // F = A1 * B0
uint8x16_t g = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2 uint8x16_t g = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 2))); // G = A0 * B2
uint8x16_t h = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0 uint8x16_t h = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 2), b)); // H = A2 * B0
uint8x16_t i = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3 uint8x16_t i = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 3))); // I = A0 * B3
uint8x16_t j = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0 uint8x16_t j = vreinterpretq_u8_p16(vmull_p8(vext_p8(a, a, 3), b)); // J = A3 * B0
uint8x16_t k = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4 uint8x16_t k = vreinterpretq_u8_p16(vmull_p8(a, vext_p8(b, b, 4))); // L = A0 * B4
// Add cross products // Add cross products
uint8x16_t l = veorq_u8(e, f); // L = E + F uint8x16_t l = veorq_u8(e, f); // L = E + F
uint8x16_t m = veorq_u8(g, h); // M = G + H uint8x16_t m = veorq_u8(g, h); // M = G + H
uint8x16_t n = veorq_u8(i, j); // N = I + J uint8x16_t n = veorq_u8(i, j); // N = I + J
// Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL // Interleave. Using vzip1 and vzip2 prevents Clang from emitting TBL
// instructions. // instructions.
@@ -125,10 +125,10 @@ TARGET_WITH_NEON uint64x2_t sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h)); uint8x16_t t2 = vcombine_u8(vget_low_u8(t2t3_l), vget_low_u8(t2t3_h));
#endif #endif
// Shift the cross products // Shift the cross products
uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8 uint8x16_t t0_shift = vextq_u8(t0, t0, 15); // t0 << 8
uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16 uint8x16_t t1_shift = vextq_u8(t1, t1, 14); // t1 << 16
uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24 uint8x16_t t2_shift = vextq_u8(t2, t2, 13); // t2 << 24
uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32 uint8x16_t t3_shift = vextq_u8(t3, t3, 12); // t3 << 32
// Accumulate the products // Accumulate the products
uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift); uint8x16_t cross1 = veorq_u8(t0_shift, t1_shift);
@@ -140,16 +140,16 @@ TARGET_WITH_NEON uint64x2_t sse2neon_vmull_p64(uint64x1_t _a, uint64x1_t _b)
TARGET_WITH_NEON uint64x2_t mm_shuffle_epi8(uint64x2_t a, uint64x2_t b) TARGET_WITH_NEON uint64x2_t mm_shuffle_epi8(uint64x2_t a, uint64x2_t b)
{ {
uint8x16_t tbl = vreinterpretq_u8_u64(a); // input a uint8x16_t tbl = vreinterpretq_u8_u64(a); // input a
uint8x16_t idx = vreinterpretq_u8_u64(b); // input b uint8x16_t idx = vreinterpretq_u8_u64(b); // input b
uint8x16_t idx_masked = vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits uint8x16_t idx_masked = vandq_u8(idx, vdupq_n_u8(0x8F)); // avoid using meaningless bits
#if defined(__aarch64__) || defined(_M_ARM64) #if defined(__aarch64__) || defined(_M_ARM64)
return vreinterpretq_u64_u8(vqtbl1q_u8(tbl, idx_masked)); return vreinterpretq_u64_u8(vqtbl1q_u8(tbl, idx_masked));
#else #else
// use this line if testing on aarch64 // use this line if testing on aarch64
uint8x8x2_t a_split = {vget_low_u8(tbl), vget_high_u8(tbl)}; uint8x8x2_t a_split = {vget_low_u8(tbl), vget_high_u8(tbl)};
return vreinterpretq_u64_u8( return vreinterpretq_u64_u8(
vcombine_u8(vtbl2_u8(a_split, vget_low_u8(idx_masked)), vtbl2_u8(a_split, vget_high_u8(idx_masked)))); vcombine_u8(vtbl2_u8(a_split, vget_low_u8(idx_masked)), vtbl2_u8(a_split, vget_high_u8(idx_masked))));
#endif #endif
} }

View File

@@ -29,4 +29,4 @@ TARGET_WITH_NEON uint64x2_t mm_slli_si128(uint64x2_t a, int imm);
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_ARM_VMULL_H #endif // AARU_CHECKSUMS_NATIVE_ARM_VMULL_H

10
crc16.c
View File

@@ -64,12 +64,12 @@ AARU_EXPORT int AARU_CALL crc16_update(crc16_ctx *ctx, const uint8_t *data, uint
if(!ctx || !data) return -1; if(!ctx || !data) return -1;
uint16_t crc; uint16_t crc;
const uint32_t *current; const uint32_t *current;
const uint8_t *current_char = data; const uint8_t *current_char = data;
const size_t unroll = 4; const size_t unroll = 4;
const size_t bytes_at_once = 8 * unroll; const size_t bytes_at_once = 8 * unroll;
uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3; uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3;
crc = ctx->crc; crc = ctx->crc;

313
crc16.h
View File

@@ -25,162 +25,163 @@ typedef struct
} crc16_ctx; } crc16_ctx;
const uint16_t crc16_table[8][256] = { const uint16_t crc16_table[8][256] = {
{0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, {0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1,
0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,
0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1,
0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1,
0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,
0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1,
0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0,
0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,
0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0,
0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1,
0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,
0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0,
0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0,
0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,
0x4100, 0x81C1, 0x8081, 0x4040}, 0x4100, 0x81C1, 0x8081, 0x4040},
{0x0000, 0x9001, 0x6001, 0xF000, 0xC002, 0x5003, 0xA003, 0x3002, 0xC007, 0x5006, 0xA006, 0x3007, 0x0005, 0x9004, {0x0000, 0x9001, 0x6001, 0xF000, 0xC002, 0x5003, 0xA003, 0x3002, 0xC007, 0x5006, 0xA006, 0x3007, 0x0005, 0x9004,
0x6004, 0xF005, 0xC00D, 0x500C, 0xA00C, 0x300D, 0x000F, 0x900E, 0x600E, 0xF00F, 0x000A, 0x900B, 0x600B, 0xF00A, 0x6004, 0xF005, 0xC00D, 0x500C, 0xA00C, 0x300D, 0x000F, 0x900E, 0x600E, 0xF00F, 0x000A, 0x900B, 0x600B, 0xF00A,
0xC008, 0x5009, 0xA009, 0x3008, 0xC019, 0x5018, 0xA018, 0x3019, 0x001B, 0x901A, 0x601A, 0xF01B, 0x001E, 0x901F, 0xC008, 0x5009, 0xA009, 0x3008, 0xC019, 0x5018, 0xA018, 0x3019, 0x001B, 0x901A, 0x601A, 0xF01B, 0x001E, 0x901F,
0x601F, 0xF01E, 0xC01C, 0x501D, 0xA01D, 0x301C, 0x0014, 0x9015, 0x6015, 0xF014, 0xC016, 0x5017, 0xA017, 0x3016, 0x601F, 0xF01E, 0xC01C, 0x501D, 0xA01D, 0x301C, 0x0014, 0x9015, 0x6015, 0xF014, 0xC016, 0x5017, 0xA017, 0x3016,
0xC013, 0x5012, 0xA012, 0x3013, 0x0011, 0x9010, 0x6010, 0xF011, 0xC031, 0x5030, 0xA030, 0x3031, 0x0033, 0x9032, 0xC013, 0x5012, 0xA012, 0x3013, 0x0011, 0x9010, 0x6010, 0xF011, 0xC031, 0x5030, 0xA030, 0x3031, 0x0033, 0x9032,
0x6032, 0xF033, 0x0036, 0x9037, 0x6037, 0xF036, 0xC034, 0x5035, 0xA035, 0x3034, 0x003C, 0x903D, 0x603D, 0xF03C, 0x6032, 0xF033, 0x0036, 0x9037, 0x6037, 0xF036, 0xC034, 0x5035, 0xA035, 0x3034, 0x003C, 0x903D, 0x603D, 0xF03C,
0xC03E, 0x503F, 0xA03F, 0x303E, 0xC03B, 0x503A, 0xA03A, 0x303B, 0x0039, 0x9038, 0x6038, 0xF039, 0x0028, 0x9029, 0xC03E, 0x503F, 0xA03F, 0x303E, 0xC03B, 0x503A, 0xA03A, 0x303B, 0x0039, 0x9038, 0x6038, 0xF039, 0x0028, 0x9029,
0x6029, 0xF028, 0xC02A, 0x502B, 0xA02B, 0x302A, 0xC02F, 0x502E, 0xA02E, 0x302F, 0x002D, 0x902C, 0x602C, 0xF02D, 0x6029, 0xF028, 0xC02A, 0x502B, 0xA02B, 0x302A, 0xC02F, 0x502E, 0xA02E, 0x302F, 0x002D, 0x902C, 0x602C, 0xF02D,
0xC025, 0x5024, 0xA024, 0x3025, 0x0027, 0x9026, 0x6026, 0xF027, 0x0022, 0x9023, 0x6023, 0xF022, 0xC020, 0x5021, 0xC025, 0x5024, 0xA024, 0x3025, 0x0027, 0x9026, 0x6026, 0xF027, 0x0022, 0x9023, 0x6023, 0xF022, 0xC020, 0x5021,
0xA021, 0x3020, 0xC061, 0x5060, 0xA060, 0x3061, 0x0063, 0x9062, 0x6062, 0xF063, 0x0066, 0x9067, 0x6067, 0xF066, 0xA021, 0x3020, 0xC061, 0x5060, 0xA060, 0x3061, 0x0063, 0x9062, 0x6062, 0xF063, 0x0066, 0x9067, 0x6067, 0xF066,
0xC064, 0x5065, 0xA065, 0x3064, 0x006C, 0x906D, 0x606D, 0xF06C, 0xC06E, 0x506F, 0xA06F, 0x306E, 0xC06B, 0x506A, 0xC064, 0x5065, 0xA065, 0x3064, 0x006C, 0x906D, 0x606D, 0xF06C, 0xC06E, 0x506F, 0xA06F, 0x306E, 0xC06B, 0x506A,
0xA06A, 0x306B, 0x0069, 0x9068, 0x6068, 0xF069, 0x0078, 0x9079, 0x6079, 0xF078, 0xC07A, 0x507B, 0xA07B, 0x307A, 0xA06A, 0x306B, 0x0069, 0x9068, 0x6068, 0xF069, 0x0078, 0x9079, 0x6079, 0xF078, 0xC07A, 0x507B, 0xA07B, 0x307A,
0xC07F, 0x507E, 0xA07E, 0x307F, 0x007D, 0x907C, 0x607C, 0xF07D, 0xC075, 0x5074, 0xA074, 0x3075, 0x0077, 0x9076, 0xC07F, 0x507E, 0xA07E, 0x307F, 0x007D, 0x907C, 0x607C, 0xF07D, 0xC075, 0x5074, 0xA074, 0x3075, 0x0077, 0x9076,
0x6076, 0xF077, 0x0072, 0x9073, 0x6073, 0xF072, 0xC070, 0x5071, 0xA071, 0x3070, 0x0050, 0x9051, 0x6051, 0xF050, 0x6076, 0xF077, 0x0072, 0x9073, 0x6073, 0xF072, 0xC070, 0x5071, 0xA071, 0x3070, 0x0050, 0x9051, 0x6051, 0xF050,
0xC052, 0x5053, 0xA053, 0x3052, 0xC057, 0x5056, 0xA056, 0x3057, 0x0055, 0x9054, 0x6054, 0xF055, 0xC05D, 0x505C, 0xC052, 0x5053, 0xA053, 0x3052, 0xC057, 0x5056, 0xA056, 0x3057, 0x0055, 0x9054, 0x6054, 0xF055, 0xC05D, 0x505C,
0xA05C, 0x305D, 0x005F, 0x905E, 0x605E, 0xF05F, 0x005A, 0x905B, 0x605B, 0xF05A, 0xC058, 0x5059, 0xA059, 0x3058, 0xA05C, 0x305D, 0x005F, 0x905E, 0x605E, 0xF05F, 0x005A, 0x905B, 0x605B, 0xF05A, 0xC058, 0x5059, 0xA059, 0x3058,
0xC049, 0x5048, 0xA048, 0x3049, 0x004B, 0x904A, 0x604A, 0xF04B, 0x004E, 0x904F, 0x604F, 0xF04E, 0xC04C, 0x504D, 0xC049, 0x5048, 0xA048, 0x3049, 0x004B, 0x904A, 0x604A, 0xF04B, 0x004E, 0x904F, 0x604F, 0xF04E, 0xC04C, 0x504D,
0xA04D, 0x304C, 0x0044, 0x9045, 0x6045, 0xF044, 0xC046, 0x5047, 0xA047, 0x3046, 0xC043, 0x5042, 0xA042, 0x3043, 0xA04D, 0x304C, 0x0044, 0x9045, 0x6045, 0xF044, 0xC046, 0x5047, 0xA047, 0x3046, 0xC043, 0x5042, 0xA042, 0x3043,
0x0041, 0x9040, 0x6040, 0xF041}, 0x0041, 0x9040, 0x6040, 0xF041},
{0x0000, 0xC051, 0xC0A1, 0x00F0, 0xC141, 0x0110, 0x01E0, 0xC1B1, 0xC281, 0x02D0, 0x0220, 0xC271, 0x03C0, 0xC391, {0x0000, 0xC051, 0xC0A1, 0x00F0, 0xC141, 0x0110, 0x01E0, 0xC1B1, 0xC281, 0x02D0, 0x0220, 0xC271, 0x03C0, 0xC391,
0xC361, 0x0330, 0xC501, 0x0550, 0x05A0, 0xC5F1, 0x0440, 0xC411, 0xC4E1, 0x04B0, 0x0780, 0xC7D1, 0xC721, 0x0770, 0xC361, 0x0330, 0xC501, 0x0550, 0x05A0, 0xC5F1, 0x0440, 0xC411, 0xC4E1, 0x04B0, 0x0780, 0xC7D1, 0xC721, 0x0770,
0xC6C1, 0x0690, 0x0660, 0xC631, 0xCA01, 0x0A50, 0x0AA0, 0xCAF1, 0x0B40, 0xCB11, 0xCBE1, 0x0BB0, 0x0880, 0xC8D1, 0xC6C1, 0x0690, 0x0660, 0xC631, 0xCA01, 0x0A50, 0x0AA0, 0xCAF1, 0x0B40, 0xCB11, 0xCBE1, 0x0BB0, 0x0880, 0xC8D1,
0xC821, 0x0870, 0xC9C1, 0x0990, 0x0960, 0xC931, 0x0F00, 0xCF51, 0xCFA1, 0x0FF0, 0xCE41, 0x0E10, 0x0EE0, 0xCEB1, 0xC821, 0x0870, 0xC9C1, 0x0990, 0x0960, 0xC931, 0x0F00, 0xCF51, 0xCFA1, 0x0FF0, 0xCE41, 0x0E10, 0x0EE0, 0xCEB1,
0xCD81, 0x0DD0, 0x0D20, 0xCD71, 0x0CC0, 0xCC91, 0xCC61, 0x0C30, 0xD401, 0x1450, 0x14A0, 0xD4F1, 0x1540, 0xD511, 0xCD81, 0x0DD0, 0x0D20, 0xCD71, 0x0CC0, 0xCC91, 0xCC61, 0x0C30, 0xD401, 0x1450, 0x14A0, 0xD4F1, 0x1540, 0xD511,
0xD5E1, 0x15B0, 0x1680, 0xD6D1, 0xD621, 0x1670, 0xD7C1, 0x1790, 0x1760, 0xD731, 0x1100, 0xD151, 0xD1A1, 0x11F0, 0xD5E1, 0x15B0, 0x1680, 0xD6D1, 0xD621, 0x1670, 0xD7C1, 0x1790, 0x1760, 0xD731, 0x1100, 0xD151, 0xD1A1, 0x11F0,
0xD041, 0x1010, 0x10E0, 0xD0B1, 0xD381, 0x13D0, 0x1320, 0xD371, 0x12C0, 0xD291, 0xD261, 0x1230, 0x1E00, 0xDE51, 0xD041, 0x1010, 0x10E0, 0xD0B1, 0xD381, 0x13D0, 0x1320, 0xD371, 0x12C0, 0xD291, 0xD261, 0x1230, 0x1E00, 0xDE51,
0xDEA1, 0x1EF0, 0xDF41, 0x1F10, 0x1FE0, 0xDFB1, 0xDC81, 0x1CD0, 0x1C20, 0xDC71, 0x1DC0, 0xDD91, 0xDD61, 0x1D30, 0xDEA1, 0x1EF0, 0xDF41, 0x1F10, 0x1FE0, 0xDFB1, 0xDC81, 0x1CD0, 0x1C20, 0xDC71, 0x1DC0, 0xDD91, 0xDD61, 0x1D30,
0xDB01, 0x1B50, 0x1BA0, 0xDBF1, 0x1A40, 0xDA11, 0xDAE1, 0x1AB0, 0x1980, 0xD9D1, 0xD921, 0x1970, 0xD8C1, 0x1890, 0xDB01, 0x1B50, 0x1BA0, 0xDBF1, 0x1A40, 0xDA11, 0xDAE1, 0x1AB0, 0x1980, 0xD9D1, 0xD921, 0x1970, 0xD8C1, 0x1890,
0x1860, 0xD831, 0xE801, 0x2850, 0x28A0, 0xE8F1, 0x2940, 0xE911, 0xE9E1, 0x29B0, 0x2A80, 0xEAD1, 0xEA21, 0x2A70, 0x1860, 0xD831, 0xE801, 0x2850, 0x28A0, 0xE8F1, 0x2940, 0xE911, 0xE9E1, 0x29B0, 0x2A80, 0xEAD1, 0xEA21, 0x2A70,
0xEBC1, 0x2B90, 0x2B60, 0xEB31, 0x2D00, 0xED51, 0xEDA1, 0x2DF0, 0xEC41, 0x2C10, 0x2CE0, 0xECB1, 0xEF81, 0x2FD0, 0xEBC1, 0x2B90, 0x2B60, 0xEB31, 0x2D00, 0xED51, 0xEDA1, 0x2DF0, 0xEC41, 0x2C10, 0x2CE0, 0xECB1, 0xEF81, 0x2FD0,
0x2F20, 0xEF71, 0x2EC0, 0xEE91, 0xEE61, 0x2E30, 0x2200, 0xE251, 0xE2A1, 0x22F0, 0xE341, 0x2310, 0x23E0, 0xE3B1, 0x2F20, 0xEF71, 0x2EC0, 0xEE91, 0xEE61, 0x2E30, 0x2200, 0xE251, 0xE2A1, 0x22F0, 0xE341, 0x2310, 0x23E0, 0xE3B1,
0xE081, 0x20D0, 0x2020, 0xE071, 0x21C0, 0xE191, 0xE161, 0x2130, 0xE701, 0x2750, 0x27A0, 0xE7F1, 0x2640, 0xE611, 0xE081, 0x20D0, 0x2020, 0xE071, 0x21C0, 0xE191, 0xE161, 0x2130, 0xE701, 0x2750, 0x27A0, 0xE7F1, 0x2640, 0xE611,
0xE6E1, 0x26B0, 0x2580, 0xE5D1, 0xE521, 0x2570, 0xE4C1, 0x2490, 0x2460, 0xE431, 0x3C00, 0xFC51, 0xFCA1, 0x3CF0, 0xE6E1, 0x26B0, 0x2580, 0xE5D1, 0xE521, 0x2570, 0xE4C1, 0x2490, 0x2460, 0xE431, 0x3C00, 0xFC51, 0xFCA1, 0x3CF0,
0xFD41, 0x3D10, 0x3DE0, 0xFDB1, 0xFE81, 0x3ED0, 0x3E20, 0xFE71, 0x3FC0, 0xFF91, 0xFF61, 0x3F30, 0xF901, 0x3950, 0xFD41, 0x3D10, 0x3DE0, 0xFDB1, 0xFE81, 0x3ED0, 0x3E20, 0xFE71, 0x3FC0, 0xFF91, 0xFF61, 0x3F30, 0xF901, 0x3950,
0x39A0, 0xF9F1, 0x3840, 0xF811, 0xF8E1, 0x38B0, 0x3B80, 0xFBD1, 0xFB21, 0x3B70, 0xFAC1, 0x3A90, 0x3A60, 0xFA31, 0x39A0, 0xF9F1, 0x3840, 0xF811, 0xF8E1, 0x38B0, 0x3B80, 0xFBD1, 0xFB21, 0x3B70, 0xFAC1, 0x3A90, 0x3A60, 0xFA31,
0xF601, 0x3650, 0x36A0, 0xF6F1, 0x3740, 0xF711, 0xF7E1, 0x37B0, 0x3480, 0xF4D1, 0xF421, 0x3470, 0xF5C1, 0x3590, 0xF601, 0x3650, 0x36A0, 0xF6F1, 0x3740, 0xF711, 0xF7E1, 0x37B0, 0x3480, 0xF4D1, 0xF421, 0x3470, 0xF5C1, 0x3590,
0x3560, 0xF531, 0x3300, 0xF351, 0xF3A1, 0x33F0, 0xF241, 0x3210, 0x32E0, 0xF2B1, 0xF181, 0x31D0, 0x3120, 0xF171, 0x3560, 0xF531, 0x3300, 0xF351, 0xF3A1, 0x33F0, 0xF241, 0x3210, 0x32E0, 0xF2B1, 0xF181, 0x31D0, 0x3120, 0xF171,
0x30C0, 0xF091, 0xF061, 0x3030}, 0x30C0, 0xF091, 0xF061, 0x3030},
{0x0000, 0xFC01, 0xB801, 0x4400, 0x3001, 0xCC00, 0x8800, 0x7401, 0x6002, 0x9C03, 0xD803, 0x2402, 0x5003, 0xAC02, {0x0000, 0xFC01, 0xB801, 0x4400, 0x3001, 0xCC00, 0x8800, 0x7401, 0x6002, 0x9C03, 0xD803, 0x2402, 0x5003, 0xAC02,
0xE802, 0x1403, 0xC004, 0x3C05, 0x7805, 0x8404, 0xF005, 0x0C04, 0x4804, 0xB405, 0xA006, 0x5C07, 0x1807, 0xE406, 0xE802, 0x1403, 0xC004, 0x3C05, 0x7805, 0x8404, 0xF005, 0x0C04, 0x4804, 0xB405, 0xA006, 0x5C07, 0x1807, 0xE406,
0x9007, 0x6C06, 0x2806, 0xD407, 0xC00B, 0x3C0A, 0x780A, 0x840B, 0xF00A, 0x0C0B, 0x480B, 0xB40A, 0xA009, 0x5C08, 0x9007, 0x6C06, 0x2806, 0xD407, 0xC00B, 0x3C0A, 0x780A, 0x840B, 0xF00A, 0x0C0B, 0x480B, 0xB40A, 0xA009, 0x5C08,
0x1808, 0xE409, 0x9008, 0x6C09, 0x2809, 0xD408, 0x000F, 0xFC0E, 0xB80E, 0x440F, 0x300E, 0xCC0F, 0x880F, 0x740E, 0x1808, 0xE409, 0x9008, 0x6C09, 0x2809, 0xD408, 0x000F, 0xFC0E, 0xB80E, 0x440F, 0x300E, 0xCC0F, 0x880F, 0x740E,
0x600D, 0x9C0C, 0xD80C, 0x240D, 0x500C, 0xAC0D, 0xE80D, 0x140C, 0xC015, 0x3C14, 0x7814, 0x8415, 0xF014, 0x0C15, 0x600D, 0x9C0C, 0xD80C, 0x240D, 0x500C, 0xAC0D, 0xE80D, 0x140C, 0xC015, 0x3C14, 0x7814, 0x8415, 0xF014, 0x0C15,
0x4815, 0xB414, 0xA017, 0x5C16, 0x1816, 0xE417, 0x9016, 0x6C17, 0x2817, 0xD416, 0x0011, 0xFC10, 0xB810, 0x4411, 0x4815, 0xB414, 0xA017, 0x5C16, 0x1816, 0xE417, 0x9016, 0x6C17, 0x2817, 0xD416, 0x0011, 0xFC10, 0xB810, 0x4411,
0x3010, 0xCC11, 0x8811, 0x7410, 0x6013, 0x9C12, 0xD812, 0x2413, 0x5012, 0xAC13, 0xE813, 0x1412, 0x001E, 0xFC1F, 0x3010, 0xCC11, 0x8811, 0x7410, 0x6013, 0x9C12, 0xD812, 0x2413, 0x5012, 0xAC13, 0xE813, 0x1412, 0x001E, 0xFC1F,
0xB81F, 0x441E, 0x301F, 0xCC1E, 0x881E, 0x741F, 0x601C, 0x9C1D, 0xD81D, 0x241C, 0x501D, 0xAC1C, 0xE81C, 0x141D, 0xB81F, 0x441E, 0x301F, 0xCC1E, 0x881E, 0x741F, 0x601C, 0x9C1D, 0xD81D, 0x241C, 0x501D, 0xAC1C, 0xE81C, 0x141D,
0xC01A, 0x3C1B, 0x781B, 0x841A, 0xF01B, 0x0C1A, 0x481A, 0xB41B, 0xA018, 0x5C19, 0x1819, 0xE418, 0x9019, 0x6C18, 0xC01A, 0x3C1B, 0x781B, 0x841A, 0xF01B, 0x0C1A, 0x481A, 0xB41B, 0xA018, 0x5C19, 0x1819, 0xE418, 0x9019, 0x6C18,
0x2818, 0xD419, 0xC029, 0x3C28, 0x7828, 0x8429, 0xF028, 0x0C29, 0x4829, 0xB428, 0xA02B, 0x5C2A, 0x182A, 0xE42B, 0x2818, 0xD419, 0xC029, 0x3C28, 0x7828, 0x8429, 0xF028, 0x0C29, 0x4829, 0xB428, 0xA02B, 0x5C2A, 0x182A, 0xE42B,
0x902A, 0x6C2B, 0x282B, 0xD42A, 0x002D, 0xFC2C, 0xB82C, 0x442D, 0x302C, 0xCC2D, 0x882D, 0x742C, 0x602F, 0x9C2E, 0x902A, 0x6C2B, 0x282B, 0xD42A, 0x002D, 0xFC2C, 0xB82C, 0x442D, 0x302C, 0xCC2D, 0x882D, 0x742C, 0x602F, 0x9C2E,
0xD82E, 0x242F, 0x502E, 0xAC2F, 0xE82F, 0x142E, 0x0022, 0xFC23, 0xB823, 0x4422, 0x3023, 0xCC22, 0x8822, 0x7423, 0xD82E, 0x242F, 0x502E, 0xAC2F, 0xE82F, 0x142E, 0x0022, 0xFC23, 0xB823, 0x4422, 0x3023, 0xCC22, 0x8822, 0x7423,
0x6020, 0x9C21, 0xD821, 0x2420, 0x5021, 0xAC20, 0xE820, 0x1421, 0xC026, 0x3C27, 0x7827, 0x8426, 0xF027, 0x0C26, 0x6020, 0x9C21, 0xD821, 0x2420, 0x5021, 0xAC20, 0xE820, 0x1421, 0xC026, 0x3C27, 0x7827, 0x8426, 0xF027, 0x0C26,
0x4826, 0xB427, 0xA024, 0x5C25, 0x1825, 0xE424, 0x9025, 0x6C24, 0x2824, 0xD425, 0x003C, 0xFC3D, 0xB83D, 0x443C, 0x4826, 0xB427, 0xA024, 0x5C25, 0x1825, 0xE424, 0x9025, 0x6C24, 0x2824, 0xD425, 0x003C, 0xFC3D, 0xB83D, 0x443C,
0x303D, 0xCC3C, 0x883C, 0x743D, 0x603E, 0x9C3F, 0xD83F, 0x243E, 0x503F, 0xAC3E, 0xE83E, 0x143F, 0xC038, 0x3C39, 0x303D, 0xCC3C, 0x883C, 0x743D, 0x603E, 0x9C3F, 0xD83F, 0x243E, 0x503F, 0xAC3E, 0xE83E, 0x143F, 0xC038, 0x3C39,
0x7839, 0x8438, 0xF039, 0x0C38, 0x4838, 0xB439, 0xA03A, 0x5C3B, 0x183B, 0xE43A, 0x903B, 0x6C3A, 0x283A, 0xD43B, 0x7839, 0x8438, 0xF039, 0x0C38, 0x4838, 0xB439, 0xA03A, 0x5C3B, 0x183B, 0xE43A, 0x903B, 0x6C3A, 0x283A, 0xD43B,
0xC037, 0x3C36, 0x7836, 0x8437, 0xF036, 0x0C37, 0x4837, 0xB436, 0xA035, 0x5C34, 0x1834, 0xE435, 0x9034, 0x6C35, 0xC037, 0x3C36, 0x7836, 0x8437, 0xF036, 0x0C37, 0x4837, 0xB436, 0xA035, 0x5C34, 0x1834, 0xE435, 0x9034, 0x6C35,
0x2835, 0xD434, 0x0033, 0xFC32, 0xB832, 0x4433, 0x3032, 0xCC33, 0x8833, 0x7432, 0x6031, 0x9C30, 0xD830, 0x2431, 0x2835, 0xD434, 0x0033, 0xFC32, 0xB832, 0x4433, 0x3032, 0xCC33, 0x8833, 0x7432, 0x6031, 0x9C30, 0xD830, 0x2431,
0x5030, 0xAC31, 0xE831, 0x1430}, 0x5030, 0xAC31, 0xE831, 0x1430},
{0x0000, 0xC03D, 0xC079, 0x0044, 0xC0F1, 0x00CC, 0x0088, 0xC0B5, 0xC1E1, 0x01DC, 0x0198, 0xC1A5, 0x0110, 0xC12D, {0x0000, 0xC03D, 0xC079, 0x0044, 0xC0F1, 0x00CC, 0x0088, 0xC0B5, 0xC1E1, 0x01DC, 0x0198, 0xC1A5, 0x0110, 0xC12D,
0xC169, 0x0154, 0xC3C1, 0x03FC, 0x03B8, 0xC385, 0x0330, 0xC30D, 0xC349, 0x0374, 0x0220, 0xC21D, 0xC259, 0x0264, 0xC169, 0x0154, 0xC3C1, 0x03FC, 0x03B8, 0xC385, 0x0330, 0xC30D, 0xC349, 0x0374, 0x0220, 0xC21D, 0xC259, 0x0264,
0xC2D1, 0x02EC, 0x02A8, 0xC295, 0xC781, 0x07BC, 0x07F8, 0xC7C5, 0x0770, 0xC74D, 0xC709, 0x0734, 0x0660, 0xC65D, 0xC2D1, 0x02EC, 0x02A8, 0xC295, 0xC781, 0x07BC, 0x07F8, 0xC7C5, 0x0770, 0xC74D, 0xC709, 0x0734, 0x0660, 0xC65D,
0xC619, 0x0624, 0xC691, 0x06AC, 0x06E8, 0xC6D5, 0x0440, 0xC47D, 0xC439, 0x0404, 0xC4B1, 0x048C, 0x04C8, 0xC4F5, 0xC619, 0x0624, 0xC691, 0x06AC, 0x06E8, 0xC6D5, 0x0440, 0xC47D, 0xC439, 0x0404, 0xC4B1, 0x048C, 0x04C8, 0xC4F5,
0xC5A1, 0x059C, 0x05D8, 0xC5E5, 0x0550, 0xC56D, 0xC529, 0x0514, 0xCF01, 0x0F3C, 0x0F78, 0xCF45, 0x0FF0, 0xCFCD, 0xC5A1, 0x059C, 0x05D8, 0xC5E5, 0x0550, 0xC56D, 0xC529, 0x0514, 0xCF01, 0x0F3C, 0x0F78, 0xCF45, 0x0FF0, 0xCFCD,
0xCF89, 0x0FB4, 0x0EE0, 0xCEDD, 0xCE99, 0x0EA4, 0xCE11, 0x0E2C, 0x0E68, 0xCE55, 0x0CC0, 0xCCFD, 0xCCB9, 0x0C84, 0xCF89, 0x0FB4, 0x0EE0, 0xCEDD, 0xCE99, 0x0EA4, 0xCE11, 0x0E2C, 0x0E68, 0xCE55, 0x0CC0, 0xCCFD, 0xCCB9, 0x0C84,
0xCC31, 0x0C0C, 0x0C48, 0xCC75, 0xCD21, 0x0D1C, 0x0D58, 0xCD65, 0x0DD0, 0xCDED, 0xCDA9, 0x0D94, 0x0880, 0xC8BD, 0xCC31, 0x0C0C, 0x0C48, 0xCC75, 0xCD21, 0x0D1C, 0x0D58, 0xCD65, 0x0DD0, 0xCDED, 0xCDA9, 0x0D94, 0x0880, 0xC8BD,
0xC8F9, 0x08C4, 0xC871, 0x084C, 0x0808, 0xC835, 0xC961, 0x095C, 0x0918, 0xC925, 0x0990, 0xC9AD, 0xC9E9, 0x09D4, 0xC8F9, 0x08C4, 0xC871, 0x084C, 0x0808, 0xC835, 0xC961, 0x095C, 0x0918, 0xC925, 0x0990, 0xC9AD, 0xC9E9, 0x09D4,
0xCB41, 0x0B7C, 0x0B38, 0xCB05, 0x0BB0, 0xCB8D, 0xCBC9, 0x0BF4, 0x0AA0, 0xCA9D, 0xCAD9, 0x0AE4, 0xCA51, 0x0A6C, 0xCB41, 0x0B7C, 0x0B38, 0xCB05, 0x0BB0, 0xCB8D, 0xCBC9, 0x0BF4, 0x0AA0, 0xCA9D, 0xCAD9, 0x0AE4, 0xCA51, 0x0A6C,
0x0A28, 0xCA15, 0xDE01, 0x1E3C, 0x1E78, 0xDE45, 0x1EF0, 0xDECD, 0xDE89, 0x1EB4, 0x1FE0, 0xDFDD, 0xDF99, 0x1FA4, 0x0A28, 0xCA15, 0xDE01, 0x1E3C, 0x1E78, 0xDE45, 0x1EF0, 0xDECD, 0xDE89, 0x1EB4, 0x1FE0, 0xDFDD, 0xDF99, 0x1FA4,
0xDF11, 0x1F2C, 0x1F68, 0xDF55, 0x1DC0, 0xDDFD, 0xDDB9, 0x1D84, 0xDD31, 0x1D0C, 0x1D48, 0xDD75, 0xDC21, 0x1C1C, 0xDF11, 0x1F2C, 0x1F68, 0xDF55, 0x1DC0, 0xDDFD, 0xDDB9, 0x1D84, 0xDD31, 0x1D0C, 0x1D48, 0xDD75, 0xDC21, 0x1C1C,
0x1C58, 0xDC65, 0x1CD0, 0xDCED, 0xDCA9, 0x1C94, 0x1980, 0xD9BD, 0xD9F9, 0x19C4, 0xD971, 0x194C, 0x1908, 0xD935, 0x1C58, 0xDC65, 0x1CD0, 0xDCED, 0xDCA9, 0x1C94, 0x1980, 0xD9BD, 0xD9F9, 0x19C4, 0xD971, 0x194C, 0x1908, 0xD935,
0xD861, 0x185C, 0x1818, 0xD825, 0x1890, 0xD8AD, 0xD8E9, 0x18D4, 0xDA41, 0x1A7C, 0x1A38, 0xDA05, 0x1AB0, 0xDA8D, 0xD861, 0x185C, 0x1818, 0xD825, 0x1890, 0xD8AD, 0xD8E9, 0x18D4, 0xDA41, 0x1A7C, 0x1A38, 0xDA05, 0x1AB0, 0xDA8D,
0xDAC9, 0x1AF4, 0x1BA0, 0xDB9D, 0xDBD9, 0x1BE4, 0xDB51, 0x1B6C, 0x1B28, 0xDB15, 0x1100, 0xD13D, 0xD179, 0x1144, 0xDAC9, 0x1AF4, 0x1BA0, 0xDB9D, 0xDBD9, 0x1BE4, 0xDB51, 0x1B6C, 0x1B28, 0xDB15, 0x1100, 0xD13D, 0xD179, 0x1144,
0xD1F1, 0x11CC, 0x1188, 0xD1B5, 0xD0E1, 0x10DC, 0x1098, 0xD0A5, 0x1010, 0xD02D, 0xD069, 0x1054, 0xD2C1, 0x12FC, 0xD1F1, 0x11CC, 0x1188, 0xD1B5, 0xD0E1, 0x10DC, 0x1098, 0xD0A5, 0x1010, 0xD02D, 0xD069, 0x1054, 0xD2C1, 0x12FC,
0x12B8, 0xD285, 0x1230, 0xD20D, 0xD249, 0x1274, 0x1320, 0xD31D, 0xD359, 0x1364, 0xD3D1, 0x13EC, 0x13A8, 0xD395, 0x12B8, 0xD285, 0x1230, 0xD20D, 0xD249, 0x1274, 0x1320, 0xD31D, 0xD359, 0x1364, 0xD3D1, 0x13EC, 0x13A8, 0xD395,
0xD681, 0x16BC, 0x16F8, 0xD6C5, 0x1670, 0xD64D, 0xD609, 0x1634, 0x1760, 0xD75D, 0xD719, 0x1724, 0xD791, 0x17AC, 0xD681, 0x16BC, 0x16F8, 0xD6C5, 0x1670, 0xD64D, 0xD609, 0x1634, 0x1760, 0xD75D, 0xD719, 0x1724, 0xD791, 0x17AC,
0x17E8, 0xD7D5, 0x1540, 0xD57D, 0xD539, 0x1504, 0xD5B1, 0x158C, 0x15C8, 0xD5F5, 0xD4A1, 0x149C, 0x14D8, 0xD4E5, 0x17E8, 0xD7D5, 0x1540, 0xD57D, 0xD539, 0x1504, 0xD5B1, 0x158C, 0x15C8, 0xD5F5, 0xD4A1, 0x149C, 0x14D8, 0xD4E5,
0x1450, 0xD46D, 0xD429, 0x1414}, 0x1450, 0xD46D, 0xD429, 0x1414},
{0x0000, 0xD101, 0xE201, 0x3300, 0x8401, 0x5500, 0x6600, 0xB701, 0x4801, 0x9900, 0xAA00, 0x7B01, 0xCC00, 0x1D01, {0x0000, 0xD101, 0xE201, 0x3300, 0x8401, 0x5500, 0x6600, 0xB701, 0x4801, 0x9900, 0xAA00, 0x7B01, 0xCC00, 0x1D01,
0x2E01, 0xFF00, 0x9002, 0x4103, 0x7203, 0xA302, 0x1403, 0xC502, 0xF602, 0x2703, 0xD803, 0x0902, 0x3A02, 0xEB03, 0x2E01, 0xFF00, 0x9002, 0x4103, 0x7203, 0xA302, 0x1403, 0xC502, 0xF602, 0x2703, 0xD803, 0x0902, 0x3A02, 0xEB03,
0x5C02, 0x8D03, 0xBE03, 0x6F02, 0x6007, 0xB106, 0x8206, 0x5307, 0xE406, 0x3507, 0x0607, 0xD706, 0x2806, 0xF907, 0x5C02, 0x8D03, 0xBE03, 0x6F02, 0x6007, 0xB106, 0x8206, 0x5307, 0xE406, 0x3507, 0x0607, 0xD706, 0x2806, 0xF907,
0xCA07, 0x1B06, 0xAC07, 0x7D06, 0x4E06, 0x9F07, 0xF005, 0x2104, 0x1204, 0xC305, 0x7404, 0xA505, 0x9605, 0x4704, 0xCA07, 0x1B06, 0xAC07, 0x7D06, 0x4E06, 0x9F07, 0xF005, 0x2104, 0x1204, 0xC305, 0x7404, 0xA505, 0x9605, 0x4704,
0xB804, 0x6905, 0x5A05, 0x8B04, 0x3C05, 0xED04, 0xDE04, 0x0F05, 0xC00E, 0x110F, 0x220F, 0xF30E, 0x440F, 0x950E, 0xB804, 0x6905, 0x5A05, 0x8B04, 0x3C05, 0xED04, 0xDE04, 0x0F05, 0xC00E, 0x110F, 0x220F, 0xF30E, 0x440F, 0x950E,
0xA60E, 0x770F, 0x880F, 0x590E, 0x6A0E, 0xBB0F, 0x0C0E, 0xDD0F, 0xEE0F, 0x3F0E, 0x500C, 0x810D, 0xB20D, 0x630C, 0xA60E, 0x770F, 0x880F, 0x590E, 0x6A0E, 0xBB0F, 0x0C0E, 0xDD0F, 0xEE0F, 0x3F0E, 0x500C, 0x810D, 0xB20D, 0x630C,
0xD40D, 0x050C, 0x360C, 0xE70D, 0x180D, 0xC90C, 0xFA0C, 0x2B0D, 0x9C0C, 0x4D0D, 0x7E0D, 0xAF0C, 0xA009, 0x7108, 0xD40D, 0x050C, 0x360C, 0xE70D, 0x180D, 0xC90C, 0xFA0C, 0x2B0D, 0x9C0C, 0x4D0D, 0x7E0D, 0xAF0C, 0xA009, 0x7108,
0x4208, 0x9309, 0x2408, 0xF509, 0xC609, 0x1708, 0xE808, 0x3909, 0x0A09, 0xDB08, 0x6C09, 0xBD08, 0x8E08, 0x5F09, 0x4208, 0x9309, 0x2408, 0xF509, 0xC609, 0x1708, 0xE808, 0x3909, 0x0A09, 0xDB08, 0x6C09, 0xBD08, 0x8E08, 0x5F09,
0x300B, 0xE10A, 0xD20A, 0x030B, 0xB40A, 0x650B, 0x560B, 0x870A, 0x780A, 0xA90B, 0x9A0B, 0x4B0A, 0xFC0B, 0x2D0A, 0x300B, 0xE10A, 0xD20A, 0x030B, 0xB40A, 0x650B, 0x560B, 0x870A, 0x780A, 0xA90B, 0x9A0B, 0x4B0A, 0xFC0B, 0x2D0A,
0x1E0A, 0xCF0B, 0xC01F, 0x111E, 0x221E, 0xF31F, 0x441E, 0x951F, 0xA61F, 0x771E, 0x881E, 0x591F, 0x6A1F, 0xBB1E, 0x1E0A, 0xCF0B, 0xC01F, 0x111E, 0x221E, 0xF31F, 0x441E, 0x951F, 0xA61F, 0x771E, 0x881E, 0x591F, 0x6A1F, 0xBB1E,
0x0C1F, 0xDD1E, 0xEE1E, 0x3F1F, 0x501D, 0x811C, 0xB21C, 0x631D, 0xD41C, 0x051D, 0x361D, 0xE71C, 0x181C, 0xC91D, 0x0C1F, 0xDD1E, 0xEE1E, 0x3F1F, 0x501D, 0x811C, 0xB21C, 0x631D, 0xD41C, 0x051D, 0x361D, 0xE71C, 0x181C, 0xC91D,
0xFA1D, 0x2B1C, 0x9C1D, 0x4D1C, 0x7E1C, 0xAF1D, 0xA018, 0x7119, 0x4219, 0x9318, 0x2419, 0xF518, 0xC618, 0x1719, 0xFA1D, 0x2B1C, 0x9C1D, 0x4D1C, 0x7E1C, 0xAF1D, 0xA018, 0x7119, 0x4219, 0x9318, 0x2419, 0xF518, 0xC618, 0x1719,
0xE819, 0x3918, 0x0A18, 0xDB19, 0x6C18, 0xBD19, 0x8E19, 0x5F18, 0x301A, 0xE11B, 0xD21B, 0x031A, 0xB41B, 0x651A, 0xE819, 0x3918, 0x0A18, 0xDB19, 0x6C18, 0xBD19, 0x8E19, 0x5F18, 0x301A, 0xE11B, 0xD21B, 0x031A, 0xB41B, 0x651A,
0x561A, 0x871B, 0x781B, 0xA91A, 0x9A1A, 0x4B1B, 0xFC1A, 0x2D1B, 0x1E1B, 0xCF1A, 0x0011, 0xD110, 0xE210, 0x3311, 0x561A, 0x871B, 0x781B, 0xA91A, 0x9A1A, 0x4B1B, 0xFC1A, 0x2D1B, 0x1E1B, 0xCF1A, 0x0011, 0xD110, 0xE210, 0x3311,
0x8410, 0x5511, 0x6611, 0xB710, 0x4810, 0x9911, 0xAA11, 0x7B10, 0xCC11, 0x1D10, 0x2E10, 0xFF11, 0x9013, 0x4112, 0x8410, 0x5511, 0x6611, 0xB710, 0x4810, 0x9911, 0xAA11, 0x7B10, 0xCC11, 0x1D10, 0x2E10, 0xFF11, 0x9013, 0x4112,
0x7212, 0xA313, 0x1412, 0xC513, 0xF613, 0x2712, 0xD812, 0x0913, 0x3A13, 0xEB12, 0x5C13, 0x8D12, 0xBE12, 0x6F13, 0x7212, 0xA313, 0x1412, 0xC513, 0xF613, 0x2712, 0xD812, 0x0913, 0x3A13, 0xEB12, 0x5C13, 0x8D12, 0xBE12, 0x6F13,
0x6016, 0xB117, 0x8217, 0x5316, 0xE417, 0x3516, 0x0616, 0xD717, 0x2817, 0xF916, 0xCA16, 0x1B17, 0xAC16, 0x7D17, 0x6016, 0xB117, 0x8217, 0x5316, 0xE417, 0x3516, 0x0616, 0xD717, 0x2817, 0xF916, 0xCA16, 0x1B17, 0xAC16, 0x7D17,
0x4E17, 0x9F16, 0xF014, 0x2115, 0x1215, 0xC314, 0x7415, 0xA514, 0x9614, 0x4715, 0xB815, 0x6914, 0x5A14, 0x8B15, 0x4E17, 0x9F16, 0xF014, 0x2115, 0x1215, 0xC314, 0x7415, 0xA514, 0x9614, 0x4715, 0xB815, 0x6914, 0x5A14, 0x8B15,
0x3C14, 0xED15, 0xDE15, 0x0F14}, 0x3C14, 0xED15, 0xDE15, 0x0F14},
{0x0000, 0xC010, 0xC023, 0x0033, 0xC045, 0x0055, 0x0066, 0xC076, 0xC089, 0x0099, 0x00AA, 0xC0BA, 0x00CC, 0xC0DC, {0x0000, 0xC010, 0xC023, 0x0033, 0xC045, 0x0055, 0x0066, 0xC076, 0xC089, 0x0099, 0x00AA, 0xC0BA, 0x00CC, 0xC0DC,
0xC0EF, 0x00FF, 0xC111, 0x0101, 0x0132, 0xC122, 0x0154, 0xC144, 0xC177, 0x0167, 0x0198, 0xC188, 0xC1BB, 0x01AB, 0xC0EF, 0x00FF, 0xC111, 0x0101, 0x0132, 0xC122, 0x0154, 0xC144, 0xC177, 0x0167, 0x0198, 0xC188, 0xC1BB, 0x01AB,
0xC1DD, 0x01CD, 0x01FE, 0xC1EE, 0xC221, 0x0231, 0x0202, 0xC212, 0x0264, 0xC274, 0xC247, 0x0257, 0x02A8, 0xC2B8, 0xC1DD, 0x01CD, 0x01FE, 0xC1EE, 0xC221, 0x0231, 0x0202, 0xC212, 0x0264, 0xC274, 0xC247, 0x0257, 0x02A8, 0xC2B8,
0xC28B, 0x029B, 0xC2ED, 0x02FD, 0x02CE, 0xC2DE, 0x0330, 0xC320, 0xC313, 0x0303, 0xC375, 0x0365, 0x0356, 0xC346, 0xC28B, 0x029B, 0xC2ED, 0x02FD, 0x02CE, 0xC2DE, 0x0330, 0xC320, 0xC313, 0x0303, 0xC375, 0x0365, 0x0356, 0xC346,
0xC3B9, 0x03A9, 0x039A, 0xC38A, 0x03FC, 0xC3EC, 0xC3DF, 0x03CF, 0xC441, 0x0451, 0x0462, 0xC472, 0x0404, 0xC414, 0xC3B9, 0x03A9, 0x039A, 0xC38A, 0x03FC, 0xC3EC, 0xC3DF, 0x03CF, 0xC441, 0x0451, 0x0462, 0xC472, 0x0404, 0xC414,
0xC427, 0x0437, 0x04C8, 0xC4D8, 0xC4EB, 0x04FB, 0xC48D, 0x049D, 0x04AE, 0xC4BE, 0x0550, 0xC540, 0xC573, 0x0563, 0xC427, 0x0437, 0x04C8, 0xC4D8, 0xC4EB, 0x04FB, 0xC48D, 0x049D, 0x04AE, 0xC4BE, 0x0550, 0xC540, 0xC573, 0x0563,
0xC515, 0x0505, 0x0536, 0xC526, 0xC5D9, 0x05C9, 0x05FA, 0xC5EA, 0x059C, 0xC58C, 0xC5BF, 0x05AF, 0x0660, 0xC670, 0xC515, 0x0505, 0x0536, 0xC526, 0xC5D9, 0x05C9, 0x05FA, 0xC5EA, 0x059C, 0xC58C, 0xC5BF, 0x05AF, 0x0660, 0xC670,
0xC643, 0x0653, 0xC625, 0x0635, 0x0606, 0xC616, 0xC6E9, 0x06F9, 0x06CA, 0xC6DA, 0x06AC, 0xC6BC, 0xC68F, 0x069F, 0xC643, 0x0653, 0xC625, 0x0635, 0x0606, 0xC616, 0xC6E9, 0x06F9, 0x06CA, 0xC6DA, 0x06AC, 0xC6BC, 0xC68F, 0x069F,
0xC771, 0x0761, 0x0752, 0xC742, 0x0734, 0xC724, 0xC717, 0x0707, 0x07F8, 0xC7E8, 0xC7DB, 0x07CB, 0xC7BD, 0x07AD, 0xC771, 0x0761, 0x0752, 0xC742, 0x0734, 0xC724, 0xC717, 0x0707, 0x07F8, 0xC7E8, 0xC7DB, 0x07CB, 0xC7BD, 0x07AD,
0x079E, 0xC78E, 0xC881, 0x0891, 0x08A2, 0xC8B2, 0x08C4, 0xC8D4, 0xC8E7, 0x08F7, 0x0808, 0xC818, 0xC82B, 0x083B, 0x079E, 0xC78E, 0xC881, 0x0891, 0x08A2, 0xC8B2, 0x08C4, 0xC8D4, 0xC8E7, 0x08F7, 0x0808, 0xC818, 0xC82B, 0x083B,
0xC84D, 0x085D, 0x086E, 0xC87E, 0x0990, 0xC980, 0xC9B3, 0x09A3, 0xC9D5, 0x09C5, 0x09F6, 0xC9E6, 0xC919, 0x0909, 0xC84D, 0x085D, 0x086E, 0xC87E, 0x0990, 0xC980, 0xC9B3, 0x09A3, 0xC9D5, 0x09C5, 0x09F6, 0xC9E6, 0xC919, 0x0909,
0x093A, 0xC92A, 0x095C, 0xC94C, 0xC97F, 0x096F, 0x0AA0, 0xCAB0, 0xCA83, 0x0A93, 0xCAE5, 0x0AF5, 0x0AC6, 0xCAD6, 0x093A, 0xC92A, 0x095C, 0xC94C, 0xC97F, 0x096F, 0x0AA0, 0xCAB0, 0xCA83, 0x0A93, 0xCAE5, 0x0AF5, 0x0AC6, 0xCAD6,
0xCA29, 0x0A39, 0x0A0A, 0xCA1A, 0x0A6C, 0xCA7C, 0xCA4F, 0x0A5F, 0xCBB1, 0x0BA1, 0x0B92, 0xCB82, 0x0BF4, 0xCBE4, 0xCA29, 0x0A39, 0x0A0A, 0xCA1A, 0x0A6C, 0xCA7C, 0xCA4F, 0x0A5F, 0xCBB1, 0x0BA1, 0x0B92, 0xCB82, 0x0BF4, 0xCBE4,
0xCBD7, 0x0BC7, 0x0B38, 0xCB28, 0xCB1B, 0x0B0B, 0xCB7D, 0x0B6D, 0x0B5E, 0xCB4E, 0x0CC0, 0xCCD0, 0xCCE3, 0x0CF3, 0xCBD7, 0x0BC7, 0x0B38, 0xCB28, 0xCB1B, 0x0B0B, 0xCB7D, 0x0B6D, 0x0B5E, 0xCB4E, 0x0CC0, 0xCCD0, 0xCCE3, 0x0CF3,
0xCC85, 0x0C95, 0x0CA6, 0xCCB6, 0xCC49, 0x0C59, 0x0C6A, 0xCC7A, 0x0C0C, 0xCC1C, 0xCC2F, 0x0C3F, 0xCDD1, 0x0DC1, 0xCC85, 0x0C95, 0x0CA6, 0xCCB6, 0xCC49, 0x0C59, 0x0C6A, 0xCC7A, 0x0C0C, 0xCC1C, 0xCC2F, 0x0C3F, 0xCDD1, 0x0DC1,
0x0DF2, 0xCDE2, 0x0D94, 0xCD84, 0xCDB7, 0x0DA7, 0x0D58, 0xCD48, 0xCD7B, 0x0D6B, 0xCD1D, 0x0D0D, 0x0D3E, 0xCD2E, 0x0DF2, 0xCDE2, 0x0D94, 0xCD84, 0xCDB7, 0x0DA7, 0x0D58, 0xCD48, 0xCD7B, 0x0D6B, 0xCD1D, 0x0D0D, 0x0D3E, 0xCD2E,
0xCEE1, 0x0EF1, 0x0EC2, 0xCED2, 0x0EA4, 0xCEB4, 0xCE87, 0x0E97, 0x0E68, 0xCE78, 0xCE4B, 0x0E5B, 0xCE2D, 0x0E3D, 0xCEE1, 0x0EF1, 0x0EC2, 0xCED2, 0x0EA4, 0xCEB4, 0xCE87, 0x0E97, 0x0E68, 0xCE78, 0xCE4B, 0x0E5B, 0xCE2D, 0x0E3D,
0x0E0E, 0xCE1E, 0x0FF0, 0xCFE0, 0xCFD3, 0x0FC3, 0xCFB5, 0x0FA5, 0x0F96, 0xCF86, 0xCF79, 0x0F69, 0x0F5A, 0xCF4A, 0x0E0E, 0xCE1E, 0x0FF0, 0xCFE0, 0xCFD3, 0x0FC3, 0xCFB5, 0x0FA5, 0x0F96, 0xCF86, 0xCF79, 0x0F69, 0x0F5A, 0xCF4A,
0x0F3C, 0xCF2C, 0xCF1F, 0x0F0F}, 0x0F3C, 0xCF2C, 0xCF1F, 0x0F0F},
{0x0000, 0xCCC1, 0xD981, 0x1540, 0xF301, 0x3FC0, 0x2A80, 0xE641, 0xA601, 0x6AC0, 0x7F80, 0xB341, 0x5500, 0x99C1, {0x0000, 0xCCC1, 0xD981, 0x1540, 0xF301, 0x3FC0, 0x2A80, 0xE641, 0xA601, 0x6AC0, 0x7F80, 0xB341, 0x5500, 0x99C1,
0x8C81, 0x4040, 0x0C01, 0xC0C0, 0xD580, 0x1941, 0xFF00, 0x33C1, 0x2681, 0xEA40, 0xAA00, 0x66C1, 0x7381, 0xBF40, 0x8C81, 0x4040, 0x0C01, 0xC0C0, 0xD580, 0x1941, 0xFF00, 0x33C1, 0x2681, 0xEA40, 0xAA00, 0x66C1, 0x7381, 0xBF40,
0x5901, 0x95C0, 0x8080, 0x4C41, 0x1802, 0xD4C3, 0xC183, 0x0D42, 0xEB03, 0x27C2, 0x3282, 0xFE43, 0xBE03, 0x72C2, 0x5901, 0x95C0, 0x8080, 0x4C41, 0x1802, 0xD4C3, 0xC183, 0x0D42, 0xEB03, 0x27C2, 0x3282, 0xFE43, 0xBE03, 0x72C2,
0x6782, 0xAB43, 0x4D02, 0x81C3, 0x9483, 0x5842, 0x1403, 0xD8C2, 0xCD82, 0x0143, 0xE702, 0x2BC3, 0x3E83, 0xF242, 0x6782, 0xAB43, 0x4D02, 0x81C3, 0x9483, 0x5842, 0x1403, 0xD8C2, 0xCD82, 0x0143, 0xE702, 0x2BC3, 0x3E83, 0xF242,
0xB202, 0x7EC3, 0x6B83, 0xA742, 0x4103, 0x8DC2, 0x9882, 0x5443, 0x3004, 0xFCC5, 0xE985, 0x2544, 0xC305, 0x0FC4, 0xB202, 0x7EC3, 0x6B83, 0xA742, 0x4103, 0x8DC2, 0x9882, 0x5443, 0x3004, 0xFCC5, 0xE985, 0x2544, 0xC305, 0x0FC4,
0x1A84, 0xD645, 0x9605, 0x5AC4, 0x4F84, 0x8345, 0x6504, 0xA9C5, 0xBC85, 0x7044, 0x3C05, 0xF0C4, 0xE584, 0x2945, 0x1A84, 0xD645, 0x9605, 0x5AC4, 0x4F84, 0x8345, 0x6504, 0xA9C5, 0xBC85, 0x7044, 0x3C05, 0xF0C4, 0xE584, 0x2945,
0xCF04, 0x03C5, 0x1685, 0xDA44, 0x9A04, 0x56C5, 0x4385, 0x8F44, 0x6905, 0xA5C4, 0xB084, 0x7C45, 0x2806, 0xE4C7, 0xCF04, 0x03C5, 0x1685, 0xDA44, 0x9A04, 0x56C5, 0x4385, 0x8F44, 0x6905, 0xA5C4, 0xB084, 0x7C45, 0x2806, 0xE4C7,
0xF187, 0x3D46, 0xDB07, 0x17C6, 0x0286, 0xCE47, 0x8E07, 0x42C6, 0x5786, 0x9B47, 0x7D06, 0xB1C7, 0xA487, 0x6846, 0xF187, 0x3D46, 0xDB07, 0x17C6, 0x0286, 0xCE47, 0x8E07, 0x42C6, 0x5786, 0x9B47, 0x7D06, 0xB1C7, 0xA487, 0x6846,
0x2407, 0xE8C6, 0xFD86, 0x3147, 0xD706, 0x1BC7, 0x0E87, 0xC246, 0x8206, 0x4EC7, 0x5B87, 0x9746, 0x7107, 0xBDC6, 0x2407, 0xE8C6, 0xFD86, 0x3147, 0xD706, 0x1BC7, 0x0E87, 0xC246, 0x8206, 0x4EC7, 0x5B87, 0x9746, 0x7107, 0xBDC6,
0xA886, 0x6447, 0x6008, 0xACC9, 0xB989, 0x7548, 0x9309, 0x5FC8, 0x4A88, 0x8649, 0xC609, 0x0AC8, 0x1F88, 0xD349, 0xA886, 0x6447, 0x6008, 0xACC9, 0xB989, 0x7548, 0x9309, 0x5FC8, 0x4A88, 0x8649, 0xC609, 0x0AC8, 0x1F88, 0xD349,
0x3508, 0xF9C9, 0xEC89, 0x2048, 0x6C09, 0xA0C8, 0xB588, 0x7949, 0x9F08, 0x53C9, 0x4689, 0x8A48, 0xCA08, 0x06C9, 0x3508, 0xF9C9, 0xEC89, 0x2048, 0x6C09, 0xA0C8, 0xB588, 0x7949, 0x9F08, 0x53C9, 0x4689, 0x8A48, 0xCA08, 0x06C9,
0x1389, 0xDF48, 0x3909, 0xF5C8, 0xE088, 0x2C49, 0x780A, 0xB4CB, 0xA18B, 0x6D4A, 0x8B0B, 0x47CA, 0x528A, 0x9E4B, 0x1389, 0xDF48, 0x3909, 0xF5C8, 0xE088, 0x2C49, 0x780A, 0xB4CB, 0xA18B, 0x6D4A, 0x8B0B, 0x47CA, 0x528A, 0x9E4B,
0xDE0B, 0x12CA, 0x078A, 0xCB4B, 0x2D0A, 0xE1CB, 0xF48B, 0x384A, 0x740B, 0xB8CA, 0xAD8A, 0x614B, 0x870A, 0x4BCB, 0xDE0B, 0x12CA, 0x078A, 0xCB4B, 0x2D0A, 0xE1CB, 0xF48B, 0x384A, 0x740B, 0xB8CA, 0xAD8A, 0x614B, 0x870A, 0x4BCB,
0x5E8B, 0x924A, 0xD20A, 0x1ECB, 0x0B8B, 0xC74A, 0x210B, 0xEDCA, 0xF88A, 0x344B, 0x500C, 0x9CCD, 0x898D, 0x454C, 0x5E8B, 0x924A, 0xD20A, 0x1ECB, 0x0B8B, 0xC74A, 0x210B, 0xEDCA, 0xF88A, 0x344B, 0x500C, 0x9CCD, 0x898D, 0x454C,
0xA30D, 0x6FCC, 0x7A8C, 0xB64D, 0xF60D, 0x3ACC, 0x2F8C, 0xE34D, 0x050C, 0xC9CD, 0xDC8D, 0x104C, 0x5C0D, 0x90CC, 0xA30D, 0x6FCC, 0x7A8C, 0xB64D, 0xF60D, 0x3ACC, 0x2F8C, 0xE34D, 0x050C, 0xC9CD, 0xDC8D, 0x104C, 0x5C0D, 0x90CC,
0x858C, 0x494D, 0xAF0C, 0x63CD, 0x768D, 0xBA4C, 0xFA0C, 0x36CD, 0x238D, 0xEF4C, 0x090D, 0xC5CC, 0xD08C, 0x1C4D, 0x858C, 0x494D, 0xAF0C, 0x63CD, 0x768D, 0xBA4C, 0xFA0C, 0x36CD, 0x238D, 0xEF4C, 0x090D, 0xC5CC, 0xD08C, 0x1C4D,
0x480E, 0x84CF, 0x918F, 0x5D4E, 0xBB0F, 0x77CE, 0x628E, 0xAE4F, 0xEE0F, 0x22CE, 0x378E, 0xFB4F, 0x1D0E, 0xD1CF, 0x480E, 0x84CF, 0x918F, 0x5D4E, 0xBB0F, 0x77CE, 0x628E, 0xAE4F, 0xEE0F, 0x22CE, 0x378E, 0xFB4F, 0x1D0E, 0xD1CF,
0xC48F, 0x084E, 0x440F, 0x88CE, 0x9D8E, 0x514F, 0xB70E, 0x7BCF, 0x6E8F, 0xA24E, 0xE20E, 0x2ECF, 0x3B8F, 0xF74E, 0xC48F, 0x084E, 0x440F, 0x88CE, 0x9D8E, 0x514F, 0xB70E, 0x7BCF, 0x6E8F, 0xA24E, 0xE20E, 0x2ECF, 0x3B8F, 0xF74E,
0x110F, 0xDDCE, 0xC88E, 0x044F}}; 0x110F, 0xDDCE, 0xC88E, 0x044F}
};
AARU_EXPORT crc16_ctx *AARU_CALL crc16_init(); AARU_EXPORT crc16_ctx *AARU_CALL crc16_init();
AARU_EXPORT int AARU_CALL crc16_update(crc16_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL crc16_update(crc16_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL crc16_final(crc16_ctx *ctx, uint16_t *crc); AARU_EXPORT int AARU_CALL crc16_final(crc16_ctx *ctx, uint16_t *crc);
AARU_EXPORT void AARU_CALL crc16_free(crc16_ctx *ctx); AARU_EXPORT void AARU_CALL crc16_free(crc16_ctx *ctx);
#endif // AARU_CHECKSUMS_NATIVE_CRC16_H #endif // AARU_CHECKSUMS_NATIVE_CRC16_H

View File

@@ -64,11 +64,11 @@ AARU_EXPORT int AARU_CALL crc16_ccitt_update(crc16_ccitt_ctx *ctx, const uint8_t
if(!ctx || !data) return -1; if(!ctx || !data) return -1;
uint16_t crc; uint16_t crc;
const uint8_t *current_char = data; const uint8_t *current_char = data;
const size_t unroll = 4; const size_t unroll = 4;
const size_t bytes_at_once = 8 * unroll; const size_t bytes_at_once = 8 * unroll;
uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3; uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3;
crc = ctx->crc; crc = ctx->crc;

View File

@@ -25,162 +25,163 @@ typedef struct
} crc16_ccitt_ctx; } crc16_ccitt_ctx;
const uint16_t crc16_ccitt_table[8][256] = { const uint16_t crc16_ccitt_table[8][256] = {
{0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD,
0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A,
0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B,
0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861,
0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96,
0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87,
0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A,
0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3,
0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290,
0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E,
0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F,
0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C,
0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83,
0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74,
0x2E93, 0x3EB2, 0x0ED1, 0x1EF0}, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0},
{0x0000, 0x3331, 0x6662, 0x5553, 0xCCC4, 0xFFF5, 0xAAA6, 0x9997, 0x89A9, 0xBA98, 0xEFCB, 0xDCFA, 0x456D, 0x765C, {0x0000, 0x3331, 0x6662, 0x5553, 0xCCC4, 0xFFF5, 0xAAA6, 0x9997, 0x89A9, 0xBA98, 0xEFCB, 0xDCFA, 0x456D, 0x765C,
0x230F, 0x103E, 0x0373, 0x3042, 0x6511, 0x5620, 0xCFB7, 0xFC86, 0xA9D5, 0x9AE4, 0x8ADA, 0xB9EB, 0xECB8, 0xDF89, 0x230F, 0x103E, 0x0373, 0x3042, 0x6511, 0x5620, 0xCFB7, 0xFC86, 0xA9D5, 0x9AE4, 0x8ADA, 0xB9EB, 0xECB8, 0xDF89,
0x461E, 0x752F, 0x207C, 0x134D, 0x06E6, 0x35D7, 0x6084, 0x53B5, 0xCA22, 0xF913, 0xAC40, 0x9F71, 0x8F4F, 0xBC7E, 0x461E, 0x752F, 0x207C, 0x134D, 0x06E6, 0x35D7, 0x6084, 0x53B5, 0xCA22, 0xF913, 0xAC40, 0x9F71, 0x8F4F, 0xBC7E,
0xE92D, 0xDA1C, 0x438B, 0x70BA, 0x25E9, 0x16D8, 0x0595, 0x36A4, 0x63F7, 0x50C6, 0xC951, 0xFA60, 0xAF33, 0x9C02, 0xE92D, 0xDA1C, 0x438B, 0x70BA, 0x25E9, 0x16D8, 0x0595, 0x36A4, 0x63F7, 0x50C6, 0xC951, 0xFA60, 0xAF33, 0x9C02,
0x8C3C, 0xBF0D, 0xEA5E, 0xD96F, 0x40F8, 0x73C9, 0x269A, 0x15AB, 0x0DCC, 0x3EFD, 0x6BAE, 0x589F, 0xC108, 0xF239, 0x8C3C, 0xBF0D, 0xEA5E, 0xD96F, 0x40F8, 0x73C9, 0x269A, 0x15AB, 0x0DCC, 0x3EFD, 0x6BAE, 0x589F, 0xC108, 0xF239,
0xA76A, 0x945B, 0x8465, 0xB754, 0xE207, 0xD136, 0x48A1, 0x7B90, 0x2EC3, 0x1DF2, 0x0EBF, 0x3D8E, 0x68DD, 0x5BEC, 0xA76A, 0x945B, 0x8465, 0xB754, 0xE207, 0xD136, 0x48A1, 0x7B90, 0x2EC3, 0x1DF2, 0x0EBF, 0x3D8E, 0x68DD, 0x5BEC,
0xC27B, 0xF14A, 0xA419, 0x9728, 0x8716, 0xB427, 0xE174, 0xD245, 0x4BD2, 0x78E3, 0x2DB0, 0x1E81, 0x0B2A, 0x381B, 0xC27B, 0xF14A, 0xA419, 0x9728, 0x8716, 0xB427, 0xE174, 0xD245, 0x4BD2, 0x78E3, 0x2DB0, 0x1E81, 0x0B2A, 0x381B,
0x6D48, 0x5E79, 0xC7EE, 0xF4DF, 0xA18C, 0x92BD, 0x8283, 0xB1B2, 0xE4E1, 0xD7D0, 0x4E47, 0x7D76, 0x2825, 0x1B14, 0x6D48, 0x5E79, 0xC7EE, 0xF4DF, 0xA18C, 0x92BD, 0x8283, 0xB1B2, 0xE4E1, 0xD7D0, 0x4E47, 0x7D76, 0x2825, 0x1B14,
0x0859, 0x3B68, 0x6E3B, 0x5D0A, 0xC49D, 0xF7AC, 0xA2FF, 0x91CE, 0x81F0, 0xB2C1, 0xE792, 0xD4A3, 0x4D34, 0x7E05, 0x0859, 0x3B68, 0x6E3B, 0x5D0A, 0xC49D, 0xF7AC, 0xA2FF, 0x91CE, 0x81F0, 0xB2C1, 0xE792, 0xD4A3, 0x4D34, 0x7E05,
0x2B56, 0x1867, 0x1B98, 0x28A9, 0x7DFA, 0x4ECB, 0xD75C, 0xE46D, 0xB13E, 0x820F, 0x9231, 0xA100, 0xF453, 0xC762, 0x2B56, 0x1867, 0x1B98, 0x28A9, 0x7DFA, 0x4ECB, 0xD75C, 0xE46D, 0xB13E, 0x820F, 0x9231, 0xA100, 0xF453, 0xC762,
0x5EF5, 0x6DC4, 0x3897, 0x0BA6, 0x18EB, 0x2BDA, 0x7E89, 0x4DB8, 0xD42F, 0xE71E, 0xB24D, 0x817C, 0x9142, 0xA273, 0x5EF5, 0x6DC4, 0x3897, 0x0BA6, 0x18EB, 0x2BDA, 0x7E89, 0x4DB8, 0xD42F, 0xE71E, 0xB24D, 0x817C, 0x9142, 0xA273,
0xF720, 0xC411, 0x5D86, 0x6EB7, 0x3BE4, 0x08D5, 0x1D7E, 0x2E4F, 0x7B1C, 0x482D, 0xD1BA, 0xE28B, 0xB7D8, 0x84E9, 0xF720, 0xC411, 0x5D86, 0x6EB7, 0x3BE4, 0x08D5, 0x1D7E, 0x2E4F, 0x7B1C, 0x482D, 0xD1BA, 0xE28B, 0xB7D8, 0x84E9,
0x94D7, 0xA7E6, 0xF2B5, 0xC184, 0x5813, 0x6B22, 0x3E71, 0x0D40, 0x1E0D, 0x2D3C, 0x786F, 0x4B5E, 0xD2C9, 0xE1F8, 0x94D7, 0xA7E6, 0xF2B5, 0xC184, 0x5813, 0x6B22, 0x3E71, 0x0D40, 0x1E0D, 0x2D3C, 0x786F, 0x4B5E, 0xD2C9, 0xE1F8,
0xB4AB, 0x879A, 0x97A4, 0xA495, 0xF1C6, 0xC2F7, 0x5B60, 0x6851, 0x3D02, 0x0E33, 0x1654, 0x2565, 0x7036, 0x4307, 0xB4AB, 0x879A, 0x97A4, 0xA495, 0xF1C6, 0xC2F7, 0x5B60, 0x6851, 0x3D02, 0x0E33, 0x1654, 0x2565, 0x7036, 0x4307,
0xDA90, 0xE9A1, 0xBCF2, 0x8FC3, 0x9FFD, 0xACCC, 0xF99F, 0xCAAE, 0x5339, 0x6008, 0x355B, 0x066A, 0x1527, 0x2616, 0xDA90, 0xE9A1, 0xBCF2, 0x8FC3, 0x9FFD, 0xACCC, 0xF99F, 0xCAAE, 0x5339, 0x6008, 0x355B, 0x066A, 0x1527, 0x2616,
0x7345, 0x4074, 0xD9E3, 0xEAD2, 0xBF81, 0x8CB0, 0x9C8E, 0xAFBF, 0xFAEC, 0xC9DD, 0x504A, 0x637B, 0x3628, 0x0519, 0x7345, 0x4074, 0xD9E3, 0xEAD2, 0xBF81, 0x8CB0, 0x9C8E, 0xAFBF, 0xFAEC, 0xC9DD, 0x504A, 0x637B, 0x3628, 0x0519,
0x10B2, 0x2383, 0x76D0, 0x45E1, 0xDC76, 0xEF47, 0xBA14, 0x8925, 0x991B, 0xAA2A, 0xFF79, 0xCC48, 0x55DF, 0x66EE, 0x10B2, 0x2383, 0x76D0, 0x45E1, 0xDC76, 0xEF47, 0xBA14, 0x8925, 0x991B, 0xAA2A, 0xFF79, 0xCC48, 0x55DF, 0x66EE,
0x33BD, 0x008C, 0x13C1, 0x20F0, 0x75A3, 0x4692, 0xDF05, 0xEC34, 0xB967, 0x8A56, 0x9A68, 0xA959, 0xFC0A, 0xCF3B, 0x33BD, 0x008C, 0x13C1, 0x20F0, 0x75A3, 0x4692, 0xDF05, 0xEC34, 0xB967, 0x8A56, 0x9A68, 0xA959, 0xFC0A, 0xCF3B,
0x56AC, 0x659D, 0x30CE, 0x03FF}, 0x56AC, 0x659D, 0x30CE, 0x03FF},
{0x0000, 0x3730, 0x6E60, 0x5950, 0xDCC0, 0xEBF0, 0xB2A0, 0x8590, 0xA9A1, 0x9E91, 0xC7C1, 0xF0F1, 0x7561, 0x4251, {0x0000, 0x3730, 0x6E60, 0x5950, 0xDCC0, 0xEBF0, 0xB2A0, 0x8590, 0xA9A1, 0x9E91, 0xC7C1, 0xF0F1, 0x7561, 0x4251,
0x1B01, 0x2C31, 0x4363, 0x7453, 0x2D03, 0x1A33, 0x9FA3, 0xA893, 0xF1C3, 0xC6F3, 0xEAC2, 0xDDF2, 0x84A2, 0xB392, 0x1B01, 0x2C31, 0x4363, 0x7453, 0x2D03, 0x1A33, 0x9FA3, 0xA893, 0xF1C3, 0xC6F3, 0xEAC2, 0xDDF2, 0x84A2, 0xB392,
0x3602, 0x0132, 0x5862, 0x6F52, 0x86C6, 0xB1F6, 0xE8A6, 0xDF96, 0x5A06, 0x6D36, 0x3466, 0x0356, 0x2F67, 0x1857, 0x3602, 0x0132, 0x5862, 0x6F52, 0x86C6, 0xB1F6, 0xE8A6, 0xDF96, 0x5A06, 0x6D36, 0x3466, 0x0356, 0x2F67, 0x1857,
0x4107, 0x7637, 0xF3A7, 0xC497, 0x9DC7, 0xAAF7, 0xC5A5, 0xF295, 0xABC5, 0x9CF5, 0x1965, 0x2E55, 0x7705, 0x4035, 0x4107, 0x7637, 0xF3A7, 0xC497, 0x9DC7, 0xAAF7, 0xC5A5, 0xF295, 0xABC5, 0x9CF5, 0x1965, 0x2E55, 0x7705, 0x4035,
0x6C04, 0x5B34, 0x0264, 0x3554, 0xB0C4, 0x87F4, 0xDEA4, 0xE994, 0x1DAD, 0x2A9D, 0x73CD, 0x44FD, 0xC16D, 0xF65D, 0x6C04, 0x5B34, 0x0264, 0x3554, 0xB0C4, 0x87F4, 0xDEA4, 0xE994, 0x1DAD, 0x2A9D, 0x73CD, 0x44FD, 0xC16D, 0xF65D,
0xAF0D, 0x983D, 0xB40C, 0x833C, 0xDA6C, 0xED5C, 0x68CC, 0x5FFC, 0x06AC, 0x319C, 0x5ECE, 0x69FE, 0x30AE, 0x079E, 0xAF0D, 0x983D, 0xB40C, 0x833C, 0xDA6C, 0xED5C, 0x68CC, 0x5FFC, 0x06AC, 0x319C, 0x5ECE, 0x69FE, 0x30AE, 0x079E,
0x820E, 0xB53E, 0xEC6E, 0xDB5E, 0xF76F, 0xC05F, 0x990F, 0xAE3F, 0x2BAF, 0x1C9F, 0x45CF, 0x72FF, 0x9B6B, 0xAC5B, 0x820E, 0xB53E, 0xEC6E, 0xDB5E, 0xF76F, 0xC05F, 0x990F, 0xAE3F, 0x2BAF, 0x1C9F, 0x45CF, 0x72FF, 0x9B6B, 0xAC5B,
0xF50B, 0xC23B, 0x47AB, 0x709B, 0x29CB, 0x1EFB, 0x32CA, 0x05FA, 0x5CAA, 0x6B9A, 0xEE0A, 0xD93A, 0x806A, 0xB75A, 0xF50B, 0xC23B, 0x47AB, 0x709B, 0x29CB, 0x1EFB, 0x32CA, 0x05FA, 0x5CAA, 0x6B9A, 0xEE0A, 0xD93A, 0x806A, 0xB75A,
0xD808, 0xEF38, 0xB668, 0x8158, 0x04C8, 0x33F8, 0x6AA8, 0x5D98, 0x71A9, 0x4699, 0x1FC9, 0x28F9, 0xAD69, 0x9A59, 0xD808, 0xEF38, 0xB668, 0x8158, 0x04C8, 0x33F8, 0x6AA8, 0x5D98, 0x71A9, 0x4699, 0x1FC9, 0x28F9, 0xAD69, 0x9A59,
0xC309, 0xF439, 0x3B5A, 0x0C6A, 0x553A, 0x620A, 0xE79A, 0xD0AA, 0x89FA, 0xBECA, 0x92FB, 0xA5CB, 0xFC9B, 0xCBAB, 0xC309, 0xF439, 0x3B5A, 0x0C6A, 0x553A, 0x620A, 0xE79A, 0xD0AA, 0x89FA, 0xBECA, 0x92FB, 0xA5CB, 0xFC9B, 0xCBAB,
0x4E3B, 0x790B, 0x205B, 0x176B, 0x7839, 0x4F09, 0x1659, 0x2169, 0xA4F9, 0x93C9, 0xCA99, 0xFDA9, 0xD198, 0xE6A8, 0x4E3B, 0x790B, 0x205B, 0x176B, 0x7839, 0x4F09, 0x1659, 0x2169, 0xA4F9, 0x93C9, 0xCA99, 0xFDA9, 0xD198, 0xE6A8,
0xBFF8, 0x88C8, 0x0D58, 0x3A68, 0x6338, 0x5408, 0xBD9C, 0x8AAC, 0xD3FC, 0xE4CC, 0x615C, 0x566C, 0x0F3C, 0x380C, 0xBFF8, 0x88C8, 0x0D58, 0x3A68, 0x6338, 0x5408, 0xBD9C, 0x8AAC, 0xD3FC, 0xE4CC, 0x615C, 0x566C, 0x0F3C, 0x380C,
0x143D, 0x230D, 0x7A5D, 0x4D6D, 0xC8FD, 0xFFCD, 0xA69D, 0x91AD, 0xFEFF, 0xC9CF, 0x909F, 0xA7AF, 0x223F, 0x150F, 0x143D, 0x230D, 0x7A5D, 0x4D6D, 0xC8FD, 0xFFCD, 0xA69D, 0x91AD, 0xFEFF, 0xC9CF, 0x909F, 0xA7AF, 0x223F, 0x150F,
0x4C5F, 0x7B6F, 0x575E, 0x606E, 0x393E, 0x0E0E, 0x8B9E, 0xBCAE, 0xE5FE, 0xD2CE, 0x26F7, 0x11C7, 0x4897, 0x7FA7, 0x4C5F, 0x7B6F, 0x575E, 0x606E, 0x393E, 0x0E0E, 0x8B9E, 0xBCAE, 0xE5FE, 0xD2CE, 0x26F7, 0x11C7, 0x4897, 0x7FA7,
0xFA37, 0xCD07, 0x9457, 0xA367, 0x8F56, 0xB866, 0xE136, 0xD606, 0x5396, 0x64A6, 0x3DF6, 0x0AC6, 0x6594, 0x52A4, 0xFA37, 0xCD07, 0x9457, 0xA367, 0x8F56, 0xB866, 0xE136, 0xD606, 0x5396, 0x64A6, 0x3DF6, 0x0AC6, 0x6594, 0x52A4,
0x0BF4, 0x3CC4, 0xB954, 0x8E64, 0xD734, 0xE004, 0xCC35, 0xFB05, 0xA255, 0x9565, 0x10F5, 0x27C5, 0x7E95, 0x49A5, 0x0BF4, 0x3CC4, 0xB954, 0x8E64, 0xD734, 0xE004, 0xCC35, 0xFB05, 0xA255, 0x9565, 0x10F5, 0x27C5, 0x7E95, 0x49A5,
0xA031, 0x9701, 0xCE51, 0xF961, 0x7CF1, 0x4BC1, 0x1291, 0x25A1, 0x0990, 0x3EA0, 0x67F0, 0x50C0, 0xD550, 0xE260, 0xA031, 0x9701, 0xCE51, 0xF961, 0x7CF1, 0x4BC1, 0x1291, 0x25A1, 0x0990, 0x3EA0, 0x67F0, 0x50C0, 0xD550, 0xE260,
0xBB30, 0x8C00, 0xE352, 0xD462, 0x8D32, 0xBA02, 0x3F92, 0x08A2, 0x51F2, 0x66C2, 0x4AF3, 0x7DC3, 0x2493, 0x13A3, 0xBB30, 0x8C00, 0xE352, 0xD462, 0x8D32, 0xBA02, 0x3F92, 0x08A2, 0x51F2, 0x66C2, 0x4AF3, 0x7DC3, 0x2493, 0x13A3,
0x9633, 0xA103, 0xF853, 0xCF63}, 0x9633, 0xA103, 0xF853, 0xCF63},
{0x0000, 0x76B4, 0xED68, 0x9BDC, 0xCAF1, 0xBC45, 0x2799, 0x512D, 0x85C3, 0xF377, 0x68AB, 0x1E1F, 0x4F32, 0x3986, {0x0000, 0x76B4, 0xED68, 0x9BDC, 0xCAF1, 0xBC45, 0x2799, 0x512D, 0x85C3, 0xF377, 0x68AB, 0x1E1F, 0x4F32, 0x3986,
0xA25A, 0xD4EE, 0x1BA7, 0x6D13, 0xF6CF, 0x807B, 0xD156, 0xA7E2, 0x3C3E, 0x4A8A, 0x9E64, 0xE8D0, 0x730C, 0x05B8, 0xA25A, 0xD4EE, 0x1BA7, 0x6D13, 0xF6CF, 0x807B, 0xD156, 0xA7E2, 0x3C3E, 0x4A8A, 0x9E64, 0xE8D0, 0x730C, 0x05B8,
0x5495, 0x2221, 0xB9FD, 0xCF49, 0x374E, 0x41FA, 0xDA26, 0xAC92, 0xFDBF, 0x8B0B, 0x10D7, 0x6663, 0xB28D, 0xC439, 0x5495, 0x2221, 0xB9FD, 0xCF49, 0x374E, 0x41FA, 0xDA26, 0xAC92, 0xFDBF, 0x8B0B, 0x10D7, 0x6663, 0xB28D, 0xC439,
0x5FE5, 0x2951, 0x787C, 0x0EC8, 0x9514, 0xE3A0, 0x2CE9, 0x5A5D, 0xC181, 0xB735, 0xE618, 0x90AC, 0x0B70, 0x7DC4, 0x5FE5, 0x2951, 0x787C, 0x0EC8, 0x9514, 0xE3A0, 0x2CE9, 0x5A5D, 0xC181, 0xB735, 0xE618, 0x90AC, 0x0B70, 0x7DC4,
0xA92A, 0xDF9E, 0x4442, 0x32F6, 0x63DB, 0x156F, 0x8EB3, 0xF807, 0x6E9C, 0x1828, 0x83F4, 0xF540, 0xA46D, 0xD2D9, 0xA92A, 0xDF9E, 0x4442, 0x32F6, 0x63DB, 0x156F, 0x8EB3, 0xF807, 0x6E9C, 0x1828, 0x83F4, 0xF540, 0xA46D, 0xD2D9,
0x4905, 0x3FB1, 0xEB5F, 0x9DEB, 0x0637, 0x7083, 0x21AE, 0x571A, 0xCCC6, 0xBA72, 0x753B, 0x038F, 0x9853, 0xEEE7, 0x4905, 0x3FB1, 0xEB5F, 0x9DEB, 0x0637, 0x7083, 0x21AE, 0x571A, 0xCCC6, 0xBA72, 0x753B, 0x038F, 0x9853, 0xEEE7,
0xBFCA, 0xC97E, 0x52A2, 0x2416, 0xF0F8, 0x864C, 0x1D90, 0x6B24, 0x3A09, 0x4CBD, 0xD761, 0xA1D5, 0x59D2, 0x2F66, 0xBFCA, 0xC97E, 0x52A2, 0x2416, 0xF0F8, 0x864C, 0x1D90, 0x6B24, 0x3A09, 0x4CBD, 0xD761, 0xA1D5, 0x59D2, 0x2F66,
0xB4BA, 0xC20E, 0x9323, 0xE597, 0x7E4B, 0x08FF, 0xDC11, 0xAAA5, 0x3179, 0x47CD, 0x16E0, 0x6054, 0xFB88, 0x8D3C, 0xB4BA, 0xC20E, 0x9323, 0xE597, 0x7E4B, 0x08FF, 0xDC11, 0xAAA5, 0x3179, 0x47CD, 0x16E0, 0x6054, 0xFB88, 0x8D3C,
0x4275, 0x34C1, 0xAF1D, 0xD9A9, 0x8884, 0xFE30, 0x65EC, 0x1358, 0xC7B6, 0xB102, 0x2ADE, 0x5C6A, 0x0D47, 0x7BF3, 0x4275, 0x34C1, 0xAF1D, 0xD9A9, 0x8884, 0xFE30, 0x65EC, 0x1358, 0xC7B6, 0xB102, 0x2ADE, 0x5C6A, 0x0D47, 0x7BF3,
0xE02F, 0x969B, 0xDD38, 0xAB8C, 0x3050, 0x46E4, 0x17C9, 0x617D, 0xFAA1, 0x8C15, 0x58FB, 0x2E4F, 0xB593, 0xC327, 0xE02F, 0x969B, 0xDD38, 0xAB8C, 0x3050, 0x46E4, 0x17C9, 0x617D, 0xFAA1, 0x8C15, 0x58FB, 0x2E4F, 0xB593, 0xC327,
0x920A, 0xE4BE, 0x7F62, 0x09D6, 0xC69F, 0xB02B, 0x2BF7, 0x5D43, 0x0C6E, 0x7ADA, 0xE106, 0x97B2, 0x435C, 0x35E8, 0x920A, 0xE4BE, 0x7F62, 0x09D6, 0xC69F, 0xB02B, 0x2BF7, 0x5D43, 0x0C6E, 0x7ADA, 0xE106, 0x97B2, 0x435C, 0x35E8,
0xAE34, 0xD880, 0x89AD, 0xFF19, 0x64C5, 0x1271, 0xEA76, 0x9CC2, 0x071E, 0x71AA, 0x2087, 0x5633, 0xCDEF, 0xBB5B, 0xAE34, 0xD880, 0x89AD, 0xFF19, 0x64C5, 0x1271, 0xEA76, 0x9CC2, 0x071E, 0x71AA, 0x2087, 0x5633, 0xCDEF, 0xBB5B,
0x6FB5, 0x1901, 0x82DD, 0xF469, 0xA544, 0xD3F0, 0x482C, 0x3E98, 0xF1D1, 0x8765, 0x1CB9, 0x6A0D, 0x3B20, 0x4D94, 0x6FB5, 0x1901, 0x82DD, 0xF469, 0xA544, 0xD3F0, 0x482C, 0x3E98, 0xF1D1, 0x8765, 0x1CB9, 0x6A0D, 0x3B20, 0x4D94,
0xD648, 0xA0FC, 0x7412, 0x02A6, 0x997A, 0xEFCE, 0xBEE3, 0xC857, 0x538B, 0x253F, 0xB3A4, 0xC510, 0x5ECC, 0x2878, 0xD648, 0xA0FC, 0x7412, 0x02A6, 0x997A, 0xEFCE, 0xBEE3, 0xC857, 0x538B, 0x253F, 0xB3A4, 0xC510, 0x5ECC, 0x2878,
0x7955, 0x0FE1, 0x943D, 0xE289, 0x3667, 0x40D3, 0xDB0F, 0xADBB, 0xFC96, 0x8A22, 0x11FE, 0x674A, 0xA803, 0xDEB7, 0x7955, 0x0FE1, 0x943D, 0xE289, 0x3667, 0x40D3, 0xDB0F, 0xADBB, 0xFC96, 0x8A22, 0x11FE, 0x674A, 0xA803, 0xDEB7,
0x456B, 0x33DF, 0x62F2, 0x1446, 0x8F9A, 0xF92E, 0x2DC0, 0x5B74, 0xC0A8, 0xB61C, 0xE731, 0x9185, 0x0A59, 0x7CED, 0x456B, 0x33DF, 0x62F2, 0x1446, 0x8F9A, 0xF92E, 0x2DC0, 0x5B74, 0xC0A8, 0xB61C, 0xE731, 0x9185, 0x0A59, 0x7CED,
0x84EA, 0xF25E, 0x6982, 0x1F36, 0x4E1B, 0x38AF, 0xA373, 0xD5C7, 0x0129, 0x779D, 0xEC41, 0x9AF5, 0xCBD8, 0xBD6C, 0x84EA, 0xF25E, 0x6982, 0x1F36, 0x4E1B, 0x38AF, 0xA373, 0xD5C7, 0x0129, 0x779D, 0xEC41, 0x9AF5, 0xCBD8, 0xBD6C,
0x26B0, 0x5004, 0x9F4D, 0xE9F9, 0x7225, 0x0491, 0x55BC, 0x2308, 0xB8D4, 0xCE60, 0x1A8E, 0x6C3A, 0xF7E6, 0x8152, 0x26B0, 0x5004, 0x9F4D, 0xE9F9, 0x7225, 0x0491, 0x55BC, 0x2308, 0xB8D4, 0xCE60, 0x1A8E, 0x6C3A, 0xF7E6, 0x8152,
0xD07F, 0xA6CB, 0x3D17, 0x4BA3}, 0xD07F, 0xA6CB, 0x3D17, 0x4BA3},
{0x0000, 0xAA51, 0x4483, 0xEED2, 0x8906, 0x2357, 0xCD85, 0x67D4, 0x022D, 0xA87C, 0x46AE, 0xECFF, 0x8B2B, 0x217A, {0x0000, 0xAA51, 0x4483, 0xEED2, 0x8906, 0x2357, 0xCD85, 0x67D4, 0x022D, 0xA87C, 0x46AE, 0xECFF, 0x8B2B, 0x217A,
0xCFA8, 0x65F9, 0x045A, 0xAE0B, 0x40D9, 0xEA88, 0x8D5C, 0x270D, 0xC9DF, 0x638E, 0x0677, 0xAC26, 0x42F4, 0xE8A5, 0xCFA8, 0x65F9, 0x045A, 0xAE0B, 0x40D9, 0xEA88, 0x8D5C, 0x270D, 0xC9DF, 0x638E, 0x0677, 0xAC26, 0x42F4, 0xE8A5,
0x8F71, 0x2520, 0xCBF2, 0x61A3, 0x08B4, 0xA2E5, 0x4C37, 0xE666, 0x81B2, 0x2BE3, 0xC531, 0x6F60, 0x0A99, 0xA0C8, 0x8F71, 0x2520, 0xCBF2, 0x61A3, 0x08B4, 0xA2E5, 0x4C37, 0xE666, 0x81B2, 0x2BE3, 0xC531, 0x6F60, 0x0A99, 0xA0C8,
0x4E1A, 0xE44B, 0x839F, 0x29CE, 0xC71C, 0x6D4D, 0x0CEE, 0xA6BF, 0x486D, 0xE23C, 0x85E8, 0x2FB9, 0xC16B, 0x6B3A, 0x4E1A, 0xE44B, 0x839F, 0x29CE, 0xC71C, 0x6D4D, 0x0CEE, 0xA6BF, 0x486D, 0xE23C, 0x85E8, 0x2FB9, 0xC16B, 0x6B3A,
0x0EC3, 0xA492, 0x4A40, 0xE011, 0x87C5, 0x2D94, 0xC346, 0x6917, 0x1168, 0xBB39, 0x55EB, 0xFFBA, 0x986E, 0x323F, 0x0EC3, 0xA492, 0x4A40, 0xE011, 0x87C5, 0x2D94, 0xC346, 0x6917, 0x1168, 0xBB39, 0x55EB, 0xFFBA, 0x986E, 0x323F,
0xDCED, 0x76BC, 0x1345, 0xB914, 0x57C6, 0xFD97, 0x9A43, 0x3012, 0xDEC0, 0x7491, 0x1532, 0xBF63, 0x51B1, 0xFBE0, 0xDCED, 0x76BC, 0x1345, 0xB914, 0x57C6, 0xFD97, 0x9A43, 0x3012, 0xDEC0, 0x7491, 0x1532, 0xBF63, 0x51B1, 0xFBE0,
0x9C34, 0x3665, 0xD8B7, 0x72E6, 0x171F, 0xBD4E, 0x539C, 0xF9CD, 0x9E19, 0x3448, 0xDA9A, 0x70CB, 0x19DC, 0xB38D, 0x9C34, 0x3665, 0xD8B7, 0x72E6, 0x171F, 0xBD4E, 0x539C, 0xF9CD, 0x9E19, 0x3448, 0xDA9A, 0x70CB, 0x19DC, 0xB38D,
0x5D5F, 0xF70E, 0x90DA, 0x3A8B, 0xD459, 0x7E08, 0x1BF1, 0xB1A0, 0x5F72, 0xF523, 0x92F7, 0x38A6, 0xD674, 0x7C25, 0x5D5F, 0xF70E, 0x90DA, 0x3A8B, 0xD459, 0x7E08, 0x1BF1, 0xB1A0, 0x5F72, 0xF523, 0x92F7, 0x38A6, 0xD674, 0x7C25,
0x1D86, 0xB7D7, 0x5905, 0xF354, 0x9480, 0x3ED1, 0xD003, 0x7A52, 0x1FAB, 0xB5FA, 0x5B28, 0xF179, 0x96AD, 0x3CFC, 0x1D86, 0xB7D7, 0x5905, 0xF354, 0x9480, 0x3ED1, 0xD003, 0x7A52, 0x1FAB, 0xB5FA, 0x5B28, 0xF179, 0x96AD, 0x3CFC,
0xD22E, 0x787F, 0x22D0, 0x8881, 0x6653, 0xCC02, 0xABD6, 0x0187, 0xEF55, 0x4504, 0x20FD, 0x8AAC, 0x647E, 0xCE2F, 0xD22E, 0x787F, 0x22D0, 0x8881, 0x6653, 0xCC02, 0xABD6, 0x0187, 0xEF55, 0x4504, 0x20FD, 0x8AAC, 0x647E, 0xCE2F,
0xA9FB, 0x03AA, 0xED78, 0x4729, 0x268A, 0x8CDB, 0x6209, 0xC858, 0xAF8C, 0x05DD, 0xEB0F, 0x415E, 0x24A7, 0x8EF6, 0xA9FB, 0x03AA, 0xED78, 0x4729, 0x268A, 0x8CDB, 0x6209, 0xC858, 0xAF8C, 0x05DD, 0xEB0F, 0x415E, 0x24A7, 0x8EF6,
0x6024, 0xCA75, 0xADA1, 0x07F0, 0xE922, 0x4373, 0x2A64, 0x8035, 0x6EE7, 0xC4B6, 0xA362, 0x0933, 0xE7E1, 0x4DB0, 0x6024, 0xCA75, 0xADA1, 0x07F0, 0xE922, 0x4373, 0x2A64, 0x8035, 0x6EE7, 0xC4B6, 0xA362, 0x0933, 0xE7E1, 0x4DB0,
0x2849, 0x8218, 0x6CCA, 0xC69B, 0xA14F, 0x0B1E, 0xE5CC, 0x4F9D, 0x2E3E, 0x846F, 0x6ABD, 0xC0EC, 0xA738, 0x0D69, 0x2849, 0x8218, 0x6CCA, 0xC69B, 0xA14F, 0x0B1E, 0xE5CC, 0x4F9D, 0x2E3E, 0x846F, 0x6ABD, 0xC0EC, 0xA738, 0x0D69,
0xE3BB, 0x49EA, 0x2C13, 0x8642, 0x6890, 0xC2C1, 0xA515, 0x0F44, 0xE196, 0x4BC7, 0x33B8, 0x99E9, 0x773B, 0xDD6A, 0xE3BB, 0x49EA, 0x2C13, 0x8642, 0x6890, 0xC2C1, 0xA515, 0x0F44, 0xE196, 0x4BC7, 0x33B8, 0x99E9, 0x773B, 0xDD6A,
0xBABE, 0x10EF, 0xFE3D, 0x546C, 0x3195, 0x9BC4, 0x7516, 0xDF47, 0xB893, 0x12C2, 0xFC10, 0x5641, 0x37E2, 0x9DB3, 0xBABE, 0x10EF, 0xFE3D, 0x546C, 0x3195, 0x9BC4, 0x7516, 0xDF47, 0xB893, 0x12C2, 0xFC10, 0x5641, 0x37E2, 0x9DB3,
0x7361, 0xD930, 0xBEE4, 0x14B5, 0xFA67, 0x5036, 0x35CF, 0x9F9E, 0x714C, 0xDB1D, 0xBCC9, 0x1698, 0xF84A, 0x521B, 0x7361, 0xD930, 0xBEE4, 0x14B5, 0xFA67, 0x5036, 0x35CF, 0x9F9E, 0x714C, 0xDB1D, 0xBCC9, 0x1698, 0xF84A, 0x521B,
0x3B0C, 0x915D, 0x7F8F, 0xD5DE, 0xB20A, 0x185B, 0xF689, 0x5CD8, 0x3921, 0x9370, 0x7DA2, 0xD7F3, 0xB027, 0x1A76, 0x3B0C, 0x915D, 0x7F8F, 0xD5DE, 0xB20A, 0x185B, 0xF689, 0x5CD8, 0x3921, 0x9370, 0x7DA2, 0xD7F3, 0xB027, 0x1A76,
0xF4A4, 0x5EF5, 0x3F56, 0x9507, 0x7BD5, 0xD184, 0xB650, 0x1C01, 0xF2D3, 0x5882, 0x3D7B, 0x972A, 0x79F8, 0xD3A9, 0xF4A4, 0x5EF5, 0x3F56, 0x9507, 0x7BD5, 0xD184, 0xB650, 0x1C01, 0xF2D3, 0x5882, 0x3D7B, 0x972A, 0x79F8, 0xD3A9,
0xB47D, 0x1E2C, 0xF0FE, 0x5AAF}, 0xB47D, 0x1E2C, 0xF0FE, 0x5AAF},
{0x0000, 0x45A0, 0x8B40, 0xCEE0, 0x06A1, 0x4301, 0x8DE1, 0xC841, 0x0D42, 0x48E2, 0x8602, 0xC3A2, 0x0BE3, 0x4E43, {0x0000, 0x45A0, 0x8B40, 0xCEE0, 0x06A1, 0x4301, 0x8DE1, 0xC841, 0x0D42, 0x48E2, 0x8602, 0xC3A2, 0x0BE3, 0x4E43,
0x80A3, 0xC503, 0x1A84, 0x5F24, 0x91C4, 0xD464, 0x1C25, 0x5985, 0x9765, 0xD2C5, 0x17C6, 0x5266, 0x9C86, 0xD926, 0x80A3, 0xC503, 0x1A84, 0x5F24, 0x91C4, 0xD464, 0x1C25, 0x5985, 0x9765, 0xD2C5, 0x17C6, 0x5266, 0x9C86, 0xD926,
0x1167, 0x54C7, 0x9A27, 0xDF87, 0x3508, 0x70A8, 0xBE48, 0xFBE8, 0x33A9, 0x7609, 0xB8E9, 0xFD49, 0x384A, 0x7DEA, 0x1167, 0x54C7, 0x9A27, 0xDF87, 0x3508, 0x70A8, 0xBE48, 0xFBE8, 0x33A9, 0x7609, 0xB8E9, 0xFD49, 0x384A, 0x7DEA,
0xB30A, 0xF6AA, 0x3EEB, 0x7B4B, 0xB5AB, 0xF00B, 0x2F8C, 0x6A2C, 0xA4CC, 0xE16C, 0x292D, 0x6C8D, 0xA26D, 0xE7CD, 0xB30A, 0xF6AA, 0x3EEB, 0x7B4B, 0xB5AB, 0xF00B, 0x2F8C, 0x6A2C, 0xA4CC, 0xE16C, 0x292D, 0x6C8D, 0xA26D, 0xE7CD,
0x22CE, 0x676E, 0xA98E, 0xEC2E, 0x246F, 0x61CF, 0xAF2F, 0xEA8F, 0x6A10, 0x2FB0, 0xE150, 0xA4F0, 0x6CB1, 0x2911, 0x22CE, 0x676E, 0xA98E, 0xEC2E, 0x246F, 0x61CF, 0xAF2F, 0xEA8F, 0x6A10, 0x2FB0, 0xE150, 0xA4F0, 0x6CB1, 0x2911,
0xE7F1, 0xA251, 0x6752, 0x22F2, 0xEC12, 0xA9B2, 0x61F3, 0x2453, 0xEAB3, 0xAF13, 0x7094, 0x3534, 0xFBD4, 0xBE74, 0xE7F1, 0xA251, 0x6752, 0x22F2, 0xEC12, 0xA9B2, 0x61F3, 0x2453, 0xEAB3, 0xAF13, 0x7094, 0x3534, 0xFBD4, 0xBE74,
0x7635, 0x3395, 0xFD75, 0xB8D5, 0x7DD6, 0x3876, 0xF696, 0xB336, 0x7B77, 0x3ED7, 0xF037, 0xB597, 0x5F18, 0x1AB8, 0x7635, 0x3395, 0xFD75, 0xB8D5, 0x7DD6, 0x3876, 0xF696, 0xB336, 0x7B77, 0x3ED7, 0xF037, 0xB597, 0x5F18, 0x1AB8,
0xD458, 0x91F8, 0x59B9, 0x1C19, 0xD2F9, 0x9759, 0x525A, 0x17FA, 0xD91A, 0x9CBA, 0x54FB, 0x115B, 0xDFBB, 0x9A1B, 0xD458, 0x91F8, 0x59B9, 0x1C19, 0xD2F9, 0x9759, 0x525A, 0x17FA, 0xD91A, 0x9CBA, 0x54FB, 0x115B, 0xDFBB, 0x9A1B,
0x459C, 0x003C, 0xCEDC, 0x8B7C, 0x433D, 0x069D, 0xC87D, 0x8DDD, 0x48DE, 0x0D7E, 0xC39E, 0x863E, 0x4E7F, 0x0BDF, 0x459C, 0x003C, 0xCEDC, 0x8B7C, 0x433D, 0x069D, 0xC87D, 0x8DDD, 0x48DE, 0x0D7E, 0xC39E, 0x863E, 0x4E7F, 0x0BDF,
0xC53F, 0x809F, 0xD420, 0x9180, 0x5F60, 0x1AC0, 0xD281, 0x9721, 0x59C1, 0x1C61, 0xD962, 0x9CC2, 0x5222, 0x1782, 0xC53F, 0x809F, 0xD420, 0x9180, 0x5F60, 0x1AC0, 0xD281, 0x9721, 0x59C1, 0x1C61, 0xD962, 0x9CC2, 0x5222, 0x1782,
0xDFC3, 0x9A63, 0x5483, 0x1123, 0xCEA4, 0x8B04, 0x45E4, 0x0044, 0xC805, 0x8DA5, 0x4345, 0x06E5, 0xC3E6, 0x8646, 0xDFC3, 0x9A63, 0x5483, 0x1123, 0xCEA4, 0x8B04, 0x45E4, 0x0044, 0xC805, 0x8DA5, 0x4345, 0x06E5, 0xC3E6, 0x8646,
0x48A6, 0x0D06, 0xC547, 0x80E7, 0x4E07, 0x0BA7, 0xE128, 0xA488, 0x6A68, 0x2FC8, 0xE789, 0xA229, 0x6CC9, 0x2969, 0x48A6, 0x0D06, 0xC547, 0x80E7, 0x4E07, 0x0BA7, 0xE128, 0xA488, 0x6A68, 0x2FC8, 0xE789, 0xA229, 0x6CC9, 0x2969,
0xEC6A, 0xA9CA, 0x672A, 0x228A, 0xEACB, 0xAF6B, 0x618B, 0x242B, 0xFBAC, 0xBE0C, 0x70EC, 0x354C, 0xFD0D, 0xB8AD, 0xEC6A, 0xA9CA, 0x672A, 0x228A, 0xEACB, 0xAF6B, 0x618B, 0x242B, 0xFBAC, 0xBE0C, 0x70EC, 0x354C, 0xFD0D, 0xB8AD,
0x764D, 0x33ED, 0xF6EE, 0xB34E, 0x7DAE, 0x380E, 0xF04F, 0xB5EF, 0x7B0F, 0x3EAF, 0xBE30, 0xFB90, 0x3570, 0x70D0, 0x764D, 0x33ED, 0xF6EE, 0xB34E, 0x7DAE, 0x380E, 0xF04F, 0xB5EF, 0x7B0F, 0x3EAF, 0xBE30, 0xFB90, 0x3570, 0x70D0,
0xB891, 0xFD31, 0x33D1, 0x7671, 0xB372, 0xF6D2, 0x3832, 0x7D92, 0xB5D3, 0xF073, 0x3E93, 0x7B33, 0xA4B4, 0xE114, 0xB891, 0xFD31, 0x33D1, 0x7671, 0xB372, 0xF6D2, 0x3832, 0x7D92, 0xB5D3, 0xF073, 0x3E93, 0x7B33, 0xA4B4, 0xE114,
0x2FF4, 0x6A54, 0xA215, 0xE7B5, 0x2955, 0x6CF5, 0xA9F6, 0xEC56, 0x22B6, 0x6716, 0xAF57, 0xEAF7, 0x2417, 0x61B7, 0x2FF4, 0x6A54, 0xA215, 0xE7B5, 0x2955, 0x6CF5, 0xA9F6, 0xEC56, 0x22B6, 0x6716, 0xAF57, 0xEAF7, 0x2417, 0x61B7,
0x8B38, 0xCE98, 0x0078, 0x45D8, 0x8D99, 0xC839, 0x06D9, 0x4379, 0x867A, 0xC3DA, 0x0D3A, 0x489A, 0x80DB, 0xC57B, 0x8B38, 0xCE98, 0x0078, 0x45D8, 0x8D99, 0xC839, 0x06D9, 0x4379, 0x867A, 0xC3DA, 0x0D3A, 0x489A, 0x80DB, 0xC57B,
0x0B9B, 0x4E3B, 0x91BC, 0xD41C, 0x1AFC, 0x5F5C, 0x971D, 0xD2BD, 0x1C5D, 0x59FD, 0x9CFE, 0xD95E, 0x17BE, 0x521E, 0x0B9B, 0x4E3B, 0x91BC, 0xD41C, 0x1AFC, 0x5F5C, 0x971D, 0xD2BD, 0x1C5D, 0x59FD, 0x9CFE, 0xD95E, 0x17BE, 0x521E,
0x9A5F, 0xDFFF, 0x111F, 0x54BF}, 0x9A5F, 0xDFFF, 0x111F, 0x54BF},
{0x0000, 0xB861, 0x60E3, 0xD882, 0xC1C6, 0x79A7, 0xA125, 0x1944, 0x93AD, 0x2BCC, 0xF34E, 0x4B2F, 0x526B, 0xEA0A, {0x0000, 0xB861, 0x60E3, 0xD882, 0xC1C6, 0x79A7, 0xA125, 0x1944, 0x93AD, 0x2BCC, 0xF34E, 0x4B2F, 0x526B, 0xEA0A,
0x3288, 0x8AE9, 0x377B, 0x8F1A, 0x5798, 0xEFF9, 0xF6BD, 0x4EDC, 0x965E, 0x2E3F, 0xA4D6, 0x1CB7, 0xC435, 0x7C54, 0x3288, 0x8AE9, 0x377B, 0x8F1A, 0x5798, 0xEFF9, 0xF6BD, 0x4EDC, 0x965E, 0x2E3F, 0xA4D6, 0x1CB7, 0xC435, 0x7C54,
0x6510, 0xDD71, 0x05F3, 0xBD92, 0x6EF6, 0xD697, 0x0E15, 0xB674, 0xAF30, 0x1751, 0xCFD3, 0x77B2, 0xFD5B, 0x453A, 0x6510, 0xDD71, 0x05F3, 0xBD92, 0x6EF6, 0xD697, 0x0E15, 0xB674, 0xAF30, 0x1751, 0xCFD3, 0x77B2, 0xFD5B, 0x453A,
0x9DB8, 0x25D9, 0x3C9D, 0x84FC, 0x5C7E, 0xE41F, 0x598D, 0xE1EC, 0x396E, 0x810F, 0x984B, 0x202A, 0xF8A8, 0x40C9, 0x9DB8, 0x25D9, 0x3C9D, 0x84FC, 0x5C7E, 0xE41F, 0x598D, 0xE1EC, 0x396E, 0x810F, 0x984B, 0x202A, 0xF8A8, 0x40C9,
0xCA20, 0x7241, 0xAAC3, 0x12A2, 0x0BE6, 0xB387, 0x6B05, 0xD364, 0xDDEC, 0x658D, 0xBD0F, 0x056E, 0x1C2A, 0xA44B, 0xCA20, 0x7241, 0xAAC3, 0x12A2, 0x0BE6, 0xB387, 0x6B05, 0xD364, 0xDDEC, 0x658D, 0xBD0F, 0x056E, 0x1C2A, 0xA44B,
0x7CC9, 0xC4A8, 0x4E41, 0xF620, 0x2EA2, 0x96C3, 0x8F87, 0x37E6, 0xEF64, 0x5705, 0xEA97, 0x52F6, 0x8A74, 0x3215, 0x7CC9, 0xC4A8, 0x4E41, 0xF620, 0x2EA2, 0x96C3, 0x8F87, 0x37E6, 0xEF64, 0x5705, 0xEA97, 0x52F6, 0x8A74, 0x3215,
0x2B51, 0x9330, 0x4BB2, 0xF3D3, 0x793A, 0xC15B, 0x19D9, 0xA1B8, 0xB8FC, 0x009D, 0xD81F, 0x607E, 0xB31A, 0x0B7B, 0x2B51, 0x9330, 0x4BB2, 0xF3D3, 0x793A, 0xC15B, 0x19D9, 0xA1B8, 0xB8FC, 0x009D, 0xD81F, 0x607E, 0xB31A, 0x0B7B,
0xD3F9, 0x6B98, 0x72DC, 0xCABD, 0x123F, 0xAA5E, 0x20B7, 0x98D6, 0x4054, 0xF835, 0xE171, 0x5910, 0x8192, 0x39F3, 0xD3F9, 0x6B98, 0x72DC, 0xCABD, 0x123F, 0xAA5E, 0x20B7, 0x98D6, 0x4054, 0xF835, 0xE171, 0x5910, 0x8192, 0x39F3,
0x8461, 0x3C00, 0xE482, 0x5CE3, 0x45A7, 0xFDC6, 0x2544, 0x9D25, 0x17CC, 0xAFAD, 0x772F, 0xCF4E, 0xD60A, 0x6E6B, 0x8461, 0x3C00, 0xE482, 0x5CE3, 0x45A7, 0xFDC6, 0x2544, 0x9D25, 0x17CC, 0xAFAD, 0x772F, 0xCF4E, 0xD60A, 0x6E6B,
0xB6E9, 0x0E88, 0xABF9, 0x1398, 0xCB1A, 0x737B, 0x6A3F, 0xD25E, 0x0ADC, 0xB2BD, 0x3854, 0x8035, 0x58B7, 0xE0D6, 0xB6E9, 0x0E88, 0xABF9, 0x1398, 0xCB1A, 0x737B, 0x6A3F, 0xD25E, 0x0ADC, 0xB2BD, 0x3854, 0x8035, 0x58B7, 0xE0D6,
0xF992, 0x41F3, 0x9971, 0x2110, 0x9C82, 0x24E3, 0xFC61, 0x4400, 0x5D44, 0xE525, 0x3DA7, 0x85C6, 0x0F2F, 0xB74E, 0xF992, 0x41F3, 0x9971, 0x2110, 0x9C82, 0x24E3, 0xFC61, 0x4400, 0x5D44, 0xE525, 0x3DA7, 0x85C6, 0x0F2F, 0xB74E,
0x6FCC, 0xD7AD, 0xCEE9, 0x7688, 0xAE0A, 0x166B, 0xC50F, 0x7D6E, 0xA5EC, 0x1D8D, 0x04C9, 0xBCA8, 0x642A, 0xDC4B, 0x6FCC, 0xD7AD, 0xCEE9, 0x7688, 0xAE0A, 0x166B, 0xC50F, 0x7D6E, 0xA5EC, 0x1D8D, 0x04C9, 0xBCA8, 0x642A, 0xDC4B,
0x56A2, 0xEEC3, 0x3641, 0x8E20, 0x9764, 0x2F05, 0xF787, 0x4FE6, 0xF274, 0x4A15, 0x9297, 0x2AF6, 0x33B2, 0x8BD3, 0x56A2, 0xEEC3, 0x3641, 0x8E20, 0x9764, 0x2F05, 0xF787, 0x4FE6, 0xF274, 0x4A15, 0x9297, 0x2AF6, 0x33B2, 0x8BD3,
0x5351, 0xEB30, 0x61D9, 0xD9B8, 0x013A, 0xB95B, 0xA01F, 0x187E, 0xC0FC, 0x789D, 0x7615, 0xCE74, 0x16F6, 0xAE97, 0x5351, 0xEB30, 0x61D9, 0xD9B8, 0x013A, 0xB95B, 0xA01F, 0x187E, 0xC0FC, 0x789D, 0x7615, 0xCE74, 0x16F6, 0xAE97,
0xB7D3, 0x0FB2, 0xD730, 0x6F51, 0xE5B8, 0x5DD9, 0x855B, 0x3D3A, 0x247E, 0x9C1F, 0x449D, 0xFCFC, 0x416E, 0xF90F, 0xB7D3, 0x0FB2, 0xD730, 0x6F51, 0xE5B8, 0x5DD9, 0x855B, 0x3D3A, 0x247E, 0x9C1F, 0x449D, 0xFCFC, 0x416E, 0xF90F,
0x218D, 0x99EC, 0x80A8, 0x38C9, 0xE04B, 0x582A, 0xD2C3, 0x6AA2, 0xB220, 0x0A41, 0x1305, 0xAB64, 0x73E6, 0xCB87, 0x218D, 0x99EC, 0x80A8, 0x38C9, 0xE04B, 0x582A, 0xD2C3, 0x6AA2, 0xB220, 0x0A41, 0x1305, 0xAB64, 0x73E6, 0xCB87,
0x18E3, 0xA082, 0x7800, 0xC061, 0xD925, 0x6144, 0xB9C6, 0x01A7, 0x8B4E, 0x332F, 0xEBAD, 0x53CC, 0x4A88, 0xF2E9, 0x18E3, 0xA082, 0x7800, 0xC061, 0xD925, 0x6144, 0xB9C6, 0x01A7, 0x8B4E, 0x332F, 0xEBAD, 0x53CC, 0x4A88, 0xF2E9,
0x2A6B, 0x920A, 0x2F98, 0x97F9, 0x4F7B, 0xF71A, 0xEE5E, 0x563F, 0x8EBD, 0x36DC, 0xBC35, 0x0454, 0xDCD6, 0x64B7, 0x2A6B, 0x920A, 0x2F98, 0x97F9, 0x4F7B, 0xF71A, 0xEE5E, 0x563F, 0x8EBD, 0x36DC, 0xBC35, 0x0454, 0xDCD6, 0x64B7,
0x7DF3, 0xC592, 0x1D10, 0xA571}, 0x7DF3, 0xC592, 0x1D10, 0xA571},
{0x0000, 0x47D3, 0x8FA6, 0xC875, 0x0F6D, 0x48BE, 0x80CB, 0xC718, 0x1EDA, 0x5909, 0x917C, 0xD6AF, 0x11B7, 0x5664, {0x0000, 0x47D3, 0x8FA6, 0xC875, 0x0F6D, 0x48BE, 0x80CB, 0xC718, 0x1EDA, 0x5909, 0x917C, 0xD6AF, 0x11B7, 0x5664,
0x9E11, 0xD9C2, 0x3DB4, 0x7A67, 0xB212, 0xF5C1, 0x32D9, 0x750A, 0xBD7F, 0xFAAC, 0x236E, 0x64BD, 0xACC8, 0xEB1B, 0x9E11, 0xD9C2, 0x3DB4, 0x7A67, 0xB212, 0xF5C1, 0x32D9, 0x750A, 0xBD7F, 0xFAAC, 0x236E, 0x64BD, 0xACC8, 0xEB1B,
0x2C03, 0x6BD0, 0xA3A5, 0xE476, 0x7B68, 0x3CBB, 0xF4CE, 0xB31D, 0x7405, 0x33D6, 0xFBA3, 0xBC70, 0x65B2, 0x2261, 0x2C03, 0x6BD0, 0xA3A5, 0xE476, 0x7B68, 0x3CBB, 0xF4CE, 0xB31D, 0x7405, 0x33D6, 0xFBA3, 0xBC70, 0x65B2, 0x2261,
0xEA14, 0xADC7, 0x6ADF, 0x2D0C, 0xE579, 0xA2AA, 0x46DC, 0x010F, 0xC97A, 0x8EA9, 0x49B1, 0x0E62, 0xC617, 0x81C4, 0xEA14, 0xADC7, 0x6ADF, 0x2D0C, 0xE579, 0xA2AA, 0x46DC, 0x010F, 0xC97A, 0x8EA9, 0x49B1, 0x0E62, 0xC617, 0x81C4,
0x5806, 0x1FD5, 0xD7A0, 0x9073, 0x576B, 0x10B8, 0xD8CD, 0x9F1E, 0xF6D0, 0xB103, 0x7976, 0x3EA5, 0xF9BD, 0xBE6E, 0x5806, 0x1FD5, 0xD7A0, 0x9073, 0x576B, 0x10B8, 0xD8CD, 0x9F1E, 0xF6D0, 0xB103, 0x7976, 0x3EA5, 0xF9BD, 0xBE6E,
0x761B, 0x31C8, 0xE80A, 0xAFD9, 0x67AC, 0x207F, 0xE767, 0xA0B4, 0x68C1, 0x2F12, 0xCB64, 0x8CB7, 0x44C2, 0x0311, 0x761B, 0x31C8, 0xE80A, 0xAFD9, 0x67AC, 0x207F, 0xE767, 0xA0B4, 0x68C1, 0x2F12, 0xCB64, 0x8CB7, 0x44C2, 0x0311,
0xC409, 0x83DA, 0x4BAF, 0x0C7C, 0xD5BE, 0x926D, 0x5A18, 0x1DCB, 0xDAD3, 0x9D00, 0x5575, 0x12A6, 0x8DB8, 0xCA6B, 0xC409, 0x83DA, 0x4BAF, 0x0C7C, 0xD5BE, 0x926D, 0x5A18, 0x1DCB, 0xDAD3, 0x9D00, 0x5575, 0x12A6, 0x8DB8, 0xCA6B,
0x021E, 0x45CD, 0x82D5, 0xC506, 0x0D73, 0x4AA0, 0x9362, 0xD4B1, 0x1CC4, 0x5B17, 0x9C0F, 0xDBDC, 0x13A9, 0x547A, 0x021E, 0x45CD, 0x82D5, 0xC506, 0x0D73, 0x4AA0, 0x9362, 0xD4B1, 0x1CC4, 0x5B17, 0x9C0F, 0xDBDC, 0x13A9, 0x547A,
0xB00C, 0xF7DF, 0x3FAA, 0x7879, 0xBF61, 0xF8B2, 0x30C7, 0x7714, 0xAED6, 0xE905, 0x2170, 0x66A3, 0xA1BB, 0xE668, 0xB00C, 0xF7DF, 0x3FAA, 0x7879, 0xBF61, 0xF8B2, 0x30C7, 0x7714, 0xAED6, 0xE905, 0x2170, 0x66A3, 0xA1BB, 0xE668,
0x2E1D, 0x69CE, 0xFD81, 0xBA52, 0x7227, 0x35F4, 0xF2EC, 0xB53F, 0x7D4A, 0x3A99, 0xE35B, 0xA488, 0x6CFD, 0x2B2E, 0x2E1D, 0x69CE, 0xFD81, 0xBA52, 0x7227, 0x35F4, 0xF2EC, 0xB53F, 0x7D4A, 0x3A99, 0xE35B, 0xA488, 0x6CFD, 0x2B2E,
0xEC36, 0xABE5, 0x6390, 0x2443, 0xC035, 0x87E6, 0x4F93, 0x0840, 0xCF58, 0x888B, 0x40FE, 0x072D, 0xDEEF, 0x993C, 0xEC36, 0xABE5, 0x6390, 0x2443, 0xC035, 0x87E6, 0x4F93, 0x0840, 0xCF58, 0x888B, 0x40FE, 0x072D, 0xDEEF, 0x993C,
0x5149, 0x169A, 0xD182, 0x9651, 0x5E24, 0x19F7, 0x86E9, 0xC13A, 0x094F, 0x4E9C, 0x8984, 0xCE57, 0x0622, 0x41F1, 0x5149, 0x169A, 0xD182, 0x9651, 0x5E24, 0x19F7, 0x86E9, 0xC13A, 0x094F, 0x4E9C, 0x8984, 0xCE57, 0x0622, 0x41F1,
0x9833, 0xDFE0, 0x1795, 0x5046, 0x975E, 0xD08D, 0x18F8, 0x5F2B, 0xBB5D, 0xFC8E, 0x34FB, 0x7328, 0xB430, 0xF3E3, 0x9833, 0xDFE0, 0x1795, 0x5046, 0x975E, 0xD08D, 0x18F8, 0x5F2B, 0xBB5D, 0xFC8E, 0x34FB, 0x7328, 0xB430, 0xF3E3,
0x3B96, 0x7C45, 0xA587, 0xE254, 0x2A21, 0x6DF2, 0xAAEA, 0xED39, 0x254C, 0x629F, 0x0B51, 0x4C82, 0x84F7, 0xC324, 0x3B96, 0x7C45, 0xA587, 0xE254, 0x2A21, 0x6DF2, 0xAAEA, 0xED39, 0x254C, 0x629F, 0x0B51, 0x4C82, 0x84F7, 0xC324,
0x043C, 0x43EF, 0x8B9A, 0xCC49, 0x158B, 0x5258, 0x9A2D, 0xDDFE, 0x1AE6, 0x5D35, 0x9540, 0xD293, 0x36E5, 0x7136, 0x043C, 0x43EF, 0x8B9A, 0xCC49, 0x158B, 0x5258, 0x9A2D, 0xDDFE, 0x1AE6, 0x5D35, 0x9540, 0xD293, 0x36E5, 0x7136,
0xB943, 0xFE90, 0x3988, 0x7E5B, 0xB62E, 0xF1FD, 0x283F, 0x6FEC, 0xA799, 0xE04A, 0x2752, 0x6081, 0xA8F4, 0xEF27, 0xB943, 0xFE90, 0x3988, 0x7E5B, 0xB62E, 0xF1FD, 0x283F, 0x6FEC, 0xA799, 0xE04A, 0x2752, 0x6081, 0xA8F4, 0xEF27,
0x7039, 0x37EA, 0xFF9F, 0xB84C, 0x7F54, 0x3887, 0xF0F2, 0xB721, 0x6EE3, 0x2930, 0xE145, 0xA696, 0x618E, 0x265D, 0x7039, 0x37EA, 0xFF9F, 0xB84C, 0x7F54, 0x3887, 0xF0F2, 0xB721, 0x6EE3, 0x2930, 0xE145, 0xA696, 0x618E, 0x265D,
0xEE28, 0xA9FB, 0x4D8D, 0x0A5E, 0xC22B, 0x85F8, 0x42E0, 0x0533, 0xCD46, 0x8A95, 0x5357, 0x1484, 0xDCF1, 0x9B22, 0xEE28, 0xA9FB, 0x4D8D, 0x0A5E, 0xC22B, 0x85F8, 0x42E0, 0x0533, 0xCD46, 0x8A95, 0x5357, 0x1484, 0xDCF1, 0x9B22,
0x5C3A, 0x1BE9, 0xD39C, 0x944F}}; 0x5C3A, 0x1BE9, 0xD39C, 0x944F}
};
AARU_EXPORT crc16_ccitt_ctx *AARU_CALL crc16_ccitt_init(); AARU_EXPORT crc16_ccitt_ctx *AARU_CALL crc16_ccitt_init();
AARU_EXPORT int AARU_CALL crc16_ccitt_update(crc16_ccitt_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL crc16_ccitt_update(crc16_ccitt_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL crc16_ccitt_final(crc16_ccitt_ctx *ctx, uint16_t *crc); AARU_EXPORT int AARU_CALL crc16_ccitt_final(crc16_ccitt_ctx *ctx, uint16_t *crc);
AARU_EXPORT void AARU_CALL crc16_ccitt_free(crc16_ccitt_ctx *ctx); AARU_EXPORT void AARU_CALL crc16_ccitt_free(crc16_ccitt_ctx *ctx);
#endif // AARU_CHECKSUMS_NATIVE_CRC16_H #endif // AARU_CHECKSUMS_NATIVE_CRC16_H

12
crc32.c
View File

@@ -106,12 +106,12 @@ AARU_EXPORT void AARU_CALL crc32_slicing(uint32_t *previous_crc, const uint8_t *
// Unroll according to Intel slicing by uint8_t // Unroll according to Intel slicing by uint8_t
// http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf // http://www.intel.com/technology/comms/perfnet/download/CRC_generators.pdf
// http://sourceforge.net/projects/slicing-by-8/ // http://sourceforge.net/projects/slicing-by-8/
uint32_t c; uint32_t c;
const uint32_t *current; const uint32_t *current;
const uint8_t *current_char = data; const uint8_t *current_char = data;
const size_t unroll = 4; const size_t unroll = 4;
const size_t bytes_at_once = 8 * unroll; const size_t bytes_at_once = 8 * unroll;
uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3; uintptr_t unaligned_length = (4 - (((uintptr_t)current_char) & 3)) & 3;
c = *previous_crc; c = *previous_crc;
@@ -132,7 +132,7 @@ AARU_EXPORT void AARU_CALL crc32_slicing(uint32_t *previous_crc, const uint8_t *
uint32_t one = *current++ ^ c; uint32_t one = *current++ ^ c;
uint32_t two = *current++; uint32_t two = *current++;
// TODO: Big endian! // TODO: Big endian!
c = crc32_table[0][(two >> 24) & 0xFF] ^ crc32_table[1][(two >> 16) & 0xFF] ^ c = crc32_table[0][(two >> 24) & 0xFF] ^ crc32_table[1][(two >> 16) & 0xFF] ^
crc32_table[2][(two >> 8) & 0xFF] ^ crc32_table[3][two & 0xFF] ^ crc32_table[4][(one >> 24) & 0xFF] ^ crc32_table[2][(two >> 8) & 0xFF] ^ crc32_table[3][two & 0xFF] ^ crc32_table[4][(one >> 24) & 0xFF] ^
crc32_table[5][(one >> 16) & 0xFF] ^ crc32_table[6][(one >> 8) & 0xFF] ^ crc32_table[7][one & 0xFF]; crc32_table[5][(one >> 16) & 0xFF] ^ crc32_table[6][(one >> 8) & 0xFF] ^ crc32_table[7][one & 0xFF];
} }

23
crc32.h
View File

@@ -262,24 +262,23 @@ static const uint32_t crc32_table[8][256] = {
#define CRC32_ISO_POLY 0xEDB88320 #define CRC32_ISO_POLY 0xEDB88320
#define CRC32_ISO_SEED 0xFFFFFFFF #define CRC32_ISO_SEED 0xFFFFFFFF
AARU_EXPORT crc32_ctx* AARU_CALL crc32_init(); AARU_EXPORT crc32_ctx *AARU_CALL crc32_init();
AARU_EXPORT int AARU_CALL crc32_update(crc32_ctx* ctx, const uint8_t* data, uint32_t len); AARU_EXPORT int AARU_CALL crc32_update(crc32_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL crc32_final(crc32_ctx* ctx, uint32_t* crc); AARU_EXPORT int AARU_CALL crc32_final(crc32_ctx *ctx, uint32_t *crc);
AARU_EXPORT void AARU_CALL crc32_free(crc32_ctx* ctx); AARU_EXPORT void AARU_CALL crc32_free(crc32_ctx *ctx);
AARU_EXPORT void AARU_CALL crc32_slicing(uint32_t* previous_crc, const uint8_t* data, long len); AARU_EXPORT void AARU_CALL crc32_slicing(uint32_t *previous_crc, const uint8_t *data, long len);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
AARU_EXPORT TARGET_WITH_CLMUL uint32_t AARU_CALL crc32_clmul(uint32_t previous_crc, const uint8_t* data, long len); AARU_EXPORT TARGET_WITH_CLMUL uint32_t AARU_CALL crc32_clmul(uint32_t previous_crc, const uint8_t *data, long len);
#endif #endif
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) #if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
#if __ARM_ARCH >= 7 #if __ARM_ARCH >= 7
AARU_EXPORT TARGET_ARMV8_WITH_CRC uint32_t AARU_CALL armv8_crc32_little(uint32_t previous_crc, AARU_EXPORT TARGET_ARMV8_WITH_CRC uint32_t AARU_CALL armv8_crc32_little(uint32_t previous_crc, const uint8_t *data,
const uint8_t* data, uint32_t len);
uint32_t len);
#endif #endif
AARU_EXPORT TARGET_WITH_NEON uint32_t AARU_CALL crc32_vmull(uint32_t previous_crc, const uint8_t* data, long len); AARU_EXPORT TARGET_WITH_NEON uint32_t AARU_CALL crc32_vmull(uint32_t previous_crc, const uint8_t *data, long len);
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_CRC32_H #endif // AARU_CHECKSUMS_NATIVE_CRC32_H

View File

@@ -82,7 +82,7 @@ TARGET_ARMV8_WITH_CRC uint32_t armv8_crc32_little(uint32_t previous_crc, const u
} }
data = (const uint8_t *)buf8; data = (const uint8_t *)buf8;
#else // AARCH64 #else // AARCH64
while(len && ((uintptr_t)data & 3)) while(len && ((uintptr_t)data & 3))
{ {
c = __crc32b(c, *data++); c = __crc32b(c, *data++);
@@ -110,8 +110,7 @@ TARGET_ARMV8_WITH_CRC uint32_t armv8_crc32_little(uint32_t previous_crc, const u
data = (const uint8_t *)buf4; data = (const uint8_t *)buf4;
#endif #endif
while(len--) while(len--) { c = __crc32b(c, *data++); }
{ c = __crc32b(c, *data++); }
return c; return c;
} }

View File

@@ -46,9 +46,9 @@ TARGET_WITH_CLMUL static void fold_1(__m128i *xmm_crc0, __m128i *xmm_crc1, __m12
*xmm_crc3 = *xmm_crc0; *xmm_crc3 = *xmm_crc0;
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
ps_res = _mm_xor_ps(ps_crc0, ps_crc3); ps_res = _mm_xor_ps(ps_crc0, ps_crc3);
*xmm_crc0 = *xmm_crc1; *xmm_crc0 = *xmm_crc1;
*xmm_crc1 = *xmm_crc2; *xmm_crc1 = *xmm_crc2;
@@ -69,16 +69,16 @@ TARGET_WITH_CLMUL static void fold_2(__m128i *xmm_crc0, __m128i *xmm_crc1, __m12
*xmm_crc3 = *xmm_crc1; *xmm_crc3 = *xmm_crc1;
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1); ps_res31 = _mm_xor_ps(ps_crc3, ps_crc1);
*xmm_crc2 = *xmm_crc0; *xmm_crc2 = *xmm_crc0;
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2); ps_res20 = _mm_xor_ps(ps_crc0, ps_crc2);
*xmm_crc0 = x_tmp2; *xmm_crc0 = x_tmp2;
*xmm_crc1 = x_tmp3; *xmm_crc1 = x_tmp3;
@@ -98,23 +98,23 @@ TARGET_WITH_CLMUL static void fold_3(__m128i *xmm_crc0, __m128i *xmm_crc1, __m12
*xmm_crc3 = *xmm_crc2; *xmm_crc3 = *xmm_crc2;
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10); *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x10);
ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3); ps_res32 = _mm_xor_ps(ps_crc2, ps_crc3);
*xmm_crc2 = *xmm_crc1; *xmm_crc2 = *xmm_crc1;
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10); *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x10);
ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2); ps_res21 = _mm_xor_ps(ps_crc1, ps_crc2);
*xmm_crc1 = *xmm_crc0; *xmm_crc1 = *xmm_crc0;
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10); *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x10);
ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1); ps_res10 = _mm_xor_ps(ps_crc0, ps_crc1);
*xmm_crc0 = x_tmp3; *xmm_crc0 = x_tmp3;
*xmm_crc1 = _mm_castps_si128(ps_res10); *xmm_crc1 = _mm_castps_si128(ps_res10);
@@ -137,28 +137,28 @@ TARGET_WITH_CLMUL static void fold_4(__m128i *xmm_crc0, __m128i *xmm_crc1, __m12
x_tmp3 = *xmm_crc3; x_tmp3 = *xmm_crc3;
*xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01); *xmm_crc0 = _mm_clmulepi64_si128(*xmm_crc0, xmm_fold4, 0x01);
x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10); x_tmp0 = _mm_clmulepi64_si128(x_tmp0, xmm_fold4, 0x10);
ps_crc0 = _mm_castsi128_ps(*xmm_crc0); ps_crc0 = _mm_castsi128_ps(*xmm_crc0);
ps_t0 = _mm_castsi128_ps(x_tmp0); ps_t0 = _mm_castsi128_ps(x_tmp0);
ps_res0 = _mm_xor_ps(ps_crc0, ps_t0); ps_res0 = _mm_xor_ps(ps_crc0, ps_t0);
*xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01); *xmm_crc1 = _mm_clmulepi64_si128(*xmm_crc1, xmm_fold4, 0x01);
x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10); x_tmp1 = _mm_clmulepi64_si128(x_tmp1, xmm_fold4, 0x10);
ps_crc1 = _mm_castsi128_ps(*xmm_crc1); ps_crc1 = _mm_castsi128_ps(*xmm_crc1);
ps_t1 = _mm_castsi128_ps(x_tmp1); ps_t1 = _mm_castsi128_ps(x_tmp1);
ps_res1 = _mm_xor_ps(ps_crc1, ps_t1); ps_res1 = _mm_xor_ps(ps_crc1, ps_t1);
*xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01); *xmm_crc2 = _mm_clmulepi64_si128(*xmm_crc2, xmm_fold4, 0x01);
x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10); x_tmp2 = _mm_clmulepi64_si128(x_tmp2, xmm_fold4, 0x10);
ps_crc2 = _mm_castsi128_ps(*xmm_crc2); ps_crc2 = _mm_castsi128_ps(*xmm_crc2);
ps_t2 = _mm_castsi128_ps(x_tmp2); ps_t2 = _mm_castsi128_ps(x_tmp2);
ps_res2 = _mm_xor_ps(ps_crc2, ps_t2); ps_res2 = _mm_xor_ps(ps_crc2, ps_t2);
*xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01); *xmm_crc3 = _mm_clmulepi64_si128(*xmm_crc3, xmm_fold4, 0x01);
x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10); x_tmp3 = _mm_clmulepi64_si128(x_tmp3, xmm_fold4, 0x10);
ps_crc3 = _mm_castsi128_ps(*xmm_crc3); ps_crc3 = _mm_castsi128_ps(*xmm_crc3);
ps_t3 = _mm_castsi128_ps(x_tmp3); ps_t3 = _mm_castsi128_ps(x_tmp3);
ps_res3 = _mm_xor_ps(ps_crc3, ps_t3); ps_res3 = _mm_xor_ps(ps_crc3, ps_t3);
*xmm_crc0 = _mm_castps_si128(ps_res0); *xmm_crc0 = _mm_castps_si128(ps_res0);
*xmm_crc1 = _mm_castps_si128(ps_res1); *xmm_crc1 = _mm_castps_si128(ps_res1);
@@ -166,12 +166,8 @@ TARGET_WITH_CLMUL static void fold_4(__m128i *xmm_crc0, __m128i *xmm_crc1, __m12
*xmm_crc3 = _mm_castps_si128(ps_res3); *xmm_crc3 = _mm_castps_si128(ps_res3);
} }
TARGET_WITH_CLMUL static void partial_fold(const size_t len, TARGET_WITH_CLMUL static void partial_fold(const size_t len, __m128i *xmm_crc0, __m128i *xmm_crc1, __m128i *xmm_crc2,
__m128i *xmm_crc0, __m128i *xmm_crc3, __m128i *xmm_crc_part)
__m128i *xmm_crc1,
__m128i *xmm_crc2,
__m128i *xmm_crc3,
__m128i *xmm_crc_part)
{ {
const __m128i xmm_fold4 = _mm_set_epi32(0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596); const __m128i xmm_fold4 = _mm_set_epi32(0x00000001, 0x54442bd4, 0x00000001, 0xc6e41596);
const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080); const __m128i xmm_mask3 = _mm_set1_epi32(0x80808080);
@@ -187,15 +183,15 @@ TARGET_WITH_CLMUL static void partial_fold(const size_t len,
xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl); xmm_a0_0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shl);
*xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr); *xmm_crc0 = _mm_shuffle_epi8(*xmm_crc0, xmm_shr);
xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl); xmm_tmp1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shl);
*xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1); *xmm_crc0 = _mm_or_si128(*xmm_crc0, xmm_tmp1);
*xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr); *xmm_crc1 = _mm_shuffle_epi8(*xmm_crc1, xmm_shr);
xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl); xmm_tmp2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shl);
*xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2); *xmm_crc1 = _mm_or_si128(*xmm_crc1, xmm_tmp2);
*xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr); *xmm_crc2 = _mm_shuffle_epi8(*xmm_crc2, xmm_shr);
xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl); xmm_tmp3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shl);
*xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3); *xmm_crc2 = _mm_or_si128(*xmm_crc2, xmm_tmp3);
*xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr); *xmm_crc3 = _mm_shuffle_epi8(*xmm_crc3, xmm_shr);

View File

@@ -20,47 +20,41 @@
#define AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H #define AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H
static const unsigned ALIGNED_(32) pshufb_shf_table[60] = { static const unsigned ALIGNED_(32) pshufb_shf_table[60] = {
0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */ 0x84838281, 0x88878685, 0x8c8b8a89, 0x008f8e8d, /* shl 15 (16 - 1)/shr1 */
0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */ 0x85848382, 0x89888786, 0x8d8c8b8a, 0x01008f8e, /* shl 14 (16 - 3)/shr2 */
0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */ 0x86858483, 0x8a898887, 0x8e8d8c8b, 0x0201008f, /* shl 13 (16 - 4)/shr3 */
0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */ 0x87868584, 0x8b8a8988, 0x8f8e8d8c, 0x03020100, /* shl 12 (16 - 4)/shr4 */
0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */ 0x88878685, 0x8c8b8a89, 0x008f8e8d, 0x04030201, /* shl 11 (16 - 5)/shr5 */
0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */ 0x89888786, 0x8d8c8b8a, 0x01008f8e, 0x05040302, /* shl 10 (16 - 6)/shr6 */
0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */ 0x8a898887, 0x8e8d8c8b, 0x0201008f, 0x06050403, /* shl 9 (16 - 7)/shr7 */
0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */ 0x8b8a8988, 0x8f8e8d8c, 0x03020100, 0x07060504, /* shl 8 (16 - 8)/shr8 */
0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */ 0x8c8b8a89, 0x008f8e8d, 0x04030201, 0x08070605, /* shl 7 (16 - 9)/shr9 */
0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/ 0x8d8c8b8a, 0x01008f8e, 0x05040302, 0x09080706, /* shl 6 (16 -10)/shr10*/
0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/ 0x8e8d8c8b, 0x0201008f, 0x06050403, 0x0a090807, /* shl 5 (16 -11)/shr11*/
0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/ 0x8f8e8d8c, 0x03020100, 0x07060504, 0x0b0a0908, /* shl 4 (16 -12)/shr12*/
0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/ 0x008f8e8d, 0x04030201, 0x08070605, 0x0c0b0a09, /* shl 3 (16 -13)/shr13*/
0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/ 0x01008f8e, 0x05040302, 0x09080706, 0x0d0c0b0a, /* shl 2 (16 -14)/shr14*/
0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/ 0x0201008f, 0x06050403, 0x0a090807, 0x0e0d0c0b /* shl 1 (16 -15)/shr15*/
}; };
static const uint32_t ALIGNED_(16) crc_k[] = { static const uint32_t ALIGNED_(16) crc_k[] = {
0xccaa009e, 0xccaa009e, 0x00000000, /* rk1 */
0x00000000, /* rk1 */ 0x751997d0, 0x00000001, /* rk2 */
0x751997d0, 0xccaa009e, 0x00000000, /* rk5 */
0x00000001, /* rk2 */ 0x63cd6124, 0x00000001, /* rk6 */
0xccaa009e, 0xf7011640, 0x00000001, /* rk7 */
0x00000000, /* rk5 */ 0xdb710640, 0x00000001 /* rk8 */
0x63cd6124,
0x00000001, /* rk6 */
0xf7011640,
0x00000001, /* rk7 */
0xdb710640,
0x00000001 /* rk8 */
}; };
static const unsigned ALIGNED_(16) crc_mask[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}; static const unsigned ALIGNED_(16) crc_mask[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000};
static const unsigned ALIGNED_(16) crc_mask2[4] = {0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}; static const unsigned ALIGNED_(16) crc_mask2[4] = {0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
#define ONCE(op) \ #define ONCE(op) \
if(first) \ if(first) \
{ \ { \
first = 0; \ first = 0; \
(op); \ (op); \
} }
#endif // AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H #endif // AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H

View File

@@ -40,14 +40,14 @@
* always zero q_initial). Guess speculative execution and branch prediction got the better of * always zero q_initial). Guess speculative execution and branch prediction got the better of
* yet another "optimization tip". * yet another "optimization tip".
*/ */
#define XOR_INITIAL(where) \ #define XOR_INITIAL(where) \
ONCE(where = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(where), vreinterpretq_u32_u64(q_initial)))) ONCE(where = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(where), vreinterpretq_u32_u64(q_initial))))
TARGET_WITH_NEON FORCE_INLINE void TARGET_WITH_NEON FORCE_INLINE void fold_1(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2,
fold_1(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q_crc3) uint64x2_t *q_crc3)
{ {
uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001}; uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001};
const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data)); const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data));
uint64x2_t x_tmp3; uint64x2_t x_tmp3;
uint32x4_t ps_crc0, ps_crc3, ps_res; uint32x4_t ps_crc0, ps_crc3, ps_res;
@@ -67,11 +67,11 @@ fold_1(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q
*q_crc3 = vreinterpretq_u64_u32(ps_res); *q_crc3 = vreinterpretq_u64_u32(ps_res);
} }
TARGET_WITH_NEON FORCE_INLINE void TARGET_WITH_NEON FORCE_INLINE void fold_2(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2,
fold_2(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q_crc3) uint64x2_t *q_crc3)
{ {
uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001}; uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001};
const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data)); const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data));
uint64x2_t x_tmp3, x_tmp2; uint64x2_t x_tmp3, x_tmp2;
uint32x4_t ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20; uint32x4_t ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res31, ps_res20;
@@ -79,16 +79,16 @@ fold_2(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q
x_tmp3 = *q_crc3; x_tmp3 = *q_crc3;
x_tmp2 = *q_crc2; x_tmp2 = *q_crc2;
*q_crc3 = *q_crc1; *q_crc3 = *q_crc1;
*q_crc1 = sse2neon_vmull_p64(vget_high_u64(*q_crc1), vget_low_u64(q_fold4)); *q_crc1 = sse2neon_vmull_p64(vget_high_u64(*q_crc1), vget_low_u64(q_fold4));
*q_crc3 = sse2neon_vmull_p64(vget_low_u64(*q_crc3), vget_high_u64(q_fold4)); *q_crc3 = sse2neon_vmull_p64(vget_low_u64(*q_crc3), vget_high_u64(q_fold4));
ps_crc3 = vreinterpretq_u32_u64(*q_crc3); ps_crc3 = vreinterpretq_u32_u64(*q_crc3);
ps_crc1 = vreinterpretq_u32_u64(*q_crc1); ps_crc1 = vreinterpretq_u32_u64(*q_crc1);
ps_res31 = veorq_u32(ps_crc3, ps_crc1); ps_res31 = veorq_u32(ps_crc3, ps_crc1);
*q_crc2 = *q_crc0; *q_crc2 = *q_crc0;
*q_crc0 = sse2neon_vmull_p64(vget_high_u64(*q_crc0), vget_low_u64(q_fold4)); *q_crc0 = sse2neon_vmull_p64(vget_high_u64(*q_crc0), vget_low_u64(q_fold4));
*q_crc2 = sse2neon_vmull_p64(vget_low_u64(*q_crc2), vget_high_u64(q_fold4)); *q_crc2 = sse2neon_vmull_p64(vget_low_u64(*q_crc2), vget_high_u64(q_fold4));
ps_crc0 = vreinterpretq_u32_u64(*q_crc0); ps_crc0 = vreinterpretq_u32_u64(*q_crc0);
ps_crc2 = vreinterpretq_u32_u64(*q_crc2); ps_crc2 = vreinterpretq_u32_u64(*q_crc2);
ps_res20 = veorq_u32(ps_crc0, ps_crc2); ps_res20 = veorq_u32(ps_crc0, ps_crc2);
@@ -99,34 +99,34 @@ fold_2(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q
*q_crc3 = vreinterpretq_u64_u32(ps_res31); *q_crc3 = vreinterpretq_u64_u32(ps_res31);
} }
TARGET_WITH_NEON FORCE_INLINE void TARGET_WITH_NEON FORCE_INLINE void fold_3(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2,
fold_3(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q_crc3) uint64x2_t *q_crc3)
{ {
uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001}; uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001};
const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data)); const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data));
uint64x2_t x_tmp3; uint64x2_t x_tmp3;
uint32x4_t ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10; uint32x4_t ps_crc0, ps_crc1, ps_crc2, ps_crc3, ps_res32, ps_res21, ps_res10;
x_tmp3 = *q_crc3; x_tmp3 = *q_crc3;
*q_crc3 = *q_crc2; *q_crc3 = *q_crc2;
*q_crc2 = sse2neon_vmull_p64(vget_high_u64(*q_crc2), vget_low_u64(q_fold4)); *q_crc2 = sse2neon_vmull_p64(vget_high_u64(*q_crc2), vget_low_u64(q_fold4));
*q_crc3 = sse2neon_vmull_p64(vget_low_u64(*q_crc3), vget_high_u64(q_fold4)); *q_crc3 = sse2neon_vmull_p64(vget_low_u64(*q_crc3), vget_high_u64(q_fold4));
ps_crc2 = vreinterpretq_u32_u64(*q_crc2); ps_crc2 = vreinterpretq_u32_u64(*q_crc2);
ps_crc3 = vreinterpretq_u32_u64(*q_crc3); ps_crc3 = vreinterpretq_u32_u64(*q_crc3);
ps_res32 = veorq_u32(ps_crc2, ps_crc3); ps_res32 = veorq_u32(ps_crc2, ps_crc3);
*q_crc2 = *q_crc1; *q_crc2 = *q_crc1;
*q_crc1 = sse2neon_vmull_p64(vget_high_u64(*q_crc1), vget_low_u64(q_fold4)); *q_crc1 = sse2neon_vmull_p64(vget_high_u64(*q_crc1), vget_low_u64(q_fold4));
*q_crc2 = sse2neon_vmull_p64(vget_low_u64(*q_crc2), vget_high_u64(q_fold4)); *q_crc2 = sse2neon_vmull_p64(vget_low_u64(*q_crc2), vget_high_u64(q_fold4));
ps_crc1 = vreinterpretq_u32_u64(*q_crc1); ps_crc1 = vreinterpretq_u32_u64(*q_crc1);
ps_crc2 = vreinterpretq_u32_u64(*q_crc2); ps_crc2 = vreinterpretq_u32_u64(*q_crc2);
ps_res21 = veorq_u32(ps_crc1, ps_crc2); ps_res21 = veorq_u32(ps_crc1, ps_crc2);
*q_crc1 = *q_crc0; *q_crc1 = *q_crc0;
*q_crc0 = sse2neon_vmull_p64(vget_high_u64(*q_crc0), vget_low_u64(q_fold4)); *q_crc0 = sse2neon_vmull_p64(vget_high_u64(*q_crc0), vget_low_u64(q_fold4));
*q_crc1 = sse2neon_vmull_p64(vget_low_u64(*q_crc1), vget_high_u64(q_fold4)); *q_crc1 = sse2neon_vmull_p64(vget_low_u64(*q_crc1), vget_high_u64(q_fold4));
ps_crc0 = vreinterpretq_u32_u64(*q_crc0); ps_crc0 = vreinterpretq_u32_u64(*q_crc0);
ps_crc1 = vreinterpretq_u32_u64(*q_crc1); ps_crc1 = vreinterpretq_u32_u64(*q_crc1);
ps_res10 = veorq_u32(ps_crc0, ps_crc1); ps_res10 = veorq_u32(ps_crc0, ps_crc1);
@@ -137,11 +137,11 @@ fold_3(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q
*q_crc3 = vreinterpretq_u64_u32(ps_res32); *q_crc3 = vreinterpretq_u64_u32(ps_res32);
} }
TARGET_WITH_NEON FORCE_INLINE void TARGET_WITH_NEON FORCE_INLINE void fold_4(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2,
fold_4(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q_crc3) uint64x2_t *q_crc3)
{ {
uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001}; uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001};
const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data)); const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data));
uint64x2_t x_tmp0; uint64x2_t x_tmp0;
uint64x2_t x_tmp1; uint64x2_t x_tmp1;
@@ -184,16 +184,12 @@ fold_4(uint64x2_t *q_crc0, uint64x2_t *q_crc1, uint64x2_t *q_crc2, uint64x2_t *q
*q_crc3 = vreinterpretq_u64_u32(ps_res3); *q_crc3 = vreinterpretq_u64_u32(ps_res3);
} }
TARGET_WITH_NEON FORCE_INLINE void partial_fold(const size_t len, TARGET_WITH_NEON FORCE_INLINE void partial_fold(const size_t len, uint64x2_t *q_crc0, uint64x2_t *q_crc1,
uint64x2_t *q_crc0, uint64x2_t *q_crc2, uint64x2_t *q_crc3, uint64x2_t *q_crc_part)
uint64x2_t *q_crc1,
uint64x2_t *q_crc2,
uint64x2_t *q_crc3,
uint64x2_t *q_crc_part)
{ {
uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001}; uint32_t ALIGNED_(16) data[4] = {0xc6e41596, 0x00000001, 0x54442bd4, 0x00000001};
const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data)); const uint64x2_t q_fold4 = vreinterpretq_u64_u32(vld1q_u32(data));
const uint64x2_t q_mask3 = vreinterpretq_u64_u32(vdupq_n_u32(0x80808080)); const uint64x2_t q_mask3 = vreinterpretq_u64_u32(vdupq_n_u32(0x80808080));
uint64x2_t q_shl, q_shr, q_tmp1, q_tmp2, q_tmp3, q_a0_0, q_a0_1; uint64x2_t q_shl, q_shr, q_tmp1, q_tmp2, q_tmp3, q_a0_0, q_a0_1;
uint32x4_t ps_crc3, psa0_0, psa0_1, ps_res; uint32x4_t ps_crc3, psa0_0, psa0_1, ps_res;
@@ -205,15 +201,15 @@ TARGET_WITH_NEON FORCE_INLINE void partial_fold(const size_t len,
q_a0_0 = mm_shuffle_epi8(*q_crc0, q_shl); q_a0_0 = mm_shuffle_epi8(*q_crc0, q_shl);
*q_crc0 = mm_shuffle_epi8(*q_crc0, q_shr); *q_crc0 = mm_shuffle_epi8(*q_crc0, q_shr);
q_tmp1 = mm_shuffle_epi8(*q_crc1, q_shl); q_tmp1 = mm_shuffle_epi8(*q_crc1, q_shl);
*q_crc0 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc0), vreinterpretq_u32_u64(q_tmp1))); *q_crc0 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc0), vreinterpretq_u32_u64(q_tmp1)));
*q_crc1 = mm_shuffle_epi8(*q_crc1, q_shr); *q_crc1 = mm_shuffle_epi8(*q_crc1, q_shr);
q_tmp2 = mm_shuffle_epi8(*q_crc2, q_shl); q_tmp2 = mm_shuffle_epi8(*q_crc2, q_shl);
*q_crc1 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc1), vreinterpretq_u32_u64(q_tmp2))); *q_crc1 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc1), vreinterpretq_u32_u64(q_tmp2)));
*q_crc2 = mm_shuffle_epi8(*q_crc2, q_shr); *q_crc2 = mm_shuffle_epi8(*q_crc2, q_shr);
q_tmp3 = mm_shuffle_epi8(*q_crc3, q_shl); q_tmp3 = mm_shuffle_epi8(*q_crc3, q_shl);
*q_crc2 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc2), vreinterpretq_u32_u64(q_tmp3))); *q_crc2 = vreinterpretq_u64_u32(vorrq_u32(vreinterpretq_u32_u64(*q_crc2), vreinterpretq_u32_u64(q_tmp3)));
*q_crc3 = mm_shuffle_epi8(*q_crc3, q_shr); *q_crc3 = mm_shuffle_epi8(*q_crc3, q_shr);
@@ -428,16 +424,16 @@ done:
*/ */
crc_fold = vreinterpretq_u64_u32(vld1q_u32(crc_k + 4)); crc_fold = vreinterpretq_u64_u32(vld1q_u32(crc_k + 4));
q_crc0 = q_crc3; q_crc0 = q_crc3;
q_crc3 = (sse2neon_vmull_p64(vget_low_u64((q_crc3)), vget_low_u64((crc_fold)))); q_crc3 = (sse2neon_vmull_p64(vget_low_u64((q_crc3)), vget_low_u64((crc_fold))));
uint8x16_t tmp[2] = {vreinterpretq_u8_u64(q_crc0), vdupq_n_u8(0)}; uint8x16_t tmp[2] = {vreinterpretq_u8_u64(q_crc0), vdupq_n_u8(0)};
q_crc0 = vreinterpretq_u64_u8(vld1q_u8(((uint8_t const *)tmp) + 8)); q_crc0 = vreinterpretq_u64_u8(vld1q_u8(((uint8_t const *)tmp) + 8));
q_crc3 = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_crc0))); q_crc3 = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_crc0)));
q_crc0 = q_crc3; q_crc0 = q_crc3;
uint8x16_t tmp_1[2] = {vdupq_n_u8(0), vreinterpretq_u8_u64(q_crc3)}; uint8x16_t tmp_1[2] = {vdupq_n_u8(0), vreinterpretq_u8_u64(q_crc3)};
q_crc3 = vreinterpretq_u64_u8(vld1q_u8(((uint8_t const *)tmp_1) + (16 - 4))); q_crc3 = vreinterpretq_u64_u8(vld1q_u8(((uint8_t const *)tmp_1) + (16 - 4)));
q_crc3 = (sse2neon_vmull_p64(vget_low_u64((q_crc3)), vget_high_u64((crc_fold)))); q_crc3 = (sse2neon_vmull_p64(vget_low_u64((q_crc3)), vget_high_u64((crc_fold))));
q_crc3 = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_crc0))); q_crc3 = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_crc0)));
q_crc3 = vreinterpretq_u64_u32(vandq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_mask2))); q_crc3 = vreinterpretq_u64_u32(vandq_u32(vreinterpretq_u32_u64(q_crc3), vreinterpretq_u32_u64(q_mask2)));

427
crc64.h
View File

@@ -25,223 +25,224 @@ typedef struct
} crc64_ctx; } crc64_ctx;
const static uint64_t crc64_table[4][256] = { const static uint64_t crc64_table[4][256] = {
{0x0000000000000000, 0xB32E4CBE03A75F6F, 0xF4843657A840A05B, 0x47AA7AE9ABE7FF34, 0x7BD0C384FF8F5E33, {0x0000000000000000, 0xB32E4CBE03A75F6F, 0xF4843657A840A05B, 0x47AA7AE9ABE7FF34, 0x7BD0C384FF8F5E33,
0xC8FE8F3AFC28015C, 0x8F54F5D357CFFE68, 0x3C7AB96D5468A107, 0xF7A18709FF1EBC66, 0x448FCBB7FCB9E309, 0xC8FE8F3AFC28015C, 0x8F54F5D357CFFE68, 0x3C7AB96D5468A107, 0xF7A18709FF1EBC66, 0x448FCBB7FCB9E309,
0x0325B15E575E1C3D, 0xB00BFDE054F94352, 0x8C71448D0091E255, 0x3F5F08330336BD3A, 0x78F572DAA8D1420E, 0x0325B15E575E1C3D, 0xB00BFDE054F94352, 0x8C71448D0091E255, 0x3F5F08330336BD3A, 0x78F572DAA8D1420E,
0xCBDB3E64AB761D61, 0x7D9BA13851336649, 0xCEB5ED8652943926, 0x891F976FF973C612, 0x3A31DBD1FAD4997D, 0xCBDB3E64AB761D61, 0x7D9BA13851336649, 0xCEB5ED8652943926, 0x891F976FF973C612, 0x3A31DBD1FAD4997D,
0x064B62BCAEBC387A, 0xB5652E02AD1B6715, 0xF2CF54EB06FC9821, 0x41E11855055BC74E, 0x8A3A2631AE2DDA2F, 0x064B62BCAEBC387A, 0xB5652E02AD1B6715, 0xF2CF54EB06FC9821, 0x41E11855055BC74E, 0x8A3A2631AE2DDA2F,
0x39146A8FAD8A8540, 0x7EBE1066066D7A74, 0xCD905CD805CA251B, 0xF1EAE5B551A2841C, 0x42C4A90B5205DB73, 0x39146A8FAD8A8540, 0x7EBE1066066D7A74, 0xCD905CD805CA251B, 0xF1EAE5B551A2841C, 0x42C4A90B5205DB73,
0x056ED3E2F9E22447, 0xB6409F5CFA457B28, 0xFB374270A266CC92, 0x48190ECEA1C193FD, 0x0FB374270A266CC9, 0x056ED3E2F9E22447, 0xB6409F5CFA457B28, 0xFB374270A266CC92, 0x48190ECEA1C193FD, 0x0FB374270A266CC9,
0xBC9D3899098133A6, 0x80E781F45DE992A1, 0x33C9CD4A5E4ECDCE, 0x7463B7A3F5A932FA, 0xC74DFB1DF60E6D95, 0xBC9D3899098133A6, 0x80E781F45DE992A1, 0x33C9CD4A5E4ECDCE, 0x7463B7A3F5A932FA, 0xC74DFB1DF60E6D95,
0x0C96C5795D7870F4, 0xBFB889C75EDF2F9B, 0xF812F32EF538D0AF, 0x4B3CBF90F69F8FC0, 0x774606FDA2F72EC7, 0x0C96C5795D7870F4, 0xBFB889C75EDF2F9B, 0xF812F32EF538D0AF, 0x4B3CBF90F69F8FC0, 0x774606FDA2F72EC7,
0xC4684A43A15071A8, 0x83C230AA0AB78E9C, 0x30EC7C140910D1F3, 0x86ACE348F355AADB, 0x3582AFF6F0F2F5B4, 0xC4684A43A15071A8, 0x83C230AA0AB78E9C, 0x30EC7C140910D1F3, 0x86ACE348F355AADB, 0x3582AFF6F0F2F5B4,
0x7228D51F5B150A80, 0xC10699A158B255EF, 0xFD7C20CC0CDAF4E8, 0x4E526C720F7DAB87, 0x09F8169BA49A54B3, 0x7228D51F5B150A80, 0xC10699A158B255EF, 0xFD7C20CC0CDAF4E8, 0x4E526C720F7DAB87, 0x09F8169BA49A54B3,
0xBAD65A25A73D0BDC, 0x710D64410C4B16BD, 0xC22328FF0FEC49D2, 0x85895216A40BB6E6, 0x36A71EA8A7ACE989, 0xBAD65A25A73D0BDC, 0x710D64410C4B16BD, 0xC22328FF0FEC49D2, 0x85895216A40BB6E6, 0x36A71EA8A7ACE989,
0x0ADDA7C5F3C4488E, 0xB9F3EB7BF06317E1, 0xFE5991925B84E8D5, 0x4D77DD2C5823B7BA, 0x64B62BCAEBC387A1, 0x0ADDA7C5F3C4488E, 0xB9F3EB7BF06317E1, 0xFE5991925B84E8D5, 0x4D77DD2C5823B7BA, 0x64B62BCAEBC387A1,
0xD7986774E864D8CE, 0x90321D9D438327FA, 0x231C512340247895, 0x1F66E84E144CD992, 0xAC48A4F017EB86FD, 0xD7986774E864D8CE, 0x90321D9D438327FA, 0x231C512340247895, 0x1F66E84E144CD992, 0xAC48A4F017EB86FD,
0xEBE2DE19BC0C79C9, 0x58CC92A7BFAB26A6, 0x9317ACC314DD3BC7, 0x2039E07D177A64A8, 0x67939A94BC9D9B9C, 0xEBE2DE19BC0C79C9, 0x58CC92A7BFAB26A6, 0x9317ACC314DD3BC7, 0x2039E07D177A64A8, 0x67939A94BC9D9B9C,
0xD4BDD62ABF3AC4F3, 0xE8C76F47EB5265F4, 0x5BE923F9E8F53A9B, 0x1C4359104312C5AF, 0xAF6D15AE40B59AC0, 0xD4BDD62ABF3AC4F3, 0xE8C76F47EB5265F4, 0x5BE923F9E8F53A9B, 0x1C4359104312C5AF, 0xAF6D15AE40B59AC0,
0x192D8AF2BAF0E1E8, 0xAA03C64CB957BE87, 0xEDA9BCA512B041B3, 0x5E87F01B11171EDC, 0x62FD4976457FBFDB, 0x192D8AF2BAF0E1E8, 0xAA03C64CB957BE87, 0xEDA9BCA512B041B3, 0x5E87F01B11171EDC, 0x62FD4976457FBFDB,
0xD1D305C846D8E0B4, 0x96797F21ED3F1F80, 0x2557339FEE9840EF, 0xEE8C0DFB45EE5D8E, 0x5DA24145464902E1, 0xD1D305C846D8E0B4, 0x96797F21ED3F1F80, 0x2557339FEE9840EF, 0xEE8C0DFB45EE5D8E, 0x5DA24145464902E1,
0x1A083BACEDAEFDD5, 0xA9267712EE09A2BA, 0x955CCE7FBA6103BD, 0x267282C1B9C65CD2, 0x61D8F8281221A3E6, 0x1A083BACEDAEFDD5, 0xA9267712EE09A2BA, 0x955CCE7FBA6103BD, 0x267282C1B9C65CD2, 0x61D8F8281221A3E6,
0xD2F6B4961186FC89, 0x9F8169BA49A54B33, 0x2CAF25044A02145C, 0x6B055FEDE1E5EB68, 0xD82B1353E242B407, 0xD2F6B4961186FC89, 0x9F8169BA49A54B33, 0x2CAF25044A02145C, 0x6B055FEDE1E5EB68, 0xD82B1353E242B407,
0xE451AA3EB62A1500, 0x577FE680B58D4A6F, 0x10D59C691E6AB55B, 0xA3FBD0D71DCDEA34, 0x6820EEB3B6BBF755, 0xE451AA3EB62A1500, 0x577FE680B58D4A6F, 0x10D59C691E6AB55B, 0xA3FBD0D71DCDEA34, 0x6820EEB3B6BBF755,
0xDB0EA20DB51CA83A, 0x9CA4D8E41EFB570E, 0x2F8A945A1D5C0861, 0x13F02D374934A966, 0xA0DE61894A93F609, 0xDB0EA20DB51CA83A, 0x9CA4D8E41EFB570E, 0x2F8A945A1D5C0861, 0x13F02D374934A966, 0xA0DE61894A93F609,
0xE7741B60E174093D, 0x545A57DEE2D35652, 0xE21AC88218962D7A, 0x5134843C1B317215, 0x169EFED5B0D68D21, 0xE7741B60E174093D, 0x545A57DEE2D35652, 0xE21AC88218962D7A, 0x5134843C1B317215, 0x169EFED5B0D68D21,
0xA5B0B26BB371D24E, 0x99CA0B06E7197349, 0x2AE447B8E4BE2C26, 0x6D4E3D514F59D312, 0xDE6071EF4CFE8C7D, 0xA5B0B26BB371D24E, 0x99CA0B06E7197349, 0x2AE447B8E4BE2C26, 0x6D4E3D514F59D312, 0xDE6071EF4CFE8C7D,
0x15BB4F8BE788911C, 0xA6950335E42FCE73, 0xE13F79DC4FC83147, 0x521135624C6F6E28, 0x6E6B8C0F1807CF2F, 0x15BB4F8BE788911C, 0xA6950335E42FCE73, 0xE13F79DC4FC83147, 0x521135624C6F6E28, 0x6E6B8C0F1807CF2F,
0xDD45C0B11BA09040, 0x9AEFBA58B0476F74, 0x29C1F6E6B3E0301B, 0xC96C5795D7870F42, 0x7A421B2BD420502D, 0xDD45C0B11BA09040, 0x9AEFBA58B0476F74, 0x29C1F6E6B3E0301B, 0xC96C5795D7870F42, 0x7A421B2BD420502D,
0x3DE861C27FC7AF19, 0x8EC62D7C7C60F076, 0xB2BC941128085171, 0x0192D8AF2BAF0E1E, 0x4638A2468048F12A, 0x3DE861C27FC7AF19, 0x8EC62D7C7C60F076, 0xB2BC941128085171, 0x0192D8AF2BAF0E1E, 0x4638A2468048F12A,
0xF516EEF883EFAE45, 0x3ECDD09C2899B324, 0x8DE39C222B3EEC4B, 0xCA49E6CB80D9137F, 0x7967AA75837E4C10, 0xF516EEF883EFAE45, 0x3ECDD09C2899B324, 0x8DE39C222B3EEC4B, 0xCA49E6CB80D9137F, 0x7967AA75837E4C10,
0x451D1318D716ED17, 0xF6335FA6D4B1B278, 0xB199254F7F564D4C, 0x02B769F17CF11223, 0xB4F7F6AD86B4690B, 0x451D1318D716ED17, 0xF6335FA6D4B1B278, 0xB199254F7F564D4C, 0x02B769F17CF11223, 0xB4F7F6AD86B4690B,
0x07D9BA1385133664, 0x4073C0FA2EF4C950, 0xF35D8C442D53963F, 0xCF273529793B3738, 0x7C0979977A9C6857, 0x07D9BA1385133664, 0x4073C0FA2EF4C950, 0xF35D8C442D53963F, 0xCF273529793B3738, 0x7C0979977A9C6857,
0x3BA3037ED17B9763, 0x888D4FC0D2DCC80C, 0x435671A479AAD56D, 0xF0783D1A7A0D8A02, 0xB7D247F3D1EA7536, 0x3BA3037ED17B9763, 0x888D4FC0D2DCC80C, 0x435671A479AAD56D, 0xF0783D1A7A0D8A02, 0xB7D247F3D1EA7536,
0x04FC0B4DD24D2A59, 0x3886B22086258B5E, 0x8BA8FE9E8582D431, 0xCC0284772E652B05, 0x7F2CC8C92DC2746A, 0x04FC0B4DD24D2A59, 0x3886B22086258B5E, 0x8BA8FE9E8582D431, 0xCC0284772E652B05, 0x7F2CC8C92DC2746A,
0x325B15E575E1C3D0, 0x8175595B76469CBF, 0xC6DF23B2DDA1638B, 0x75F16F0CDE063CE4, 0x498BD6618A6E9DE3, 0x325B15E575E1C3D0, 0x8175595B76469CBF, 0xC6DF23B2DDA1638B, 0x75F16F0CDE063CE4, 0x498BD6618A6E9DE3,
0xFAA59ADF89C9C28C, 0xBD0FE036222E3DB8, 0x0E21AC88218962D7, 0xC5FA92EC8AFF7FB6, 0x76D4DE52895820D9, 0xFAA59ADF89C9C28C, 0xBD0FE036222E3DB8, 0x0E21AC88218962D7, 0xC5FA92EC8AFF7FB6, 0x76D4DE52895820D9,
0x317EA4BB22BFDFED, 0x8250E80521188082, 0xBE2A516875702185, 0x0D041DD676D77EEA, 0x4AAE673FDD3081DE, 0x317EA4BB22BFDFED, 0x8250E80521188082, 0xBE2A516875702185, 0x0D041DD676D77EEA, 0x4AAE673FDD3081DE,
0xF9802B81DE97DEB1, 0x4FC0B4DD24D2A599, 0xFCEEF8632775FAF6, 0xBB44828A8C9205C2, 0x086ACE348F355AAD, 0xF9802B81DE97DEB1, 0x4FC0B4DD24D2A599, 0xFCEEF8632775FAF6, 0xBB44828A8C9205C2, 0x086ACE348F355AAD,
0x34107759DB5DFBAA, 0x873E3BE7D8FAA4C5, 0xC094410E731D5BF1, 0x73BA0DB070BA049E, 0xB86133D4DBCC19FF, 0x34107759DB5DFBAA, 0x873E3BE7D8FAA4C5, 0xC094410E731D5BF1, 0x73BA0DB070BA049E, 0xB86133D4DBCC19FF,
0x0B4F7F6AD86B4690, 0x4CE50583738CB9A4, 0xFFCB493D702BE6CB, 0xC3B1F050244347CC, 0x709FBCEE27E418A3, 0x0B4F7F6AD86B4690, 0x4CE50583738CB9A4, 0xFFCB493D702BE6CB, 0xC3B1F050244347CC, 0x709FBCEE27E418A3,
0x3735C6078C03E797, 0x841B8AB98FA4B8F8, 0xADDA7C5F3C4488E3, 0x1EF430E13FE3D78C, 0x595E4A08940428B8, 0x3735C6078C03E797, 0x841B8AB98FA4B8F8, 0xADDA7C5F3C4488E3, 0x1EF430E13FE3D78C, 0x595E4A08940428B8,
0xEA7006B697A377D7, 0xD60ABFDBC3CBD6D0, 0x6524F365C06C89BF, 0x228E898C6B8B768B, 0x91A0C532682C29E4, 0xEA7006B697A377D7, 0xD60ABFDBC3CBD6D0, 0x6524F365C06C89BF, 0x228E898C6B8B768B, 0x91A0C532682C29E4,
0x5A7BFB56C35A3485, 0xE955B7E8C0FD6BEA, 0xAEFFCD016B1A94DE, 0x1DD181BF68BDCBB1, 0x21AB38D23CD56AB6, 0x5A7BFB56C35A3485, 0xE955B7E8C0FD6BEA, 0xAEFFCD016B1A94DE, 0x1DD181BF68BDCBB1, 0x21AB38D23CD56AB6,
0x9285746C3F7235D9, 0xD52F0E859495CAED, 0x6601423B97329582, 0xD041DD676D77EEAA, 0x636F91D96ED0B1C5, 0x9285746C3F7235D9, 0xD52F0E859495CAED, 0x6601423B97329582, 0xD041DD676D77EEAA, 0x636F91D96ED0B1C5,
0x24C5EB30C5374EF1, 0x97EBA78EC690119E, 0xAB911EE392F8B099, 0x18BF525D915FEFF6, 0x5F1528B43AB810C2, 0x24C5EB30C5374EF1, 0x97EBA78EC690119E, 0xAB911EE392F8B099, 0x18BF525D915FEFF6, 0x5F1528B43AB810C2,
0xEC3B640A391F4FAD, 0x27E05A6E926952CC, 0x94CE16D091CE0DA3, 0xD3646C393A29F297, 0x604A2087398EADF8, 0xEC3B640A391F4FAD, 0x27E05A6E926952CC, 0x94CE16D091CE0DA3, 0xD3646C393A29F297, 0x604A2087398EADF8,
0x5C3099EA6DE60CFF, 0xEF1ED5546E415390, 0xA8B4AFBDC5A6ACA4, 0x1B9AE303C601F3CB, 0x56ED3E2F9E224471, 0x5C3099EA6DE60CFF, 0xEF1ED5546E415390, 0xA8B4AFBDC5A6ACA4, 0x1B9AE303C601F3CB, 0x56ED3E2F9E224471,
0xE5C372919D851B1E, 0xA26908783662E42A, 0x114744C635C5BB45, 0x2D3DFDAB61AD1A42, 0x9E13B115620A452D, 0xE5C372919D851B1E, 0xA26908783662E42A, 0x114744C635C5BB45, 0x2D3DFDAB61AD1A42, 0x9E13B115620A452D,
0xD9B9CBFCC9EDBA19, 0x6A978742CA4AE576, 0xA14CB926613CF817, 0x1262F598629BA778, 0x55C88F71C97C584C, 0xD9B9CBFCC9EDBA19, 0x6A978742CA4AE576, 0xA14CB926613CF817, 0x1262F598629BA778, 0x55C88F71C97C584C,
0xE6E6C3CFCADB0723, 0xDA9C7AA29EB3A624, 0x69B2361C9D14F94B, 0x2E184CF536F3067F, 0x9D36004B35545910, 0xE6E6C3CFCADB0723, 0xDA9C7AA29EB3A624, 0x69B2361C9D14F94B, 0x2E184CF536F3067F, 0x9D36004B35545910,
0x2B769F17CF112238, 0x9858D3A9CCB67D57, 0xDFF2A94067518263, 0x6CDCE5FE64F6DD0C, 0x50A65C93309E7C0B, 0x2B769F17CF112238, 0x9858D3A9CCB67D57, 0xDFF2A94067518263, 0x6CDCE5FE64F6DD0C, 0x50A65C93309E7C0B,
0xE388102D33392364, 0xA4226AC498DEDC50, 0x170C267A9B79833F, 0xDCD7181E300F9E5E, 0x6FF954A033A8C131, 0xE388102D33392364, 0xA4226AC498DEDC50, 0x170C267A9B79833F, 0xDCD7181E300F9E5E, 0x6FF954A033A8C131,
0x28532E49984F3E05, 0x9B7D62F79BE8616A, 0xA707DB9ACF80C06D, 0x14299724CC279F02, 0x5383EDCD67C06036, 0x28532E49984F3E05, 0x9B7D62F79BE8616A, 0xA707DB9ACF80C06D, 0x14299724CC279F02, 0x5383EDCD67C06036,
0xE0ADA17364673F59}, 0xE0ADA17364673F59},
{0x0000000000000000, 0x54E979925CD0F10D, 0xA9D2F324B9A1E21A, 0xFD3B8AB6E5711317, 0xC17D4962DC4DDAB1, {0x0000000000000000, 0x54E979925CD0F10D, 0xA9D2F324B9A1E21A, 0xFD3B8AB6E5711317, 0xC17D4962DC4DDAB1,
0x959430F0809D2BBC, 0x68AFBA4665EC38AB, 0x3C46C3D4393CC9A6, 0x10223DEE1795ABE7, 0x44CB447C4B455AEA, 0x959430F0809D2BBC, 0x68AFBA4665EC38AB, 0x3C46C3D4393CC9A6, 0x10223DEE1795ABE7, 0x44CB447C4B455AEA,
0xB9F0CECAAE3449FD, 0xED19B758F2E4B8F0, 0xD15F748CCBD87156, 0x85B60D1E9708805B, 0x788D87A87279934C, 0xB9F0CECAAE3449FD, 0xED19B758F2E4B8F0, 0xD15F748CCBD87156, 0x85B60D1E9708805B, 0x788D87A87279934C,
0x2C64FE3A2EA96241, 0x20447BDC2F2B57CE, 0x74AD024E73FBA6C3, 0x899688F8968AB5D4, 0xDD7FF16ACA5A44D9, 0x2C64FE3A2EA96241, 0x20447BDC2F2B57CE, 0x74AD024E73FBA6C3, 0x899688F8968AB5D4, 0xDD7FF16ACA5A44D9,
0xE13932BEF3668D7F, 0xB5D04B2CAFB67C72, 0x48EBC19A4AC76F65, 0x1C02B80816179E68, 0x3066463238BEFC29, 0xE13932BEF3668D7F, 0xB5D04B2CAFB67C72, 0x48EBC19A4AC76F65, 0x1C02B80816179E68, 0x3066463238BEFC29,
0x648F3FA0646E0D24, 0x99B4B516811F1E33, 0xCD5DCC84DDCFEF3E, 0xF11B0F50E4F32698, 0xA5F276C2B823D795, 0x648F3FA0646E0D24, 0x99B4B516811F1E33, 0xCD5DCC84DDCFEF3E, 0xF11B0F50E4F32698, 0xA5F276C2B823D795,
0x58C9FC745D52C482, 0x0C2085E60182358F, 0x4088F7B85E56AF9C, 0x14618E2A02865E91, 0xE95A049CE7F74D86, 0x58C9FC745D52C482, 0x0C2085E60182358F, 0x4088F7B85E56AF9C, 0x14618E2A02865E91, 0xE95A049CE7F74D86,
0xBDB37D0EBB27BC8B, 0x81F5BEDA821B752D, 0xD51CC748DECB8420, 0x28274DFE3BBA9737, 0x7CCE346C676A663A, 0xBDB37D0EBB27BC8B, 0x81F5BEDA821B752D, 0xD51CC748DECB8420, 0x28274DFE3BBA9737, 0x7CCE346C676A663A,
0x50AACA5649C3047B, 0x0443B3C41513F576, 0xF9783972F062E661, 0xAD9140E0ACB2176C, 0x91D78334958EDECA, 0x50AACA5649C3047B, 0x0443B3C41513F576, 0xF9783972F062E661, 0xAD9140E0ACB2176C, 0x91D78334958EDECA,
0xC53EFAA6C95E2FC7, 0x380570102C2F3CD0, 0x6CEC098270FFCDDD, 0x60CC8C64717DF852, 0x3425F5F62DAD095F, 0xC53EFAA6C95E2FC7, 0x380570102C2F3CD0, 0x6CEC098270FFCDDD, 0x60CC8C64717DF852, 0x3425F5F62DAD095F,
0xC91E7F40C8DC1A48, 0x9DF706D2940CEB45, 0xA1B1C506AD3022E3, 0xF558BC94F1E0D3EE, 0x086336221491C0F9, 0xC91E7F40C8DC1A48, 0x9DF706D2940CEB45, 0xA1B1C506AD3022E3, 0xF558BC94F1E0D3EE, 0x086336221491C0F9,
0x5C8A4FB0484131F4, 0x70EEB18A66E853B5, 0x2407C8183A38A2B8, 0xD93C42AEDF49B1AF, 0x8DD53B3C839940A2, 0x5C8A4FB0484131F4, 0x70EEB18A66E853B5, 0x2407C8183A38A2B8, 0xD93C42AEDF49B1AF, 0x8DD53B3C839940A2,
0xB193F8E8BAA58904, 0xE57A817AE6757809, 0x18410BCC03046B1E, 0x4CA8725E5FD49A13, 0x8111EF70BCAD5F38, 0xB193F8E8BAA58904, 0xE57A817AE6757809, 0x18410BCC03046B1E, 0x4CA8725E5FD49A13, 0x8111EF70BCAD5F38,
0xD5F896E2E07DAE35, 0x28C31C54050CBD22, 0x7C2A65C659DC4C2F, 0x406CA61260E08589, 0x1485DF803C307484, 0xD5F896E2E07DAE35, 0x28C31C54050CBD22, 0x7C2A65C659DC4C2F, 0x406CA61260E08589, 0x1485DF803C307484,
0xE9BE5536D9416793, 0xBD572CA48591969E, 0x9133D29EAB38F4DF, 0xC5DAAB0CF7E805D2, 0x38E121BA129916C5, 0xE9BE5536D9416793, 0xBD572CA48591969E, 0x9133D29EAB38F4DF, 0xC5DAAB0CF7E805D2, 0x38E121BA129916C5,
0x6C0858284E49E7C8, 0x504E9BFC77752E6E, 0x04A7E26E2BA5DF63, 0xF99C68D8CED4CC74, 0xAD75114A92043D79, 0x6C0858284E49E7C8, 0x504E9BFC77752E6E, 0x04A7E26E2BA5DF63, 0xF99C68D8CED4CC74, 0xAD75114A92043D79,
0xA15594AC938608F6, 0xF5BCED3ECF56F9FB, 0x088767882A27EAEC, 0x5C6E1E1A76F71BE1, 0x6028DDCE4FCBD247, 0xA15594AC938608F6, 0xF5BCED3ECF56F9FB, 0x088767882A27EAEC, 0x5C6E1E1A76F71BE1, 0x6028DDCE4FCBD247,
0x34C1A45C131B234A, 0xC9FA2EEAF66A305D, 0x9D135778AABAC150, 0xB177A9428413A311, 0xE59ED0D0D8C3521C, 0x34C1A45C131B234A, 0xC9FA2EEAF66A305D, 0x9D135778AABAC150, 0xB177A9428413A311, 0xE59ED0D0D8C3521C,
0x18A55A663DB2410B, 0x4C4C23F46162B006, 0x700AE020585E79A0, 0x24E399B2048E88AD, 0xD9D81304E1FF9BBA, 0x18A55A663DB2410B, 0x4C4C23F46162B006, 0x700AE020585E79A0, 0x24E399B2048E88AD, 0xD9D81304E1FF9BBA,
0x8D316A96BD2F6AB7, 0xC19918C8E2FBF0A4, 0x9570615ABE2B01A9, 0x684BEBEC5B5A12BE, 0x3CA2927E078AE3B3, 0x8D316A96BD2F6AB7, 0xC19918C8E2FBF0A4, 0x9570615ABE2B01A9, 0x684BEBEC5B5A12BE, 0x3CA2927E078AE3B3,
0x00E451AA3EB62A15, 0x540D28386266DB18, 0xA936A28E8717C80F, 0xFDDFDB1CDBC73902, 0xD1BB2526F56E5B43, 0x00E451AA3EB62A15, 0x540D28386266DB18, 0xA936A28E8717C80F, 0xFDDFDB1CDBC73902, 0xD1BB2526F56E5B43,
0x85525CB4A9BEAA4E, 0x7869D6024CCFB959, 0x2C80AF90101F4854, 0x10C66C44292381F2, 0x442F15D675F370FF, 0x85525CB4A9BEAA4E, 0x7869D6024CCFB959, 0x2C80AF90101F4854, 0x10C66C44292381F2, 0x442F15D675F370FF,
0xB9149F60908263E8, 0xEDFDE6F2CC5292E5, 0xE1DD6314CDD0A76A, 0xB5341A8691005667, 0x480F903074714570, 0xB9149F60908263E8, 0xEDFDE6F2CC5292E5, 0xE1DD6314CDD0A76A, 0xB5341A8691005667, 0x480F903074714570,
0x1CE6E9A228A1B47D, 0x20A02A76119D7DDB, 0x744953E44D4D8CD6, 0x8972D952A83C9FC1, 0xDD9BA0C0F4EC6ECC, 0x1CE6E9A228A1B47D, 0x20A02A76119D7DDB, 0x744953E44D4D8CD6, 0x8972D952A83C9FC1, 0xDD9BA0C0F4EC6ECC,
0xF1FF5EFADA450C8D, 0xA51627688695FD80, 0x582DADDE63E4EE97, 0x0CC4D44C3F341F9A, 0x308217980608D63C, 0xF1FF5EFADA450C8D, 0xA51627688695FD80, 0x582DADDE63E4EE97, 0x0CC4D44C3F341F9A, 0x308217980608D63C,
0x646B6E0A5AD82731, 0x9950E4BCBFA93426, 0xCDB99D2EE379C52B, 0x90FB71CAD654A0F5, 0xC41208588A8451F8, 0x646B6E0A5AD82731, 0x9950E4BCBFA93426, 0xCDB99D2EE379C52B, 0x90FB71CAD654A0F5, 0xC41208588A8451F8,
0x392982EE6FF542EF, 0x6DC0FB7C3325B3E2, 0x518638A80A197A44, 0x056F413A56C98B49, 0xF854CB8CB3B8985E, 0x392982EE6FF542EF, 0x6DC0FB7C3325B3E2, 0x518638A80A197A44, 0x056F413A56C98B49, 0xF854CB8CB3B8985E,
0xACBDB21EEF686953, 0x80D94C24C1C10B12, 0xD43035B69D11FA1F, 0x290BBF007860E908, 0x7DE2C69224B01805, 0xACBDB21EEF686953, 0x80D94C24C1C10B12, 0xD43035B69D11FA1F, 0x290BBF007860E908, 0x7DE2C69224B01805,
0x41A405461D8CD1A3, 0x154D7CD4415C20AE, 0xE876F662A42D33B9, 0xBC9F8FF0F8FDC2B4, 0xB0BF0A16F97FF73B, 0x41A405461D8CD1A3, 0x154D7CD4415C20AE, 0xE876F662A42D33B9, 0xBC9F8FF0F8FDC2B4, 0xB0BF0A16F97FF73B,
0xE4567384A5AF0636, 0x196DF93240DE1521, 0x4D8480A01C0EE42C, 0x71C2437425322D8A, 0x252B3AE679E2DC87, 0xE4567384A5AF0636, 0x196DF93240DE1521, 0x4D8480A01C0EE42C, 0x71C2437425322D8A, 0x252B3AE679E2DC87,
0xD810B0509C93CF90, 0x8CF9C9C2C0433E9D, 0xA09D37F8EEEA5CDC, 0xF4744E6AB23AADD1, 0x094FC4DC574BBEC6, 0xD810B0509C93CF90, 0x8CF9C9C2C0433E9D, 0xA09D37F8EEEA5CDC, 0xF4744E6AB23AADD1, 0x094FC4DC574BBEC6,
0x5DA6BD4E0B9B4FCB, 0x61E07E9A32A7866D, 0x350907086E777760, 0xC8328DBE8B066477, 0x9CDBF42CD7D6957A, 0x5DA6BD4E0B9B4FCB, 0x61E07E9A32A7866D, 0x350907086E777760, 0xC8328DBE8B066477, 0x9CDBF42CD7D6957A,
0xD073867288020F69, 0x849AFFE0D4D2FE64, 0x79A1755631A3ED73, 0x2D480CC46D731C7E, 0x110ECF10544FD5D8, 0xD073867288020F69, 0x849AFFE0D4D2FE64, 0x79A1755631A3ED73, 0x2D480CC46D731C7E, 0x110ECF10544FD5D8,
0x45E7B682089F24D5, 0xB8DC3C34EDEE37C2, 0xEC3545A6B13EC6CF, 0xC051BB9C9F97A48E, 0x94B8C20EC3475583, 0x45E7B682089F24D5, 0xB8DC3C34EDEE37C2, 0xEC3545A6B13EC6CF, 0xC051BB9C9F97A48E, 0x94B8C20EC3475583,
0x698348B826364694, 0x3D6A312A7AE6B799, 0x012CF2FE43DA7E3F, 0x55C58B6C1F0A8F32, 0xA8FE01DAFA7B9C25, 0x698348B826364694, 0x3D6A312A7AE6B799, 0x012CF2FE43DA7E3F, 0x55C58B6C1F0A8F32, 0xA8FE01DAFA7B9C25,
0xFC177848A6AB6D28, 0xF037FDAEA72958A7, 0xA4DE843CFBF9A9AA, 0x59E50E8A1E88BABD, 0x0D0C771842584BB0, 0xFC177848A6AB6D28, 0xF037FDAEA72958A7, 0xA4DE843CFBF9A9AA, 0x59E50E8A1E88BABD, 0x0D0C771842584BB0,
0x314AB4CC7B648216, 0x65A3CD5E27B4731B, 0x989847E8C2C5600C, 0xCC713E7A9E159101, 0xE015C040B0BCF340, 0x314AB4CC7B648216, 0x65A3CD5E27B4731B, 0x989847E8C2C5600C, 0xCC713E7A9E159101, 0xE015C040B0BCF340,
0xB4FCB9D2EC6C024D, 0x49C73364091D115A, 0x1D2E4AF655CDE057, 0x216889226CF129F1, 0x7581F0B03021D8FC, 0xB4FCB9D2EC6C024D, 0x49C73364091D115A, 0x1D2E4AF655CDE057, 0x216889226CF129F1, 0x7581F0B03021D8FC,
0x88BA7A06D550CBEB, 0xDC53039489803AE6, 0x11EA9EBA6AF9FFCD, 0x4503E72836290EC0, 0xB8386D9ED3581DD7, 0x88BA7A06D550CBEB, 0xDC53039489803AE6, 0x11EA9EBA6AF9FFCD, 0x4503E72836290EC0, 0xB8386D9ED3581DD7,
0xECD1140C8F88ECDA, 0xD097D7D8B6B4257C, 0x847EAE4AEA64D471, 0x794524FC0F15C766, 0x2DAC5D6E53C5366B, 0xECD1140C8F88ECDA, 0xD097D7D8B6B4257C, 0x847EAE4AEA64D471, 0x794524FC0F15C766, 0x2DAC5D6E53C5366B,
0x01C8A3547D6C542A, 0x5521DAC621BCA527, 0xA81A5070C4CDB630, 0xFCF329E2981D473D, 0xC0B5EA36A1218E9B, 0x01C8A3547D6C542A, 0x5521DAC621BCA527, 0xA81A5070C4CDB630, 0xFCF329E2981D473D, 0xC0B5EA36A1218E9B,
0x945C93A4FDF17F96, 0x6967191218806C81, 0x3D8E608044509D8C, 0x31AEE56645D2A803, 0x65479CF41902590E, 0x945C93A4FDF17F96, 0x6967191218806C81, 0x3D8E608044509D8C, 0x31AEE56645D2A803, 0x65479CF41902590E,
0x987C1642FC734A19, 0xCC956FD0A0A3BB14, 0xF0D3AC04999F72B2, 0xA43AD596C54F83BF, 0x59015F20203E90A8, 0x987C1642FC734A19, 0xCC956FD0A0A3BB14, 0xF0D3AC04999F72B2, 0xA43AD596C54F83BF, 0x59015F20203E90A8,
0x0DE826B27CEE61A5, 0x218CD888524703E4, 0x7565A11A0E97F2E9, 0x885E2BACEBE6E1FE, 0xDCB7523EB73610F3, 0x0DE826B27CEE61A5, 0x218CD888524703E4, 0x7565A11A0E97F2E9, 0x885E2BACEBE6E1FE, 0xDCB7523EB73610F3,
0xE0F191EA8E0AD955, 0xB418E878D2DA2858, 0x492362CE37AB3B4F, 0x1DCA1B5C6B7BCA42, 0x5162690234AF5051, 0xE0F191EA8E0AD955, 0xB418E878D2DA2858, 0x492362CE37AB3B4F, 0x1DCA1B5C6B7BCA42, 0x5162690234AF5051,
0x058B1090687FA15C, 0xF8B09A268D0EB24B, 0xAC59E3B4D1DE4346, 0x901F2060E8E28AE0, 0xC4F659F2B4327BED, 0x058B1090687FA15C, 0xF8B09A268D0EB24B, 0xAC59E3B4D1DE4346, 0x901F2060E8E28AE0, 0xC4F659F2B4327BED,
0x39CDD344514368FA, 0x6D24AAD60D9399F7, 0x414054EC233AFBB6, 0x15A92D7E7FEA0ABB, 0xE892A7C89A9B19AC, 0x39CDD344514368FA, 0x6D24AAD60D9399F7, 0x414054EC233AFBB6, 0x15A92D7E7FEA0ABB, 0xE892A7C89A9B19AC,
0xBC7BDE5AC64BE8A1, 0x803D1D8EFF772107, 0xD4D4641CA3A7D00A, 0x29EFEEAA46D6C31D, 0x7D0697381A063210, 0xBC7BDE5AC64BE8A1, 0x803D1D8EFF772107, 0xD4D4641CA3A7D00A, 0x29EFEEAA46D6C31D, 0x7D0697381A063210,
0x712612DE1B84079F, 0x25CF6B4C4754F692, 0xD8F4E1FAA225E585, 0x8C1D9868FEF51488, 0xB05B5BBCC7C9DD2E, 0x712612DE1B84079F, 0x25CF6B4C4754F692, 0xD8F4E1FAA225E585, 0x8C1D9868FEF51488, 0xB05B5BBCC7C9DD2E,
0xE4B2222E9B192C23, 0x1989A8987E683F34, 0x4D60D10A22B8CE39, 0x61042F300C11AC78, 0x35ED56A250C15D75, 0xE4B2222E9B192C23, 0x1989A8987E683F34, 0x4D60D10A22B8CE39, 0x61042F300C11AC78, 0x35ED56A250C15D75,
0xC8D6DC14B5B04E62, 0x9C3FA586E960BF6F, 0xA0796652D05C76C9, 0xF4901FC08C8C87C4, 0x09AB957669FD94D3, 0xC8D6DC14B5B04E62, 0x9C3FA586E960BF6F, 0xA0796652D05C76C9, 0xF4901FC08C8C87C4, 0x09AB957669FD94D3,
0x5D42ECE4352D65DE}, 0x5D42ECE4352D65DE},
{0x0000000000000000, 0x3F0BE14A916A6DCB, 0x7E17C29522D4DB96, 0x411C23DFB3BEB65D, 0xFC2F852A45A9B72C, {0x0000000000000000, 0x3F0BE14A916A6DCB, 0x7E17C29522D4DB96, 0x411C23DFB3BEB65D, 0xFC2F852A45A9B72C,
0xC3246460D4C3DAE7, 0x823847BF677D6CBA, 0xBD33A6F5F6170171, 0x6A87A57F245D70DD, 0x558C4435B5371D16, 0xC3246460D4C3DAE7, 0x823847BF677D6CBA, 0xBD33A6F5F6170171, 0x6A87A57F245D70DD, 0x558C4435B5371D16,
0x149067EA0689AB4B, 0x2B9B86A097E3C680, 0x96A8205561F4C7F1, 0xA9A3C11FF09EAA3A, 0xE8BFE2C043201C67, 0x149067EA0689AB4B, 0x2B9B86A097E3C680, 0x96A8205561F4C7F1, 0xA9A3C11FF09EAA3A, 0xE8BFE2C043201C67,
0xD7B4038AD24A71AC, 0xD50F4AFE48BAE1BA, 0xEA04ABB4D9D08C71, 0xAB18886B6A6E3A2C, 0x94136921FB0457E7, 0xD7B4038AD24A71AC, 0xD50F4AFE48BAE1BA, 0xEA04ABB4D9D08C71, 0xAB18886B6A6E3A2C, 0x94136921FB0457E7,
0x2920CFD40D135696, 0x162B2E9E9C793B5D, 0x57370D412FC78D00, 0x683CEC0BBEADE0CB, 0xBF88EF816CE79167, 0x2920CFD40D135696, 0x162B2E9E9C793B5D, 0x57370D412FC78D00, 0x683CEC0BBEADE0CB, 0xBF88EF816CE79167,
0x80830ECBFD8DFCAC, 0xC19F2D144E334AF1, 0xFE94CC5EDF59273A, 0x43A76AAB294E264B, 0x7CAC8BE1B8244B80, 0x80830ECBFD8DFCAC, 0xC19F2D144E334AF1, 0xFE94CC5EDF59273A, 0x43A76AAB294E264B, 0x7CAC8BE1B8244B80,
0x3DB0A83E0B9AFDDD, 0x02BB49749AF09016, 0x38C63AD73E7BDDF1, 0x07CDDB9DAF11B03A, 0x46D1F8421CAF0667, 0x3DB0A83E0B9AFDDD, 0x02BB49749AF09016, 0x38C63AD73E7BDDF1, 0x07CDDB9DAF11B03A, 0x46D1F8421CAF0667,
0x79DA19088DC56BAC, 0xC4E9BFFD7BD26ADD, 0xFBE25EB7EAB80716, 0xBAFE7D685906B14B, 0x85F59C22C86CDC80, 0x79DA19088DC56BAC, 0xC4E9BFFD7BD26ADD, 0xFBE25EB7EAB80716, 0xBAFE7D685906B14B, 0x85F59C22C86CDC80,
0x52419FA81A26AD2C, 0x6D4A7EE28B4CC0E7, 0x2C565D3D38F276BA, 0x135DBC77A9981B71, 0xAE6E1A825F8F1A00, 0x52419FA81A26AD2C, 0x6D4A7EE28B4CC0E7, 0x2C565D3D38F276BA, 0x135DBC77A9981B71, 0xAE6E1A825F8F1A00,
0x9165FBC8CEE577CB, 0xD079D8177D5BC196, 0xEF72395DEC31AC5D, 0xEDC9702976C13C4B, 0xD2C29163E7AB5180, 0x9165FBC8CEE577CB, 0xD079D8177D5BC196, 0xEF72395DEC31AC5D, 0xEDC9702976C13C4B, 0xD2C29163E7AB5180,
0x93DEB2BC5415E7DD, 0xACD553F6C57F8A16, 0x11E6F50333688B67, 0x2EED1449A202E6AC, 0x6FF1379611BC50F1, 0x93DEB2BC5415E7DD, 0xACD553F6C57F8A16, 0x11E6F50333688B67, 0x2EED1449A202E6AC, 0x6FF1379611BC50F1,
0x50FAD6DC80D63D3A, 0x874ED556529C4C96, 0xB845341CC3F6215D, 0xF95917C370489700, 0xC652F689E122FACB, 0x50FAD6DC80D63D3A, 0x874ED556529C4C96, 0xB845341CC3F6215D, 0xF95917C370489700, 0xC652F689E122FACB,
0x7B61507C1735FBBA, 0x446AB136865F9671, 0x057692E935E1202C, 0x3A7D73A3A48B4DE7, 0x718C75AE7CF7BBE2, 0x7B61507C1735FBBA, 0x446AB136865F9671, 0x057692E935E1202C, 0x3A7D73A3A48B4DE7, 0x718C75AE7CF7BBE2,
0x4E8794E4ED9DD629, 0x0F9BB73B5E236074, 0x30905671CF490DBF, 0x8DA3F084395E0CCE, 0xB2A811CEA8346105, 0x4E8794E4ED9DD629, 0x0F9BB73B5E236074, 0x30905671CF490DBF, 0x8DA3F084395E0CCE, 0xB2A811CEA8346105,
0xF3B432111B8AD758, 0xCCBFD35B8AE0BA93, 0x1B0BD0D158AACB3F, 0x2400319BC9C0A6F4, 0x651C12447A7E10A9, 0xF3B432111B8AD758, 0xCCBFD35B8AE0BA93, 0x1B0BD0D158AACB3F, 0x2400319BC9C0A6F4, 0x651C12447A7E10A9,
0x5A17F30EEB147D62, 0xE72455FB1D037C13, 0xD82FB4B18C6911D8, 0x9933976E3FD7A785, 0xA6387624AEBDCA4E, 0x5A17F30EEB147D62, 0xE72455FB1D037C13, 0xD82FB4B18C6911D8, 0x9933976E3FD7A785, 0xA6387624AEBDCA4E,
0xA4833F50344D5A58, 0x9B88DE1AA5273793, 0xDA94FDC5169981CE, 0xE59F1C8F87F3EC05, 0x58ACBA7A71E4ED74, 0xA4833F50344D5A58, 0x9B88DE1AA5273793, 0xDA94FDC5169981CE, 0xE59F1C8F87F3EC05, 0x58ACBA7A71E4ED74,
0x67A75B30E08E80BF, 0x26BB78EF533036E2, 0x19B099A5C25A5B29, 0xCE049A2F10102A85, 0xF10F7B65817A474E, 0x67A75B30E08E80BF, 0x26BB78EF533036E2, 0x19B099A5C25A5B29, 0xCE049A2F10102A85, 0xF10F7B65817A474E,
0xB01358BA32C4F113, 0x8F18B9F0A3AE9CD8, 0x322B1F0555B99DA9, 0x0D20FE4FC4D3F062, 0x4C3CDD90776D463F, 0xB01358BA32C4F113, 0x8F18B9F0A3AE9CD8, 0x322B1F0555B99DA9, 0x0D20FE4FC4D3F062, 0x4C3CDD90776D463F,
0x73373CDAE6072BF4, 0x494A4F79428C6613, 0x7641AE33D3E60BD8, 0x375D8DEC6058BD85, 0x08566CA6F132D04E, 0x73373CDAE6072BF4, 0x494A4F79428C6613, 0x7641AE33D3E60BD8, 0x375D8DEC6058BD85, 0x08566CA6F132D04E,
0xB565CA530725D13F, 0x8A6E2B19964FBCF4, 0xCB7208C625F10AA9, 0xF479E98CB49B6762, 0x23CDEA0666D116CE, 0xB565CA530725D13F, 0x8A6E2B19964FBCF4, 0xCB7208C625F10AA9, 0xF479E98CB49B6762, 0x23CDEA0666D116CE,
0x1CC60B4CF7BB7B05, 0x5DDA28934405CD58, 0x62D1C9D9D56FA093, 0xDFE26F2C2378A1E2, 0xE0E98E66B212CC29, 0x1CC60B4CF7BB7B05, 0x5DDA28934405CD58, 0x62D1C9D9D56FA093, 0xDFE26F2C2378A1E2, 0xE0E98E66B212CC29,
0xA1F5ADB901AC7A74, 0x9EFE4CF390C617BF, 0x9C4505870A3687A9, 0xA34EE4CD9B5CEA62, 0xE252C71228E25C3F, 0xA1F5ADB901AC7A74, 0x9EFE4CF390C617BF, 0x9C4505870A3687A9, 0xA34EE4CD9B5CEA62, 0xE252C71228E25C3F,
0xDD592658B98831F4, 0x606A80AD4F9F3085, 0x5F6161E7DEF55D4E, 0x1E7D42386D4BEB13, 0x2176A372FC2186D8, 0xDD592658B98831F4, 0x606A80AD4F9F3085, 0x5F6161E7DEF55D4E, 0x1E7D42386D4BEB13, 0x2176A372FC2186D8,
0xF6C2A0F82E6BF774, 0xC9C941B2BF019ABF, 0x88D5626D0CBF2CE2, 0xB7DE83279DD54129, 0x0AED25D26BC24058, 0xF6C2A0F82E6BF774, 0xC9C941B2BF019ABF, 0x88D5626D0CBF2CE2, 0xB7DE83279DD54129, 0x0AED25D26BC24058,
0x35E6C498FAA82D93, 0x74FAE74749169BCE, 0x4BF1060DD87CF605, 0xE318EB5CF9EF77C4, 0xDC130A1668851A0F, 0x35E6C498FAA82D93, 0x74FAE74749169BCE, 0x4BF1060DD87CF605, 0xE318EB5CF9EF77C4, 0xDC130A1668851A0F,
0x9D0F29C9DB3BAC52, 0xA204C8834A51C199, 0x1F376E76BC46C0E8, 0x203C8F3C2D2CAD23, 0x6120ACE39E921B7E, 0x9D0F29C9DB3BAC52, 0xA204C8834A51C199, 0x1F376E76BC46C0E8, 0x203C8F3C2D2CAD23, 0x6120ACE39E921B7E,
0x5E2B4DA90FF876B5, 0x899F4E23DDB20719, 0xB694AF694CD86AD2, 0xF7888CB6FF66DC8F, 0xC8836DFC6E0CB144, 0x5E2B4DA90FF876B5, 0x899F4E23DDB20719, 0xB694AF694CD86AD2, 0xF7888CB6FF66DC8F, 0xC8836DFC6E0CB144,
0x75B0CB09981BB035, 0x4ABB2A430971DDFE, 0x0BA7099CBACF6BA3, 0x34ACE8D62BA50668, 0x3617A1A2B155967E, 0x75B0CB09981BB035, 0x4ABB2A430971DDFE, 0x0BA7099CBACF6BA3, 0x34ACE8D62BA50668, 0x3617A1A2B155967E,
0x091C40E8203FFBB5, 0x4800633793814DE8, 0x770B827D02EB2023, 0xCA382488F4FC2152, 0xF533C5C265964C99, 0x091C40E8203FFBB5, 0x4800633793814DE8, 0x770B827D02EB2023, 0xCA382488F4FC2152, 0xF533C5C265964C99,
0xB42FE61DD628FAC4, 0x8B2407574742970F, 0x5C9004DD9508E6A3, 0x639BE59704628B68, 0x2287C648B7DC3D35, 0xB42FE61DD628FAC4, 0x8B2407574742970F, 0x5C9004DD9508E6A3, 0x639BE59704628B68, 0x2287C648B7DC3D35,
0x1D8C270226B650FE, 0xA0BF81F7D0A1518F, 0x9FB460BD41CB3C44, 0xDEA84362F2758A19, 0xE1A3A228631FE7D2, 0x1D8C270226B650FE, 0xA0BF81F7D0A1518F, 0x9FB460BD41CB3C44, 0xDEA84362F2758A19, 0xE1A3A228631FE7D2,
0xDBDED18BC794AA35, 0xE4D530C156FEC7FE, 0xA5C9131EE54071A3, 0x9AC2F254742A1C68, 0x27F154A1823D1D19, 0xDBDED18BC794AA35, 0xE4D530C156FEC7FE, 0xA5C9131EE54071A3, 0x9AC2F254742A1C68, 0x27F154A1823D1D19,
0x18FAB5EB135770D2, 0x59E69634A0E9C68F, 0x66ED777E3183AB44, 0xB15974F4E3C9DAE8, 0x8E5295BE72A3B723, 0x18FAB5EB135770D2, 0x59E69634A0E9C68F, 0x66ED777E3183AB44, 0xB15974F4E3C9DAE8, 0x8E5295BE72A3B723,
0xCF4EB661C11D017E, 0xF045572B50776CB5, 0x4D76F1DEA6606DC4, 0x727D1094370A000F, 0x3361334B84B4B652, 0xCF4EB661C11D017E, 0xF045572B50776CB5, 0x4D76F1DEA6606DC4, 0x727D1094370A000F, 0x3361334B84B4B652,
0x0C6AD20115DEDB99, 0x0ED19B758F2E4B8F, 0x31DA7A3F1E442644, 0x70C659E0ADFA9019, 0x4FCDB8AA3C90FDD2, 0x0C6AD20115DEDB99, 0x0ED19B758F2E4B8F, 0x31DA7A3F1E442644, 0x70C659E0ADFA9019, 0x4FCDB8AA3C90FDD2,
0xF2FE1E5FCA87FCA3, 0xCDF5FF155BED9168, 0x8CE9DCCAE8532735, 0xB3E23D8079394AFE, 0x64563E0AAB733B52, 0xF2FE1E5FCA87FCA3, 0xCDF5FF155BED9168, 0x8CE9DCCAE8532735, 0xB3E23D8079394AFE, 0x64563E0AAB733B52,
0x5B5DDF403A195699, 0x1A41FC9F89A7E0C4, 0x254A1DD518CD8D0F, 0x9879BB20EEDA8C7E, 0xA7725A6A7FB0E1B5, 0x5B5DDF403A195699, 0x1A41FC9F89A7E0C4, 0x254A1DD518CD8D0F, 0x9879BB20EEDA8C7E, 0xA7725A6A7FB0E1B5,
0xE66E79B5CC0E57E8, 0xD96598FF5D643A23, 0x92949EF28518CC26, 0xAD9F7FB81472A1ED, 0xEC835C67A7CC17B0, 0xE66E79B5CC0E57E8, 0xD96598FF5D643A23, 0x92949EF28518CC26, 0xAD9F7FB81472A1ED, 0xEC835C67A7CC17B0,
0xD388BD2D36A67A7B, 0x6EBB1BD8C0B17B0A, 0x51B0FA9251DB16C1, 0x10ACD94DE265A09C, 0x2FA73807730FCD57, 0xD388BD2D36A67A7B, 0x6EBB1BD8C0B17B0A, 0x51B0FA9251DB16C1, 0x10ACD94DE265A09C, 0x2FA73807730FCD57,
0xF8133B8DA145BCFB, 0xC718DAC7302FD130, 0x8604F9188391676D, 0xB90F185212FB0AA6, 0x043CBEA7E4EC0BD7, 0xF8133B8DA145BCFB, 0xC718DAC7302FD130, 0x8604F9188391676D, 0xB90F185212FB0AA6, 0x043CBEA7E4EC0BD7,
0x3B375FED7586661C, 0x7A2B7C32C638D041, 0x45209D785752BD8A, 0x479BD40CCDA22D9C, 0x789035465CC84057, 0x3B375FED7586661C, 0x7A2B7C32C638D041, 0x45209D785752BD8A, 0x479BD40CCDA22D9C, 0x789035465CC84057,
0x398C1699EF76F60A, 0x0687F7D37E1C9BC1, 0xBBB45126880B9AB0, 0x84BFB06C1961F77B, 0xC5A393B3AADF4126, 0x398C1699EF76F60A, 0x0687F7D37E1C9BC1, 0xBBB45126880B9AB0, 0x84BFB06C1961F77B, 0xC5A393B3AADF4126,
0xFAA872F93BB52CED, 0x2D1C7173E9FF5D41, 0x121790397895308A, 0x530BB3E6CB2B86D7, 0x6C0052AC5A41EB1C, 0xFAA872F93BB52CED, 0x2D1C7173E9FF5D41, 0x121790397895308A, 0x530BB3E6CB2B86D7, 0x6C0052AC5A41EB1C,
0xD133F459AC56EA6D, 0xEE3815133D3C87A6, 0xAF2436CC8E8231FB, 0x902FD7861FE85C30, 0xAA52A425BB6311D7, 0xD133F459AC56EA6D, 0xEE3815133D3C87A6, 0xAF2436CC8E8231FB, 0x902FD7861FE85C30, 0xAA52A425BB6311D7,
0x9559456F2A097C1C, 0xD44566B099B7CA41, 0xEB4E87FA08DDA78A, 0x567D210FFECAA6FB, 0x6976C0456FA0CB30, 0x9559456F2A097C1C, 0xD44566B099B7CA41, 0xEB4E87FA08DDA78A, 0x567D210FFECAA6FB, 0x6976C0456FA0CB30,
0x286AE39ADC1E7D6D, 0x176102D04D7410A6, 0xC0D5015A9F3E610A, 0xFFDEE0100E540CC1, 0xBEC2C3CFBDEABA9C, 0x286AE39ADC1E7D6D, 0x176102D04D7410A6, 0xC0D5015A9F3E610A, 0xFFDEE0100E540CC1, 0xBEC2C3CFBDEABA9C,
0x81C922852C80D757, 0x3CFA8470DA97D626, 0x03F1653A4BFDBBED, 0x42ED46E5F8430DB0, 0x7DE6A7AF6929607B, 0x81C922852C80D757, 0x3CFA8470DA97D626, 0x03F1653A4BFDBBED, 0x42ED46E5F8430DB0, 0x7DE6A7AF6929607B,
0x7F5DEEDBF3D9F06D, 0x40560F9162B39DA6, 0x014A2C4ED10D2BFB, 0x3E41CD0440674630, 0x83726BF1B6704741, 0x7F5DEEDBF3D9F06D, 0x40560F9162B39DA6, 0x014A2C4ED10D2BFB, 0x3E41CD0440674630, 0x83726BF1B6704741,
0xBC798ABB271A2A8A, 0xFD65A96494A49CD7, 0xC26E482E05CEF11C, 0x15DA4BA4D78480B0, 0x2AD1AAEE46EEED7B, 0xBC798ABB271A2A8A, 0xFD65A96494A49CD7, 0xC26E482E05CEF11C, 0x15DA4BA4D78480B0, 0x2AD1AAEE46EEED7B,
0x6BCD8931F5505B26, 0x54C6687B643A36ED, 0xE9F5CE8E922D379C, 0xD6FE2FC403475A57, 0x97E20C1BB0F9EC0A, 0x6BCD8931F5505B26, 0x54C6687B643A36ED, 0xE9F5CE8E922D379C, 0xD6FE2FC403475A57, 0x97E20C1BB0F9EC0A,
0xA8E9ED51219381C1}, 0xA8E9ED51219381C1},
{0x0000000000000000, 0x1DEE8A5E222CA1DC, 0x3BDD14BC445943B8, 0x26339EE26675E264, 0x77BA297888B28770, {0x0000000000000000, 0x1DEE8A5E222CA1DC, 0x3BDD14BC445943B8, 0x26339EE26675E264, 0x77BA297888B28770,
0x6A54A326AA9E26AC, 0x4C673DC4CCEBC4C8, 0x5189B79AEEC76514, 0xEF7452F111650EE0, 0xF29AD8AF3349AF3C, 0x6A54A326AA9E26AC, 0x4C673DC4CCEBC4C8, 0x5189B79AEEC76514, 0xEF7452F111650EE0, 0xF29AD8AF3349AF3C,
0xD4A9464D553C4D58, 0xC947CC137710EC84, 0x98CE7B8999D78990, 0x8520F1D7BBFB284C, 0xA3136F35DD8ECA28, 0xD4A9464D553C4D58, 0xC947CC137710EC84, 0x98CE7B8999D78990, 0x8520F1D7BBFB284C, 0xA3136F35DD8ECA28,
0xBEFDE56BFFA26BF4, 0x4C300AC98DC40345, 0x51DE8097AFE8A299, 0x77ED1E75C99D40FD, 0x6A03942BEBB1E121, 0xBEFDE56BFFA26BF4, 0x4C300AC98DC40345, 0x51DE8097AFE8A299, 0x77ED1E75C99D40FD, 0x6A03942BEBB1E121,
0x3B8A23B105768435, 0x2664A9EF275A25E9, 0x0057370D412FC78D, 0x1DB9BD5363036651, 0xA34458389CA10DA5, 0x3B8A23B105768435, 0x2664A9EF275A25E9, 0x0057370D412FC78D, 0x1DB9BD5363036651, 0xA34458389CA10DA5,
0xBEAAD266BE8DAC79, 0x98994C84D8F84E1D, 0x8577C6DAFAD4EFC1, 0xD4FE714014138AD5, 0xC910FB1E363F2B09, 0xBEAAD266BE8DAC79, 0x98994C84D8F84E1D, 0x8577C6DAFAD4EFC1, 0xD4FE714014138AD5, 0xC910FB1E363F2B09,
0xEF2365FC504AC96D, 0xF2CDEFA2726668B1, 0x986015931B88068A, 0x858E9FCD39A4A756, 0xA3BD012F5FD14532, 0xEF2365FC504AC96D, 0xF2CDEFA2726668B1, 0x986015931B88068A, 0x858E9FCD39A4A756, 0xA3BD012F5FD14532,
0xBE538B717DFDE4EE, 0xEFDA3CEB933A81FA, 0xF234B6B5B1162026, 0xD4072857D763C242, 0xC9E9A209F54F639E, 0xBE538B717DFDE4EE, 0xEFDA3CEB933A81FA, 0xF234B6B5B1162026, 0xD4072857D763C242, 0xC9E9A209F54F639E,
0x771447620AED086A, 0x6AFACD3C28C1A9B6, 0x4CC953DE4EB44BD2, 0x5127D9806C98EA0E, 0x00AE6E1A825F8F1A, 0x771447620AED086A, 0x6AFACD3C28C1A9B6, 0x4CC953DE4EB44BD2, 0x5127D9806C98EA0E, 0x00AE6E1A825F8F1A,
0x1D40E444A0732EC6, 0x3B737AA6C606CCA2, 0x269DF0F8E42A6D7E, 0xD4501F5A964C05CF, 0xC9BE9504B460A413, 0x1D40E444A0732EC6, 0x3B737AA6C606CCA2, 0x269DF0F8E42A6D7E, 0xD4501F5A964C05CF, 0xC9BE9504B460A413,
0xEF8D0BE6D2154677, 0xF26381B8F039E7AB, 0xA3EA36221EFE82BF, 0xBE04BC7C3CD22363, 0x9837229E5AA7C107, 0xEF8D0BE6D2154677, 0xF26381B8F039E7AB, 0xA3EA36221EFE82BF, 0xBE04BC7C3CD22363, 0x9837229E5AA7C107,
0x85D9A8C0788B60DB, 0x3B244DAB87290B2F, 0x26CAC7F5A505AAF3, 0x00F95917C3704897, 0x1D17D349E15CE94B, 0x85D9A8C0788B60DB, 0x3B244DAB87290B2F, 0x26CAC7F5A505AAF3, 0x00F95917C3704897, 0x1D17D349E15CE94B,
0x4C9E64D30F9B8C5F, 0x5170EE8D2DB72D83, 0x7743706F4BC2CFE7, 0x6AADFA3169EE6E3B, 0xA218840D981E1391, 0x4C9E64D30F9B8C5F, 0x5170EE8D2DB72D83, 0x7743706F4BC2CFE7, 0x6AADFA3169EE6E3B, 0xA218840D981E1391,
0xBFF60E53BA32B24D, 0x99C590B1DC475029, 0x842B1AEFFE6BF1F5, 0xD5A2AD7510AC94E1, 0xC84C272B3280353D, 0xBFF60E53BA32B24D, 0x99C590B1DC475029, 0x842B1AEFFE6BF1F5, 0xD5A2AD7510AC94E1, 0xC84C272B3280353D,
0xEE7FB9C954F5D759, 0xF391339776D97685, 0x4D6CD6FC897B1D71, 0x50825CA2AB57BCAD, 0x76B1C240CD225EC9, 0xEE7FB9C954F5D759, 0xF391339776D97685, 0x4D6CD6FC897B1D71, 0x50825CA2AB57BCAD, 0x76B1C240CD225EC9,
0x6B5F481EEF0EFF15, 0x3AD6FF8401C99A01, 0x273875DA23E53BDD, 0x010BEB384590D9B9, 0x1CE5616667BC7865, 0x6B5F481EEF0EFF15, 0x3AD6FF8401C99A01, 0x273875DA23E53BDD, 0x010BEB384590D9B9, 0x1CE5616667BC7865,
0xEE288EC415DA10D4, 0xF3C6049A37F6B108, 0xD5F59A785183536C, 0xC81B102673AFF2B0, 0x9992A7BC9D6897A4, 0xEE288EC415DA10D4, 0xF3C6049A37F6B108, 0xD5F59A785183536C, 0xC81B102673AFF2B0, 0x9992A7BC9D6897A4,
0x847C2DE2BF443678, 0xA24FB300D931D41C, 0xBFA1395EFB1D75C0, 0x015CDC3504BF1E34, 0x1CB2566B2693BFE8, 0x847C2DE2BF443678, 0xA24FB300D931D41C, 0xBFA1395EFB1D75C0, 0x015CDC3504BF1E34, 0x1CB2566B2693BFE8,
0x3A81C88940E65D8C, 0x276F42D762CAFC50, 0x76E6F54D8C0D9944, 0x6B087F13AE213898, 0x4D3BE1F1C854DAFC, 0x3A81C88940E65D8C, 0x276F42D762CAFC50, 0x76E6F54D8C0D9944, 0x6B087F13AE213898, 0x4D3BE1F1C854DAFC,
0x50D56BAFEA787B20, 0x3A78919E8396151B, 0x27961BC0A1BAB4C7, 0x01A58522C7CF56A3, 0x1C4B0F7CE5E3F77F, 0x50D56BAFEA787B20, 0x3A78919E8396151B, 0x27961BC0A1BAB4C7, 0x01A58522C7CF56A3, 0x1C4B0F7CE5E3F77F,
0x4DC2B8E60B24926B, 0x502C32B8290833B7, 0x761FAC5A4F7DD1D3, 0x6BF126046D51700F, 0xD50CC36F92F31BFB, 0x4DC2B8E60B24926B, 0x502C32B8290833B7, 0x761FAC5A4F7DD1D3, 0x6BF126046D51700F, 0xD50CC36F92F31BFB,
0xC8E24931B0DFBA27, 0xEED1D7D3D6AA5843, 0xF33F5D8DF486F99F, 0xA2B6EA171A419C8B, 0xBF586049386D3D57, 0xC8E24931B0DFBA27, 0xEED1D7D3D6AA5843, 0xF33F5D8DF486F99F, 0xA2B6EA171A419C8B, 0xBF586049386D3D57,
0x996BFEAB5E18DF33, 0x848574F57C347EEF, 0x76489B570E52165E, 0x6BA611092C7EB782, 0x4D958FEB4A0B55E6, 0x996BFEAB5E18DF33, 0x848574F57C347EEF, 0x76489B570E52165E, 0x6BA611092C7EB782, 0x4D958FEB4A0B55E6,
0x507B05B56827F43A, 0x01F2B22F86E0912E, 0x1C1C3871A4CC30F2, 0x3A2FA693C2B9D296, 0x27C12CCDE095734A, 0x507B05B56827F43A, 0x01F2B22F86E0912E, 0x1C1C3871A4CC30F2, 0x3A2FA693C2B9D296, 0x27C12CCDE095734A,
0x993CC9A61F3718BE, 0x84D243F83D1BB962, 0xA2E1DD1A5B6E5B06, 0xBF0F57447942FADA, 0xEE86E0DE97859FCE, 0x993CC9A61F3718BE, 0x84D243F83D1BB962, 0xA2E1DD1A5B6E5B06, 0xBF0F57447942FADA, 0xEE86E0DE97859FCE,
0xF3686A80B5A93E12, 0xD55BF462D3DCDC76, 0xC8B57E3CF1F07DAA, 0xD6E9A7309F3239A7, 0xCB072D6EBD1E987B, 0xF3686A80B5A93E12, 0xD55BF462D3DCDC76, 0xC8B57E3CF1F07DAA, 0xD6E9A7309F3239A7, 0xCB072D6EBD1E987B,
0xED34B38CDB6B7A1F, 0xF0DA39D2F947DBC3, 0xA1538E481780BED7, 0xBCBD041635AC1F0B, 0x9A8E9AF453D9FD6F, 0xED34B38CDB6B7A1F, 0xF0DA39D2F947DBC3, 0xA1538E481780BED7, 0xBCBD041635AC1F0B, 0x9A8E9AF453D9FD6F,
0x876010AA71F55CB3, 0x399DF5C18E573747, 0x24737F9FAC7B969B, 0x0240E17DCA0E74FF, 0x1FAE6B23E822D523, 0x876010AA71F55CB3, 0x399DF5C18E573747, 0x24737F9FAC7B969B, 0x0240E17DCA0E74FF, 0x1FAE6B23E822D523,
0x4E27DCB906E5B037, 0x53C956E724C911EB, 0x75FAC80542BCF38F, 0x6814425B60905253, 0x9AD9ADF912F63AE2, 0x4E27DCB906E5B037, 0x53C956E724C911EB, 0x75FAC80542BCF38F, 0x6814425B60905253, 0x9AD9ADF912F63AE2,
0x873727A730DA9B3E, 0xA104B94556AF795A, 0xBCEA331B7483D886, 0xED6384819A44BD92, 0xF08D0EDFB8681C4E, 0x873727A730DA9B3E, 0xA104B94556AF795A, 0xBCEA331B7483D886, 0xED6384819A44BD92, 0xF08D0EDFB8681C4E,
0xD6BE903DDE1DFE2A, 0xCB501A63FC315FF6, 0x75ADFF0803933402, 0x6843755621BF95DE, 0x4E70EBB447CA77BA, 0xD6BE903DDE1DFE2A, 0xCB501A63FC315FF6, 0x75ADFF0803933402, 0x6843755621BF95DE, 0x4E70EBB447CA77BA,
0x539E61EA65E6D666, 0x0217D6708B21B372, 0x1FF95C2EA90D12AE, 0x39CAC2CCCF78F0CA, 0x24244892ED545116, 0x539E61EA65E6D666, 0x0217D6708B21B372, 0x1FF95C2EA90D12AE, 0x39CAC2CCCF78F0CA, 0x24244892ED545116,
0x4E89B2A384BA3F2D, 0x536738FDA6969EF1, 0x7554A61FC0E37C95, 0x68BA2C41E2CFDD49, 0x39339BDB0C08B85D, 0x4E89B2A384BA3F2D, 0x536738FDA6969EF1, 0x7554A61FC0E37C95, 0x68BA2C41E2CFDD49, 0x39339BDB0C08B85D,
0x24DD11852E241981, 0x02EE8F674851FBE5, 0x1F0005396A7D5A39, 0xA1FDE05295DF31CD, 0xBC136A0CB7F39011, 0x24DD11852E241981, 0x02EE8F674851FBE5, 0x1F0005396A7D5A39, 0xA1FDE05295DF31CD, 0xBC136A0CB7F39011,
0x9A20F4EED1867275, 0x87CE7EB0F3AAD3A9, 0xD647C92A1D6DB6BD, 0xCBA943743F411761, 0xED9ADD965934F505, 0x9A20F4EED1867275, 0x87CE7EB0F3AAD3A9, 0xD647C92A1D6DB6BD, 0xCBA943743F411761, 0xED9ADD965934F505,
0xF07457C87B1854D9, 0x02B9B86A097E3C68, 0x1F5732342B529DB4, 0x3964ACD64D277FD0, 0x248A26886F0BDE0C, 0xF07457C87B1854D9, 0x02B9B86A097E3C68, 0x1F5732342B529DB4, 0x3964ACD64D277FD0, 0x248A26886F0BDE0C,
0x7503911281CCBB18, 0x68ED1B4CA3E01AC4, 0x4EDE85AEC595F8A0, 0x53300FF0E7B9597C, 0xEDCDEA9B181B3288, 0x7503911281CCBB18, 0x68ED1B4CA3E01AC4, 0x4EDE85AEC595F8A0, 0x53300FF0E7B9597C, 0xEDCDEA9B181B3288,
0xF02360C53A379354, 0xD610FE275C427130, 0xCBFE74797E6ED0EC, 0x9A77C3E390A9B5F8, 0x879949BDB2851424, 0xF02360C53A379354, 0xD610FE275C427130, 0xCBFE74797E6ED0EC, 0x9A77C3E390A9B5F8, 0x879949BDB2851424,
0xA1AAD75FD4F0F640, 0xBC445D01F6DC579C, 0x74F1233D072C2A36, 0x691FA96325008BEA, 0x4F2C37814375698E, 0xA1AAD75FD4F0F640, 0xBC445D01F6DC579C, 0x74F1233D072C2A36, 0x691FA96325008BEA, 0x4F2C37814375698E,
0x52C2BDDF6159C852, 0x034B0A458F9EAD46, 0x1EA5801BADB20C9A, 0x38961EF9CBC7EEFE, 0x257894A7E9EB4F22, 0x52C2BDDF6159C852, 0x034B0A458F9EAD46, 0x1EA5801BADB20C9A, 0x38961EF9CBC7EEFE, 0x257894A7E9EB4F22,
0x9B8571CC164924D6, 0x866BFB923465850A, 0xA05865705210676E, 0xBDB6EF2E703CC6B2, 0xEC3F58B49EFBA3A6, 0x9B8571CC164924D6, 0x866BFB923465850A, 0xA05865705210676E, 0xBDB6EF2E703CC6B2, 0xEC3F58B49EFBA3A6,
0xF1D1D2EABCD7027A, 0xD7E24C08DAA2E01E, 0xCA0CC656F88E41C2, 0x38C129F48AE82973, 0x252FA3AAA8C488AF, 0xF1D1D2EABCD7027A, 0xD7E24C08DAA2E01E, 0xCA0CC656F88E41C2, 0x38C129F48AE82973, 0x252FA3AAA8C488AF,
0x031C3D48CEB16ACB, 0x1EF2B716EC9DCB17, 0x4F7B008C025AAE03, 0x52958AD220760FDF, 0x74A614304603EDBB, 0x031C3D48CEB16ACB, 0x1EF2B716EC9DCB17, 0x4F7B008C025AAE03, 0x52958AD220760FDF, 0x74A614304603EDBB,
0x69489E6E642F4C67, 0xD7B57B059B8D2793, 0xCA5BF15BB9A1864F, 0xEC686FB9DFD4642B, 0xF186E5E7FDF8C5F7, 0x69489E6E642F4C67, 0xD7B57B059B8D2793, 0xCA5BF15BB9A1864F, 0xEC686FB9DFD4642B, 0xF186E5E7FDF8C5F7,
0xA00F527D133FA0E3, 0xBDE1D8233113013F, 0x9BD246C15766E35B, 0x863CCC9F754A4287, 0xEC9136AE1CA42CBC, 0xA00F527D133FA0E3, 0xBDE1D8233113013F, 0x9BD246C15766E35B, 0x863CCC9F754A4287, 0xEC9136AE1CA42CBC,
0xF17FBCF03E888D60, 0xD74C221258FD6F04, 0xCAA2A84C7AD1CED8, 0x9B2B1FD69416ABCC, 0x86C59588B63A0A10, 0xF17FBCF03E888D60, 0xD74C221258FD6F04, 0xCAA2A84C7AD1CED8, 0x9B2B1FD69416ABCC, 0x86C59588B63A0A10,
0xA0F60B6AD04FE874, 0xBD188134F26349A8, 0x03E5645F0DC1225C, 0x1E0BEE012FED8380, 0x383870E3499861E4, 0xA0F60B6AD04FE874, 0xBD188134F26349A8, 0x03E5645F0DC1225C, 0x1E0BEE012FED8380, 0x383870E3499861E4,
0x25D6FABD6BB4C038, 0x745F4D278573A52C, 0x69B1C779A75F04F0, 0x4F82599BC12AE694, 0x526CD3C5E3064748, 0x25D6FABD6BB4C038, 0x745F4D278573A52C, 0x69B1C779A75F04F0, 0x4F82599BC12AE694, 0x526CD3C5E3064748,
0xA0A13C6791602FF9, 0xBD4FB639B34C8E25, 0x9B7C28DBD5396C41, 0x8692A285F715CD9D, 0xD71B151F19D2A889, 0xA0A13C6791602FF9, 0xBD4FB639B34C8E25, 0x9B7C28DBD5396C41, 0x8692A285F715CD9D, 0xD71B151F19D2A889,
0xCAF59F413BFE0955, 0xECC601A35D8BEB31, 0xF1288BFD7FA74AED, 0x4FD56E9680052119, 0x523BE4C8A22980C5, 0xCAF59F413BFE0955, 0xECC601A35D8BEB31, 0xF1288BFD7FA74AED, 0x4FD56E9680052119, 0x523BE4C8A22980C5,
0x74087A2AC45C62A1, 0x69E6F074E670C37D, 0x386F47EE08B7A669, 0x2581CDB02A9B07B5, 0x03B253524CEEE5D1, 0x74087A2AC45C62A1, 0x69E6F074E670C37D, 0x386F47EE08B7A669, 0x2581CDB02A9B07B5, 0x03B253524CEEE5D1,
0x1E5CD90C6EC2440D}}; 0x1E5CD90C6EC2440D}
};
#define CRC64_ECMA_POLY 0xC96C5795D7870F42 #define CRC64_ECMA_POLY 0xC96C5795D7870F42
#define CRC64_ECMA_SEED 0xFFFFFFFFFFFFFFFF #define CRC64_ECMA_SEED 0xFFFFFFFFFFFFFFFF
AARU_EXPORT crc64_ctx *AARU_CALL crc64_init(); AARU_EXPORT crc64_ctx *AARU_CALL crc64_init();
AARU_EXPORT int AARU_CALL crc64_update(crc64_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL crc64_update(crc64_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL crc64_final(crc64_ctx *ctx, uint64_t *crc); AARU_EXPORT int AARU_CALL crc64_final(crc64_ctx *ctx, uint64_t *crc);
AARU_EXPORT void AARU_CALL crc64_free(crc64_ctx *ctx); AARU_EXPORT void AARU_CALL crc64_free(crc64_ctx *ctx);
AARU_EXPORT void AARU_CALL crc64_slicing(uint64_t *previous_crc, const uint8_t *data, uint32_t len); AARU_EXPORT void AARU_CALL crc64_slicing(uint64_t *previous_crc, const uint8_t *data, uint32_t len);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
@@ -252,4 +253,4 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_crc, const uint8_t *data, long len); AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_crc, const uint8_t *data, long len);
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_CRC64_H #endif // AARU_CHECKSUMS_NATIVE_CRC64_H

View File

@@ -56,8 +56,8 @@ static uint64_t div129by65(uint64_t poly)
} }
static const uint8_t shuffleMasks[] = { static const uint8_t shuffleMasks[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
}; };
TARGET_WITH_CLMUL static void shiftRight128(__m128i in, size_t n, __m128i *outLeft, __m128i *outRight) TARGET_WITH_CLMUL static void shiftRight128(__m128i in, size_t n, __m128i *outLeft, __m128i *outRight)
@@ -85,10 +85,10 @@ TARGET_WITH_CLMUL static __m128i fold(__m128i in, __m128i foldConstants)
*/ */
AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const uint8_t *data, long length) AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const uint8_t *data, long length)
{ {
const uint64_t k1 = 0xe05dd497ca393ae4; // bitReflect(expMod65(128 + 64, poly, 1)) << 1; const uint64_t k1 = 0xe05dd497ca393ae4; // bitReflect(expMod65(128 + 64, poly, 1)) << 1;
const uint64_t k2 = 0xdabe95afc7875f40; // bitReflect(expMod65(128, poly, 1)) << 1; const uint64_t k2 = 0xdabe95afc7875f40; // bitReflect(expMod65(128, poly, 1)) << 1;
const uint64_t mu = 0x9c3e466c172963d5; // (bitReflect(div129by65(poly)) << 1) | 1; const uint64_t mu = 0x9c3e466c172963d5; // (bitReflect(div129by65(poly)) << 1) | 1;
const uint64_t p = 0x92d8af2baf0e1e85; // (bitReflect(poly) << 1) | 1; const uint64_t p = 0x92d8af2baf0e1e85; // (bitReflect(poly) << 1) | 1;
const __m128i foldConstants1 = _mm_set_epi64x(k2, k1); const __m128i foldConstants1 = _mm_set_epi64x(k2, k1);
const __m128i foldConstants2 = _mm_set_epi64x(p, mu); const __m128i foldConstants2 = _mm_set_epi64x(p, mu);
@@ -124,8 +124,8 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
shiftRight128(data0, leadOutSize, &A, &B); shiftRight128(data0, leadOutSize, &A, &B);
const __m128i P = _mm_xor_si128(A, crc0); const __m128i P = _mm_xor_si128(A, crc0);
R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10), R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10),
_mm_xor_si128(_mm_srli_si128(P, 8), _mm_slli_si128(crc1, 8))); _mm_xor_si128(_mm_srli_si128(P, 8), _mm_slli_si128(crc1, 8)));
} }
else if(alignedLength == 2) else if(alignedLength == 2)
{ {
@@ -142,8 +142,8 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
shiftRight128(data1, leadOutSize, &C, &D); shiftRight128(data1, leadOutSize, &C, &D);
const __m128i P = _mm_xor_si128(_mm_xor_si128(B, C), crc0); const __m128i P = _mm_xor_si128(_mm_xor_si128(B, C), crc0);
R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10), R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10),
_mm_xor_si128(_mm_srli_si128(P, 8), _mm_slli_si128(crc1, 8))); _mm_xor_si128(_mm_srli_si128(P, 8), _mm_slli_si128(crc1, 8)));
} }
else else
{ {
@@ -156,7 +156,7 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
shiftRight128(_mm_xor_si128(data1, crc1), leadOutSize, &C, &D); shiftRight128(_mm_xor_si128(data1, crc1), leadOutSize, &C, &D);
const __m128i P = _mm_xor_si128(fold(A, foldConstants1), _mm_xor_si128(B, C)); const __m128i P = _mm_xor_si128(fold(A, foldConstants1), _mm_xor_si128(B, C));
R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10), _mm_srli_si128(P, 8)); R = _mm_xor_si128(_mm_clmulepi64_si128(P, foldConstants1, 0x10), _mm_srli_si128(P, 8));
} }
} }
else else
@@ -179,8 +179,7 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
} }
__m128i P; __m128i P;
if(length == 16) if(length == 16) { P = _mm_xor_si128(accumulator, _mm_load_si128(alignedData)); }
{ P = _mm_xor_si128(accumulator, _mm_load_si128(alignedData)); }
else else
{ {
const __m128i end0 = _mm_xor_si128(accumulator, _mm_load_si128(alignedData)); const __m128i end0 = _mm_xor_si128(accumulator, _mm_load_si128(alignedData));
@@ -199,9 +198,7 @@ AARU_EXPORT TARGET_WITH_CLMUL uint64_t AARU_CALL crc64_clmul(uint64_t crc, const
// Final Barrett reduction // Final Barrett reduction
const __m128i T1 = _mm_clmulepi64_si128(R, foldConstants2, 0x00); const __m128i T1 = _mm_clmulepi64_si128(R, foldConstants2, 0x00);
const __m128i T2 = const __m128i T2 =
_mm_xor_si128( _mm_xor_si128(_mm_xor_si128(_mm_clmulepi64_si128(T1, foldConstants2, 0x10), _mm_slli_si128(T1, 8)), R);
_mm_xor_si128(_mm_clmulepi64_si128(T1, foldConstants2, 0x10), _mm_slli_si128(T1, 8)),
R);
#if defined(_WIN64) #if defined(_WIN64)
return ~_mm_extract_epi64(T2, 1); return ~_mm_extract_epi64(T2, 1);

View File

@@ -17,36 +17,30 @@
#include "crc64.h" #include "crc64.h"
static const uint8_t shuffleMasks[] = { static const uint8_t shuffleMasks[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
}; };
TARGET_WITH_NEON FORCE_INLINE void shiftRight128(uint64x2_t in, size_t n, uint64x2_t *outLeft, uint64x2_t *outRight) TARGET_WITH_NEON FORCE_INLINE void shiftRight128(uint64x2_t in, size_t n, uint64x2_t *outLeft, uint64x2_t *outRight)
{ {
const uint64x2_t maskA = const uint64x2_t maskA =
vreinterpretq_u64_u32( vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)(const uint64x2_t *)(shuffleMasks + (16 - n))));
vld1q_u32((const uint32_t *)(const uint64x2_t *)(shuffleMasks + (16 - n))));
uint64x2_t b = vreinterpretq_u64_u8(vceqq_u8(vreinterpretq_u8_u64(vreinterpretq_u64_u32(vdupq_n_u32(0))), uint64x2_t b = vreinterpretq_u64_u8(vceqq_u8(vreinterpretq_u8_u64(vreinterpretq_u64_u32(vdupq_n_u32(0))),
vreinterpretq_u8_u64( vreinterpretq_u8_u64(vreinterpretq_u64_u32(vdupq_n_u32(0)))));
vreinterpretq_u64_u32(vdupq_n_u32(0)))));
const uint64x2_t maskB = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(maskA), vreinterpretq_u32_u64(b))); const uint64x2_t maskB = vreinterpretq_u64_u32(veorq_u32(vreinterpretq_u32_u64(maskA), vreinterpretq_u32_u64(b)));
*outLeft = mm_shuffle_epi8(in, maskB); *outLeft = mm_shuffle_epi8(in, maskB);
*outRight = mm_shuffle_epi8(in, maskA); *outRight = mm_shuffle_epi8(in, maskA);
} }
TARGET_WITH_NEON FORCE_INLINE uint64x2_t TARGET_WITH_NEON FORCE_INLINE uint64x2_t fold(uint64x2_t in, uint64x2_t foldConstants)
fold (uint64x2_t
in,
uint64x2_t foldConstants
)
{ {
return return
veorq_u64(sse2neon_vmull_p64(vget_low_u64(in), vget_low_u64(foldConstants)), veorq_u64(sse2neon_vmull_p64(vget_low_u64(in), vget_low_u64(foldConstants)),
sse2neon_vmull_p64(vget_high_u64(in), vget_high_u64(foldConstants)) sse2neon_vmull_p64(vget_high_u64(in), vget_high_u64(foldConstants))
); );
} }
/** /**
@@ -65,10 +59,10 @@ veorq_u64(sse2neon_vmull_p64(vget_low_u64(in), vget_low_u64(foldConstants)),
*/ */
AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_crc, const uint8_t *data, long len) AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_crc, const uint8_t *data, long len)
{ {
const uint64_t k1 = 0xe05dd497ca393ae4; // bitReflect(expMod65(128 + 64, poly, 1)) << 1; const uint64_t k1 = 0xe05dd497ca393ae4; // bitReflect(expMod65(128 + 64, poly, 1)) << 1;
const uint64_t k2 = 0xdabe95afc7875f40; // bitReflect(expMod65(128, poly, 1)) << 1; const uint64_t k2 = 0xdabe95afc7875f40; // bitReflect(expMod65(128, poly, 1)) << 1;
const uint64_t mu = 0x9c3e466c172963d5; // (bitReflect(div129by65(poly)) << 1) | 1; const uint64_t mu = 0x9c3e466c172963d5; // (bitReflect(div129by65(poly)) << 1) | 1;
const uint64_t p = 0x92d8af2baf0e1e85; // (bitReflect(poly) << 1) | 1; const uint64_t p = 0x92d8af2baf0e1e85; // (bitReflect(poly) << 1) | 1;
const uint64x2_t foldConstants1 = vcombine_u64(vcreate_u64(k1), vcreate_u64(k2)); const uint64x2_t foldConstants1 = vcombine_u64(vcreate_u64(k1), vcreate_u64(k2));
const uint64x2_t foldConstants2 = vcombine_u64(vcreate_u64(mu), vcreate_u64(p)); const uint64x2_t foldConstants2 = vcombine_u64(vcreate_u64(mu), vcreate_u64(p));
@@ -85,16 +79,13 @@ AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_cr
const size_t alignedLength = alignedEnd - alignedData; const size_t alignedLength = alignedEnd - alignedData;
const uint64x2_t leadInMask = const uint64x2_t leadInMask =
vreinterpretq_u64_u32(vld1q_u32( vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)(const uint64x2_t *)(shuffleMasks + (16 - leadInSize))));
(const uint32_t *)(const uint64x2_t *)(shuffleMasks + (16 - leadInSize)))); uint64x2_t a = vreinterpretq_u64_u32(vdupq_n_u32(0));
uint64x2_t a = vreinterpretq_u64_u32(vdupq_n_u32(0)); uint64x2_t b = vreinterpretq_u64_u32(
uint64x2_t b = vreinterpretq_u64_u32( vld1q_u32((const uint32_t *)alignedData)); // Use a signed shift right to create a mask with the sign bit
vld1q_u32((const uint32_t *)alignedData)); // Use a signed shift right to create a mask with the sign bit const uint64x2_t data0 =
const uint64x2_t data0 = vreinterpretq_u64_u8(vbslq_u8(vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_u64(leadInMask), 7)),
vreinterpretq_u64_u8( vreinterpretq_u8_u64(b), vreinterpretq_u8_u64(a)));
vbslq_u8(vreinterpretq_u8_s8(vshrq_n_s8(vreinterpretq_s8_u64(leadInMask), 7)),
vreinterpretq_u8_u64(b),
vreinterpretq_u8_u64(a)));
const uint64x2_t initialCrc = vsetq_lane_u64(~previous_crc, vdupq_n_u64(0), 0); const uint64x2_t initialCrc = vsetq_lane_u64(~previous_crc, vdupq_n_u64(0), 0);
@@ -109,8 +100,8 @@ AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_cr
shiftRight128(data0, leadOutSize, &A, &B); shiftRight128(data0, leadOutSize, &A, &B);
const uint64x2_t P = veorq_u64(A, crc0); const uint64x2_t P = veorq_u64(A, crc0);
R = veorq_u64(sse2neon_vmull_p64(vget_low_u64(P), vget_high_u64(foldConstants1)), R = veorq_u64(sse2neon_vmull_p64(vget_low_u64(P), vget_high_u64(foldConstants1)),
veorq_u64(mm_srli_si128(P, 8), mm_slli_si128(crc1, 8))); veorq_u64(mm_srli_si128(P, 8), mm_slli_si128(crc1, 8)));
} }
else if(alignedLength == 2) else if(alignedLength == 2)
{ {
@@ -127,8 +118,8 @@ AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_cr
shiftRight128(data1, leadOutSize, &C, &D); shiftRight128(data1, leadOutSize, &C, &D);
const uint64x2_t P = veorq_u64(veorq_u64(B, C), crc0); const uint64x2_t P = veorq_u64(veorq_u64(B, C), crc0);
R = veorq_u64(sse2neon_vmull_p64(vget_low_u64(P), vget_high_u64(foldConstants1)), R = veorq_u64(sse2neon_vmull_p64(vget_low_u64(P), vget_high_u64(foldConstants1)),
veorq_u64(mm_srli_si128(P, 8), mm_slli_si128(crc1, 8))); veorq_u64(mm_srli_si128(P, 8), mm_slli_si128(crc1, 8)));
} }
else else
{ {
@@ -165,12 +156,12 @@ AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_cr
} }
uint64x2_t P; uint64x2_t P;
if(len == 16) P = veorq_u64(accumulator, vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)alignedData))); if(len == 16)
P = veorq_u64(accumulator, vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)alignedData)));
else else
{ {
const uint64x2_t end0 = const uint64x2_t end0 =
veorq_u64(accumulator, veorq_u64(accumulator, vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)alignedData)));
vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)alignedData)));
const uint64x2_t end1 = vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)(alignedData + 1))); const uint64x2_t end1 = vreinterpretq_u64_u32(vld1q_u32((const uint32_t *)(alignedData + 1)));
uint64x2_t A, B, C, D; uint64x2_t A, B, C, D;
@@ -187,7 +178,7 @@ AARU_EXPORT TARGET_WITH_NEON uint64_t AARU_CALL crc64_vmull(uint64_t previous_cr
// Final Barrett reduction // Final Barrett reduction
const uint64x2_t T1 = sse2neon_vmull_p64(vget_low_u64(R), vget_low_u64(foldConstants2)); const uint64x2_t T1 = sse2neon_vmull_p64(vget_low_u64(R), vget_low_u64(foldConstants2));
const uint64x2_t T2 = veorq_u64( const uint64x2_t T2 = veorq_u64(
veorq_u64(sse2neon_vmull_p64(vget_low_u64(T1), vget_high_u64(foldConstants2)), mm_slli_si128(T1, 8)), R); veorq_u64(sse2neon_vmull_p64(vget_low_u64(T1), vget_high_u64(foldConstants2)), mm_slli_si128(T1, 8)), R);
return ~vgetq_lane_u64(T2, 1); return ~vgetq_lane_u64(T2, 1);
} }

View File

@@ -75,7 +75,7 @@ AARU_EXPORT int AARU_CALL fletcher16_update(fletcher16_ctx *ctx, const uint8_t *
} }
#endif #endif
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
if(have_avx2()) if(have_avx2())
{ {
@@ -129,8 +129,7 @@ AARU_EXPORT int AARU_CALL fletcher16_update(fletcher16_ctx *ctx, const uint8_t *
{ {
len -= NMAX; len -= NMAX;
n = NMAX / 6; /* NMAX is divisible by 6 */ n = NMAX / 6; /* NMAX is divisible by 6 */
do do {
{
sum1 += data[0]; sum1 += data[0];
sum2 += sum1; sum2 += sum1;
sum1 += data[0 + 1]; sum1 += data[0 + 1];
@@ -146,8 +145,7 @@ AARU_EXPORT int AARU_CALL fletcher16_update(fletcher16_ctx *ctx, const uint8_t *
/* 6 sums unrolled */ /* 6 sums unrolled */
data += 6; data += 6;
} } while(--n);
while(--n);
sum1 %= FLETCHER16_MODULE; sum1 %= FLETCHER16_MODULE;
sum2 %= FLETCHER16_MODULE; sum2 %= FLETCHER16_MODULE;
} }

View File

@@ -21,7 +21,7 @@
#define FLETCHER16_MODULE 0xFF #define FLETCHER16_MODULE 0xFF
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(FLETCHER16_MODULE-1) <= 2^32-1 */ /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(FLETCHER16_MODULE-1) <= 2^32-1 */
#define NMAX 5802 #define NMAX 5802
typedef struct typedef struct
{ {
@@ -30,22 +30,25 @@ typedef struct
} fletcher16_ctx; } fletcher16_ctx;
AARU_EXPORT fletcher16_ctx *AARU_CALL fletcher16_init(); AARU_EXPORT fletcher16_ctx *AARU_CALL fletcher16_init();
AARU_EXPORT int AARU_CALL fletcher16_update(fletcher16_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL fletcher16_update(fletcher16_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL fletcher16_final(fletcher16_ctx *ctx, uint16_t *checksum); AARU_EXPORT int AARU_CALL fletcher16_final(fletcher16_ctx *ctx, uint16_t *checksum);
AARU_EXPORT void AARU_CALL fletcher16_free(fletcher16_ctx *ctx); AARU_EXPORT void AARU_CALL fletcher16_free(fletcher16_ctx *ctx);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher16_avx2(uint8_t* sum1, uint8_t* sum2, const uint8_t* data, long len); AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data,
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher16_ssse3(uint8_t* sum1, uint8_t* sum2, const uint8_t* data, long len); long len);
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data,
long len);
#endif #endif
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) #if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
AARU_EXPORT TARGET_WITH_NEON void AARU_CALL fletcher16_neon(uint8_t* sum1, uint8_t* sum2, const uint8_t* data, uint32_t len); AARU_EXPORT TARGET_WITH_NEON void AARU_CALL fletcher16_neon(uint8_t *sum1, uint8_t *sum2, const uint8_t *data,
uint32_t len);
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_FLETCHER16_H #endif // AARU_CHECKSUMS_NATIVE_FLETCHER16_H

View File

@@ -42,8 +42,7 @@
* @param data Pointer to the data buffer. * @param data Pointer to the data buffer.
* @param len Length of the data buffer in bytes. * @param len Length of the data buffer in bytes.
*/ */
AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
{ {
uint32_t s1 = *sum1; uint32_t s1 = *sum1;
uint32_t s2 = *sum2; uint32_t s2 = *sum2;
@@ -54,7 +53,7 @@ fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
const unsigned BLOCK_SIZE = 1 << 5; const unsigned BLOCK_SIZE = 1 << 5;
if(len >= BLOCK_SIZE) if(len >= BLOCK_SIZE)
{ {
long blocks = len / BLOCK_SIZE; long blocks = len / BLOCK_SIZE;
len -= blocks * BLOCK_SIZE; len -= blocks * BLOCK_SIZE;
while(blocks) while(blocks)
@@ -64,38 +63,8 @@ fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
if(n > blocks) n = (unsigned)blocks; if(n > blocks) n = (unsigned)blocks;
blocks -= n; blocks -= n;
const __m256i tap = _mm256_set_epi8(1, const __m256i tap = _mm256_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32);
const __m256i zero = _mm256_setzero_si256(); const __m256i zero = _mm256_setzero_si256();
const __m256i ones = _mm256_set1_epi16(1); const __m256i ones = _mm256_set1_epi16(1);
@@ -106,8 +75,7 @@ fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
__m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n)); __m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n));
__m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2); __m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2);
__m256i v_s1 = _mm256_setzero_si256(); __m256i v_s1 = _mm256_setzero_si256();
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -116,24 +84,23 @@ fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm256_add_epi32(v_ps, v_s1); v_ps = _mm256_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero)); v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero));
const __m256i mad = _mm256_maddubs_epi16(bytes, tap); const __m256i mad = _mm256_maddubs_epi16(bytes, tap);
v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones)); v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n);
__m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1)); __m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1));
__m128i hi = _mm_unpackhi_epi64(sum, sum); __m128i hi = _mm_unpackhi_epi64(sum, sum);
sum = _mm_add_epi32(hi, sum); sum = _mm_add_epi32(hi, sum);
hi = _mm_shuffle_epi32(sum, 177); hi = _mm_shuffle_epi32(sum, 177);
sum = _mm_add_epi32(sum, hi); sum = _mm_add_epi32(sum, hi);
s1 += _mm_cvtsi128_si32(sum); s1 += _mm_cvtsi128_si32(sum);
v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5)); v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5));
@@ -177,8 +144,7 @@ fletcher16_avx2(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
s1 %= FLETCHER16_MODULE; s1 %= FLETCHER16_MODULE;
s2 %= FLETCHER16_MODULE; s2 %= FLETCHER16_MODULE;
} }

View File

@@ -88,8 +88,12 @@ TARGET_WITH_NEON void fletcher16_neon(uint8_t *sum1, uint8_t *sum2, const uint8_
* processed before s2 must be reduced modulo FLETCHER16_MODULE. * processed before s2 must be reduced modulo FLETCHER16_MODULE.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
uint32x4_t v_s2 = {.n128_u32 = {0, 0, 0, s1 * n}}; uint32x4_t v_s2 = {
uint32x4_t v_s1 = {.n128_u32 = {0, 0, 0, 0}}; .n128_u32 = {0, 0, 0, s1 * n}
};
uint32x4_t v_s1 = {
.n128_u32 = {0, 0, 0, 0}
};
#else #else
uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n}; uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n};
uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0}; uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0};
@@ -98,8 +102,7 @@ TARGET_WITH_NEON void fletcher16_neon(uint8_t *sum1, uint8_t *sum2, const uint8_
uint16x8_t v_column_sum_2 = vdupq_n_u16(0); uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
uint16x8_t v_column_sum_3 = vdupq_n_u16(0); uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
uint16x8_t v_column_sum_4 = vdupq_n_u16(0); uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -108,22 +111,21 @@ TARGET_WITH_NEON void fletcher16_neon(uint8_t *sum1, uint8_t *sum2, const uint8_
/* /*
* Add previous block byte sum to v_s2. * Add previous block byte sum to v_s2.
*/ */
v_s2 = vaddq_u32(v_s2, v_s1); v_s2 = vaddq_u32(v_s2, v_s1);
/* /*
* Horizontally add the bytes for s1. * Horizontally add the bytes for s1.
*/ */
v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
/* /*
* Vertically add the bytes for s2. * Vertically add the bytes for s2.
*/ */
v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1)); v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1));
v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2)); v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2));
v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = vshlq_n_u32(v_s2, 5);
v_s2 = vshlq_n_u32(v_s2, 5);
/* /*
* Multiply-add bytes by [ 32, 31, 30, ... ] for s2. * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
*/ */
@@ -198,8 +200,7 @@ TARGET_WITH_NEON void fletcher16_neon(uint8_t *sum1, uint8_t *sum2, const uint8_
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
s1 %= FLETCHER16_MODULE; s1 %= FLETCHER16_MODULE;
s2 %= FLETCHER16_MODULE; s2 %= FLETCHER16_MODULE;
} }

View File

@@ -49,8 +49,8 @@
* @param data Pointer to the data buffer. * @param data Pointer to the data buffer.
* @param len Length of the data buffer in bytes. * @param len Length of the data buffer in bytes.
*/ */
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data,
fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len) long len)
{ {
uint32_t s1 = *sum1; uint32_t s1 = *sum1;
uint32_t s2 = *sum2; uint32_t s2 = *sum2;
@@ -79,8 +79,7 @@ fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
__m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n); __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
__m128i v_s2 = _mm_set_epi32(0, 0, 0, s2); __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
__m128i v_s1 = _mm_set_epi32(0, 0, 0, 0); __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -89,21 +88,20 @@ fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm_add_epi32(v_ps, v_s1); v_ps = _mm_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1); const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2); const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
/* /*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2). * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/ */
@@ -150,8 +148,7 @@ fletcher16_ssse3(uint8_t *sum1, uint8_t *sum2, const uint8_t *data, long len)
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
s1 %= FLETCHER16_MODULE; s1 %= FLETCHER16_MODULE;
s2 %= FLETCHER16_MODULE; s2 %= FLETCHER16_MODULE;
} }

View File

@@ -92,7 +92,6 @@ AARU_EXPORT int AARU_CALL fletcher32_update(fletcher32_ctx *ctx, const uint8_t *
} }
#endif #endif
uint32_t sum1 = ctx->sum1; uint32_t sum1 = ctx->sum1;
uint32_t sum2 = ctx->sum2; uint32_t sum2 = ctx->sum2;
unsigned n; unsigned n;
@@ -130,8 +129,7 @@ AARU_EXPORT int AARU_CALL fletcher32_update(fletcher32_ctx *ctx, const uint8_t *
{ {
len -= NMAX; len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */ n = NMAX / 16; /* NMAX is divisible by 16 */
do do {
{
sum1 += data[0]; sum1 += data[0];
sum2 += sum1; sum2 += sum1;
sum1 += data[0 + 1]; sum1 += data[0 + 1];
@@ -167,8 +165,7 @@ AARU_EXPORT int AARU_CALL fletcher32_update(fletcher32_ctx *ctx, const uint8_t *
/* 16 sums unrolled */ /* 16 sums unrolled */
data += 16; data += 16;
} } while(--n);
while(--n);
sum1 %= FLETCHER32_MODULE; sum1 %= FLETCHER32_MODULE;
sum2 %= FLETCHER32_MODULE; sum2 %= FLETCHER32_MODULE;
} }

View File

@@ -21,7 +21,7 @@
#define FLETCHER32_MODULE 0xFFFF #define FLETCHER32_MODULE 0xFFFF
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(FLETCHER32_MODULE-1) <= 2^32-1 */ /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(FLETCHER32_MODULE-1) <= 2^32-1 */
#define NMAX 5552 #define NMAX 5552
typedef struct typedef struct
{ {
@@ -29,23 +29,25 @@ typedef struct
uint16_t sum2; uint16_t sum2;
} fletcher32_ctx; } fletcher32_ctx;
AARU_EXPORT fletcher32_ctx* AARU_CALL fletcher32_init(); AARU_EXPORT fletcher32_ctx *AARU_CALL fletcher32_init();
AARU_EXPORT int AARU_CALL fletcher32_update(fletcher32_ctx* ctx, const uint8_t* data, uint32_t len); AARU_EXPORT int AARU_CALL fletcher32_update(fletcher32_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL fletcher32_final(fletcher32_ctx* ctx, uint32_t* checksum); AARU_EXPORT int AARU_CALL fletcher32_final(fletcher32_ctx *ctx, uint32_t *checksum);
AARU_EXPORT void AARU_CALL fletcher32_free(fletcher32_ctx* ctx); AARU_EXPORT void AARU_CALL fletcher32_free(fletcher32_ctx *ctx);
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher32_avx2(uint16_t* sum1, uint16_t* sum2, const uint8_t* data, long len); AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher32_ssse3(uint16_t* sum1, uint16_t* sum2, const uint8_t* data, long len); long len);
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
long len);
#endif #endif
#if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM) #if defined(__aarch64__) || defined(_M_ARM64) || defined(__arm__) || defined(_M_ARM)
AARU_EXPORT void AARU_CALL fletcher32_neon(uint16_t* sum1, uint16_t* sum2, const uint8_t* data, uint32_t len); AARU_EXPORT void AARU_CALL fletcher32_neon(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, uint32_t len);
#endif #endif
#endif // AARU_CHECKSUMS_NATIVE_FLETCHER32_H #endif // AARU_CHECKSUMS_NATIVE_FLETCHER32_H

View File

@@ -42,8 +42,8 @@
* @param data Pointer to the data buffer. * @param data Pointer to the data buffer.
* @param len Length of the data buffer in bytes. * @param len Length of the data buffer in bytes.
*/ */
AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL AARU_EXPORT TARGET_WITH_AVX2 void AARU_CALL fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len) long len)
{ {
uint32_t s1 = *sum1; uint32_t s1 = *sum1;
uint32_t s2 = *sum2; uint32_t s2 = *sum2;
@@ -64,38 +64,8 @@ fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
if(n > blocks) n = (unsigned)blocks; if(n > blocks) n = (unsigned)blocks;
blocks -= n; blocks -= n;
const __m256i tap = _mm256_set_epi8(1, const __m256i tap = _mm256_set_epi8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
2, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32);
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32);
const __m256i zero = _mm256_setzero_si256(); const __m256i zero = _mm256_setzero_si256();
const __m256i ones = _mm256_set1_epi16(1); const __m256i ones = _mm256_set1_epi16(1);
@@ -106,8 +76,7 @@ fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
__m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n)); __m256i v_ps = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, (s1 * n));
__m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2); __m256i v_s2 = _mm256_set_epi32(0, 0, 0, 0, 0, 0, 0, s2);
__m256i v_s1 = _mm256_setzero_si256(); __m256i v_s1 = _mm256_setzero_si256();
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -116,24 +85,23 @@ fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm256_add_epi32(v_ps, v_s1); v_ps = _mm256_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero)); v_s1 = _mm256_add_epi32(v_s1, _mm256_sad_epu8(bytes, zero));
const __m256i mad = _mm256_maddubs_epi16(bytes, tap); const __m256i mad = _mm256_maddubs_epi16(bytes, tap);
v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones)); v_s2 = _mm256_add_epi32(v_s2, _mm256_madd_epi16(mad, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n);
__m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1)); __m128i sum = _mm_add_epi32(_mm256_castsi256_si128(v_s1), _mm256_extracti128_si256(v_s1, 1));
__m128i hi = _mm_unpackhi_epi64(sum, sum); __m128i hi = _mm_unpackhi_epi64(sum, sum);
sum = _mm_add_epi32(hi, sum); sum = _mm_add_epi32(hi, sum);
hi = _mm_shuffle_epi32(sum, 177); hi = _mm_shuffle_epi32(sum, 177);
sum = _mm_add_epi32(sum, hi); sum = _mm_add_epi32(sum, hi);
s1 += _mm_cvtsi128_si32(sum); s1 += _mm_cvtsi128_si32(sum);
v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5)); v_s2 = _mm256_add_epi32(v_s2, _mm256_slli_epi32(v_ps, 5));
@@ -177,8 +145,7 @@ fletcher32_avx2(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE; if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE;
s2 %= FLETCHER32_MODULE; s2 %= FLETCHER32_MODULE;
} }

View File

@@ -88,8 +88,12 @@ TARGET_WITH_NEON void fletcher32_neon(uint16_t *sum1, uint16_t *sum2, const uint
* processed before s2 must be reduced modulo FLETCHER32_MODULE. * processed before s2 must be reduced modulo FLETCHER32_MODULE.
*/ */
#ifdef _MSC_VER #ifdef _MSC_VER
uint32x4_t v_s2 = {.n128_u32 = {0, 0, 0, s1 * n}}; uint32x4_t v_s2 = {
uint32x4_t v_s1 = {.n128_u32 = {0, 0, 0, 0}}; .n128_u32 = {0, 0, 0, s1 * n}
};
uint32x4_t v_s1 = {
.n128_u32 = {0, 0, 0, 0}
};
#else #else
uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n}; uint32x4_t v_s2 = (uint32x4_t){0, 0, 0, s1 * n};
uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0}; uint32x4_t v_s1 = (uint32x4_t){0, 0, 0, 0};
@@ -98,8 +102,7 @@ TARGET_WITH_NEON void fletcher32_neon(uint16_t *sum1, uint16_t *sum2, const uint
uint16x8_t v_column_sum_2 = vdupq_n_u16(0); uint16x8_t v_column_sum_2 = vdupq_n_u16(0);
uint16x8_t v_column_sum_3 = vdupq_n_u16(0); uint16x8_t v_column_sum_3 = vdupq_n_u16(0);
uint16x8_t v_column_sum_4 = vdupq_n_u16(0); uint16x8_t v_column_sum_4 = vdupq_n_u16(0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -108,22 +111,21 @@ TARGET_WITH_NEON void fletcher32_neon(uint16_t *sum1, uint16_t *sum2, const uint
/* /*
* Add previous block byte sum to v_s2. * Add previous block byte sum to v_s2.
*/ */
v_s2 = vaddq_u32(v_s2, v_s1); v_s2 = vaddq_u32(v_s2, v_s1);
/* /*
* Horizontally add the bytes for s1. * Horizontally add the bytes for s1.
*/ */
v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2)); v_s1 = vpadalq_u16(v_s1, vpadalq_u8(vpaddlq_u8(bytes1), bytes2));
/* /*
* Vertically add the bytes for s2. * Vertically add the bytes for s2.
*/ */
v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1)); v_column_sum_1 = vaddw_u8(v_column_sum_1, vget_low_u8(bytes1));
v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1)); v_column_sum_2 = vaddw_u8(v_column_sum_2, vget_high_u8(bytes1));
v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2)); v_column_sum_3 = vaddw_u8(v_column_sum_3, vget_low_u8(bytes2));
v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2)); v_column_sum_4 = vaddw_u8(v_column_sum_4, vget_high_u8(bytes2));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = vshlq_n_u32(v_s2, 5);
v_s2 = vshlq_n_u32(v_s2, 5);
/* /*
* Multiply-add bytes by [ 32, 31, 30, ... ] for s2. * Multiply-add bytes by [ 32, 31, 30, ... ] for s2.
*/ */
@@ -198,8 +200,7 @@ TARGET_WITH_NEON void fletcher32_neon(uint16_t *sum1, uint16_t *sum2, const uint
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE; if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE;
s2 %= FLETCHER32_MODULE; s2 %= FLETCHER32_MODULE;
} }

View File

@@ -49,8 +49,8 @@
* @param data Pointer to the data buffer. * @param data Pointer to the data buffer.
* @param len Length of the data buffer in bytes. * @param len Length of the data buffer in bytes.
*/ */
AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL AARU_EXPORT TARGET_WITH_SSSE3 void AARU_CALL fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data,
fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len) long len)
{ {
uint32_t s1 = *sum1; uint32_t s1 = *sum1;
uint32_t s2 = *sum2; uint32_t s2 = *sum2;
@@ -79,8 +79,7 @@ fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
__m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n); __m128i v_ps = _mm_set_epi32(0, 0, 0, s1 * n);
__m128i v_s2 = _mm_set_epi32(0, 0, 0, s2); __m128i v_s2 = _mm_set_epi32(0, 0, 0, s2);
__m128i v_s1 = _mm_set_epi32(0, 0, 0, 0); __m128i v_s1 = _mm_set_epi32(0, 0, 0, 0);
do do {
{
/* /*
* Load 32 input bytes. * Load 32 input bytes.
*/ */
@@ -89,21 +88,20 @@ fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
/* /*
* Add previous block byte sum to v_ps. * Add previous block byte sum to v_ps.
*/ */
v_ps = _mm_add_epi32(v_ps, v_s1); v_ps = _mm_add_epi32(v_ps, v_s1);
/* /*
* Horizontally add the bytes for s1, multiply-adds the * Horizontally add the bytes for s1, multiply-adds the
* bytes by [ 32, 31, 30, ... ] for s2. * bytes by [ 32, 31, 30, ... ] for s2.
*/ */
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes1, zero));
const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1); const __m128i mad1 = _mm_maddubs_epi16(bytes1, tap1);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad1, ones));
v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero)); v_s1 = _mm_add_epi32(v_s1, _mm_sad_epu8(bytes2, zero));
const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2); const __m128i mad2 = _mm_maddubs_epi16(bytes2, tap2);
v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones)); v_s2 = _mm_add_epi32(v_s2, _mm_madd_epi16(mad2, ones));
data += BLOCK_SIZE; data += BLOCK_SIZE;
} } while(--n);
while(--n); v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
v_s2 = _mm_add_epi32(v_s2, _mm_slli_epi32(v_ps, 5));
/* /*
* Sum epi32 ints v_s1(s2) and accumulate in s1(s2). * Sum epi32 ints v_s1(s2) and accumulate in s1(s2).
*/ */
@@ -150,8 +148,7 @@ fletcher32_ssse3(uint16_t *sum1, uint16_t *sum2, const uint8_t *data, long len)
s2 += (s1 += *data++); s2 += (s1 += *data++);
len -= 16; len -= 16;
} }
while(len--) while(len--) { s2 += (s1 += *data++); }
{ s2 += (s1 += *data++); }
if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE; if(s1 >= FLETCHER32_MODULE) s1 -= FLETCHER32_MODULE;
s2 %= FLETCHER32_MODULE; s2 %= FLETCHER32_MODULE;
} }

View File

@@ -20,5 +20,4 @@
#include "library.h" #include "library.h"
AARU_EXPORT uint64_t AARU_CALL get_acn_version() AARU_EXPORT uint64_t AARU_CALL get_acn_version() { return AARU_CHECKUMS_NATIVE_VERSION; }
{ return AARU_CHECKUMS_NATIVE_VERSION; }

View File

@@ -26,7 +26,7 @@
#endif #endif
#if defined(_WIN32) #if defined(_WIN32)
#define AARU_CALL __stdcall #define AARU_CALL __stdcall
#define AARU_EXPORT EXTERNC __declspec(dllexport) #define AARU_EXPORT EXTERNC __declspec(dllexport)
#define AARU_LOCAL #define AARU_LOCAL
#ifndef PATH_MAX #ifndef PATH_MAX
@@ -36,11 +36,11 @@
#define AARU_CALL #define AARU_CALL
#if defined(__APPLE__) #if defined(__APPLE__)
#define AARU_EXPORT EXTERNC __attribute__((visibility("default"))) #define AARU_EXPORT EXTERNC __attribute__((visibility("default")))
#define AARU_LOCAL __attribute__((visibility("hidden"))) #define AARU_LOCAL __attribute__((visibility("hidden")))
#else #else
#if __GNUC__ >= 4 #if __GNUC__ >= 4
#define AARU_EXPORT EXTERNC __attribute__((visibility("default"))) #define AARU_EXPORT EXTERNC __attribute__((visibility("default")))
#define AARU_LOCAL __attribute__((visibility("hidden"))) #define AARU_LOCAL __attribute__((visibility("hidden")))
#else #else
#define AARU_EXPORT EXTERNC #define AARU_EXPORT EXTERNC
#define AARU_LOCAL #define AARU_LOCAL
@@ -60,4 +60,4 @@
AARU_EXPORT uint64_t AARU_CALL get_acn_version(); AARU_EXPORT uint64_t AARU_CALL get_acn_version();
#endif // AARU_CHECKSUMS_NATIVE_LIBRARY_H #endif // AARU_CHECKSUMS_NATIVE_LIBRARY_H

9
simd.c
View File

@@ -56,7 +56,7 @@
* *
* @return None. * @return None.
*/ */
static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) static void cpuid(int info, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
unsigned int registers[4]; unsigned int registers[4];
@@ -99,7 +99,7 @@ static void cpuid(int info, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigne
* *
* @return None. * @return None.
*/ */
static void cpuidex(int info, int count, unsigned* eax, unsigned* ebx, unsigned* ecx, unsigned* edx) static void cpuidex(int info, int count, unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx)
{ {
#ifdef _MSC_VER #ifdef _MSC_VER
unsigned int registers[4]; unsigned int registers[4];
@@ -264,8 +264,7 @@ int have_crc32_apple()
* *
* @return true if the current processor supports cryptographic instructions, false otherwise. * @return true if the current processor supports cryptographic instructions, false otherwise.
*/ */
int have_crypto_apple() int have_crypto_apple() { return 0; }
{ return 0; }
#endif #endif
@@ -273,7 +272,7 @@ int have_crypto_apple()
int have_neon(void) int have_neon(void)
{ {
return 1; // ARMv8-A made it mandatory return 1; // ARMv8-A made it mandatory
} }
/** /**

24
simd.h
View File

@@ -33,7 +33,7 @@
#define TARGET_WITH_SSSE3 #define TARGET_WITH_SSSE3
#define TARGET_WITH_CLMUL #define TARGET_WITH_CLMUL
#else #else
#define TARGET_WITH_AVX2 __attribute__((target("avx2"))) #define TARGET_WITH_AVX2 __attribute__((target("avx2")))
#define TARGET_WITH_SSSE3 __attribute__((target("ssse3"))) #define TARGET_WITH_SSSE3 __attribute__((target("ssse3")))
#define TARGET_WITH_CLMUL __attribute__((target("pclmul,sse4.1"))) #define TARGET_WITH_CLMUL __attribute__((target("pclmul,sse4.1")))
#endif #endif
@@ -44,14 +44,14 @@ AARU_EXPORT int have_avx2(void);
#endif #endif
#if(defined(__arm__) || defined(_M_ARM)) && !defined(_WIN32) #if(defined(__arm__) || defined(_M_ARM)) && !defined(_WIN32)
#define HWCAP_NEON (1 << 12) #define HWCAP_NEON (1 << 12)
#define HWCAP2_AES (1 << 0) #define HWCAP2_AES (1 << 0)
#define HWCAP2_CRC32 (1 << 4) #define HWCAP2_CRC32 (1 << 4)
#endif #endif
#if(defined(__aarch64__) || defined(_M_ARM64)) && !defined(_WIN32) #if(defined(__aarch64__) || defined(_M_ARM64)) && !defined(_WIN32)
#define HWCAP_NEON (1 << 1) #define HWCAP_NEON (1 << 1)
#define HWCAP_AES (1 << 3) #define HWCAP_AES (1 << 3)
#define HWCAP_CRC32 (1 << 7) #define HWCAP_CRC32 (1 << 7)
#endif #endif
@@ -73,7 +73,7 @@ AARU_EXPORT int have_arm_crypto(void);
#define TARGET_WITH_CRYPTO #define TARGET_WITH_CRYPTO
#define TARGET_WITH_NEON #define TARGET_WITH_NEON
#else // _MSC_VER #else // _MSC_VER
#if defined(__aarch64__) || defined(_M_ARM64) #if defined(__aarch64__) || defined(_M_ARM64)
@@ -92,7 +92,7 @@ AARU_EXPORT int have_arm_crypto(void);
#define TARGET_WITH_NEON #define TARGET_WITH_NEON
#else #else
#if (__ARM_ARCH >= 7 || defined (__ARM_ARCH_8A)) #if(__ARM_ARCH >= 7 || defined(__ARM_ARCH_8A))
#ifdef __clang__ #ifdef __clang__
#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc"))) #define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc")))
@@ -100,7 +100,7 @@ AARU_EXPORT int have_arm_crypto(void);
#define TARGET_ARMV8_WITH_CRC __attribute__((target("arch=armv8-a+crc"))) #define TARGET_ARMV8_WITH_CRC __attribute__((target("arch=armv8-a+crc")))
#endif #endif
#endif // __ARM_ARCH_7A__ #endif // __ARM_ARCH_7A__
#ifdef __clang__ #ifdef __clang__
#define TARGET_WITH_CRYPTO __attribute__((target("armv8-a,crypto"))) #define TARGET_WITH_CRYPTO __attribute__((target("armv8-a,crypto")))
@@ -114,10 +114,10 @@ AARU_EXPORT int have_arm_crypto(void);
#define TARGET_WITH_NEON __attribute__((target("fpu=neon"))) #define TARGET_WITH_NEON __attribute__((target("fpu=neon")))
#endif #endif
#endif // __aarch64__ || _M_ARM64 #endif // __aarch64__ || _M_ARM64
#endif // _MSC_VER #endif // _MSC_VER
#endif // __aarch64__ || _M_ARM64 || __arm__ || _M_ARM #endif // __aarch64__ || _M_ARM64 || __arm__ || _M_ARM
#endif // AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H #endif // AARU_CHECKSUMS_NATIVE_CRC32_SIMD_H

View File

@@ -92,8 +92,8 @@ AARU_EXPORT void AARU_CALL spamsum_free(spamsum_ctx *ctx)
if(ctx) free(ctx); if(ctx) free(ctx);
} }
#define ROLL_SUM(ctx) ((ctx)->roll.h1 + (ctx)->roll.h2 + (ctx)->roll.h3) #define ROLL_SUM(ctx) ((ctx)->roll.h1 + (ctx)->roll.h2 + (ctx)->roll.h3)
#define SUM_HASH(c, h) (((h)*HASH_PRIME) ^ (c)); #define SUM_HASH(c, h) (((h) * HASH_PRIME) ^ (c));
#define SSDEEP_BS(index) (MIN_BLOCKSIZE << (index)) #define SSDEEP_BS(index) (MIN_BLOCKSIZE << (index))
FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c) FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c)
@@ -107,7 +107,7 @@ FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c)
for(i = ctx->bh_start; i < ctx->bh_end; ++i) for(i = ctx->bh_start; i < ctx->bh_end; ++i)
{ {
ctx->bh[i].h = SUM_HASH(c, ctx->bh[i].h); ctx->bh[i].h = SUM_HASH(c, ctx->bh[i].h);
ctx->bh[i].half_h = SUM_HASH(c, ctx->bh[i].half_h); ctx->bh[i].half_h = SUM_HASH(c, ctx->bh[i].half_h);
} }
@@ -126,7 +126,7 @@ FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c)
if(0 == ctx->bh[i].d_len) fuzzy_try_fork_blockhash(ctx); if(0 == ctx->bh[i].d_len) fuzzy_try_fork_blockhash(ctx);
ctx->bh[i].digest[ctx->bh[i].d_len] = b64[ctx->bh[i].h % 64]; ctx->bh[i].digest[ctx->bh[i].d_len] = b64[ctx->bh[i].h % 64];
ctx->bh[i].half_digest = b64[ctx->bh[i].half_h % 64]; ctx->bh[i].half_digest = b64[ctx->bh[i].half_h % 64];
if(ctx->bh[i].d_len < SPAMSUM_LENGTH - 1) if(ctx->bh[i].d_len < SPAMSUM_LENGTH - 1)
{ {
@@ -137,7 +137,7 @@ FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c)
* last few pieces of the message into a single piece * last few pieces of the message into a single piece
* */ * */
ctx->bh[i].digest[++ctx->bh[i].d_len] = 0; ctx->bh[i].digest[++ctx->bh[i].d_len] = 0;
ctx->bh[i].h = HASH_INIT; ctx->bh[i].h = HASH_INIT;
if(ctx->bh[i].d_len >= SPAMSUM_LENGTH / 2) continue; if(ctx->bh[i].d_len >= SPAMSUM_LENGTH / 2) continue;
@@ -193,11 +193,11 @@ FORCE_INLINE void fuzzy_try_fork_blockhash(spamsum_ctx *ctx)
// assert(ctx->bh_end != 0); // assert(ctx->bh_end != 0);
uint32_t obh = ctx->bh_end - 1; uint32_t obh = ctx->bh_end - 1;
uint32_t nbh = ctx->bh_end; uint32_t nbh = ctx->bh_end;
ctx->bh[nbh].h = ctx->bh[obh].h; ctx->bh[nbh].h = ctx->bh[obh].h;
ctx->bh[nbh].half_h = ctx->bh[obh].half_h; ctx->bh[nbh].half_h = ctx->bh[obh].half_h;
ctx->bh[nbh].digest[0] = 0; ctx->bh[nbh].digest[0] = 0;
ctx->bh[nbh].half_digest = 0; ctx->bh[nbh].half_digest = 0;
ctx->bh[nbh].d_len = 0; ctx->bh[nbh].d_len = 0;
++ctx->bh_end; ++ctx->bh_end;
@@ -297,7 +297,8 @@ AARU_EXPORT int AARU_CALL spamsum_final(spamsum_ctx *ctx, uint8_t *result)
++bi; ++bi;
i = (int)ctx->bh[bi].d_len; i = (int)ctx->bh[bi].d_len;
if(i <= remain); if(i <= remain)
;
memcpy(result, ctx->bh[bi].digest, (size_t)i); memcpy(result, ctx->bh[bi].digest, (size_t)i);
result += i; result += i;
@@ -307,7 +308,7 @@ AARU_EXPORT int AARU_CALL spamsum_final(spamsum_ctx *ctx, uint8_t *result)
{ {
// assert(remain > 0); // assert(remain > 0);
h = ctx->bh[bi].half_h; h = ctx->bh[bi].half_h;
*result = b64[h % 64]; *result = b64[h % 64];
if(i < 3 || *result != result[-1] || *result != result[-2] || *result != result[-3]) if(i < 3 || *result != result[-1] || *result != result[-2] || *result != result[-3])

View File

@@ -19,12 +19,12 @@
#ifndef AARU_CHECKSUMS_NATIVE_SPAMSUM_H #ifndef AARU_CHECKSUMS_NATIVE_SPAMSUM_H
#define AARU_CHECKSUMS_NATIVE_SPAMSUM_H #define AARU_CHECKSUMS_NATIVE_SPAMSUM_H
#define SPAMSUM_LENGTH 64 #define SPAMSUM_LENGTH 64
#define NUM_BLOCKHASHES 31 #define NUM_BLOCKHASHES 31
#define ROLLING_WINDOW 7 #define ROLLING_WINDOW 7
#define HASH_INIT 0x28021967 #define HASH_INIT 0x28021967
#define HASH_PRIME 0x01000193 #define HASH_PRIME 0x01000193
#define MIN_BLOCKSIZE 3 #define MIN_BLOCKSIZE 3
#define FUZZY_MAX_RESULT ((2 * SPAMSUM_LENGTH) + 20) #define FUZZY_MAX_RESULT ((2 * SPAMSUM_LENGTH) + 20)
typedef struct typedef struct
@@ -55,9 +55,9 @@ typedef struct
} spamsum_ctx; } spamsum_ctx;
AARU_EXPORT spamsum_ctx *AARU_CALL spamsum_init(void); AARU_EXPORT spamsum_ctx *AARU_CALL spamsum_init(void);
AARU_EXPORT int AARU_CALL spamsum_update(spamsum_ctx *ctx, const uint8_t *data, uint32_t len); AARU_EXPORT int AARU_CALL spamsum_update(spamsum_ctx *ctx, const uint8_t *data, uint32_t len);
AARU_EXPORT int AARU_CALL spamsum_final(spamsum_ctx *ctx, uint8_t *result); AARU_EXPORT int AARU_CALL spamsum_final(spamsum_ctx *ctx, uint8_t *result);
AARU_EXPORT void AARU_CALL spamsum_free(spamsum_ctx *ctx); AARU_EXPORT void AARU_CALL spamsum_free(spamsum_ctx *ctx);
FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c); FORCE_INLINE void fuzzy_engine_step(spamsum_ctx *ctx, uint8_t c);
@@ -67,4 +67,4 @@ FORCE_INLINE void fuzzy_try_reduce_blockhash(spamsum_ctx *ctx);
FORCE_INLINE void fuzzy_try_fork_blockhash(spamsum_ctx *ctx); FORCE_INLINE void fuzzy_try_fork_blockhash(spamsum_ctx *ctx);
#endif // AARU_CHECKSUMS_NATIVE_SPAMSUM_H #endif // AARU_CHECKSUMS_NATIVE_SPAMSUM_H

View File

@@ -1,6 +1,6 @@
if("${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW" OR "${AARU_BUILD_PACKAGE}" MATCHES 1) if ("${CMAKE_C_PLATFORM_ID}" MATCHES "MinGW" OR "${AARU_BUILD_PACKAGE}" MATCHES 1)
return() return()
endif() endif ()
# 'Google_test' is the subproject name # 'Google_test' is the subproject name
project(tests) project(tests)
@@ -10,7 +10,7 @@ add_subdirectory(lib)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/random file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/data/random
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/) DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/data/)
# 'Google_Tests_run' is the target name # 'Google_Tests_run' is the target name
# 'test1.cpp tests2.cpp' are source files with tests # 'test1.cpp tests2.cpp' are source files with tests

View File

@@ -10,10 +10,10 @@
#include "../adler32.h" #include "../adler32.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_ADLER32 0x3728d186 #define EXPECTED_ADLER32 0x3728d186
#define EXPECTED_ADLER32_15BYTES 0x34DC067D #define EXPECTED_ADLER32_15BYTES 0x34DC067D
#define EXPECTED_ADLER32_31BYTES 0xD8F10EAA #define EXPECTED_ADLER32_31BYTES 0xD8F10EAA
#define EXPECTED_ADLER32_63BYTES 0xD8AC2081 #define EXPECTED_ADLER32_63BYTES 0xD8AC2081
#define EXPECTED_ADLER32_2352BYTES 0xECD1738B #define EXPECTED_ADLER32_2352BYTES 0xECD1738B
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(adler32Fixture, adler32_auto) TEST_F(adler32Fixture, adler32_auto)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -92,7 +92,7 @@ TEST_F(adler32Fixture, adler32_slicing)
TEST_F(adler32Fixture, adler32_auto_misaligned) TEST_F(adler32Fixture, adler32_auto_misaligned)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -121,7 +121,7 @@ TEST_F(adler32Fixture, adler32_slicing_misaligned)
TEST_F(adler32Fixture, adler32_auto_15bytes) TEST_F(adler32Fixture, adler32_auto_15bytes)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -150,7 +150,7 @@ TEST_F(adler32Fixture, adler32_slicing_15bytes)
TEST_F(adler32Fixture, adler32_auto_31bytes) TEST_F(adler32Fixture, adler32_auto_31bytes)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -179,7 +179,7 @@ TEST_F(adler32Fixture, adler32_slicing_31bytes)
TEST_F(adler32Fixture, adler32_auto_63bytes) TEST_F(adler32Fixture, adler32_auto_63bytes)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -208,7 +208,7 @@ TEST_F(adler32Fixture, adler32_slicing_63bytes)
TEST_F(adler32Fixture, adler32_auto_2352bytes) TEST_F(adler32Fixture, adler32_auto_2352bytes)
{ {
adler32_ctx *ctx = adler32_init(); adler32_ctx *ctx = adler32_init();
uint32_t adler32; uint32_t adler32;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,10 +10,10 @@
#include "../crc16.h" #include "../crc16.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_CRC16 0x2d6d #define EXPECTED_CRC16 0x2d6d
#define EXPECTED_CRC16_15BYTES 0x72a6 #define EXPECTED_CRC16_15BYTES 0x72a6
#define EXPECTED_CRC16_31BYTES 0xF49E #define EXPECTED_CRC16_31BYTES 0xF49E
#define EXPECTED_CRC16_63BYTES 0xFBD9 #define EXPECTED_CRC16_63BYTES 0xFBD9
#define EXPECTED_CRC16_2352BYTES 0x23F4 #define EXPECTED_CRC16_2352BYTES 0x23F4
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(crc16Fixture, crc16_auto) TEST_F(crc16Fixture, crc16_auto)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -76,7 +76,7 @@ TEST_F(crc16Fixture, crc16_auto)
TEST_F(crc16Fixture, crc16_auto_misaligned) TEST_F(crc16Fixture, crc16_auto_misaligned)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -89,7 +89,7 @@ TEST_F(crc16Fixture, crc16_auto_misaligned)
TEST_F(crc16Fixture, crc16_auto_15bytes) TEST_F(crc16Fixture, crc16_auto_15bytes)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -102,7 +102,7 @@ TEST_F(crc16Fixture, crc16_auto_15bytes)
TEST_F(crc16Fixture, crc16_auto_31bytes) TEST_F(crc16Fixture, crc16_auto_31bytes)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -115,7 +115,7 @@ TEST_F(crc16Fixture, crc16_auto_31bytes)
TEST_F(crc16Fixture, crc16_auto_63bytes) TEST_F(crc16Fixture, crc16_auto_63bytes)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -128,7 +128,7 @@ TEST_F(crc16Fixture, crc16_auto_63bytes)
TEST_F(crc16Fixture, crc16_auto_2352bytes) TEST_F(crc16Fixture, crc16_auto_2352bytes)
{ {
crc16_ctx *ctx = crc16_init(); crc16_ctx *ctx = crc16_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,10 +10,10 @@
#include "../crc16_ccitt.h" #include "../crc16_ccitt.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_CRC16_CCITT 0x3640 #define EXPECTED_CRC16_CCITT 0x3640
#define EXPECTED_CRC16_CCITT_15BYTES 0x166e #define EXPECTED_CRC16_CCITT_15BYTES 0x166e
#define EXPECTED_CRC16_CCITT_31BYTES 0xd016 #define EXPECTED_CRC16_CCITT_31BYTES 0xd016
#define EXPECTED_CRC16_CCITT_63BYTES 0x73c4 #define EXPECTED_CRC16_CCITT_63BYTES 0x73c4
#define EXPECTED_CRC16_CCITT_2352BYTES 0x1946 #define EXPECTED_CRC16_CCITT_2352BYTES 0x1946
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(crc16_ccittFixture, crc16_ccitt_auto) TEST_F(crc16_ccittFixture, crc16_ccitt_auto)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -76,7 +76,7 @@ TEST_F(crc16_ccittFixture, crc16_ccitt_auto)
TEST_F(crc16_ccittFixture, crc16_ccitt_auto_misaligned) TEST_F(crc16_ccittFixture, crc16_ccitt_auto_misaligned)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -89,7 +89,7 @@ TEST_F(crc16_ccittFixture, crc16_ccitt_auto_misaligned)
TEST_F(crc16_ccittFixture, crc16_ccitt_auto_15bytes) TEST_F(crc16_ccittFixture, crc16_ccitt_auto_15bytes)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -102,7 +102,7 @@ TEST_F(crc16_ccittFixture, crc16_ccitt_auto_15bytes)
TEST_F(crc16_ccittFixture, crc16_ccitt_auto_31bytes) TEST_F(crc16_ccittFixture, crc16_ccitt_auto_31bytes)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -115,7 +115,7 @@ TEST_F(crc16_ccittFixture, crc16_ccitt_auto_31bytes)
TEST_F(crc16_ccittFixture, crc16_ccitt_auto_63bytes) TEST_F(crc16_ccittFixture, crc16_ccitt_auto_63bytes)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -128,7 +128,7 @@ TEST_F(crc16_ccittFixture, crc16_ccitt_auto_63bytes)
TEST_F(crc16_ccittFixture, crc16_ccitt_auto_2352bytes) TEST_F(crc16_ccittFixture, crc16_ccitt_auto_2352bytes)
{ {
crc16_ccitt_ctx *ctx = crc16_ccitt_init(); crc16_ccitt_ctx *ctx = crc16_ccitt_init();
uint16_t crc; uint16_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,10 +10,10 @@
#include "../crc32.h" #include "../crc32.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_CRC32 0x2B6E6854 #define EXPECTED_CRC32 0x2B6E6854
#define EXPECTED_CRC32_15BYTES 0xad6da727 #define EXPECTED_CRC32_15BYTES 0xad6da727
#define EXPECTED_CRC32_31BYTES 0xa2ad2faa #define EXPECTED_CRC32_31BYTES 0xa2ad2faa
#define EXPECTED_CRC32_63BYTES 0xbff6a341 #define EXPECTED_CRC32_63BYTES 0xbff6a341
#define EXPECTED_CRC32_2352BYTES 0x08ba93ea #define EXPECTED_CRC32_2352BYTES 0x08ba93ea
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(crc32Fixture, crc32_auto) TEST_F(crc32Fixture, crc32_auto)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -87,7 +87,7 @@ TEST_F(crc32Fixture, crc32_slicing)
TEST_F(crc32Fixture, crc32_auto_misaligned) TEST_F(crc32Fixture, crc32_auto_misaligned)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -111,7 +111,7 @@ TEST_F(crc32Fixture, crc32_slicing_misaligned)
TEST_F(crc32Fixture, crc32_auto_15bytes) TEST_F(crc32Fixture, crc32_auto_15bytes)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -135,7 +135,7 @@ TEST_F(crc32Fixture, crc32_slicing_15bytes)
TEST_F(crc32Fixture, crc32_auto_31bytes) TEST_F(crc32Fixture, crc32_auto_31bytes)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -159,7 +159,7 @@ TEST_F(crc32Fixture, crc32_slicing_31bytes)
TEST_F(crc32Fixture, crc32_auto_63bytes) TEST_F(crc32Fixture, crc32_auto_63bytes)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -183,7 +183,7 @@ TEST_F(crc32Fixture, crc32_slicing_63bytes)
TEST_F(crc32Fixture, crc32_auto_2352bytes) TEST_F(crc32Fixture, crc32_auto_2352bytes)
{ {
crc32_ctx *ctx = crc32_init(); crc32_ctx *ctx = crc32_init();
uint32_t crc; uint32_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,10 +10,10 @@
#include "../crc64.h" #include "../crc64.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_CRC64 0xbf09992cc5ede38e #define EXPECTED_CRC64 0xbf09992cc5ede38e
#define EXPECTED_CRC64_15BYTES 0x797F3766FD93975B #define EXPECTED_CRC64_15BYTES 0x797F3766FD93975B
#define EXPECTED_CRC64_31BYTES 0xCD9201905A7937FD #define EXPECTED_CRC64_31BYTES 0xCD9201905A7937FD
#define EXPECTED_CRC64_63BYTES 0x29F331FC90702BF4 #define EXPECTED_CRC64_63BYTES 0x29F331FC90702BF4
#define EXPECTED_CRC64_2352BYTES 0x126435DB43477623 #define EXPECTED_CRC64_2352BYTES 0x126435DB43477623
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(crc64Fixture, crc64_auto) TEST_F(crc64Fixture, crc64_auto)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -87,7 +87,7 @@ TEST_F(crc64Fixture, crc64_slicing)
TEST_F(crc64Fixture, crc64_auto_misaligned) TEST_F(crc64Fixture, crc64_auto_misaligned)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -111,7 +111,7 @@ TEST_F(crc64Fixture, crc64_slicing_misaligned)
TEST_F(crc64Fixture, crc64_auto_15bytes) TEST_F(crc64Fixture, crc64_auto_15bytes)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -135,7 +135,7 @@ TEST_F(crc64Fixture, crc64_slicing_15bytes)
TEST_F(crc64Fixture, crc64_auto_31bytes) TEST_F(crc64Fixture, crc64_auto_31bytes)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -159,7 +159,7 @@ TEST_F(crc64Fixture, crc64_slicing_31bytes)
TEST_F(crc64Fixture, crc64_auto_63bytes) TEST_F(crc64Fixture, crc64_auto_63bytes)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -183,7 +183,7 @@ TEST_F(crc64Fixture, crc64_slicing_63bytes)
TEST_F(crc64Fixture, crc64_auto_2352bytes) TEST_F(crc64Fixture, crc64_auto_2352bytes)
{ {
crc64_ctx *ctx = crc64_init(); crc64_ctx *ctx = crc64_init();
uint64_t crc; uint64_t crc;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,13 +10,13 @@
#include "../fletcher16.h" #include "../fletcher16.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_FLETCHER16 0x3357 #define EXPECTED_FLETCHER16 0x3357
#define EXPECTED_FLETCHER16_1BYTE 0xAFAF #define EXPECTED_FLETCHER16_1BYTE 0xAFAF
#define EXPECTED_FLETCHER16_5BYTES 0x1F16 #define EXPECTED_FLETCHER16_5BYTES 0x1F16
#define EXPECTED_FLETCHER16_7BYTES 0x865B #define EXPECTED_FLETCHER16_7BYTES 0x865B
#define EXPECTED_FLETCHER16_15BYTES 0x0282 #define EXPECTED_FLETCHER16_15BYTES 0x0282
#define EXPECTED_FLETCHER16_31BYTES 0xABB7 #define EXPECTED_FLETCHER16_31BYTES 0xABB7
#define EXPECTED_FLETCHER16_63BYTES 0x1CA0 #define EXPECTED_FLETCHER16_63BYTES 0x1CA0
#define EXPECTED_FLETCHER16_2352BYTES 0x0AC5 #define EXPECTED_FLETCHER16_2352BYTES 0x0AC5
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -41,7 +41,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -66,7 +66,7 @@ protected:
TEST_F(fletcher16Fixture, fletcher16_auto) TEST_F(fletcher16Fixture, fletcher16_auto)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -79,7 +79,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto)
TEST_F(fletcher16Fixture, fletcher16_auto_misaligned) TEST_F(fletcher16Fixture, fletcher16_auto_misaligned)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -91,7 +91,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_misaligned)
TEST_F(fletcher16Fixture, fletcher16_auto_1byte) TEST_F(fletcher16Fixture, fletcher16_auto_1byte)
{ {
fletcher16_ctx* ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -104,7 +104,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_1byte)
TEST_F(fletcher16Fixture, fletcher16_auto_5bytes) TEST_F(fletcher16Fixture, fletcher16_auto_5bytes)
{ {
fletcher16_ctx* ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -117,7 +117,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_5bytes)
TEST_F(fletcher16Fixture, fletcher16_auto_7bytes) TEST_F(fletcher16Fixture, fletcher16_auto_7bytes)
{ {
fletcher16_ctx* ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -131,7 +131,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_7bytes)
TEST_F(fletcher16Fixture, fletcher16_auto_15bytes) TEST_F(fletcher16Fixture, fletcher16_auto_15bytes)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -144,7 +144,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_15bytes)
TEST_F(fletcher16Fixture, fletcher16_auto_31bytes) TEST_F(fletcher16Fixture, fletcher16_auto_31bytes)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -157,7 +157,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_31bytes)
TEST_F(fletcher16Fixture, fletcher16_auto_63bytes) TEST_F(fletcher16Fixture, fletcher16_auto_63bytes)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -170,7 +170,7 @@ TEST_F(fletcher16Fixture, fletcher16_auto_63bytes)
TEST_F(fletcher16Fixture, fletcher16_auto_2352bytes) TEST_F(fletcher16Fixture, fletcher16_auto_2352bytes)
{ {
fletcher16_ctx *ctx = fletcher16_init(); fletcher16_ctx *ctx = fletcher16_init();
uint16_t fletcher; uint16_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -185,8 +185,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -203,8 +203,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon_misaligned)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -257,8 +257,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon_15bytes)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -275,8 +275,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon_31bytes)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -293,8 +293,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon_63bytes)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -311,8 +311,8 @@ TEST_F(fletcher16Fixture, fletcher16_neon_2352bytes)
{ {
if(!have_neon()) return; if(!have_neon()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -326,7 +326,7 @@ TEST_F(fletcher16Fixture, fletcher16_neon_2352bytes)
} }
#endif #endif
#if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \ #if defined(__x86_64__) || defined(__amd64) || defined(_M_AMD64) || defined(_M_X64) || defined(__I386__) || \
defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86) defined(__i386__) || defined(__THW_INTEL) || defined(_M_IX86)
TEST_F(fletcher16Fixture, fletcher16_avx2) TEST_F(fletcher16Fixture, fletcher16_avx2)
@@ -351,8 +351,8 @@ TEST_F(fletcher16Fixture, fletcher16_ssse3)
{ {
if(!have_ssse3()) return; if(!have_ssse3()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -477,8 +477,8 @@ TEST_F(fletcher16Fixture, fletcher16_avx2_15bytes)
{ {
if(!have_avx2()) return; if(!have_avx2()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -513,8 +513,8 @@ TEST_F(fletcher16Fixture, fletcher16_avx2_31bytes)
{ {
if(!have_avx2()) return; if(!have_avx2()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -549,8 +549,8 @@ TEST_F(fletcher16Fixture, fletcher16_avx2_63bytes)
{ {
if(!have_avx2()) return; if(!have_avx2()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;
@@ -585,8 +585,8 @@ TEST_F(fletcher16Fixture, fletcher16_avx2_2352bytes)
{ {
if(!have_avx2()) return; if(!have_avx2()) return;
uint8_t sum1; uint8_t sum1;
uint8_t sum2; uint8_t sum2;
uint32_t fletcher16; uint32_t fletcher16;
sum1 = 0xFF; sum1 = 0xFF;

View File

@@ -10,10 +10,10 @@
#include "../fletcher32.h" #include "../fletcher32.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_FLETCHER32 0x211261f5 #define EXPECTED_FLETCHER32 0x211261f5
#define EXPECTED_FLETCHER32_15BYTES 0x34CD067C #define EXPECTED_FLETCHER32_15BYTES 0x34CD067C
#define EXPECTED_FLETCHER32_31BYTES 0xD8D20EA9 #define EXPECTED_FLETCHER32_31BYTES 0xD8D20EA9
#define EXPECTED_FLETCHER32_63BYTES 0xD8432080 #define EXPECTED_FLETCHER32_63BYTES 0xD8432080
#define EXPECTED_FLETCHER32_2352BYTES 0xCB3E7352 #define EXPECTED_FLETCHER32_2352BYTES 0xCB3E7352
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);
@@ -63,7 +63,7 @@ protected:
TEST_F(fletcher32Fixture, fletcher32_auto) TEST_F(fletcher32Fixture, fletcher32_auto)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -76,7 +76,7 @@ TEST_F(fletcher32Fixture, fletcher32_auto)
TEST_F(fletcher32Fixture, fletcher32_auto_misaligned) TEST_F(fletcher32Fixture, fletcher32_auto_misaligned)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -89,7 +89,7 @@ TEST_F(fletcher32Fixture, fletcher32_auto_misaligned)
TEST_F(fletcher32Fixture, fletcher32_auto_15bytes) TEST_F(fletcher32Fixture, fletcher32_auto_15bytes)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -102,7 +102,7 @@ TEST_F(fletcher32Fixture, fletcher32_auto_15bytes)
TEST_F(fletcher32Fixture, fletcher32_auto_31bytes) TEST_F(fletcher32Fixture, fletcher32_auto_31bytes)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -115,7 +115,7 @@ TEST_F(fletcher32Fixture, fletcher32_auto_31bytes)
TEST_F(fletcher32Fixture, fletcher32_auto_63bytes) TEST_F(fletcher32Fixture, fletcher32_auto_63bytes)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);
@@ -128,7 +128,7 @@ TEST_F(fletcher32Fixture, fletcher32_auto_63bytes)
TEST_F(fletcher32Fixture, fletcher32_auto_2352bytes) TEST_F(fletcher32Fixture, fletcher32_auto_2352bytes)
{ {
fletcher32_ctx *ctx = fletcher32_init(); fletcher32_ctx *ctx = fletcher32_init();
uint32_t fletcher; uint32_t fletcher;
EXPECT_NE(ctx, nullptr); EXPECT_NE(ctx, nullptr);

View File

@@ -10,10 +10,10 @@
#include "../spamsum.h" #include "../spamsum.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#define EXPECTED_SPAMSUM "24576:3dvzuAsHTQ16pc7O1Q/gS9qze+Swwn9s6IX:8/TQQpaVqze+JN6IX" #define EXPECTED_SPAMSUM "24576:3dvzuAsHTQ16pc7O1Q/gS9qze+Swwn9s6IX:8/TQQpaVqze+JN6IX"
#define EXPECTED_SPAMSUM_15BYTES "3:Ac4E9t:Ac4E9t" #define EXPECTED_SPAMSUM_15BYTES "3:Ac4E9t:Ac4E9t"
#define EXPECTED_SPAMSUM_31BYTES "3:Ac4E9E5+S09qn:Ac4E9EgSsq" #define EXPECTED_SPAMSUM_31BYTES "3:Ac4E9E5+S09qn:Ac4E9EgSsq"
#define EXPECTED_SPAMSUM_63BYTES "3:Ac4E9E5+S09q2kABV9:Ac4E9EgSs7kW9" #define EXPECTED_SPAMSUM_63BYTES "3:Ac4E9E5+S09q2kABV9:Ac4E9EgSs7kW9"
#define EXPECTED_SPAMSUM_2352BYTES "48:pasCLoANDXmjCz1p2OpPm+Gek3xmZfJJ5DD4BacmmlodQMQa/58Z:csK1Nxz7XFGeJS/flHMQu2Z" #define EXPECTED_SPAMSUM_2352BYTES "48:pasCLoANDXmjCz1p2OpPm+Gek3xmZfJJ5DD4BacmmlodQMQa/58Z:csK1Nxz7XFGeJS/flHMQu2Z"
static const uint8_t *buffer; static const uint8_t *buffer;
@@ -38,7 +38,7 @@ protected:
snprintf(filename, PATH_MAX, "%s/data/random", path); snprintf(filename, PATH_MAX, "%s/data/random", path);
FILE *file = fopen(filename, "rb"); FILE *file = fopen(filename, "rb");
buffer = (const uint8_t *)malloc(1048576); buffer = (const uint8_t *)malloc(1048576);
fread((void *)buffer, 1, 1048576, file); fread((void *)buffer, 1, 1048576, file);
fclose(file); fclose(file);