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
105
121inline int poissonRandomNumber(double lambda, std::mt19937& gen)
122{
123 if (lambda > 50)
124 return detail::poissonRatioOfUniformsInteger(lambda, gen);
125
126 std::uniform_real_distribution<double> unif(0, 1);
127
128 double L = exp(-lambda);
129 int k = 0;
130 double p = 1.0;
131 do {
132 k = k + 1;
133 p = p * unif(gen);
134 } while (p > L);
135
136 return k - 1;
137}
138
139inline int poissonRandomNumber(double lambda)
140{
141 static std::random_device rd;
142 static std::mt19937 gen(rd());
143 return detail::poissonRatioOfUniformsInteger(lambda, gen);
144}
145
156template<Point3Concept PointType>
158{
159 using ScalarType = PointType::ScalarType;
160
161 PointType interp;
162 std::uniform_real_distribution<ScalarType> unif(0, 1);
163
164 interp[1] = unif(gen);
165 interp[2] = unif(gen);
166 if (interp[1] + interp[2] > 1.0) {
167 interp[1] = 1.0 - interp[1];
168 interp[2] = 1.0 - interp[2];
169 }
170
171 interp[0] = 1.0 - (interp[1] + interp[2]);
172 return interp;
173}
174
175template<Point3Concept PointType>
176PointType randomTriangleBarycentricCoordinate()
177{
178 static std::random_device rd;
179 static std::mt19937 gen(rd());
180 return randomTriangleBarycentricCoordinate<PointType>(gen);
181}
182
183template<typename ScalarType>
184std::vector<ScalarType> randomPolygonBarycentricCoordinate(
185 uint polySize,
186 std::mt19937& gen)
187{
188 std::vector<ScalarType> barCoord(polySize);
189 ScalarType sum = 0;
190
191 std::uniform_real_distribution<ScalarType> unif(0, 100);
192
193 for (uint i = 0; i < polySize; i++) {
194 barCoord[i] = unif(gen);
195 sum += barCoord[i];
196 }
197 for (uint i = 0; i < polySize; i++) {
198 barCoord[i] /= sum;
199 }
200 return barCoord;
201}
202
203template<typename ScalarType>
204std::vector<ScalarType> randomPolygonBarycentricCoordinate(uint polySize)
205{
206 static std::random_device rd;
207 static std::mt19937 gen(rd());
208 return randomPolygonBarycentricCoordinate<ScalarType>(polySize, gen);
209}
210
211} // namespace vcl
212
213#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:157
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:121
double lnOfFactorial(int n)
Computes and caches the result of the natural logarithm of n!
Definition math.h:112