vSMC
vSMC: Scalable Monte Carlo
rdrand.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/rdrand.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_RNG_RDRAND_HPP
33 #define VSMC_RNG_RDRAND_HPP
34 
36 #include <immintrin.h>
37 
38 #ifndef VSMC_RDRAND_NTRIAL_MAX
39 #define VSMC_RDRAND_NTRIAL_MAX 0
40 #endif
41 
42 #define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax) \
43  VSMC_RUNTIME_WARNING((ntrial < NTrialMax), \
44  "**RDRAND::generate** MAXIMUM NUMBER OF TRIALS EXCEEDED")
45 
46 namespace vsmc
47 {
48 
51 template <typename UIntType, std::size_t W>
52 inline bool rdrand(UIntType *, std::integral_constant<std::size_t, W>);
53 
56 template <typename UIntType>
57 inline bool rdrand(
58  UIntType *rand, std::integral_constant<std::size_t, sizeof(std::uint16_t)>)
59 {
60  unsigned short r;
61  int cf = _rdrand16_step(&r);
62  *rand = static_cast<UIntType>(r);
63 
64  return cf != 0;
65 }
66 
69 template <typename UIntType>
70 inline bool rdrand(
71  UIntType *rand, std::integral_constant<std::size_t, sizeof(std::uint32_t)>)
72 {
73  unsigned r;
74  int cf = _rdrand32_step(&r);
75  *rand = static_cast<UIntType>(r);
76 
77  return cf != 0;
78 }
79 
82 template <typename UIntType>
83 inline bool rdrand(
84  UIntType *rand, std::integral_constant<std::size_t, sizeof(std::uint64_t)>)
85 {
86 #if defined(VSMC_MSVC) || (defined(VSMC_INTEL) && VSMC_INTEL_VERSION < 1600)
87  unsigned __int64 r;
88 #else
89  unsigned long long r;
90 #endif
91  int cf = _rdrand64_step(&r);
92  *rand = static_cast<UIntType>(r);
93 
94  return cf != 0;
95 }
96 
99 template <typename ResultType, std::size_t NTrialMax = VSMC_RDRAND_NTRIAL_MAX>
101 {
102  static_assert(std::is_unsigned<ResultType>::value,
103  "**RDRANDEngine** USED WITH ResultType OTHER THAN UNSIGNED INTEGER "
104  "TYPES");
105 
106  static_assert(sizeof(ResultType) == sizeof(std::uint16_t) ||
107  sizeof(ResultType) == sizeof(std::uint32_t) ||
108  sizeof(ResultType) == sizeof(std::uint64_t),
109  "**RDRANDEngine** USED WITH ResultType OF SIZE OTHER THAN 16, 32 OR "
110  "64 BITS");
111 
112  public:
113  using result_type = ResultType;
114 
115  explicit RDRANDEngine(result_type = 0) {}
116 
117  template <typename SeedSeq>
118  explicit RDRANDEngine(SeedSeq &,
119  typename std::enable_if<internal::is_seed_seq<SeedSeq, result_type,
120  RDRANDEngine<ResultType, NTrialMax>>::value>::type * = nullptr)
121  {
122  }
123 
124  void seed(result_type) {}
125 
126  template <typename SeedSeq>
127  void seed(SeedSeq &, typename std::enable_if<internal::is_seed_seq<SeedSeq,
128  result_type>::value>::type * = nullptr)
129  {
130  }
131 
133  {
134  return generate(std::integral_constant<bool, NTrialMax != 0>());
135  }
136 
137  void discard(std::size_t) {}
138 
139  static constexpr result_type min()
140  {
141  return std::numeric_limits<result_type>::min();
142  }
143 
144  static constexpr result_type max()
145  {
146  return std::numeric_limits<result_type>::max();
147  }
148 
151  {
152  return false;
153  }
154 
157  {
158  return true;
159  }
160 
161  template <typename CharT, typename CharTraits>
162  friend std::basic_ostream<CharT, CharTraits> &operator<<(
163  std::basic_ostream<CharT, CharTraits> &os,
165  {
166  return os;
167  }
168 
169  template <typename CharT, typename CharTraits>
170  friend std::basic_istream<CharT, CharTraits> &operator>>(
171  std::basic_istream<CharT, CharTraits> &is,
173  {
174  return is;
175  }
176 
177  private:
178  result_type generate(std::true_type)
179  {
180  result_type r;
181  std::size_t ntrial = 0;
182  while (true) {
183  ++ntrial;
184  bool success = rdrand<result_type>(&r,
185  std::integral_constant<std::size_t, sizeof(result_type)>());
186  if (success || ntrial > NTrialMax)
187  break;
188  }
190 
191  return r;
192  }
193 
194  result_type generate(std::false_type)
195  {
196  result_type r;
197  while (true) {
198  bool success = rdrand<result_type>(&r,
199  std::integral_constant<std::size_t, sizeof(result_type)>());
200  if (success)
201  break;
202  }
203 
204  return r;
205  }
206 }; // class RDRANDEngine
207 
211 
215 
219 
220 } // namespace vsmc
221 
222 #endif // VSMC_RNG_RDRAND_HPP
RDRAND generator.
Definition: rdrand.hpp:100
friend bool operator==(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:149
Definition: monitor.hpp:49
static constexpr result_type max()
Definition: rdrand.hpp:144
ResultType result_type
Definition: rdrand.hpp:113
friend bool operator!=(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:155
result_type operator()()
Definition: rdrand.hpp:132
static constexpr result_type min()
Definition: rdrand.hpp:139
uint uint32_t
Definition: opencl.h:39
ulong uint64_t
Definition: opencl.h:40
void seed(SeedSeq &, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type >::value >::type *=nullptr)
Definition: rdrand.hpp:127
RDRANDEngine(SeedSeq &, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, RDRANDEngine< ResultType, NTrialMax >>::value >::type *=nullptr)
Definition: rdrand.hpp:118
friend std::basic_ostream< CharT, CharTraits > & operator<<(std::basic_ostream< CharT, CharTraits > &os, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:162
void discard(std::size_t)
Definition: rdrand.hpp:137
RDRANDEngine(result_type=0)
Definition: rdrand.hpp:115
bool rdrand(UIntType *, std::integral_constant< std::size_t, W >)
Invoke the RDRAND instruction and return the carry flag.
void seed(result_type)
Definition: rdrand.hpp:124
friend std::basic_istream< CharT, CharTraits > & operator>>(std::basic_istream< CharT, CharTraits > &is, RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:170
#define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax)
Definition: rdrand.hpp:42