/src/mcl/include/cybozu/random_generator.hpp
Line | Count | Source (jump to first uncovered line) |
1 | | #pragma once |
2 | | /** |
3 | | @file |
4 | | @brief pseudrandom generator |
5 | | @author MITSUNARI Shigeo(@herumi) |
6 | | @license modified new BSD license |
7 | | http://opensource.org/licenses/BSD-3-Clause |
8 | | */ |
9 | | |
10 | | #ifndef CYBOZU_DONT_USE_EXCEPTION |
11 | | #include <cybozu/exception.hpp> |
12 | | #endif |
13 | | #ifdef _WIN32 |
14 | | #ifndef WIN32_LEAN_AND_MEAN |
15 | | #define WIN32_LEAN_AND_MEAN |
16 | | #endif |
17 | | #include <windows.h> |
18 | | #include <wincrypt.h> |
19 | | #ifdef _MSC_VER |
20 | | #pragma comment (lib, "advapi32.lib") |
21 | | #endif |
22 | | #else |
23 | | #include <stdio.h> |
24 | | #include <sys/types.h> |
25 | | #include <fcntl.h> |
26 | | #endif |
27 | | |
28 | | namespace cybozu { |
29 | | |
30 | | class RandomGenerator { |
31 | | RandomGenerator(const RandomGenerator&); |
32 | | void operator=(const RandomGenerator&); |
33 | | public: |
34 | | #ifdef _WIN32 |
35 | | RandomGenerator() |
36 | | : prov_(0) |
37 | | { |
38 | | DWORD flagTbl[] = { CRYPT_VERIFYCONTEXT | CRYPT_SILENT, 0, CRYPT_MACHINE_KEYSET }; |
39 | | for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(flagTbl); i++) { |
40 | | if (CryptAcquireContext(&prov_, NULL, NULL, PROV_RSA_FULL, flagTbl[i]) != 0) return; |
41 | | } |
42 | | #ifdef CYBOZU_DONT_USE_EXCEPTION |
43 | | prov_ = 0; |
44 | | #else |
45 | | throw cybozu::Exception("randomgenerator"); |
46 | | #endif |
47 | | } |
48 | | bool read_inner(void *buf, size_t byteSize) |
49 | | { |
50 | | if (prov_ == 0) return false; |
51 | | return CryptGenRandom(prov_, static_cast<DWORD>(byteSize), static_cast<BYTE*>(buf)) != 0; |
52 | | } |
53 | | ~RandomGenerator() |
54 | | { |
55 | | if (prov_) { |
56 | | CryptReleaseContext(prov_, 0); |
57 | | } |
58 | | } |
59 | | /* |
60 | | fill buf[0..bufNum-1] with random data |
61 | | @note bufNum is not byte size |
62 | | */ |
63 | | template<class T> |
64 | | void read(bool *pb, T *buf, size_t bufNum) |
65 | | { |
66 | | const size_t byteSize = sizeof(T) * bufNum; |
67 | | *pb = read_inner(buf, byteSize); |
68 | | } |
69 | | private: |
70 | | HCRYPTPROV prov_; |
71 | | #else |
72 | | RandomGenerator() |
73 | | : fp_(::fopen("/dev/urandom", "rb")) |
74 | 0 | { |
75 | 0 | #ifndef CYBOZU_DONT_USE_EXCEPTION |
76 | 0 | if (!fp_) throw cybozu::Exception("randomgenerator"); |
77 | 0 | #endif |
78 | 0 | } |
79 | | ~RandomGenerator() |
80 | 0 | { |
81 | 0 | if (fp_) ::fclose(fp_); |
82 | 0 | } |
83 | | /* |
84 | | fill buf[0..bufNum-1] with random data |
85 | | @note bufNum is not byte size |
86 | | */ |
87 | | template<class T> |
88 | | void read(bool *pb, T *buf, size_t bufNum) |
89 | 0 | { |
90 | 0 | if (fp_ == 0) { |
91 | 0 | *pb = false; |
92 | 0 | return; |
93 | 0 | } |
94 | 0 | const size_t byteSize = sizeof(T) * bufNum; |
95 | 0 | *pb = ::fread(buf, 1, (int)byteSize, fp_) == byteSize; |
96 | 0 | } Unexecuted instantiation: void cybozu::RandomGenerator::read<unsigned int>(bool*, unsigned int*, unsigned long) Unexecuted instantiation: void cybozu::RandomGenerator::read<unsigned long>(bool*, unsigned long*, unsigned long) Unexecuted instantiation: void cybozu::RandomGenerator::read<unsigned char>(bool*, unsigned char*, unsigned long) |
97 | | private: |
98 | | FILE *fp_; |
99 | | #endif |
100 | | #ifndef CYBOZU_DONT_USE_EXCEPTION |
101 | | public: |
102 | | template<class T> |
103 | | void read(T *buf, size_t bufNum) |
104 | 0 | { |
105 | 0 | bool b; |
106 | 0 | read(&b, buf, bufNum); |
107 | 0 | if (!b) throw cybozu::Exception("RandomGenerator:read") << bufNum; |
108 | 0 | } Unexecuted instantiation: void cybozu::RandomGenerator::read<unsigned int>(unsigned int*, unsigned long) Unexecuted instantiation: void cybozu::RandomGenerator::read<unsigned long>(unsigned long*, unsigned long) |
109 | | uint32_t get32() |
110 | 0 | { |
111 | 0 | uint32_t ret; |
112 | 0 | read(&ret, 1); |
113 | 0 | return ret; |
114 | 0 | } |
115 | | uint64_t get64() |
116 | 0 | { |
117 | 0 | uint64_t ret; |
118 | 0 | read(&ret, 1); |
119 | 0 | return ret; |
120 | 0 | } |
121 | | uint32_t operator()() |
122 | 0 | { |
123 | 0 | return get32(); |
124 | 0 | } |
125 | | #endif |
126 | | }; |
127 | | |
128 | | template<class T, class RG> |
129 | | void shuffle(T* v, size_t n, RG& rg) |
130 | | { |
131 | | if (n <= 1) return; |
132 | | for (size_t i = 0; i < n - 1; i++) { |
133 | | size_t r = i + size_t(rg.get64() % (n - i)); |
134 | | using namespace std; |
135 | | swap(v[i], v[r]); |
136 | | } |
137 | | } |
138 | | |
139 | | template<class V, class RG> |
140 | | void shuffle(V& v, RG& rg) |
141 | | { |
142 | | shuffle(v.data(), v.size(), rg); |
143 | | } |
144 | | |
145 | | } // cybozu |