From 4d17d9eabdad043382ecd36099593c6eaa604be8 Mon Sep 17 00:00:00 2001 From: DmitriyMusatkin Date: Fri, 4 Oct 2024 19:04:34 -0700 Subject: [PATCH] add big endian support --- .github/workflows/ci.yml | 21 ++ source/crc64_sw.c | 607 ++++++++++++++++++++++++++++++++++++++- source/crc_sw.c | 29 +- tests/crc64_test.c | 32 ++- 4 files changed, 660 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b52e93..3e6215d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -243,6 +243,27 @@ jobs: chmod a+x builder ./builder build -p ${{ env.PACKAGE_NAME }} + s390x: #big-endian + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - uses: uraimo/run-on-arch-action@v2 + name: Run commands + id: runcmd + with: + arch: s390x + distro: ubuntu_latest + install: | + apt-get update -q -y + apt-get -y install cmake + apt-get -y install make + apt-get -y install g++ + run: | + lscpu | grep Endian + python3 -c "from urllib.request import urlretrieve; urlretrieve('${{ env.BUILDER_HOST }}/${{ env.BUILDER_SOURCE }}/${{ env.BUILDER_VERSION }}/builder.pyz?run=${{ env.RUN }}', 'builder')" + chmod a+x builder + ./builder build -p ${{ env.PACKAGE_NAME }} + openbsd: runs-on: ubuntu-24.04 # latest strategy: diff --git a/source/crc64_sw.c b/source/crc64_sw.c index 59123b3..14e8515 100644 --- a/source/crc64_sw.c +++ b/source/crc64_sw.c @@ -6,8 +6,11 @@ #include #include -// CRC64NVME slice-by-8 lookup table (bit-reflected poly 0x9a6c9329ac4bc9b5) -static uint64_t crc64nvme_table[8][256] = { +#include + +/* CRC64NVME slice-by-8 lookup table (bit-reflected poly 0x9a6c9329ac4bc9b5) */ +/* little endian variant */ +static uint64_t crc64nvme_table_le[8][256] = { // { 0x0000000000000000, 0x7f6ef0c830358979, 0xfedde190606b12f2, 0x81b31158505e9b8b, // [0][0x00] @@ -538,6 +541,582 @@ static uint64_t crc64nvme_table[8][256] = { 0x2957aa85e69b6abf, 0x08bedc9bc3bd4b13, 0x6a8546b9acd729e7, 0x4b6c30a789f1084b // [7][0xfc] }}; +/* big endian variant */ +static uint64_t crc64nvme_table_be[8][256] = { +{ + 0x0000000000000000, 0x79893530c8f06e7f, 0xf2126b6090e1ddfe, 0x8b9b5e505811b381, // [0][0x00] + 0x8fb6419873e562c9, 0xf63f74a8bb150cb6, 0x7da42af8e304bf37, 0x042d1fc82bf4d148, // [0][0x04] + 0x75fe1468b4ec1ca6, 0x0c7721587c1c72d9, 0x87ec7f08240dc158, 0xfe654a38ecfdaf27, // [0][0x08] + 0xfa4855f0c7097e6f, 0x83c160c00ff91010, 0x085a3e9057e8a391, 0x71d30ba09f18cdee, // [0][0x0c] + 0x816fbe883bffe078, 0xf8e68bb8f30f8e07, 0x737dd5e8ab1e3d86, 0x0af4e0d863ee53f9, // [0][0x10] + 0x0ed9ff10481a82b1, 0x7750ca2080eaecce, 0xfccb9470d8fb5f4f, 0x8542a140100b3130, // [0][0x14] + 0xf491aae08f13fcde, 0x8d189fd047e392a1, 0x0683c1801ff22120, 0x7f0af4b0d7024f5f, // [0][0x18] + 0x7b27eb78fcf69e17, 0x02aede483406f068, 0x893580186c1743e9, 0xf0bcb528a4e72d96, // [0][0x1c] + 0x02df7c1177fec1f1, 0x7b564921bf0eaf8e, 0xf0cd1771e71f1c0f, 0x894422412fef7270, // [0][0x20] + 0x8d693d89041ba338, 0xf4e008b9ccebcd47, 0x7f7b56e994fa7ec6, 0x06f263d95c0a10b9, // [0][0x24] + 0x77216879c312dd57, 0x0ea85d490be2b328, 0x8533031953f300a9, 0xfcba36299b036ed6, // [0][0x28] + 0xf89729e1b0f7bf9e, 0x811e1cd17807d1e1, 0x0a85428120166260, 0x730c77b1e8e60c1f, // [0][0x2c] + 0x83b0c2994c012189, 0xfa39f7a984f14ff6, 0x71a2a9f9dce0fc77, 0x082b9cc914109208, // [0][0x30] + 0x0c0683013fe44340, 0x758fb631f7142d3f, 0xfe14e861af059ebe, 0x879ddd5167f5f0c1, // [0][0x34] + 0xf64ed6f1f8ed3d2f, 0x8fc7e3c1301d5350, 0x045cbd91680ce0d1, 0x7dd588a1a0fc8eae, // [0][0x38] + 0x79f897698b085fe6, 0x0071a25943f83199, 0x8beafc091be98218, 0xf263c939d319ec67, // [0][0x3c] + 0x6f2d6e7abdda5ad7, 0x16a45b4a752a34a8, 0x9d3f051a2d3b8729, 0xe4b6302ae5cbe956, // [0][0x40] + 0xe09b2fe2ce3f381e, 0x99121ad206cf5661, 0x128944825edee5e0, 0x6b0071b2962e8b9f, // [0][0x44] + 0x1ad37a1209364671, 0x635a4f22c1c6280e, 0xe8c1117299d79b8f, 0x914824425127f5f0, // [0][0x48] + 0x95653b8a7ad324b8, 0xecec0ebab2234ac7, 0x677750eaea32f946, 0x1efe65da22c29739, // [0][0x4c] + 0xee42d0f28625baaf, 0x97cbe5c24ed5d4d0, 0x1c50bb9216c46751, 0x65d98ea2de34092e, // [0][0x50] + 0x61f4916af5c0d866, 0x187da45a3d30b619, 0x93e6fa0a65210598, 0xea6fcf3aadd16be7, // [0][0x54] + 0x9bbcc49a32c9a609, 0xe235f1aafa39c876, 0x69aeaffaa2287bf7, 0x10279aca6ad81588, // [0][0x58] + 0x140a8502412cc4c0, 0x6d83b03289dcaabf, 0xe618ee62d1cd193e, 0x9f91db52193d7741, // [0][0x5c] + 0x6df2126bca249b26, 0x147b275b02d4f559, 0x9fe0790b5ac546d8, 0xe6694c3b923528a7, // [0][0x60] + 0xe24453f3b9c1f9ef, 0x9bcd66c371319790, 0x1056389329202411, 0x69df0da3e1d04a6e, // [0][0x64] + 0x180c06037ec88780, 0x61853333b638e9ff, 0xea1e6d63ee295a7e, 0x9397585326d93401, // [0][0x68] + 0x97ba479b0d2de549, 0xee3372abc5dd8b36, 0x65a82cfb9dcc38b7, 0x1c2119cb553c56c8, // [0][0x6c] + 0xec9dace3f1db7b5e, 0x951499d3392b1521, 0x1e8fc783613aa6a0, 0x6706f2b3a9cac8df, // [0][0x70] + 0x632bed7b823e1997, 0x1aa2d84b4ace77e8, 0x9139861b12dfc469, 0xe8b0b32bda2faa16, // [0][0x74] + 0x9963b88b453767f8, 0xe0ea8dbb8dc70987, 0x6b71d3ebd5d6ba06, 0x12f8e6db1d26d479, // [0][0x78] + 0x16d5f91336d20531, 0x6f5ccc23fe226b4e, 0xe4c79273a633d8cf, 0x9d4ea7436ec3b6b0, // [0][0x7c] + 0xb5c94bac29936c9a, 0xcc407e9ce16302e5, 0x47db20ccb972b164, 0x3e5215fc7182df1b, // [0][0x80] + 0x3a7f0a345a760e53, 0x43f63f049286602c, 0xc86d6154ca97d3ad, 0xb1e454640267bdd2, // [0][0x84] + 0xc0375fc49d7f703c, 0xb9be6af4558f1e43, 0x322534a40d9eadc2, 0x4bac0194c56ec3bd, // [0][0x88] + 0x4f811e5cee9a12f5, 0x36082b6c266a7c8a, 0xbd93753c7e7bcf0b, 0xc41a400cb68ba174, // [0][0x8c] + 0x34a6f524126c8ce2, 0x4d2fc014da9ce29d, 0xc6b49e44828d511c, 0xbf3dab744a7d3f63, // [0][0x90] + 0xbb10b4bc6189ee2b, 0xc299818ca9798054, 0x4902dfdcf16833d5, 0x308beaec39985daa, // [0][0x94] + 0x4158e14ca6809044, 0x38d1d47c6e70fe3b, 0xb34a8a2c36614dba, 0xcac3bf1cfe9123c5, // [0][0x98] + 0xceeea0d4d565f28d, 0xb76795e41d959cf2, 0x3cfccbb445842f73, 0x4575fe848d74410c, // [0][0x9c] + 0xb71637bd5e6dad6b, 0xce9f028d969dc314, 0x45045cddce8c7095, 0x3c8d69ed067c1eea, // [0][0xa0] + 0x38a076252d88cfa2, 0x41294315e578a1dd, 0xcab21d45bd69125c, 0xb33b287575997c23, // [0][0xa4] + 0xc2e823d5ea81b1cd, 0xbb6116e52271dfb2, 0x30fa48b57a606c33, 0x49737d85b290024c, // [0][0xa8] + 0x4d5e624d9964d304, 0x34d7577d5194bd7b, 0xbf4c092d09850efa, 0xc6c53c1dc1756085, // [0][0xac] + 0x3679893565924d13, 0x4ff0bc05ad62236c, 0xc46be255f57390ed, 0xbde2d7653d83fe92, // [0][0xb0] + 0xb9cfc8ad16772fda, 0xc046fd9dde8741a5, 0x4bdda3cd8696f224, 0x325496fd4e669c5b, // [0][0xb4] + 0x43879d5dd17e51b5, 0x3a0ea86d198e3fca, 0xb195f63d419f8c4b, 0xc81cc30d896fe234, // [0][0xb8] + 0xcc31dcc5a29b337c, 0xb5b8e9f56a6b5d03, 0x3e23b7a5327aee82, 0x47aa8295fa8a80fd, // [0][0xbc] + 0xdae425d69449364d, 0xa36d10e65cb95832, 0x28f64eb604a8ebb3, 0x517f7b86cc5885cc, // [0][0xc0] + 0x5552644ee7ac5484, 0x2cdb517e2f5c3afb, 0xa7400f2e774d897a, 0xdec93a1ebfbde705, // [0][0xc4] + 0xaf1a31be20a52aeb, 0xd693048ee8554494, 0x5d085adeb044f715, 0x24816fee78b4996a, // [0][0xc8] + 0x20ac702653404822, 0x592545169bb0265d, 0xd2be1b46c3a195dc, 0xab372e760b51fba3, // [0][0xcc] + 0x5b8b9b5eafb6d635, 0x2202ae6e6746b84a, 0xa999f03e3f570bcb, 0xd010c50ef7a765b4, // [0][0xd0] + 0xd43ddac6dc53b4fc, 0xadb4eff614a3da83, 0x262fb1a64cb26902, 0x5fa684968442077d, // [0][0xd4] + 0x2e758f361b5aca93, 0x57fcba06d3aaa4ec, 0xdc67e4568bbb176d, 0xa5eed166434b7912, // [0][0xd8] + 0xa1c3ceae68bfa85a, 0xd84afb9ea04fc625, 0x53d1a5cef85e75a4, 0x2a5890fe30ae1bdb, // [0][0xdc] + 0xd83b59c7e3b7f7bc, 0xa1b26cf72b4799c3, 0x2a2932a773562a42, 0x53a00797bba6443d, // [0][0xe0] + 0x578d185f90529575, 0x2e042d6f58a2fb0a, 0xa59f733f00b3488b, 0xdc16460fc84326f4, // [0][0xe4] + 0xadc54daf575beb1a, 0xd44c789f9fab8565, 0x5fd726cfc7ba36e4, 0x265e13ff0f4a589b, // [0][0xe8] + 0x22730c3724be89d3, 0x5bfa3907ec4ee7ac, 0xd0616757b45f542d, 0xa9e852677caf3a52, // [0][0xec] + 0x5954e74fd84817c4, 0x20ddd27f10b879bb, 0xab468c2f48a9ca3a, 0xd2cfb91f8059a445, // [0][0xf0] + 0xd6e2a6d7abad750d, 0xaf6b93e7635d1b72, 0x24f0cdb73b4ca8f3, 0x5d79f887f3bcc68c, // [0][0xf4] + 0x2caaf3276ca40b62, 0x5523c617a454651d, 0xdeb89847fc45d69c, 0xa731ad7734b5b8e3, // [0][0xf8] + 0xa31cb2bf1f4169ab, 0xda95878fd7b107d4, 0x510ed9df8fa0b455, 0x2887ecef4750da2a // [0][0xfc] + }, + { + 0x0000000000000000, 0x69dfbd737da97687, 0xb92decbfa974343a, 0xd0f251ccd4dd42bd, // [1][0x00] + 0x725bd87f53e96874, 0x1b84650c2e401ef3, 0xcb7634c0fa9d5c4e, 0xa2a989b387342ac9, // [1][0x04] + 0xe4b6b0ffa6d2d1e8, 0x8d690d8cdb7ba76f, 0x5d9b5c400fa6e5d2, 0x3444e133720f9355, // [1][0x08] + 0x96ed6880f53bb99c, 0xff32d5f38892cf1b, 0x2fc0843f5c4f8da6, 0x461f394c21e6fb21, // [1][0x0c] + 0xa3fef6a71e837ae5, 0xca214bd4632a0c62, 0x1ad31a18b7f74edf, 0x730ca76bca5e3858, // [1][0x10] + 0xd1a52ed84d6a1291, 0xb87a93ab30c36416, 0x6888c267e41e26ab, 0x01577f1499b7502c, // [1][0x14] + 0x47484658b851ab0d, 0x2e97fb2bc5f8dd8a, 0xfe65aae711259f37, 0x97ba17946c8ce9b0, // [1][0x18] + 0x35139e27ebb8c379, 0x5ccc23549611b5fe, 0x8c3e729842ccf743, 0xe5e1cfeb3f6581c4, // [1][0x1c] + 0x2d6e7a176e202cfe, 0x44b1c76413895a79, 0x944396a8c75418c4, 0xfd9c2bdbbafd6e43, // [1][0x20] + 0x5f35a2683dc9448a, 0x36ea1f1b4060320d, 0xe6184ed794bd70b0, 0x8fc7f3a4e9140637, // [1][0x24] + 0xc9d8cae8c8f2fd16, 0xa007779bb55b8b91, 0x70f526576186c92c, 0x192a9b241c2fbfab, // [1][0x28] + 0xbb8312979b1b9562, 0xd25cafe4e6b2e3e5, 0x02aefe28326fa158, 0x6b71435b4fc6d7df, // [1][0x2c] + 0x8e908cb070a3561b, 0xe74f31c30d0a209c, 0x37bd600fd9d76221, 0x5e62dd7ca47e14a6, // [1][0x30] + 0xfccb54cf234a3e6f, 0x9514e9bc5ee348e8, 0x45e6b8708a3e0a55, 0x2c390503f7977cd2, // [1][0x34] + 0x6a263c4fd67187f3, 0x03f9813cabd8f174, 0xd30bd0f07f05b3c9, 0xbad46d8302acc54e, // [1][0x38] + 0x187de4308598ef87, 0x71a25943f8319900, 0xa150088f2cecdbbd, 0xc88fb5fc5145ad3a, // [1][0x3c] + 0x314f63768f6681c8, 0x5890de05f2cff74f, 0x88628fc92612b5f2, 0xe1bd32ba5bbbc375, // [1][0x40] + 0x4314bb09dc8fe9bc, 0x2acb067aa1269f3b, 0xfa3957b675fbdd86, 0x93e6eac50852ab01, // [1][0x44] + 0xd5f9d38929b45020, 0xbc266efa541d26a7, 0x6cd43f3680c0641a, 0x050b8245fd69129d, // [1][0x48] + 0xa7a20bf67a5d3854, 0xce7db68507f44ed3, 0x1e8fe749d3290c6e, 0x77505a3aae807ae9, // [1][0x4c] + 0x92b195d191e5fb2d, 0xfb6e28a2ec4c8daa, 0x2b9c796e3891cf17, 0x4243c41d4538b990, // [1][0x50] + 0xe0ea4daec20c9359, 0x8935f0ddbfa5e5de, 0x59c7a1116b78a763, 0x30181c6216d1d1e4, // [1][0x54] + 0x7607252e37372ac5, 0x1fd8985d4a9e5c42, 0xcf2ac9919e431eff, 0xa6f574e2e3ea6878, // [1][0x58] + 0x045cfd5164de42b1, 0x6d83402219773436, 0xbd7111eecdaa768b, 0xd4aeac9db003000c, // [1][0x5c] + 0x1c211961e146ad36, 0x75fea4129cefdbb1, 0xa50cf5de4832990c, 0xccd348ad359bef8b, // [1][0x60] + 0x6e7ac11eb2afc542, 0x07a57c6dcf06b3c5, 0xd7572da11bdbf178, 0xbe8890d2667287ff, // [1][0x64] + 0xf897a99e47947cde, 0x914814ed3a3d0a59, 0x41ba4521eee048e4, 0x2865f85293493e63, // [1][0x68] + 0x8acc71e1147d14aa, 0xe313cc9269d4622d, 0x33e19d5ebd092090, 0x5a3e202dc0a05617, // [1][0x6c] + 0xbfdfefc6ffc5d7d3, 0xd60052b5826ca154, 0x06f2037956b1e3e9, 0x6f2dbe0a2b18956e, // [1][0x70] + 0xcd8437b9ac2cbfa7, 0xa45b8acad185c920, 0x74a9db0605588b9d, 0x1d76667578f1fd1a, // [1][0x74] + 0x5b695f395917063b, 0x32b6e24a24be70bc, 0xe244b386f0633201, 0x8b9b0ef58dca4486, // [1][0x78] + 0x293287460afe6e4f, 0x40ed3a35775718c8, 0x901f6bf9a38a5a75, 0xf9c0d68ade232cf2, // [1][0x7c] + 0x090d51b44debdba5, 0x60d2ecc73042ad22, 0xb020bd0be49fef9f, 0xd9ff007899369918, // [1][0x80] + 0x7b5689cb1e02b3d1, 0x128934b863abc556, 0xc27b6574b77687eb, 0xaba4d807cadff16c, // [1][0x84] + 0xedbbe14beb390a4d, 0x84645c3896907cca, 0x54960df4424d3e77, 0x3d49b0873fe448f0, // [1][0x88] + 0x9fe03934b8d06239, 0xf63f8447c57914be, 0x26cdd58b11a45603, 0x4f1268f86c0d2084, // [1][0x8c] + 0xaaf3a7135368a140, 0xc32c1a602ec1d7c7, 0x13de4bacfa1c957a, 0x7a01f6df87b5e3fd, // [1][0x90] + 0xd8a87f6c0081c934, 0xb177c21f7d28bfb3, 0x618593d3a9f5fd0e, 0x085a2ea0d45c8b89, // [1][0x94] + 0x4e4517ecf5ba70a8, 0x279aaa9f8813062f, 0xf768fb535cce4492, 0x9eb7462021673215, // [1][0x98] + 0x3c1ecf93a65318dc, 0x55c172e0dbfa6e5b, 0x8533232c0f272ce6, 0xecec9e5f728e5a61, // [1][0x9c] + 0x24632ba323cbf75b, 0x4dbc96d05e6281dc, 0x9d4ec71c8abfc361, 0xf4917a6ff716b5e6, // [1][0xa0] + 0x5638f3dc70229f2f, 0x3fe74eaf0d8be9a8, 0xef151f63d956ab15, 0x86caa210a4ffdd92, // [1][0xa4] + 0xc0d59b5c851926b3, 0xa90a262ff8b05034, 0x79f877e32c6d1289, 0x1027ca9051c4640e, // [1][0xa8] + 0xb28e4323d6f04ec7, 0xdb51fe50ab593840, 0x0ba3af9c7f847afd, 0x627c12ef022d0c7a, // [1][0xac] + 0x879ddd043d488dbe, 0xee42607740e1fb39, 0x3eb031bb943cb984, 0x576f8cc8e995cf03, // [1][0xb0] + 0xf5c6057b6ea1e5ca, 0x9c19b8081308934d, 0x4cebe9c4c7d5d1f0, 0x253454b7ba7ca777, // [1][0xb4] + 0x632b6dfb9b9a5c56, 0x0af4d088e6332ad1, 0xda06814432ee686c, 0xb3d93c374f471eeb, // [1][0xb8] + 0x1170b584c8733422, 0x78af08f7b5da42a5, 0xa85d593b61070018, 0xc182e4481cae769f, // [1][0xbc] + 0x384232c2c28d5a6d, 0x519d8fb1bf242cea, 0x816fde7d6bf96e57, 0xe8b0630e165018d0, // [1][0xc0] + 0x4a19eabd91643219, 0x23c657ceeccd449e, 0xf334060238100623, 0x9aebbb7145b970a4, // [1][0xc4] + 0xdcf4823d645f8b85, 0xb52b3f4e19f6fd02, 0x65d96e82cd2bbfbf, 0x0c06d3f1b082c938, // [1][0xc8] + 0xaeaf5a4237b6e3f1, 0xc770e7314a1f9576, 0x1782b6fd9ec2d7cb, 0x7e5d0b8ee36ba14c, // [1][0xcc] + 0x9bbcc465dc0e2088, 0xf2637916a1a7560f, 0x229128da757a14b2, 0x4b4e95a908d36235, // [1][0xd0] + 0xe9e71c1a8fe748fc, 0x8038a169f24e3e7b, 0x50caf0a526937cc6, 0x39154dd65b3a0a41, // [1][0xd4] + 0x7f0a749a7adcf160, 0x16d5c9e9077587e7, 0xc6279825d3a8c55a, 0xaff82556ae01b3dd, // [1][0xd8] + 0x0d51ace529359914, 0x648e1196549cef93, 0xb47c405a8041ad2e, 0xdda3fd29fde8dba9, // [1][0xdc] + 0x152c48d5acad7693, 0x7cf3f5a6d1040014, 0xac01a46a05d942a9, 0xc5de19197870342e, // [1][0xe0] + 0x677790aaff441ee7, 0x0ea82dd982ed6860, 0xde5a7c1556302add, 0xb785c1662b995c5a, // [1][0xe4] + 0xf19af82a0a7fa77b, 0x9845455977d6d1fc, 0x48b71495a30b9341, 0x2168a9e6dea2e5c6, // [1][0xe8] + 0x83c120555996cf0f, 0xea1e9d26243fb988, 0x3aeccceaf0e2fb35, 0x533371998d4b8db2, // [1][0xec] + 0xb6d2be72b22e0c76, 0xdf0d0301cf877af1, 0x0fff52cd1b5a384c, 0x6620efbe66f34ecb, // [1][0xf0] + 0xc489660de1c76402, 0xad56db7e9c6e1285, 0x7da48ab248b35038, 0x147b37c1351a26bf, // [1][0xf4] + 0x52640e8d14fcdd9e, 0x3bbbb3fe6955ab19, 0xeb49e232bd88e9a4, 0x82965f41c0219f23, // [1][0xf8] + 0x203fd6f24715b5ea, 0x49e06b813abcc36d, 0x99123a4dee6181d0, 0xf0cd873e93c8f757 // [1][0xfc] + }, + { + 0x0000000000000000, 0xbe38404e1f4e6eff, 0x17e217c46dba05ca, 0xa9da578a72f46b35, // [2][0x00] + 0x4557b8d08852d2a0, 0xfb6ff89e971cbc5f, 0x52b5af14e5e8d76a, 0xec8def5afaa6b995, // [2][0x04] + 0xe13de7f942837d75, 0x5f05a7b75dcd138a, 0xf6dff03d2f3978bf, 0x48e7b07330771640, // [2][0x08] + 0xa46a5f29cad1afd5, 0x1a521f67d59fc12a, 0xb38848eda76baa1f, 0x0db008a3b825c4e0, // [2][0x0c] + 0xc27bcef38506fbea, 0x7c438ebd9a489515, 0xd599d937e8bcfe20, 0x6ba19979f7f290df, // [2][0x10] + 0x872c76230d54294a, 0x3914366d121a47b5, 0x90ce61e760ee2c80, 0x2ef621a97fa0427f, // [2][0x14] + 0x2346290ac785869f, 0x9d7e6944d8cbe860, 0x34a43eceaa3f8355, 0x8a9c7e80b571edaa, // [2][0x18] + 0x661191da4fd7543f, 0xd829d19450993ac0, 0x71f3861e226d51f5, 0xcfcbc6503d233f0a, // [2][0x1c] + 0xef640bbf582b2fe1, 0x515c4bf14765411e, 0xf8861c7b35912a2b, 0x46be5c352adf44d4, // [2][0x20] + 0xaa33b36fd079fd41, 0x140bf321cf3793be, 0xbdd1a4abbdc3f88b, 0x03e9e4e5a28d9674, // [2][0x24] + 0x0e59ec461aa85294, 0xb061ac0805e63c6b, 0x19bbfb827712575e, 0xa783bbcc685c39a1, // [2][0x28] + 0x4b0e549692fa8034, 0xf53614d88db4eecb, 0x5cec4352ff4085fe, 0xe2d4031ce00eeb01, // [2][0x2c] + 0x2d1fc54cdd2dd40b, 0x93278502c263baf4, 0x3afdd288b097d1c1, 0x84c592c6afd9bf3e, // [2][0x30] + 0x68487d9c557f06ab, 0xd6703dd24a316854, 0x7faa6a5838c50361, 0xc1922a16278b6d9e, // [2][0x34] + 0xcc2222b59faea97e, 0x721a62fb80e0c781, 0xdbc03571f214acb4, 0x65f8753fed5ac24b, // [2][0x38] + 0x89759a6517fc7bde, 0x374dda2b08b21521, 0x9e978da17a467e14, 0x20afcdef650810eb, // [2][0x3c] + 0xb55a8126e27087f6, 0x0b62c168fd3ee909, 0xa2b896e28fca823c, 0x1c80d6ac9084ecc3, // [2][0x40] + 0xf00d39f66a225556, 0x4e3579b8756c3ba9, 0xe7ef2e320798509c, 0x59d76e7c18d63e63, // [2][0x44] + 0x546766dfa0f3fa83, 0xea5f2691bfbd947c, 0x4385711bcd49ff49, 0xfdbd3155d20791b6, // [2][0x48] + 0x1130de0f28a12823, 0xaf089e4137ef46dc, 0x06d2c9cb451b2de9, 0xb8ea89855a554316, // [2][0x4c] + 0x77214fd567767c1c, 0xc9190f9b783812e3, 0x60c358110acc79d6, 0xdefb185f15821729, // [2][0x50] + 0x3276f705ef24aebc, 0x8c4eb74bf06ac043, 0x2594e0c1829eab76, 0x9baca08f9dd0c589, // [2][0x54] + 0x961ca82c25f50169, 0x2824e8623abb6f96, 0x81febfe8484f04a3, 0x3fc6ffa657016a5c, // [2][0x58] + 0xd34b10fcada7d3c9, 0x6d7350b2b2e9bd36, 0xc4a90738c01dd603, 0x7a914776df53b8fc, // [2][0x5c] + 0x5a3e8a99ba5ba817, 0xe406cad7a515c6e8, 0x4ddc9d5dd7e1addd, 0xf3e4dd13c8afc322, // [2][0x60] + 0x1f69324932097ab7, 0xa15172072d471448, 0x088b258d5fb37f7d, 0xb6b365c340fd1182, // [2][0x64] + 0xbb036d60f8d8d562, 0x053b2d2ee796bb9d, 0xace17aa49562d0a8, 0x12d93aea8a2cbe57, // [2][0x68] + 0xfe54d5b0708a07c2, 0x406c95fe6fc4693d, 0xe9b6c2741d300208, 0x578e823a027e6cf7, // [2][0x6c] + 0x9845446a3f5d53fd, 0x267d042420133d02, 0x8fa753ae52e75637, 0x319f13e04da938c8, // [2][0x70] + 0xdd12fcbab70f815d, 0x632abcf4a841efa2, 0xcaf0eb7edab58497, 0x74c8ab30c5fbea68, // [2][0x74] + 0x7978a3937dde2e88, 0xc740e3dd62904077, 0x6e9ab45710642b42, 0xd0a2f4190f2a45bd, // [2][0x78] + 0x3c2f1b43f58cfc28, 0x82175b0deac292d7, 0x2bcd0c879836f9e2, 0x95f54cc98778971d, // [2][0x7c] + 0x0126951597c7d7d9, 0xbf1ed55b8889b926, 0x16c482d1fa7dd213, 0xa8fcc29fe533bcec, // [2][0x80] + 0x44712dc51f950579, 0xfa496d8b00db6b86, 0x53933a01722f00b3, 0xedab7a4f6d616e4c, // [2][0x84] + 0xe01b72ecd544aaac, 0x5e2332a2ca0ac453, 0xf7f96528b8feaf66, 0x49c12566a7b0c199, // [2][0x88] + 0xa54cca3c5d16780c, 0x1b748a72425816f3, 0xb2aeddf830ac7dc6, 0x0c969db62fe21339, // [2][0x8c] + 0xc35d5be612c12c33, 0x7d651ba80d8f42cc, 0xd4bf4c227f7b29f9, 0x6a870c6c60354706, // [2][0x90] + 0x860ae3369a93fe93, 0x3832a37885dd906c, 0x91e8f4f2f729fb59, 0x2fd0b4bce86795a6, // [2][0x94] + 0x2260bc1f50425146, 0x9c58fc514f0c3fb9, 0x3582abdb3df8548c, 0x8bbaeb9522b63a73, // [2][0x98] + 0x673704cfd81083e6, 0xd90f4481c75eed19, 0x70d5130bb5aa862c, 0xceed5345aae4e8d3, // [2][0x9c] + 0xee429eaacfecf838, 0x507adee4d0a296c7, 0xf9a0896ea256fdf2, 0x4798c920bd18930d, // [2][0xa0] + 0xab15267a47be2a98, 0x152d663458f04467, 0xbcf731be2a042f52, 0x02cf71f0354a41ad, // [2][0xa4] + 0x0f7f79538d6f854d, 0xb147391d9221ebb2, 0x189d6e97e0d58087, 0xa6a52ed9ff9bee78, // [2][0xa8] + 0x4a28c183053d57ed, 0xf41081cd1a733912, 0x5dcad64768875227, 0xe3f2960977c93cd8, // [2][0xac] + 0x2c3950594aea03d2, 0x9201101755a46d2d, 0x3bdb479d27500618, 0x85e307d3381e68e7, // [2][0xb0] + 0x696ee889c2b8d172, 0xd756a8c7ddf6bf8d, 0x7e8cff4daf02d4b8, 0xc0b4bf03b04cba47, // [2][0xb4] + 0xcd04b7a008697ea7, 0x733cf7ee17271058, 0xdae6a06465d37b6d, 0x64dee02a7a9d1592, // [2][0xb8] + 0x88530f70803bac07, 0x366b4f3e9f75c2f8, 0x9fb118b4ed81a9cd, 0x218958faf2cfc732, // [2][0xbc] + 0xb47c143375b7502f, 0x0a44547d6af93ed0, 0xa39e03f7180d55e5, 0x1da643b907433b1a, // [2][0xc0] + 0xf12bace3fde5828f, 0x4f13ecade2abec70, 0xe6c9bb27905f8745, 0x58f1fb698f11e9ba, // [2][0xc4] + 0x5541f3ca37342d5a, 0xeb79b384287a43a5, 0x42a3e40e5a8e2890, 0xfc9ba44045c0466f, // [2][0xc8] + 0x10164b1abf66fffa, 0xae2e0b54a0289105, 0x07f45cded2dcfa30, 0xb9cc1c90cd9294cf, // [2][0xcc] + 0x7607dac0f0b1abc5, 0xc83f9a8eefffc53a, 0x61e5cd049d0bae0f, 0xdfdd8d4a8245c0f0, // [2][0xd0] + 0x3350621078e37965, 0x8d68225e67ad179a, 0x24b275d415597caf, 0x9a8a359a0a171250, // [2][0xd4] + 0x973a3d39b232d6b0, 0x29027d77ad7cb84f, 0x80d82afddf88d37a, 0x3ee06ab3c0c6bd85, // [2][0xd8] + 0xd26d85e93a600410, 0x6c55c5a7252e6aef, 0xc58f922d57da01da, 0x7bb7d26348946f25, // [2][0xdc] + 0x5b181f8c2d9c7fce, 0xe5205fc232d21131, 0x4cfa084840267a04, 0xf2c248065f6814fb, // [2][0xe0] + 0x1e4fa75ca5cead6e, 0xa077e712ba80c391, 0x09adb098c874a8a4, 0xb795f0d6d73ac65b, // [2][0xe4] + 0xba25f8756f1f02bb, 0x041db83b70516c44, 0xadc7efb102a50771, 0x13ffafff1deb698e, // [2][0xe8] + 0xff7240a5e74dd01b, 0x414a00ebf803bee4, 0xe89057618af7d5d1, 0x56a8172f95b9bb2e, // [2][0xec] + 0x9963d17fa89a8424, 0x275b9131b7d4eadb, 0x8e81c6bbc52081ee, 0x30b986f5da6eef11, // [2][0xf0] + 0xdc3469af20c85684, 0x620c29e13f86387b, 0xcbd67e6b4d72534e, 0x75ee3e25523c3db1, // [2][0xf4] + 0x785e3686ea19f951, 0xc66676c8f55797ae, 0x6fbc214287a3fc9b, 0xd184610c98ed9264, // [2][0xf8] + 0x3d098e56624b2bf1, 0x8331ce187d05450e, 0x2aeb99920ff12e3b, 0x94d3d9dc10bf40c4 // [2][0xfc] + }, + { + 0x0000000000000000, 0x0663f9ba7c141182, 0x6755652daa0efb30, 0x61369c97d61aeab2, // [3][0x00] + 0xceaaca5a541df661, 0xc8c933e02809e7e3, 0xa9ffaf77fe130d51, 0xaf9c56cd82071cd3, // [3][0x04] + 0x9c5595b5a83aecc3, 0x9a366c0fd42efd41, 0xfb00f098023417f3, 0xfd6309227e200671, // [3][0x08] + 0x52ff5feffc271aa2, 0x549ca65580330b20, 0x35aa3ac25629e192, 0x33c9c3782a3df010, // [3][0x0c] + 0x5338bd33025301b3, 0x555b44897e471031, 0x346dd81ea85dfa83, 0x320e21a4d449eb01, // [3][0x10] + 0x9d927769564ef7d2, 0x9bf18ed32a5ae650, 0xfac71244fc400ce2, 0xfca4ebfe80541d60, // [3][0x14] + 0xcf6d2886aa69ed70, 0xc90ed13cd67dfcf2, 0xa8384dab00671640, 0xae5bb4117c7307c2, // [3][0x18] + 0x01c7e2dcfe741b11, 0x07a41b6682600a93, 0x669287f1547ae021, 0x60f17e4b286ef1a3, // [3][0x1c] + 0xcde3ed3f5780db52, 0xcb8014852b94cad0, 0xaab68812fd8e2062, 0xacd571a8819a31e0, // [3][0x20] + 0x03492765039d2d33, 0x052adedf7f893cb1, 0x641c4248a993d603, 0x627fbbf2d587c781, // [3][0x24] + 0x51b6788affba3791, 0x57d5813083ae2613, 0x36e31da755b4cca1, 0x3080e41d29a0dd23, // [3][0x28] + 0x9f1cb2d0aba7c1f0, 0x997f4b6ad7b3d072, 0xf849d7fd01a93ac0, 0xfe2a2e477dbd2b42, // [3][0x2c] + 0x9edb500c55d3dae1, 0x98b8a9b629c7cb63, 0xf98e3521ffdd21d1, 0xffedcc9b83c93053, // [3][0x30] + 0x50719a5601ce2c80, 0x561263ec7dda3d02, 0x3724ff7babc0d7b0, 0x314706c1d7d4c632, // [3][0x34] + 0x028ec5b9fde93622, 0x04ed3c0381fd27a0, 0x65dba09457e7cd12, 0x63b8592e2bf3dc90, // [3][0x38] + 0xcc240fe3a9f4c043, 0xca47f659d5e0d1c1, 0xab716ace03fa3b73, 0xad1293747fee2af1, // [3][0x3c] + 0x9ac7db7fae00b7a5, 0x9ca422c5d214a627, 0xfd92be52040e4c95, 0xfbf147e8781a5d17, // [3][0x40] + 0x546d1125fa1d41c4, 0x520ee89f86095046, 0x333874085013baf4, 0x355b8db22c07ab76, // [3][0x44] + 0x06924eca063a5b66, 0x00f1b7707a2e4ae4, 0x61c72be7ac34a056, 0x67a4d25dd020b1d4, // [3][0x48] + 0xc83884905227ad07, 0xce5b7d2a2e33bc85, 0xaf6de1bdf8295637, 0xa90e1807843d47b5, // [3][0x4c] + 0xc9ff664cac53b616, 0xcf9c9ff6d047a794, 0xaeaa0361065d4d26, 0xa8c9fadb7a495ca4, // [3][0x50] + 0x0755ac16f84e4077, 0x013655ac845a51f5, 0x6000c93b5240bb47, 0x666330812e54aac5, // [3][0x54] + 0x55aaf3f904695ad5, 0x53c90a43787d4b57, 0x32ff96d4ae67a1e5, 0x349c6f6ed273b067, // [3][0x58] + 0x9b0039a35074acb4, 0x9d63c0192c60bd36, 0xfc555c8efa7a5784, 0xfa36a534866e4606, // [3][0x5c] + 0x57243640f9806cf7, 0x5147cffa85947d75, 0x3071536d538e97c7, 0x3612aad72f9a8645, // [3][0x60] + 0x998efc1aad9d9a96, 0x9fed05a0d1898b14, 0xfedb9937079361a6, 0xf8b8608d7b877024, // [3][0x64] + 0xcb71a3f551ba8034, 0xcd125a4f2dae91b6, 0xac24c6d8fbb47b04, 0xaa473f6287a06a86, // [3][0x68] + 0x05db69af05a77655, 0x03b8901579b367d7, 0x628e0c82afa98d65, 0x64edf538d3bd9ce7, // [3][0x6c] + 0x041c8b73fbd36d44, 0x027f72c987c77cc6, 0x6349ee5e51dd9674, 0x652a17e42dc987f6, // [3][0x70] + 0xcab64129afce9b25, 0xccd5b893d3da8aa7, 0xade3240405c06015, 0xab80ddbe79d47197, // [3][0x74] + 0x98491ec653e98187, 0x9e2ae77c2ffd9005, 0xff1c7bebf9e77ab7, 0xf97f825185f36b35, // [3][0x78] + 0x56e3d49c07f477e6, 0x50802d267be06664, 0x31b6b1b1adfa8cd6, 0x37d5480bd1ee9d54, // [3][0x7c] + 0x5f1c20a70f27b77f, 0x597fd91d7333a6fd, 0x3849458aa5294c4f, 0x3e2abc30d93d5dcd, // [3][0x80] + 0x91b6eafd5b3a411e, 0x97d51347272e509c, 0xf6e38fd0f134ba2e, 0xf080766a8d20abac, // [3][0x84] + 0xc349b512a71d5bbc, 0xc52a4ca8db094a3e, 0xa41cd03f0d13a08c, 0xa27f29857107b10e, // [3][0x88] + 0x0de37f48f300addd, 0x0b8086f28f14bc5f, 0x6ab61a65590e56ed, 0x6cd5e3df251a476f, // [3][0x8c] + 0x0c249d940d74b6cc, 0x0a47642e7160a74e, 0x6b71f8b9a77a4dfc, 0x6d120103db6e5c7e, // [3][0x90] + 0xc28e57ce596940ad, 0xc4edae74257d512f, 0xa5db32e3f367bb9d, 0xa3b8cb598f73aa1f, // [3][0x94] + 0x90710821a54e5a0f, 0x9612f19bd95a4b8d, 0xf7246d0c0f40a13f, 0xf14794b67354b0bd, // [3][0x98] + 0x5edbc27bf153ac6e, 0x58b83bc18d47bdec, 0x398ea7565b5d575e, 0x3fed5eec274946dc, // [3][0x9c] + 0x92ffcd9858a76c2d, 0x949c342224b37daf, 0xf5aaa8b5f2a9971d, 0xf3c9510f8ebd869f, // [3][0xa0] + 0x5c5507c20cba9a4c, 0x5a36fe7870ae8bce, 0x3b0062efa6b4617c, 0x3d639b55daa070fe, // [3][0xa4] + 0x0eaa582df09d80ee, 0x08c9a1978c89916c, 0x69ff3d005a937bde, 0x6f9cc4ba26876a5c, // [3][0xa8] + 0xc0009277a480768f, 0xc6636bcdd894670d, 0xa755f75a0e8e8dbf, 0xa1360ee0729a9c3d, // [3][0xac] + 0xc1c770ab5af46d9e, 0xc7a4891126e07c1c, 0xa6921586f0fa96ae, 0xa0f1ec3c8cee872c, // [3][0xb0] + 0x0f6dbaf10ee99bff, 0x090e434b72fd8a7d, 0x6838dfdca4e760cf, 0x6e5b2666d8f3714d, // [3][0xb4] + 0x5d92e51ef2ce815d, 0x5bf11ca48eda90df, 0x3ac7803358c07a6d, 0x3ca4798924d46bef, // [3][0xb8] + 0x93382f44a6d3773c, 0x955bd6fedac766be, 0xf46d4a690cdd8c0c, 0xf20eb3d370c99d8e, // [3][0xbc] + 0xc5dbfbd8a12700da, 0xc3b80262dd331158, 0xa28e9ef50b29fbea, 0xa4ed674f773dea68, // [3][0xc0] + 0x0b713182f53af6bb, 0x0d12c838892ee739, 0x6c2454af5f340d8b, 0x6a47ad1523201c09, // [3][0xc4] + 0x598e6e6d091dec19, 0x5fed97d77509fd9b, 0x3edb0b40a3131729, 0x38b8f2fadf0706ab, // [3][0xc8] + 0x9724a4375d001a78, 0x91475d8d21140bfa, 0xf071c11af70ee148, 0xf61238a08b1af0ca, // [3][0xcc] + 0x96e346eba3740169, 0x9080bf51df6010eb, 0xf1b623c6097afa59, 0xf7d5da7c756eebdb, // [3][0xd0] + 0x58498cb1f769f708, 0x5e2a750b8b7de68a, 0x3f1ce99c5d670c38, 0x397f102621731dba, // [3][0xd4] + 0x0ab6d35e0b4eedaa, 0x0cd52ae4775afc28, 0x6de3b673a140169a, 0x6b804fc9dd540718, // [3][0xd8] + 0xc41c19045f531bcb, 0xc27fe0be23470a49, 0xa3497c29f55de0fb, 0xa52a85938949f179, // [3][0xdc] + 0x083816e7f6a7db88, 0x0e5bef5d8ab3ca0a, 0x6f6d73ca5ca920b8, 0x690e8a7020bd313a, // [3][0xe0] + 0xc692dcbda2ba2de9, 0xc0f12507deae3c6b, 0xa1c7b99008b4d6d9, 0xa7a4402a74a0c75b, // [3][0xe4] + 0x946d83525e9d374b, 0x920e7ae8228926c9, 0xf338e67ff493cc7b, 0xf55b1fc58887ddf9, // [3][0xe8] + 0x5ac749080a80c12a, 0x5ca4b0b27694d0a8, 0x3d922c25a08e3a1a, 0x3bf1d59fdc9a2b98, // [3][0xec] + 0x5b00abd4f4f4da3b, 0x5d63526e88e0cbb9, 0x3c55cef95efa210b, 0x3a36374322ee3089, // [3][0xf0] + 0x95aa618ea0e92c5a, 0x93c99834dcfd3dd8, 0xf2ff04a30ae7d76a, 0xf49cfd1976f3c6e8, // [3][0xf4] + 0xc7553e615cce36f8, 0xc136c7db20da277a, 0xa0005b4cf6c0cdc8, 0xa663a2f68ad4dc4a, // [3][0xf8] + 0x09fff43b08d3c099, 0x0f9c0d8174c7d11b, 0x6eaa9116a2dd3ba9, 0x68c968acdec92a2b // [3][0xfc] + }, + { + 0x0000000000000000, 0x1e5d9084f7153d37, 0x3cba2009ef2b7a6e, 0x22e7b08d183e4759, // [4][0x00] + 0x78744112de57f4dc, 0x6629d1962942c9eb, 0x44ce611b317c8eb2, 0x5a93f19fc669b385, // [4][0x04] + 0x9b7b157cef89318d, 0x852685f8189c0cba, 0xa7c1357500a24be3, 0xb99ca5f1f7b776d4, // [4][0x08] + 0xe30f546e31dec551, 0xfd52c4eac6cbf866, 0xdfb57467def5bf3f, 0xc1e8e4e329e08208, // [4][0x0c] + 0x5d64bda08d35ba2e, 0x43392d247a208719, 0x61de9da9621ec040, 0x7f830d2d950bfd77, // [4][0x10] + 0x2510fcb253624ef2, 0x3b4d6c36a47773c5, 0x19aadcbbbc49349c, 0x07f74c3f4b5c09ab, // [4][0x14] + 0xc61fa8dc62bc8ba3, 0xd842385895a9b694, 0xfaa588d58d97f1cd, 0xe4f818517a82ccfa, // [4][0x18] + 0xbe6be9cebceb7f7f, 0xa036794a4bfe4248, 0x82d1c9c753c00511, 0x9c8c5943a4d53826, // [4][0x1c] + 0xbac87a411b6b745d, 0xa495eac5ec7e496a, 0x86725a48f4400e33, 0x982fcacc03553304, // [4][0x20] + 0xc2bc3b53c53c8081, 0xdce1abd73229bdb6, 0xfe061b5a2a17faef, 0xe05b8bdedd02c7d8, // [4][0x24] + 0x21b36f3df4e245d0, 0x3feeffb903f778e7, 0x1d094f341bc93fbe, 0x0354dfb0ecdc0289, // [4][0x28] + 0x59c72e2f2ab5b10c, 0x479abeabdda08c3b, 0x657d0e26c59ecb62, 0x7b209ea2328bf655, // [4][0x2c] + 0xe7acc7e1965ece73, 0xf9f15765614bf344, 0xdb16e7e87975b41d, 0xc54b776c8e60892a, // [4][0x30] + 0x9fd886f348093aaf, 0x81851677bf1c0798, 0xa362a6faa72240c1, 0xbd3f367e50377df6, // [4][0x34] + 0x7cd7d29d79d7fffe, 0x628a42198ec2c2c9, 0x406df29496fc8590, 0x5e30621061e9b8a7, // [4][0x38] + 0x04a3938fa7800b22, 0x1afe030b50953615, 0x3819b38648ab714c, 0x26442302bfbe4c7b, // [4][0x3c] + 0x7491f58236d6e8ba, 0x6acc6506c1c3d58d, 0x482bd58bd9fd92d4, 0x5676450f2ee8afe3, // [4][0x40] + 0x0ce5b490e8811c66, 0x12b824141f942151, 0x305f949907aa6608, 0x2e02041df0bf5b3f, // [4][0x44] + 0xefeae0fed95fd937, 0xf1b7707a2e4ae400, 0xd350c0f73674a359, 0xcd0d5073c1619e6e, // [4][0x48] + 0x979ea1ec07082deb, 0x89c33168f01d10dc, 0xab2481e5e8235785, 0xb57911611f366ab2, // [4][0x4c] + 0x29f54822bbe35294, 0x37a8d8a64cf66fa3, 0x154f682b54c828fa, 0x0b12f8afa3dd15cd, // [4][0x50] + 0x5181093065b4a648, 0x4fdc99b492a19b7f, 0x6d3b29398a9fdc26, 0x7366b9bd7d8ae111, // [4][0x54] + 0xb28e5d5e546a6319, 0xacd3cddaa37f5e2e, 0x8e347d57bb411977, 0x9069edd34c542440, // [4][0x58] + 0xcafa1c4c8a3d97c5, 0xd4a78cc87d28aaf2, 0xf6403c456516edab, 0xe81dacc19203d09c, // [4][0x5c] + 0xce598fc32dbd9ce7, 0xd0041f47daa8a1d0, 0xf2e3afcac296e689, 0xecbe3f4e3583dbbe, // [4][0x60] + 0xb62dced1f3ea683b, 0xa8705e5504ff550c, 0x8a97eed81cc11255, 0x94ca7e5cebd42f62, // [4][0x64] + 0x55229abfc234ad6a, 0x4b7f0a3b3521905d, 0x6998bab62d1fd704, 0x77c52a32da0aea33, // [4][0x68] + 0x2d56dbad1c6359b6, 0x330b4b29eb766481, 0x11ecfba4f34823d8, 0x0fb16b20045d1eef, // [4][0x6c] + 0x933d3263a08826c9, 0x8d60a2e7579d1bfe, 0xaf87126a4fa35ca7, 0xb1da82eeb8b66190, // [4][0x70] + 0xeb4973717edfd215, 0xf514e3f589caef22, 0xd7f3537891f4a87b, 0xc9aec3fc66e1954c, // [4][0x74] + 0x0846271f4f011744, 0x161bb79bb8142a73, 0x34fc0716a02a6d2a, 0x2aa19792573f501d, // [4][0x78] + 0x7032660d9156e398, 0x6e6ff6896643deaf, 0x4c8846047e7d99f6, 0x52d5d6808968a4c1, // [4][0x7c] + 0x83b17c5d3e8a0841, 0x9dececd9c99f3576, 0xbf0b5c54d1a1722f, 0xa156ccd026b44f18, // [4][0x80] + 0xfbc53d4fe0ddfc9d, 0xe598adcb17c8c1aa, 0xc77f1d460ff686f3, 0xd9228dc2f8e3bbc4, // [4][0x84] + 0x18ca6921d10339cc, 0x0697f9a5261604fb, 0x247049283e2843a2, 0x3a2dd9acc93d7e95, // [4][0x88] + 0x60be28330f54cd10, 0x7ee3b8b7f841f027, 0x5c04083ae07fb77e, 0x425998be176a8a49, // [4][0x8c] + 0xded5c1fdb3bfb26f, 0xc088517944aa8f58, 0xe26fe1f45c94c801, 0xfc327170ab81f536, // [4][0x90] + 0xa6a180ef6de846b3, 0xb8fc106b9afd7b84, 0x9a1ba0e682c33cdd, 0x8446306275d601ea, // [4][0x94] + 0x45aed4815c3683e2, 0x5bf34405ab23bed5, 0x7914f488b31df98c, 0x6749640c4408c4bb, // [4][0x98] + 0x3dda95938261773e, 0x2387051775744a09, 0x0160b59a6d4a0d50, 0x1f3d251e9a5f3067, // [4][0x9c] + 0x3979061c25e17c1c, 0x27249698d2f4412b, 0x05c32615caca0672, 0x1b9eb6913ddf3b45, // [4][0xa0] + 0x410d470efbb688c0, 0x5f50d78a0ca3b5f7, 0x7db76707149df2ae, 0x63eaf783e388cf99, // [4][0xa4] + 0xa2021360ca684d91, 0xbc5f83e43d7d70a6, 0x9eb83369254337ff, 0x80e5a3edd2560ac8, // [4][0xa8] + 0xda765272143fb94d, 0xc42bc2f6e32a847a, 0xe6cc727bfb14c323, 0xf891e2ff0c01fe14, // [4][0xac] + 0x641dbbbca8d4c632, 0x7a402b385fc1fb05, 0x58a79bb547ffbc5c, 0x46fa0b31b0ea816b, // [4][0xb0] + 0x1c69faae768332ee, 0x02346a2a81960fd9, 0x20d3daa799a84880, 0x3e8e4a236ebd75b7, // [4][0xb4] + 0xff66aec0475df7bf, 0xe13b3e44b048ca88, 0xc3dc8ec9a8768dd1, 0xdd811e4d5f63b0e6, // [4][0xb8] + 0x8712efd2990a0363, 0x994f7f566e1f3e54, 0xbba8cfdb7621790d, 0xa5f55f5f8134443a, // [4][0xbc] + 0xf72089df085ce0fb, 0xe97d195bff49ddcc, 0xcb9aa9d6e7779a95, 0xd5c739521062a7a2, // [4][0xc0] + 0x8f54c8cdd60b1427, 0x91095849211e2910, 0xb3eee8c439206e49, 0xadb37840ce35537e, // [4][0xc4] + 0x6c5b9ca3e7d5d176, 0x72060c2710c0ec41, 0x50e1bcaa08feab18, 0x4ebc2c2effeb962f, // [4][0xc8] + 0x142fddb1398225aa, 0x0a724d35ce97189d, 0x2895fdb8d6a95fc4, 0x36c86d3c21bc62f3, // [4][0xcc] + 0xaa44347f85695ad5, 0xb419a4fb727c67e2, 0x96fe14766a4220bb, 0x88a384f29d571d8c, // [4][0xd0] + 0xd230756d5b3eae09, 0xcc6de5e9ac2b933e, 0xee8a5564b415d467, 0xf0d7c5e04300e950, // [4][0xd4] + 0x313f21036ae06b58, 0x2f62b1879df5566f, 0x0d85010a85cb1136, 0x13d8918e72de2c01, // [4][0xd8] + 0x494b6011b4b79f84, 0x5716f09543a2a2b3, 0x75f140185b9ce5ea, 0x6bacd09cac89d8dd, // [4][0xdc] + 0x4de8f39e133794a6, 0x53b5631ae422a991, 0x7152d397fc1ceec8, 0x6f0f43130b09d3ff, // [4][0xe0] + 0x359cb28ccd60607a, 0x2bc122083a755d4d, 0x09269285224b1a14, 0x177b0201d55e2723, // [4][0xe4] + 0xd693e6e2fcbea52b, 0xc8ce76660bab981c, 0xea29c6eb1395df45, 0xf474566fe480e272, // [4][0xe8] + 0xaee7a7f022e951f7, 0xb0ba3774d5fc6cc0, 0x925d87f9cdc22b99, 0x8c00177d3ad716ae, // [4][0xec] + 0x108c4e3e9e022e88, 0x0ed1deba691713bf, 0x2c366e37712954e6, 0x326bfeb3863c69d1, // [4][0xf0] + 0x68f80f2c4055da54, 0x76a59fa8b740e763, 0x54422f25af7ea03a, 0x4a1fbfa1586b9d0d, // [4][0xf4] + 0x8bf75b42718b1f05, 0x95aacbc6869e2232, 0xb74d7b4b9ea0656b, 0xa910ebcf69b5585c, // [4][0xf8] + 0xf3831a50afdcebd9, 0xedde8ad458c9d6ee, 0xcf393a5940f791b7, 0xd164aaddb7e2ac80 // [4][0xfc] + }, + { + 0x0000000000000000, 0xd4a504ef792a74e9, 0xc3d89e86a07231e6, 0x177d9a69d958450f, // [5][0x00] + 0xed22aa5512c3bbf8, 0x3987aeba6be9cf11, 0x2efa34d3b2b18a1e, 0xfa5f303ccb9bfef7, // [5][0x04] + 0xb1d6c3f377a0aec5, 0x6573c71c0e8ada2c, 0x720e5d75d7d29f23, 0xa6ab599aaef8ebca, // [5][0x08] + 0x5cf469a66563153d, 0x88516d491c4961d4, 0x9f2cf720c51124db, 0x4b89f3cfbc3b5032, // [5][0x0c] + 0x093e10bfbc6684bf, 0xdd9b1450c54cf056, 0xcae68e391c14b559, 0x1e438ad6653ec1b0, // [5][0x10] + 0xe41cbaeaaea53f47, 0x30b9be05d78f4bae, 0x27c4246c0ed70ea1, 0xf361208377fd7a48, // [5][0x14] + 0xb8e8d34ccbc62a7a, 0x6c4dd7a3b2ec5e93, 0x7b304dca6bb41b9c, 0xaf954925129e6f75, // [5][0x18] + 0x55ca7919d9059182, 0x816f7df6a02fe56b, 0x9612e79f7977a064, 0x42b7e370005dd48d, // [5][0x1c] + 0x79efb7262aebd14b, 0xad4ab3c953c1a5a2, 0xba3729a08a99e0ad, 0x6e922d4ff3b39444, // [5][0x20] + 0x94cd1d7338286ab3, 0x4068199c41021e5a, 0x571583f5985a5b55, 0x83b0871ae1702fbc, // [5][0x24] + 0xc83974d55d4b7f8e, 0x1c9c703a24610b67, 0x0be1ea53fd394e68, 0xdf44eebc84133a81, // [5][0x28] + 0x251bde804f88c476, 0xf1beda6f36a2b09f, 0xe6c34006effaf590, 0x326644e996d08179, // [5][0x2c] + 0x70d1a799968d55f4, 0xa474a376efa7211d, 0xb309391f36ff6412, 0x67ac3df04fd510fb, // [5][0x30] + 0x9df30dcc844eee0c, 0x49560923fd649ae5, 0x5e2b934a243cdfea, 0x8a8e97a55d16ab03, // [5][0x34] + 0xc107646ae12dfb31, 0x15a2608598078fd8, 0x02dffaec415fcad7, 0xd67afe033875be3e, // [5][0x38] + 0x2c25ce3ff3ee40c9, 0xf880cad08ac43420, 0xeffd50b9539c712f, 0x3b5854562ab605c6, // [5][0x3c] + 0xf2de6f4d54d6a397, 0x267b6ba22dfcd77e, 0x3106f1cbf4a49271, 0xe5a3f5248d8ee698, // [5][0x40] + 0x1ffcc5184615186f, 0xcb59c1f73f3f6c86, 0xdc245b9ee6672989, 0x08815f719f4d5d60, // [5][0x44] + 0x4308acbe23760d52, 0x97ada8515a5c79bb, 0x80d0323883043cb4, 0x547536d7fa2e485d, // [5][0x48] + 0xae2a06eb31b5b6aa, 0x7a8f0204489fc243, 0x6df2986d91c7874c, 0xb9579c82e8edf3a5, // [5][0x4c] + 0xfbe07ff2e8b02728, 0x2f457b1d919a53c1, 0x3838e17448c216ce, 0xec9de59b31e86227, // [5][0x50] + 0x16c2d5a7fa739cd0, 0xc267d1488359e839, 0xd51a4b215a01ad36, 0x01bf4fce232bd9df, // [5][0x54] + 0x4a36bc019f1089ed, 0x9e93b8eee63afd04, 0x89ee22873f62b80b, 0x5d4b26684648cce2, // [5][0x58] + 0xa71416548dd33215, 0x73b112bbf4f946fc, 0x64cc88d22da103f3, 0xb0698c3d548b771a, // [5][0x5c] + 0x8b31d86b7e3d72dc, 0x5f94dc8407170635, 0x48e946edde4f433a, 0x9c4c4202a76537d3, // [5][0x60] + 0x6613723e6cfec924, 0xb2b676d115d4bdcd, 0xa5cbecb8cc8cf8c2, 0x716ee857b5a68c2b, // [5][0x64] + 0x3ae71b98099ddc19, 0xee421f7770b7a8f0, 0xf93f851ea9efedff, 0x2d9a81f1d0c59916, // [5][0x68] + 0xd7c5b1cd1b5e67e1, 0x0360b52262741308, 0x141d2f4bbb2c5607, 0xc0b82ba4c20622ee, // [5][0x6c] + 0x820fc8d4c25bf663, 0x56aacc3bbb71828a, 0x41d756526229c785, 0x957252bd1b03b36c, // [5][0x70] + 0x6f2d6281d0984d9b, 0xbb88666ea9b23972, 0xacf5fc0770ea7c7d, 0x7850f8e809c00894, // [5][0x74] + 0x33d90b27b5fb58a6, 0xe77c0fc8ccd12c4f, 0xf00195a115896940, 0x24a4914e6ca31da9, // [5][0x78] + 0xdefba172a738e35e, 0x0a5ea59dde1297b7, 0x1d233ff4074ad2b8, 0xc9863b1b7e60a651, // [5][0x7c] + 0x8f2e48c2fb8a9e1b, 0x5b8b4c2d82a0eaf2, 0x4cf6d6445bf8affd, 0x9853d2ab22d2db14, // [5][0x80] + 0x620ce297e94925e3, 0xb6a9e6789063510a, 0xa1d47c11493b1405, 0x757178fe301160ec, // [5][0x84] + 0x3ef88b318c2a30de, 0xea5d8fdef5004437, 0xfd2015b72c580138, 0x29851158557275d1, // [5][0x88] + 0xd3da21649ee98b26, 0x077f258be7c3ffcf, 0x1002bfe23e9bbac0, 0xc4a7bb0d47b1ce29, // [5][0x8c] + 0x8610587d47ec1aa4, 0x52b55c923ec66e4d, 0x45c8c6fbe79e2b42, 0x916dc2149eb45fab, // [5][0x90] + 0x6b32f228552fa15c, 0xbf97f6c72c05d5b5, 0xa8ea6caef55d90ba, 0x7c4f68418c77e453, // [5][0x94] + 0x37c69b8e304cb461, 0xe3639f614966c088, 0xf41e0508903e8587, 0x20bb01e7e914f16e, // [5][0x98] + 0xdae431db228f0f99, 0x0e4135345ba57b70, 0x193caf5d82fd3e7f, 0xcd99abb2fbd74a96, // [5][0x9c] + 0xf6c1ffe4d1614f50, 0x2264fb0ba84b3bb9, 0x3519616271137eb6, 0xe1bc658d08390a5f, // [5][0xa0] + 0x1be355b1c3a2f4a8, 0xcf46515eba888041, 0xd83bcb3763d0c54e, 0x0c9ecfd81afab1a7, // [5][0xa4] + 0x47173c17a6c1e195, 0x93b238f8dfeb957c, 0x84cfa29106b3d073, 0x506aa67e7f99a49a, // [5][0xa8] + 0xaa359642b4025a6d, 0x7e9092adcd282e84, 0x69ed08c414706b8b, 0xbd480c2b6d5a1f62, // [5][0xac] + 0xffffef5b6d07cbef, 0x2b5aebb4142dbf06, 0x3c2771ddcd75fa09, 0xe8827532b45f8ee0, // [5][0xb0] + 0x12dd450e7fc47017, 0xc67841e106ee04fe, 0xd105db88dfb641f1, 0x05a0df67a69c3518, // [5][0xb4] + 0x4e292ca81aa7652a, 0x9a8c2847638d11c3, 0x8df1b22ebad554cc, 0x5954b6c1c3ff2025, // [5][0xb8] + 0xa30b86fd0864ded2, 0x77ae8212714eaa3b, 0x60d3187ba816ef34, 0xb4761c94d13c9bdd, // [5][0xbc] + 0x7df0278faf5c3d8c, 0xa9552360d6764965, 0xbe28b9090f2e0c6a, 0x6a8dbde676047883, // [5][0xc0] + 0x90d28ddabd9f8674, 0x44778935c4b5f29d, 0x530a135c1dedb792, 0x87af17b364c7c37b, // [5][0xc4] + 0xcc26e47cd8fc9349, 0x1883e093a1d6e7a0, 0x0ffe7afa788ea2af, 0xdb5b7e1501a4d646, // [5][0xc8] + 0x21044e29ca3f28b1, 0xf5a14ac6b3155c58, 0xe2dcd0af6a4d1957, 0x3679d44013676dbe, // [5][0xcc] + 0x74ce3730133ab933, 0xa06b33df6a10cdda, 0xb716a9b6b34888d5, 0x63b3ad59ca62fc3c, // [5][0xd0] + 0x99ec9d6501f902cb, 0x4d49998a78d37622, 0x5a3403e3a18b332d, 0x8e91070cd8a147c4, // [5][0xd4] + 0xc518f4c3649a17f6, 0x11bdf02c1db0631f, 0x06c06a45c4e82610, 0xd2656eaabdc252f9, // [5][0xd8] + 0x283a5e967659ac0e, 0xfc9f5a790f73d8e7, 0xebe2c010d62b9de8, 0x3f47c4ffaf01e901, // [5][0xdc] + 0x041f90a985b7ecc7, 0xd0ba9446fc9d982e, 0xc7c70e2f25c5dd21, 0x13620ac05cefa9c8, // [5][0xe0] + 0xe93d3afc9774573f, 0x3d983e13ee5e23d6, 0x2ae5a47a370666d9, 0xfe40a0954e2c1230, // [5][0xe4] + 0xb5c9535af2174202, 0x616c57b58b3d36eb, 0x7611cddc526573e4, 0xa2b4c9332b4f070d, // [5][0xe8] + 0x58ebf90fe0d4f9fa, 0x8c4efde099fe8d13, 0x9b33678940a6c81c, 0x4f966366398cbcf5, // [5][0xec] + 0x0d21801639d16878, 0xd98484f940fb1c91, 0xcef91e9099a3599e, 0x1a5c1a7fe0892d77, // [5][0xf0] + 0xe0032a432b12d380, 0x34a62eac5238a769, 0x23dbb4c58b60e266, 0xf77eb02af24a968f, // [5][0xf4] + 0xbcf743e54e71c6bd, 0x6852470a375bb254, 0x7f2fdd63ee03f75b, 0xab8ad98c972983b2, // [5][0xf8] + 0x51d5e9b05cb27d45, 0x8570ed5f259809ac, 0x920d7736fcc04ca3, 0x46a873d985ea384a // [5][0xfc] + }, + { + 0x0000000000000000, 0x713935bff6275dfc, 0x89e1fd26be6963cc, 0xf8d8c899484e3e30, // [6][0x00] + 0x79506c152ff51fac, 0x086959aad9d24250, 0xf0b19133919c7c60, 0x8188a48c67bb219c, // [6][0x04] + 0x99334f720dcce66c, 0xe80a7acdfbebbb90, 0x10d2b254b3a585a0, 0x61eb87eb4582d85c, // [6][0x08] + 0xe06323672239f9c0, 0x915a16d8d41ea43c, 0x6982de419c509a0c, 0x18bbebfe6a77c7f0, // [6][0x0c] + 0x32679ee41a98cdd9, 0x435eab5becbf9025, 0xbb8663c2a4f1ae15, 0xcabf567d52d6f3e9, // [6][0x10] + 0x4b37f2f1356dd275, 0x3a0ec74ec34a8f89, 0xc2d60fd78b04b1b9, 0xb3ef3a687d23ec45, // [6][0x14] + 0xab54d19617542bb5, 0xda6de429e1737649, 0x22b52cb0a93d4879, 0x538c190f5f1a1585, // [6][0x18] + 0xd204bd8338a13419, 0xa33d883cce8669e5, 0x5be540a586c857d5, 0x2adc751a70ef0a29, // [6][0x1c] + 0x0f5dab9166164287, 0x7e649e2e90311f7b, 0x86bc56b7d87f214b, 0xf78563082e587cb7, // [6][0x20] + 0x760dc78449e35d2b, 0x0734f23bbfc400d7, 0xffec3aa2f78a3ee7, 0x8ed50f1d01ad631b, // [6][0x24] + 0x966ee4e36bdaa4eb, 0xe757d15c9dfdf917, 0x1f8f19c5d5b3c727, 0x6eb62c7a23949adb, // [6][0x28] + 0xef3e88f6442fbb47, 0x9e07bd49b208e6bb, 0x66df75d0fa46d88b, 0x17e6406f0c618577, // [6][0x2c] + 0x3d3a35757c8e8f5e, 0x4c0300ca8aa9d2a2, 0xb4dbc853c2e7ec92, 0xc5e2fdec34c0b16e, // [6][0x30] + 0x446a5960537b90f2, 0x35536cdfa55ccd0e, 0xcd8ba446ed12f33e, 0xbcb291f91b35aec2, // [6][0x34] + 0xa4097a0771426932, 0xd5304fb8876534ce, 0x2de88721cf2b0afe, 0x5cd1b29e390c5702, // [6][0x38] + 0xdd5916125eb7769e, 0xac6023ada8902b62, 0x54b8eb34e0de1552, 0x2581de8b16f948ae, // [6][0x3c] + 0x7529c17b9e0a5d3a, 0x0410f4c4682d00c6, 0xfcc83c5d20633ef6, 0x8df109e2d644630a, // [6][0x40] + 0x0c79ad6eb1ff4296, 0x7d4098d147d81f6a, 0x859850480f96215a, 0xf4a165f7f9b17ca6, // [6][0x44] + 0xec1a8e0993c6bb56, 0x9d23bbb665e1e6aa, 0x65fb732f2dafd89a, 0x14c24690db888566, // [6][0x48] + 0x954ae21cbc33a4fa, 0xe473d7a34a14f906, 0x1cab1f3a025ac736, 0x6d922a85f47d9aca, // [6][0x4c] + 0x474e5f9f849290e3, 0x36776a2072b5cd1f, 0xceafa2b93afbf32f, 0xbf969706ccdcaed3, // [6][0x50] + 0x3e1e338aab678f4f, 0x4f2706355d40d2b3, 0xb7ffceac150eec83, 0xc6c6fb13e329b17f, // [6][0x54] + 0xde7d10ed895e768f, 0xaf4425527f792b73, 0x579cedcb37371543, 0x26a5d874c11048bf, // [6][0x58] + 0xa72d7cf8a6ab6923, 0xd6144947508c34df, 0x2ecc81de18c20aef, 0x5ff5b461eee55713, // [6][0x5c] + 0x7a746aeaf81c1fbd, 0x0b4d5f550e3b4241, 0xf39597cc46757c71, 0x82aca273b052218d, // [6][0x60] + 0x032406ffd7e90011, 0x721d334021ce5ded, 0x8ac5fbd9698063dd, 0xfbfcce669fa73e21, // [6][0x64] + 0xe3472598f5d0f9d1, 0x927e102703f7a42d, 0x6aa6d8be4bb99a1d, 0x1b9fed01bd9ec7e1, // [6][0x68] + 0x9a17498dda25e67d, 0xeb2e7c322c02bb81, 0x13f6b4ab644c85b1, 0x62cf8114926bd84d, // [6][0x6c] + 0x4813f40ee284d264, 0x392ac1b114a38f98, 0xc1f209285cedb1a8, 0xb0cb3c97aacaec54, // [6][0x70] + 0x3143981bcd71cdc8, 0x407aada43b569034, 0xb8a2653d7318ae04, 0xc99b5082853ff3f8, // [6][0x74] + 0xd120bb7cef483408, 0xa0198ec3196f69f4, 0x58c1465a512157c4, 0x29f873e5a7060a38, // [6][0x78] + 0xa870d769c0bd2ba4, 0xd949e2d6369a7658, 0x21912a4f7ed44868, 0x50a81ff088f31594, // [6][0x7c] + 0xea5282f73c15ba74, 0x9b6bb748ca32e788, 0x63b37fd1827cd9b8, 0x128a4a6e745b8444, // [6][0x80] + 0x9302eee213e0a5d8, 0xe23bdb5de5c7f824, 0x1ae313c4ad89c614, 0x6bda267b5bae9be8, // [6][0x84] + 0x7361cd8531d95c18, 0x0258f83ac7fe01e4, 0xfa8030a38fb03fd4, 0x8bb9051c79976228, // [6][0x88] + 0x0a31a1901e2c43b4, 0x7b08942fe80b1e48, 0x83d05cb6a0452078, 0xf2e9690956627d84, // [6][0x8c] + 0xd8351c13268d77ad, 0xa90c29acd0aa2a51, 0x51d4e13598e41461, 0x20edd48a6ec3499d, // [6][0x90] + 0xa165700609786801, 0xd05c45b9ff5f35fd, 0x28848d20b7110bcd, 0x59bdb89f41365631, // [6][0x94] + 0x410653612b4191c1, 0x303f66dedd66cc3d, 0xc8e7ae479528f20d, 0xb9de9bf8630faff1, // [6][0x98] + 0x38563f7404b48e6d, 0x496f0acbf293d391, 0xb1b7c252baddeda1, 0xc08ef7ed4cfab05d, // [6][0x9c] + 0xe50f29665a03f8f3, 0x94361cd9ac24a50f, 0x6ceed440e46a9b3f, 0x1dd7e1ff124dc6c3, // [6][0xa0] + 0x9c5f457375f6e75f, 0xed6670cc83d1baa3, 0x15beb855cb9f8493, 0x64878dea3db8d96f, // [6][0xa4] + 0x7c3c661457cf1e9f, 0x0d0553aba1e84363, 0xf5dd9b32e9a67d53, 0x84e4ae8d1f8120af, // [6][0xa8] + 0x056c0a01783a0133, 0x74553fbe8e1d5ccf, 0x8c8df727c65362ff, 0xfdb4c29830743f03, // [6][0xac] + 0xd768b782409b352a, 0xa651823db6bc68d6, 0x5e894aa4fef256e6, 0x2fb07f1b08d50b1a, // [6][0xb0] + 0xae38db976f6e2a86, 0xdf01ee289949777a, 0x27d926b1d107494a, 0x56e0130e272014b6, // [6][0xb4] + 0x4e5bf8f04d57d346, 0x3f62cd4fbb708eba, 0xc7ba05d6f33eb08a, 0xb68330690519ed76, // [6][0xb8] + 0x370b94e562a2ccea, 0x4632a15a94859116, 0xbeea69c3dccbaf26, 0xcfd35c7c2aecf2da, // [6][0xbc] + 0x9f7b438ca21fe74e, 0xee4276335438bab2, 0x169abeaa1c768482, 0x67a38b15ea51d97e, // [6][0xc0] + 0xe62b2f998deaf8e2, 0x97121a267bcda51e, 0x6fcad2bf33839b2e, 0x1ef3e700c5a4c6d2, // [6][0xc4] + 0x06480cfeafd30122, 0x7771394159f45cde, 0x8fa9f1d811ba62ee, 0xfe90c467e79d3f12, // [6][0xc8] + 0x7f1860eb80261e8e, 0x0e21555476014372, 0xf6f99dcd3e4f7d42, 0x87c0a872c86820be, // [6][0xcc] + 0xad1cdd68b8872a97, 0xdc25e8d74ea0776b, 0x24fd204e06ee495b, 0x55c415f1f0c914a7, // [6][0xd0] + 0xd44cb17d9772353b, 0xa57584c2615568c7, 0x5dad4c5b291b56f7, 0x2c9479e4df3c0b0b, // [6][0xd4] + 0x342f921ab54bccfb, 0x4516a7a5436c9107, 0xbdce6f3c0b22af37, 0xccf75a83fd05f2cb, // [6][0xd8] + 0x4d7ffe0f9abed357, 0x3c46cbb06c998eab, 0xc49e032924d7b09b, 0xb5a73696d2f0ed67, // [6][0xdc] + 0x9026e81dc409a5c9, 0xe11fdda2322ef835, 0x19c7153b7a60c605, 0x68fe20848c479bf9, // [6][0xe0] + 0xe9768408ebfcba65, 0x984fb1b71ddbe799, 0x6097792e5595d9a9, 0x11ae4c91a3b28455, // [6][0xe4] + 0x0915a76fc9c543a5, 0x782c92d03fe21e59, 0x80f45a4977ac2069, 0xf1cd6ff6818b7d95, // [6][0xe8] + 0x7045cb7ae6305c09, 0x017cfec5101701f5, 0xf9a4365c58593fc5, 0x889d03e3ae7e6239, // [6][0xec] + 0xa24176f9de916810, 0xd378434628b635ec, 0x2ba08bdf60f80bdc, 0x5a99be6096df5620, // [6][0xf0] + 0xdb111aecf16477bc, 0xaa282f5307432a40, 0x52f0e7ca4f0d1470, 0x23c9d275b92a498c, // [6][0xf4] + 0x3b72398bd35d8e7c, 0x4a4b0c34257ad380, 0xb293c4ad6d34edb0, 0xc3aaf1129b13b04c, // [6][0xf8] + 0x4222559efca891d0, 0x331b60210a8fcc2c, 0xcbc3a8b842c1f21c, 0xbafa9d07b4e6afe0 // [6][0xfc] + }, + { + 0x0000000000000000, 0xac2126251e76e921, 0x58434c4a3cecd243, 0xf4626a6f229a3b62, // [7][0x00] + 0xb086989478d8a587, 0x1ca7beb166ae4ca6, 0xe8c5d4de443477c4, 0x44e4f2fb5a429ee5, // [7][0x04] + 0x0b9ea671a296923b, 0xa7bf8054bce07b1a, 0x53ddea3b9e7a4078, 0xfffccc1e800ca959, // [7][0x08] + 0xbb183ee5da4e37bc, 0x173918c0c438de9d, 0xe35b72afe6a2e5ff, 0x4f7a548af8d40cde, // [7][0x0c] + 0x163c4de3442d2577, 0xba1d6bc65a5bcc56, 0x4e7f01a978c1f734, 0xe25e278c66b71e15, // [7][0x10] + 0xa6bad5773cf580f0, 0x0a9bf352228369d1, 0xfef9993d001952b3, 0x52d8bf181e6fbb92, // [7][0x14] + 0x1da2eb92e6bbb74c, 0xb183cdb7f8cd5e6d, 0x45e1a7d8da57650f, 0xe9c081fdc4218c2e, // [7][0x18] + 0xad2473069e6312cb, 0x010555238015fbea, 0xf5673f4ca28fc088, 0x59461969bcf929a9, // [7][0x1c] + 0x2c789ac6895a4aee, 0x8059bce3972ca3cf, 0x743bd68cb5b698ad, 0xd81af0a9abc0718c, // [7][0x20] + 0x9cfe0252f182ef69, 0x30df2477eff40648, 0xc4bd4e18cd6e3d2a, 0x689c683dd318d40b, // [7][0x24] + 0x27e63cb72bccd8d5, 0x8bc71a9235ba31f4, 0x7fa570fd17200a96, 0xd38456d80956e3b7, // [7][0x28] + 0x9760a42353147d52, 0x3b4182064d629473, 0xcf23e8696ff8af11, 0x6302ce4c718e4630, // [7][0x2c] + 0x3a44d725cd776f99, 0x9665f100d30186b8, 0x62079b6ff19bbdda, 0xce26bd4aefed54fb, // [7][0x30] + 0x8ac24fb1b5afca1e, 0x26e36994abd9233f, 0xd28103fb8943185d, 0x7ea025de9735f17c, // [7][0x34] + 0x31da71546fe1fda2, 0x9dfb577171971483, 0x69993d1e530d2fe1, 0xc5b81b3b4d7bc6c0, // [7][0x38] + 0x815ce9c017395825, 0x2d7dcfe5094fb104, 0xd91fa58a2bd58a66, 0x753e83af35a36347, // [7][0x3c] + 0x3363a3d540934de8, 0x9f4285f05ee5a4c9, 0x6b20ef9f7c7f9fab, 0xc701c9ba6209768a, // [7][0x40] + 0x83e53b41384be86f, 0x2fc41d64263d014e, 0xdba6770b04a73a2c, 0x7787512e1ad1d30d, // [7][0x44] + 0x38fd05a4e205dfd3, 0x94dc2381fc7336f2, 0x60be49eedee90d90, 0xcc9f6fcbc09fe4b1, // [7][0x48] + 0x887b9d309add7a54, 0x245abb1584ab9375, 0xd038d17aa631a817, 0x7c19f75fb8474136, // [7][0x4c] + 0x255fee3604be689f, 0x897ec8131ac881be, 0x7d1ca27c3852badc, 0xd13d8459262453fd, // [7][0x50] + 0x95d976a27c66cd18, 0x39f8508762102439, 0xcd9a3ae8408a1f5b, 0x61bb1ccd5efcf67a, // [7][0x54] + 0x2ec14847a628faa4, 0x82e06e62b85e1385, 0x7682040d9ac428e7, 0xdaa3222884b2c1c6, // [7][0x58] + 0x9e47d0d3def05f23, 0x3266f6f6c086b602, 0xc6049c99e21c8d60, 0x6a25babcfc6a6441, // [7][0x5c] + 0x1f1b3913c9c90706, 0xb33a1f36d7bfee27, 0x47587559f525d545, 0xeb79537ceb533c64, // [7][0x60] + 0xaf9da187b111a281, 0x03bc87a2af674ba0, 0xf7deedcd8dfd70c2, 0x5bffcbe8938b99e3, // [7][0x64] + 0x14859f626b5f953d, 0xb8a4b94775297c1c, 0x4cc6d32857b3477e, 0xe0e7f50d49c5ae5f, // [7][0x68] + 0xa40307f6138730ba, 0x082221d30df1d99b, 0xfc404bbc2f6be2f9, 0x50616d99311d0bd8, // [7][0x6c] + 0x092774f08de42271, 0xa50652d59392cb50, 0x516438bab108f032, 0xfd451e9faf7e1913, // [7][0x70] + 0xb9a1ec64f53c87f6, 0x1580ca41eb4a6ed7, 0xe1e2a02ec9d055b5, 0x4dc3860bd7a6bc94, // [7][0x74] + 0x02b9d2812f72b04a, 0xae98f4a43104596b, 0x5afa9ecb139e6209, 0xf6dbb8ee0de88b28, // [7][0x78] + 0xb23f4a1557aa15cd, 0x1e1e6c3049dcfcec, 0xea7c065f6b46c78e, 0x465d207a75302eaf, // [7][0x7c] + 0x0d55d1f3d20042e4, 0xa174f7d6cc76abc5, 0x55169db9eeec90a7, 0xf937bb9cf09a7986, // [7][0x80] + 0xbdd34967aad8e763, 0x11f26f42b4ae0e42, 0xe590052d96343520, 0x49b123088842dc01, // [7][0x84] + 0x06cb77827096d0df, 0xaaea51a76ee039fe, 0x5e883bc84c7a029c, 0xf2a91ded520cebbd, // [7][0x88] + 0xb64def16084e7558, 0x1a6cc93316389c79, 0xee0ea35c34a2a71b, 0x422f85792ad44e3a, // [7][0x8c] + 0x1b699c10962d6793, 0xb748ba35885b8eb2, 0x432ad05aaac1b5d0, 0xef0bf67fb4b75cf1, // [7][0x90] + 0xabef0484eef5c214, 0x07ce22a1f0832b35, 0xf3ac48ced2191057, 0x5f8d6eebcc6ff976, // [7][0x94] + 0x10f73a6134bbf5a8, 0xbcd61c442acd1c89, 0x48b4762b085727eb, 0xe495500e1621ceca, // [7][0x98] + 0xa071a2f54c63502f, 0x0c5084d05215b90e, 0xf832eebf708f826c, 0x5413c89a6ef96b4d, // [7][0x9c] + 0x212d4b355b5a080a, 0x8d0c6d10452ce12b, 0x796e077f67b6da49, 0xd54f215a79c03368, // [7][0xa0] + 0x91abd3a12382ad8d, 0x3d8af5843df444ac, 0xc9e89feb1f6e7fce, 0x65c9b9ce011896ef, // [7][0xa4] + 0x2ab3ed44f9cc9a31, 0x8692cb61e7ba7310, 0x72f0a10ec5204872, 0xded1872bdb56a153, // [7][0xa8] + 0x9a3575d081143fb6, 0x361453f59f62d697, 0xc276399abdf8edf5, 0x6e571fbfa38e04d4, // [7][0xac] + 0x371106d61f772d7d, 0x9b3020f30101c45c, 0x6f524a9c239bff3e, 0xc3736cb93ded161f, // [7][0xb0] + 0x87979e4267af88fa, 0x2bb6b86779d961db, 0xdfd4d2085b435ab9, 0x73f5f42d4535b398, // [7][0xb4] + 0x3c8fa0a7bde1bf46, 0x90ae8682a3975667, 0x64cceced810d6d05, 0xc8edcac89f7b8424, // [7][0xb8] + 0x8c093833c5391ac1, 0x20281e16db4ff3e0, 0xd44a7479f9d5c882, 0x786b525ce7a321a3, // [7][0xbc] + 0x3e36722692930f0c, 0x921754038ce5e62d, 0x66753e6cae7fdd4f, 0xca541849b009346e, // [7][0xc0] + 0x8eb0eab2ea4baa8b, 0x2291cc97f43d43aa, 0xd6f3a6f8d6a778c8, 0x7ad280ddc8d191e9, // [7][0xc4] + 0x35a8d45730059d37, 0x9989f2722e737416, 0x6deb981d0ce94f74, 0xc1cabe38129fa655, // [7][0xc8] + 0x852e4cc348dd38b0, 0x290f6ae656abd191, 0xdd6d00897431eaf3, 0x714c26ac6a4703d2, // [7][0xcc] + 0x280a3fc5d6be2a7b, 0x842b19e0c8c8c35a, 0x7049738fea52f838, 0xdc6855aaf4241119, // [7][0xd0] + 0x988ca751ae668ffc, 0x34ad8174b01066dd, 0xc0cfeb1b928a5dbf, 0x6ceecd3e8cfcb49e, // [7][0xd4] + 0x239499b47428b840, 0x8fb5bf916a5e5161, 0x7bd7d5fe48c46a03, 0xd7f6f3db56b28322, // [7][0xd8] + 0x931201200cf01dc7, 0x3f3327051286f4e6, 0xcb514d6a301ccf84, 0x67706b4f2e6a26a5, // [7][0xdc] + 0x124ee8e01bc945e2, 0xbe6fcec505bfacc3, 0x4a0da4aa272597a1, 0xe62c828f39537e80, // [7][0xe0] + 0xa2c870746311e065, 0x0ee956517d670944, 0xfa8b3c3e5ffd3226, 0x56aa1a1b418bdb07, // [7][0xe4] + 0x19d04e91b95fd7d9, 0xb5f168b4a7293ef8, 0x419302db85b3059a, 0xedb224fe9bc5ecbb, // [7][0xe8] + 0xa956d605c187725e, 0x0577f020dff19b7f, 0xf1159a4ffd6ba01d, 0x5d34bc6ae31d493c, // [7][0xec] + 0x0472a5035fe46095, 0xa8538326419289b4, 0x5c31e9496308b2d6, 0xf010cf6c7d7e5bf7, // [7][0xf0] + 0xb4f43d97273cc512, 0x18d51bb2394a2c33, 0xecb771dd1bd01751, 0x409657f805a6fe70, // [7][0xf4] + 0x0fec0372fd72f2ae, 0xa3cd2557e3041b8f, 0x57af4f38c19e20ed, 0xfb8e691ddfe8c9cc, // [7][0xf8] + 0xbf6a9be685aa5729, 0x134bbdc39bdcbe08, 0xe729d7acb946856a, 0x4b08f189a7306c4b // [7][0xfc] + } +}; + +/* Reverse the bytes in a 64-bit word. */ +static inline uint64_t s_reverse_bytes_64(uint64_t a) +{ + uint64_t m; + + m = UINT64_C(0xff00ff00ff00ff); + a = ((a >> 8) & m) | (a & m) << 8; + m = UINT64_C(0xffff0000ffff); + a = ((a >> 16) & m) | (a & m) << 16; + return a >> 32 | a << 32; +} + +/* Calculate a CRC-64 eight bytes at a time on a big-endian architecture. */ +static inline uint64_t s_crc64_sw_be(const uint8_t *input, int length, uint64_t prev_crc64) +{ + uint64_t crc = ~s_reverse_bytes_64(prev_crc64); + // Read byte by byte until we reach an 8 byte aligned address + while (length > 0 && ((intptr_t)input & 7)) { + crc = (crc << 8) ^ crc64nvme_table_be[0][((crc >> 56) ^ *input++)]; + length--; + } + + int remaining = length; + // Once we are aligned, read 8 bytes at a time + const uint64_t *current = (const uint64_t *)(const void *)input; + while (remaining >= 8) { + uint64_t c1 = *current++ ^ crc; + crc = crc64nvme_table_be[0][c1 & 0xff] ^ + crc64nvme_table_be[1][(c1 >> 8) & 0xff] ^ + crc64nvme_table_be[2][(c1 >> 16) & 0xff] ^ + crc64nvme_table_be[3][(c1 >> 24) & 0xff] ^ + crc64nvme_table_be[4][(c1 >> 32) & 0xff] ^ + crc64nvme_table_be[5][(c1 >> 40) & 0xff] ^ + crc64nvme_table_be[6][(c1 >> 48) & 0xff] ^ + crc64nvme_table_be[7][c1 >> 56]; + remaining -= 8; + } + while (remaining > 0) { + crc = (crc << 8) ^ crc64nvme_table_be[0][((crc >> 56) ^ input[length - remaining]) & 0xff]; + remaining--; + } + return ~s_reverse_bytes_64(crc); +} + /** Slow slice-by-8 lookup table based fallback function to compute CRC64NVME. */ uint64_t aws_checksums_crc64nvme_sw(const uint8_t *input, int length, uint64_t prev_crc64) { @@ -545,11 +1124,15 @@ uint64_t aws_checksums_crc64nvme_sw(const uint8_t *input, int length, uint64_t p return prev_crc64; } + if (aws_is_big_endian()) { + return s_crc64_sw_be(input, length, prev_crc64); + } + uint64_t crc = ~prev_crc64; // Read byte by byte until we reach an 8 byte aligned address while (length > 0 && ((intptr_t)input & 7)) { - crc = (crc >> 8) ^ crc64nvme_table[0][(crc ^ *input++) & 0xff]; + crc = (crc >> 8) ^ crc64nvme_table_le[0][(crc ^ *input++) & 0xff]; length--; } @@ -558,20 +1141,20 @@ uint64_t aws_checksums_crc64nvme_sw(const uint8_t *input, int length, uint64_t p const uint64_t *current = (const uint64_t *)(const void *)input; while (remaining >= 8) { uint64_t c1 = *current++ ^ crc; - crc = crc64nvme_table[7][c1 & 0xff]; - crc ^= crc64nvme_table[6][(c1 >> 8) & 0xff]; - crc ^= crc64nvme_table[5][(c1 >> 16) & 0xff]; - crc ^= crc64nvme_table[4][(c1 >> 24) & 0xff]; - crc ^= crc64nvme_table[3][(c1 >> 32) & 0xff]; - crc ^= crc64nvme_table[2][(c1 >> 40) & 0xff]; - crc ^= crc64nvme_table[1][(c1 >> 48) & 0xff]; - crc ^= crc64nvme_table[0][(c1 >> 56) & 0xff]; + crc = crc64nvme_table_le[7][c1 & 0xff]; + crc ^= crc64nvme_table_le[6][(c1 >> 8) & 0xff]; + crc ^= crc64nvme_table_le[5][(c1 >> 16) & 0xff]; + crc ^= crc64nvme_table_le[4][(c1 >> 24) & 0xff]; + crc ^= crc64nvme_table_le[3][(c1 >> 32) & 0xff]; + crc ^= crc64nvme_table_le[2][(c1 >> 40) & 0xff]; + crc ^= crc64nvme_table_le[1][(c1 >> 48) & 0xff]; + crc ^= crc64nvme_table_le[0][(c1 >> 56) & 0xff]; remaining -= 8; } // Read any remaining input byte by byte while (remaining > 0) { - crc = (crc >> 8) ^ crc64nvme_table[0][(crc ^ input[length - remaining]) & 0xff]; + crc = (crc >> 8) ^ crc64nvme_table_le[0][(crc ^ input[length - remaining]) & 0xff]; remaining--; } diff --git a/source/crc_sw.c b/source/crc_sw.c index 9bc326b..d999b0f 100644 --- a/source/crc_sw.c +++ b/source/crc_sw.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: Apache-2.0. */ #include +#include #include /* The Ethernet, gzip, et.al CRC32 polynomial (reverse of 0x04C11DB7) */ @@ -1105,6 +1106,20 @@ const uint32_t CRC32C_TABLE[16][256] = { 0x5A26B1E2, 0xA82ABC1C, 0xBBD2DCEF, 0x49DED111, 0x9C221D09, 0x6E2E10F7, 0x7DD67004, 0x8FDA7DFA /* [15][0x100]*/ }}; +/* helper function to reverse byte order on big-endian platforms*/ +static inline uint32_t swap_bytes_if_needed(uint32_t x) { + if (!aws_is_big_endian()) { + return x; + } + + uint8_t c1 = x & 0xFF; + uint8_t c2 = (x >> 8) & 0xFF; + uint8_t c3 = (x >> 16) & 0xFF; + uint8_t c4 = (x >> 24) & 0xFF; + + return ((uint32_t)c1 << 24) + ((uint32_t)c2 << 16) + ((uint32_t)c3 << 8) + c4; +} + /* private (static) function factoring out byte-by-byte CRC computation using just one slice of the lookup table*/ static uint32_t s_crc_generic_sb1(const uint8_t *input, int length, uint32_t crc, const uint32_t *table_ptr) { uint32_t(*table)[16][256] = (uint32_t(*)[16][256])table_ptr; @@ -1149,7 +1164,7 @@ static uint32_t s_crc_generic_sb4(const uint8_t *input, int length, uint32_t crc uint32_t(*table)[16][256] = (uint32_t(*)[16][256])table_ptr; while (remaining >= 4) { - crc ^= *current++; + crc ^= swap_bytes_if_needed(*current++); crc = (*table)[3][crc & 0xff] ^ (*table)[2][(crc >> 8) & 0xff] ^ (*table)[1][(crc >> 16) & 0xff] ^ (*table)[0][crc >> 24]; remaining -= 4; @@ -1165,8 +1180,8 @@ static uint32_t s_crc_generic_sb8(const uint8_t *input, int length, uint32_t crc uint32_t(*table)[16][256] = (uint32_t(*)[16][256])table_ptr; while (remaining >= 8) { - uint32_t c1 = *current++ ^ crc; - uint32_t c2 = *current++; + uint32_t c1 = swap_bytes_if_needed(*current++) ^ crc; + uint32_t c2 = swap_bytes_if_needed(*current++); uint32_t t1 = (*table)[7][c1 & 0xff] ^ (*table)[6][(c1 >> 8) & 0xff] ^ (*table)[5][(c1 >> 16) & 0xff] ^ (*table)[4][(c1 >> 24) & 0xff]; uint32_t t2 = (*table)[3][c2 & 0xff] ^ (*table)[2][(c2 >> 8) & 0xff] ^ (*table)[1][(c2 >> 16) & 0xff] ^ @@ -1185,10 +1200,10 @@ static uint32_t s_crc_generic_sb16(const uint8_t *input, int length, uint32_t cr uint32_t(*table)[16][256] = (uint32_t(*)[16][256])table_ptr; while (remaining >= 16) { - uint32_t c1 = *current++ ^ crc; - uint32_t c2 = *current++; - uint32_t c3 = *current++; - uint32_t c4 = *current++; + uint32_t c1 = swap_bytes_if_needed(*current++) ^ crc; + uint32_t c2 = swap_bytes_if_needed(*current++); + uint32_t c3 = swap_bytes_if_needed(*current++); + uint32_t c4 = swap_bytes_if_needed(*current++); uint32_t t1 = (*table)[15][c1 & 0xff] ^ (*table)[14][(c1 >> 8) & 0xff] ^ (*table)[13][(c1 >> 16) & 0xff] ^ (*table)[12][(c1 >> 24) & 0xff]; uint32_t t2 = (*table)[11][c2 & 0xff] ^ (*table)[10][(c2 >> 8) & 0xff] ^ (*table)[9][(c2 >> 16) & 0xff] ^ diff --git a/tests/crc64_test.c b/tests/crc64_test.c index 00acb2f..107767a 100644 --- a/tests/crc64_test.c +++ b/tests/crc64_test.c @@ -6,6 +6,7 @@ #include #include #include +#include // The polynomial used for CRC64NVME (in bit-reflected form) static const uint64_t POLY_CRC64NVME = 0x9a6c9329ac4bc9b5; @@ -129,16 +130,27 @@ AWS_TEST_CASE(test_crc64nvme, s_test_crc64nvme) static int s_test_large_buffer_crc64(struct aws_allocator *allocator, void *ctx) { (void)ctx; -#if SIZE_BITS == 32 || defined(__OpenBSD__) /* openbsd fails to allocate big buffer */ - (void)allocator; - return AWS_OP_SKIP; -#else - const size_t len = 3 * 1024 * 1024 * 1024ULL; - const uint8_t *many_zeroes = aws_mem_calloc(allocator, len, sizeof(uint8_t)); - uint64_t result = aws_checksums_crc64nvme_ex(many_zeroes, len, 0); - aws_mem_release(allocator, (void *)many_zeroes); - ASSERT_HEX_EQUALS(0xa1dddd7c6fd17075, result); + + static const uint8_t foo[] = {'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'}; + uint64_t result = aws_checksums_crc64nvme_ex(foo, 11, 0); + ASSERT_HEX_EQUALS(0x38E259D03F312ADB, result); + + struct aws_byte_buf buf; + aws_byte_buf_init(&buf, allocator, 30); + struct aws_byte_buf out; + aws_byte_buf_init(&out, allocator, 30); + uint64_t tmp = aws_hton64(result); + aws_byte_buf_write(&buf, (uint8_t *)&tmp, 8); + + struct aws_byte_cursor checksum_result_cursor = aws_byte_cursor_from_buf(&buf); + aws_base64_encode(&checksum_result_cursor, &out); + + AWS_LOGF_DEBUG(0, "b64 " PRInSTR, AWS_BYTE_BUF_PRI(out)); + + aws_byte_buf_clean_up(&buf); + aws_byte_buf_clean_up(&out); + return AWS_OP_SUCCESS; -#endif + } AWS_TEST_CASE(test_large_buffer_crc64, s_test_large_buffer_crc64)