mirror of
https://github.com/TomHarte/CLK.git
synced 2026-04-21 17:16:44 +00:00
Renames: NumberTheory -> Numeric.
This commit is contained in:
+110
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// CRC.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 18/09/2016.
|
||||
// Copyright 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef CRC_hpp
|
||||
#define CRC_hpp
|
||||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
namespace CRC {
|
||||
|
||||
/*! Provides a class capable of generating a CRC from source data. */
|
||||
template <typename T, T reset_value, T xor_output, bool reflect_input, bool reflect_output> class Generator {
|
||||
public:
|
||||
/*!
|
||||
Instantiates a CRC16 that will compute the CRC16 specified by the supplied
|
||||
@c polynomial and @c reset_value.
|
||||
*/
|
||||
Generator(T polynomial): value_(reset_value) {
|
||||
const T top_bit = T(~(T(~0) >> 1));
|
||||
for(int c = 0; c < 256; c++) {
|
||||
T shift_value = static_cast<T>(c << multibyte_shift);
|
||||
for(int b = 0; b < 8; b++) {
|
||||
T exclusive_or = (shift_value&top_bit) ? polynomial : 0;
|
||||
shift_value = static_cast<T>(shift_value << 1) ^ exclusive_or;
|
||||
}
|
||||
xor_table[c] = shift_value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Resets the CRC to the reset value.
|
||||
void reset() { value_ = reset_value; }
|
||||
|
||||
/// Updates the CRC to include @c byte.
|
||||
void add(uint8_t byte) {
|
||||
if(reflect_input) byte = reverse_byte(byte);
|
||||
value_ = static_cast<T>((value_ << 8) ^ xor_table[(value_ >> multibyte_shift) ^ byte]);
|
||||
}
|
||||
|
||||
/// @returns The current value of the CRC.
|
||||
inline T get_value() const {
|
||||
T result = value_^xor_output;
|
||||
if(reflect_output) {
|
||||
T reflected_output = 0;
|
||||
for(std::size_t c = 0; c < sizeof(T); ++c) {
|
||||
reflected_output = T(reflected_output << 8) | T(reverse_byte(result & 0xff));
|
||||
result >>= 8;
|
||||
}
|
||||
return reflected_output;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Sets the current value of the CRC.
|
||||
inline void set_value(T value) { value_ = value; }
|
||||
|
||||
/*!
|
||||
A compound for:
|
||||
|
||||
reset()
|
||||
[add all data from @c data]
|
||||
get_value()
|
||||
*/
|
||||
T compute_crc(const std::vector<uint8_t> &data) {
|
||||
reset();
|
||||
for(const auto &byte: data) add(byte);
|
||||
return get_value();
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int multibyte_shift = (sizeof(T) * 8) - 8;
|
||||
T xor_table[256];
|
||||
T value_;
|
||||
|
||||
constexpr uint8_t reverse_byte(uint8_t byte) const {
|
||||
return
|
||||
((byte & 0x80) ? 0x01 : 0x00) |
|
||||
((byte & 0x40) ? 0x02 : 0x00) |
|
||||
((byte & 0x20) ? 0x04 : 0x00) |
|
||||
((byte & 0x10) ? 0x08 : 0x00) |
|
||||
((byte & 0x08) ? 0x10 : 0x00) |
|
||||
((byte & 0x04) ? 0x20 : 0x00) |
|
||||
((byte & 0x02) ? 0x40 : 0x00) |
|
||||
((byte & 0x01) ? 0x80 : 0x00);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
Provides a generator of 16-bit CCITT CRCs, which amongst other uses are
|
||||
those used by the FM and MFM disk encodings.
|
||||
*/
|
||||
struct CCITT: public Generator<uint16_t, 0xffff, 0x0000, false, false> {
|
||||
CCITT(): Generator(0x1021) {}
|
||||
};
|
||||
|
||||
/*!
|
||||
Provides a generator of "standard 32-bit" CRCs.
|
||||
*/
|
||||
struct CRC32: public Generator<uint32_t, 0xffffffff, 0xffffffff, true, true> {
|
||||
CRC32(): Generator(0x04c11db7) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* CRC_hpp */
|
||||
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// Factors.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 29/07/2016.
|
||||
// Copyright 2016 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef Factors_hpp
|
||||
#define Factors_hpp
|
||||
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
|
||||
namespace Numeric {
|
||||
/*!
|
||||
@returns The greatest common divisor of @c a and @c b.
|
||||
*/
|
||||
template<class T> T greatest_common_divisor(T a, T b) {
|
||||
return std::gcd(a, b);
|
||||
}
|
||||
|
||||
/*!
|
||||
@returns The least common multiple of @c a and @c b computed indirectly via the greatest
|
||||
common divisor.
|
||||
*/
|
||||
template<class T> T least_common_multiple(T a, T b) {
|
||||
return std::lcm(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* Factors_hpp */
|
||||
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// LFSR.hpp
|
||||
// Clock Signal
|
||||
//
|
||||
// Created by Thomas Harte on 19/01/2020.
|
||||
// Copyright © 2020 Thomas Harte. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef LFSR_h
|
||||
#define LFSR_h
|
||||
|
||||
namespace Numeric {
|
||||
|
||||
template <typename IntType> struct LSFRPolynomial {};
|
||||
|
||||
// The following were taken 'at random' from https://users.ece.cmu.edu/~koopman/lfsr/index.html
|
||||
template <> struct LSFRPolynomial<uint64_t> {
|
||||
static constexpr uint64_t value = 0x80000000000019E2;
|
||||
};
|
||||
|
||||
template <> struct LSFRPolynomial<uint32_t> {
|
||||
static constexpr uint32_t value = 0x80000C34;
|
||||
};
|
||||
|
||||
template <> struct LSFRPolynomial<uint16_t> {
|
||||
static constexpr uint16_t value = 0x853E;
|
||||
};
|
||||
|
||||
template <> struct LSFRPolynomial<uint8_t> {
|
||||
static constexpr uint8_t value = 0xAF;
|
||||
};
|
||||
|
||||
/*!
|
||||
Provides a linear-feedback shift register with a random initial state; if no polynomial is supplied
|
||||
then one will be picked that is guaranteed to give the maximal number of LFSR states that can fit
|
||||
in the specified int type.
|
||||
*/
|
||||
template <typename IntType = uint64_t, IntType polynomial = LSFRPolynomial<IntType>::value> class LFSR {
|
||||
public:
|
||||
LFSR() {
|
||||
// Randomise the value, ensuring it doesn't end up being 0.
|
||||
while(!value_) {
|
||||
uint8_t *value_byte = reinterpret_cast<uint8_t *>(&value_);
|
||||
for(size_t c = 0; c < sizeof(IntType); ++c) {
|
||||
*value_byte = uint8_t(uint64_t(rand()) * 255 / RAND_MAX);
|
||||
++value_byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Advances the LSFR, returning either an @c IntType of value @c 1 or @c 0,
|
||||
determining the bit that was just shifted out.
|
||||
*/
|
||||
IntType next() {
|
||||
const auto result = value_ & 1;
|
||||
value_ = (value_ >> 1) ^ (result * polynomial);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
IntType value_ = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* LFSR_h */
|
||||
Reference in New Issue
Block a user