32 #ifndef MCKL_RANDOM_INTERNAL_PHILOX_COMMON_HPP 33 #define MCKL_RANDOM_INTERNAL_PHILOX_COMMON_HPP 43 template <typename T, int = std::numeric_limits<T>::digits>
50 static T
eval(T a, T b, T &h)
57 buf.p =
static_cast<std::uint64_t>(a) * static_cast<std::uint64_t>(b);
59 #if MCKL_HAS_LITTLE_ENDIAN 60 h = std::get<1>(buf.r);
62 return std::get<0>(buf.r);
63 #elif MCKL_HAS_BIG_ENDIAN 64 h = std::get<0>(buf.r);
66 return std::get<1>(buf.r);
68 h =
static_cast<T
>(buf.p >> 32);
70 return static_cast<T
>(buf.p);
79 static T
eval(T a, T b, T &h)
81 #if MCKL_USE_BMI2 && MCKL_HAS_X86_64 82 return eval_bmi2(a, b, h);
84 return eval_int128(a, b, h);
86 return eval_generic(a, b, h);
91 static T eval_generic(T a, T b, T &h)
93 const T mask = (const_one<T>() << 32) - 1;
95 const T al = a & mask;
97 const T bl = b & mask;
98 const T ahbl = ah * bl;
99 const T albh = al * bh;
100 const T ahbl_albh = ((ahbl & mask) + (albh & mask));
102 h = ah * bh + (ahbl >> 32) + (albh >> 32);
103 h += ahbl_albh >> 32;
104 h += (l >> 32) < (ahbl_albh & mask) ? 1 : 0;
109 #if MCKL_USE_BMI2 && MCKL_HAS_X86_64 110 static T eval_bmi2(T a, T b, T &h)
114 static_cast<T
>(_mulx_u64(static_cast<unsigned MCKL_INT64>(a),
115 static_cast<unsigned MCKL_INT64>(b), &t));
116 h =
static_cast<T
>(t);
123 static T eval_int128(T a, T b, T &h)
127 unsigned MCKL_INT128 p;
131 buf.p =
static_cast<unsigned MCKL_INT128
>(a) *
132 static_cast<unsigned MCKL_INT128>(b);
135 #if MCKL_HAS_LITTLE_ENDIAN 136 h = std::get<1>(buf.r);
137 return std::get<0>(buf.r);
138 #elif MCKL_HAS_BIG_ENDIAN 139 h = std::get<0>(buf.r);
140 return std::get<1>(buf.r);
142 h =
static_cast<T
>(buf.p >> 64);
143 return static_cast<T
>(buf.p);
149 #if MCKL_USE_BMI2 && MCKL_HAS_X86_64 158 return _mulx_u64(a, b, &h);
162 #endif // MCKL_USE_BMI2 && MCKL_HAS_X86_64 164 template <
typename T, std::
size_t K, std::
size_t N,
typename Constants>
168 static void eval(std::array<T, K> &s,
const std::array<T, K / 2> &k)
171 pbox<0>(s, t, std::integral_constant<bool, 0 < K>());
172 sbox<0>(s, t, k, std::integral_constant<bool, 0 < K / 2>());
176 template <std::
size_t>
177 static void sbox(std::array<T, K> &,
const std::array<T, K> &,
178 const std::array<T, K / 2> &, std::false_type)
182 template <std::
size_t I>
183 static void sbox(std::array<T, K> &s,
const std::array<T, K> &t,
184 const std::array<T, K / 2> &k, std::true_type)
186 constexpr std::size_t I0 = I * 2;
187 constexpr std::size_t I1 = I * 2 + 1;
188 constexpr T w = Constants::weyl::value[I] *
static_cast<T
>(N - 1);
189 constexpr T m = Constants::multiplier::value[I];
193 std::get<I0>(s) = (std::get<I>(k) + w) ^ (std::get<I1>(t) ^ h);
194 sbox<I + 1>(s, t, k, std::integral_constant<bool, I + 1 < K / 2>());
197 template <std::
size_t>
199 const std::array<T, K> &, std::array<T, K> &, std::false_type)
203 template <std::
size_t I>
205 const std::array<T, K> &s, std::array<T, K> &t, std::true_type)
207 constexpr std::size_t P =
209 constexpr std::size_t J = K - P - 1;
211 std::get<I>(t) = std::get<J>(s);
212 pbox<I + 1>(s, t, std::integral_constant<bool, I + 1 < K>());
216 template <
typename T, std::
size_t N,
typename Constants>
220 static void eval(std::array<T, 2> &s,
const std::array<T, 1> &k)
222 constexpr T w0 = Constants::weyl::value[0] *
static_cast<T
>(N - 1);
223 constexpr T m0 = Constants::multiplier::value[0];
225 T s1 = std::get<1>(s);
228 std::get<0>(s) = (std::get<0>(k) + w0) ^ (s1 ^ h0);
232 template <
typename T, std::
size_t N,
typename Constants>
236 static void eval(std::array<T, 4> &s,
const std::array<T, 2> &k)
238 constexpr T w0 = Constants::weyl::value[0] *
static_cast<T
>(N - 1);
239 constexpr T w1 = Constants::weyl::value[1] *
static_cast<T
>(N - 1);
240 constexpr T m2 = Constants::multiplier::value[0];
241 constexpr T m0 = Constants::multiplier::value[1];
243 T s1 = std::get<1>(s);
244 T s3 = std::get<3>(s);
249 std::get<0>(s) = (std::get<0>(k) + w0) ^ (s1 ^ h2);
250 std::get<2>(s) = (std::get<1>(k) + w1) ^ (s3 ^ h0);
258 #endif // MCKL_RANDOM_INTERNAL_PHILOX_COMMON_HPP static void eval(std::array< T, 4 > &s, const std::array< T, 2 > &k)
#define MCKL_PUSH_GCC_WARNING(warning)
static void eval(std::array< T, K > &s, const std::array< T, K/2 > &k)
static T eval(T a, T b, T &h)
static void eval(std::array< T, 2 > &s, const std::array< T, 1 > &k)
Default Threefry constants.
static T eval(T a, T b, T &h)
static unsigned long long eval(unsigned long long a, unsigned long long b, unsigned long long &h)
#define MCKL_POP_GCC_WARNING