• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>&lt;<a
12href="../../boost/crc.hpp">boost/crc.hpp</a>&gt;</cite></h1>
13
14<p>The header <cite>&lt;<a
15href="../../boost/crc.hpp">boost/crc.hpp</a>&gt;</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 &lt;boost/integer.hpp&gt;  <i>// for boost::uint_t</i>
49#include &lt;cstddef&gt;            <i>// for std::size_t</i>
50
51namespace boost
52{
53
54template &lt; std::size_t Bits &gt;
55    class crc_basic;
56
57template &lt; 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 &gt;
61    class crc_optimal;
62
63template &lt; 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 &gt;
66    typename uint_t&lt;Bits&gt;::fast  crc( void const *buffer,
67     std::size_t byte_count );
68
69template &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
70    typename uint_t&lt;Bits&gt;::fast  augmented_crc( void const *buffer,
71     std::size_t byte_count,
72     typename uint_t&lt;Bits&gt;::fast initial_remainder = 0u );
73
74typedef crc_optimal&lt;16, 0x8005, 0, 0, true, true&gt;         crc_16_type;
75typedef crc_optimal&lt;16, 0x1021, 0xFFFF, 0, false, false&gt;  crc_ccitt_type;
76typedef crc_optimal&lt;16, 0x8408, 0, 0, true, true&gt;         crc_xmodem_type;
77
78typedef crc_optimal&lt;32, 0x04C11DB7, 0xFFFFFFFF, 0xFFFFFFFF, true, true&gt;
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 &quot;blind spots.&quot;  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 &lt; std::size_t Bits &gt;
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&lt;Bits&gt;::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 &lt; 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 &gt;
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&lt;Bits&gt;::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 &lt;boost/crc.hpp&gt;      <i>// for boost::crc_basic, boost::crc_optimal</i>
379#include &lt;boost/cstdint.hpp&gt;  <i>// for boost::uint16_t</i>
380
381#include &lt;algorithm&gt;  <i>// for std::for_each</i>
382#include &lt;cassert&gt;    <i>// for assert</i>
383#include &lt;cstddef&gt;    <i>// for std::size_t</i>
384#include &lt;iostream&gt;   <i>// for std::cout</i>
385#include &lt;ostream&gt;    <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&lt;16&gt;  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&lt;16, 0x1021, 0xFFFF, 0, false, false&gt;  crc_ccitt2;
407    crc_ccitt2 = std::for_each( data, data + data_len, crc_ccitt2 );
408    assert( crc_ccitt2() == expected );
409
410    std::cout &lt;&lt; "All tests passed." &lt;&lt; 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 &lt; 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 &gt;
420typename boost::uint_t&lt;Bits&gt;::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 &lt; std::size_t Bits, <em>impl_def</em> TruncPoly &gt;
434typename boost::uint_t&lt;Bits&gt;::fast
435boost::augmented_crc( void const *buffer, std::size_t byte_count,
436 typename boost::uint_t&lt;Bits&gt;::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 &lt;boost/crc.hpp&gt;      <i>// for boost::crc_basic, boost::augmented_crc</i>
489#include &lt;boost/cstdint.hpp&gt;  <i>// for boost::uint16_t</i>
490
491#include &lt;cassert&gt;    <i>// for assert</i>
492#include &lt;iostream&gt;   <i>// for std::cout</i>
493#include &lt;ostream&gt;    <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&lt;16, 0x8005&gt;( data, sizeof(data), init_rem );
507
508    uint16_t const  zero = 0;
509    uint16_t const  new_init_rem = augmented_crc&lt;16, 0x8005&gt;( &amp;zero, sizeof(zero) );
510
511    boost::crc_basic&lt;16&gt;  crc2( 0x8005, new_init_rem );
512    crc2.process_block( data, &amp;data[5] );  // don't include CRC
513    assert( crc2.checksum() == crc1 );
514
515    std::cout &lt;&lt; "All tests passed." &lt;&lt; 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&quot;good&quot; 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&eacute; Consultatif International
541		    T&eacute;l&eacute;graphique et T&eacute;l&eacute;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 &quot;Slow and Steady
574		Never Lost the Race&quot; in the January 2000 issue of <cite><a
575		href="http://www.embedded.com/">Embedded Systems
576		Programming</a></cite>, pages 37&ndash;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&lt;<a href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>
630
631</body>
632</html>
633