Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
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 
84 vpUniRand::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 
94 double vpUniRand::operator()() { return uniform(0.0, 1.0); }
95 
108 uint32_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 = -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 
145 uint32_t vpUniRand::next()
146 {
147  uint64_t oldstate = m_rng.state;
148  m_rng.state = (oldstate * 6364136223846793005ULL) + m_rng.inc;
149  uint32_t xorshifted = static_cast<uint32_t>(((oldstate >> 18u) ^ oldstate) >> 27u);
150  uint32_t rot = oldstate >> 59u;
151  return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
152 }
153 
159 int vpUniRand::uniform(int a, int b)
160 {
161  if (a == b) {
162  return a;
163  }
164  return boundedRand(b - a) + a;
165 }
166 
172 float vpUniRand::uniform(float a, float b) { return (next() * m_maxInvFlt * (b - a)) + a; }
173 
179 double vpUniRand::uniform(double a, double b) { return (next() * m_maxInvDbl * (b - a)) + a; }
180 
202 void vpUniRand::setSeed(uint64_t initstate, uint64_t initseq)
203 {
204  m_rng.state = 0U;
205  m_rng.inc = (initseq << 1u) | 1u;
206  next();
207  m_rng.state += initstate;
208  next();
209 }
210 END_VISP_NAMESPACE
int uniform(int a, int b)
Definition: vpUniRand.cpp:159
uint32_t next()
Definition: vpUniRand.cpp:145
double operator()()
Definition: vpUniRand.cpp:94
void setSeed(uint64_t initstate, uint64_t initseq)
Definition: vpUniRand.cpp:202