From 5eec31a61fe444cfd7b70fa90acfb41cb5e07f18 Mon Sep 17 00:00:00 2001 From: Ahmet Inan Date: Sat, 28 Jul 2018 21:05:26 +0200 Subject: [PATCH] need CRCs way to often --- README.md | 16 ++++++++++++ crc.hh | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 crc.hh diff --git a/README.md b/README.md index 38342df..960cf16 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,19 @@ Read and write [WAV](https://en.wikipedia.org/wiki/WAV) files Algorithm for computing uniform and [natural cubic splines](https://en.wikipedia.org/wiki/Spline_(mathematics)#Algorithm_for_computing_natural_cubic_splines) Very useful for data interpolation. +### [crc.hh](crc.hh) + +A [Cyclic redundancy check](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) may not really be DSP-related, but it is needed over and over again when you do DSP that it fits just perfectly here. + +For example, if we need to integrate CRC32 checking for a few bytes, like in the following: +``` +# echo -n 'Hello World!' | rhash -C - +(stdin) 1C291CA3 +``` +We can add it to our project as simple as that: +``` +DSP::CRC crc(0xEDB88320, 0xFFFFFFFF); +for (uint8_t c: std::string("Hello World!")) crc(c); +assert(!crc(uint32_t(~0x1C291CA3))); +``` + diff --git a/crc.hh b/crc.hh new file mode 100644 index 0000000..3ff8ede --- /dev/null +++ b/crc.hh @@ -0,0 +1,77 @@ +/* +Cyclic redundancy check + +Copyright 2018 Ahmet Inan +*/ + +#ifndef CRC_HH +#define CRC_HH + +namespace DSP { + +template +class CRC +{ + static const int BYTES = sizeof(TYPE); + TYPE lut[BYTES * 256]; + TYPE poly; + TYPE crc; +public: + CRC(TYPE poly, TYPE crc = 0) : poly(poly), crc(crc) + { + // exploit linearity of CRC only bytewise + for (int k = 0; k < BYTES; ++k) { + for (int j = 0; j < 256; ++j) { + TYPE tmp = j << (k << 3); + for (int i = 8; i; --i) + tmp = (tmp >> 1) ^ ((tmp & 1) * poly); + lut[(k << 8) + j] = tmp; + } + } + } + void reset(TYPE v) + { + crc = v; + } + TYPE operator()(bool data) + { + TYPE tmp = crc ^ data; + tmp = (tmp >> 1) ^ ((tmp & 1) * poly); + return crc = tmp; + } + TYPE operator()(uint8_t data) + { + TYPE tmp = crc ^ data; + crc = lut[tmp & 255]; + for (int k = 1; k < BYTES; ++k) + crc ^= lut[(k << 8) + ((tmp >>= 8) & 255)]; + return crc; + } + template + TYPE operator()(DATA data) + { + for (int i = sizeof(data); i; --i) { + (*this)((uint8_t)data); + data >>= 8; + } + return crc; + } +}; + +template<> +uint16_t CRC::operator()(uint8_t data) +{ + uint16_t tmp = crc ^ data; + return crc = lut[256 + (tmp >> 8)] ^ lut[tmp & 255]; +} + +template<> +uint8_t CRC::operator()(uint8_t data) +{ + return crc = lut[crc ^ data]; +} + +} + +#endif +