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