block.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /**
  2. *
  3. * @license GNU Public License (version 2); see LICENSE for full license text
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program 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 General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. **/
  19. #ifndef LOWMC_BLOCK_H__
  20. #define LOWMC_BLOCK_H__
  21. #include <bitset> // std::bitset
  22. #include <string> // std::string
  23. #include <iostream> // std::istream and std::ostream
  24. #include <x86intrin.h> // SSE and AVX intrinsics
  25. // namespace lowmc
  26. // {
  27. template <typename __mX>
  28. union block
  29. {
  30. public:
  31. typedef __mX value_type;
  32. block(const uint64_t input = 0ULL) : bits(input) { }
  33. block(const __mX & val) : mX(val) { }
  34. block(const std::string bit_string) : bits(bit_string) { }
  35. inline operator __mX() const { return mX; }
  36. inline block<__mX> & operator=(const __mX & val) { mX = val; return *this; }
  37. inline bool operator==(const __mX & rhs) const;
  38. inline bool operator!=(const __mX & rhs) const { return !(*this == rhs); }
  39. inline typename std::bitset<sizeof(__mX) * 8>::reference operator[](const size_t pos) { return bits[pos]; }
  40. inline const bool operator[](const size_t pos) const { return bits[pos]; }
  41. constexpr inline size_t size() const { return sizeof(__mX) * 8; }
  42. inline const unsigned parity() const { return bits.count() % 2; }
  43. inline void shiftr(const size_t pos) { bits >>= pos; }
  44. inline void shiftl(const size_t pos) { bits <<= pos; }
  45. std::bitset<8 * sizeof(__mX)> bits;
  46. //private:
  47. block(std::bitset<8 * sizeof(__mX)> & bitset) : bits(bitset) { }
  48. __mX mX;
  49. };
  50. template<>
  51. inline bool block<__m128i>::operator==(const __m128i & rhs) const
  52. {
  53. auto vcmp = _mm_xor_si128(*this, rhs);
  54. return _mm_testz_si128(vcmp, vcmp);
  55. }
  56. template<>
  57. inline bool block<__m256i>::operator==(const __m256i & rhs) const
  58. {
  59. auto vcmp = _mm256_xor_si256(*this, rhs);
  60. return _mm256_testz_si256(vcmp, vcmp);
  61. }
  62. template<typename __mX>
  63. inline block<__mX> operator|(const block<__mX> & block1, const block<__mX> & block2);
  64. template<>
  65. inline block<__m256i> operator|(const block<__m256i> & block1, const block<__m256i> & block2)
  66. {
  67. return _mm256_or_si256(block1, block2);
  68. }
  69. template<>
  70. inline block<__m128i> operator|(const block<__m128i> & block1, const block<__m128i> & block2)
  71. {
  72. return _mm_or_si128(block1, block2);
  73. }
  74. template<typename __mX>
  75. inline block<__mX> operator&(const block<__mX> & block1, const block<__mX> & block2);
  76. template<>
  77. inline block<__m256i> operator&(const block<__m256i> & block1, const block<__m256i> & block2)
  78. {
  79. return _mm256_and_si256(block1, block2);
  80. }
  81. template<>
  82. inline block<__m128i> operator&(const block<__m128i> & block1, const block<__m128i> & block2)
  83. {
  84. return _mm_and_si128(block1, block2);
  85. }
  86. template<typename __mX>
  87. inline block<__mX> operator^(const block<__mX> & block1, const block<__mX> & block2);
  88. template<>
  89. inline block<__m256i> operator^(const block<__m256i> & block1, const block<__m256i> & block2)
  90. {
  91. return _mm256_xor_si256(block1, block2);
  92. }
  93. template<>
  94. inline block<__m128i> operator^(const block<__m128i> & block1, const block<__m128i> & block2)
  95. {
  96. return _mm_xor_si128(block1, block2);
  97. }
  98. template<typename __mX>
  99. inline block<__mX> & operator^=(block<__mX> & block1, const block<__mX> & block2);
  100. template<>
  101. inline block<__m256i> & operator^=(block<__m256i> & block1, const block<__m256i> & block2)
  102. {
  103. block1 = _mm256_xor_si256(block1, block2);
  104. return block1;
  105. }
  106. template<>
  107. inline block<__m128i> & operator^=(block<__m128i> & block1, const block<__m128i> & block2)
  108. {
  109. block1 = _mm_xor_si128(block1, block2);
  110. return block1;
  111. }
  112. template<typename __mX>
  113. inline block<__mX> operator~(const block<__mX> & block);
  114. template<>
  115. inline block<__m256i> operator~(const block<__m256i> & block)
  116. {
  117. return ~static_cast<__m256i>(block);
  118. }
  119. template<>
  120. inline block<__m128i> operator~(const block<__m128i> & block)
  121. {
  122. return ~static_cast<__m128i>(block);
  123. }
  124. template<typename __mX>
  125. inline block<__mX> operator<<(const block<__mX> & block, const long & shift);
  126. template<>
  127. inline block<__m256i> operator<<(const block<__m256i> & block , const long & shift)
  128. {
  129. return _mm256_or_si256(_mm256_slli_epi64(block, shift), _mm256_blend_epi32(_mm256_setzero_si256(), _mm256_permute4x64_epi64(_mm256_srli_epi64(block, 64 - shift), _MM_SHUFFLE(2,1,0,0)), _MM_SHUFFLE(3,3,3,0)));
  130. }
  131. template<>
  132. inline block<__m128i> operator<<(const block<__m128i> & block, const long & shift)
  133. {
  134. return _mm_or_si128(_mm_slli_epi64(block, shift), _mm_srli_epi64(_mm_slli_si128(block, 8), 64 - shift));
  135. }
  136. template<typename __mX>
  137. inline block<__mX> & operator<<=(block<__mX> & block, const long & shift)
  138. {
  139. block = block << shift;
  140. return block;
  141. }
  142. template<typename __mX>
  143. inline block<__mX> operator>>(const block<__mX> & block, const long & shift);
  144. template<>
  145. inline block<__m256i> operator>>(const block<__m256i> & block, const long & shift)
  146. {
  147. return _mm256_or_si256(_mm256_srli_epi64(block, shift), _mm256_blend_epi32(_mm256_setzero_si256(), _mm256_permute4x64_epi64(_mm256_slli_epi64(block, 64 - shift), _MM_SHUFFLE(0,3,2,1)), _MM_SHUFFLE(0,3,3,3)));
  148. }
  149. template<>
  150. inline block<__m128i> operator>>(const block<__m128i> & block, const long & shift)
  151. {
  152. return _mm_or_si128(_mm_srli_epi64(block, shift), _mm_slli_epi64(_mm_srli_si128(block, 8), 64 - shift));
  153. }
  154. template<typename __mX>
  155. inline block<__mX> & operator>>=(block<__mX> & block, const long & shift)
  156. {
  157. block = block >> shift;
  158. return block;
  159. }
  160. //} // namespace lowmc
  161. #endif // LOWMC_BLOCK_H__