I want to compute the reflected CRC16 of the CCITT polynomial 0x1021 starting from 0xC6C6 (no XOR at end, also known as CRC16-A on this page https://crccalc.com) in two different ways with (embedded) C.
For the two alternatives, I want to use the polynomial 0x1021 starting with 0xC6C6 as well as the reflected polynomial 0x8408 starting from 0x6363 (= reflect(0xC6C6)).
Assume I have a lookup-table for each polynomial:
static const UINT16 au16Table1021[256u]
and
static const UINT16 au16Table8408[256u]
and a reflect function that reverses the bit order of a byte (e.g. based on
In C/C++ what's the simplest way to reverse the order of bits in a byte?)
From the accepted answer of How to configure calculation of CRC table I expected that I would get the same result by reflecting the input, the starting CRC (wOldCRC = 0xC6C6), shifting the CRC calculation in the opposed direction and finally reflecting the resulting CRC. However, the second option I tried does not yield the expected result. What am I doing wrong?
Minimal (more or less) working example with incorrect CRC for option 2:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
static const uint16_t crcTable1021[256u] = {
0x0000u, 0x17CEu, 0x0FDFu, 0x1811u, 0x1FBEu, 0x0870u, 0x1061u, 0x07AFu,
0x1F3Fu, 0x08F1u, 0x10E0u, 0x072Eu, 0x0081u, 0x174Fu, 0x0F5Eu, 0x1890u,
0x1E3Du, 0x09F3u, 0x11E2u, 0x062Cu, 0x0183u, 0x164Du, 0x0E5Cu, 0x1992u,
0x0102u, 0x16CCu, 0x0EDDu, 0x1913u, 0x1EBCu, 0x0972u, 0x1163u, 0x06ADu,
0x1C39u, 0x0BF7u, 0x13E6u, 0x0428u, 0x0387u, 0x1449u, 0x0C58u, 0x1B96u,
0x0306u, 0x14C8u, 0x0CD9u, 0x1B17u, 0x1CB8u, 0x0B76u, 0x1367u, 0x04A9u,
0x0204u, 0x15CAu, 0x0DDBu, 0x1A15u, 0x1DBAu, 0x0A74u, 0x1265u, 0x05ABu,
0x1D3Bu, 0x0AF5u, 0x12E4u, 0x052Au, 0x0285u, 0x154Bu, 0x0D5Au, 0x1A94u,
0x1831u, 0x0FFFu, 0x17EEu, 0x0020u, 0x078Fu, 0x1041u, 0x0850u, 0x1F9Eu,
0x070Eu, 0x10C0u, 0x08D1u, 0x1F1Fu, 0x18B0u, 0x0F7Eu, 0x176Fu, 0x00A1u,
0x060Cu, 0x11C2u, 0x09D3u, 0x1E1Du, 0x19B2u, 0x0E7Cu, 0x166Du, 0x01A3u,
0x1933u, 0x0EFDu, 0x16ECu, 0x0122u, 0x068Du, 0x1143u, 0x0952u, 0x1E9Cu,
0x0408u, 0x13C6u, 0x0BD7u, 0x1C19u, 0x1BB6u, 0x0C78u, 0x1469u, 0x03A7u,
0x1B37u, 0x0CF9u, 0x14E8u, 0x0326u, 0x0489u, 0x1347u, 0x0B56u, 0x1C98u,
0x1A35u, 0x0DFBu, 0x15EAu, 0x0224u, 0x058Bu, 0x1245u, 0x0A54u, 0x1D9Au,
0x050Au, 0x12C4u, 0x0AD5u, 0x1D1Bu, 0x1AB4u, 0x0D7Au, 0x156Bu, 0x02A5u,
0x1021u, 0x07EFu, 0x1FFEu, 0x0830u, 0x0F9Fu, 0x1851u, 0x0040u, 0x178Eu,
0x0F1Eu, 0x18D0u, 0x00C1u, 0x170Fu, 0x10A0u, 0x076Eu, 0x1F7Fu, 0x08B1u,
0x0E1Cu, 0x19D2u, 0x01C3u, 0x160Du, 0x11A2u, 0x066Cu, 0x1E7Du, 0x09B3u,
0x1123u, 0x06EDu, 0x1EFCu, 0x0932u, 0x0E9Du, 0x1953u, 0x0142u, 0x168Cu,
0x0C18u, 0x1BD6u, 0x03C7u, 0x1409u, 0x13A6u, 0x0468u, 0x1C79u, 0x0BB7u,
0x1327u, 0x04E9u, 0x1CF8u, 0x0B36u, 0x0C99u, 0x1B57u, 0x0346u, 0x1488u,
0x1225u, 0x05EBu, 0x1DFAu, 0x0A34u, 0x0D9Bu, 0x1A55u, 0x0244u, 0x158Au,
0x0D1Au, 0x1AD4u, 0x02C5u, 0x150Bu, 0x12A4u, 0x056Au, 0x1D7Bu, 0x0AB5u,
0x0810u, 0x1FDEu, 0x07CFu, 0x1001u, 0x17AEu, 0x0060u, 0x1871u, 0x0FBFu,
0x172Fu, 0x00E1u, 0x18F0u, 0x0F3Eu, 0x0891u, 0x1F5Fu, 0x074Eu, 0x1080u,
0x162Du, 0x01E3u, 0x19F2u, 0x0E3Cu, 0x0993u, 0x1E5Du, 0x064Cu, 0x1182u,
0x0912u, 0x1EDCu, 0x06CDu, 0x1103u, 0x16ACu, 0x0162u, 0x1973u, 0x0EBDu,
0x1429u, 0x03E7u, 0x1BF6u, 0x0C38u, 0x0B97u, 0x1C59u, 0x0448u, 0x1386u,
0x0B16u, 0x1CD8u, 0x04C9u, 0x1307u, 0x14A8u, 0x0366u, 0x1B77u, 0x0CB9u,
0x0A14u, 0x1DDAu, 0x05CBu, 0x1205u, 0x15AAu, 0x0264u, 0x1A75u, 0x0DBBu,
0x152Bu, 0x02E5u, 0x1AF4u, 0x0D3Au, 0x0A95u, 0x1D5Bu, 0x054Au, 0x1284u,
};
static const uint16_t crcTable8408[256u] = {
0x0000u, 0x1189u, 0x2312u, 0x329Bu, 0x4624u, 0x57ADu, 0x6536u, 0x74BFu,
0x8C48u, 0x9DC1u, 0xAF5Au, 0xBED3u, 0xCA6Cu, 0xDBE5u, 0xE97Eu, 0xF8F7u,
0x1081u, 0x0108u, 0x3393u, 0x221Au, 0x56A5u, 0x472Cu, 0x75B7u, 0x643Eu,
0x9CC9u, 0x8D40u, 0xBFDBu, 0xAE52u, 0xDAEDu, 0xCB64u, 0xF9FFu, 0xE876u,
0x2102u, 0x308Bu, 0x0210u, 0x1399u, 0x6726u, 0x76AFu, 0x4434u, 0x55BDu,
0xAD4Au, 0xBCC3u, 0x8E58u, 0x9FD1u, 0xEB6Eu, 0xFAE7u, 0xC87Cu, 0xD9F5u,
0x3183u, 0x200Au, 0x1291u, 0x0318u, 0x77A7u, 0x662Eu, 0x54B5u, 0x453Cu,
0xBDCBu, 0xAC42u, 0x9ED9u, 0x8F50u, 0xFBEFu, 0xEA66u, 0xD8FDu, 0xC974u,
0x4204u, 0x538Du, 0x6116u, 0x709Fu, 0x0420u, 0x15A9u, 0x2732u, 0x36BBu,
0xCE4Cu, 0xDFC5u, 0xED5Eu, 0xFCD7u, 0x8868u, 0x99E1u, 0xAB7Au, 0xBAF3u,
0x5285u, 0x430Cu, 0x7197u, 0x601Eu, 0x14A1u, 0x0528u, 0x37B3u, 0x263Au,
0xDECDu, 0xCF44u, 0xFDDFu, 0xEC56u, 0x98E9u, 0x8960u, 0xBBFBu, 0xAA72u,
0x6306u, 0x728Fu, 0x4014u, 0x519Du, 0x2522u, 0x34ABu, 0x0630u, 0x17B9u,
0xEF4Eu, 0xFEC7u, 0xCC5Cu, 0xDDD5u, 0xA96Au, 0xB8E3u, 0x8A78u, 0x9BF1u,
0x7387u, 0x620Eu, 0x5095u, 0x411Cu, 0x35A3u, 0x242Au, 0x16B1u, 0x0738u,
0xFFCFu, 0xEE46u, 0xDCDDu, 0xCD54u, 0xB9EBu, 0xA862u, 0x9AF9u, 0x8B70u,
0x8408u, 0x9581u, 0xA71Au, 0xB693u, 0xC22Cu, 0xD3A5u, 0xE13Eu, 0xF0B7u,
0x0840u, 0x19C9u, 0x2B52u, 0x3ADBu, 0x4E64u, 0x5FEDu, 0x6D76u, 0x7CFFu,
0x9489u, 0x8500u, 0xB79Bu, 0xA612u, 0xD2ADu, 0xC324u, 0xF1BFu, 0xE036u,
0x18C1u, 0x0948u, 0x3BD3u, 0x2A5Au, 0x5EE5u, 0x4F6Cu, 0x7DF7u, 0x6C7Eu,
0xA50Au, 0xB483u, 0x8618u, 0x9791u, 0xE32Eu, 0xF2A7u, 0xC03Cu, 0xD1B5u,
0x2942u, 0x38CBu, 0x0A50u, 0x1BD9u, 0x6F66u, 0x7EEFu, 0x4C74u, 0x5DFDu,
0xB58Bu, 0xA402u, 0x9699u, 0x8710u, 0xF3AFu, 0xE226u, 0xD0BDu, 0xC134u,
0x39C3u, 0x284Au, 0x1AD1u, 0x0B58u, 0x7FE7u, 0x6E6Eu, 0x5CF5u, 0x4D7Cu,
0xC60Cu, 0xD785u, 0xE51Eu, 0xF497u, 0x8028u, 0x91A1u, 0xA33Au, 0xB2B3u,
0x4A44u, 0x5BCDu, 0x6956u, 0x78DFu, 0x0C60u, 0x1DE9u, 0x2F72u, 0x3EFBu,
0xD68Du, 0xC704u, 0xF59Fu, 0xE416u, 0x90A9u, 0x8120u, 0xB3BBu, 0xA232u,
0x5AC5u, 0x4B4Cu, 0x79D7u, 0x685Eu, 0x1CE1u, 0x0D68u, 0x3FF3u, 0x2E7Au,
0xE70Eu, 0xF687u, 0xC41Cu, 0xD595u, 0xA12Au, 0xB0A3u, 0x8238u, 0x93B1u,
0x6B46u, 0x7ACFu, 0x4854u, 0x59DDu, 0x2D62u, 0x3CEBu, 0x0E70u, 0x1FF9u,
0xF78Fu, 0xE606u, 0xD49Du, 0xC514u, 0xB1ABu, 0xA022u, 0x92B9u, 0x8330u,
0x7BC7u, 0x6A4Eu, 0x58D5u, 0x495Cu, 0x3DE3u, 0x2C6Au, 0x1EF1u, 0x0F78u,
};
static uint8_t reverse(uint8_t n) {
static uint8_t lookup[16] = {
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
uint8_t result;
result = lookup[n & 0xF] << 4 | lookup[n>>4];
return result;
}
static uint16_t reverse16(uint16_t n) {
return reverse(n & 0xFF) << 8 | reverse(n >> 8);
}
uint16_t Calculate(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC;
for (int byte = 0; byte < nBytes; ++byte) {
data = message[byte] ^ remainder;
remainder = crcTable8408[data] ^ (remainder >> 8);
}
return remainder;
}
uint16_t CalculateInv(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC; //already reversed in function call
for (int byte = nBytes; byte > 0; --byte) {
data = reverse(message[byte-1]) ^ remainder;
remainder = crcTable1021[data] ^ (remainder << 8);
}
return reverse16(remainder);
}
int main(void) {
uint16_t expected = 0x4167;
uint8_t pattern[] = "Hello World!";
uint16_t result = Calculate(pattern, 12, 0x6363);
printf("CRC option 1: 0x%04x, expected 0x%04x\n", result, expected);
result = CalculateInv(pattern, 12, 0xC6C6);
printf("CRC option 2: 0x%04X, expected 0x%04X\n", result, expected);
return EXIT_SUCCESS;
}
Output:
CRC option 1: 0x4167, expected 0x4167
CRC option 2: 0x62FD, expected 0x4167
Edit: I created the tables by slightly adapting the code from the accepted answer from How to configure calculation of CRC table as follows:
uint16_t crcTable[256];
void Init(uint16_t polynomial) {
uint16_t remainder;
for (int dividend = 0; dividend < 256; ++dividend) {
remainder = dividend;
for (uint8_t bit = 8; bit > 0; --bit) {
if (remainder & 1)
remainder = (remainder >> 1) ^ polynomial;
else
remainder = (remainder >> 1);
}
crcTable[dividend] = remainder;
}
printf("static const uint_t crcTable[256u] = {");
for (int i = 0; i<32; ++i) {
printf("\n ");
for (int j=0; j<8; ++j) {
printf("0x%04Xu, ",crcTable[i*8+j]);
}
}
printf("\n};\n");
}
For a reflected CRC16, only the bits of each byte of a message are reversed, the message itself is not reversed. The other issue is that crcTable1021 needs to be based on a left shifting algorithm, or it can be a copy of crcTable8408 with the index and values reflected. (Comment - the 8408 CRC is a reflected CRC, while the 1021 is normally a non-reflected CRC, but in this case the input and output is being reflected to match the 8408 CRC). Example code that appears to be working:
static uint16_t crcTable8408[256u]; // could use table from question
static uint16_t crcTable1021[256u]; // could use table from automationwiki
// ... no changes ... //
uint16_t CalculateInv(const uint8_t *message, int nBytes, uint16_t wOldCRC) {
uint8_t data;
uint16_t remainder = wOldCRC; //already reversed in function call
for (int byte = 0; byte < nBytes; ++byte) { // fix
data = reverse(message[byte]) ^ (remainder >> 8); // fix
remainder = crcTable1021[data] ^ (remainder << 8); // fix
}
return reverse16(remainder);
}
void InitTables(void) { // generate tables
uint16_t polynomial = 0x8408;
uint16_t remainder;
for (int dividend = 0; dividend < 256; ++dividend) {
remainder = dividend;
for (uint8_t bit = 8; bit > 0; --bit) {
if (remainder & 1)
remainder = (remainder >> 1) ^ polynomial;
else
remainder = (remainder >> 1);
}
crcTable8408[dividend] = remainder;
crcTable1021[reverse(dividend)] = reverse16(remainder);
}
}
int main(void) {
uint16_t expected = 0x4167;
uint8_t pattern[] = "Hello World!";
InitTables(); // generate tables (or use constant tables)
uint16_t result = Calculate(pattern, 12, 0x6363);
printf("CRC option 1: 0x%04X, expected 0x%04x\n", result, expected);
result = CalculateInv(pattern, 12, 0xC6C6);
printf("CRC option 2: 0x%04X, expected 0x%04X\n", result, expected);
return 0;
}
You can use crcany to generate the code (in C) for any CRC you specify. As it happens, the 16-bit CRC reflected with polynomial 0x1021, initial value 0xc6c6, and final xor 0 is already in the list of standard CRCs. This is the code generated, and it produces 0x4167 for the 12 bytes "Hello, World!":
crc16iso_iec_14443_3_a.h:
// The _bit, _byte, and _word routines return the CRC of the len bytes at mem,
// applied to the previous CRC value, crc. If mem is NULL, then the other
// arguments are ignored, and the initial CRC, i.e. the CRC of zero bytes, is
// returned. Those routines will all return the same result, differing only in
// speed and code complexity. The _rem routine returns the CRC of the remaining
// bits in the last byte, for when the number of bits in the message is not a
// multiple of eight. The low bits bits of the low byte of val are applied to
// crc. bits must be in 0..8.
#include <stddef.h>
// Compute the CRC a bit at a time.
unsigned crc16iso_iec_14443_3_a_bit(unsigned crc, void const *mem, size_t len);
// Compute the CRC of the low bits bits in val.
unsigned crc16iso_iec_14443_3_a_rem(unsigned crc, unsigned val, unsigned bits);
// Compute the CRC a byte at a time.
unsigned crc16iso_iec_14443_3_a_byte(unsigned crc, void const *mem, size_t len);
// Compute the CRC a word at a time.
unsigned crc16iso_iec_14443_3_a_word(unsigned crc, void const *mem, size_t len);
crc16iso_iec_14443_3_a.c:
#include <stdint.h>
#include "crc16iso_iec_14443_3_a.h"
// This code assumes that unsigned is 4 bytes.
unsigned crc16iso_iec_14443_3_a_bit(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
crc &= 0xffff;
while (len--) {
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
}
return crc;
}
unsigned crc16iso_iec_14443_3_a_rem(unsigned crc, unsigned val, unsigned bits) {
crc &= 0xffff;
val &= (1U << bits) - 1;
crc ^= val;
while (bits--)
crc = crc & 1 ? (crc >> 1) ^ 0x8408 : crc >> 1;
return crc;
}
#define table_byte table_word[0]
static unsigned short const table_word[][256] = {
{0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1,
0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 0x0108, 0x3393, 0x221a,
0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64,
0xf9ff, 0xe876, 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 0x200a,
0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 0xac42, 0x9ed9, 0x8f50,
0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9,
0x2732, 0x36bb, 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 0xcf44,
0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 0x728f, 0x4014, 0x519d,
0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3,
0x8a78, 0x9bf1, 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 0x9581,
0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 0x19c9, 0x2b52, 0x3adb,
0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324,
0xf1bf, 0xe036, 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 0x38cb,
0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 0xa402, 0x9699, 0x8710,
0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e,
0x5cf5, 0x4d7c, 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 0xc704,
0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 0x4b4c, 0x79d7, 0x685e,
0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3,
0x8238, 0x93b1, 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 0x6a4e,
0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78},
{0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08, 0xcec0, 0xd718,
0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8, 0x9591, 0x8c49, 0xa621, 0xbff9,
0xf2f1, 0xeb29, 0xc141, 0xd899, 0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9,
0x0f81, 0x1659, 0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b,
0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb, 0xb6a2, 0xaf7a,
0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa, 0x7862, 0x61ba, 0x4bd2, 0x520a,
0x1f02, 0x06da, 0x2cb2, 0x356a, 0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de,
0x12b6, 0x0b6e, 0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae,
0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff, 0x1d37, 0x04ef,
0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f, 0x6555, 0x7c8d, 0x56e5, 0x4f3d,
0x0235, 0x1bed, 0x3185, 0x285d, 0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d,
0xff45, 0xe69d, 0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc,
0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c, 0x8ccc, 0x9514,
0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4, 0x420c, 0x5bd4, 0x71bc, 0x6864,
0x256c, 0x3cb4, 0x16dc, 0x0f04, 0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5,
0x4d8d, 0x5455, 0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95,
0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7, 0x613f, 0x78e7,
0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37, 0x3a6e, 0x23b6, 0x09de, 0x1006,
0x5d0e, 0x44d6, 0x6ebe, 0x7766, 0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16,
0xa07e, 0xb9a6, 0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2,
0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962, 0x5f3b, 0x46e3,
0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233, 0x91fb, 0x8823, 0xa24b, 0xbb93,
0xf69b, 0xef43, 0xc52b, 0xdcf3, 0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721,
0xbd49, 0xa491, 0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51,
0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100, 0xb2c8, 0xab10,
0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0},
{0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05, 0xc6c2, 0x9c1e,
0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7, 0x8595, 0xdf49, 0x302d, 0x6af1,
0xe6f4, 0xbc28, 0x534c, 0x0990, 0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea,
0x958e, 0xcf52, 0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e,
0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc, 0x86ae, 0xdc72,
0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab, 0x406c, 0x1ab0, 0xf5d4, 0xaf08,
0x230d, 0x79d1, 0x96b5, 0xcc69, 0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb,
0xd0af, 0x8a73, 0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1,
0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6, 0x4521, 0x1ffd,
0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924, 0x054d, 0x5f91, 0xb0f5, 0xea29,
0x662c, 0x3cf0, 0xd394, 0x8948, 0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32,
0x1556, 0x4f8a, 0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd,
0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f, 0x0cec, 0x5630,
0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9, 0xca2e, 0x90f2, 0x7f96, 0x254a,
0xa94f, 0xf393, 0x1cf7, 0x462b, 0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4,
0x5fa0, 0x057c, 0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be,
0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2, 0xc915, 0x93c9,
0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510, 0x8a42, 0xd09e, 0x3ffa, 0x6526,
0xe923, 0xb3ff, 0x5c9b, 0x0647, 0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d,
0x9a59, 0xc085, 0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f,
0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d, 0x8f0f, 0xd5d3,
0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a, 0x49cd, 0x1311, 0xfc75, 0xa6a9,
0x2aac, 0x7070, 0x9f14, 0xc5c8, 0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c,
0xdf78, 0x85a4, 0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366,
0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031, 0x4af6, 0x102a,
0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3},
{0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721, 0xe5d8, 0xf963,
0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9, 0xc3a1, 0xdf1a, 0xfad7, 0xe66c,
0xb14d, 0xadf6, 0x883b, 0x9480, 0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e,
0x6de3, 0x7158, 0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872,
0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa, 0x4cf2, 0x5049,
0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3, 0xa92a, 0xb591, 0x905c, 0x8ce7,
0xdbc6, 0xc77d, 0xe2b0, 0xfe0b, 0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0,
0x5d2d, 0x4196, 0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e,
0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237, 0x30ce, 0x2c75,
0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef, 0x99e4, 0x855f, 0xa092, 0xbc29,
0xeb08, 0xf7b3, 0xd27e, 0xcec5, 0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b,
0x37a6, 0x2b1d, 0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64,
0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc, 0x2d6e, 0x31d5,
0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f, 0xc8b6, 0xd40d, 0xf1c0, 0xed7b,
0xba5a, 0xa6e1, 0x832c, 0x9f97, 0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098,
0xa555, 0xb9ee, 0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36,
0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c, 0x47e5, 0x5b5e,
0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4, 0x619c, 0x7d27, 0x58ea, 0x4451,
0x1370, 0x0fcb, 0x2a06, 0x36bd, 0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13,
0xcfde, 0xd365, 0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8,
0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920, 0xf878, 0xe4c3,
0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59, 0x1da0, 0x011b, 0x24d6, 0x386d,
0x6f4c, 0x73f7, 0x563a, 0x4a81, 0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd,
0xff10, 0xe3ab, 0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673,
0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a, 0x92f3, 0x8e48,
0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2},
{0x0000, 0x0b44, 0x1688, 0x1dcc, 0x2d10, 0x2654, 0x3b98, 0x30dc, 0x5a20, 0x5164,
0x4ca8, 0x47ec, 0x7730, 0x7c74, 0x61b8, 0x6afc, 0xb440, 0xbf04, 0xa2c8, 0xa98c,
0x9950, 0x9214, 0x8fd8, 0x849c, 0xee60, 0xe524, 0xf8e8, 0xf3ac, 0xc370, 0xc834,
0xd5f8, 0xdebc, 0x6091, 0x6bd5, 0x7619, 0x7d5d, 0x4d81, 0x46c5, 0x5b09, 0x504d,
0x3ab1, 0x31f5, 0x2c39, 0x277d, 0x17a1, 0x1ce5, 0x0129, 0x0a6d, 0xd4d1, 0xdf95,
0xc259, 0xc91d, 0xf9c1, 0xf285, 0xef49, 0xe40d, 0x8ef1, 0x85b5, 0x9879, 0x933d,
0xa3e1, 0xa8a5, 0xb569, 0xbe2d, 0xc122, 0xca66, 0xd7aa, 0xdcee, 0xec32, 0xe776,
0xfaba, 0xf1fe, 0x9b02, 0x9046, 0x8d8a, 0x86ce, 0xb612, 0xbd56, 0xa09a, 0xabde,
0x7562, 0x7e26, 0x63ea, 0x68ae, 0x5872, 0x5336, 0x4efa, 0x45be, 0x2f42, 0x2406,
0x39ca, 0x328e, 0x0252, 0x0916, 0x14da, 0x1f9e, 0xa1b3, 0xaaf7, 0xb73b, 0xbc7f,
0x8ca3, 0x87e7, 0x9a2b, 0x916f, 0xfb93, 0xf0d7, 0xed1b, 0xe65f, 0xd683, 0xddc7,
0xc00b, 0xcb4f, 0x15f3, 0x1eb7, 0x037b, 0x083f, 0x38e3, 0x33a7, 0x2e6b, 0x252f,
0x4fd3, 0x4497, 0x595b, 0x521f, 0x62c3, 0x6987, 0x744b, 0x7f0f, 0x8a55, 0x8111,
0x9cdd, 0x9799, 0xa745, 0xac01, 0xb1cd, 0xba89, 0xd075, 0xdb31, 0xc6fd, 0xcdb9,
0xfd65, 0xf621, 0xebed, 0xe0a9, 0x3e15, 0x3551, 0x289d, 0x23d9, 0x1305, 0x1841,
0x058d, 0x0ec9, 0x6435, 0x6f71, 0x72bd, 0x79f9, 0x4925, 0x4261, 0x5fad, 0x54e9,
0xeac4, 0xe180, 0xfc4c, 0xf708, 0xc7d4, 0xcc90, 0xd15c, 0xda18, 0xb0e4, 0xbba0,
0xa66c, 0xad28, 0x9df4, 0x96b0, 0x8b7c, 0x8038, 0x5e84, 0x55c0, 0x480c, 0x4348,
0x7394, 0x78d0, 0x651c, 0x6e58, 0x04a4, 0x0fe0, 0x122c, 0x1968, 0x29b4, 0x22f0,
0x3f3c, 0x3478, 0x4b77, 0x4033, 0x5dff, 0x56bb, 0x6667, 0x6d23, 0x70ef, 0x7bab,
0x1157, 0x1a13, 0x07df, 0x0c9b, 0x3c47, 0x3703, 0x2acf, 0x218b, 0xff37, 0xf473,
0xe9bf, 0xe2fb, 0xd227, 0xd963, 0xc4af, 0xcfeb, 0xa517, 0xae53, 0xb39f, 0xb8db,
0x8807, 0x8343, 0x9e8f, 0x95cb, 0x2be6, 0x20a2, 0x3d6e, 0x362a, 0x06f6, 0x0db2,
0x107e, 0x1b3a, 0x71c6, 0x7a82, 0x674e, 0x6c0a, 0x5cd6, 0x5792, 0x4a5e, 0x411a,
0x9fa6, 0x94e2, 0x892e, 0x826a, 0xb2b6, 0xb9f2, 0xa43e, 0xaf7a, 0xc586, 0xcec2,
0xd30e, 0xd84a, 0xe896, 0xe3d2, 0xfe1e, 0xf55a},
{0x0000, 0x042b, 0x0856, 0x0c7d, 0x10ac, 0x1487, 0x18fa, 0x1cd1, 0x2158, 0x2573,
0x290e, 0x2d25, 0x31f4, 0x35df, 0x39a2, 0x3d89, 0x42b0, 0x469b, 0x4ae6, 0x4ecd,
0x521c, 0x5637, 0x5a4a, 0x5e61, 0x63e8, 0x67c3, 0x6bbe, 0x6f95, 0x7344, 0x776f,
0x7b12, 0x7f39, 0x8560, 0x814b, 0x8d36, 0x891d, 0x95cc, 0x91e7, 0x9d9a, 0x99b1,
0xa438, 0xa013, 0xac6e, 0xa845, 0xb494, 0xb0bf, 0xbcc2, 0xb8e9, 0xc7d0, 0xc3fb,
0xcf86, 0xcbad, 0xd77c, 0xd357, 0xdf2a, 0xdb01, 0xe688, 0xe2a3, 0xeede, 0xeaf5,
0xf624, 0xf20f, 0xfe72, 0xfa59, 0x02d1, 0x06fa, 0x0a87, 0x0eac, 0x127d, 0x1656,
0x1a2b, 0x1e00, 0x2389, 0x27a2, 0x2bdf, 0x2ff4, 0x3325, 0x370e, 0x3b73, 0x3f58,
0x4061, 0x444a, 0x4837, 0x4c1c, 0x50cd, 0x54e6, 0x589b, 0x5cb0, 0x6139, 0x6512,
0x696f, 0x6d44, 0x7195, 0x75be, 0x79c3, 0x7de8, 0x87b1, 0x839a, 0x8fe7, 0x8bcc,
0x971d, 0x9336, 0x9f4b, 0x9b60, 0xa6e9, 0xa2c2, 0xaebf, 0xaa94, 0xb645, 0xb26e,
0xbe13, 0xba38, 0xc501, 0xc12a, 0xcd57, 0xc97c, 0xd5ad, 0xd186, 0xddfb, 0xd9d0,
0xe459, 0xe072, 0xec0f, 0xe824, 0xf4f5, 0xf0de, 0xfca3, 0xf888, 0x05a2, 0x0189,
0x0df4, 0x09df, 0x150e, 0x1125, 0x1d58, 0x1973, 0x24fa, 0x20d1, 0x2cac, 0x2887,
0x3456, 0x307d, 0x3c00, 0x382b, 0x4712, 0x4339, 0x4f44, 0x4b6f, 0x57be, 0x5395,
0x5fe8, 0x5bc3, 0x664a, 0x6261, 0x6e1c, 0x6a37, 0x76e6, 0x72cd, 0x7eb0, 0x7a9b,
0x80c2, 0x84e9, 0x8894, 0x8cbf, 0x906e, 0x9445, 0x9838, 0x9c13, 0xa19a, 0xa5b1,
0xa9cc, 0xade7, 0xb136, 0xb51d, 0xb960, 0xbd4b, 0xc272, 0xc659, 0xca24, 0xce0f,
0xd2de, 0xd6f5, 0xda88, 0xdea3, 0xe32a, 0xe701, 0xeb7c, 0xef57, 0xf386, 0xf7ad,
0xfbd0, 0xfffb, 0x0773, 0x0358, 0x0f25, 0x0b0e, 0x17df, 0x13f4, 0x1f89, 0x1ba2,
0x262b, 0x2200, 0x2e7d, 0x2a56, 0x3687, 0x32ac, 0x3ed1, 0x3afa, 0x45c3, 0x41e8,
0x4d95, 0x49be, 0x556f, 0x5144, 0x5d39, 0x5912, 0x649b, 0x60b0, 0x6ccd, 0x68e6,
0x7437, 0x701c, 0x7c61, 0x784a, 0x8213, 0x8638, 0x8a45, 0x8e6e, 0x92bf, 0x9694,
0x9ae9, 0x9ec2, 0xa34b, 0xa760, 0xab1d, 0xaf36, 0xb3e7, 0xb7cc, 0xbbb1, 0xbf9a,
0xc0a3, 0xc488, 0xc8f5, 0xccde, 0xd00f, 0xd424, 0xd859, 0xdc72, 0xe1fb, 0xe5d0,
0xe9ad, 0xed86, 0xf157, 0xf57c, 0xf901, 0xfd2a},
{0x0000, 0x9fd5, 0x37bb, 0xa86e, 0x6f76, 0xf0a3, 0x58cd, 0xc718, 0xdeec, 0x4139,
0xe957, 0x7682, 0xb19a, 0x2e4f, 0x8621, 0x19f4, 0xb5c9, 0x2a1c, 0x8272, 0x1da7,
0xdabf, 0x456a, 0xed04, 0x72d1, 0x6b25, 0xf4f0, 0x5c9e, 0xc34b, 0x0453, 0x9b86,
0x33e8, 0xac3d, 0x6383, 0xfc56, 0x5438, 0xcbed, 0x0cf5, 0x9320, 0x3b4e, 0xa49b,
0xbd6f, 0x22ba, 0x8ad4, 0x1501, 0xd219, 0x4dcc, 0xe5a2, 0x7a77, 0xd64a, 0x499f,
0xe1f1, 0x7e24, 0xb93c, 0x26e9, 0x8e87, 0x1152, 0x08a6, 0x9773, 0x3f1d, 0xa0c8,
0x67d0, 0xf805, 0x506b, 0xcfbe, 0xc706, 0x58d3, 0xf0bd, 0x6f68, 0xa870, 0x37a5,
0x9fcb, 0x001e, 0x19ea, 0x863f, 0x2e51, 0xb184, 0x769c, 0xe949, 0x4127, 0xdef2,
0x72cf, 0xed1a, 0x4574, 0xdaa1, 0x1db9, 0x826c, 0x2a02, 0xb5d7, 0xac23, 0x33f6,
0x9b98, 0x044d, 0xc355, 0x5c80, 0xf4ee, 0x6b3b, 0xa485, 0x3b50, 0x933e, 0x0ceb,
0xcbf3, 0x5426, 0xfc48, 0x639d, 0x7a69, 0xe5bc, 0x4dd2, 0xd207, 0x151f, 0x8aca,
0x22a4, 0xbd71, 0x114c, 0x8e99, 0x26f7, 0xb922, 0x7e3a, 0xe1ef, 0x4981, 0xd654,
0xcfa0, 0x5075, 0xf81b, 0x67ce, 0xa0d6, 0x3f03, 0x976d, 0x08b8, 0x861d, 0x19c8,
0xb1a6, 0x2e73, 0xe96b, 0x76be, 0xded0, 0x4105, 0x58f1, 0xc724, 0x6f4a, 0xf09f,
0x3787, 0xa852, 0x003c, 0x9fe9, 0x33d4, 0xac01, 0x046f, 0x9bba, 0x5ca2, 0xc377,
0x6b19, 0xf4cc, 0xed38, 0x72ed, 0xda83, 0x4556, 0x824e, 0x1d9b, 0xb5f5, 0x2a20,
0xe59e, 0x7a4b, 0xd225, 0x4df0, 0x8ae8, 0x153d, 0xbd53, 0x2286, 0x3b72, 0xa4a7,
0x0cc9, 0x931c, 0x5404, 0xcbd1, 0x63bf, 0xfc6a, 0x5057, 0xcf82, 0x67ec, 0xf839,
0x3f21, 0xa0f4, 0x089a, 0x974f, 0x8ebb, 0x116e, 0xb900, 0x26d5, 0xe1cd, 0x7e18,
0xd676, 0x49a3, 0x411b, 0xdece, 0x76a0, 0xe975, 0x2e6d, 0xb1b8, 0x19d6, 0x8603,
0x9ff7, 0x0022, 0xa84c, 0x3799, 0xf081, 0x6f54, 0xc73a, 0x58ef, 0xf4d2, 0x6b07,
0xc369, 0x5cbc, 0x9ba4, 0x0471, 0xac1f, 0x33ca, 0x2a3e, 0xb5eb, 0x1d85, 0x8250,
0x4548, 0xda9d, 0x72f3, 0xed26, 0x2298, 0xbd4d, 0x1523, 0x8af6, 0x4dee, 0xd23b,
0x7a55, 0xe580, 0xfc74, 0x63a1, 0xcbcf, 0x541a, 0x9302, 0x0cd7, 0xa4b9, 0x3b6c,
0x9751, 0x0884, 0xa0ea, 0x3f3f, 0xf827, 0x67f2, 0xcf9c, 0x5049, 0x49bd, 0xd668,
0x7e06, 0xe1d3, 0x26cb, 0xb91e, 0x1170, 0x8ea5},
{0x0000, 0x81bf, 0x0b6f, 0x8ad0, 0x16de, 0x9761, 0x1db1, 0x9c0e, 0x2dbc, 0xac03,
0x26d3, 0xa76c, 0x3b62, 0xbadd, 0x300d, 0xb1b2, 0x5b78, 0xdac7, 0x5017, 0xd1a8,
0x4da6, 0xcc19, 0x46c9, 0xc776, 0x76c4, 0xf77b, 0x7dab, 0xfc14, 0x601a, 0xe1a5,
0x6b75, 0xeaca, 0xb6f0, 0x374f, 0xbd9f, 0x3c20, 0xa02e, 0x2191, 0xab41, 0x2afe,
0x9b4c, 0x1af3, 0x9023, 0x119c, 0x8d92, 0x0c2d, 0x86fd, 0x0742, 0xed88, 0x6c37,
0xe6e7, 0x6758, 0xfb56, 0x7ae9, 0xf039, 0x7186, 0xc034, 0x418b, 0xcb5b, 0x4ae4,
0xd6ea, 0x5755, 0xdd85, 0x5c3a, 0x65f1, 0xe44e, 0x6e9e, 0xef21, 0x732f, 0xf290,
0x7840, 0xf9ff, 0x484d, 0xc9f2, 0x4322, 0xc29d, 0x5e93, 0xdf2c, 0x55fc, 0xd443,
0x3e89, 0xbf36, 0x35e6, 0xb459, 0x2857, 0xa9e8, 0x2338, 0xa287, 0x1335, 0x928a,
0x185a, 0x99e5, 0x05eb, 0x8454, 0x0e84, 0x8f3b, 0xd301, 0x52be, 0xd86e, 0x59d1,
0xc5df, 0x4460, 0xceb0, 0x4f0f, 0xfebd, 0x7f02, 0xf5d2, 0x746d, 0xe863, 0x69dc,
0xe30c, 0x62b3, 0x8879, 0x09c6, 0x8316, 0x02a9, 0x9ea7, 0x1f18, 0x95c8, 0x1477,
0xa5c5, 0x247a, 0xaeaa, 0x2f15, 0xb31b, 0x32a4, 0xb874, 0x39cb, 0xcbe2, 0x4a5d,
0xc08d, 0x4132, 0xdd3c, 0x5c83, 0xd653, 0x57ec, 0xe65e, 0x67e1, 0xed31, 0x6c8e,
0xf080, 0x713f, 0xfbef, 0x7a50, 0x909a, 0x1125, 0x9bf5, 0x1a4a, 0x8644, 0x07fb,
0x8d2b, 0x0c94, 0xbd26, 0x3c99, 0xb649, 0x37f6, 0xabf8, 0x2a47, 0xa097, 0x2128,
0x7d12, 0xfcad, 0x767d, 0xf7c2, 0x6bcc, 0xea73, 0x60a3, 0xe11c, 0x50ae, 0xd111,
0x5bc1, 0xda7e, 0x4670, 0xc7cf, 0x4d1f, 0xcca0, 0x266a, 0xa7d5, 0x2d05, 0xacba,
0x30b4, 0xb10b, 0x3bdb, 0xba64, 0x0bd6, 0x8a69, 0x00b9, 0x8106, 0x1d08, 0x9cb7,
0x1667, 0x97d8, 0xae13, 0x2fac, 0xa57c, 0x24c3, 0xb8cd, 0x3972, 0xb3a2, 0x321d,
0x83af, 0x0210, 0x88c0, 0x097f, 0x9571, 0x14ce, 0x9e1e, 0x1fa1, 0xf56b, 0x74d4,
0xfe04, 0x7fbb, 0xe3b5, 0x620a, 0xe8da, 0x6965, 0xd8d7, 0x5968, 0xd3b8, 0x5207,
0xce09, 0x4fb6, 0xc566, 0x44d9, 0x18e3, 0x995c, 0x138c, 0x9233, 0x0e3d, 0x8f82,
0x0552, 0x84ed, 0x355f, 0xb4e0, 0x3e30, 0xbf8f, 0x2381, 0xa23e, 0x28ee, 0xa951,
0x439b, 0xc224, 0x48f4, 0xc94b, 0x5545, 0xd4fa, 0x5e2a, 0xdf95, 0x6e27, 0xef98,
0x6548, 0xe4f7, 0x78f9, 0xf946, 0x7396, 0xf229}
};
unsigned crc16iso_iec_14443_3_a_byte(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
crc &= 0xffff;
while (len--)
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
return crc;
}
// This code assumes that integers are stored little-endian.
unsigned crc16iso_iec_14443_3_a_word(unsigned crc, void const *mem, size_t len) {
unsigned char const *data = mem;
if (data == NULL)
return 0x6363;
crc &= 0xffff;
while (len && ((ptrdiff_t)data & 0x7)) {
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
len--;
}
if (len >= 8) {
do {
uintmax_t word = crc ^ *(uintmax_t const *)data;
crc = table_word[7][word & 0xff] ^
table_word[6][(word >> 8) & 0xff] ^
table_word[5][(word >> 16) & 0xff] ^
table_word[4][(word >> 24) & 0xff] ^
table_word[3][(word >> 32) & 0xff] ^
table_word[2][(word >> 40) & 0xff] ^
table_word[1][(word >> 48) & 0xff] ^
table_word[0][word >> 56];
data += 8;
len -= 8;
} while (len >= 8);
}
while (len--)
crc = (crc >> 8) ^
table_byte[(crc ^ *data++) & 0xff];
return crc;
}