Visual Computing Library  devel
Loading...
Searching...
No Matches
random.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_ALGORITHMS_CORE_RANDOM_H
24#define VCL_ALGORITHMS_CORE_RANDOM_H
25
26#include <vclib/space/core.h>
27
28#include <random>
29
30namespace vcl {
31
32namespace detail {
33
57inline int poissonRatioOfUniformsInteger(double L, std::mt19937& gen)
58{
59 // constants
60 const double SHAT1 = 2.943035529371538573; // 8/e
61 const double SHAT2 = 0.8989161620588987408; // 3-sqrt(12/e)
62
63 double u; // uniform random
64 double lf; // ln(f(x))
65 double x; // real sample
66 int k; // integer sample
67
68 double pois_a = L + 0.5; // hat center
69 int mode = (int) L; // mode
70 double pois_g = std::log(L);
71 double pois_f0 = mode * pois_g - lnOfFactorial(mode); // value at mode
72 double pois_h = std::sqrt(SHAT1 * (L + 0.5)) + SHAT2; // hat width
73 double pois_bound = (int) (pois_a + 6.0 * pois_h); // safety-bound
74
75 std::uniform_real_distribution<double> unif(0, 1);
76
77 while (1) {
78 u = unif(gen);
79 if (u == 0)
80 continue; // avoid division by 0
81 x = pois_a + pois_h * (unif(gen) - 0.5) / u;
82 if (x < 0 || x >= pois_bound)
83 continue; // reject if outside valid range
84 k = (int) (x);
85 lf = k * pois_g - lnOfFactorial(k) - pois_f0;
86 if (lf >= u * (4.0 - u) - 3.0)
87 break; // quick acceptance
88 if (u * (u - lf) > 1.0)
89 continue; // quick rejection
90 if (2.0 * log(u) <= lf)
91 break; // final acceptance
92 }
93 return k;
94}
95
96inline int poissonRatioOfUniformsInteger(double L)
97{
98 static std::random_device rd;
99 static std::mt19937 gen(rd());
100 return poissonRatioOfUniformsInteger(L, gen);
101}
102
103} // namespace detail
104
120inline int poissonRandomNumber(double lambda, std::mt19937& gen)
121{
122 if (lambda > 50)
123 return detail::poissonRatioOfUniformsInteger(lambda, gen);
124
125 std::uniform_real_distribution<double> unif(0, 1);
126
127 double L = exp(-lambda);
128 int k = 0;
129 double p = 1.0;
130 do {
131 k = k + 1;
132 p = p * unif(gen);
133 } while (p > L);
134
135 return k - 1;
136}
137
138inline int poissonRandomNumber(double lambda)
139{
140 static std::random_device rd;
141 static std::mt19937 gen(rd());
142 return detail::poissonRatioOfUniformsInteger(lambda, gen);
143}
144
155template<Point3Concept PointType>
157{
158 using ScalarType = PointType::ScalarType;
159
160 PointType interp;
161 std::uniform_real_distribution<ScalarType> unif(0, 1);
162
163 interp[1] = unif(gen);
164 interp[2] = unif(gen);
165 if (interp[1] + interp[2] > 1.0) {
166 interp[1] = 1.0 - interp[1];
167 interp[2] = 1.0 - interp[2];
168 }
169
170 interp[0] = 1.0 - (interp[1] + interp[2]);
171 return interp;
172}
173
174template<Point3Concept PointType>
175PointType randomTriangleBarycentricCoordinate()
176{
177 static std::random_device rd;
178 static std::mt19937 gen(rd());
179 return randomTriangleBarycentricCoordinate<PointType>(gen);
180}
181
182template<typename ScalarType>
183std::vector<ScalarType> randomPolygonBarycentricCoordinate(
184 uint polySize,
185 std::mt19937& gen)
186{
187 std::vector<ScalarType> barCoord(polySize);
188 ScalarType sum = 0;
189
190 std::uniform_real_distribution<ScalarType> unif(0, 100);
191
192 for (uint i = 0; i < polySize; i++) {
193 barCoord[i] = unif(gen);
194 sum += barCoord[i];
195 }
196 for (uint i = 0; i < polySize; i++) {
197 barCoord[i] /= sum;
198 }
199 return barCoord;
200}
201
202template<typename ScalarType>
203std::vector<ScalarType> randomPolygonBarycentricCoordinate(uint polySize)
204{
205 static std::random_device rd;
206 static std::mt19937 gen(rd());
207 return randomPolygonBarycentricCoordinate<ScalarType>(polySize, gen);
208}
209
210} // namespace vcl
211
212#endif // VCL_ALGORITHMS_CORE_RANDOM_H
A class representing a box in N-dimensional space.
Definition box.h:46
PointType randomTriangleBarycentricCoordinate(std::mt19937 &gen)
Generate the barycentric coords of a random point over a triangle, with a uniform distribution over t...
Definition random.h:156
int poissonRandomNumber(double lambda, std::mt19937 &gen)
algorithm poisson random number (Knuth): init: Let L ← e^−λ, k ← 0 and p ← 1. do: k ← k + 1....
Definition random.h:120
double lnOfFactorial(int n)
Computes and caches the result of the natural logarithm of n!
Definition math.h:112