32 #ifndef VSMC_RNG_AES_NI_HPP
33 #define VSMC_RNG_AES_NI_HPP
37 #include <wmmintrin.h>
39 #define VSMC_STATIC_ASSERT_RNG_AES_NI_BLOCKS(Blocks) \
40 VSMC_STATIC_ASSERT((Blocks > 0), USE_AESNIEngine_WITH_ZERO_BLOCKS)
42 #define VSMC_STATIC_ASSERT_RNG_AES_NI_RESULT_TYPE(ResultType) \
43 VSMC_STATIC_ASSERT((cxx11::is_unsigned<ResultType>::value), \
44 USE_AESNIEngine_WITH_RESULT_TYPE_NOT_AN_UNSIGNED_INTEGER)
46 #define VSMC_STATIC_ASSERT_RNG_AES_NI \
47 VSMC_STATIC_ASSERT_RNG_AES_NI_BLOCKS(Blocks); \
48 VSMC_STATIC_ASSERT_RNG_AES_NI_RESULT_TYPE(ResultType);
54 template <
typename KeySeq,
bool KeySeqInit, std::
size_t Rounds>
57 template <
typename KeySeq, std::
size_t Rounds>
65 key_seq_type
get (
const key_type &)
const {
return key_seq_;}
67 void set (
const key_type &k)
70 seq.generate(k, key_seq_);
73 template <
typename CharT,
typename Traits>
74 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
75 std::basic_ostream<CharT, Traits> &os,
81 for (std::size_t i = 0; i != Rounds + 1; ++i) {
89 template <
typename CharT,
typename Traits>
90 friend inline std::basic_istream<CharT, Traits> &operator>> (
91 std::basic_istream<CharT, Traits> &is,
98 for (std::size_t i = 0; i != Rounds + 1; ++i)
102 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
114 key_seq_type key_seq_;
117 template <
typename KeySeq, std::
size_t Rounds>
125 key_seq_type
get (
const key_type &k)
const
134 void set (
const key_type &) {}
136 template <
typename CharT,
typename Traits>
137 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
138 std::basic_ostream<CharT, Traits> &os,
141 template <
typename CharT,
typename Traits>
142 friend inline std::basic_istream<CharT, Traits> &operator>> (
143 std::basic_istream<CharT, Traits> &is,
211 template <
typename ResultType,
typename KeySeq,
bool KeySeqInit,
212 std::size_t Rounds, std::size_t Blocks>
216 sizeof(
__m128i) /
sizeof(ResultType) * Blocks;
239 template <
typename SeedSeq>
257 counter::reset(ctr_block_);
264 template <
typename SeedSeq>
268 counter::reset(ctr_block_);
269 seq.generate(key_.begin(), key_.end());
276 counter::reset(ctr_block_);
282 template <std::
size_t B>
287 key_type
key ()
const {
return key_;}
289 key_seq_type
key_seq ()
const {
return key_seq_.get(key_);}
291 void ctr (
const ctr_type &c)
293 counter::set(ctr_block_, c);
297 void key (
const key_type &k)
307 counter::increment(ctr_block_);
308 generate_buffer(ctr_block_, buffer_);
312 return reinterpret_cast<const result_type *
>(buffer_.
data())[index_++];
322 generate_buffer(cb, buf);
332 generate_buffer(cb, buf);
343 generate_buffer(cb, buf);
348 void operator() (
const ctr_block_type &cb, buffer_type &buf)
const
349 {generate_buffer(cb, buf);}
353 std::size_t n =
static_cast<std::size_t
>(nskip);
354 if (index_ + n <= K_) {
367 counter::increment(ctr_block_, static_cast<result_type>(n / K_));
375 ~(
static_cast<result_type
>(0)));
382 ResultType, KeySeq, KeySeqInit, Rounds, Blocks> &eng1,
384 ResultType, KeySeq, KeySeqInit, Rounds, Blocks> &eng2)
386 return eng1.index_ == eng2.index_ &&
387 eng1.key_ == eng2.key_ &&
388 eng1.ctr_block_ == eng2.ctr_block_;
393 ResultType, KeySeq, KeySeqInit, Rounds, Blocks> &eng1,
395 ResultType, KeySeq, KeySeqInit, Rounds, Blocks> &eng2)
396 {
return !(eng1 == eng2);}
398 template <
typename CharT,
typename Traits>
399 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
400 std::basic_ostream<CharT, Traits> &os,
402 ResultType, KeySeq, KeySeqInit, Rounds, Blocks> &eng)
407 for (std::size_t i = 0; i != Blocks; ++i) {
411 os << eng.ctr_block_ <<
' ';
412 os << eng.key_ <<
' ';
418 template <
typename CharT,
typename Traits>
419 friend inline std::basic_istream<CharT, Traits> &
operator>> (
420 std::basic_istream<CharT, Traits> &is,
427 for (std::size_t i = 0; i != Blocks; ++i)
429 is >> std::ws >> eng_tmp.ctr_block_;
430 is >> std::ws >> eng_tmp.key_;
431 is >> std::ws >> eng_tmp.index_;
434 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
453 ctr_block_type ctr_block_;
457 void generate_buffer (
const ctr_block_type &cb,
458 buffer_type &buf)
const
460 const key_seq_type ks(key_seq_.get(key_));
467 template <std::
size_t>
468 void enc_first (
const key_seq_type &, buffer_type &,
471 template <std::
size_t B>
472 void enc_first (
const key_seq_type &ks, buffer_type &buf,
475 buf[Position<B>()] = _mm_xor_si128(buf[Position<B>()], ks.front());
476 enc_first<B + 1>(ks, buf,
477 cxx11::integral_constant<bool, B + 1 < Blocks>());
480 template <std::
size_t>
481 void enc_round (
const key_seq_type &, buffer_type &,
484 template <std::
size_t N>
485 void enc_round (
const key_seq_type &ks, buffer_type &buf,
489 enc_round<N + 1>(ks, buf,
490 cxx11::integral_constant<bool, N + 1 < Rounds>());
493 template <std::
size_t, std::
size_t>
494 void enc_round_block (
const key_seq_type &, buffer_type &,
497 template <std::
size_t B, std::
size_t N>
498 void enc_round_block (
const key_seq_type &ks, buffer_type &buf,
501 buf[Position<B>()] = _mm_aesenc_si128(
502 buf[Position<B>()], ks[Position<N>()]);
503 enc_round_block<B + 1, N>(ks, buf,
504 cxx11::integral_constant<bool, B + 1 < Blocks>());
507 template <std::
size_t>
511 template <std::
size_t B>
512 void enc_last (
const key_seq_type &ks, buffer_type &buf,
515 buf[Position<B>()] = _mm_aesenclast_si128(
516 buf[Position<B>()], ks.back());
517 enc_last<B + 1>(ks, buf,
518 cxx11::integral_constant<bool, B + 1 < Blocks>());
524 template <std::
size_t>
528 template <std::
size_t B>
532 m128i_pack<0>(cb[Position<B>()], buf[Position<B>()]);
533 pack_ctr<B + 1>(cb, buf,
534 cxx11::integral_constant<bool, B + 1 < Blocks>());
540 #endif // VSMC_RNG_AES_NI_HPP
void ctr(const ctr_type &c)
friend bool operator==(const AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng1, const AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng2)
#define VSMC_CONSTEXPR
constexpr
KeySeq::key_type key_type
Array< __m128i, Blocks > buffer_type
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng)
void set(const key_type &)
static constexpr const result_type _Min
key_seq_type key_seq() const
integral_constant< bool, false > false_type
AESNIEngine(SeedSeq &seq, typename cxx11::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type, AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > >::value >::type *=nullptr)
Function template argument used for position.
AESNIEngine(result_type s=0)
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
Array< __m128i, Rounds+1 > key_seq_type
static constexpr result_type min()
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng)
KeySeq::key_type key_type
std::basic_istream< CharT, Traits > & m128i_input(std::basic_istream< CharT, Traits > &is, __m128i &a)
Input an __m128i object from an input stream as 16 bytes unsigned integers written by m128i_output...
RNG engine using AES-NI instructions.
remove_reference< T >::type && move(T &&t) noexcept
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const Sampler< T > &sampler)
static constexpr result_type max()
void seed(SeedSeq &seq, typename cxx11::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type >::value >::type *=nullptr)
KeySeq::key_type key_type
Array< __m128i, Rounds+1 > key_seq_type
#define VSMC_NULLPTR
nullptr
void key(const key_type &k)
integral_constant< bool, true > true_type
Array< ctr_type, Blocks > ctr_block_type
void set(const key_type &k)
#define VSMC_STATIC_ASSERT_RNG_AES_NI
Array< ResultType, sizeof(__m128i)/sizeof(ResultType)> ctr_type
std::basic_ostream< CharT, Traits > & m128i_output(std::basic_ostream< CharT, Traits > &os, const __m128i &a)
Write an __m128i object into an output stream as 16 bytes unsigned integers.
void discard(result_type nskip)
Array< __m128i, Rounds+1 > key_seq_type
friend bool operator!=(const AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng1, const AESNIEngine< ResultType, KeySeq, KeySeqInit, Rounds, Blocks > &eng2)
void seed(const key_type &k)
static constexpr const result_type _Max
AESNIEngine(const key_type &k)
ctr_block_type ctr_block() const