forked from jspark1105/tbb_test
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Rand.cc
140 lines (119 loc) · 3.65 KB
/
Rand.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include "Rand.h"
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <mkl.h>
std::default_random_engine eng;
#define USE_MKL_RNG
#ifdef USE_MKL_RNG
VSLStreamStatePtr getRngStream()
{
static VSLStreamStatePtr rng_stream;
static bool initialized = false;
if (!initialized) {
vslNewStream(&rng_stream, VSL_BRNG_NIEDERR, 3);
initialized = true;
}
return rng_stream;
}
#endif
void randFill(float *vec, size_t len, const float low, const float high,
bool duplicates) {
#ifdef USE_MKL_RNG
if (len > (1 << 29)) {
for (size_t i = 0; i < len; i += (1 << 29)) {
int l = std::min(1UL << 29, len - i);
vsRngUniform(
VSL_RNG_METHOD_UNIFORM_STD, getRngStream(), l, vec + i, low, high);
}
}
else {
vsRngUniform(
VSL_RNG_METHOD_UNIFORM_STD, getRngStream(), len, vec, low, high);
}
#else
std::uniform_real_distribution<float> dis(low, high);
for (size_t i = 0; i < len; ++i) {
vec[i] = dis(eng);
}
#endif
}
void randFill(double *vec, size_t len, const double low, const double high,
bool duplicates) {
#ifdef USE_MKL_RNG
if (len > (1 << 29)) {
for (size_t i = 0; i < len; i += (1 << 29)) {
int l = std::min(1UL << 29, len - i);
vdRngUniform(
VSL_RNG_METHOD_UNIFORM_STD, getRngStream(), l, vec + i, low, high);
}
}
else {
vdRngUniform(
VSL_RNG_METHOD_UNIFORM_STD, getRngStream(), len, vec, low, high);
}
#else
std::uniform_real_distribution<double> dis(low, high);
for (size_t i = 0; i < len; ++i) {
vec[i] = dis(eng);
}
#endif
}
void randFill(
aligned_vector<float> &vec, const float low, const float high) {
randFill(vec.data(), vec.size(), low, high);
}
void randFill(
aligned_vector<double> &vec, const double low, const double high) {
randFill(vec.data(), vec.size(), low, high);
}
template<typename T>
void randFill_(T *array, int len, const int low, const int high,
bool duplicates) {
if (duplicates == true) {
std::uniform_int_distribution<T> dis(low, high);
for (int i = 0; i < len; ++i) {
array[i] = dis(eng);
}
} else {
// no duplicates
// produce a list
assert(high - low >= len); // can't sample without duplicates
// An array with logical length high - low + 1
// If identity_map[k] doesn't exist, it implies identity_map[k] = k
std::unordered_map<int, T> identity_map;
for (auto i = 0; i < len; ++i) {
int j = (eng() % (high - low + 1 - i)) + i;
// swap identity_map[i] and identity_map[j], and put
// identity_map[i] to array[i].
array[i] =
(identity_map.find(j) == identity_map.end() ? j : identity_map[j]) +
low;
identity_map[j] =
identity_map.find(i) == identity_map.end() ? i : identity_map[i];
}
std::unordered_set<T> selected;
for (int i = 0; i < len; ++i) {
assert(array[i] >= low);
assert(array[i] <= high);
assert(selected.find(array[i]) == selected.end());
selected.insert(array[i]);
}
}
}
void randFill(int *array, int len, const int low, const int high,
bool duplicates) {
return randFill_(array, len, low, high, duplicates);
}
void randFill(int64_t *array, int len, const int low, const int high,
bool duplicates) {
return randFill_(array, len, low, high, duplicates);
}
void randFill(aligned_vector<int> &vec, const int low, const int high,
bool duplicates) {
return randFill(vec.data(), vec.size(), low, high, duplicates);
}
void randFill(aligned_vector<int64_t> &vec, const int low,
const int high, bool duplicates) {
return randFill(vec.data(), vec.size(), low, high, duplicates);
}