crc_test.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756
  1. // Boost CRC test program file ---------------------------------------------//
  2. // Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
  3. // distribution are subject to the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or a copy at
  5. // <http://www.boost.org/LICENSE_1_0.txt>.)
  6. // See <http://www.boost.org/libs/crc/> for the library's home page.
  7. // Revision History
  8. // 28 Aug 2004 Added CRC tests for polynominals shorter than 8 bits
  9. // (Daryle Walker, by patch from Bert Klaps)
  10. // 23 Aug 2003 Adjust to updated Test framework (Daryle Walker)
  11. // 14 May 2001 Initial version (Daryle Walker)
  12. #include <boost/config.hpp> // for BOOST_MSVC, etc.
  13. #include <boost/crc.hpp> // for boost::crc_basic, etc.
  14. #include <boost/cstdint.hpp> // for boost::uint16_t, etc.
  15. #include <boost/cstdlib.hpp> // for boost::exit_success
  16. #include <boost/integer.hpp> // for boost::uint_t
  17. #include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
  18. #include <boost/core/lightweight_test.hpp>
  19. #include <boost/timer.hpp> // for boost::timer
  20. #include <algorithm> // for std::for_each, std::generate_n, std::count
  21. #include <climits> // for CHAR_BIT
  22. #include <cstddef> // for std::size_t
  23. #include <iostream> // for std::cout (std::ostream and std::endl indirectly)
  24. #if CHAR_BIT != 8
  25. #error The expected results assume an eight-bit byte.
  26. #endif
  27. #if !(defined(BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS) || (defined(BOOST_MSVC) && (BOOST_MSVC <= 1300)))
  28. #define CRC_PARM_TYPE typename boost::uint_t<Bits>::fast
  29. #else
  30. #define CRC_PARM_TYPE unsigned long
  31. #endif
  32. #if !defined(BOOST_MSVC) && !defined(__GNUC__)
  33. #define PRIVATE_DECLARE_BOOST( TypeName ) using boost:: TypeName
  34. #else
  35. #define PRIVATE_DECLARE_BOOST( TypeName ) typedef boost:: TypeName TypeName
  36. #endif
  37. // Types
  38. template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
  39. CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
  40. class crc_tester
  41. {
  42. public:
  43. // All the following were separate function templates, but they have
  44. // been moved to class-static member functions of a class template
  45. // because MS VC++ 6 can't handle function templates that can't
  46. // deduce all their template arguments from their function arguments.
  47. typedef typename boost::uint_t<Bits>::fast value_type;
  48. static void master_test( char const *test_name, value_type expected );
  49. private:
  50. typedef boost::crc_optimal<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
  51. optimal_crc_type;
  52. typedef boost::crc_basic<Bits> basic_crc_type;
  53. static void compute_test( value_type expected );
  54. static void interrupt_test( value_type expected );
  55. static void error_test();
  56. }; // crc_tester
  57. // Global data
  58. unsigned char const std_data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  59. 0x38, 0x39 };
  60. std::size_t const std_data_len = sizeof( std_data ) / sizeof( std_data[0] );
  61. boost::uint16_t const std_crc_ccitt_result = 0x29B1;
  62. boost::uint16_t const std_crc_16_result = 0xBB3D;
  63. boost::uint32_t const std_crc_32_result = 0xCBF43926;
  64. // Function prototypes
  65. void timing_test();
  66. boost::uint32_t basic_crc32( void const *buffer, std::size_t byte_count );
  67. boost::uint32_t optimal_crc32( void const *buffer, std::size_t byte_count );
  68. boost::uint32_t quick_crc32( void const *buffer, std::size_t byte_count );
  69. boost::uint32_t quick_reflect( boost::uint32_t value, std::size_t bits );
  70. double time_trial( char const *name,
  71. boost::uint32_t (*crc_func)(void const *, std::size_t),
  72. boost::uint32_t expected, void const *data, std::size_t length );
  73. void augmented_tests();
  74. boost::uint32_t native_to_big( boost::uint32_t x );
  75. boost::uint32_t big_to_native( boost::uint32_t x );
  76. void small_crc_test1();
  77. void small_crc_test2();
  78. // Macro to compact code
  79. #define PRIVATE_TESTER_NAME crc_tester<Bits, TrPo, InRe, FiXo, ReIn, ReRe>
  80. // Run a test on slow and fast CRC computers and function
  81. template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
  82. CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
  83. void
  84. PRIVATE_TESTER_NAME::compute_test
  85. (
  86. typename PRIVATE_TESTER_NAME::value_type expected
  87. )
  88. {
  89. std::cout << "\tDoing computation tests." << std::endl;
  90. optimal_crc_type fast_crc;
  91. basic_crc_type slow_crc( TrPo, InRe, FiXo, ReIn, ReRe );
  92. value_type const func_result = boost::crc<Bits, TrPo, InRe, FiXo, ReIn,
  93. ReRe>( std_data, std_data_len );
  94. fast_crc.process_bytes( std_data, std_data_len );
  95. slow_crc.process_bytes( std_data, std_data_len );
  96. BOOST_TEST_EQ( fast_crc.checksum(), expected );
  97. BOOST_TEST_EQ( slow_crc.checksum(), expected );
  98. BOOST_TEST_EQ( func_result, expected );
  99. }
  100. // Run a test in two runs, and check all the inspectors
  101. template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
  102. CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
  103. void
  104. PRIVATE_TESTER_NAME::interrupt_test
  105. (
  106. typename PRIVATE_TESTER_NAME::value_type expected
  107. )
  108. {
  109. std::cout << "\tDoing interrupt tests." << std::endl;
  110. // Process the first half of the data (also test accessors)
  111. optimal_crc_type fast_crc1;
  112. basic_crc_type slow_crc1( fast_crc1.get_truncated_polynominal(),
  113. fast_crc1.get_initial_remainder(), fast_crc1.get_final_xor_value(),
  114. fast_crc1.get_reflect_input(), fast_crc1.get_reflect_remainder() );
  115. BOOST_TEST_EQ( fast_crc1.get_interim_remainder(),
  116. slow_crc1.get_initial_remainder() );
  117. std::size_t const mid_way = std_data_len / 2;
  118. unsigned char const * const std_data_end = std_data + std_data_len;
  119. fast_crc1.process_bytes( std_data, mid_way );
  120. slow_crc1.process_bytes( std_data, mid_way );
  121. BOOST_TEST_EQ( fast_crc1.checksum(), slow_crc1.checksum() );
  122. // Process the second half of the data (also test accessors)
  123. boost::crc_optimal<optimal_crc_type::bit_count,
  124. optimal_crc_type::truncated_polynominal, optimal_crc_type::initial_remainder,
  125. optimal_crc_type::final_xor_value, optimal_crc_type::reflect_input,
  126. optimal_crc_type::reflect_remainder>
  127. fast_crc2( fast_crc1.get_interim_remainder() );
  128. boost::crc_basic<basic_crc_type::bit_count> slow_crc2(
  129. slow_crc1.get_truncated_polynominal(), slow_crc1.get_interim_remainder(),
  130. slow_crc1.get_final_xor_value(), slow_crc1.get_reflect_input(),
  131. slow_crc1.get_reflect_remainder() );
  132. fast_crc2.process_block( std_data + mid_way, std_data_end );
  133. slow_crc2.process_block( std_data + mid_way, std_data_end );
  134. BOOST_TEST_EQ( fast_crc2.checksum(), slow_crc2.checksum() );
  135. BOOST_TEST_EQ( fast_crc2.checksum(), expected );
  136. BOOST_TEST_EQ( slow_crc2.checksum(), expected );
  137. }
  138. // Run a test to see if a single-bit error is detected
  139. template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
  140. CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
  141. void
  142. PRIVATE_TESTER_NAME::error_test
  143. (
  144. )
  145. {
  146. PRIVATE_DECLARE_BOOST( uint32_t );
  147. // A single-bit error is ensured to be detected if the polynominal
  148. // has at least two bits set. The highest bit is what is removed
  149. // to give the truncated polynominal, and it is always set. This
  150. // means that the truncated polynominal needs at least one of its
  151. // bits set, which implies that it cannot be zero.
  152. if ( !(TrPo & boost::detail::low_bits_mask_c<Bits>::value) )
  153. {
  154. BOOST_ERROR( "truncated CRC polymonial is zero" );
  155. }
  156. std::cout << "\tDoing error tests." << std::endl;
  157. // Create a random block of data
  158. uint32_t ran_data[ 256 ];
  159. std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
  160. std::generate_n( ran_data, ran_length, boost::minstd_rand() );
  161. // Create computers and compute the checksum of the data
  162. optimal_crc_type fast_tester;
  163. basic_crc_type slow_tester( TrPo, InRe, FiXo, ReIn, ReRe );
  164. fast_tester.process_bytes( ran_data, sizeof(ran_data) );
  165. slow_tester.process_bytes( ran_data, sizeof(ran_data) );
  166. uint32_t const fast_checksum = fast_tester.checksum();
  167. uint32_t const slow_checksum = slow_tester.checksum();
  168. BOOST_TEST_EQ( fast_checksum, slow_checksum );
  169. // Do the checksum again (and test resetting ability)
  170. fast_tester.reset();
  171. slow_tester.reset( InRe );
  172. fast_tester.process_bytes( ran_data, sizeof(ran_data) );
  173. slow_tester.process_bytes( ran_data, sizeof(ran_data) );
  174. BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
  175. BOOST_TEST_EQ( fast_tester.checksum(), fast_checksum );
  176. BOOST_TEST_EQ( slow_tester.checksum(), slow_checksum );
  177. // Produce a single-bit error
  178. ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
  179. // Compute the checksum of the errorenous data
  180. // (and continue testing resetting ability)
  181. fast_tester.reset( InRe );
  182. slow_tester.reset();
  183. fast_tester.process_bytes( ran_data, sizeof(ran_data) );
  184. slow_tester.process_bytes( ran_data, sizeof(ran_data) );
  185. BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
  186. BOOST_TEST_NE( fast_tester.checksum(), fast_checksum );
  187. BOOST_TEST_NE( slow_tester.checksum(), slow_checksum );
  188. }
  189. // Run the other CRC object tests
  190. template < std::size_t Bits, CRC_PARM_TYPE TrPo, CRC_PARM_TYPE InRe,
  191. CRC_PARM_TYPE FiXo, bool ReIn, bool ReRe >
  192. void
  193. PRIVATE_TESTER_NAME::master_test
  194. (
  195. char const * test_name,
  196. typename PRIVATE_TESTER_NAME::value_type expected
  197. )
  198. {
  199. std::cout << "Doing test suite for " << test_name << '.' << std::endl;
  200. compute_test( expected );
  201. interrupt_test( expected );
  202. error_test();
  203. }
  204. // Undo limited macros
  205. #undef PRIVATE_TESTER_NAME
  206. // A CRC-32 computer based on crc_basic, for timing
  207. boost::uint32_t
  208. basic_crc32
  209. (
  210. void const * buffer,
  211. std::size_t byte_count
  212. )
  213. {
  214. static boost::crc_basic<32> computer( 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF,
  215. true, true );
  216. computer.reset();
  217. computer.process_bytes( buffer, byte_count );
  218. return computer.checksum();
  219. }
  220. // A CRC-32 computer based on crc_optimal, for timing
  221. inline
  222. boost::uint32_t
  223. optimal_crc32
  224. (
  225. void const * buffer,
  226. std::size_t byte_count
  227. )
  228. {
  229. static boost::crc_32_type computer;
  230. computer.reset();
  231. computer.process_bytes( buffer, byte_count );
  232. return computer.checksum();
  233. }
  234. // Reflect the lower "bits" bits of a "value"
  235. boost::uint32_t
  236. quick_reflect
  237. (
  238. boost::uint32_t value,
  239. std::size_t bits
  240. )
  241. {
  242. boost::uint32_t reflection = 0;
  243. for ( std::size_t i = 0 ; i < bits ; ++i )
  244. {
  245. if ( value & (1u << i) )
  246. {
  247. reflection |= 1 << ( bits - 1 - i );
  248. }
  249. }
  250. return reflection;
  251. }
  252. // A customized CRC-32 computer, for timing
  253. boost::uint32_t
  254. quick_crc32
  255. (
  256. void const * buffer,
  257. std::size_t byte_count
  258. )
  259. {
  260. PRIVATE_DECLARE_BOOST( uint32_t );
  261. typedef unsigned char byte_type;
  262. // Compute the CRC table (first run only)
  263. static bool did_init = false;
  264. static uint32_t crc_table[ 1ul << CHAR_BIT ];
  265. if ( !did_init )
  266. {
  267. uint32_t const value_high_bit = static_cast<uint32_t>(1) << 31u;
  268. byte_type dividend = 0;
  269. do
  270. {
  271. uint32_t remainder = 0;
  272. for ( byte_type mask = 1u << (CHAR_BIT - 1u) ; mask ; mask >>= 1 )
  273. {
  274. if ( dividend & mask )
  275. {
  276. remainder ^= value_high_bit;
  277. }
  278. if ( remainder & value_high_bit )
  279. {
  280. remainder <<= 1;
  281. remainder ^= 0x04C11DB7u;
  282. }
  283. else
  284. {
  285. remainder <<= 1;
  286. }
  287. }
  288. crc_table[ quick_reflect(dividend, CHAR_BIT) ]
  289. = quick_reflect( remainder, 32 );
  290. }
  291. while ( ++dividend );
  292. did_init = true;
  293. }
  294. // Compute the CRC of the data
  295. uint32_t rem = 0xFFFFFFFF;
  296. byte_type const * const b_begin = static_cast<byte_type const *>( buffer );
  297. byte_type const * const b_end = b_begin + byte_count;
  298. for ( byte_type const *p = b_begin ; p < b_end ; ++p )
  299. {
  300. byte_type const byte_index = *p ^ rem;
  301. rem >>= CHAR_BIT;
  302. rem ^= crc_table[ byte_index ];
  303. }
  304. return ~rem;
  305. }
  306. // Run an individual timing trial
  307. double
  308. time_trial
  309. (
  310. char const * name,
  311. boost::uint32_t (*crc_func)(void const *, std::size_t),
  312. boost::uint32_t expected,
  313. void const * data,
  314. std::size_t length
  315. )
  316. {
  317. PRIVATE_DECLARE_BOOST( uint32_t );
  318. using std::cout;
  319. // Limits of a trial
  320. static uint32_t const max_count = 1L << 16; // ~square-root of max
  321. static double const max_time = 3.14159; // easy as pi(e)
  322. // Mark the trial
  323. cout << '\t' << name << " CRC-32: ";
  324. // Trial loop
  325. uint32_t trial_count = 0, wrong_count = 0;
  326. double elapsed_time = 0.0;
  327. boost::timer t;
  328. do
  329. {
  330. uint32_t const scratch = (*crc_func)( data, length );
  331. if ( scratch != expected )
  332. {
  333. ++wrong_count;
  334. }
  335. elapsed_time = t.elapsed();
  336. ++trial_count;
  337. } while ( (trial_count < max_count) && (elapsed_time < max_time) );
  338. if ( wrong_count )
  339. {
  340. BOOST_ERROR( "at least one time trial didn't match expected" );
  341. }
  342. // Report results
  343. double const rate = trial_count / elapsed_time;
  344. cout << trial_count << " runs, " << elapsed_time << " s, " << rate
  345. << " run/s" << std::endl;
  346. return rate;
  347. }
  348. // Time runs of Boost CRCs vs. a customized CRC function
  349. void
  350. timing_test
  351. (
  352. )
  353. {
  354. PRIVATE_DECLARE_BOOST( uint32_t );
  355. using std::cout;
  356. using std::endl;
  357. cout << "Doing timing tests." << endl;
  358. // Create a random block of data
  359. boost::int32_t ran_data[ 256 ];
  360. std::size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
  361. std::generate_n( ran_data, ran_length, boost::minstd_rand() );
  362. // Use the first runs as a check. This gives a chance for first-
  363. // time static initialization to not interfere in the timings.
  364. uint32_t const basic_result = basic_crc32( ran_data, sizeof(ran_data) );
  365. uint32_t const optimal_result = optimal_crc32( ran_data, sizeof(ran_data) );
  366. uint32_t const quick_result = quick_crc32( ran_data, sizeof(ran_data) );
  367. BOOST_TEST_EQ( basic_result, optimal_result );
  368. BOOST_TEST_EQ( optimal_result, quick_result );
  369. BOOST_TEST_EQ( quick_result, basic_result );
  370. // Run trials
  371. double const basic_rate = time_trial( "Boost-Basic", basic_crc32,
  372. basic_result, ran_data, sizeof(ran_data) );
  373. double const optimal_rate = time_trial( "Boost-Optimal", optimal_crc32,
  374. optimal_result, ran_data, sizeof(ran_data) );
  375. double const quick_rate = time_trial( "Reference", quick_crc32,
  376. quick_result, ran_data, sizeof(ran_data) );
  377. // Report results
  378. cout << "\tThe optimal Boost version has " << optimal_rate / quick_rate *
  379. 100.0 << "% the speed of the reference version.\n";
  380. cout << "\tThe basic Boost version has " << basic_rate / quick_rate * 100.0
  381. << "% the speed of the reference version.\n";
  382. cout << "\tThe basic Boost version has " << basic_rate / optimal_rate *
  383. 100.0 << "% the speed of the optimal Boost version."
  384. << endl;
  385. }
  386. // Reformat an integer to the big-endian storage format
  387. boost::uint32_t
  388. native_to_big
  389. (
  390. boost::uint32_t x
  391. )
  392. {
  393. boost::uint32_t temp;
  394. unsigned char * tp = reinterpret_cast<unsigned char *>( &temp );
  395. for ( std::size_t i = sizeof(x) ; i > 0 ; --i )
  396. {
  397. tp[ i - 1 ] = static_cast<unsigned char>( x );
  398. x >>= CHAR_BIT;
  399. }
  400. return temp;
  401. }
  402. // Restore an integer from the big-endian storage format
  403. boost::uint32_t
  404. big_to_native
  405. (
  406. boost::uint32_t x
  407. )
  408. {
  409. boost::uint32_t temp = 0;
  410. unsigned char * xp = reinterpret_cast<unsigned char *>( &x );
  411. for ( std::size_t i = 0 ; i < sizeof(x) ; ++i )
  412. {
  413. temp <<= CHAR_BIT;
  414. temp |= xp[ i ];
  415. }
  416. return temp;
  417. }
  418. // Run tests on using CRCs on augmented messages
  419. void
  420. augmented_tests
  421. (
  422. )
  423. {
  424. #define PRIVATE_ACRC_FUNC boost::augmented_crc<32, 0x04C11DB7>
  425. using std::size_t;
  426. PRIVATE_DECLARE_BOOST( uint32_t );
  427. std::cout << "Doing CRC-augmented message tests." << std::endl;
  428. // Create a random block of data, with space for a CRC.
  429. uint32_t ran_data[ 257 ];
  430. size_t const ran_length = sizeof(ran_data) / sizeof(ran_data[0]);
  431. size_t const data_length = ran_length - 1;
  432. std::generate_n( ran_data, data_length, boost::minstd_rand() );
  433. // When creating a CRC for an augmented message, use
  434. // zeros in the appended CRC spot for the first run.
  435. uint32_t & ran_crc = ran_data[ data_length ];
  436. ran_crc = 0;
  437. // Compute the CRC with augmented-CRC computing function
  438. typedef boost::uint_t<32>::fast return_type;
  439. ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
  440. // With the appended CRC set, running the checksum again should get zero.
  441. // NOTE: CRC algorithm assumes numbers are in big-endian format
  442. ran_crc = native_to_big( ran_crc );
  443. uint32_t ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
  444. BOOST_TEST_EQ( 0, ran_crc_check );
  445. // Compare that result with other CRC computing functions
  446. // and classes, which don't accept augmented messages.
  447. typedef boost::crc_optimal<32, 0x04C11DB7> fast_crc_type;
  448. typedef boost::crc_basic<32> slow_crc_type;
  449. fast_crc_type fast_tester;
  450. slow_crc_type slow_tester( 0x04C11DB7 );
  451. size_t const data_size = data_length * sizeof(ran_data[0]);
  452. uint32_t const func_tester = boost::crc<32, 0x04C11DB7, 0, 0, false,
  453. false>( ran_data, data_size );
  454. fast_tester.process_bytes( ran_data, data_size );
  455. slow_tester.process_bytes( ran_data, data_size );
  456. BOOST_TEST_EQ( fast_tester.checksum(), slow_tester.checksum() );
  457. ran_crc = big_to_native( ran_crc );
  458. BOOST_TEST_EQ( fast_tester.checksum(), ran_crc );
  459. BOOST_TEST_EQ( func_tester, ran_crc );
  460. // Do a single-bit error test
  461. ran_crc = native_to_big( ran_crc );
  462. ran_data[ ran_data[0] % ran_length ] ^= ( 1 << (ran_data[1] % 32) );
  463. ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data) );
  464. BOOST_TEST_NE( 0, ran_crc_check );
  465. // Run a version of these tests with a nonzero initial remainder.
  466. uint32_t const init_rem = ran_data[ ran_data[2] % ran_length ];
  467. ran_crc = 0;
  468. ran_crc = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
  469. // Have some fun by processing data in two steps.
  470. size_t const mid_index = ran_length / 2;
  471. ran_crc = native_to_big( ran_crc );
  472. ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, mid_index
  473. * sizeof(ran_data[0]), init_rem );
  474. ran_crc_check = PRIVATE_ACRC_FUNC( &ran_data[mid_index], sizeof(ran_data)
  475. - mid_index * sizeof(ran_data[0]), ran_crc_check );
  476. BOOST_TEST_EQ( 0, ran_crc_check );
  477. // This substep translates an augmented-CRC initial
  478. // remainder to an unaugmented-CRC initial remainder.
  479. uint32_t const zero = 0;
  480. uint32_t const new_init_rem = PRIVATE_ACRC_FUNC( &zero, sizeof(zero),
  481. init_rem );
  482. slow_crc_type slow_tester2( 0x04C11DB7, new_init_rem );
  483. slow_tester2.process_bytes( ran_data, data_size );
  484. ran_crc = big_to_native( ran_crc );
  485. BOOST_TEST_EQ( slow_tester2.checksum(), ran_crc );
  486. // Redo single-bit error test
  487. ran_data[ ran_data[3] % ran_length ] ^= ( 1 << (ran_data[4] % 32) );
  488. ran_crc_check = PRIVATE_ACRC_FUNC( ran_data, sizeof(ran_data), init_rem );
  489. BOOST_TEST_NE( 0, ran_crc_check );
  490. #undef PRIVATE_ACRC_FUNC
  491. }
  492. // Run tests on CRCs below a byte in size (here, 3 bits)
  493. void
  494. small_crc_test1
  495. (
  496. )
  497. {
  498. std::cout << "Doing short-CRC (3-bit augmented) message tests."
  499. << std::endl;
  500. // The CRC standard is a SDH/SONET Low Order LCAS control word with CRC-3
  501. // taken from ITU-T G.707 (12/03) XIII.2.
  502. // Four samples, each four bytes; should all have a CRC of zero
  503. unsigned char const samples[4][4]
  504. = {
  505. { 0x3A, 0xC4, 0x08, 0x06 },
  506. { 0x42, 0xC5, 0x0A, 0x41 },
  507. { 0x4A, 0xC5, 0x08, 0x22 },
  508. { 0x52, 0xC4, 0x08, 0x05 }
  509. };
  510. // Basic computer
  511. boost::crc_basic<3> tester1( 0x03 );
  512. tester1.process_bytes( samples[0], 4 );
  513. BOOST_TEST_EQ( tester1.checksum(), 0 );
  514. tester1.reset();
  515. tester1.process_bytes( samples[1], 4 );
  516. BOOST_TEST_EQ( tester1.checksum(), 0 );
  517. tester1.reset();
  518. tester1.process_bytes( samples[2], 4 );
  519. BOOST_TEST_EQ( tester1.checksum(), 0 );
  520. tester1.reset();
  521. tester1.process_bytes( samples[3], 4 );
  522. BOOST_TEST_EQ( tester1.checksum(), 0 );
  523. // Optimal computer
  524. #define PRIVATE_CRC_FUNC boost::crc<3, 0x03, 0, 0, false, false>
  525. #define PRIVATE_ACRC_FUNC boost::augmented_crc<3, 0x03>
  526. BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[0], 4) );
  527. BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[1], 4) );
  528. BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[2], 4) );
  529. BOOST_TEST_EQ( 0, PRIVATE_CRC_FUNC(samples[3], 4) );
  530. // maybe the fix to CRC functions needs to be applied to augmented CRCs?
  531. #undef PRIVATE_ACRC_FUNC
  532. #undef PRIVATE_CRC_FUNC
  533. }
  534. // Run tests on CRCs below a byte in size (here, 7 bits)
  535. void
  536. small_crc_test2
  537. (
  538. )
  539. {
  540. std::cout << "Doing short-CRC (7-bit augmented) message tests."
  541. << std::endl;
  542. // The CRC standard is a SDH/SONET J0/J1/J2/N1/N2/TR TTI (trace message)
  543. // with CRC-7, o.a. ITU-T G.707 Annex B, G.832 Annex A.
  544. // Two samples, each sixteen bytes
  545. // Sample 1 is '\x80' + ASCII("123456789ABCDEF")
  546. // Sample 2 is '\x80' + ASCII("TTI UNAVAILABLE")
  547. unsigned char const samples[2][16]
  548. = {
  549. { 0x80, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41,
  550. 0x42, 0x43, 0x44, 0x45, 0x46 },
  551. { 0x80, 0x54, 0x54, 0x49, 0x20, 0x55, 0x4E, 0x41, 0x56, 0x41, 0x49,
  552. 0x4C, 0x41, 0x42, 0x4C, 0x45 }
  553. };
  554. unsigned const results[2] = { 0x62, 0x23 };
  555. // Basic computer
  556. boost::crc_basic<7> tester1( 0x09 );
  557. tester1.process_bytes( samples[0], 16 );
  558. BOOST_TEST_EQ( tester1.checksum(), results[0] );
  559. tester1.reset();
  560. tester1.process_bytes( samples[1], 16 );
  561. BOOST_TEST_EQ( tester1.checksum(), results[1] );
  562. // Optimal computer
  563. #define PRIVATE_CRC_FUNC boost::crc<7, 0x09, 0, 0, false, false>
  564. #define PRIVATE_ACRC_FUNC boost::augmented_crc<7, 0x09>
  565. BOOST_TEST_EQ( results[0], PRIVATE_CRC_FUNC(samples[0], 16) );
  566. BOOST_TEST_EQ( results[1], PRIVATE_CRC_FUNC(samples[1], 16) );
  567. // maybe the fix to CRC functions needs to be applied to augmented CRCs?
  568. #undef PRIVATE_ACRC_FUNC
  569. #undef PRIVATE_CRC_FUNC
  570. }
  571. #ifndef BOOST_MSVC
  572. // Explicit template instantiations
  573. // (needed to fix a link error in Metrowerks CodeWarrior Pro 5.3)
  574. template class crc_tester<16, 0x1021, 0xFFFF, 0, false, false>;
  575. template class crc_tester<16, 0x8005, 0, 0, true, true>;
  576. template class crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>;
  577. #endif
  578. // Main testing function
  579. int main()
  580. {
  581. using std::cout;
  582. using std::endl;
  583. // Run simulations on some CRC types
  584. typedef crc_tester<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_tester;
  585. typedef crc_tester<16, 0x8005, 0, 0, true, true> crc_16_tester;
  586. typedef crc_tester<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true>
  587. crc_32_tester;
  588. crc_ccitt_tester::master_test( "CRC-CCITT", std_crc_ccitt_result );
  589. crc_16_tester::master_test( "CRC-16", std_crc_16_result );
  590. crc_32_tester::master_test( "CRC-32", std_crc_32_result );
  591. // Run a timing comparison test
  592. timing_test();
  593. // Test using augmented messages
  594. augmented_tests();
  595. // Test with CRC types smaller than a byte
  596. small_crc_test1();
  597. small_crc_test2();
  598. // Try a CRC based on the (x + 1) polynominal, which is a factor in
  599. // many real-life polynominals and doesn't fit evenly in a byte.
  600. cout << "Doing one-bit polynominal CRC test." << endl;
  601. boost::crc_basic<1> crc_1( 1 );
  602. crc_1.process_bytes( std_data, std_data_len );
  603. BOOST_TEST_EQ( crc_1.checksum(), 1 );
  604. // Test the function object interface
  605. cout << "Doing functional object interface test." << endl;
  606. boost::crc_optimal<16, 0x8005, 0, 0, true, true> crc_16;
  607. crc_16 = std::for_each( std_data, std_data + std_data_len, crc_16 );
  608. BOOST_TEST_EQ( crc_16(), std_crc_16_result );
  609. return boost::report_errors();
  610. }