31#ifndef NUMCPP_NO_USE_BOOST
41#include "boost/dynamic_bitset.hpp"
56 template<
typename IntType, std::enable_if_t<std::is_
integral_v<IntType>,
int> = 0>
60 return n != 0 && (n & (n - 1)) == 0;
75 template<
typename IntType, std::enable_if_t<std::is_
integral_v<IntType>,
int> = 0>
80 throw std::invalid_argument(
"Input value must be greater than or equal to zero.");
85 return static_cast<std::size_t
>(n) << 1;
99 template<
typename IntType, std::enable_if_t<std::is_
integral_v<IntType>,
int> = 0>
102 auto i = std::size_t{ 0 };
103 auto power = std::size_t{ 1 };
104 auto powers = std::vector<std::size_t>();
107 while (i <
static_cast<std::size_t
>(n))
109 powers.push_back(
power);
126 template<
typename IntType, std::enable_if_t<std::is_
integral_v<IntType>,
int> = 0>
131 const auto upperBin = lowerBin + 1;
132 const auto dataBitBoundary = n - lowerBin - 1;
133 const auto numParityBits = numDataBits <= dataBitBoundary ? lowerBin + 1 : upperBin + 1;
137 throw std::runtime_error(
"input number of data bits is not a valid Hamming SECDED code configuration.");
140 return numParityBits;
155 template<
typename IntType1,
157 std::enable_if_t<std::is_integral_v<IntType1>,
int> = 0,
158 std::enable_if_t<std::is_integral_v<IntType2>,
int> = 0>
163 throw std::invalid_argument(
"All hamming parity bits are indexed by powers of two.");
166 std::size_t dataIndex = 1;
167 std::size_t totalIndex = 3;
168 auto parityBit_ =
static_cast<std::size_t
>(parityBit);
170 auto indices = std::vector<std::size_t>();
171 indices.reserve(numDataBits);
173 while (dataIndex <=
static_cast<std::size_t
>(numDataBits))
175 const auto currentBitIsData = !
isPowerOfTwo(totalIndex);
176 if (currentBitIsData && (totalIndex % (parityBit_ << 1)) >= parityBit_)
178 indices.push_back(dataIndex - 1);
181 dataIndex += currentBitIsData ? 1 : 0;
195 template<std::
size_t DataBits>
199 for (std::size_t i = 0; i < DataBits - 1; ++i)
217 for (std::size_t i = 0; i < data.size() - 1; ++i)
236 template<std::
size_t DataBits,
typename IntType, std::enable_if_t<std::is_
integral_v<IntType>,
int> = 0>
240 return std::accumulate(bitsCovered.begin(),
243 [&data](
bool parity,
const auto value) noexcept ->
bool { return parity ^= value; });
254 template<std::size_t DataBits,
255 std::size_t EncodedBits,
256 std::enable_if_t<greaterThan_v<EncodedBits, DataBits>,
int> = 0>
260 if (numParityBits + DataBits != EncodedBits)
262 throw std::runtime_error(
"DataBits and EncodedBits are not consistent");
265 return numParityBits;
276 template<std::size_t DataBits,
277 std::size_t EncodedBits,
278 std::enable_if_t<greaterThan_v<EncodedBits, DataBits>,
int> = 0>
279 std::bitset<DataBits>
extractData(
const std::bitset<EncodedBits>& encodedBits)
noexcept
281 auto dataBits = std::bitset<DataBits>();
283 std::size_t dataIndex = 0;
284 for (std::size_t encodedIndex = 0; encodedIndex < EncodedBits; ++encodedIndex)
288 dataBits[dataIndex++] = encodedBits[encodedIndex];
289 if (dataIndex == DataBits)
308 template<std::
size_t DataBits>
309 boost::dynamic_bitset<>
encode(
const std::bitset<DataBits>& dataBits)
312 const auto numEncodedBits = numParityBits + DataBits;
314 auto encodedBits = boost::dynamic_bitset<>(numEncodedBits);
317 for (
const auto parityBit :
324 std::size_t dataBitIndex = 0;
325 for (std::size_t bitIndex = 1; bitIndex <= numEncodedBits - 1;
330 encodedBits[bitIndex - 1] = dataBits[dataBitIndex++];
352 template<std::size_t DataBits,
353 std::size_t EncodedBits,
354 std::enable_if_t<greaterThan_v<EncodedBits, DataBits>,
int> = 0>
355 int decode(std::bitset<EncodedBits> encodedBits, std::bitset<DataBits>& decodedBits)
357 const auto numParityBits = detail::checkBitsConsistent<DataBits, EncodedBits>();
360 decodedBits = detail::extractData<DataBits>(encodedBits);
364 const auto overallActual = encodedBits[EncodedBits - 1];
365 const auto overallCorrect = overallExpected == overallActual;
368 std::size_t indexOfError = 0;
372 const auto actual = encodedBits[parityBit - 1];
373 if (expected != actual)
375 indexOfError += parityBit;
380 if (overallCorrect && indexOfError != 0)
385 else if (!overallCorrect && indexOfError != 0)
388 encodedBits.flip(indexOfError - 1);
389 decodedBits = detail::extractData<DataBits>(encodedBits);
std::vector< std::size_t > powersOfTwo(IntType n)
Definition: hammingEncode.hpp:100
std::size_t nextPowerOfTwo(IntType n)
Definition: hammingEncode.hpp:76
std::bitset< DataBits > extractData(const std::bitset< EncodedBits > &encodedBits) noexcept
Definition: hammingEncode.hpp:279
std::size_t numSecdedParityBitsNeeded(IntType numDataBits)
Definition: hammingEncode.hpp:127
constexpr bool isPowerOfTwo(IntType n) noexcept
Tests if value is a power of two.
Definition: hammingEncode.hpp:57
std::vector< std::size_t > dataBitsCovered(IntType1 numDataBits, IntType2 parityBit)
Definition: hammingEncode.hpp:159
constexpr bool calculateParity(const std::bitset< DataBits > &data) noexcept
Definition: hammingEncode.hpp:196
std::size_t checkBitsConsistent()
Definition: hammingEncode.hpp:257
Definition: hammingEncode.hpp:46
int decode(std::bitset< EncodedBits > encodedBits, std::bitset< DataBits > &decodedBits)
Definition: hammingEncode.hpp:355
boost::dynamic_bitset encode(const std::bitset< DataBits > &dataBits)
Definition: hammingEncode.hpp:309
constexpr dtype power(dtype inValue, uint8 inExponent) noexcept
Definition: Functions/power.hpp:52
dtype ceil(dtype inValue) noexcept
Definition: ceil.hpp:48
auto log2(dtype inValue) noexcept
Definition: log2.hpp:49
dtype floor(dtype inValue) noexcept
Definition: floor.hpp:48