init
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
|
||||
# define CXX interface library
|
||||
|
||||
# define target & alias (for other projects consuming the "source-tree")
|
||||
add_library(iue-rnd_rnd INTERFACE)
|
||||
|
||||
# define sources of target
|
||||
target_sources(iue-rnd_rnd
|
||||
INTERFACE FILE_SET public_headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES random.hpp)
|
||||
|
||||
# define installation step
|
||||
install(TARGETS iue-rnd_rnd EXPORT iue-rnd-export
|
||||
FILE_SET public_headers DESTINATION "./")
|
||||
|
||||
# define test
|
||||
|
||||
if(BUILD_TESTING AND PROJECT_IS_TOP_LEVEL)
|
||||
add_executable(iue-rnd_rnd.test random.test.cpp)
|
||||
target_link_libraries(iue-rnd_rnd.test iue-rnd_rnd)
|
||||
add_test(NAME iue-rnd_rnd.test COMMAND iue-rnd_rnd.test)
|
||||
endif()
|
||||
|
||||
# export targets for consuming cmake projects
|
||||
|
||||
# generate and install a .cmake file to allow dependend projects consuming the "install-tree" to import all targets
|
||||
install(EXPORT iue-rnd-export DESTINATION "iue-rnd" )
|
||||
|
||||
# allow dependend projects consuming the "build-tree" to use all targets
|
||||
export(EXPORT iue-rnd-export)
|
||||
@@ -0,0 +1,128 @@
|
||||
/// @file
|
||||
/// @brief Generators for uniform distributions of Values, Circles and Triangles
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array> // std::array
|
||||
#include <cmath> // std::sqrt, std::sin, std::cos
|
||||
#include <numbers> // std::numbers::pi
|
||||
#include <random> // std::mt19937, std::uniform_real_distribution
|
||||
#include <tuple> // std::tuple
|
||||
|
||||
namespace iue::rnd {
|
||||
|
||||
using Vec2d = std::array<double, 2>;
|
||||
using Circle = std::tuple<Vec2d, double>;
|
||||
using Triangle = std::array<Vec2d, 3>;
|
||||
|
||||
///@brief Uniformly distributed speudorandom floating point values
|
||||
struct UniformValue {
|
||||
|
||||
std::mt19937 algo; ///< Random number generator
|
||||
std::uniform_real_distribution<double> dist; ///< Interval and distribution type
|
||||
|
||||
/// @brief Constructs an instance producing random values uniformly distributed over an interval
|
||||
/// @param min Lower bound of the interval
|
||||
/// @param max Upper bound of the interval
|
||||
/// @param seed Seed used to initialize the generator algorithm
|
||||
UniformValue(const double min, const double max, const std::size_t seed = 1) : algo(seed), dist(min, max) {}
|
||||
|
||||
/// @brief Obtains the next random value using current state of the generator
|
||||
/// @return Random value
|
||||
double operator()() { return dist(algo); }
|
||||
};
|
||||
|
||||
///@brief Uniformly distributed circles
|
||||
struct UniformCircle {
|
||||
|
||||
std::mt19937 algo; ///< Random number generator
|
||||
std::uniform_real_distribution<double> x; ///< Interval and distribution type for the x-coordinate
|
||||
std::uniform_real_distribution<double> y; ///< Interval and distribution type for the y-coordinate
|
||||
std::uniform_real_distribution<double> r; ///< Interval and distribution type for the r-coordinate
|
||||
|
||||
/// @brief Constructs an instance producing random circles uniformly distributed (center and radius)
|
||||
/// @param c_min Lower bound of the coordinate of the center
|
||||
/// @param c_max Upper bound of the coordinate of the center
|
||||
/// @param r_min Lower bound of the radius
|
||||
/// @param r_max Upper ound of the radius
|
||||
/// @param seed Seed used to initialize the generator algorithm
|
||||
UniformCircle(const Vec2d& c_min, const Vec2d& c_max, double r_min, double r_max, const std::size_t seed = 1)
|
||||
: algo(seed), x(c_min[0], c_max[0]), y(c_min[1], c_max[1]), r(r_min, r_max) {}
|
||||
|
||||
/// @brief Obtains the next random circle using current state of the generator
|
||||
/// @return Random circle
|
||||
std::tuple<std::array<double, 2>, double> operator()() {
|
||||
// random center
|
||||
Vec2d center = {x(algo), y(algo)};
|
||||
// random raidus
|
||||
double radius = r(algo);
|
||||
// return final configuration
|
||||
return {center, radius};
|
||||
}
|
||||
};
|
||||
|
||||
///@brief Uniformly distributed triangles
|
||||
struct UniformTriangle {
|
||||
|
||||
std::mt19937 algo; ///< Random number generators
|
||||
std::uniform_real_distribution<double> c_x; ///< distribution for the x-coordinate of the circumcircle
|
||||
std::uniform_real_distribution<double> c_y; ///< distribution for the y-coordinate of the circumcircle
|
||||
std::uniform_real_distribution<double> c_r; ///< distribution for the radius of the circumcircle
|
||||
std::uniform_real_distribution<double> angle120; ///< distribution for the angles of the corner points
|
||||
std::uniform_real_distribution<double> angle360; ///< distribution for the random rotation of the triangle
|
||||
|
||||
/// @brief Constructs an instance producing random triangles with
|
||||
/// - uniformly distributed circumcircles, and
|
||||
/// - uniformly distributed corner points w.r.t. three fixed non-overlapping 120-degree segments on the unit circle
|
||||
/// @param c_min Lower bound of the coordinate of the circumcirle
|
||||
/// @param c_max Upper bound of the coordinate of the circumcirle
|
||||
/// @param r_min Lower bound of the radius of the circle
|
||||
/// @param r_max Upper ound of the radius of the circle
|
||||
/// @param seed Seed used to initialize the generator algorithm
|
||||
UniformTriangle(const Vec2d& c_min, const Vec2d& c_max, double r_min, double r_max, const std::size_t seed = 1)
|
||||
: algo(seed), c_x(c_min[0], c_max[0]), c_y(c_min[1], c_max[1]), c_r(r_min, r_max),
|
||||
angle120(0, std::numbers::pi * 2 / 3), angle360(0, std::numbers::pi * 2) {}
|
||||
|
||||
/// @brief Obtains the next random triangle using current state of the generator
|
||||
/// @return Random circle
|
||||
Triangle operator()() {
|
||||
|
||||
// three points on the unit circle constraint to three 120deg-segments
|
||||
// these will be the points of the triangle
|
||||
double seg = angle120.max();
|
||||
double alpha = seg * 0 + angle120(algo);
|
||||
double beta = seg * 1 + angle120(algo);
|
||||
double gamma = seg * 2 + angle120(algo);
|
||||
|
||||
Vec2d a = {std::sin(alpha), std::cos(alpha)};
|
||||
Vec2d b = {std::sin(beta), std::cos(beta)};
|
||||
Vec2d c = {std::sin(gamma), std::cos(gamma)};
|
||||
|
||||
Triangle abc = {a, b, c};
|
||||
|
||||
// random circumcircle center
|
||||
Vec2d center = {c_x(algo), c_y(algo)};
|
||||
// random circumcircle radius
|
||||
double r = c_r(algo);
|
||||
// random rotation
|
||||
double rot = angle360(algo);
|
||||
|
||||
auto rotate = [rot](const Vec2d& p) -> const Vec2d {
|
||||
return {std::cos(rot) * p[0] + (-std::sin(rot)) * p[1], std::sin(rot) * p[0] + std::cos(rot) * p[1]};
|
||||
};
|
||||
auto shift = [center](const Vec2d& p) -> const Vec2d { return {p[0] + center[0], p[1] + center[1]}; };
|
||||
auto scale = [r](const Vec2d& p) -> const Vec2d { return {p[0] * r, p[1] * r}; };
|
||||
|
||||
// rotate/scale/shift to final configuration
|
||||
for (auto& coord : abc) {
|
||||
coord = rotate(coord);
|
||||
coord = scale(coord);
|
||||
coord = shift(coord);
|
||||
}
|
||||
|
||||
// return final configuration
|
||||
return {abc};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace iue::rnd
|
||||
@@ -0,0 +1,93 @@
|
||||
/// @file
|
||||
/// @brief Test for iue::rnd::UniformValue, iue::rnd::UniformTriangle, and iue::rnd::UniformCircle
|
||||
|
||||
#include <cassert> // assert
|
||||
#include <numeric> // std::accumulate
|
||||
#include <vector> // std::vector
|
||||
|
||||
#include "iue-rnd/random.hpp" // iue::rnd::UniformValue, iue::rnd::UniformTriangle, iue::rnd::UniformCircle
|
||||
|
||||
#include <iue-num/numerics.hpp> // iue::num::isclose
|
||||
|
||||
int main() {
|
||||
|
||||
{ // random value
|
||||
std::vector<double> items;
|
||||
|
||||
auto gen = iue::rnd::UniformValue(1.0, 2.0);
|
||||
size_t N = 1e5;
|
||||
for (int n = 0; n != N; ++n)
|
||||
items.push_back({gen()});
|
||||
|
||||
// mean
|
||||
auto get_value = [](double sum, const double& value) { return sum + value; };
|
||||
auto mean = std::accumulate(items.begin(), items.end(), 0.0, get_value) / items.size();
|
||||
assert(iue::num::isclose(mean, 1.5, 1e3 / N));
|
||||
}
|
||||
|
||||
{ // random circle
|
||||
std::vector<iue::rnd::Circle> items;
|
||||
|
||||
// generate random circles
|
||||
iue::rnd::Vec2d min = {1, 1};
|
||||
iue::rnd::Vec2d max = {2, 2};
|
||||
auto gen = iue::rnd::UniformCircle(min, max, 1, 2);
|
||||
size_t N = 1e5;
|
||||
for (int n = 0; n != N; ++n)
|
||||
items.push_back({gen()});
|
||||
|
||||
// r_mean
|
||||
auto get_r = [](double sum, const iue::rnd::Circle& circ) {
|
||||
const auto& [c, r] = circ;
|
||||
return sum + r;
|
||||
};
|
||||
auto r_mean = std::accumulate(items.begin(), items.end(), 0.0, get_r) / items.size();
|
||||
assert(iue::num::isclose(r_mean, 1.5, 1e3 / N));
|
||||
|
||||
// cx_mean
|
||||
auto get_cx = [](double sum, const iue::rnd::Circle& circ) {
|
||||
const auto& [c, r] = circ;
|
||||
return sum + c[0];
|
||||
};
|
||||
auto cx_mean = std::accumulate(items.begin(), items.end(), 0.0, get_cx) / items.size();
|
||||
assert(iue::num::isclose(cx_mean, 1.5, 1e3 / N));
|
||||
|
||||
// cy_mean
|
||||
auto get_cy = [](double sum, const iue::rnd::Circle& circ) {
|
||||
const auto& [c, r] = circ;
|
||||
return sum + c[1];
|
||||
};
|
||||
auto cy_mean = std::accumulate(items.begin(), items.end(), 0.0, get_cy) / items.size();
|
||||
assert(iue::num::isclose(cy_mean, 1.5, 1e3 / N));
|
||||
}
|
||||
|
||||
{ // random triangle
|
||||
std::vector<iue::rnd::Triangle> items;
|
||||
|
||||
// generate random circles
|
||||
iue::rnd::Vec2d min = {1, 1};
|
||||
iue::rnd::Vec2d max = {2, 2};
|
||||
auto gen = iue::rnd::UniformTriangle(min, max, 1, 2);
|
||||
size_t N = 1e5;
|
||||
for (int n = 0; n != N; ++n)
|
||||
items.push_back({gen()});
|
||||
|
||||
// abcx_mean
|
||||
auto get_x = [](double sum, const iue::rnd::Triangle& tri) {
|
||||
const auto& [a, b, c] = tri;
|
||||
return sum + a[0] + b[0] + c[0];
|
||||
};
|
||||
auto abcx_mean = std::accumulate(items.begin(), items.end(), 0.0, get_x) / items.size() / 3.0;
|
||||
assert(iue::num::isclose(abcx_mean, 1.5, 1e3 / N));
|
||||
|
||||
// abcx_mean
|
||||
auto get_y = [](double sum, const iue::rnd::Triangle& tri) {
|
||||
const auto& [a, b, c] = tri;
|
||||
return sum + a[1] + b[1] + c[1];
|
||||
};
|
||||
auto abcy_mean = std::accumulate(items.begin(), items.end(), 0.0, get_y) / items.size() / 3.0;
|
||||
assert(iue::num::isclose(abcy_mean, 1.5, 1e3 / N));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user