codec/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 
64 #if (BOOST_ARCH_CURRENT_WORD_BITS == 32)
65  b = unbounded_shr<16>(((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU);
66 #elif (BOOST_ARCH_CURRENT_WORD_BITS == 64)
67  b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
68 #else
69 #error "BOOST_ARCH_CURRENT_WORD_BITS not set"
70 #endif
71  }
72 
85  template<int UnitBits, int k = 0>
86  struct bit_in_unit_byte_reverser {
87 
88  BOOST_STATIC_ASSERT(!(UnitBits % CHAR_BIT));
89 
91  typedef typename boost::uint_t<UnitBits>::exact UnitType;
92 
93  inline static void reverse(UnitType &in, UnitType &out) {
94  int const shift = UnitBits - (CHAR_BIT + k);
95  byte_type byte = byte_type(low_bits<CHAR_BIT>(unbounded_shr(in, shift)));
96  reverse_byte(byte);
97  out |= unbounded_shl(low_bits<CHAR_BIT>(UnitType(byte)), shift);
98 
99  next_type::reverse(in, out);
100  }
101  };
102 
103  template<int UnitBits>
104  struct bit_in_unit_byte_reverser<UnitBits, UnitBits> {
105  inline static void reverse(typename boost::uint_t<UnitBits>::exact &,
106  typename boost::uint_t<UnitBits>::exact &) {
107  }
108  };
109 
128  template<typename UnitType,
129  int UnitBits = sizeof(UnitType) * CHAR_BIT,
130  typename std::enable_if<(UnitBits > CHAR_BIT), int>::type = 0>
131  inline void reverse_bits(UnitType &unit) {
132  boost::endian::endian_reverse_inplace(unit);
133  UnitType out = UnitType();
135  unit = out;
136  }
149  template<typename UnitType,
150  int UnitBits = sizeof(UnitType) * CHAR_BIT,
151  typename std::enable_if<(UnitBits == CHAR_BIT), int>::type = 0>
152  inline void reverse_bits(UnitType &unit) {
153  reverse_byte(unit);
154  }
155 
169  template<int InputBits, int UnitBits, int k = 0>
170  struct bit_in_unit_reverser {
171 
172  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
173 
175  typedef typename boost::uint_t<UnitBits>::exact UnitType;
176 
177  template<typename ValueType>
178  inline static void reverse(ValueType &in, ValueType &out) {
179  int const shift = InputBits - (UnitBits + k);
180  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
181  reverse_bits(unit);
182  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
183 
184  next_type::reverse(in, out);
185  }
186  };
187 
188  template<int InputBits, int UnitBits>
189  struct bit_in_unit_reverser<InputBits, UnitBits, InputBits> {
190  template<typename ValueType>
191  inline static void reverse(ValueType &, ValueType &) {
192  }
193  };
194 
209  template<typename Endianness, int UnitBits>
210  struct is_big_bit {
211  constexpr static const bool value =
212  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
213  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value;
214  };
215 
225  template<typename Endianness, int UnitBits>
226  struct is_little_bit {
227  constexpr static const bool value =
228  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value ||
229  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
230  };
231 
242  template<typename Endianness1, typename Endianness2, int UnitBits>
243  struct is_same_bit {
244  constexpr static const bool value =
247  };
248 
261  template<typename InputEndianness,
262  typename OutputEndianness,
263  int UnitBits,
265  struct bit_reverser;
266 
277  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
278  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, true> {
279  template<typename ValueType>
280  inline static void reverse(ValueType &) {
281  }
282 
283  template<typename ValueType>
284  inline static ValueType reverse(ValueType const &val) {
285  return val;
286  }
287  };
288 
299  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
300  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, false> {
301  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
302  inline static void reverse(ValueType &val) {
303  ValueType out = ValueType();
305  val = out;
306  }
307 
308  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
309  inline static ValueType reverse(ValueType const &val) {
310  ValueType tmp = val;
311  ValueType out = ValueType();
313  return out;
314  }
315  };
316 
330  template<int InputBits, int UnitBits, int k = 0>
331  struct byte_in_unit_reverser {
332 
333  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
334 
336  typedef typename boost::uint_t<UnitBits>::exact UnitType;
337 
338  template<typename ValueType>
339  inline static void reverse(ValueType &in, ValueType &out) {
340  int const shift = InputBits - (UnitBits + k);
341  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
342  boost::endian::endian_reverse_inplace(unit);
343  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
344 
345  next_type::reverse(in, out);
346  }
347  };
348 
349  template<int InputBits, int UnitBits>
350  struct byte_in_unit_reverser<InputBits, UnitBits, InputBits> {
351  template<typename ValueType>
352  inline static void reverse(ValueType &, ValueType &) {
353  }
354  };
355 
370  template<typename Endianness, int UnitBits>
371  struct is_big_unit {
372  constexpr static const bool value =
373  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
374  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value;
375  };
376 
386  template<typename Endianness, int UnitBits>
387  struct is_little_unit {
388  constexpr static const bool value =
389  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value ||
390  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
391  };
392 
403  template<typename Endianness1, typename Endianness2, int UnitBits>
404  struct is_same_unit {
405  constexpr static const bool value =
408  };
409 
421  template<typename InputEndianness, typename OutputEndianness, int UnitBits, typename Enable = void>
422  struct unit_reverser;
423 
434  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
435  struct unit_reverser<
436  InputEndianness,
437  OutputEndianness,
438  UnitBits,
439  typename std::enable_if<is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value>::type> {
440  template<typename ValueType>
441  inline static void reverse(ValueType &) {
442  }
443 
444  template<typename ValueType>
445  inline static ValueType reverse(ValueType const &val) {
446  return val;
447  }
448  };
449 
460  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
461  struct unit_reverser<
462  InputEndianness,
463  OutputEndianness,
464  UnitBits,
465  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
466  UnitBits == CHAR_BIT>::type> {
467  template<typename ValueType>
468  inline static void reverse(ValueType &val) {
469  boost::endian::endian_reverse_inplace(val);
470  }
471 
472  template<typename ValueType>
473  inline static ValueType reverse(ValueType const &val) {
474  return boost::endian::endian_reverse(val);
475  }
476  };
477 
489  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
490  struct unit_reverser<
491  InputEndianness,
492  OutputEndianness,
493  UnitBits,
494  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
495  (UnitBits > CHAR_BIT)>::type> {
496  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
497  inline static void reverse(ValueType &val) {
498  boost::endian::endian_reverse_inplace(val);
499  ValueType out = ValueType();
501  val = out;
502  }
503 
504  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
505  inline static ValueType reverse(ValueType const &val) {
506  ValueType tmp = boost::endian::endian_reverse(val);
507  ValueType out = ValueType();
509  return out;
510  }
511  };
512  } // namespace detail
513  } // namespace crypto3
514 } // namespace nil
515 
516 #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: codec/include/nil/crypto3/detail/reverser.hpp:105
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: codec/include/nil/crypto3/detail/reverser.hpp:93
boost::uint_t< UnitBits >::exact UnitType
Definition: codec/include/nil/crypto3/detail/reverser.hpp:91
bit_in_unit_byte_reverser< UnitBits, k+CHAR_BIT > next_type
Definition: codec/include/nil/crypto3/detail/reverser.hpp:90
static void reverse(ValueType &, ValueType &)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:191
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: codec/include/nil/crypto3/detail/reverser.hpp:178
bit_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: codec/include/nil/crypto3/detail/reverser.hpp:174
boost::uint_t< UnitBits >::exact UnitType
Definition: codec/include/nil/crypto3/detail/reverser.hpp:175
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
static ValueType reverse(ValueType const &val)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:309
static void reverse(ValueType &val)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:302
static ValueType reverse(ValueType const &val)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:284
static void reverse(ValueType &)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:280
static void reverse(ValueType &, ValueType &)
Definition: codec/include/nil/crypto3/detail/reverser.hpp:352
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: codec/include/nil/crypto3/detail/reverser.hpp:339
boost::uint_t< UnitBits >::exact UnitType
Definition: codec/include/nil/crypto3/detail/reverser.hpp:336
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
byte_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: codec/include/nil/crypto3/detail/reverser.hpp:335
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