123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857 |
- /**
- \file cbitvector.cpp
- \author michael.zohner@ec-spride.de
- \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation
- Copyright (C) 2019 ENCRYPTO Group, TU Darmstadt
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- ABY is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- \brief CBitVector Implementation
- */
- #include "cbitvector.h"
- #include "crypto/crypto.h"
- #include "utils.h"
- #include <algorithm>
- #include <iomanip>
- #include <iostream>
- #include <cstring>
- namespace {
- /** Array which stores the bytes which are reversed. For example, the hexadecimal 0x01 is when reversed becomes 0x80. */
- constexpr BYTE REVERSE_BYTE_ORDER[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8,
- 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C,
- 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2,
- 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96,
- 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1,
- 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85,
- 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD,
- 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B,
- 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF,
- 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF };
- /**
- This array is used by \link XORBits(BYTE* p, int pos, int len) \endlink and \link SetBits(BYTE* p, uint64_t pos, uint64_t len) \endlink
- method for lower bit mask.
- */
- constexpr BYTE RESET_BIT_POSITIONS[9] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
- /**
- This array is used by \link XORBits(BYTE* p, int pos, int len) \endlink and \link SetBits(BYTE* p, uint64_t pos, uint64_t len) \endlink
- method for upper bit mask.
- */
- constexpr BYTE RESET_BIT_POSITIONS_INV[9] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
- /** This array is used by \link GetBits(BYTE* p, int pos, int len) \endlink method for lower bit mask. */
- constexpr BYTE GET_BIT_POSITIONS[9] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00 };
- /** This array is used by \link GetBits(BYTE* p, int pos, int len) \endlink method for upper bit mask. */
- constexpr BYTE GET_BIT_POSITIONS_INV[9] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00 };
- /**
- This array is used for masking bits and extracting a particular positional bit from the provided byte array.
- This array is used by \link GetBit(int idx) \endlink method.
- */
- constexpr BYTE MASK_BIT[8] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
- /**
- This array is used for extracting a particular positional bit from the provided byte array without masking.
- This array is used by \link GetBitNoMask(int idx) \endlink method.
- */
- static constexpr BYTE BIT[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
- /**
- This array is used for masking bits and setting a particular positional bit from the provided byte array in the CBitVector.
- This array is used by \link SetBit(int idx, BYTE b) \endlink and \link ANDBit(int idx, BYTE b) \endlink methods.
- */
- constexpr BYTE CMASK_BIT[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
- /**
- This array is used for setting a particular positional bit from the provided byte array without masking in the CBitVector.
- This array is used by \link SetBitNoMask(int idx, BYTE b) \endlink and \link ANDBitNoMask(int idx, BYTE b) \endlink methods.
- */
- constexpr BYTE C_BIT[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
- /**
- This array is used for masking bits and setting a particular positional bit from the provided byte array in the CBitVector.
- This array is used by \link SetBit(int idx, BYTE b) \endlink and \link XORBit(int idx, BYTE b) \endlink methods.
- */
- constexpr BYTE MASK_SET_BIT_C[2][8] = { { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }, { 0, 0, 0, 0, 0, 0, 0, 0 } };
- /**
- This array is used for setting a particular positional bit from the provided byte array without masking in the CBitVector.
- This array is used by \link SetBitNoMask(int idx, BYTE b) \endlink and \link XORBitNoMask(int idx, BYTE b) \endlink methods.
- */
- constexpr BYTE SET_BIT_C[2][8] = { { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }, { 0, 0, 0, 0, 0, 0, 0, 0 } };
- const BYTE SELECT_BIT_POSITIONS[9] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
- #if (__WORDSIZE==32)
- constexpr REGISTER_SIZE TRANSPOSITION_MASKS[6] =
- { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
- constexpr REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] =
- { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
- #else
- #if (__WORDSIZE==64)
- /** Transposition mask used for Eklund Bit Matrix Transposition.*/
- constexpr REGISTER_SIZE TRANSPOSITION_MASKS[6] = { 0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF };
- constexpr REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] = { 0xAAAAAAAAAAAAAAAA, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 };
- #else
- #endif
- #endif
- constexpr size_t SHIFTVAL = 3;
- template<class T> void GetBytes(T* dst, const T* src, const T* lim) {
- while (dst != lim) {
- *dst++ = *src++;
- }
- }
- template<class T> void SetBytes(T* dst, const T* src, const T* lim) {
- while (dst < lim) {
- *dst++ = *src++;
- }
- }
- //Generic bytewise XOR operation
- template<class T> void XORBytes(T* dst, const T* src, const T* lim) {
- while (dst != lim) {
- *dst++ ^= *src++;
- }
- }
- template<class T> void ANDBytes(T* dst, const T* src, const T* lim) {
- while (dst != lim) {
- *dst++ &= *src++;
- }
- }
- constexpr BYTE GetArrayBit(const BYTE* p, size_t idx) {
- return 0 != (p[idx >> 3] & BIT[idx & 0x7]);
- }
- } // namespace
- CBitVector::CBitVector() {
- Init();
- }
- CBitVector::CBitVector(std::size_t bits) {
- Init();
- Create(bits);
- }
- CBitVector::CBitVector(std::size_t bits, crypto* crypt) {
- Init();
- Create(bits, crypt);
- }
- void CBitVector::Init() {
- m_pBits = NULL;
- m_nByteSize = 0;
- }
- CBitVector::~CBitVector(){
- delCBitVector();
- };
- void CBitVector::delCBitVector() {
- if (( m_nByteSize > 0 )&& (m_pBits != NULL)) {
- free(m_pBits);
- }
- m_nByteSize = 0;
- m_pBits = NULL;
- }
- /* Fill random values using the pre-defined AES key */
- void CBitVector::FillRand(std::size_t bits, crypto* crypt) {
- if (bits > m_nByteSize << 3)
- Create(bits);
- crypt->gen_rnd(m_pBits, ceil_divide(bits, 8));
- }
- void CBitVector::CreateExact(std::size_t bits) {
- if (bits == 0){
- bits = AES_BITS;
- }
- // if memory was previously allocated: free it
- if (m_nByteSize > 0) {
- free(m_pBits);
- }
- m_nByteSize = ceil_divide(bits, 8);
- m_pBits = (BYTE*) calloc(m_nByteSize, sizeof(BYTE));
- assert(m_pBits != NULL);
- m_nElementLength = 1;
- m_nNumElements = m_nByteSize;
- m_nNumElementsDimB = 1;
- }
- void CBitVector::Create(std::size_t bits) {
- //TODO: check if padding to AES_BITS is still necessary as default
- CreateExact(ceil_divide(bits, AES_BITS) * AES_BITS);
- }
- void CBitVector::CreateBytes(std::size_t bytes) {
- Create(bytes << 3);
- }
- void CBitVector::CreateBytes(std::size_t bytes, crypto* crypt) {
- Create(bytes << 3, crypt);
- }
- void CBitVector::CreateZeros(std::size_t bits) {
- Create(bits);
- memset(m_pBits, 0, m_nByteSize);
- }
- void CBitVector::Create(std::size_t bits, crypto* crypt) {
- Create(bits);
- FillRand(bits, crypt);
- }
- void CBitVector::Create(std::size_t numelements, std::size_t elementlength) {
- Create(numelements * elementlength);
- m_nElementLength = elementlength;
- m_nNumElements = numelements;
- m_nNumElementsDimB = 1;
- }
- void CBitVector::Create(std::size_t numelements, std::size_t elementlength, crypto* crypt) {
- Create(numelements * elementlength, crypt);
- m_nElementLength = elementlength;
- m_nNumElements = numelements;
- m_nNumElementsDimB = 1;
- }
- void CBitVector::Create(std::size_t numelementsDimA, std::size_t numelementsDimB, std::size_t elementlength) {
- Create(numelementsDimA * numelementsDimB * elementlength);
- m_nElementLength = elementlength;
- m_nNumElements = numelementsDimA;
- m_nNumElementsDimB = numelementsDimB;
- }
- void CBitVector::Create(std::size_t numelementsDimA, std::size_t numelementsDimB, std::size_t elementlength, crypto* crypt) {
- Create(numelementsDimA * numelementsDimB * elementlength, crypt);
- m_nElementLength = elementlength;
- m_nNumElements = numelementsDimA;
- m_nNumElementsDimB = numelementsDimB;
- }
- void CBitVector::ResizeinBytes(std::size_t newSizeBytes) {
- BYTE* tBits = m_pBits;
- uint64_t tSize = (m_nByteSize<newSizeBytes)? m_nByteSize:newSizeBytes; //fix for overflow condition in memcpy.
- m_nByteSize = newSizeBytes;
- m_pBits = (uint8_t*) calloc(m_nByteSize, sizeof(uint8_t));
- memcpy(m_pBits, tBits, tSize);
- free(tBits);
- }
- void CBitVector::Reset() {
- memset(m_pBits, 0, m_nByteSize);
- }
- void CBitVector::ResetFromTo(std::size_t frombyte, std::size_t tobyte) {
- assert(frombyte <= tobyte);
- assert(tobyte < m_nByteSize);
- memset(m_pBits + frombyte, 0, tobyte - frombyte);
- }
- void CBitVector::SetToOne() {
- memset(m_pBits, 0xFF, m_nByteSize);
- }
- void CBitVector::Invert() {
- for(std::size_t i = 0; i < m_nByteSize; i++) {
- m_pBits[i] = ~m_pBits[i];
- }
- }
- std::size_t CBitVector::GetSize() const {
- return m_nByteSize;
- }
- BOOL CBitVector::IsEqual(const CBitVector& vec) const {
- if (vec.GetSize() != m_nByteSize) {
- return false;
- }
- const BYTE* ptr = vec.GetArr();
- for (std::size_t i = 0; i < m_nByteSize; i++) {
- if (ptr[i] != m_pBits[i]) {
- return false;
- }
- }
- return true;
- }
- BOOL CBitVector::IsEqual(const CBitVector& vec, std::size_t from, std::size_t to) const {
- if (vec.GetSize() * 8 < to || m_nByteSize * 8 < to || from > to) {
- return false;
- }
- for (std::size_t i = from; i < to; i++) {
- if (vec.GetBit(i) != GetBit(i)) {
- return false;
- }
- }
- return true;
- }
- void CBitVector::SetElementLength(std::size_t elelen) {
- m_nElementLength = elelen;
- }
- std::size_t CBitVector::GetElementLength() const {
- return m_nElementLength;
- }
- void CBitVector::Copy(const CBitVector& vec) {
- Copy(vec.GetArr(), 0, vec.GetSize());
- }
- void CBitVector::Copy(const CBitVector& vec, std::size_t pos, std::size_t len) {
- Copy(vec.GetArr(), pos, len);
- }
- void CBitVector::Copy(const BYTE* p, std::size_t pos, std::size_t len) {
- if (pos + len > m_nByteSize) {
- if (m_pBits)
- ResizeinBytes(pos + len);
- else {
- CreateBytes(pos + len);
- }
- }
- memcpy(m_pBits + pos, p, len);
- }
- void CBitVector::ORByte(std::size_t pos, BYTE p) {
- assert(pos <= m_nByteSize);
- m_pBits[pos] |= p;
- }
- BYTE CBitVector::GetBit(std::size_t idx) const {
- assert(idx < (m_nByteSize << 3));
- return !!(m_pBits[idx >> 3] & MASK_BIT[idx & 0x7]);
- }
- void CBitVector::SetBit(std::size_t idx, BYTE b) {
- assert(idx < (m_nByteSize << 3));
- m_pBits[idx >> 3] = (m_pBits[idx >> 3] & CMASK_BIT[idx & 0x7]) | MASK_SET_BIT_C[!(b & 0x01)][idx & 0x7];
- }
- BYTE CBitVector::GetBitNoMask(std::size_t idx) const {
- assert(idx < (m_nByteSize << 3));
- return GetArrayBit(m_pBits, idx);
- }
- void CBitVector::SetBitNoMask(std::size_t idx, BYTE b) {
- assert(idx < (m_nByteSize << 3));
- m_pBits[idx >> 3] = (m_pBits[idx >> 3] & C_BIT[idx & 0x7]) | SET_BIT_C[!(b & 0x01)][idx & 0x7];
- }
- void CBitVector::XORBitNoMask(std::size_t idx, BYTE b) {
- assert(idx < (m_nByteSize << 3));
- m_pBits[idx >> 3] ^= SET_BIT_C[!(b & 0x01)][idx & 0x7];
- }
- void CBitVector::SetByte(std::size_t idx, BYTE p) {
- assert(idx < m_nByteSize);
- m_pBits[idx] = p;
- }
- BYTE CBitVector::GetByte(std::size_t idx) const {
- assert(idx < m_nByteSize);
- return m_pBits[idx];
- }
- void CBitVector::XORByte(std::size_t idx, BYTE b) {
- assert(idx < m_nByteSize);
- m_pBits[idx] ^= b;
- }
- void CBitVector::ANDByte(std::size_t idx, BYTE b) {
- assert(idx < m_nByteSize);
- m_pBits[idx] &= b;
- }
- void CBitVector::GetBits(BYTE* p, std::size_t pos, std::size_t len) const {
- if (len < 1 || (pos + len) > (m_nByteSize << 3)) {
- return;
- }
- if (len == 1) {
- *p = GetBitNoMask(pos);
- return;
- }
- if (!((pos & 0x07) || (len & 0x07))) {
- GetBytes(p, pos >> 3, len >> 3);
- return;
- }
- int posctr = pos >> 3;
- int lowermask = pos & 7;
- int uppermask = 8 - lowermask;
- std::size_t i;
- for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
- p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF;
- p[i] |= (m_pBits[posctr + 1] & GET_BIT_POSITIONS_INV[uppermask]) << uppermask;
- }
- int remlen = len & 0x07;
- if (remlen) {
- if (remlen <= uppermask) {
- p[i] = ((m_pBits[posctr] & ((((1 << remlen) - 1) << lowermask))) >> lowermask) & 0xFF;
- } else {
- p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF;
- p[i] |= (m_pBits[posctr + 1] & (((1 << (remlen - uppermask)) - 1))) << uppermask;
- }
- }
- }
- //optimized bytewise for set operation
- void CBitVector::GetBytes(BYTE* p, std::size_t pos, std::size_t len) const {
- assert(pos+len <= m_nByteSize);
- BYTE* src = m_pBits + pos;
- BYTE* dst = p;
- //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
- ::GetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
- dst += ((len >> SHIFTVAL) << SHIFTVAL);
- src += ((len >> SHIFTVAL) << SHIFTVAL);
- ::GetBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
- }
- //
- //pos and len in bits
- void CBitVector::SetBits(const BYTE* p, std::size_t pos, std::size_t len) {
- if (len < 1 || (pos + len) > (m_nByteSize << 3)){
- return;
- }
- if (len == 1) {
- SetBitNoMask(pos, *p);
- return;
- }
- if (!((pos & 0x07) || (len & 0x07))) {
- SetBytes(p, pos >> 3, len >> 3);
- return;
- }
- std::size_t posctr = pos >> 3;
- int lowermask = pos & 7;
- int uppermask = 8 - lowermask;
- std::size_t i;
- BYTE temp;
- for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
- temp = p[i];
- m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF);
- m_pBits[posctr + 1] = (m_pBits[posctr + 1] & RESET_BIT_POSITIONS_INV[uppermask]) | (temp >> uppermask);
- }
- int remlen = len & 0x07;
- if (remlen) {
- temp = p[i] & RESET_BIT_POSITIONS[remlen];
- if (remlen <= uppermask) {
- m_pBits[posctr] = (m_pBits[posctr] & (~(((1 << remlen) - 1) << lowermask))) | ((temp << lowermask) & 0xFF);
- } else {
- m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF);
- m_pBits[posctr + 1] = (m_pBits[posctr + 1] & (~(((1 << (remlen - uppermask)) - 1)))) | (temp >> uppermask);
- }
- }
- }
- //Set bits given an offset on the bits for p which is not necessarily divisible by 8
- void CBitVector::SetBitsPosOffset(const BYTE* p, std::size_t ppos, std::size_t pos, std::size_t len) {
- for (auto i = pos, j = ppos; j < ppos + len; i++, j++) {
- BYTE source_bit = GetArrayBit(p, j);
- SetBitNoMask(i, source_bit);
- }
- }
- //optimized bytewise for set operation
- void CBitVector::SetBytes(const BYTE *src, std::size_t pos, std::size_t len) {
- assert(pos + len <= m_nByteSize);
- BYTE *dst = m_pBits + pos;
- //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
- ::SetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
- dst += ((len >> SHIFTVAL) << SHIFTVAL);
- src += ((len >> SHIFTVAL) << SHIFTVAL);
- ::SetBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
- }
- void CBitVector::SetBytesToZero(std::size_t bytepos, std::size_t bytelen) {
- assert(bytepos + bytelen <= m_nByteSize);
- memset(m_pBits + bytepos, 0x00, bytelen);
- }
- void CBitVector::SetBitsToZero(std::size_t bitpos, std::size_t bitlen) {
- int firstlim = ceil_divide(bitpos, 8);
- int firstlen = ceil_divide(bitlen - (bitpos % 8), 8);
- for (int i = bitpos; i < firstlim; i++) {
- SetBitNoMask(i, 0);
- }
- if (bitlen > 7) {
- memset(m_pBits + firstlim, 0, firstlen);
- }
- for (std::size_t i = (firstlim + firstlen) << 8; i < bitpos + bitlen; i++) {
- SetBitNoMask(i, 0);
- }
- }
- //optimized bytewise XOR operation
- void CBitVector::XORBytes(const BYTE* p, std::size_t pos, std::size_t len) {
- if(pos + len > m_nByteSize)
- std::cout << "pos = " << pos << ", len = " << len << ", bytesize = " << m_nByteSize << std::endl;
- assert(pos + len <= m_nByteSize);
- BYTE* dst = m_pBits + pos;
- const BYTE* src = p;
- //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
- ::XORBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
- dst += ((len >> SHIFTVAL) << SHIFTVAL);
- src += ((len >> SHIFTVAL) << SHIFTVAL);
- ::XORBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
- }
- void CBitVector::XORBytes(const BYTE* p, std::size_t len) {
- XORBytes(p, 0, len);
- }
- void CBitVector::XORVector(const CBitVector &vec, std::size_t pos, std::size_t len) {
- XORBytes(vec.GetArr(), pos, len);
- }
- void CBitVector::XORBits(const BYTE* p, std::size_t pos, std::size_t len) {
- if (len < 1 || (pos + len) > m_nByteSize << 3) {
- return;
- }
- if (len == 1) {
- XORBitNoMask(pos, *p);
- return;
- }
- if (!((pos & 0x07) || (len & 0x07))) {
- XORBytes(p, pos >> 3, len >> 3);
- return;
- }
- int posctr = pos >> 3;
- int lowermask = pos & 7;
- int uppermask = 8 - lowermask;
- std::size_t i;
- BYTE temp;
- for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
- temp = p[i];
- m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
- m_pBits[posctr + 1] ^= (temp >> uppermask);
- }
- int remlen = len & 0x07;
- if (remlen) {
- temp = p[i] & RESET_BIT_POSITIONS[remlen];
- if (remlen <= uppermask) {
- m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
- } else {
- m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
- m_pBits[posctr + 1] ^= (temp >> uppermask);
- }
- }
- }
- //XOR bits given an offset on the bits for p which is not necessarily divisible by 8
- void CBitVector::XORBitsPosOffset(const BYTE* p, std::size_t ppos, std::size_t pos, std::size_t len) {
- assert((pos + len) <= (m_nByteSize<<3));
- for (auto i = pos, j = ppos; j < ppos + len; i++, j++) {
- m_pBits[i / 8] ^= (((p[j / 8] & (1 << (j % 8))) >> j % 8) << i % 8);
- }
- }
- //Method for directly XORing CBitVectors
- void CBitVector::XOR(const CBitVector* b) {
- assert(b->GetSize() == m_nByteSize);
- XORBytes(b->GetArr(), 0, m_nByteSize);
- }
- void CBitVector::XORBytesReverse(const BYTE* p, std::size_t pos, std::size_t len) {
- assert((pos + len) <= m_nByteSize);
- const BYTE* src = p;
- BYTE* dst = m_pBits + pos;
- BYTE* lim = dst + len;
- while (dst != lim) {
- *dst++ ^= REVERSE_BYTE_ORDER[*src++];
- }
- }
- //optimized bytewise for AND operation
- void CBitVector::ANDBytes(const BYTE* p, std::size_t pos, std::size_t len) {
- assert(pos+len <= m_nByteSize);
- BYTE* dst = m_pBits + pos;
- const BYTE* src = p;
- //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
- ::ANDBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
- dst += ((len >> SHIFTVAL) << SHIFTVAL);
- src += ((len >> SHIFTVAL) << SHIFTVAL);
- ::ANDBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
- }
- void CBitVector::SetXOR(const BYTE* p, const BYTE* q, std::size_t pos, std::size_t len) {
- Copy(p, pos, len);
- XORBytes(q, pos, len);
- }
- void CBitVector::SetAND(const BYTE* p, const BYTE* q, std::size_t pos, std::size_t len) {
- Copy(p, pos, len);
- ANDBytes(q, pos, len);
- }
- //Method for directly ANDing CBitVectors
- void CBitVector::AND(const CBitVector* b) {
- assert(b->GetSize() == m_nByteSize);
- ANDBytes(b->GetArr(), 0, m_nByteSize);
- }
- //Cyclic left shift by pos bits
- void CBitVector::CLShift(std::size_t pos) {
- uint8_t* tmpbuf = (uint8_t*) malloc(m_nByteSize);
- for(std::size_t i = 0; i < m_nByteSize; i++) {
- tmpbuf[i+pos] = m_pBits[i];
- }
- free(m_pBits);
- m_pBits = tmpbuf;
- }
- BYTE* CBitVector::GetArr() {
- return m_pBits;
- }
- const BYTE* CBitVector::GetArr() const {
- return m_pBits;
- }
- void CBitVector::AttachBuf(BYTE* p, std::size_t size) {
- m_pBits = p;
- m_nByteSize = size;
- }
- /**
- This method is used to detach the buffer from the CBitVector. */
- void CBitVector::DetachBuf() {
- m_pBits = NULL;
- m_nByteSize = 0;
- }
- void CBitVector::Print(std::size_t fromBit, std::size_t toBit) {
- std::size_t to = toBit > (m_nByteSize << 3) ? (m_nByteSize << 3) : toBit;
- std::cout << "fromBit = " << fromBit << std::endl;
- std::cout << "to = " << to << std::endl;
- for (std::size_t i = fromBit; i < to; i++) {
- std::cout << (unsigned int) GetBitNoMask(i);
- }
- std::cout << std::endl;
- }
- void CBitVector::PrintHex(bool linebreak) {
- for (std::size_t i = 0; i < m_nByteSize; i++) {
- std::cout << std::setw(2) << std::setfill('0') << (std::hex) << ((unsigned int) m_pBits[i]);
- }
- if(linebreak){
- std::cout << (std::dec) << std::endl;
- }
- }
- void CBitVector::PrintHex(std::size_t fromByte, std::size_t toByte, bool linebreak) {
- std::size_t to = toByte > (m_nByteSize) ? (m_nByteSize) : toByte;
- for (std::size_t i = fromByte; i < to; i++) {
- std::cout << std::setw(2) << std::setfill('0') << (std::hex) << ((unsigned int) m_pBits[i]);
- }
- if(linebreak){
- std::cout << (std::dec) << std::endl;
- }
- }
- void CBitVector::PrintBinary() {
- std::cout << "PRINT BINARY:: " << std::endl;
- Print(0, m_nByteSize << 3);
- }
- void CBitVector::PrintContent() {
- if (m_nElementLength == 1) {
- PrintHex();
- return;
- }
- if (m_nNumElementsDimB == 1) {
- for (std::size_t i = 0; i < m_nNumElements; i++) {
- std::cout << Get<int>(i) << ", ";
- }
- std::cout << std::endl;
- } else {
- for (std::size_t i = 0; i < m_nNumElements; i++) {
- std::cout << "(";
- for (std::size_t j = 0; j < m_nNumElementsDimB - 1; j++) {
- std::cout << Get2D<int>(i, j) << ", ";
- }
- std::cout << Get2D<int>(i, m_nNumElementsDimB - 1);
- std::cout << "), ";
- }
- std::cout << std::endl;
- }
- }
- void CBitVector::PrintBinaryMasked(std::size_t from, std::size_t to) {
- std::size_t new_to = to > (m_nByteSize<<3) ? (m_nByteSize<<3) : to;
- for (std::size_t i = from; i < new_to; i++) {
- std::cout << (unsigned int) GetBit(i);
- }
- std::cout << std::endl;
- }
- void CBitVector::Transpose(std::size_t rows, std::size_t columns) {
- #ifdef SIMPLE_TRANSPOSE
- SimpleTranspose(rows, columns);
- #else
- EklundhBitTranspose(rows, columns);
- #endif
- }
- void CBitVector::SimpleTranspose(std::size_t rows, std::size_t columns) {
- CBitVector temp(rows * columns);
- temp.Copy(m_pBits, 0, rows * columns / 8);
- for (std::size_t i = 0; i < rows; i++) {
- for (std::size_t j = 0; j < columns; j++) {
- SetBit(j * rows + i, temp.GetBit(i * columns + j));
- }
- }
- }
- //A transposition algorithm for bit-matrices of size 2^i x 2^i
- void CBitVector::EklundhBitTranspose(std::size_t rows, std::size_t columns) {
- REGISTER_SIZE* rowaptr; //ptr;
- REGISTER_SIZE* rowbptr;
- REGISTER_SIZE temp_row;
- REGISTER_SIZE mask;
- REGISTER_SIZE invmask;
- REGISTER_SIZE* lim;
- lim = (REGISTER_SIZE*) m_pBits + ceil_divide(rows * columns, 8);
- std::size_t offset = (columns >> 3) / sizeof(REGISTER_SIZE);
- std::size_t numiters = ceil_log2(std::min(rows, columns));
- std::size_t srcidx = 1, destidx;
- std::size_t rounds;
- //If swapping is performed on bit-level
- for (std::size_t i = 0; i < LOG2_REGISTER_SIZE; i++, srcidx *= 2) {
- destidx = offset * srcidx;
- rowaptr = (REGISTER_SIZE*) m_pBits;
- rowbptr = rowaptr + destidx;
- //Preset the masks that are required for bit-level swapping operations
- mask = TRANSPOSITION_MASKS[i];
- invmask = ~mask;
- //If swapping is performed on byte-level reverse operations due to little-endian format.
- rounds = rows / (srcidx * 2);
- if (i > 2) {
- for (std::size_t j = 0; j < rounds; j++) {
- for (lim = rowbptr + destidx; rowbptr < lim; rowaptr++, rowbptr++) {
- temp_row = *rowaptr;
- *rowaptr = ((*rowaptr & mask) ^ ((*rowbptr & mask) << srcidx));
- *rowbptr = ((*rowbptr & invmask) ^ ((temp_row & invmask) >> srcidx));
- }
- rowaptr += destidx;
- rowbptr += destidx;
- }
- } else {
- for (std::size_t j = 0; j < rounds; j++) {
- for (lim = rowbptr + destidx; rowbptr < lim; rowaptr++, rowbptr++) {
- temp_row = *rowaptr;
- *rowaptr = ((*rowaptr & invmask) ^ ((*rowbptr & invmask) >> srcidx));
- *rowbptr = ((*rowbptr & mask) ^ ((temp_row & mask) << srcidx));
- }
- rowaptr += destidx;
- rowbptr += destidx;
- }
- }
- }
- for (std::size_t i = LOG2_REGISTER_SIZE, swapoffset = 1, dswapoffset; i < numiters; i++, srcidx *= 2, swapoffset = swapoffset << 1) {
- destidx = offset * srcidx;
- dswapoffset = swapoffset << 1;
- rowaptr = (REGISTER_SIZE*) m_pBits;
- rowbptr = rowaptr + destidx - swapoffset;
- rounds = rows / (srcidx * 2);
- for (std::size_t j = 0; j < rows / (srcidx * 2); j++) {
- std::size_t p;
- for (p = 0, lim = rowbptr + destidx; p < destidx && rowbptr < lim; p++, rowaptr++, rowbptr++) {
- if ((p % dswapoffset >= swapoffset)) {
- temp_row = *rowaptr;
- *rowaptr = *rowbptr;
- *rowbptr = temp_row;
- }
- }
- rowaptr += destidx;
- rowbptr += destidx;
- }
- }
- if (columns > rows) {
- BYTE* tempvec = (BYTE*) malloc((rows * columns) / 8);
- memcpy(tempvec, m_pBits, ((rows / 8) * columns));
- rowaptr = (REGISTER_SIZE*) m_pBits;
- std::size_t rowbytesize = rows / 8;
- std::size_t rowregsize = rows / (sizeof(REGISTER_SIZE) * 8);
- for (std::size_t i = 0; i < columns / rows; i++) {
- rowbptr = (REGISTER_SIZE*) tempvec;
- rowbptr += (i * rowregsize);
- for (std::size_t j = 0; j < rows; j++, rowaptr += rowregsize, rowbptr += offset) {
- memcpy(rowaptr, rowbptr, rowbytesize);
- }
- }
- free(tempvec);
- }
- if (rows > columns) {
- BYTE* tempvec = (BYTE*) malloc((rows * columns) / 8);
- memcpy(tempvec, m_pBits, ((rows / 8) * columns));
- REGISTER_SIZE* rowaptr = (REGISTER_SIZE*) m_pBits;
- std::size_t colbytesize = columns / 8;
- std::size_t colregsize = columns / (sizeof(REGISTER_SIZE) * 8);
- std::size_t offset_cols = (columns * columns) / (sizeof(REGISTER_SIZE) * 8);
- for (std::size_t i = 0; i < columns; i++) {
- rowbptr = (REGISTER_SIZE*) tempvec;
- rowbptr += (i * colregsize);
- for (std::size_t j = 0; j < rows / columns; j++, rowaptr += colregsize, rowbptr += offset_cols) {
- memcpy(rowaptr, rowbptr, colbytesize);
- }
- }
- free(tempvec);
- }
- }
|