1*35238bceSAndroid Build Coastguard Worker #ifndef _DERANDOM_HPP
2*35238bceSAndroid Build Coastguard Worker #define _DERANDOM_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker * drawElements C++ Base Library
5*35238bceSAndroid Build Coastguard Worker * -----------------------------
6*35238bceSAndroid Build Coastguard Worker *
7*35238bceSAndroid Build Coastguard Worker * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker *
9*35238bceSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker *
13*35238bceSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker *
15*35238bceSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker *
21*35238bceSAndroid Build Coastguard Worker *//*!
22*35238bceSAndroid Build Coastguard Worker * \file
23*35238bceSAndroid Build Coastguard Worker * \brief Random number generator utilities.
24*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker
26*35238bceSAndroid Build Coastguard Worker #include "deDefs.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deRandom.h"
28*35238bceSAndroid Build Coastguard Worker
29*35238bceSAndroid Build Coastguard Worker #include <iterator> // std::distance()
30*35238bceSAndroid Build Coastguard Worker #include <algorithm> // std::swap()
31*35238bceSAndroid Build Coastguard Worker
32*35238bceSAndroid Build Coastguard Worker namespace de
33*35238bceSAndroid Build Coastguard Worker {
34*35238bceSAndroid Build Coastguard Worker
35*35238bceSAndroid Build Coastguard Worker //! Random self-test - compare returned values against hard-coded values.
36*35238bceSAndroid Build Coastguard Worker void Random_selfTest(void);
37*35238bceSAndroid Build Coastguard Worker
38*35238bceSAndroid Build Coastguard Worker class Random
39*35238bceSAndroid Build Coastguard Worker {
40*35238bceSAndroid Build Coastguard Worker public:
Random(uint32_t seed)41*35238bceSAndroid Build Coastguard Worker Random(uint32_t seed)
42*35238bceSAndroid Build Coastguard Worker {
43*35238bceSAndroid Build Coastguard Worker deRandom_init(&m_rnd, seed);
44*35238bceSAndroid Build Coastguard Worker }
~Random(void)45*35238bceSAndroid Build Coastguard Worker ~Random(void)
46*35238bceSAndroid Build Coastguard Worker {
47*35238bceSAndroid Build Coastguard Worker }
48*35238bceSAndroid Build Coastguard Worker
getFloat(void)49*35238bceSAndroid Build Coastguard Worker float getFloat(void)
50*35238bceSAndroid Build Coastguard Worker {
51*35238bceSAndroid Build Coastguard Worker return deRandom_getFloat(&m_rnd);
52*35238bceSAndroid Build Coastguard Worker }
getDouble(void)53*35238bceSAndroid Build Coastguard Worker double getDouble(void)
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker return deRandom_getDouble(&m_rnd);
56*35238bceSAndroid Build Coastguard Worker }
getBool(void)57*35238bceSAndroid Build Coastguard Worker bool getBool(void)
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker return deRandom_getBool(&m_rnd) == true;
60*35238bceSAndroid Build Coastguard Worker }
61*35238bceSAndroid Build Coastguard Worker
62*35238bceSAndroid Build Coastguard Worker float getFloat(float min, float max);
63*35238bceSAndroid Build Coastguard Worker double getDouble(double min, double max);
64*35238bceSAndroid Build Coastguard Worker int getInt(int min, int max);
65*35238bceSAndroid Build Coastguard Worker
getInt64(void)66*35238bceSAndroid Build Coastguard Worker int64_t getInt64(void)
67*35238bceSAndroid Build Coastguard Worker {
68*35238bceSAndroid Build Coastguard Worker uint32_t upper = getUint32();
69*35238bceSAndroid Build Coastguard Worker return static_cast<int64_t>((uint64_t)upper << 32ull | (uint64_t)getUint32());
70*35238bceSAndroid Build Coastguard Worker }
getUint64(void)71*35238bceSAndroid Build Coastguard Worker uint64_t getUint64(void)
72*35238bceSAndroid Build Coastguard Worker {
73*35238bceSAndroid Build Coastguard Worker uint32_t upper = getUint32();
74*35238bceSAndroid Build Coastguard Worker return (uint64_t)upper << 32ull | (uint64_t)getUint32();
75*35238bceSAndroid Build Coastguard Worker }
getInt32(void)76*35238bceSAndroid Build Coastguard Worker int32_t getInt32(void)
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker return static_cast<int32_t>(getUint32());
79*35238bceSAndroid Build Coastguard Worker }
getUint32(void)80*35238bceSAndroid Build Coastguard Worker uint32_t getUint32(void)
81*35238bceSAndroid Build Coastguard Worker {
82*35238bceSAndroid Build Coastguard Worker return deRandom_getUint32(&m_rnd);
83*35238bceSAndroid Build Coastguard Worker }
getUint16(void)84*35238bceSAndroid Build Coastguard Worker uint16_t getUint16(void)
85*35238bceSAndroid Build Coastguard Worker {
86*35238bceSAndroid Build Coastguard Worker return (uint16_t)deRandom_getUint32(&m_rnd);
87*35238bceSAndroid Build Coastguard Worker }
getUint8(void)88*35238bceSAndroid Build Coastguard Worker uint8_t getUint8(void)
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker return (uint8_t)deRandom_getUint32(&m_rnd);
91*35238bceSAndroid Build Coastguard Worker }
92*35238bceSAndroid Build Coastguard Worker
93*35238bceSAndroid Build Coastguard Worker template <class InputIter, class OutputIter>
94*35238bceSAndroid Build Coastguard Worker void choose(InputIter first, InputIter last, OutputIter result, int numItems);
95*35238bceSAndroid Build Coastguard Worker
96*35238bceSAndroid Build Coastguard Worker template <typename T, class InputIter>
97*35238bceSAndroid Build Coastguard Worker T choose(InputIter first, InputIter last);
98*35238bceSAndroid Build Coastguard Worker
99*35238bceSAndroid Build Coastguard Worker // \note Weights must be floats
100*35238bceSAndroid Build Coastguard Worker template <typename T, class InputIter, class WeightIter>
101*35238bceSAndroid Build Coastguard Worker T chooseWeighted(InputIter first, InputIter last, WeightIter weight);
102*35238bceSAndroid Build Coastguard Worker
103*35238bceSAndroid Build Coastguard Worker template <class Iterator>
104*35238bceSAndroid Build Coastguard Worker void shuffle(Iterator first, Iterator last);
105*35238bceSAndroid Build Coastguard Worker
106*35238bceSAndroid Build Coastguard Worker bool operator==(const Random &other) const;
107*35238bceSAndroid Build Coastguard Worker bool operator!=(const Random &other) const;
108*35238bceSAndroid Build Coastguard Worker
109*35238bceSAndroid Build Coastguard Worker private:
110*35238bceSAndroid Build Coastguard Worker deRandom m_rnd;
111*35238bceSAndroid Build Coastguard Worker } DE_WARN_UNUSED_TYPE;
112*35238bceSAndroid Build Coastguard Worker
113*35238bceSAndroid Build Coastguard Worker // Inline implementations
114*35238bceSAndroid Build Coastguard Worker
getFloat(float min,float max)115*35238bceSAndroid Build Coastguard Worker inline float Random::getFloat(float min, float max)
116*35238bceSAndroid Build Coastguard Worker {
117*35238bceSAndroid Build Coastguard Worker DE_ASSERT(min <= max);
118*35238bceSAndroid Build Coastguard Worker return min + (max - min) * getFloat();
119*35238bceSAndroid Build Coastguard Worker }
120*35238bceSAndroid Build Coastguard Worker
getDouble(double min,double max)121*35238bceSAndroid Build Coastguard Worker inline double Random::getDouble(double min, double max)
122*35238bceSAndroid Build Coastguard Worker {
123*35238bceSAndroid Build Coastguard Worker DE_ASSERT(min <= max);
124*35238bceSAndroid Build Coastguard Worker return min + (max - min) * getDouble();
125*35238bceSAndroid Build Coastguard Worker }
126*35238bceSAndroid Build Coastguard Worker
getInt(int min,int max)127*35238bceSAndroid Build Coastguard Worker inline int Random::getInt(int min, int max)
128*35238bceSAndroid Build Coastguard Worker {
129*35238bceSAndroid Build Coastguard Worker DE_ASSERT(min <= max);
130*35238bceSAndroid Build Coastguard Worker if (min == (int)0x80000000 && max == (int)0x7fffffff)
131*35238bceSAndroid Build Coastguard Worker return (int)getUint32();
132*35238bceSAndroid Build Coastguard Worker else
133*35238bceSAndroid Build Coastguard Worker return min + (int)(getUint32() % ((uint32_t)max - (uint32_t)min + 1u));
134*35238bceSAndroid Build Coastguard Worker }
135*35238bceSAndroid Build Coastguard Worker
136*35238bceSAndroid Build Coastguard Worker // Template implementations
137*35238bceSAndroid Build Coastguard Worker
138*35238bceSAndroid Build Coastguard Worker template <class InputIter, class OutputIter>
choose(InputIter first,InputIter last,OutputIter result,int numItems)139*35238bceSAndroid Build Coastguard Worker void Random::choose(InputIter first, InputIter last, OutputIter result, int numItems)
140*35238bceSAndroid Build Coastguard Worker {
141*35238bceSAndroid Build Coastguard Worker // Algorithm: Reservoir sampling
142*35238bceSAndroid Build Coastguard Worker // http://en.wikipedia.org/wiki/Reservoir_sampling
143*35238bceSAndroid Build Coastguard Worker // \note Will not work for suffling an array. Use suffle() instead.
144*35238bceSAndroid Build Coastguard Worker
145*35238bceSAndroid Build Coastguard Worker int ndx;
146*35238bceSAndroid Build Coastguard Worker for (ndx = 0; first != last; ++first, ++ndx)
147*35238bceSAndroid Build Coastguard Worker {
148*35238bceSAndroid Build Coastguard Worker if (ndx < numItems)
149*35238bceSAndroid Build Coastguard Worker *(result + ndx) = *first;
150*35238bceSAndroid Build Coastguard Worker else
151*35238bceSAndroid Build Coastguard Worker {
152*35238bceSAndroid Build Coastguard Worker int r = getInt(0, ndx);
153*35238bceSAndroid Build Coastguard Worker if (r < numItems)
154*35238bceSAndroid Build Coastguard Worker *(result + r) = *first;
155*35238bceSAndroid Build Coastguard Worker }
156*35238bceSAndroid Build Coastguard Worker }
157*35238bceSAndroid Build Coastguard Worker
158*35238bceSAndroid Build Coastguard Worker DE_ASSERT(ndx >= numItems);
159*35238bceSAndroid Build Coastguard Worker }
160*35238bceSAndroid Build Coastguard Worker
161*35238bceSAndroid Build Coastguard Worker template <typename T, class InputIter>
choose(InputIter first,InputIter last)162*35238bceSAndroid Build Coastguard Worker T Random::choose(InputIter first, InputIter last)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker T val = T();
165*35238bceSAndroid Build Coastguard Worker DE_ASSERT(first != last);
166*35238bceSAndroid Build Coastguard Worker choose(first, last, &val, 1);
167*35238bceSAndroid Build Coastguard Worker return val;
168*35238bceSAndroid Build Coastguard Worker }
169*35238bceSAndroid Build Coastguard Worker
170*35238bceSAndroid Build Coastguard Worker template <typename T, class InputIter, class WeightIter>
chooseWeighted(InputIter first,InputIter last,WeightIter weight)171*35238bceSAndroid Build Coastguard Worker T Random::chooseWeighted(InputIter first, InputIter last, WeightIter weight)
172*35238bceSAndroid Build Coastguard Worker {
173*35238bceSAndroid Build Coastguard Worker // Compute weight sum
174*35238bceSAndroid Build Coastguard Worker float weightSum = 0.0f;
175*35238bceSAndroid Build Coastguard Worker int ndx;
176*35238bceSAndroid Build Coastguard Worker for (ndx = 0; (first + ndx) != last; ndx++)
177*35238bceSAndroid Build Coastguard Worker weightSum += *(weight + ndx);
178*35238bceSAndroid Build Coastguard Worker
179*35238bceSAndroid Build Coastguard Worker // Random point in 0..weightSum
180*35238bceSAndroid Build Coastguard Worker float p = getFloat(0.0f, weightSum);
181*35238bceSAndroid Build Coastguard Worker
182*35238bceSAndroid Build Coastguard Worker // Find item in range
183*35238bceSAndroid Build Coastguard Worker InputIter lastNonZero = last;
184*35238bceSAndroid Build Coastguard Worker float curWeight = 0.0f;
185*35238bceSAndroid Build Coastguard Worker for (ndx = 0; (first + ndx) != last; ndx++)
186*35238bceSAndroid Build Coastguard Worker {
187*35238bceSAndroid Build Coastguard Worker float w = *(weight + ndx);
188*35238bceSAndroid Build Coastguard Worker
189*35238bceSAndroid Build Coastguard Worker curWeight += w;
190*35238bceSAndroid Build Coastguard Worker
191*35238bceSAndroid Build Coastguard Worker if (p < curWeight)
192*35238bceSAndroid Build Coastguard Worker return *(first + ndx);
193*35238bceSAndroid Build Coastguard Worker else if (w > 0.0f)
194*35238bceSAndroid Build Coastguard Worker lastNonZero = first + ndx;
195*35238bceSAndroid Build Coastguard Worker }
196*35238bceSAndroid Build Coastguard Worker
197*35238bceSAndroid Build Coastguard Worker DE_ASSERT(lastNonZero != last);
198*35238bceSAndroid Build Coastguard Worker return *lastNonZero;
199*35238bceSAndroid Build Coastguard Worker }
200*35238bceSAndroid Build Coastguard Worker
201*35238bceSAndroid Build Coastguard Worker template <class Iterator>
shuffle(Iterator first,Iterator last)202*35238bceSAndroid Build Coastguard Worker void Random::shuffle(Iterator first, Iterator last)
203*35238bceSAndroid Build Coastguard Worker {
204*35238bceSAndroid Build Coastguard Worker using std::swap;
205*35238bceSAndroid Build Coastguard Worker
206*35238bceSAndroid Build Coastguard Worker // Fisher-Yates suffle
207*35238bceSAndroid Build Coastguard Worker int numItems = (int)std::distance(first, last);
208*35238bceSAndroid Build Coastguard Worker
209*35238bceSAndroid Build Coastguard Worker for (int i = numItems - 1; i >= 1; i--)
210*35238bceSAndroid Build Coastguard Worker {
211*35238bceSAndroid Build Coastguard Worker int j = getInt(0, i);
212*35238bceSAndroid Build Coastguard Worker swap(*(first + i), *(first + j));
213*35238bceSAndroid Build Coastguard Worker }
214*35238bceSAndroid Build Coastguard Worker }
215*35238bceSAndroid Build Coastguard Worker
216*35238bceSAndroid Build Coastguard Worker template <typename T>
217*35238bceSAndroid Build Coastguard Worker T randomScalar(de::Random &rnd, T minValue, T maxValue);
218*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,float minValue,float maxValue)219*35238bceSAndroid Build Coastguard Worker inline float randomScalar(de::Random &rnd, float minValue, float maxValue)
220*35238bceSAndroid Build Coastguard Worker {
221*35238bceSAndroid Build Coastguard Worker return rnd.getFloat(minValue, maxValue);
222*35238bceSAndroid Build Coastguard Worker }
223*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,int32_t minValue,int32_t maxValue)224*35238bceSAndroid Build Coastguard Worker inline int32_t randomScalar(de::Random &rnd, int32_t minValue, int32_t maxValue)
225*35238bceSAndroid Build Coastguard Worker {
226*35238bceSAndroid Build Coastguard Worker return rnd.getInt(minValue, maxValue);
227*35238bceSAndroid Build Coastguard Worker }
228*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,uint32_t minValue,uint32_t maxValue)229*35238bceSAndroid Build Coastguard Worker inline uint32_t randomScalar(de::Random &rnd, uint32_t minValue, uint32_t maxValue)
230*35238bceSAndroid Build Coastguard Worker {
231*35238bceSAndroid Build Coastguard Worker if (minValue == 0 && maxValue == 0xffffffff)
232*35238bceSAndroid Build Coastguard Worker return rnd.getUint32();
233*35238bceSAndroid Build Coastguard Worker return minValue + rnd.getUint32() % (maxValue - minValue + 1);
234*35238bceSAndroid Build Coastguard Worker }
235*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,int16_t minValue,int16_t maxValue)236*35238bceSAndroid Build Coastguard Worker inline int16_t randomScalar(de::Random &rnd, int16_t minValue, int16_t maxValue)
237*35238bceSAndroid Build Coastguard Worker {
238*35238bceSAndroid Build Coastguard Worker return (int16_t)rnd.getInt(minValue, maxValue);
239*35238bceSAndroid Build Coastguard Worker }
240*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,uint16_t minValue,uint16_t maxValue)241*35238bceSAndroid Build Coastguard Worker inline uint16_t randomScalar(de::Random &rnd, uint16_t minValue, uint16_t maxValue)
242*35238bceSAndroid Build Coastguard Worker {
243*35238bceSAndroid Build Coastguard Worker return (uint16_t)(minValue + rnd.getUint16() % (maxValue - minValue + 1));
244*35238bceSAndroid Build Coastguard Worker }
245*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,int8_t minValue,int8_t maxValue)246*35238bceSAndroid Build Coastguard Worker inline int8_t randomScalar(de::Random &rnd, int8_t minValue, int8_t maxValue)
247*35238bceSAndroid Build Coastguard Worker {
248*35238bceSAndroid Build Coastguard Worker return (int8_t)rnd.getInt(minValue, maxValue);
249*35238bceSAndroid Build Coastguard Worker }
250*35238bceSAndroid Build Coastguard Worker template <>
randomScalar(de::Random & rnd,uint8_t minValue,uint8_t maxValue)251*35238bceSAndroid Build Coastguard Worker inline uint8_t randomScalar(de::Random &rnd, uint8_t minValue, uint8_t maxValue)
252*35238bceSAndroid Build Coastguard Worker {
253*35238bceSAndroid Build Coastguard Worker return (uint8_t)(minValue + rnd.getUint8() % (maxValue - minValue + 1));
254*35238bceSAndroid Build Coastguard Worker }
255*35238bceSAndroid Build Coastguard Worker
256*35238bceSAndroid Build Coastguard Worker } // namespace de
257*35238bceSAndroid Build Coastguard Worker
258*35238bceSAndroid Build Coastguard Worker #endif // _DERANDOM_HPP
259