#include "GCrypt/Block.h" #include "GCrypt/Config.h" #include "GCrypt/Util.h" #include #include #include // Just to be sure, the compiler will optimize this // little formula out, let's do it in the preprocessor #define MAT_INDEX(row, column) (column*4 + row) namespace Leonetienne::GCrypt { template Basic_Block::Basic_Block() { } template Basic_Block::Basic_Block(const std::string& str) { FromString(str); } template Basic_Block::Basic_Block(const Basic_Block& other) { data = other.data; } template void Basic_Block::FromString(const std::string& str) { assert(str.length() == BLOCK_SIZE_BITS); for (std::size_t i = 0; i < data.size(); i++) { data[i] = std::bitset( str.substr(i*CHUNK_SIZE_BITS, CHUNK_SIZE_BITS) ).to_ulong(); } return; } template std::string Basic_Block::ToString() const { std::stringstream ss; for (std::size_t i = 0; i < data.size(); i++) { ss << std::bitset(data[i]).to_string(); } return ss.str(); } template Basic_Block Basic_Block::MMul(const Basic_Block& o) const { Basic_Block m; // Maybe pre-calculate the 1d-index...? m.Get(0, 0) = (this->Get(0, 0) * o.Get(0, 0)) + (this->Get(0, 1) * o.Get(1, 0)) + (this->Get(0, 2) * o.Get(2, 0)) + (this->Get(0, 3) * o.Get(3, 0)); m.Get(0, 1) = (this->Get(0, 0) * o.Get(0, 1)) + (this->Get(0, 1) * o.Get(1, 1)) + (this->Get(0, 2) * o.Get(2, 1)) + (this->Get(0, 3) * o.Get(3, 1)); m.Get(0, 2) = (this->Get(0, 0) * o.Get(0, 2)) + (this->Get(0, 1) * o.Get(1, 2)) + (this->Get(0, 2) * o.Get(2, 2)) + (this->Get(0, 3) * o.Get(3, 2)); m.Get(0, 3) = (this->Get(0, 0) * o.Get(0, 3)) + (this->Get(0, 1) * o.Get(1, 3)) + (this->Get(0, 2) * o.Get(2, 3)) + (this->Get(0, 3) * o.Get(3, 3)); m.Get(1, 0) = (this->Get(1, 0) * o.Get(0, 0)) + (this->Get(1, 1) * o.Get(1, 0)) + (this->Get(1, 2) * o.Get(2, 0)) + (this->Get(1, 3) * o.Get(3, 0)); m.Get(1, 1) = (this->Get(1, 0) * o.Get(0, 1)) + (this->Get(1, 1) * o.Get(1, 1)) + (this->Get(1, 2) * o.Get(2, 1)) + (this->Get(1, 3) * o.Get(3, 1)); m.Get(1, 2) = (this->Get(1, 0) * o.Get(0, 2)) + (this->Get(1, 1) * o.Get(1, 2)) + (this->Get(1, 2) * o.Get(2, 2)) + (this->Get(1, 3) * o.Get(3, 2)); m.Get(1, 3) = (this->Get(1, 0) * o.Get(0, 3)) + (this->Get(1, 1) * o.Get(1, 3)) + (this->Get(1, 2) * o.Get(2, 3)) + (this->Get(1, 3) * o.Get(3, 3)); m.Get(2, 0) = (this->Get(2, 0) * o.Get(0, 0)) + (this->Get(2, 1) * o.Get(1, 0)) + (this->Get(2, 2) * o.Get(2, 0)) + (this->Get(2, 3) * o.Get(3, 0)); m.Get(2, 1) = (this->Get(2, 0) * o.Get(0, 1)) + (this->Get(2, 1) * o.Get(1, 1)) + (this->Get(2, 2) * o.Get(2, 1)) + (this->Get(2, 3) * o.Get(3, 1)); m.Get(2, 2) = (this->Get(2, 0) * o.Get(0, 2)) + (this->Get(2, 1) * o.Get(1, 2)) + (this->Get(2, 2) * o.Get(2, 2)) + (this->Get(2, 3) * o.Get(3, 2)); m.Get(2, 3) = (this->Get(2, 0) * o.Get(0, 3)) + (this->Get(2, 1) * o.Get(1, 3)) + (this->Get(2, 2) * o.Get(2, 3)) + (this->Get(2, 3) * o.Get(3, 3)); m.Get(3, 0) = (this->Get(3, 0) * o.Get(0, 0)) + (this->Get(3, 1) * o.Get(1, 0)) + (this->Get(3, 2) * o.Get(2, 0)) + (this->Get(3, 3) * o.Get(3, 0)); m.Get(3, 1) = (this->Get(3, 0) * o.Get(0, 1)) + (this->Get(3, 1) * o.Get(1, 1)) + (this->Get(3, 2) * o.Get(2, 1)) + (this->Get(3, 3) * o.Get(3, 1)); m.Get(3, 2) = (this->Get(3, 0) * o.Get(0, 2)) + (this->Get(3, 1) * o.Get(1, 2)) + (this->Get(3, 2) * o.Get(2, 2)) + (this->Get(3, 3) * o.Get(3, 2)); m.Get(3, 3) = (this->Get(3, 0) * o.Get(0, 3)) + (this->Get(3, 1) * o.Get(1, 3)) + (this->Get(3, 2) * o.Get(2, 3)) + (this->Get(3, 3) * o.Get(3, 3)); return m; } template Basic_Block Basic_Block::operator*(const Basic_Block& other) const { return this->MMul(other); } template void Basic_Block::MMulInplace(const Basic_Block& o) { Basic_Block m = *this; // Maybe pre-calculate the 1d-index...? this->Get(0, 0) = (m.Get(0, 0) * o.Get(0, 0)) + (m.Get(0, 1) * o.Get(1, 0)) + (m.Get(0, 2) * o.Get(2, 0)) + (m.Get(0, 3) * o.Get(3, 0)); this->Get(0, 1) = (m.Get(0, 0) * o.Get(0, 1)) + (m.Get(0, 1) * o.Get(1, 1)) + (m.Get(0, 2) * o.Get(2, 1)) + (m.Get(0, 3) * o.Get(3, 1)); this->Get(0, 2) = (m.Get(0, 0) * o.Get(0, 2)) + (m.Get(0, 1) * o.Get(1, 2)) + (m.Get(0, 2) * o.Get(2, 2)) + (m.Get(0, 3) * o.Get(3, 2)); this->Get(0, 3) = (m.Get(0, 0) * o.Get(0, 3)) + (m.Get(0, 1) * o.Get(1, 3)) + (m.Get(0, 2) * o.Get(2, 3)) + (m.Get(0, 3) * o.Get(3, 3)); this->Get(1, 0) = (m.Get(1, 0) * o.Get(0, 0)) + (m.Get(1, 1) * o.Get(1, 0)) + (m.Get(1, 2) * o.Get(2, 0)) + (m.Get(1, 3) * o.Get(3, 0)); this->Get(1, 1) = (m.Get(1, 0) * o.Get(0, 1)) + (m.Get(1, 1) * o.Get(1, 1)) + (m.Get(1, 2) * o.Get(2, 1)) + (m.Get(1, 3) * o.Get(3, 1)); this->Get(1, 2) = (m.Get(1, 0) * o.Get(0, 2)) + (m.Get(1, 1) * o.Get(1, 2)) + (m.Get(1, 2) * o.Get(2, 2)) + (m.Get(1, 3) * o.Get(3, 2)); this->Get(1, 3) = (m.Get(1, 0) * o.Get(0, 3)) + (m.Get(1, 1) * o.Get(1, 3)) + (m.Get(1, 2) * o.Get(2, 3)) + (m.Get(1, 3) * o.Get(3, 3)); this->Get(2, 0) = (m.Get(2, 0) * o.Get(0, 0)) + (m.Get(2, 1) * o.Get(1, 0)) + (m.Get(2, 2) * o.Get(2, 0)) + (m.Get(2, 3) * o.Get(3, 0)); this->Get(2, 1) = (m.Get(2, 0) * o.Get(0, 1)) + (m.Get(2, 1) * o.Get(1, 1)) + (m.Get(2, 2) * o.Get(2, 1)) + (m.Get(2, 3) * o.Get(3, 1)); this->Get(2, 2) = (m.Get(2, 0) * o.Get(0, 2)) + (m.Get(2, 1) * o.Get(1, 2)) + (m.Get(2, 2) * o.Get(2, 2)) + (m.Get(2, 3) * o.Get(3, 2)); this->Get(2, 3) = (m.Get(2, 0) * o.Get(0, 3)) + (m.Get(2, 1) * o.Get(1, 3)) + (m.Get(2, 2) * o.Get(2, 3)) + (m.Get(2, 3) * o.Get(3, 3)); this->Get(3, 0) = (m.Get(3, 0) * o.Get(0, 0)) + (m.Get(3, 1) * o.Get(1, 0)) + (m.Get(3, 2) * o.Get(2, 0)) + (m.Get(3, 3) * o.Get(3, 0)); this->Get(3, 1) = (m.Get(3, 0) * o.Get(0, 1)) + (m.Get(3, 1) * o.Get(1, 1)) + (m.Get(3, 2) * o.Get(2, 1)) + (m.Get(3, 3) * o.Get(3, 1)); this->Get(3, 2) = (m.Get(3, 0) * o.Get(0, 2)) + (m.Get(3, 1) * o.Get(1, 2)) + (m.Get(3, 2) * o.Get(2, 2)) + (m.Get(3, 3) * o.Get(3, 2)); this->Get(3, 3) = (m.Get(3, 0) * o.Get(0, 3)) + (m.Get(3, 1) * o.Get(1, 3)) + (m.Get(3, 2) * o.Get(2, 3)) + (m.Get(3, 3) * o.Get(3, 3)); return; } template Basic_Block& Basic_Block::operator*=(const Basic_Block& other) { MMulInplace(other); return *this; } template Basic_Block Basic_Block::Xor(const Basic_Block& other) const { Basic_Block m; for (std::size_t i = 0; i < data.size(); i++) { m.Get(i) = this->Get(i) ^ other.Get(i); } return m; } template Basic_Block Basic_Block::operator^(const Basic_Block& other) const { return Xor(other); } template void Basic_Block::XorInplace(const Basic_Block& other) { for (std::size_t i = 0; i < data.size(); i++) { this->Get(i) ^= other.Get(i); } return; } template Basic_Block& Basic_Block::operator^=(const Basic_Block& other) { XorInplace(other); return *this; } template Basic_Block Basic_Block::Add(const Basic_Block& other) const { Basic_Block m; for (std::size_t i = 0; i < data.size(); i++) { m.Get(i) = this->Get(i) + other.Get(i); } return m; } template Basic_Block Basic_Block::operator+(const Basic_Block& other) const { return Add(other); } template void Basic_Block::AddInplace(const Basic_Block& other) { for (std::size_t i = 0; i < data.size(); i++) { this->Get(i) += other.Get(i); } return; } template Basic_Block& Basic_Block::operator+=(const Basic_Block& other) { AddInplace(other); return *this; } template Basic_Block Basic_Block::Sub(const Basic_Block& other) const { Basic_Block m; for (std::size_t i = 0; i < data.size(); i++) { m.Get(i) = this->Get(i) - other.Get(i); } return m; } template Basic_Block Basic_Block::operator-(const Basic_Block& other) const { return Sub(other); } template void Basic_Block::SubInplace(const Basic_Block& other) { for (std::size_t i = 0; i < data.size(); i++) { this->Get(i) -= other.Get(i); } return; } template Basic_Block& Basic_Block::operator-=(const Basic_Block& other) { SubInplace(other); return *this; } template void Basic_Block::ShiftRowsUpInplace() { Basic_Block tmp = *this; Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(1, 0)); Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(1, 1)); Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(1, 2)); Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(1, 3)); Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(2, 0)); Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(2, 1)); Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(2, 2)); Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(2, 3)); Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(3, 0)); Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(3, 1)); Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(3, 2)); Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(3, 3)); Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(0, 0)); Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(0, 1)); Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(0, 2)); Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(0, 3)); return; } template Basic_Block Basic_Block::ShiftRowsUp() const { Basic_Block b; b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(1, 0)); b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(1, 1)); b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(1, 2)); b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(1, 3)); b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(2, 0)); b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(2, 1)); b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(2, 2)); b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(2, 3)); b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(3, 0)); b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(3, 1)); b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(3, 2)); b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(3, 3)); b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(0, 0)); b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(0, 1)); b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(0, 2)); b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(0, 3)); return b; } template void Basic_Block::ShiftRowsDownInplace() { Basic_Block tmp = *this; Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(3, 0)); Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(3, 1)); Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(3, 2)); Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(3, 3)); Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(0, 0)); Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(0, 1)); Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(0, 2)); Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(0, 3)); Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(1, 0)); Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(1, 1)); Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(1, 2)); Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(1, 3)); Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(2, 0)); Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(2, 1)); Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(2, 2)); Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(2, 3)); return; } template Basic_Block Basic_Block::ShiftRowsDown() const { Basic_Block b; b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(3, 0)); b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(3, 1)); b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(3, 2)); b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(3, 3)); b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(0, 0)); b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(0, 1)); b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(0, 2)); b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(0, 3)); b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(1, 0)); b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(1, 1)); b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(1, 2)); b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(1, 3)); b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(2, 0)); b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(2, 1)); b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(2, 2)); b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(2, 3)); return b; } template void Basic_Block::ShiftColumnsLeftInplace() { Basic_Block tmp = *this; Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(0, 1)); Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(1, 1)); Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(2, 1)); Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(3, 1)); Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(0, 2)); Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(1, 2)); Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(2, 2)); Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(3, 2)); Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(0, 3)); Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(1, 3)); Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(2, 3)); Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(3, 3)); Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(0, 0)); Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(1, 0)); Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(2, 0)); Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(3, 0)); return; } template Basic_Block Basic_Block::ShiftColumnsLeft() const { Basic_Block b; b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(0, 1)); b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(1, 1)); b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(2, 1)); b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(3, 1)); b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(0, 2)); b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(1, 2)); b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(2, 2)); b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(3, 2)); b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(0, 3)); b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(1, 3)); b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(2, 3)); b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(3, 3)); b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(0, 0)); b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(1, 0)); b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(2, 0)); b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(3, 0)); return b; } template void Basic_Block::ShiftColumnsRightInplace() { Basic_Block tmp = *this; Get(MAT_INDEX(0, 1)) = tmp.Get(MAT_INDEX(0, 0)); Get(MAT_INDEX(1, 1)) = tmp.Get(MAT_INDEX(1, 0)); Get(MAT_INDEX(2, 1)) = tmp.Get(MAT_INDEX(2, 0)); Get(MAT_INDEX(3, 1)) = tmp.Get(MAT_INDEX(3, 0)); Get(MAT_INDEX(0, 2)) = tmp.Get(MAT_INDEX(0, 1)); Get(MAT_INDEX(1, 2)) = tmp.Get(MAT_INDEX(1, 1)); Get(MAT_INDEX(2, 2)) = tmp.Get(MAT_INDEX(2, 1)); Get(MAT_INDEX(3, 2)) = tmp.Get(MAT_INDEX(3, 1)); Get(MAT_INDEX(0, 3)) = tmp.Get(MAT_INDEX(0, 2)); Get(MAT_INDEX(1, 3)) = tmp.Get(MAT_INDEX(1, 2)); Get(MAT_INDEX(2, 3)) = tmp.Get(MAT_INDEX(2, 2)); Get(MAT_INDEX(3, 3)) = tmp.Get(MAT_INDEX(3, 2)); Get(MAT_INDEX(0, 0)) = tmp.Get(MAT_INDEX(0, 3)); Get(MAT_INDEX(1, 0)) = tmp.Get(MAT_INDEX(1, 3)); Get(MAT_INDEX(2, 0)) = tmp.Get(MAT_INDEX(2, 3)); Get(MAT_INDEX(3, 0)) = tmp.Get(MAT_INDEX(3, 3)); return; } template Basic_Block Basic_Block::ShiftColumnsRight() const { Basic_Block b; b.Get(MAT_INDEX(0, 1)) = Get(MAT_INDEX(0, 0)); b.Get(MAT_INDEX(1, 1)) = Get(MAT_INDEX(1, 0)); b.Get(MAT_INDEX(2, 1)) = Get(MAT_INDEX(2, 0)); b.Get(MAT_INDEX(3, 1)) = Get(MAT_INDEX(3, 0)); b.Get(MAT_INDEX(0, 2)) = Get(MAT_INDEX(0, 1)); b.Get(MAT_INDEX(1, 2)) = Get(MAT_INDEX(1, 1)); b.Get(MAT_INDEX(2, 2)) = Get(MAT_INDEX(2, 1)); b.Get(MAT_INDEX(3, 2)) = Get(MAT_INDEX(3, 1)); b.Get(MAT_INDEX(0, 3)) = Get(MAT_INDEX(0, 2)); b.Get(MAT_INDEX(1, 3)) = Get(MAT_INDEX(1, 2)); b.Get(MAT_INDEX(2, 3)) = Get(MAT_INDEX(2, 2)); b.Get(MAT_INDEX(3, 3)) = Get(MAT_INDEX(3, 2)); b.Get(MAT_INDEX(0, 0)) = Get(MAT_INDEX(0, 3)); b.Get(MAT_INDEX(1, 0)) = Get(MAT_INDEX(1, 3)); b.Get(MAT_INDEX(2, 0)) = Get(MAT_INDEX(2, 3)); b.Get(MAT_INDEX(3, 0)) = Get(MAT_INDEX(3, 3)); return b; } template void Basic_Block::ShiftCellsLeftInplace() { Basic_Block tmp = *this; Get(15) = tmp.Get(0); for (std::size_t i = 0; i < 15; i++) { Get(i) = tmp.Get(i+1); } return; } template Basic_Block Basic_Block::ShiftCellsLeft() const { Basic_Block b; b.Get(15) = Get(0); for (std::size_t i = 0; i < 15; i++) { b.Get(i) = Get(i+1); } return b; } template void Basic_Block::ShiftCellsRightInplace() { Basic_Block tmp = *this; Get(0) = tmp.Get(15); for (std::size_t i = 1; i < 16; i++) { Get(i) = tmp.Get(i-1); } return; } template Basic_Block Basic_Block::ShiftCellsRight() const { Basic_Block b; b.Get(0) = Get(15); for (std::size_t i = 1; i < 16; i++) { b.Get(i) = Get(i-1); } return b; } template Basic_Block& Basic_Block::operator=(const Basic_Block& other) { data = other.data; return *this; } template bool Basic_Block::GetBit(const std::size_t index) const { // Fetch index of integer the bit is located in const std::size_t intIndex = index / CHUNK_SIZE_BITS; // Fetch bit index relative to that int const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS); // Pre-calculate the bitmask to use const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1); return data[intIndex] & bitmask; } template void Basic_Block::SetBit(const std::size_t index, const bool state) { // Fetch index of integer the bit is located in const std::size_t intIndex = index / CHUNK_SIZE_BITS; // Fetch bit index relative to that int const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS); // Pre-calculate the bitmask to use const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1); // Set the bit if (state) { data[intIndex] |= bitmask; } // Clear the bit else { data[intIndex] &= ~bitmask; } return; } template void Basic_Block::FlipBit(const std::size_t index) { // Fetch index of integer the bit is located in const std::size_t intIndex = index / CHUNK_SIZE_BITS; // Fetch bit index relative to that int const std::size_t relBitIndex = index - (intIndex * CHUNK_SIZE_BITS); // Pre-calculate the bitmask to use const std::size_t bitmask = 1 << (CHUNK_SIZE_BITS - relBitIndex - 1); data[intIndex] ^= bitmask; return; } template Basic_Block Basic_Block::ShiftBitsLeft() const { Basic_Block b; // First, copy this block over b = *this; // Then, shift all integers individually for (std::size_t i = 0; i < data.size(); i++) { b.data[i] <<= 1; } // Current state: the LSB is zero everywhere. We have to carry // it over manually from the previous state. // Carry over the MSB of data[i] to LSB of data[i-1] constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1); constexpr std::size_t bitmaskLsb = 1; for (int i = 0; i < data.size(); i++) { const bool msb = data[i] & bitmaskMsb; // Set the lsb if (msb) { b.data[Mod(i-1, data.size())] |= bitmaskLsb; } // Clear the lsb else { b.data[Mod(i-1, data.size())] &= ~bitmaskLsb; } } return b; } template void Basic_Block::ShiftBitsLeftInplace() { Basic_Block tmp = *this; // Then, shift all integers individually for (std::size_t i = 0; i < data.size(); i++) { data[i] <<= 1; } // Current state: the LSB is zero everywhere. We have to carry // it over manually from the previous state. // Carry over the MSB of data[i] to LSB of data[i-1] constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1); constexpr std::size_t bitmaskLsb = 1; for (int i = 0; i < data.size(); i++) { const bool msb = tmp.data[i] & bitmaskMsb; // Set the lsb if (msb) { data[Mod(i-1, data.size())] |= bitmaskLsb; } // Clear the lsb else { data[Mod(i-1, data.size())] &= ~bitmaskLsb; } } return; } template Basic_Block Basic_Block::ShiftBitsRight() const { Basic_Block b; // First, copy this block over b = *this; // Then, shift all integers individually for (std::size_t i = 0; i < data.size(); i++) { b.data[i] >>= 1; } // Current state: the LSB is zero everywhere. We have to carry // it over manually from the previous state. // Carry over the LSB of data[i] to MSB of data[i+1] constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1); constexpr std::size_t bitmaskLsb = 1; for (int i = 0; i < data.size(); i++) { const bool lsb = data[i] & bitmaskLsb; // Set the msb if (lsb) { b.data[Mod(i+1, data.size())] |= bitmaskMsb; } // Clear the msb else { b.data[Mod(i+1, data.size())] &= ~bitmaskMsb; } } return b; } template void Basic_Block::ShiftBitsRightInplace() { Basic_Block tmp = *this; // Then, shift all integers individually for (std::size_t i = 0; i < data.size(); i++) { data[i] >>= 1; } // Current state: the LSB is zero everywhere. We have to carry // it over manually from the previous state. // Carry over the LSB of data[i] to MSB of data[i+1] constexpr std::size_t bitmaskMsb = 1 << (CHUNK_SIZE_BITS - 1); constexpr std::size_t bitmaskLsb = 1; for (int i = 0; i < data.size(); i++) { const bool lsb = tmp.data[i] & bitmaskLsb; // Set the msb if (lsb) { data[Mod(i+1, data.size())] |= bitmaskMsb; } // Clear the msb else { data[Mod(i+1, data.size())] &= ~bitmaskMsb; } } return; } template T& Basic_Block::Get(const std::uint8_t row, const std::uint8_t column){ return data[MAT_INDEX(row, column)]; } template const T& Basic_Block::Get(const std::uint8_t row, const std::uint8_t column) const { return data[MAT_INDEX(row, column)]; } template T& Basic_Block::Get(const std::uint8_t index) { return data[index]; } template const T& Basic_Block::Get(const std::uint8_t index) const { return data[index]; } template T& Basic_Block::operator[](const std::uint8_t index) { return data[index]; } template const T& Basic_Block::operator[](const std::uint8_t index) const { return data[index]; } template bool Basic_Block::operator==(const Basic_Block& other) const { return data == other.data; } template bool Basic_Block::operator!=(const Basic_Block& other) const { return data != other.data; } #if defined _WIN32 || defined _WIN64 #pragma optimize("", off ) #elif defined __GNUG__ #pragma GCC push_options #pragma GCC optimize ("O0") #endif template Basic_Block::~Basic_Block() { Reset(); } template void Basic_Block::Reset() { memset(data.data(), 0, CHUNK_SIZE*data.size()); return; } #if defined _WIN32 || defined _WIN64 #pragma optimize("", on ) #elif defined __GNUG__ #pragma GCC pop_options #endif } #undef MAT_INDEX