cbitvector.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. /**
  2. \file cbitvector.cpp
  3. \author michael.zohner@ec-spride.de
  4. \copyright ABY - A Framework for Efficient Mixed-protocol Secure Two-party Computation
  5. Copyright (C) 2019 ENCRYPTO Group, TU Darmstadt
  6. This program is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU Lesser General Public License as published
  8. by the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. ABY is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU Lesser General Public License for more details.
  14. You should have received a copy of the GNU Lesser General Public License
  15. along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. \brief CBitVector Implementation
  17. */
  18. #include "cbitvector.h"
  19. #include "crypto/crypto.h"
  20. #include "utils.h"
  21. #include <algorithm>
  22. #include <iomanip>
  23. #include <iostream>
  24. #include <cstring>
  25. namespace {
  26. /** Array which stores the bytes which are reversed. For example, the hexadecimal 0x01 is when reversed becomes 0x80. */
  27. 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,
  28. 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,
  29. 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,
  30. 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,
  31. 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,
  32. 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,
  33. 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,
  34. 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,
  35. 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,
  36. 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF };
  37. /**
  38. 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
  39. method for lower bit mask.
  40. */
  41. constexpr BYTE RESET_BIT_POSITIONS[9] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
  42. /**
  43. 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
  44. method for upper bit mask.
  45. */
  46. constexpr BYTE RESET_BIT_POSITIONS_INV[9] = { 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF };
  47. /** This array is used by \link GetBits(BYTE* p, int pos, int len) \endlink method for lower bit mask. */
  48. constexpr BYTE GET_BIT_POSITIONS[9] = { 0xFF, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00 };
  49. /** This array is used by \link GetBits(BYTE* p, int pos, int len) \endlink method for upper bit mask. */
  50. constexpr BYTE GET_BIT_POSITIONS_INV[9] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00 };
  51. /**
  52. This array is used for masking bits and extracting a particular positional bit from the provided byte array.
  53. This array is used by \link GetBit(int idx) \endlink method.
  54. */
  55. constexpr BYTE MASK_BIT[8] = { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 };
  56. /**
  57. This array is used for extracting a particular positional bit from the provided byte array without masking.
  58. This array is used by \link GetBitNoMask(int idx) \endlink method.
  59. */
  60. static constexpr BYTE BIT[8] = { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 };
  61. /**
  62. This array is used for masking bits and setting a particular positional bit from the provided byte array in the CBitVector.
  63. This array is used by \link SetBit(int idx, BYTE b) \endlink and \link ANDBit(int idx, BYTE b) \endlink methods.
  64. */
  65. constexpr BYTE CMASK_BIT[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
  66. /**
  67. This array is used for setting a particular positional bit from the provided byte array without masking in the CBitVector.
  68. This array is used by \link SetBitNoMask(int idx, BYTE b) \endlink and \link ANDBitNoMask(int idx, BYTE b) \endlink methods.
  69. */
  70. constexpr BYTE C_BIT[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F };
  71. /**
  72. This array is used for masking bits and setting a particular positional bit from the provided byte array in the CBitVector.
  73. This array is used by \link SetBit(int idx, BYTE b) \endlink and \link XORBit(int idx, BYTE b) \endlink methods.
  74. */
  75. constexpr BYTE MASK_SET_BIT_C[2][8] = { { 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 }, { 0, 0, 0, 0, 0, 0, 0, 0 } };
  76. /**
  77. This array is used for setting a particular positional bit from the provided byte array without masking in the CBitVector.
  78. This array is used by \link SetBitNoMask(int idx, BYTE b) \endlink and \link XORBitNoMask(int idx, BYTE b) \endlink methods.
  79. */
  80. constexpr BYTE SET_BIT_C[2][8] = { { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 }, { 0, 0, 0, 0, 0, 0, 0, 0 } };
  81. const BYTE SELECT_BIT_POSITIONS[9] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF };
  82. #if (__WORDSIZE==32)
  83. constexpr REGISTER_SIZE TRANSPOSITION_MASKS[6] =
  84. { 0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
  85. constexpr REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] =
  86. { 0xAAAAAAAA, 0xCCCCCCCC, 0xF0F0F0F0, 0xFF00FF00, 0xFFFF0000};
  87. #else
  88. #if (__WORDSIZE==64)
  89. /** Transposition mask used for Eklund Bit Matrix Transposition.*/
  90. constexpr REGISTER_SIZE TRANSPOSITION_MASKS[6] = { 0x5555555555555555, 0x3333333333333333, 0x0F0F0F0F0F0F0F0F, 0x00FF00FF00FF00FF, 0x0000FFFF0000FFFF, 0x00000000FFFFFFFF };
  91. constexpr REGISTER_SIZE TRANSPOSITION_MASKS_INV[6] = { 0xAAAAAAAAAAAAAAAA, 0xCCCCCCCCCCCCCCCC, 0xF0F0F0F0F0F0F0F0, 0xFF00FF00FF00FF00, 0xFFFF0000FFFF0000, 0xFFFFFFFF00000000 };
  92. #else
  93. #endif
  94. #endif
  95. constexpr size_t SHIFTVAL = 3;
  96. template<class T> void GetBytes(T* dst, const T* src, const T* lim) {
  97. while (dst != lim) {
  98. *dst++ = *src++;
  99. }
  100. }
  101. template<class T> void SetBytes(T* dst, const T* src, const T* lim) {
  102. while (dst < lim) {
  103. *dst++ = *src++;
  104. }
  105. }
  106. //Generic bytewise XOR operation
  107. template<class T> void XORBytes(T* dst, const T* src, const T* lim) {
  108. while (dst != lim) {
  109. *dst++ ^= *src++;
  110. }
  111. }
  112. template<class T> void ANDBytes(T* dst, const T* src, const T* lim) {
  113. while (dst != lim) {
  114. *dst++ &= *src++;
  115. }
  116. }
  117. constexpr BYTE GetArrayBit(const BYTE* p, size_t idx) {
  118. return 0 != (p[idx >> 3] & BIT[idx & 0x7]);
  119. }
  120. } // namespace
  121. CBitVector::CBitVector() {
  122. Init();
  123. }
  124. CBitVector::CBitVector(std::size_t bits) {
  125. Init();
  126. Create(bits);
  127. }
  128. CBitVector::CBitVector(std::size_t bits, crypto* crypt) {
  129. Init();
  130. Create(bits, crypt);
  131. }
  132. void CBitVector::Init() {
  133. m_pBits = NULL;
  134. m_nByteSize = 0;
  135. }
  136. CBitVector::~CBitVector(){
  137. delCBitVector();
  138. };
  139. void CBitVector::delCBitVector() {
  140. if (( m_nByteSize > 0 )&& (m_pBits != NULL)) {
  141. free(m_pBits);
  142. }
  143. m_nByteSize = 0;
  144. m_pBits = NULL;
  145. }
  146. /* Fill random values using the pre-defined AES key */
  147. void CBitVector::FillRand(std::size_t bits, crypto* crypt) {
  148. if (bits > m_nByteSize << 3)
  149. Create(bits);
  150. crypt->gen_rnd(m_pBits, ceil_divide(bits, 8));
  151. }
  152. void CBitVector::CreateExact(std::size_t bits) {
  153. if (bits == 0){
  154. bits = AES_BITS;
  155. }
  156. // if memory was previously allocated: free it
  157. if (m_nByteSize > 0) {
  158. free(m_pBits);
  159. }
  160. m_nByteSize = ceil_divide(bits, 8);
  161. m_pBits = (BYTE*) calloc(m_nByteSize, sizeof(BYTE));
  162. assert(m_pBits != NULL);
  163. m_nElementLength = 1;
  164. m_nNumElements = m_nByteSize;
  165. m_nNumElementsDimB = 1;
  166. }
  167. void CBitVector::Create(std::size_t bits) {
  168. //TODO: check if padding to AES_BITS is still necessary as default
  169. CreateExact(ceil_divide(bits, AES_BITS) * AES_BITS);
  170. }
  171. void CBitVector::CreateBytes(std::size_t bytes) {
  172. Create(bytes << 3);
  173. }
  174. void CBitVector::CreateBytes(std::size_t bytes, crypto* crypt) {
  175. Create(bytes << 3, crypt);
  176. }
  177. void CBitVector::CreateZeros(std::size_t bits) {
  178. Create(bits);
  179. memset(m_pBits, 0, m_nByteSize);
  180. }
  181. void CBitVector::Create(std::size_t bits, crypto* crypt) {
  182. Create(bits);
  183. FillRand(bits, crypt);
  184. }
  185. void CBitVector::Create(std::size_t numelements, std::size_t elementlength) {
  186. Create(numelements * elementlength);
  187. m_nElementLength = elementlength;
  188. m_nNumElements = numelements;
  189. m_nNumElementsDimB = 1;
  190. }
  191. void CBitVector::Create(std::size_t numelements, std::size_t elementlength, crypto* crypt) {
  192. Create(numelements * elementlength, crypt);
  193. m_nElementLength = elementlength;
  194. m_nNumElements = numelements;
  195. m_nNumElementsDimB = 1;
  196. }
  197. void CBitVector::Create(std::size_t numelementsDimA, std::size_t numelementsDimB, std::size_t elementlength) {
  198. Create(numelementsDimA * numelementsDimB * elementlength);
  199. m_nElementLength = elementlength;
  200. m_nNumElements = numelementsDimA;
  201. m_nNumElementsDimB = numelementsDimB;
  202. }
  203. void CBitVector::Create(std::size_t numelementsDimA, std::size_t numelementsDimB, std::size_t elementlength, crypto* crypt) {
  204. Create(numelementsDimA * numelementsDimB * elementlength, crypt);
  205. m_nElementLength = elementlength;
  206. m_nNumElements = numelementsDimA;
  207. m_nNumElementsDimB = numelementsDimB;
  208. }
  209. void CBitVector::ResizeinBytes(std::size_t newSizeBytes) {
  210. BYTE* tBits = m_pBits;
  211. uint64_t tSize = (m_nByteSize<newSizeBytes)? m_nByteSize:newSizeBytes; //fix for overflow condition in memcpy.
  212. m_nByteSize = newSizeBytes;
  213. m_pBits = (uint8_t*) calloc(m_nByteSize, sizeof(uint8_t));
  214. memcpy(m_pBits, tBits, tSize);
  215. free(tBits);
  216. }
  217. void CBitVector::Reset() {
  218. memset(m_pBits, 0, m_nByteSize);
  219. }
  220. void CBitVector::ResetFromTo(std::size_t frombyte, std::size_t tobyte) {
  221. assert(frombyte <= tobyte);
  222. assert(tobyte < m_nByteSize);
  223. memset(m_pBits + frombyte, 0, tobyte - frombyte);
  224. }
  225. void CBitVector::SetToOne() {
  226. memset(m_pBits, 0xFF, m_nByteSize);
  227. }
  228. void CBitVector::Invert() {
  229. for(std::size_t i = 0; i < m_nByteSize; i++) {
  230. m_pBits[i] = ~m_pBits[i];
  231. }
  232. }
  233. std::size_t CBitVector::GetSize() const {
  234. return m_nByteSize;
  235. }
  236. BOOL CBitVector::IsEqual(const CBitVector& vec) const {
  237. if (vec.GetSize() != m_nByteSize) {
  238. return false;
  239. }
  240. const BYTE* ptr = vec.GetArr();
  241. for (std::size_t i = 0; i < m_nByteSize; i++) {
  242. if (ptr[i] != m_pBits[i]) {
  243. return false;
  244. }
  245. }
  246. return true;
  247. }
  248. BOOL CBitVector::IsEqual(const CBitVector& vec, std::size_t from, std::size_t to) const {
  249. if (vec.GetSize() * 8 < to || m_nByteSize * 8 < to || from > to) {
  250. return false;
  251. }
  252. for (std::size_t i = from; i < to; i++) {
  253. if (vec.GetBit(i) != GetBit(i)) {
  254. return false;
  255. }
  256. }
  257. return true;
  258. }
  259. void CBitVector::SetElementLength(std::size_t elelen) {
  260. m_nElementLength = elelen;
  261. }
  262. std::size_t CBitVector::GetElementLength() const {
  263. return m_nElementLength;
  264. }
  265. void CBitVector::Copy(const CBitVector& vec) {
  266. Copy(vec.GetArr(), 0, vec.GetSize());
  267. }
  268. void CBitVector::Copy(const CBitVector& vec, std::size_t pos, std::size_t len) {
  269. Copy(vec.GetArr(), pos, len);
  270. }
  271. void CBitVector::Copy(const BYTE* p, std::size_t pos, std::size_t len) {
  272. if (pos + len > m_nByteSize) {
  273. if (m_pBits)
  274. ResizeinBytes(pos + len);
  275. else {
  276. CreateBytes(pos + len);
  277. }
  278. }
  279. memcpy(m_pBits + pos, p, len);
  280. }
  281. void CBitVector::ORByte(std::size_t pos, BYTE p) {
  282. assert(pos <= m_nByteSize);
  283. m_pBits[pos] |= p;
  284. }
  285. BYTE CBitVector::GetBit(std::size_t idx) const {
  286. assert(idx < (m_nByteSize << 3));
  287. return !!(m_pBits[idx >> 3] & MASK_BIT[idx & 0x7]);
  288. }
  289. void CBitVector::SetBit(std::size_t idx, BYTE b) {
  290. assert(idx < (m_nByteSize << 3));
  291. m_pBits[idx >> 3] = (m_pBits[idx >> 3] & CMASK_BIT[idx & 0x7]) | MASK_SET_BIT_C[!(b & 0x01)][idx & 0x7];
  292. }
  293. BYTE CBitVector::GetBitNoMask(std::size_t idx) const {
  294. assert(idx < (m_nByteSize << 3));
  295. return GetArrayBit(m_pBits, idx);
  296. }
  297. void CBitVector::SetBitNoMask(std::size_t idx, BYTE b) {
  298. assert(idx < (m_nByteSize << 3));
  299. m_pBits[idx >> 3] = (m_pBits[idx >> 3] & C_BIT[idx & 0x7]) | SET_BIT_C[!(b & 0x01)][idx & 0x7];
  300. }
  301. void CBitVector::XORBitNoMask(std::size_t idx, BYTE b) {
  302. assert(idx < (m_nByteSize << 3));
  303. m_pBits[idx >> 3] ^= SET_BIT_C[!(b & 0x01)][idx & 0x7];
  304. }
  305. void CBitVector::SetByte(std::size_t idx, BYTE p) {
  306. assert(idx < m_nByteSize);
  307. m_pBits[idx] = p;
  308. }
  309. BYTE CBitVector::GetByte(std::size_t idx) const {
  310. assert(idx < m_nByteSize);
  311. return m_pBits[idx];
  312. }
  313. void CBitVector::XORByte(std::size_t idx, BYTE b) {
  314. assert(idx < m_nByteSize);
  315. m_pBits[idx] ^= b;
  316. }
  317. void CBitVector::ANDByte(std::size_t idx, BYTE b) {
  318. assert(idx < m_nByteSize);
  319. m_pBits[idx] &= b;
  320. }
  321. void CBitVector::GetBits(BYTE* p, std::size_t pos, std::size_t len) const {
  322. if (len < 1 || (pos + len) > (m_nByteSize << 3)) {
  323. return;
  324. }
  325. if (len == 1) {
  326. *p = GetBitNoMask(pos);
  327. return;
  328. }
  329. if (!((pos & 0x07) || (len & 0x07))) {
  330. GetBytes(p, pos >> 3, len >> 3);
  331. return;
  332. }
  333. int posctr = pos >> 3;
  334. int lowermask = pos & 7;
  335. int uppermask = 8 - lowermask;
  336. std::size_t i;
  337. for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
  338. p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF;
  339. p[i] |= (m_pBits[posctr + 1] & GET_BIT_POSITIONS_INV[uppermask]) << uppermask;
  340. }
  341. int remlen = len & 0x07;
  342. if (remlen) {
  343. if (remlen <= uppermask) {
  344. p[i] = ((m_pBits[posctr] & ((((1 << remlen) - 1) << lowermask))) >> lowermask) & 0xFF;
  345. } else {
  346. p[i] = ((m_pBits[posctr] & GET_BIT_POSITIONS[lowermask]) >> lowermask) & 0xFF;
  347. p[i] |= (m_pBits[posctr + 1] & (((1 << (remlen - uppermask)) - 1))) << uppermask;
  348. }
  349. }
  350. }
  351. //optimized bytewise for set operation
  352. void CBitVector::GetBytes(BYTE* p, std::size_t pos, std::size_t len) const {
  353. assert(pos+len <= m_nByteSize);
  354. BYTE* src = m_pBits + pos;
  355. BYTE* dst = p;
  356. //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
  357. ::GetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
  358. dst += ((len >> SHIFTVAL) << SHIFTVAL);
  359. src += ((len >> SHIFTVAL) << SHIFTVAL);
  360. ::GetBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
  361. }
  362. //
  363. //pos and len in bits
  364. void CBitVector::SetBits(const BYTE* p, std::size_t pos, std::size_t len) {
  365. if (len < 1 || (pos + len) > (m_nByteSize << 3)){
  366. return;
  367. }
  368. if (len == 1) {
  369. SetBitNoMask(pos, *p);
  370. return;
  371. }
  372. if (!((pos & 0x07) || (len & 0x07))) {
  373. SetBytes(p, pos >> 3, len >> 3);
  374. return;
  375. }
  376. std::size_t posctr = pos >> 3;
  377. int lowermask = pos & 7;
  378. int uppermask = 8 - lowermask;
  379. std::size_t i;
  380. BYTE temp;
  381. for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
  382. temp = p[i];
  383. m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF);
  384. m_pBits[posctr + 1] = (m_pBits[posctr + 1] & RESET_BIT_POSITIONS_INV[uppermask]) | (temp >> uppermask);
  385. }
  386. int remlen = len & 0x07;
  387. if (remlen) {
  388. temp = p[i] & RESET_BIT_POSITIONS[remlen];
  389. if (remlen <= uppermask) {
  390. m_pBits[posctr] = (m_pBits[posctr] & (~(((1 << remlen) - 1) << lowermask))) | ((temp << lowermask) & 0xFF);
  391. } else {
  392. m_pBits[posctr] = (m_pBits[posctr] & RESET_BIT_POSITIONS[lowermask]) | ((temp << lowermask) & 0xFF);
  393. m_pBits[posctr + 1] = (m_pBits[posctr + 1] & (~(((1 << (remlen - uppermask)) - 1)))) | (temp >> uppermask);
  394. }
  395. }
  396. }
  397. //Set bits given an offset on the bits for p which is not necessarily divisible by 8
  398. void CBitVector::SetBitsPosOffset(const BYTE* p, std::size_t ppos, std::size_t pos, std::size_t len) {
  399. for (auto i = pos, j = ppos; j < ppos + len; i++, j++) {
  400. BYTE source_bit = GetArrayBit(p, j);
  401. SetBitNoMask(i, source_bit);
  402. }
  403. }
  404. //optimized bytewise for set operation
  405. void CBitVector::SetBytes(const BYTE *src, std::size_t pos, std::size_t len) {
  406. assert(pos + len <= m_nByteSize);
  407. BYTE *dst = m_pBits + pos;
  408. //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
  409. ::SetBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
  410. dst += ((len >> SHIFTVAL) << SHIFTVAL);
  411. src += ((len >> SHIFTVAL) << SHIFTVAL);
  412. ::SetBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
  413. }
  414. void CBitVector::SetBytesToZero(std::size_t bytepos, std::size_t bytelen) {
  415. assert(bytepos + bytelen <= m_nByteSize);
  416. memset(m_pBits + bytepos, 0x00, bytelen);
  417. }
  418. void CBitVector::SetBitsToZero(std::size_t bitpos, std::size_t bitlen) {
  419. int firstlim = ceil_divide(bitpos, 8);
  420. int firstlen = ceil_divide(bitlen - (bitpos % 8), 8);
  421. for (int i = bitpos; i < firstlim; i++) {
  422. SetBitNoMask(i, 0);
  423. }
  424. if (bitlen > 7) {
  425. memset(m_pBits + firstlim, 0, firstlen);
  426. }
  427. for (std::size_t i = (firstlim + firstlen) << 8; i < bitpos + bitlen; i++) {
  428. SetBitNoMask(i, 0);
  429. }
  430. }
  431. //optimized bytewise XOR operation
  432. void CBitVector::XORBytes(const BYTE* p, std::size_t pos, std::size_t len) {
  433. if(pos + len > m_nByteSize)
  434. std::cout << "pos = " << pos << ", len = " << len << ", bytesize = " << m_nByteSize << std::endl;
  435. assert(pos + len <= m_nByteSize);
  436. BYTE* dst = m_pBits + pos;
  437. const BYTE* src = p;
  438. //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
  439. ::XORBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
  440. dst += ((len >> SHIFTVAL) << SHIFTVAL);
  441. src += ((len >> SHIFTVAL) << SHIFTVAL);
  442. ::XORBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
  443. }
  444. void CBitVector::XORBytes(const BYTE* p, std::size_t len) {
  445. XORBytes(p, 0, len);
  446. }
  447. void CBitVector::XORVector(const CBitVector &vec, std::size_t pos, std::size_t len) {
  448. XORBytes(vec.GetArr(), pos, len);
  449. }
  450. void CBitVector::XORBits(const BYTE* p, std::size_t pos, std::size_t len) {
  451. if (len < 1 || (pos + len) > m_nByteSize << 3) {
  452. return;
  453. }
  454. if (len == 1) {
  455. XORBitNoMask(pos, *p);
  456. return;
  457. }
  458. if (!((pos & 0x07) || (len & 0x07))) {
  459. XORBytes(p, pos >> 3, len >> 3);
  460. return;
  461. }
  462. int posctr = pos >> 3;
  463. int lowermask = pos & 7;
  464. int uppermask = 8 - lowermask;
  465. std::size_t i;
  466. BYTE temp;
  467. for (i = 0; i < len / (sizeof(BYTE) * 8); i++, posctr++) {
  468. temp = p[i];
  469. m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
  470. m_pBits[posctr + 1] ^= (temp >> uppermask);
  471. }
  472. int remlen = len & 0x07;
  473. if (remlen) {
  474. temp = p[i] & RESET_BIT_POSITIONS[remlen];
  475. if (remlen <= uppermask) {
  476. m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
  477. } else {
  478. m_pBits[posctr] ^= ((temp << lowermask) & 0xFF);
  479. m_pBits[posctr + 1] ^= (temp >> uppermask);
  480. }
  481. }
  482. }
  483. //XOR bits given an offset on the bits for p which is not necessarily divisible by 8
  484. void CBitVector::XORBitsPosOffset(const BYTE* p, std::size_t ppos, std::size_t pos, std::size_t len) {
  485. assert((pos + len) <= (m_nByteSize<<3));
  486. for (auto i = pos, j = ppos; j < ppos + len; i++, j++) {
  487. m_pBits[i / 8] ^= (((p[j / 8] & (1 << (j % 8))) >> j % 8) << i % 8);
  488. }
  489. }
  490. //Method for directly XORing CBitVectors
  491. void CBitVector::XOR(const CBitVector* b) {
  492. assert(b->GetSize() == m_nByteSize);
  493. XORBytes(b->GetArr(), 0, m_nByteSize);
  494. }
  495. void CBitVector::XORBytesReverse(const BYTE* p, std::size_t pos, std::size_t len) {
  496. assert((pos + len) <= m_nByteSize);
  497. const BYTE* src = p;
  498. BYTE* dst = m_pBits + pos;
  499. BYTE* lim = dst + len;
  500. while (dst != lim) {
  501. *dst++ ^= REVERSE_BYTE_ORDER[*src++];
  502. }
  503. }
  504. //optimized bytewise for AND operation
  505. void CBitVector::ANDBytes(const BYTE* p, std::size_t pos, std::size_t len) {
  506. assert(pos+len <= m_nByteSize);
  507. BYTE* dst = m_pBits + pos;
  508. const BYTE* src = p;
  509. //Do many operations on REGSIZE types first and then (if necessary) use bytewise operations
  510. ::ANDBytes((REGSIZE*) dst, (REGSIZE*) src, ((REGSIZE*) dst) + (len >> SHIFTVAL));
  511. dst += ((len >> SHIFTVAL) << SHIFTVAL);
  512. src += ((len >> SHIFTVAL) << SHIFTVAL);
  513. ::ANDBytes(dst, src, dst + (len & ((1 << SHIFTVAL) - 1)));
  514. }
  515. void CBitVector::SetXOR(const BYTE* p, const BYTE* q, std::size_t pos, std::size_t len) {
  516. Copy(p, pos, len);
  517. XORBytes(q, pos, len);
  518. }
  519. void CBitVector::SetAND(const BYTE* p, const BYTE* q, std::size_t pos, std::size_t len) {
  520. Copy(p, pos, len);
  521. ANDBytes(q, pos, len);
  522. }
  523. //Method for directly ANDing CBitVectors
  524. void CBitVector::AND(const CBitVector* b) {
  525. assert(b->GetSize() == m_nByteSize);
  526. ANDBytes(b->GetArr(), 0, m_nByteSize);
  527. }
  528. //Cyclic left shift by pos bits
  529. void CBitVector::CLShift(std::size_t pos) {
  530. uint8_t* tmpbuf = (uint8_t*) malloc(m_nByteSize);
  531. for(std::size_t i = 0; i < m_nByteSize; i++) {
  532. tmpbuf[i+pos] = m_pBits[i];
  533. }
  534. free(m_pBits);
  535. m_pBits = tmpbuf;
  536. }
  537. BYTE* CBitVector::GetArr() {
  538. return m_pBits;
  539. }
  540. const BYTE* CBitVector::GetArr() const {
  541. return m_pBits;
  542. }
  543. void CBitVector::AttachBuf(BYTE* p, std::size_t size) {
  544. m_pBits = p;
  545. m_nByteSize = size;
  546. }
  547. /**
  548. This method is used to detach the buffer from the CBitVector. */
  549. void CBitVector::DetachBuf() {
  550. m_pBits = NULL;
  551. m_nByteSize = 0;
  552. }
  553. void CBitVector::Print(std::size_t fromBit, std::size_t toBit) {
  554. std::size_t to = toBit > (m_nByteSize << 3) ? (m_nByteSize << 3) : toBit;
  555. std::cout << "fromBit = " << fromBit << std::endl;
  556. std::cout << "to = " << to << std::endl;
  557. for (std::size_t i = fromBit; i < to; i++) {
  558. std::cout << (unsigned int) GetBitNoMask(i);
  559. }
  560. std::cout << std::endl;
  561. }
  562. void CBitVector::PrintHex(bool linebreak) {
  563. for (std::size_t i = 0; i < m_nByteSize; i++) {
  564. std::cout << std::setw(2) << std::setfill('0') << (std::hex) << ((unsigned int) m_pBits[i]);
  565. }
  566. if(linebreak){
  567. std::cout << (std::dec) << std::endl;
  568. }
  569. }
  570. void CBitVector::PrintHex(std::size_t fromByte, std::size_t toByte, bool linebreak) {
  571. std::size_t to = toByte > (m_nByteSize) ? (m_nByteSize) : toByte;
  572. for (std::size_t i = fromByte; i < to; i++) {
  573. std::cout << std::setw(2) << std::setfill('0') << (std::hex) << ((unsigned int) m_pBits[i]);
  574. }
  575. if(linebreak){
  576. std::cout << (std::dec) << std::endl;
  577. }
  578. }
  579. void CBitVector::PrintBinary() {
  580. std::cout << "PRINT BINARY:: " << std::endl;
  581. Print(0, m_nByteSize << 3);
  582. }
  583. void CBitVector::PrintContent() {
  584. if (m_nElementLength == 1) {
  585. PrintHex();
  586. return;
  587. }
  588. if (m_nNumElementsDimB == 1) {
  589. for (std::size_t i = 0; i < m_nNumElements; i++) {
  590. std::cout << Get<int>(i) << ", ";
  591. }
  592. std::cout << std::endl;
  593. } else {
  594. for (std::size_t i = 0; i < m_nNumElements; i++) {
  595. std::cout << "(";
  596. for (std::size_t j = 0; j < m_nNumElementsDimB - 1; j++) {
  597. std::cout << Get2D<int>(i, j) << ", ";
  598. }
  599. std::cout << Get2D<int>(i, m_nNumElementsDimB - 1);
  600. std::cout << "), ";
  601. }
  602. std::cout << std::endl;
  603. }
  604. }
  605. void CBitVector::PrintBinaryMasked(std::size_t from, std::size_t to) {
  606. std::size_t new_to = to > (m_nByteSize<<3) ? (m_nByteSize<<3) : to;
  607. for (std::size_t i = from; i < new_to; i++) {
  608. std::cout << (unsigned int) GetBit(i);
  609. }
  610. std::cout << std::endl;
  611. }
  612. void CBitVector::Transpose(std::size_t rows, std::size_t columns) {
  613. #ifdef SIMPLE_TRANSPOSE
  614. SimpleTranspose(rows, columns);
  615. #else
  616. EklundhBitTranspose(rows, columns);
  617. #endif
  618. }
  619. void CBitVector::SimpleTranspose(std::size_t rows, std::size_t columns) {
  620. CBitVector temp(rows * columns);
  621. temp.Copy(m_pBits, 0, rows * columns / 8);
  622. for (std::size_t i = 0; i < rows; i++) {
  623. for (std::size_t j = 0; j < columns; j++) {
  624. SetBit(j * rows + i, temp.GetBit(i * columns + j));
  625. }
  626. }
  627. }
  628. //A transposition algorithm for bit-matrices of size 2^i x 2^i
  629. void CBitVector::EklundhBitTranspose(std::size_t rows, std::size_t columns) {
  630. REGISTER_SIZE* rowaptr; //ptr;
  631. REGISTER_SIZE* rowbptr;
  632. REGISTER_SIZE temp_row;
  633. REGISTER_SIZE mask;
  634. REGISTER_SIZE invmask;
  635. REGISTER_SIZE* lim;
  636. lim = (REGISTER_SIZE*) m_pBits + ceil_divide(rows * columns, 8);
  637. std::size_t offset = (columns >> 3) / sizeof(REGISTER_SIZE);
  638. std::size_t numiters = ceil_log2(std::min(rows, columns));
  639. std::size_t srcidx = 1, destidx;
  640. std::size_t rounds;
  641. //If swapping is performed on bit-level
  642. for (std::size_t i = 0; i < LOG2_REGISTER_SIZE; i++, srcidx *= 2) {
  643. destidx = offset * srcidx;
  644. rowaptr = (REGISTER_SIZE*) m_pBits;
  645. rowbptr = rowaptr + destidx;
  646. //Preset the masks that are required for bit-level swapping operations
  647. mask = TRANSPOSITION_MASKS[i];
  648. invmask = ~mask;
  649. //If swapping is performed on byte-level reverse operations due to little-endian format.
  650. rounds = rows / (srcidx * 2);
  651. if (i > 2) {
  652. for (std::size_t j = 0; j < rounds; j++) {
  653. for (lim = rowbptr + destidx; rowbptr < lim; rowaptr++, rowbptr++) {
  654. temp_row = *rowaptr;
  655. *rowaptr = ((*rowaptr & mask) ^ ((*rowbptr & mask) << srcidx));
  656. *rowbptr = ((*rowbptr & invmask) ^ ((temp_row & invmask) >> srcidx));
  657. }
  658. rowaptr += destidx;
  659. rowbptr += destidx;
  660. }
  661. } else {
  662. for (std::size_t j = 0; j < rounds; j++) {
  663. for (lim = rowbptr + destidx; rowbptr < lim; rowaptr++, rowbptr++) {
  664. temp_row = *rowaptr;
  665. *rowaptr = ((*rowaptr & invmask) ^ ((*rowbptr & invmask) >> srcidx));
  666. *rowbptr = ((*rowbptr & mask) ^ ((temp_row & mask) << srcidx));
  667. }
  668. rowaptr += destidx;
  669. rowbptr += destidx;
  670. }
  671. }
  672. }
  673. for (std::size_t i = LOG2_REGISTER_SIZE, swapoffset = 1, dswapoffset; i < numiters; i++, srcidx *= 2, swapoffset = swapoffset << 1) {
  674. destidx = offset * srcidx;
  675. dswapoffset = swapoffset << 1;
  676. rowaptr = (REGISTER_SIZE*) m_pBits;
  677. rowbptr = rowaptr + destidx - swapoffset;
  678. rounds = rows / (srcidx * 2);
  679. for (std::size_t j = 0; j < rows / (srcidx * 2); j++) {
  680. std::size_t p;
  681. for (p = 0, lim = rowbptr + destidx; p < destidx && rowbptr < lim; p++, rowaptr++, rowbptr++) {
  682. if ((p % dswapoffset >= swapoffset)) {
  683. temp_row = *rowaptr;
  684. *rowaptr = *rowbptr;
  685. *rowbptr = temp_row;
  686. }
  687. }
  688. rowaptr += destidx;
  689. rowbptr += destidx;
  690. }
  691. }
  692. if (columns > rows) {
  693. BYTE* tempvec = (BYTE*) malloc((rows * columns) / 8);
  694. memcpy(tempvec, m_pBits, ((rows / 8) * columns));
  695. rowaptr = (REGISTER_SIZE*) m_pBits;
  696. std::size_t rowbytesize = rows / 8;
  697. std::size_t rowregsize = rows / (sizeof(REGISTER_SIZE) * 8);
  698. for (std::size_t i = 0; i < columns / rows; i++) {
  699. rowbptr = (REGISTER_SIZE*) tempvec;
  700. rowbptr += (i * rowregsize);
  701. for (std::size_t j = 0; j < rows; j++, rowaptr += rowregsize, rowbptr += offset) {
  702. memcpy(rowaptr, rowbptr, rowbytesize);
  703. }
  704. }
  705. free(tempvec);
  706. }
  707. if (rows > columns) {
  708. BYTE* tempvec = (BYTE*) malloc((rows * columns) / 8);
  709. memcpy(tempvec, m_pBits, ((rows / 8) * columns));
  710. REGISTER_SIZE* rowaptr = (REGISTER_SIZE*) m_pBits;
  711. std::size_t colbytesize = columns / 8;
  712. std::size_t colregsize = columns / (sizeof(REGISTER_SIZE) * 8);
  713. std::size_t offset_cols = (columns * columns) / (sizeof(REGISTER_SIZE) * 8);
  714. for (std::size_t i = 0; i < columns; i++) {
  715. rowbptr = (REGISTER_SIZE*) tempvec;
  716. rowbptr += (i * colregsize);
  717. for (std::size_t j = 0; j < rows / columns; j++, rowaptr += colregsize, rowbptr += offset_cols) {
  718. memcpy(rowaptr, rowbptr, colbytesize);
  719. }
  720. }
  721. free(tempvec);
  722. }
  723. }