pubkey/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 <climits>
31 #include <type_traits>
32 
33 #include <boost/integer.hpp>
34 #include <boost/static_assert.hpp>
35 #include <boost/endian/conversion.hpp>
36 
37 #include <nil/crypto3/detail/unbounded_shift.hpp>
38 #include <nil/crypto3/detail/stream_endian.hpp>
39 #include <nil/crypto3/detail/predef.hpp>
40 
41 namespace nil {
42  namespace crypto3 {
43  namespace detail {
44 
49  typedef typename boost::uint_t<CHAR_BIT>::exact byte_type;
50 
63  inline void reverse_byte(byte_type &b) {
64 
65 
66 
67 #if (BOOST_ARCH_CURRENT_WORD_BITS == 32)
68  b = unbounded_shr<16>(((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU);
69 #elif (BOOST_ARCH_CURRENT_WORD_BITS == 64)
70  b = (b * 0x0202020202ULL & 0x010884422010ULL) % 1023;
71 #else
72 #error "BOOST_ARCH_CURRENT_WORD_BITS not set"
73 #endif
74  }
75 
88  template<int UnitBits, int k = 0>
89  struct bit_in_unit_byte_reverser {
90 
91  BOOST_STATIC_ASSERT(!(UnitBits % CHAR_BIT));
92 
94  typedef typename boost::uint_t<UnitBits>::exact UnitType;
95 
96  inline static void reverse(UnitType &in, UnitType &out) {
97  int const shift = UnitBits - (CHAR_BIT + k);
98  byte_type byte = byte_type(low_bits<CHAR_BIT>(unbounded_shr(in, shift)));
99  reverse_byte(byte);
100  out |= unbounded_shl(low_bits<CHAR_BIT>(UnitType(byte)), shift);
101 
102  next_type::reverse(in, out);
103  }
104  };
105 
106  template<int UnitBits>
107  struct bit_in_unit_byte_reverser<UnitBits, UnitBits> {
108  inline static void reverse(typename boost::uint_t<UnitBits>::exact &,
109  typename boost::uint_t<UnitBits>::exact &) {
110  }
111  };
112 
131  template<typename UnitType,
132  int UnitBits = sizeof(UnitType) * CHAR_BIT,
133  typename std::enable_if<(UnitBits > CHAR_BIT), int>::type = 0>
134  inline void reverse_bits(UnitType &unit) {
135  boost::endian::endian_reverse_inplace(unit);
136  UnitType out = UnitType();
138  unit = out;
139  }
152  template<typename UnitType,
153  int UnitBits = sizeof(UnitType) * CHAR_BIT,
154  typename std::enable_if<(UnitBits == CHAR_BIT), int>::type = 0>
155  inline void reverse_bits(UnitType &unit) {
156  reverse_byte(unit);
157  }
158 
172  template<int InputBits, int UnitBits, int k = 0>
173  struct bit_in_unit_reverser {
174 
175  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
176 
178  typedef typename boost::uint_t<UnitBits>::exact UnitType;
179 
180  template<typename ValueType>
181  inline static void reverse(ValueType &in, ValueType &out) {
182  int const shift = InputBits - (UnitBits + k);
183  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
184  reverse_bits(unit);
185  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
186 
187  next_type::reverse(in, out);
188  }
189  };
190 
191  template<int InputBits, int UnitBits>
192  struct bit_in_unit_reverser<InputBits, UnitBits, InputBits> {
193  template<typename ValueType>
194  inline static void reverse(ValueType &, ValueType &) {
195  }
196  };
197 
212  template<typename Endianness, int UnitBits>
213  struct is_big_bit {
214  constexpr static const bool value =
215  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
216  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value;
217  };
218 
228  template<typename Endianness, int UnitBits>
229  struct is_little_bit {
230  constexpr static const bool value =
231  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value ||
232  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
233  };
234 
245  template<typename Endianness1, typename Endianness2, int UnitBits>
246  struct is_same_bit {
247  constexpr static const bool value =
250  };
251 
264  template<typename InputEndianness,
265  typename OutputEndianness,
266  int UnitBits,
268  struct bit_reverser;
269 
280  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
281  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, true> {
282  template<typename ValueType>
283  inline static void reverse(ValueType &) {
284  }
285 
286  template<typename ValueType>
287  inline static ValueType reverse(ValueType const &val) {
288  return val;
289  }
290  };
291 
302  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
303  struct bit_reverser<InputEndianness, OutputEndianness, UnitBits, false> {
304  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
305  inline static void reverse(ValueType &val) {
306  ValueType out = ValueType();
308  val = out;
309  }
310 
311  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
312  inline static ValueType reverse(ValueType const &val) {
313  ValueType tmp = val;
314  ValueType out = ValueType();
316  return out;
317  }
318  };
319 
333  template<int InputBits, int UnitBits, int k = 0>
334  struct byte_in_unit_reverser {
335 
336  BOOST_STATIC_ASSERT(!(InputBits % UnitBits) && !(UnitBits % CHAR_BIT));
337 
339  typedef typename boost::uint_t<UnitBits>::exact UnitType;
340 
341  template<typename ValueType>
342  inline static void reverse(ValueType &in, ValueType &out) {
343  int const shift = InputBits - (UnitBits + k);
344  UnitType unit = UnitType(low_bits<UnitBits>(unbounded_shr(in, shift)));
345  boost::endian::endian_reverse_inplace(unit);
346  out |= unbounded_shl(low_bits<UnitBits>(ValueType(unit)), shift);
347 
348  next_type::reverse(in, out);
349  }
350  };
351 
352  template<int InputBits, int UnitBits>
353  struct byte_in_unit_reverser<InputBits, UnitBits, InputBits> {
354  template<typename ValueType>
355  inline static void reverse(ValueType &, ValueType &) {
356  }
357  };
358 
373  template<typename Endianness, int UnitBits>
374  struct is_big_unit {
375  constexpr static const bool value =
376  std::is_same<Endianness, stream_endian::big_unit_big_bit<UnitBits>>::value ||
377  std::is_same<Endianness, stream_endian::big_unit_little_bit<UnitBits>>::value;
378  };
379 
389  template<typename Endianness, int UnitBits>
390  struct is_little_unit {
391  constexpr static const bool value =
392  std::is_same<Endianness, stream_endian::little_unit_big_bit<UnitBits>>::value ||
393  std::is_same<Endianness, stream_endian::little_unit_little_bit<UnitBits>>::value;
394  };
395 
406  template<typename Endianness1, typename Endianness2, int UnitBits>
407  struct is_same_unit {
408  constexpr static const bool value =
411  };
412 
424  template<typename InputEndianness, typename OutputEndianness, int UnitBits, typename Enable = void>
425  struct unit_reverser;
426 
437  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
438  struct unit_reverser<
439  InputEndianness,
440  OutputEndianness,
441  UnitBits,
442  typename std::enable_if<is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value>::type> {
443  template<typename ValueType>
444  inline static void reverse(ValueType &) {
445  }
446 
447  template<typename ValueType>
448  inline static ValueType reverse(ValueType const &val) {
449  return val;
450  }
451  };
452 
463  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
464  struct unit_reverser<
465  InputEndianness,
466  OutputEndianness,
467  UnitBits,
468  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
469  UnitBits == CHAR_BIT>::type> {
470  template<typename ValueType>
471  inline static void reverse(ValueType &val) {
472  boost::endian::endian_reverse_inplace(val);
473  }
474 
475  template<typename ValueType>
476  inline static ValueType reverse(ValueType const &val) {
477  return boost::endian::endian_reverse(val);
478  }
479  };
480 
492  template<typename InputEndianness, typename OutputEndianness, int UnitBits>
493  struct unit_reverser<
494  InputEndianness,
495  OutputEndianness,
496  UnitBits,
497  typename std::enable_if<!is_same_unit<InputEndianness, OutputEndianness, UnitBits>::value &&
498  (UnitBits > CHAR_BIT)>::type> {
499  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
500  inline static void reverse(ValueType &val) {
501  boost::endian::endian_reverse_inplace(val);
502  ValueType out = ValueType();
504  val = out;
505  }
506 
507  template<typename ValueType, int ValueBits = sizeof(ValueType) * CHAR_BIT>
508  inline static ValueType reverse(ValueType const &val) {
509  ValueType tmp = boost::endian::endian_reverse(val);
510  ValueType out = ValueType();
512  return out;
513  }
514  };
515  } // namespace detail
516  } // namespace crypto3
517 } // namespace nil
518 
519 #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: pubkey/include/nil/crypto3/detail/reverser.hpp:108
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: pubkey/include/nil/crypto3/detail/reverser.hpp:96
boost::uint_t< UnitBits >::exact UnitType
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:94
bit_in_unit_byte_reverser< UnitBits, k+CHAR_BIT > next_type
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:93
static void reverse(ValueType &, ValueType &)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:194
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: pubkey/include/nil/crypto3/detail/reverser.hpp:181
bit_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:177
boost::uint_t< UnitBits >::exact UnitType
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:178
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
static ValueType reverse(ValueType const &val)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:312
static void reverse(ValueType &val)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:305
static ValueType reverse(ValueType const &val)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:287
static void reverse(ValueType &)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:283
static void reverse(ValueType &, ValueType &)
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:355
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: pubkey/include/nil/crypto3/detail/reverser.hpp:342
boost::uint_t< UnitBits >::exact UnitType
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:339
BOOST_STATIC_ASSERT(!(InputBits % UnitBits) &&!(UnitBits % CHAR_BIT))
byte_in_unit_reverser< InputBits, UnitBits, k+UnitBits > next_type
Definition: pubkey/include/nil/crypto3/detail/reverser.hpp:338
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