CDT  v4.2.0
инструменты разработчика
powers.hpp
См. документацию.
1#pragma once
2
3#include "check.hpp"
4
5#include <type_traits>
6#include <utility>
7#include <array>
8
9namespace eosio {
10
11 namespace detail {
12
13 template<typename Generator, std::size_t... Is>
14 constexpr auto generate_array_helper( Generator&& g, std::index_sequence<Is...> )
15 -> std::array<decltype(g(std::size_t{}, sizeof...(Is))), sizeof...(Is)>
16 {
17 return {{g(Is, sizeof...(Is))...}};
18 }
19
20 template<std::size_t N, typename Generator>
21 constexpr auto generate_array( Generator&& g ) {
22 return generate_array_helper( std::forward<Generator>(g), std::make_index_sequence<N>{} );
23 }
24
25 template<typename T, T Base, uint8_t Exponent, uint64_t Value, bool Overflow = (Value * Base < Value)>
26 struct largest_power_helper {
27 private:
28 static_assert( std::is_integral_v<T> && std::is_unsigned_v<T> &&!std::is_same_v<T, bool> );
29 static_assert( Base > 1 );
30 constexpr static T next_value = Value * Base;
32 public:
33 constexpr static T value = next::value;
34 constexpr static uint8_t exponent = next::exponent;
35 };
36
37 template<typename T, T Base, uint8_t Exponent, uint64_t Value>
38 struct largest_power_helper<T, Base, Exponent, Value, true> {
39 private:
40 static_assert( std::is_integral_v<T> && std::is_unsigned_v<T> &&!std::is_same_v<T, bool> );
41 static_assert( Base > 1 );
42 static_assert( Exponent < 255 );
43 public:
44 constexpr static T value = Value;
45 constexpr static uint8_t exponent = Exponent;
46 };
47
48 template<typename T, T Base>
50 private:
52 public:
53 constexpr static T value = helper::value;
54 constexpr static uint8_t exponent = helper::exponent;
55 };
56
57 template<typename T>
58 constexpr T pow( T base, uint8_t exponent ) {
59 if( base <= 1 ) check( false, "base must be at least 2" );
60 T prior = 1;
61 T result = prior;
62 for( uint8_t i = 0; i < exponent; ++i, prior = result ) {
63 result = prior * base;
64 if( result <= prior ) check( false, "overflow" );
65 }
66 return result;
67 }
68
69 template<typename T, T Base>
71 return pow( Base, static_cast<uint8_t>(i) );
72 }
73
74 }
75
76 template<uint8_t Base, typename T = uint64_t>
77 inline constexpr auto powers_of_base = detail::generate_array<detail::largest_power<T, Base>::exponent + 1>( detail::pow_generator<T, Base> );
78
80 template<uint8_t Base, typename T = uint64_t>
81 constexpr T pow( uint8_t exponent ) {
82 const auto& lookup_table = powers_of_base<Base, T>;
83 if( exponent >= lookup_table.size() ) check( false, "overflow" );
84
85 return lookup_table[exponent];
86 }
87
88}