commit ee79ff2b2d1804ef399e54f5eacb77974727b8a6 Author: Ahmet Inan Date: Thu Sep 20 08:36:45 2018 +0200 moved crc and xorshift from DSP to CODE repository diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a01ee28 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.*.swp diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5e19f16 --- /dev/null +++ b/LICENSE @@ -0,0 +1,5 @@ +Copyright (C) 2018 by Ahmet Inan + +Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..787907a --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +This is a work in progress and a long overdue attempt to bring all our not-DSP-related code together and make it reusable for our future projects. + +Before using any of this you should enter the tests directory and execute "make". +This will check if your compiler is able to create binaries that are able to produce correct results when executed. + +What we have included so far: + +### [crc.hh](crc.hh) + +A [Cyclic redundancy check](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) helps ensuring data integrity. + +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() == 0x1C291CA3); +``` + +### [xorshift.hh](xorshift.hh) + +Sometimes we need a sequence of ["random enough"](https://en.wikipedia.org/wiki/Diehard_tests) numbers but don't want to store them in an array to get a repeatable sequence. +Here a [Pseudorandom number generator](https://en.wikipedia.org/wiki/Pseudorandom_number_generator) can help by prodiving a deterministic and thus repeatable sequence of numbers. +[George Marsaglia](https://en.wikipedia.org/wiki/George_Marsaglia) discovered a class of simple and fast pseudorandom number generators, which he called [Xorshift](https://en.wikipedia.org/wiki/Xorshift). + diff --git a/crc.hh b/crc.hh new file mode 100644 index 0000000..45d4df1 --- /dev/null +++ b/crc.hh @@ -0,0 +1,88 @@ +/* +Cyclic redundancy check + +Copyright 2018 Ahmet Inan +*/ + +#ifndef CRC_HH +#define CRC_HH + +namespace CODE { + +template +class CRC +{ + TYPE lut[256]; + TYPE poly; + TYPE crc; + TYPE update(TYPE prev, bool data) + { + TYPE tmp = prev ^ data; + return (prev >> 1) ^ ((tmp & 1) * poly); + } +public: + CRC(TYPE poly, TYPE crc = 0) : poly(poly), crc(crc) + { + for (int j = 0; j < 256; ++j) { + TYPE tmp = j; + for (int i = 8; i; --i) + tmp = update(tmp, 0); + lut[j] = tmp; + } + } + void reset(TYPE v = 0) + { + crc = v; + } + TYPE operator()() + { + return crc; + } + TYPE operator()(bool data) + { + return crc = update(crc, data); + } + TYPE operator()(uint8_t data) + { + TYPE tmp = crc ^ data; + return crc = (crc >> 8) ^ lut[tmp & 255]; + } + + TYPE operator()(uint16_t data) + { + (*this)(uint8_t(data & 255)); + (*this)(uint8_t((data >> 8) & 255)); + return crc; + } + TYPE operator()(uint32_t data) + { + (*this)(uint8_t(data & 255)); + (*this)(uint8_t((data >> 8) & 255)); + (*this)(uint8_t((data >> 16) & 255)); + (*this)(uint8_t((data >> 24) & 255)); + return crc; + } + TYPE operator()(uint64_t data) + { + (*this)(uint8_t(data & 255)); + (*this)(uint8_t((data >> 8) & 255)); + (*this)(uint8_t((data >> 16) & 255)); + (*this)(uint8_t((data >> 24) & 255)); + (*this)(uint8_t((data >> 32) & 255)); + (*this)(uint8_t((data >> 40) & 255)); + (*this)(uint8_t((data >> 48) & 255)); + (*this)(uint8_t((data >> 56) & 255)); + return crc; + } +}; + +template<> +uint8_t CRC::operator()(uint8_t data) +{ + return crc = lut[crc ^ data]; +} + +} + +#endif + diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 0000000..8144904 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +*_test diff --git a/tests/Makefile b/tests/Makefile new file mode 100644 index 0000000..c935b00 --- /dev/null +++ b/tests/Makefile @@ -0,0 +1,15 @@ + +CXXFLAGS = -I.. -std=c++17 -W -Wall -Ofast -fno-exceptions -fno-rtti -march=native +CXX = clang++ -stdlib=libc++ +#CXX = g++ + +.PHONY: clean test + +tests := $(basename $(wildcard *_test.*)) + +test: $(tests) + $(patsubst %,./%;,$(tests)) + +clean: + rm -f *_test + diff --git a/tests/crc_test.cc b/tests/crc_test.cc new file mode 100644 index 0000000..efae651 --- /dev/null +++ b/tests/crc_test.cc @@ -0,0 +1,37 @@ +/* +Test for the Cyclic redundancy check + +Copyright 2018 Ahmet Inan +*/ + +#include +#include +#include +#include "crc.hh" + +int main() +{ + if (1) { + CODE::CRC crc(0xEDB88320, 0xFFFFFFFF); + for (uint8_t c: std::string("Hello World!")) crc(c); + assert(~crc() == 0x1C291CA3); + } + if (1) { + CODE::CRC crc(0xA8F4); + for (uint8_t c: std::string("Hello World!")) crc(c); + assert(!crc(uint16_t(0x8FEF))); + crc.reset(0x9B38); + std::bitset<32> hw("00000010001001110111110100100100"); + for (size_t i = 0; i < hw.size(); ++i) crc(hw[i]); + //std::cerr << "0x" << std::hex << crc() << std::endl; + assert(crc() == 0x915D); + } + if (1) { + CODE::CRC crc(0x8C); + for (uint8_t c: std::string("Hello World!")) crc(c); + assert(!crc(uint8_t(0x9E))); + } + std::cerr << "Cyclic redundancy check test passed!" << std::endl; + return 0; +} + diff --git a/xorshift.hh b/xorshift.hh new file mode 100644 index 0000000..3999fa0 --- /dev/null +++ b/xorshift.hh @@ -0,0 +1,116 @@ +/* +Class of pseudorandom number generators, discovered by George Marsaglia + +Copyright 2018 Ahmet Inan +*/ + +#ifndef XORSHIFT_HH +#define XORSHIFT_HH + +namespace CODE { + +class Xorshift32 +{ + static const uint32_t Y = 2463534242; + uint32_t y_; +public: + Xorshift32(uint32_t y = Y) : y_(y) {} + void reset(uint32_t y = Y) + { + y_ = y; + } + uint32_t operator()() + { + y_ ^= y_ << 13; + y_ ^= y_ >> 17; + y_ ^= y_ << 5; + return y_; + } +}; + +class Xorshift64 +{ + static const uint64_t X = 88172645463325252; + uint64_t x_; +public: + Xorshift64(uint64_t x = X) : x_(x) {} + void reset(uint64_t x = X) + { + x_ = x; + } + uint64_t operator()() + { + x_ ^= x_ << 13; + x_ ^= x_ >> 7; + x_ ^= x_ << 17; + return x_; + } +}; + +class Xorwow +{ + static const uint32_t X = 123456789; + static const uint32_t Y = 362436069; + static const uint32_t Z = 521288629; + static const uint32_t W = 88675123; + static const uint32_t V = 5783321; + static const uint32_t D = 6615241; + uint32_t x_, y_, z_, w_, v_, d_; +public: + Xorwow(uint32_t x = X, uint32_t y = Y, + uint32_t z = Z, uint32_t w = W, + uint32_t v = V, uint32_t d = D) : + x_(x), y_(y), z_(z), w_(w), v_(v), d_(d) {} + void reset(uint32_t x = X, uint32_t y = Y, + uint32_t z = Z, uint32_t w = W, + uint32_t v = V, uint32_t d = D) + { + x_ = x; + y_ = y; + z_ = z; + w_ = w; + v_ = v; + d_ = d; + } + uint32_t operator()() + { + uint32_t t = x_ ^ (x_ >> 2); + x_ = y_; y_ = z_; z_ = w_; w_ = v_; + v_ = (v_ ^ (v_ << 4)) ^ (t ^ (t << 1)); + d_ += 362437; + return d_ + v_; + } +}; + +class Xorshift128 +{ + static const uint32_t X = 123456789; + static const uint32_t Y = 362436069; + static const uint32_t Z = 521288629; + static const uint32_t W = 88675123; + uint32_t x_, y_, z_, w_; +public: + Xorshift128(uint32_t x = X, uint32_t y = Y, + uint32_t z = Z, uint32_t w = W) : + x_(x), y_(y), z_(z), w_(w) {} + void reset(uint32_t x = X, uint32_t y = Y, + uint32_t z = Z, uint32_t w = W) + { + x_ = x; + y_ = y; + z_ = z; + w_ = w; + } + uint32_t operator()() + { + uint32_t t = (x_ ^ (x_ << 11)); + x_ = y_; y_ = z_; z_ = w_; + w_ = (w_ ^ (w_ >> 19)) ^ (t ^ (t >> 8)); + return w_; + } +}; + +} + +#endif +