]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/src/c++11/random.cc
random.h (random_device): Move implementation to...
[thirdparty/gcc.git] / libstdc++-v3 / src / c++11 / random.cc
1 // random -*- C++ -*-
2
3 // Copyright (C) 2012 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 #include <random>
26
27 #if defined __i386__ || defined __x86_64__
28 # include <cpuid.h>
29 #endif
30
31
32 namespace std _GLIBCXX_VISIBILITY(default)
33 {
34
35 namespace
36 {
37 static unsigned long
38 _M_strtoul(const std::string& __str)
39 {
40 unsigned long __ret = 5489UL;
41 if (__str != "mt19937")
42 {
43 const char* __nptr = __str.c_str();
44 char* __endptr;
45 __ret = std::strtoul(__nptr, &__endptr, 0);
46 if (*__nptr == '\0' || *__endptr != '\0')
47 std::__throw_runtime_error(__N("random_device::_M_strtoul"
48 "(const std::string&)"));
49 }
50 return __ret;
51 }
52
53 #if defined __i386__ || defined __x86_64__
54 unsigned int
55 __attribute__ ((target("rdrnd")))
56 __x86_rdrand(void)
57 {
58 unsigned int retries = 100;
59 unsigned int val;
60
61 while (__builtin_ia32_rdrand32_step(&val) == 0)
62 if (--retries == 0)
63 std::__throw_runtime_error(__N("random_device::__x86_rdrand(void)"));
64
65 return val;
66 }
67 #endif
68 }
69
70
71 void
72 random_device::_M_init(const std::string& token)
73 {
74 const char *fname = token.c_str();
75
76 if (token == "default")
77 {
78 #if defined __i386__ || defined __x86_64__
79 unsigned int eax, ebx, ecx, edx;
80 __cpuid(0, eax, ebx, ecx, edx);
81 // Check for "GenuineIntel"
82 if (ebx == 0x756e6547 && ecx == 0x6c65746e && edx == 0x49656e69)
83 {
84 __cpuid(1, eax, ebx, ecx, edx);
85 if (ecx & bit_RDRND)
86 {
87 _M_file = nullptr;
88 return;
89 }
90 }
91 #endif
92
93 fname = "/dev/urandom";
94 }
95 else if (token != "/dev/urandom" && token != "/dev/random")
96 fail:
97 std::__throw_runtime_error(__N("random_device::"
98 "random_device(const std::string&)"));
99
100 _M_file = std::fopen(fname, "rb");
101 if (! _M_file)
102 goto fail;
103 }
104
105 void
106 random_device::_M_init_pretr1(const std::string& token)
107
108 {
109 _M_mt.seed(_M_strtoul(token));
110 }
111
112 void
113 random_device::_M_fini()
114 {
115 if (_M_file)
116 std::fclose(_M_file);
117 }
118
119 random_device::result_type
120 random_device::_M_getval()
121 {
122 #if (defined __i386__ || defined __x86_64__)
123 if (! _M_file)
124 return __x86_rdrand();
125 #endif
126
127 result_type __ret;
128 std::fread(reinterpret_cast<void*>(&__ret), sizeof(result_type),
129 1, _M_file);
130 return __ret;
131 }
132
133 random_device::result_type
134 random_device::_M_getval_pretr1()
135 {
136 return _M_mt();
137 }
138
139 template class mersenne_twister_engine<
140 uint_fast32_t,
141 32, 624, 397, 31,
142 0x9908b0dfUL, 11,
143 0xffffffffUL, 7,
144 0x9d2c5680UL, 15,
145 0xefc60000UL, 18, 1812433253UL>;
146
147 }