block.h 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #ifndef LOWMC_BLOCK_H__
  2. #define LOWMC_BLOCK_H__
  3. #include <bitset> // std::bitset
  4. #include <string> // std::string
  5. #include <iostream> // std::istream and std::ostream
  6. #include <x86intrin.h> // SSE and AVX intrinsics
  7. // namespace lowmc
  8. // {
  9. template <typename __mX>
  10. union block
  11. {
  12. public:
  13. typedef __mX value_type;
  14. block(const uint64_t input = 0ULL) : bits(input) { }
  15. block(const __mX & val) : mX(val) { }
  16. block(const std::string bit_string) : bits(bit_string) { }
  17. inline operator __mX() const { return mX; }
  18. inline block<__mX> & operator=(const __mX & val) { mX = val; return *this; }
  19. inline bool operator==(const __mX & rhs) const;
  20. inline bool operator!=(const __mX & rhs) const { return !(*this == rhs); }
  21. inline typename std::bitset<sizeof(__mX) * 8>::reference operator[](const size_t pos) { return bits[pos]; }
  22. inline const bool operator[](const size_t pos) const { return bits[pos]; }
  23. constexpr inline size_t size() const { return sizeof(__mX) * 8; }
  24. inline const unsigned parity() const { return bits.count() % 2; }
  25. inline void shiftr(const size_t pos) { bits >>= pos; }
  26. inline void shiftl(const size_t pos) { bits <<= pos; }
  27. std::bitset<8 * sizeof(__mX)> bits;
  28. //private:
  29. block(std::bitset<8 * sizeof(__mX)> & bitset) : bits(bitset) { }
  30. __mX mX;
  31. };
  32. template<>
  33. inline bool block<__m128i>::operator==(const __m128i & rhs) const
  34. {
  35. auto vcmp = _mm_xor_si128(*this, rhs);
  36. return _mm_testz_si128(vcmp, vcmp);
  37. }
  38. template<>
  39. inline bool block<__m256i>::operator==(const __m256i & rhs) const
  40. {
  41. auto vcmp = _mm256_xor_si256(*this, rhs);
  42. return _mm256_testz_si256(vcmp, vcmp);
  43. }
  44. template<typename __mX>
  45. inline block<__mX> operator|(const block<__mX> & block1, const block<__mX> & block2);
  46. template<>
  47. inline block<__m256i> operator|(const block<__m256i> & block1, const block<__m256i> & block2)
  48. {
  49. return _mm256_or_si256(block1, block2);
  50. }
  51. template<>
  52. inline block<__m128i> operator|(const block<__m128i> & block1, const block<__m128i> & block2)
  53. {
  54. return _mm_or_si128(block1, block2);
  55. }
  56. template<typename __mX>
  57. inline block<__mX> operator&(const block<__mX> & block1, const block<__mX> & block2);
  58. template<>
  59. inline block<__m256i> operator&(const block<__m256i> & block1, const block<__m256i> & block2)
  60. {
  61. return _mm256_and_si256(block1, block2);
  62. }
  63. template<>
  64. inline block<__m128i> operator&(const block<__m128i> & block1, const block<__m128i> & block2)
  65. {
  66. return _mm_and_si128(block1, block2);
  67. }
  68. template<typename __mX>
  69. inline block<__mX> operator^(const block<__mX> & block1, const block<__mX> & block2);
  70. template<>
  71. inline block<__m256i> operator^(const block<__m256i> & block1, const block<__m256i> & block2)
  72. {
  73. return _mm256_xor_si256(block1, block2);
  74. }
  75. template<>
  76. inline block<__m128i> operator^(const block<__m128i> & block1, const block<__m128i> & block2)
  77. {
  78. return _mm_xor_si128(block1, block2);
  79. }
  80. template<typename __mX>
  81. inline block<__mX> & operator^=(block<__mX> & block1, const block<__mX> & block2);
  82. template<>
  83. inline block<__m256i> & operator^=(block<__m256i> & block1, const block<__m256i> & block2)
  84. {
  85. block1 = _mm256_xor_si256(block1, block2);
  86. return block1;
  87. }
  88. template<>
  89. inline block<__m128i> & operator^=(block<__m128i> & block1, const block<__m128i> & block2)
  90. {
  91. block1 = _mm_xor_si128(block1, block2);
  92. return block1;
  93. }
  94. template<typename __mX>
  95. inline block<__mX> operator~(const block<__mX> & block);
  96. template<>
  97. inline block<__m256i> operator~(const block<__m256i> & block)
  98. {
  99. return ~static_cast<__m256i>(block);
  100. }
  101. template<>
  102. inline block<__m128i> operator~(const block<__m128i> & block)
  103. {
  104. return ~static_cast<__m128i>(block);
  105. }
  106. template<typename __mX>
  107. inline block<__mX> operator<<(const block<__mX> & block, const long & shift);
  108. template<>
  109. inline block<__m256i> operator<<(const block<__m256i> & block , const long & shift)
  110. {
  111. 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)));
  112. }
  113. template<>
  114. inline block<__m128i> operator<<(const block<__m128i> & block, const long & shift)
  115. {
  116. return _mm_or_si128(_mm_slli_epi64(block, shift), _mm_srli_epi64(_mm_slli_si128(block, 8), 64 - shift));
  117. }
  118. template<typename __mX>
  119. inline block<__mX> & operator<<=(block<__mX> & block, const long & shift)
  120. {
  121. block = block << shift;
  122. return 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_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)));
  130. }
  131. template<>
  132. inline block<__m128i> operator>>(const block<__m128i> & block, const long & shift)
  133. {
  134. return _mm_or_si128(_mm_srli_epi64(block, shift), _mm_slli_epi64(_mm_srli_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. //} // namespace lowmc
  143. #endif // LOWMC_BLOCK_H__