Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpUniRand.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Pseudo random number generator.
32 */
33
34/*
35 * PCG Random Number Generation for C.
36 *
37 * Copyright 2014 Melissa O'Neill <oneill@pcg-random.org>
38 *
39 * Licensed under the Apache License, Version 2.0 (the "License");
40 * you may not use this file except in compliance with the License.
41 * You may obtain a copy of the License at
42 *
43 * http://www.apache.org/licenses/LICENSE-2.0
44 *
45 * Unless required by applicable law or agreed to in writing, software
46 * distributed under the License is distributed on an "AS IS" BASIS,
47 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
48 * See the License for the specific language governing permissions and
49 * limitations under the License.
50 *
51 * For additional information about the PCG random number generation scheme,
52 * including its license and other licensing options, visit
53 *
54 * http://www.pcg-random.org
55 */
56
57/*
58 * This code is derived from the full C implementation, which is in turn
59 * derived from the canonical C++ PCG implementation. The C++ version
60 * has many additional features and is preferable if you can use C++ in
61 * your project.
62 */
63
64// To ensure UINT32_MAX, INT32_MX are defined on centos, ubuntu 12.04 we define __STDC_LIMIT_MACROS
65
66#define __STDC_LIMIT_MACROS
67
68#include <stdint.h>
69#include <visp3/core/vpUniRand.h>
70
73 : m_maxInvDbl(1.0 / static_cast<double>(UINT32_MAX)), m_maxInvFlt(1.0f / static_cast<float>(UINT32_MAX)), m_rng()
74{ }
75
84vpUniRand::vpUniRand(uint64_t seed, uint64_t seq)
85 : m_maxInvDbl(1.0 / static_cast<double>(UINT32_MAX)), m_maxInvFlt(1.0f / static_cast<float>(UINT32_MAX)), m_rng()
86{
87 setSeed(seed, seq);
88}
89
94double vpUniRand::operator()() { return uniform(0.0, 1.0); }
95
108uint32_t vpUniRand::boundedRand(uint32_t bound)
109{
110 // To avoid bias, we need to make the range of the RNG a multiple of
111 // bound, which we do by dropping output less than a threshold.
112 // A naive scheme to calculate the threshold would be to do
113 //
114 // uint32_t threshold = 0x100000000ull % bound;
115 //
116 // but 64-bit div/mod is slower than 32-bit div/mod (especially on
117 // 32-bit platforms). In essence, we do
118 //
119 // uint32_t threshold = (0x100000000ull-bound) % bound;
120 //
121 // because this version will calculate the same modulus, but the LHS
122 // value is less than 2^32.
123
124 uint32_t threshold = static_cast<uint64_t>(-static_cast<int64_t>(bound) % bound);
125
126 // Uniformity guarantees that this loop will terminate. In practice, it
127 // should usually terminate quickly; on average (assuming all bounds are
128 // equally likely), 82.25% of the time, we can expect it to require just
129 // one iteration. In the worst case, someone passes a bound of 2^31 + 1
130 // (i.e., 2147483649), which invalidates almost 50% of the range. In
131 // practice, bounds are typically small and only a tiny amount of the range
132 // is eliminated.
133 for (;;) {
134 uint32_t r = next();
135 if (r >= threshold) {
136 return r % bound;
137 }
138 }
139}
140
146{
147 const unsigned long long val_ll = 6364136223846793005ULL;
148 const uint32_t val_31 = 31;
149 uint64_t oldstate = m_rng.state;
150 m_rng.state = (oldstate * val_ll) + m_rng.inc;
151 uint32_t xorshifted = static_cast<uint32_t>(((oldstate >> 18u) ^ oldstate) >> 27u);
152 uint32_t rot = oldstate >> 59u;
153 return (xorshifted >> rot) | (xorshifted << (static_cast<uint32_t>((-static_cast<int64_t>(rot)) & val_31)));
154}
155
161int vpUniRand::uniform(int a, int b)
162{
163 if (a == b) {
164 return a;
165 }
166 return boundedRand(b - a) + a;
167}
168
174float vpUniRand::uniform(float a, float b) { return (next() * m_maxInvFlt * (b - a)) + a; }
175
181double vpUniRand::uniform(double a, double b) { return (next() * m_maxInvDbl * (b - a)) + a; }
182
204void vpUniRand::setSeed(uint64_t initstate, uint64_t initseq)
205{
206 m_rng.state = 0U;
207 m_rng.inc = (initseq << 1u) | 1u;
208 next();
209 m_rng.state += initstate;
210 next();
211}
212
213
214std::vector<size_t> vpUniRand::sampleWithoutReplacement(size_t count, size_t vectorSize)
215{
216 count = std::min(count, vectorSize);
217 std::vector<size_t> indices(count);
218 size_t added = 0;
219 for (size_t i = 0; i < vectorSize; ++i) {
220 double randomVal = uniform(0.0, 1.0);
221 if ((vectorSize - i) * randomVal < (count - added)) {
222 indices[added++] = i;
223 }
224 if (added == count) {
225 break;
226 }
227 }
228 return indices;
229}
230
231END_VISP_NAMESPACE
int uniform(int a, int b)
uint32_t next()
std::vector< size_t > sampleWithoutReplacement(size_t count, size_t vectorSize)
double operator()()
Definition vpUniRand.cpp:94
void setSeed(uint64_t initstate, uint64_t initseq)