1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> 2<html> 3<head> 4<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 5<title>Boost CRC Library Documentation</title> 6</head> 7 8<body text="black" bgcolor="white" link="blue" vlink="purple" alink="red"> 9 10<h1><img src="../../boost.png" alt="boost.png (6897 bytes)" 11align="middle" width="277" height="86">Header <cite><<a 12href="../../boost/crc.hpp">boost/crc.hpp</a>></cite></h1> 13 14<p>The header <cite><<a 15href="../../boost/crc.hpp">boost/crc.hpp</a>></cite> supplies two 16class templates in namespace <code>boost</code>. These templates define 17objects that can compute the <dfn>CRC</dfn>, or cyclic redundancy code 18(or check), of a given stream of data. The header also supplies 19function templates to compute a CRC in one step.</p> 20 21<h2><a name="contents">Contents</a></h2> 22 23<ol> 24 <li><a href="#contents">Contents</a></li> 25 <li><a href="#header">Header Synopsis</a></li> 26 <li><a href="#rationale">Rationale</a></li> 27 <li><a href="#background">Background</a> 28 <ul> 29 <li><a href="#parameters">CRC Parameters</a></li> 30 </ul></li> 31 <li><a href="#crc_basic">Theoretical CRC Computer</a></li> 32 <li><a href="#crc_optimal">Optimized CRC Computer</a></li> 33 <li><a href="#usage">Computer Usage</a></li> 34 <li><a href="#crc_func">CRC Function</a></li> 35 <li><a href="#a_crc_func">Augmented-CRC Function</a></li> 36 <li><a href="#crc_ex">Pre-Defined CRC Samples</a></li> 37 <li><a href="#references">References</a></li> 38 <li><a href="#credits">Credits</a> 39 <ul> 40 <li><a href="#contributors">Contributors</a></li> 41 <li><a href="#acknowledgements">Acknowledgements</a></li> 42 <li><a href="#history">History</a></li> 43 </ul></li> 44</ol> 45 46<h2><a name="header">Header Synopsis</a></h2> 47 48<blockquote><pre>#include <boost/integer.hpp> <i>// for boost::uint_t</i> 49#include <cstddef> <i>// for std::size_t</i> 50 51namespace boost 52{ 53 54template < std::size_t Bits > 55 class crc_basic; 56 57template < std::size_t Bits, <em>impl_def</em> TruncPoly = 0u, 58 <em>impl_def</em> InitRem = 0u, 59 <em>impl_def</em> FinalXor = 0u, bool ReflectIn = false, 60 bool ReflectRem = false > 61 class crc_optimal; 62 63template < std::size_t Bits, <em>impl_def</em> TruncPoly, 64 <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor, 65 bool ReflectIn, bool ReflectRem > 66 typename uint_t<Bits>::fast crc( void const *buffer, 67 std::size_t byte_count ); 68 69template < std::size_t Bits, <em>impl_def</em> TruncPoly > 70 typename uint_t<Bits>::fast augmented_crc( void const *buffer, 71 std::size_t byte_count, 72 typename uint_t<Bits>::fast initial_remainder = 0u ); 73 74typedef crc_optimal<16, 0x8005, 0, 0, true, true> crc_16_type; 75typedef crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt_type; 76typedef crc_optimal<16, 0x8408, 0, 0, true, true> crc_xmodem_type; 77 78typedef crc_optimal<32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true> 79 crc_32_type; 80 81} 82</pre></blockquote> 83 84<p>The implementation-defined type <var>impl_def</var> stands for the 85quickest-to-manipulate built-in unsigned integral type that can 86represent at least <var>Bits</var> bits.</p> 87 88<h2><a name="rationale">Rationale</a></h2> 89 90<p>A common error detection technique, especially with electronic 91communications, is an appended checksum. The transmitter sends its data 92bits, followed by the bits of the checksum. The checksum is based on 93operations done on the data bit stream. The receiver applies the same 94operations on the bits it gets, and then gets the checksum. If the 95computed checksum doesn't match the received checksum, then an error 96ocurred in the transmission. There is the slight chance that the error 97is only in the checksum, and an actually-correct data stream is 98rejected. There is also the chance of an error occurring that does not 99change the checksum, making that error invisible. CRC is a common 100checksum type, used for error detection for hardware interfaces and 101encoding formats.</p> 102 103<h2><a name="background">Background</a></h2> 104 105<p>CRCs work by computing the remainder of a modulo-2 polynominal 106division. The message is treated as the (binary) coefficents of a long 107polynominal for the dividend, with the earlier bits of the message fed 108first as the polynominal's highest coefficents. A particular CRC 109algorithm has another polynominal associated with it to be used as the 110divisor. The quotient is ignored. The remainder of the division 111considered the checksum. However, the division uses modulo-2 rules (no 112carries) for the coefficents.</p> 113 114<p>See <cite><a href="http://www.ross.net/crc/crcpaper.html">A 115Painless Guide to CRC Error Detection Algorithms</a></cite> for complete 116information. A clearer guide is at the <a 117href="http://www.netrino.com/Embedded-Systems/How-To/CRC-Calculation-C-Code">CRC 118Implementation Code in C</a> web page.</p> 119 120<h3><a name="parameters">CRC Parameters</a></h3> 121 122<dl> 123 <dt>Truncated polynominal 124 <dd>The divisor polynominal has a degree one bit larger than the 125 checksum (remainder) size. That highest bit is always one, so 126 it is ignored when describing a particular CRC type. Excluding 127 this bit makes the divisor fit in the same data type as the 128 checksum. 129 130 <dt>Initial remainder 131 <dd>The interim CRC remainder changes as each bit is processed. 132 Usually, the interim remainder starts at zero, but some CRCs use 133 a different initial value to avoid "blind spots." A 134 blind spot is when a common sequence of message bits does not 135 change certain interim remainder values. 136 137 <dt>Final XOR value 138 <dd>A CRC remainder can be combined with a defined value, <i>via</i> 139 a bitwise exclusive-or operation, before being returned to the 140 user. The value is usually zero, meaning the interim remainder 141 is returned unchanged. The other common value is an all-ones 142 value, meaning that the bitwise complement of the interim 143 remainder is returned. 144 145 <dt>Reflected input 146 <dd>A message's bits are usually fed a byte at a time, with the 147 highest bits of the byte treated as the higher bits of the 148 dividend polynominal. Some CRCs reflect the bits (about the 149 byte's center, so the first and last bits are switched, 150 <i>etc.</i>) before feeding. 151 152 <dt>Reflected (remainder) output 153 <dd>Some CRCs return the reflection of the interim remainder (taking 154 place <em>before</em> the final XOR value stage). 155</dl> 156 157<h2><a name="crc_basic">Theoretical CRC Computer</a></h2> 158 159<blockquote><pre>template < std::size_t Bits > 160class boost::crc_basic 161{ 162public: 163 // Type 164 typedef <em>implementation_defined</em> value_type; 165 166 // Constant reflecting template parameter 167 static std::size_t const bit_count = Bits; 168 169 // Constructor 170 explicit crc_basic( value_type truncated_polynominal, 171 value_type initial_remainder = 0, value_type final_xor_value = 0, 172 bool reflect_input = false, bool reflect_remainder = false ); 173 174 // Internal Operations 175 value_type get_truncated_polynominal() const; 176 value_type get_initial_remainder() const; 177 value_type get_final_xor_value() const; 178 bool get_reflect_input() const; 179 bool get_reflect_remainder() const; 180 181 value_type get_interim_remainder() const; 182 void reset( value_type new_rem ); 183 void reset(); 184 185 // External Operations 186 void process_bit( bool bit ); 187 void process_bits( unsigned char bits, std::size_t bit_count ); 188 void process_byte( unsigned char byte ); 189 void process_block( void const *bytes_begin, void const *bytes_end ); 190 void process_bytes( void const *buffer, std::size_t byte_count ); 191 192 value_type checksum() const; 193 194}; 195</pre></blockquote> 196 197<p>The <code>value_type</code> is the smallest built-in type that can 198hold the specified (by <code>Bits</code>) number of bits. This should 199be <code>boost::uint_t<Bits>::least</code>, see the <a 200href="../integer/doc/html/boost_integer/integer.html">documentation for integer type 201selection</a> for details.</p> 202 203<p>This implementation is slow since it computes its CRC the same way as 204in theory, bit by bit. No optimizations are performed. It wastes space 205since most of the CRC parameters are specified at run-time as 206constructor parameters.</p> 207 208<h2><a name="crc_optimal">Optimized CRC Computer</a></h2> 209 210<blockquote><pre>template < std::size_t Bits, <em>impl_def</em> TruncPoly, 211 <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor, 212 bool ReflectIn, bool ReflectRem > 213class boost::crc_optimal 214{ 215public: 216 // Type 217 typedef <em>implementation_defined</em> value_type; 218 219 // Constants reflecting template parameters 220 static std::size_t const bit_count = Bits; 221 static value_type const truncated_polynominal = TruncPoly; 222 static value_type const initial_remainder = InitRem; 223 static value_type const final_xor_value = FinalXor; 224 static bool const reflect_input = ReflectIn; 225 static bool const reflect_remainder = ReflectRem; 226 227 // Constructor 228 explicit crc_optimal( value_type init_rem = InitRem ); 229 230 // Internal Operations 231 value_type get_truncated_polynominal() const; 232 value_type get_initial_remainder() const; 233 value_type get_final_xor_value() const; 234 bool get_reflect_input() const; 235 bool get_reflect_remainder() const; 236 237 value_type get_interim_remainder() const; 238 void reset( value_type new_rem = InitRem ); 239 240 // External Operations 241 void process_byte( unsigned char byte ); 242 void process_block( void const *bytes_begin, void const *bytes_end ); 243 void process_bytes( void const *buffer, std::size_t byte_count ); 244 245 value_type checksum() const; 246 247 // Operators 248 void operator ()( unsigned char byte ); 249 value_type operator ()() const; 250 251}; 252</pre></blockquote> 253 254<p>The <code>value_type</code> is the quickest-to-manipulate built-in 255type that can hold at least the specified (by <code>Bits</code>) number 256of bits. This should be <code>boost::uint_t<Bits>::fast</code>. 257See the <a href="../integer/doc/html/boost_integer/integer.html">integer type selection 258documentation</a> for details. The <code>TruncPoly</code>, 259<code>InitRem</code>, and <code>FinalXor</code> template parameters also 260are of this type.</p> 261 262<p>This implementation is fast since it uses as many optimizations as 263practical. All of the CRC parameters are specified at compile-time as 264template parameters. No individual bits are considered; only whole 265bytes are passed. A table of interim CRC values versus byte values is 266pre-computed when the first object using a particular bit size, 267truncated polynominal, and input reflection state is processed.</p> 268 269<h2><a name="usage">Computer Usage</a></h2> 270 271<p>The two class templates have different policies on where the CRC's 272parameters go. Both class templates use the number of bits in the CRC 273as the first template parameter. The theoretical computer class 274template has the bit count as its only template parameter, all the other 275CRC parameters are entered through the constructor. The optimized 276computer class template obtains all its CRC parameters as template 277parameters, and instantiated objects are usually 278default-constructed.</p> 279 280<p>The CRC parameters can be inspected at run-time with the following 281member functions: <code>get_truncated_polynominal</code>, 282<code>get_initial_remainder</code>, <code>get_final_xor_value</code>, 283<code>get_reflect_input</code>, and <code>get_reflect_remainder</code>. 284The fast computer also provides compile-time constants for its CRC 285parameters.</p> 286 287<p>The <code>get_interim_remainder</code> member function returns the 288internal state of the CRC remainder. It represents the unreflected 289remainder of the last division. Saving an interim remainder allows the 290freezing of CRC processing, as long as the other CRC parameters and the 291current position of the bit stream are saved. Restarting a frozen 292stream involves constructing a new computer with the most of the old 293computer's parameters. The only change is to use the frozen remainder 294as the new computer's initial remainder. Then the interrupted bit 295stream can be fed as if nothing happened. The fast CRC computer has a 296special constructor that takes one argument, an interim remainder, for 297this purpose (overriding the initial remainder CRC parameter).</p> 298 299<p>The <code>reset</code> member functions reset the internal state of 300the CRC remainder to the given value. If no value is given, then the 301internal remainder is set to the initial remainder value when the object 302was created. The remainder must be unreflected. When a CRC calculation 303is finished, calling <code>reset</code> lets the object be reused for a 304new session.</p> 305 306<p>After any construction, both CRC computers work the same way. 307Feeding new data to a computer is in a seperate operation(s) from 308extracting the current CRC value from the computer. The following table 309lists the feeding and extracting operations.</p> 310 311<table cellpadding="5" border="1"> 312 <caption>Regular CRC Operations</caption> 313 <tr> 314 <th>Operation</th> 315 <th>Description</th> 316 </tr> 317 <tr> 318 <td><code>void process_bit( bool bit );</code></td> 319 <td>Feeds the single <var>bit</var> to the computer, updating 320 the interim CRC. It is only defined for the slow CRC 321 computer.</td> 322 </tr> 323 <tr> 324 <td><code>void process_bits( unsigned char bits, std::size_t 325 bit_count );</code></td> 326 <td>Acts as applying <code>process_bit</code> to the lowest 327 <var>bit_count</var> bits given in <var>bits</var>, most 328 significant relevant bit first. The results are undefined 329 if <var>bit_count</var> exceeds the number of bits per byte. 330 It is only defined for the slow CRC computer.</td> 331 </tr> 332 <tr> 333 <td><code>void process_byte( unsigned char byte );</code></td> 334 <td>Acts as applying <code>process_bit</code> to the all the 335 bits in <var>byte</var>. If reflection is not desired, the 336 bits are fed from the most to least significant. The bits 337 are fed in the opposite order if reflection is desired.</td> 338 </tr> 339 <tr> 340 <td><code>void process_block( void const *bytes_begin, void 341 const *bytes_end );</code></td> 342 <td>Acts as applying <code>process_byte</code> to each byte in 343 the given memory block. This memory block starts at 344 <var>bytes_begin</var> and finishes before 345 <var>bytes_end</var>. The bytes are processed in that 346 order.</td> 347 </tr> 348 <tr> 349 <td><code>void process_bytes( void const *buffer, std::size_t 350 byte_count );</code></td> 351 <td>Acts as applying <code>process_byte</code> to each byte in 352 the given memory block. This memory block starts at 353 <var>buffer</var> and lasts for <var>byte_count</var> bytes. 354 The bytes are processed in ascending order.</td> 355 </tr> 356 <tr> 357 <td><code>value_type checksum() const;</code></td> 358 <td>Returns the CRC checksum of the data passed in so far, 359 possibly after applying the remainder-reflection and 360 exclusive-or operations.</td> 361 </tr> 362 <tr> 363 <td><code>void operator ()( unsigned char byte );</code></td> 364 <td>Calls <code>process_byte</code>. This member function lets 365 its object act as a (stateful) function object. It is only 366 defined for the fast CRC computer.</td> 367 </tr> 368 <tr> 369 <td><code>value_type operator ()() const;</code></td> 370 <td>Calls <code>checksum</code>. This member function lets 371 its object act as a generator function object. It is only 372 defined for the fast CRC computer.</td> 373 </tr> 374</table> 375 376<p>You can use them like this:</p> 377 378<blockquote><pre>#include <boost/crc.hpp> <i>// for boost::crc_basic, boost::crc_optimal</i> 379#include <boost/cstdint.hpp> <i>// for boost::uint16_t</i> 380 381#include <algorithm> <i>// for std::for_each</i> 382#include <cassert> <i>// for assert</i> 383#include <cstddef> <i>// for std::size_t</i> 384#include <iostream> <i>// for std::cout</i> 385#include <ostream> <i>// for std::endl</i> 386 387 388// Main function 389int 390main () 391{ 392 // This is "123456789" in ASCII 393 unsigned char const data[] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 394 0x38, 0x39 }; 395 std::size_t const data_len = sizeof( data ) / sizeof( data[0] ); 396 397 // The expected CRC for the given data 398 boost::uint16_t const expected = 0x29B1; 399 400 // Simulate CRC-CCITT 401 boost::crc_basic<16> crc_ccitt1( 0x1021, 0xFFFF, 0, false, false ); 402 crc_ccitt1.process_bytes( data, data_len ); 403 assert( crc_ccitt1.checksum() == expected ); 404 405 // Repeat with the optimal version (assuming a 16-bit type exists) 406 boost::crc_optimal<16, 0x1021, 0xFFFF, 0, false, false> crc_ccitt2; 407 crc_ccitt2 = std::for_each( data, data + data_len, crc_ccitt2 ); 408 assert( crc_ccitt2() == expected ); 409 410 std::cout << "All tests passed." << std::endl; 411 return 0; 412} 413</pre></blockquote> 414 415<h2><a name="crc_func">CRC Function</a></h2> 416 417<blockquote><pre>template < std::size_t Bits, <em>impl_def</em> TruncPoly, 418 <em>impl_def</em> InitRem, <em>impl_def</em> FinalXor, 419 bool ReflectIn, bool ReflectRem > 420typename boost::uint_t<Bits>::fast 421boost::crc( void const *buffer, std::size_t byte_count ); 422</pre></blockquote> 423 424<p>The <code>boost::crc</code> function template computes the CRC of a 425given data block. The data block starts at the address given by 426<var>buffer</var> and lasts for <var>byte_count</var> bytes. The CRC 427parameters are passed through template arguments, identical to the 428optimized CRC computer (<a href="#crc_optimal">see above</a>). In fact, 429such a computer is used to implement this function.</p> 430 431<h2><a name="a_crc_func">Augmented-CRC Function</a></h2> 432 433<blockquote><pre>template < std::size_t Bits, <em>impl_def</em> TruncPoly > 434typename boost::uint_t<Bits>::fast 435boost::augmented_crc( void const *buffer, std::size_t byte_count, 436 typename boost::uint_t<Bits>::fast initial_remainder = 0u ); 437</pre></blockquote> 438 439<p>All the other CRC-computing function or class templates work assuming 440that the division steps start immediately on the first message bits. 441The <code>boost::augmented_crc</code> function template has a 442different division order. Instead of combining (<i>via</i> bitwise 443exclusive-or) the current message bit with the highest bit of a separate 444remainder, these templates shift a new message bit into the low bit of a 445remainder register as the highest bit is shifted out. The new method 446means that the bits in the inital remainder value are processed before 447any of the actual message bits are processed. To compensate, the real 448CRC can only be extracted after feeding enough zero bits (the same count 449as the register size) after the message bits.</p> 450 451<p>The template parameters of the function template are 452the CRC's bit size (<code>Bits</code>) and the truncated polynominal 453(<code>TruncPoly</code>). The function parameters are the starting address of 454the data block to be worked on (<var>buffer</var>), the number of bytes in that 455data block (<var>byte_count</var>), and the incoming value of the remainder 456(<var>initial_remainder</var>). That last parameter defaults to zero if it is 457ommitted.</p> 458 459<p>This function template is useful if the bytes of the CRC directly 460follow the message's bytes. First, set the bytes of where the CRC will 461go to zero. Then use <code>augmented_crc</code> over the augmented 462message, <i>i.e.</i> the message bytes and the appended CRC bytes. Then 463assign the result to the CRC. To later check a received message, either 464use <code>augmented_crc</code> (with the same parameters as 465transmission, of course) on the received <em>unaugmented</em> message 466and check if the result equals the CRC, or use 467<code>augmented_crc</code> on the received <em>augmented</em> message 468and check if the result equals zero. Note that the CRC has to be stored 469with the more-significant bytes first (big-endian).</p> 470 471<p>Interruptions in the CRC data can be handled by feeding the result of 472<code>augmented_crc</code> of the previous data block as the 473<var>initial_remainder</var> when calling <code>augmented_crc</code> on 474the next data block. Remember that the actual CRC can only be 475determined after feeding the augmented bytes. Since this method uses 476modulo-2 polynominal division at its most raw, neither final XOR values 477nor reflection can be used.</p> 478 479<p>Note that for the same CRC system, the initial remainder for 480augmented message method will be different than for the unaugmented 481message method. The main exception is zero; if the augmented-CRC 482algorithm uses a zero initial remainder, the equivalent unaugmented-CRC 483algorithm will also use a zero initial remainder. Given an initial 484remainder for a augmented-CRC algorithm, the result from processing just 485zero-valued CRC bytes without any message bytes is the equivalent inital 486remainder for the unaugmented-CRC algorithm. An example follows:</p> 487 488<blockquote><pre>#include <boost/crc.hpp> <i>// for boost::crc_basic, boost::augmented_crc</i> 489#include <boost/cstdint.hpp> <i>// for boost::uint16_t</i> 490 491#include <cassert> <i>// for assert</i> 492#include <iostream> <i>// for std::cout</i> 493#include <ostream> <i>// for std::endl</i> 494 495 496// Main function 497int 498main () 499{ 500 using boost::uint16_t; 501 using boost::augmented_crc; 502 503 uint16_t data[6] = { 2, 4, 31, 67, 98, 0 }; 504 uint16_t const init_rem = 0x123; 505 506 uint16_t crc1 = augmented_crc<16, 0x8005>( data, sizeof(data), init_rem ); 507 508 uint16_t const zero = 0; 509 uint16_t const new_init_rem = augmented_crc<16, 0x8005>( &zero, sizeof(zero) ); 510 511 boost::crc_basic<16> crc2( 0x8005, new_init_rem ); 512 crc2.process_block( data, &data[5] ); // don't include CRC 513 assert( crc2.checksum() == crc1 ); 514 515 std::cout << "All tests passed." << std::endl; 516 return 0; 517} 518</pre></blockquote> 519 520<h2><a name="crc_ex">Pre-Defined CRC Samples</a></h2> 521 522<p>Four sample CRC types are given, representing several common CRC 523algorithms. For example, computations from <code>boost::crc_32_type</code> 524can be used for implementing the PKZip standard. Note that, in general, this 525library is concerned with CRC implementation, and not with determining 526"good" sets of CRC parameters.</p> 527 528<table cellpadding="5" border="1"> 529 <caption>Common CRCs</caption> 530 <tr> 531 <th>Algorithm</th> 532 <th>Example Protocols</th> 533 </tr> 534 <tr> 535 <td><code>crc_16_type</code></td> 536 <td>BISYNCH, ARC</td> 537 </tr> 538 <tr> 539 <td><code>crc_ccitt_type</code></td> 540 <td>designated by CCITT (Comité Consultatif International 541 Télégraphique et Téléphonique)</td> 542 </tr> 543 <tr> 544 <td><code>crc_xmodem_type</code></td> 545 <td>XMODEM</td> 546 </tr> 547 <tr> 548 <td><code>crc_32_type</code></td> 549 <td>PKZip, AUTODIN II, Ethernet, FDDI</td> 550 </tr> 551</table> 552 553<hr> 554 555<h2><a name="references">References</a></h2> 556 557<ul> 558 <li>The CRC header itself: <cite><a href="../../boost/crc.hpp">crc.hpp</a></cite> 559 <li>Some test code: <cite><a href="test/crc_test.cpp">crc_test.cpp</a></cite> 560 <li>Some example code: <cite><a href="crc_example.cpp">crc_example.cpp</a></cite> 561</ul> 562 563<h2><a name="credits">Credits</a></h2> 564 565<h3><a name="contributors">Contributors</a></h3> 566 567<dl> 568 <dt>Michael Barr (<a 569 href="mailto:mbarr@netrino.com">mbarr@netrino.com</a>) 570 <dd>Wrote <a 571 href="http://www.netrino.com/Embedded-Systems/How-To/CRC-Calculation-C-Code">CRC 572 Implementation Code in C</a>, a less-confusing guide to implementing CRC 573 algorithms. (Originally published as "Slow and Steady 574 Never Lost the Race" in the January 2000 issue of <cite><a 575 href="http://www.embedded.com/">Embedded Systems 576 Programming</a></cite>, pages 37–46. The web version used to be 577 known as <cite><a href="http://www.netrino.com/Connecting/2000-01/">Easier 578 Said Than Done</a></cite>.) 579 580 <dt>Daryle Walker 581 <dd>Started the library and contributed the theoretical and optimal 582 CRC computation class templates and the CRC computing function 583 template. Contributed <cite><a 584 href="test/crc_test.cpp">crc_test.cpp</a></cite> and <cite><a 585 href="crc_example.cpp">crc_example.cpp</a></cite>. 586 587 <dt>Ross N. Williams 588 <dd>Wrote <cite><a href="http://www.ross.net/crc/crcpaper.html">A 589 Painless Guide to CRC Error Detection Algorithms</a></cite>, a 590 definitive source of CRC information. 591</dl> 592 593<h3><a name="acknowledgements">Acknowledgements</a></h3> 594 595<p>For giving advice on compiler/C++ compliance, implementation, 596interface, algorithms, and bug reports:</p> 597 598<ul> 599 <li>Darin Adler</li> 600 <li>Beman Dawes</li> 601 <li>Doug Gregor</li> 602 <li>John Maddock</li> 603 <li>Joe Mariadassou</li> 604 <li>Jens Maurer</li> 605 <li>Vladimir Prus</li> 606 <li>Joel Young</li> 607</ul> 608 609<h3><a name="history">History</a></h3> 610 611<dl> 612 <dt>18 Dec 2011, Daryle Walker 613 <dd>Folded the two versions of <code>boost::augmented_crc</code> together. 614 615 <dt>15 Jun 2003, Daryle Walker 616 <dd>Added example program. 617 618 <dt>14 May 2001, Daryle Walker 619 <dd>Initial version. 620</dl> 621 622<hr> 623 624<p>Revised: 18 December 2011</p> 625 626<p>Copyright 2001, 2003, 2011 Daryle Walker. Use, modification, and distribution 627are subject to the Boost Software License, Version 1.0. (See accompanying 628file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at 629<<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p> 630 631</body> 632</html> 633