2

I have two sources to calculate the seemingly same crc value. I can not figure out why the 'boost/crc.hpp' implementation differs from the 'linux/lib/crc-ccitt.c' implementation.

crc-ccitt.c boost

Here is an example that illustrates the Problem. It is sligthly longer since i do not have the Linux kernel source on my Computer. It compiles if you link boost to it.

The Problem is that Linux and boost do not agree on the crc value. The Linux source states that:

  • The polynomial ... 0x8408.
  • Add the implicit x^16, and you have the standard CRC-CCITT.

I do not know how to apply x^16 but i die edit this question to reflect the deviating polynomial.

#include <stdio.h>
#include <boost\crc.hpp>

typedef unsigned short u16;
typedef unsigned char u8;

/*
*   linux/lib/crc-ccitt.c
*
*   This source code is licensed under the GNU General Public License,
*   Version 2. See the file COPYING for more details.
*/

/*modified for minimal example on stackoverflow*/
/*original source from http://mirrors.neusoft.edu.cn/rpi-kernel/lib/crc-ccitt.c */

u16 const crc_ccitt_table[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
};

//from crc-ccitt.h
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
{
    return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
}

u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
{
    while (len--)
        crc = crc_ccitt_byte(crc, *buffer++);
    return crc;
}

#define check(X, Y) \
if (X != Y) { \
    printf("%s !=  %s\n", #X, #Y); \
} else { \
    printf("%s ==  %s   !!! celebrate\n", #X, #Y); \
} 

void runTestSet(unsigned char * data, unsigned size)
{
    u16 linux = crc_ccitt(0xFFFF, data, size);

    boost::crc_ccitt_type boost_crc_ccitt_type;
    boost::crc_16_type boost_crc_16_type;
    boost::crc_32_type boost_crc_32_type;
    boost::crc_xmodem_type boost_crc_xmodem_type;
    boost::crc_optimal<16, 0x8408, 0xFFFF, 0, false, false> boost_crc_optimal_16_8408_FFFF_0_0_0;
    boost::crc_optimal<16, 0x8408, 0xFFFF, 0, true, true> boost_crc_optimal_16_8408_FFFF_0_1_1;
    boost::crc_optimal<16, 0xA001, 0xFFFF, 0, true, true> boost_crc_optimal_16_A001_FFFF_0_1_1;
    boost::crc_optimal<16, 0x8408, 0xFFFF, 0, true, false> boost_crc_optimal_16_8408_FFFF_0_1_0;
    boost::crc_optimal<16, 0x856F, 0xFFFF, 0, true, true> boost_crc_optimal_16_856F_FFFF_0_1_1;
    boost::crc_optimal<16, 0x856F, 0xFFFF, 0, true, false> boost_crc_optimal_16_856F_FFFF_0_1_0;

    boost_crc_ccitt_type.process_bytes(data, size);
    boost_crc_16_type.process_bytes(data, size);
    boost_crc_32_type.process_bytes(data, size);
    boost_crc_xmodem_type.process_bytes(data, size);
    boost_crc_optimal_16_8408_FFFF_0_0_0.process_bytes(data, size);
    boost_crc_optimal_16_8408_FFFF_0_1_1.process_bytes(data, size);
    boost_crc_optimal_16_A001_FFFF_0_1_1.process_bytes(data, size);
    boost_crc_optimal_16_8408_FFFF_0_1_0.process_bytes(data, size);
    boost_crc_optimal_16_856F_FFFF_0_1_1.process_bytes(data, size);
    boost_crc_optimal_16_856F_FFFF_0_1_0.process_bytes(data, size);

    printf("Testing with sequence: '");
    for (unsigned n = 0; n < size; ++n)
    {
        if (n > 0) printf(" ");
        printf("0x%02X", data[n]);
    }
    printf("'\n");
    check(boost_crc_ccitt_type.checksum(), linux);
    check(boost_crc_16_type.checksum(), linux);
    check(boost_crc_32_type.checksum(), linux);
    check(boost_crc_xmodem_type.checksum(), linux);
    check(boost_crc_optimal_16_8408_FFFF_0_0_0.checksum(), linux);
    check(boost_crc_optimal_16_8408_FFFF_0_1_1.checksum(), linux);
    check(boost_crc_optimal_16_A001_FFFF_0_1_1.checksum(), linux);
    check(boost_crc_optimal_16_8408_FFFF_0_1_0.checksum(), linux);
    check(boost_crc_optimal_16_856F_FFFF_0_1_1.checksum(), linux);
    check(boost_crc_optimal_16_856F_FFFF_0_1_0.checksum(), linux);
    printf("End Of Testrun\n\n");
}


int main()
{
    unsigned char simple[] = {0x80};
    unsigned char sequence[] = "123456789";
    runTestSet(simple, sizeof(simple));
    runTestSet(sequence, sizeof(sequence));
    return 0;
}

I see that i did not state my usecase for this. I have a System dependency and need to use the incorrect(?) Linux crc. I want to trim the boost implementation in a way that allows me to do this using boost instead.

The output on my machine is:

enter image description here

Johannes
  • 6,490
  • 10
  • 59
  • 108
  • From the link you gave to linux crc: "Add the implicit x^16, and you have the standard CRC-CCITT." Not sure what it means exactly, but have taken care of that? – Daniel Lidström Sep 11 '15 at 07:55
  • I actually did read that but it slipped my mind. Also i do not know what adding the implicit x^16 means and how i can apply that to get the "correct" crc value. – Johannes Sep 11 '15 at 07:57

4 Answers4

2

update - based on these web site crc calculators

(choose ccitt(0xffff)) http://www.lammertbies.nl/comm/info/crc-calculation.html

(choose crc ccitt) http://www.zorc.breitbandkatze.de/crc.html

A third site that calls this version crc-16-ccitt-false, and also lists the other variations also called ccitt.

http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.crc-16-ccitt-false

In this case the bits are not reversed. Also the 9 byte string "123456789" seems like a common test. However other web sites mention that some versions of ccitt do reverse the bits as done in the linux example. My guess is that which one to use will be protocol / device specific. At least now you have both the reversed (linux) and non-reversed (the code in this answer) if you need to switch.

Example code added:

A CRC is the remainder after doing a Galois type divide of a string of bits by a n bit polynomial, producing an n-1 bit remainder. In the case of a floppy disk, a 17 bit polynomial, 0x11021 is used to produce a 16 bit remainder. The logic for each bit goes something like this:

    crc << = 1;
    if(crc & 0x10000)crc ^= 0x11021;

This can be also implemented s:

    if(crc & 0x8000){crc = ((crc<<1) & 0xffff) & 0x1021;}
    else {crc = ((crc<<1) & 0xffff);}

Example code. This should match the boost code.

typedef unsigned short u16;
typedef unsigned char u8;

u16 crctbl[256] = {
    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,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,
    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,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,
    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,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,
    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,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,
    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,0x2e93,0x3eb2,0x0ed1,0x1ef0};

u16 gencrc(u8 *bfr, size_t len)
{
u16 crc = 0xffff;
    while(len--)
        crc = (crc << 8) ^ crctbl[(crc >> 8)^*bfr++];
    return(crc);
}

int main()
{
u16 crc;
u8 a[4]  = {0x80, 0, 0, 0};
u8 b[10] = {"123456789"};
    crc = gencrc(a, 1);   // returns 0x7078
    crc = gencrc(b, 9);   // returns 0x29b1
    return(0);
}
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • I tried both variants and they are not matching. I will update the question with the testruns. – Johannes Sep 11 '15 at 10:21
  • i added your Suggestion to the question. Where does that get me? – Johannes Sep 11 '15 at 10:36
  • ah - thanks for your code. Actually i wated to match in the other direction. I wanted to match the Linux code using boost. – Johannes Sep 11 '15 at 11:38
  • i think your findings are in line with the Trial and Error result 'boost::crc_optimal<16, 0x1021, 0xFFFF, 0, true, true>' – Johannes Sep 11 '15 at 11:58
  • @Johannes - try ... false, false> to see if that also matches. Looks like true true just reverses the bits twice, perhaps needlessly. – rcgldr Sep 11 '15 at 12:10
  • @Johannes - the more sites I look at, the more conflicts I see, mostly if the bits are reversed using 0x8408, or not reversed using 0x1021. You've got both code versions now. – rcgldr Sep 11 '15 at 13:16
2

The table from the question does indeed use the polynomial 0x1021. This can be checked by generating the table with this short program:

#include <iostream>

unsigned long SwapBits(unsigned long swap, int bits)
{
    unsigned long r = 0;
    for(int i = 0; i < bits; i++) {
        if(swap & 1) r |= 1 << (bits - i - 1);
        swap >>= 1;
    }
    return r;
}

int main()
{
    const unsigned short poly = 0x1021;
    unsigned short CRCTab[256];
    for(int i = 0; i < 256; i++) {
        CRCTab[i] = SwapBits(i, 8) << 8;
        for(int j = 0; j < 8; j++) CRCTab[i] = (CRCTab[i] << 1) ^ ((CRCTab[i] & 0x8000) ? poly : 0);
        CRCTab[i] = SwapBits(CRCTab[i], 16);
    }
    for(int i = 0; i < 256; ) {
        char str[10];
        for(int j = 0; j < 8; j++, i++) {
            sprintf(str, "0x%04x, ", CRCTab[i]);
            std::cout << str;
        }
        std::cout << "\n";
    }
    return 0;
}
alain
  • 11,939
  • 2
  • 31
  • 51
1

Given lib/crc-ccitt.c does not use the 0x1021 polynomial required for CRC-CCITT. So, i think boost version is correct since crc_ccitt_type is a typedef:

typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false>  crc_ccitt_type;

P.S. Warning: your line size = sizeof(data) / sizeof(data[0]) is not correct, but it gives right number. This counts number of elements, not number of bytes (but since sizeof(char)==1 it caclulates right size).

Galimov Albert
  • 7,269
  • 1
  • 24
  • 50
1

Through Trial and error i found a solution that seems to produce the correct hits. Thanks everyone for the hints. This type boost::crc_optimal<16, 0x1021, 0xFFFF, 0, true, true> seems to be correct.

I do not know why and that worries me a bit.

#include <stdio.h>
#include <boost\crc.hpp>

typedef unsigned short u16;
typedef unsigned char u8;

/*
*   linux/lib/crc-ccitt.c
*
*   This source code is licensed under the GNU General Public License,
*   Version 2. See the file COPYING for more details.
*/

/*modified for minimal example on stackoverflow*/
/*original source from http://mirrors.neusoft.edu.cn/rpi-kernel/lib/crc-ccitt.c */

u16 const crc_ccitt_table[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
};

//from crc-ccitt.h
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
{
    return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
}

u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
{
    while (len--)
        crc = crc_ccitt_byte(crc, *buffer++);
    return crc;
}

#define check(X, Y) \
if (X != Y) { \
    printf("%s (0x%08X) !=  %s (0x%08X)\n", #X, X, #Y, Y); \
} else { \
    printf("%s (0x%08X) ==  %s (0x%08X)!!! celebrate\n", #X, X, #Y, Y); \
}

void runTestSet(unsigned char * data, unsigned size)
{
    u16 linux = crc_ccitt(0xFFFF, data, size);
    boost::crc_optimal<16, 0x1021, 0xFFFF, 0, true, true> boost_crc_optimal_16_1021_FFFF_0_1_1;
    boost_crc_optimal_16_1021_FFFF_0_1_1.process_bytes(data, size);

    printf("Testing with sequence: '");
    for (unsigned n = 0; n < size; ++n)
    {
        if (n > 0) printf(" ");
        printf("0x%02X", data[n]);
    }
    printf("'\n");
    check(boost_crc_optimal_16_1021_FFFF_0_1_1.checksum(), linux);
    printf("End Of Testrun\n\n");
}


int main()
{
    unsigned char zero_Length[] = {0x00};
    unsigned char simple[] = {0x80};
    unsigned char sequence[] = "123456789";
    unsigned char LotsOfAs[] = "AAAAAAAAAAAAAAAAAAAAAAAAA";
    runTestSet(zero_Length, 0);
    runTestSet(simple, sizeof(simple));
    runTestSet(sequence, sizeof(sequence)-1);
    runTestSet(LotsOfAs, sizeof(LotsOfAs)-1);
    return 0;
}
Johannes
  • 6,490
  • 10
  • 59
  • 108
  • Try boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> and also the example code I have in my answer below. It matches the results I get from [CRC-CCITT (0xFFFF)](http://www.lammertbies.nl/comm/info/crc-calculation.html) . – rcgldr Sep 11 '15 at 11:43