hash/include/nil/crypto3/detail/reverser.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020 Alexander Sokolov <asokolov@nil.foundation>
4 // Copyright (c) 2020 Nikita Kaskov <nbering@nil.foundation>
5 //
6 // MIT License
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 //---------------------------------------------------------------------------//
26 
27 #ifndef CRYPTO3_DETAIL_REVERSER_HPP
28 #define CRYPTO3_DETAIL_REVERSER_HPP
29 
30 #include <boost/integer.hpp>
31 #include <boost/static_assert.hpp>
32 #include <boost/endian/conversion.hpp>
33 
34 #include <nil/crypto3/detail/unbounded_shift.hpp>
35 #include <nil/crypto3/detail/stream_endian.hpp>
36 #include <nil/crypto3/detail/predef.hpp>
37 
38 #include <climits>
39 
40 namespace nil {
41  namespace crypto3 {
42  namespace detail {
43 
48  typedef typename boost::uint_t<CHAR_BIT>::exact byte_type;
49 
62  inline void reverse_byte(byte_type &b) {
63 #if (BOOST_ARCH_CURRENT_WORD_BITS == 32)
64  b = unbounded_shr<16>(((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU);
65 #elif (BOOST_ARCH_CURRENT_WORD_BITS == 64)
66  b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
67 #else
68 #error "BOOST_ARCH_CURRENT_WORD_BITS not set"
69 #endif
70  }
71 
84  template<int UnitBits, int k = 0>
85  struct bit_in_unit_byte_reverser {
86 
87  BOOST_STATIC_ASSERT(!(UnitBits % CHAR_BIT));
88 
90  typedef typename boost::uint_t<UnitBits>::exact UnitType;
91 
92  inline static void reverse(UnitType &in, UnitType &out) {
93  int const shift = UnitBits - (CHAR_BIT + k);
94  byte_type byte = byte_type(low_bits<CHAR_BIT>(unbounded_shr(in, shift)));
95  reverse_byte(byte);
96  out |= unbounded_shl(low_bits<CHAR_BIT>(UnitType(byte)), shift);
97 
98  next_type::reverse(in, out);
99  }
100  };
101 
102  template<int UnitBits>
103  struct bit_in_unit_byte_reverser<UnitBits, UnitBits> {
104  inline static void reverse(typename boost::uint_t<UnitBits>::exact &,
105  typename boost::uint_t<UnitBits>::exact &) {
106  }
107  };
108 
127  template<typename UnitType,
128  int UnitBits = sizeof(UnitType) * CHAR_BIT,
129  typename std::enable_if<(UnitBits > CHAR_BIT), int>::type = 0>
130  inline void reverse_bits(UnitType &unit) {
131  boost::endian::endian_reverse_inplace(unit);
132  UnitType out = UnitType();
134  unit = out;
135  }
148  template<typename UnitType,
149  int UnitBits = sizeof(UnitType) * CHAR_BIT,
150  typename std::enable_if<(UnitBits == CHAR_BIT), int>::type = 0>
151  inline void reverse_bits(UnitType &unit) {
152  reverse_byte(unit);
153  }
154 
168  template<int InputBits, int UnitBits, int k = 0>
169  struct bit_in_unit_reverser {
170 
171  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
172 
174  typedef typename boost::uint_t<UnitBits>::exact UnitType;
175 
176  template<typename ValueType>
177  inline static void reverse(ValueType &in, ValueType &out) {
178  int const shift = InputBits - (UnitBits + k);
179  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
180  reverse_bits(unit);
181  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
182 
183  next_type::reverse(in, out);
184  }
185  };
186 
187  template<int InputBits, int UnitBits>
188  struct bit_in_unit_reverser<InputBits, UnitBits, InputBits> {
189  template<typename ValueType>
190  inline static void reverse(ValueType &, ValueType &) {
191  }
192  };
193 
208  template<typename Endianness, int UnitBits>
209  struct is_big_bit {
210  constexpr static const bool value =
211  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
212  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value;
213  };
214 
224  template<typename Endianness, int UnitBits>
225  struct is_little_bit {
226  constexpr static const bool value =
227  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value ||
228  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
229  };
230 
241  template<typename Endianness1, typename Endianness2, int UnitBits>
242  struct is_same_bit {
243  constexpr static const bool value =
246  };
247 
260  template<typename InputEndianness,
261  typename OutputEndianness,
262  int UnitBits,
264  struct bit_reverser;
265 
276  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
277  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, true> {
278  template<typename ValueType>
279  inline static void reverse(ValueType &) {
280  }
281 
282  template<typename ValueType>
283  inline static ValueType reverse(ValueType const &val) {
284  return val;
285  }
286  };
287 
298  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
299  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, false> {
300  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
301  inline static void reverse(ValueType &val) {
302  ValueType out = ValueType();
304  val = out;
305  }
306 
307  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
308  inline static ValueType reverse(ValueType const &val) {
309  ValueType tmp = val;
310  ValueType out = ValueType();
312  return out;
313  }
314  };
315 
329  template<int InputBits, int UnitBits, int k = 0>
330  struct byte_in_unit_reverser {
331 
332  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
333 
335  typedef typename boost::uint_t<UnitBits>::exact UnitType;
336 
337  template<typename ValueType>
338  inline static void reverse(ValueType &in, ValueType &out) {
339  int const shift = InputBits - (UnitBits + k);
340  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
341  boost::endian::endian_reverse_inplace(unit);
342  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
343 
344  next_type::reverse(in, out);
345  }
346  };
347 
348  template<int InputBits, int UnitBits>
349  struct byte_in_unit_reverser<InputBits, UnitBits, InputBits> {
350  template<typename ValueType>
351  inline static void reverse(ValueType &, ValueType &) {
352  }
353  };
354 
369  template<typename Endianness, int UnitBits>
370  struct is_big_unit {
371  constexpr static const bool value =
372  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
373  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value;
374  };
375 
385  template<typename Endianness, int UnitBits>
386  struct is_little_unit {
387  constexpr static const bool value =
388  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value ||
389  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
390  };
391 
402  template<typename Endianness1, typename Endianness2, int UnitBits>
403  struct is_same_unit {
404  constexpr static const bool value =
407  };
408 
420  template<typename InputEndianness, typename OutputEndianness, int UnitBits, typename Enable = void>
421  struct unit_reverser;
422 
433  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
434  struct unit_reverser<
435  InputEndianness,
436  OutputEndianness,
437  UnitBits,
438  typename std::enable_if<is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value>::type> {
439  template<typename ValueType>
440  inline static void reverse(ValueType &) {
441  }
442 
443  template<typename ValueType>
444  inline static ValueType reverse(ValueType const &val) {
445  return val;
446  }
447  };
448 
459  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
460  struct unit_reverser<
461  InputEndianness,
462  OutputEndianness,
463  UnitBits,
464  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
465  UnitBits == CHAR_BIT>::type> {
466  template<typename ValueType>
467  inline static void reverse(ValueType &val) {
468  boost::endian::endian_reverse_inplace(val);
469  }
470 
471  template<typename ValueType>
472  inline static ValueType reverse(ValueType const &val) {
473  return boost::endian::endian_reverse(val);
474  }
475  };
476 
488  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
489  struct unit_reverser<
490  InputEndianness,
491  OutputEndianness,
492  UnitBits,
493  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
494  (UnitBits > CHAR_BIT)>::type> {
495  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
496  inline static void reverse(ValueType &val) {
497  boost::endian::endian_reverse_inplace(val);
498  ValueType out = ValueType();
500  val = out;
501  }
502 
503  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
504  inline static ValueType reverse(ValueType const &val) {
505  ValueType tmp = boost::endian::endian_reverse(val);
506  ValueType out = ValueType();
508  return out;
509  }
510  };
511  } // namespace detail
512  } // namespace crypto3
513 } // namespace nil
514 
515 #endif // CRYPTO3_DETAIL_REVERSER_HPP
void reverse_bits(UnitType &unit)
The functions listed below deal with bit reversal in a unit.
Definition: block/include/nil/crypto3/detail/reverser.hpp:132
void reverse_byte(byte_type &b)
This function reverses bit order in the byte b depending on the machine word size....
Definition: block/include/nil/crypto3/detail/reverser.hpp:63
T unbounded_shr(T x)
Definition: algebra/include/nil/crypto3/detail/unbounded_shift.hpp:64
T unbounded_shl(T x)
Definition: algebra/include/nil/crypto3/detail/unbounded_shift.hpp:59
boost::uint_t< CHAR_BIT >::exact byte_type
Definition: block/include/nil/crypto3/detail/reverser.hpp:49
typename std::iterator_traits< Iterator >::value_type ValueType
Definition: algebra/include/nil/crypto3/detail/make_array.hpp:50
Definition: pair.hpp:31
static void reverse(typename boost::uint_t< UnitBits >::exact &, typename boost::uint_t< UnitBits >::exact &)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:104
bit_in_unit_byte_reverser transforms the sequence of bits in each byte of the input unit into reverse...
Definition: block/include/nil/crypto3/detail/reverser.hpp:87
static void reverse(UnitType &in, UnitType &out)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:92
boost::uint_t< UnitBits >::exact UnitType
Definition: hash/include/nil/crypto3/detail/reverser.hpp:90
bit_in_unit_byte_reverser< UnitBits, k+CHAR_BIT > next_type
Definition: hash/include/nil/crypto3/detail/reverser.hpp:89
static void reverse(ValueType &, ValueType &)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:190
bit_in_unit_reverser transforms the sequence of bits in each unit of the input value into reversed se...
Definition: block/include/nil/crypto3/detail/reverser.hpp:171
static void reverse(ValueType &in, ValueType &out)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:177
bit_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: hash/include/nil/crypto3/detail/reverser.hpp:173
boost::uint_t< UnitBits >::exact UnitType
Definition: hash/include/nil/crypto3/detail/reverser.hpp:174
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
static ValueType reverse(ValueType const &val)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:308
static void reverse(ValueType &val)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:301
static ValueType reverse(ValueType const &val)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:283
static void reverse(ValueType &)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:279
static void reverse(ValueType &, ValueType &)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:351
byte_in_unit_reverser transforms the sequence of bytes in each unit of the input value into reversed ...
Definition: block/include/nil/crypto3/detail/reverser.hpp:332
static void reverse(ValueType &in, ValueType &out)
Definition: hash/include/nil/crypto3/detail/reverser.hpp:338
boost::uint_t< UnitBits >::exact UnitType
Definition: hash/include/nil/crypto3/detail/reverser.hpp:335
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
byte_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: hash/include/nil/crypto3/detail/reverser.hpp:334
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:212
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:373
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:228
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:389
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:245
constexpr static const bool value
Definition: block/include/nil/crypto3/detail/reverser.hpp:406