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-2015, 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_STATIC_ASSERT_RNG_RDRAND_ENGINE_RESULT_TYPE(ResultType) \
43  VSMC_STATIC_ASSERT(((sizeof(ResultType) == sizeof(std::uint16_t) && \
44  std::is_unsigned<ResultType>::value) || \
45  (sizeof(ResultType) == sizeof(std::uint32_t) && \
46  std::is_unsigned<ResultType>::value) || \
47  (sizeof(ResultType) == sizeof(std::uint64_t) && \
48  std::is_unsigned<ResultType>::value)), \
49  "**RDRANDEngine** USED WITH ResultType OTHER THAN UNSIGNED 16/32/64 " \
50  "BITS INTEGER")
51 
52 #define VSMC_STATIC_ASSERT_RNG_RDRAND_ENGINE \
53  VSMC_STATIC_ASSERT_RNG_RDRAND_ENGINE_RESULT_TYPE(ResultType);
54 
55 #define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax) \
56  VSMC_RUNTIME_WARNING((ntrial < NTrialMax), \
57  "**RDRAND::generate** MAXIMUM NUMBER OF TRIALS EXCEEDED")
58 
59 namespace vsmc
60 {
61 
64 template <typename UIntType, std::size_t W>
65 inline bool rdrand(UIntType *, std::integral_constant<std::size_t, W>);
66 
69 template <typename UIntType>
70 inline bool rdrand(
71  UIntType *rand, std::integral_constant<std::size_t, sizeof(std::uint16_t)>)
72 {
73  unsigned short r;
74  int cf = _rdrand16_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::uint32_t)>)
85 {
86  unsigned r;
87  int cf = _rdrand32_step(&r);
88  *rand = static_cast<UIntType>(r);
89 
90  return cf != 0;
91 }
92 
95 template <typename UIntType>
96 inline bool rdrand(
97  UIntType *rand, std::integral_constant<std::size_t, sizeof(std::uint64_t)>)
98 {
99 #if defined(VSMC_MSVC) || (defined(VSMC_INTEL) && VSMC_INTEL_VERSION < 1600)
100  unsigned __int64 r;
101 #else
102  unsigned long long r;
103 #endif
104  int cf = _rdrand64_step(&r);
105  *rand = static_cast<UIntType>(r);
106 
107  return cf != 0;
108 }
109 
112 template <typename ResultType, std::size_t NTrialMax = VSMC_RDRAND_NTRIAL_MAX>
114 {
115 
116  public:
117  using result_type = ResultType;
118 
119  explicit RDRANDEngine(result_type = 0)
120  {
122  }
123 
124  template <typename SeedSeq>
125  explicit RDRANDEngine(SeedSeq &,
126  typename std::enable_if<internal::is_seed_seq<SeedSeq, result_type,
127  RDRANDEngine<ResultType, NTrialMax>>::value>::type * = nullptr)
128  {
130  }
131 
132  void seed(result_type) {}
133 
134  template <typename SeedSeq>
135  void seed(SeedSeq &, typename std::enable_if<internal::is_seed_seq<SeedSeq,
136  result_type>::value>::type * = nullptr)
137  {
138  }
139 
141  {
142  return generate(std::integral_constant<bool, NTrialMax != 0>());
143  }
144 
145  void discard(std::size_t) {}
146 
147  static constexpr result_type min VSMC_MNE()
148  {
149  return std::numeric_limits<result_type>::min VSMC_MNE();
150  }
151 
152  static constexpr result_type max VSMC_MNE()
153  {
154  return std::numeric_limits<result_type>::max VSMC_MNE();
155  }
156 
159  {
160  return false;
161  }
162 
165  {
166  return true;
167  }
168 
169  template <typename CharT, typename CharTraits>
170  friend std::basic_ostream<CharT, CharTraits> &operator<<(
171  std::basic_ostream<CharT, CharTraits> &os,
173  {
174  return os;
175  }
176 
177  template <typename CharT, typename CharTraits>
178  friend std::basic_istream<CharT, CharTraits> &operator>>(
179  std::basic_istream<CharT, CharTraits> &is,
181  {
182  return is;
183  }
184 
185  private:
186  result_type generate(std::true_type)
187  {
188  result_type r;
189  std::size_t ntrial = 0;
190  while (true) {
191  ++ntrial;
192  bool success = rdrand<result_type>(&r,
193  std::integral_constant<std::size_t, sizeof(result_type)>());
194  if (success || ntrial > NTrialMax)
195  break;
196  }
198 
199  return r;
200  }
201 
202  result_type generate(std::false_type)
203  {
204  result_type r;
205  while (true) {
206  bool success = rdrand<result_type>(&r,
207  std::integral_constant<std::size_t, sizeof(result_type)>());
208  if (success)
209  break;
210  }
211 
212  return r;
213  }
214 }; // class RDRANDEngine
215 
219 
223 
227 
228 } // namespace vsmc
229 
230 #endif // VSMC_RNG_RDRAND_HPP
RDRAND generator.
Definition: rdrand.hpp:113
friend bool operator==(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:157
Definition: monitor.hpp:49
static constexpr result_type max()
Definition: rdrand.hpp:152
ResultType result_type
Definition: rdrand.hpp:117
friend bool operator!=(const RDRANDEngine< ResultType, NTrialMax > &, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:163
result_type operator()()
Definition: rdrand.hpp:140
static constexpr result_type min()
Definition: rdrand.hpp:147
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:135
RDRANDEngine(SeedSeq &, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, RDRANDEngine< ResultType, NTrialMax >>::value >::type *=nullptr)
Definition: rdrand.hpp:125
friend std::basic_ostream< CharT, CharTraits > & operator<<(std::basic_ostream< CharT, CharTraits > &os, const RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:170
void discard(std::size_t)
Definition: rdrand.hpp:145
#define VSMC_MNE
Definition: defines.hpp:38
RDRANDEngine(result_type=0)
Definition: rdrand.hpp:119
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:132
friend std::basic_istream< CharT, CharTraits > & operator>>(std::basic_istream< CharT, CharTraits > &is, RDRANDEngine< ResultType, NTrialMax > &)
Definition: rdrand.hpp:178
#define VSMC_STATIC_ASSERT_RNG_RDRAND_ENGINE
Definition: rdrand.hpp:52
#define VSMC_RUNTIME_WARNING_RNG_RDRAND_ENGINE_NTRIAL(ntrial, NTrialMax)
Definition: rdrand.hpp:55