VCTR
Loading...
Searching...
No Matches
compile_time_random_array.h
1/*
2 ==============================================================================
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 Copyright 2022- by sonible GmbH.
6
7 This file is part of VCTR - Versatile Container Templates Reconceptualized.
8
9 VCTR is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License version 3
11 only, as published by the Free Software Foundation.
12
13 VCTR is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License version 3 for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 version 3 along with VCTR. If not, see <https://www.gnu.org/licenses/>.
20 ==============================================================================
21*/
22
23#pragma once
24
25#include <array>
26#include <cstdint>
27#include <numbers>
28
29#ifdef _MSC_VER
30__pragma(warning(push))
31__pragma(warning(disable:4244)) // conversion from 'long double' to 'T', possible loss of data
32#endif
33#include <gcem.hpp>
34#ifdef _MSC_VER
35__pragma(warning(pop))
36#endif
37
52namespace vctr::random::detail
53{
55consteval auto getTimeFromString (const char* str, int offset)
56{
57 return static_cast<uint32_t> (str[offset] - '0') * 10 + static_cast<uint32_t> (str[offset + 1] - '0');
58}
59
61consteval auto getSeedFromCurrentTime()
62{
63 auto t = __TIME__;
64 return getTimeFromString (t, 0) * 60 * 60 + getTimeFromString (t, 3) * 60 + getTimeFromString (t, 6);
65}
66
72consteval uint32_t uniformDistribution (uint32_t& previous)
73{
74 constexpr uint32_t lce_a = 48271;
75 constexpr uint32_t lce_c = 0;
76 constexpr uint32_t lce_m = std::numeric_limits<int32_t>::max();
77 previous = ((lce_a * previous + lce_c) % lce_m);
78 return previous;
79}
80
82template <typename T>
83consteval T uniformDistribution (T min, T max, uint32_t& seed)
84{
85 auto span = double (max - min);
86 constexpr auto scale = double (std::numeric_limits<int32_t>::max());
87 return T (double (uniformDistribution (seed)) / scale * (span)) + min;
88}
89
94template <size_t size, typename T>
95consteval auto makeArrayWithUniformDistribution (T min, T max, uint32_t seed)
96{
97 std::array<T, size> dst {};
98 for (auto& el : dst)
99 el = uniformDistribution (min, max, seed);
100
101 return dst;
102}
103
110template <size_t size, std::floating_point T>
111consteval auto makeArrayWithNormalDistribution (T mean, T sigma, uint32_t seed)
112{
113 std::array<T, size> dst {};
114
115 for (size_t i = 0; i < size - 1; i += 2)
116 {
117 auto u1 = T (0);
118 auto u2 = T (0);
119
120 // first two uniformly distributed values between [0.0, 1.0] are calculated
121 // u1 must not be zero
122 do
123 {
124 u1 = uniformDistribution (T (0), T (1), seed);
125 u2 = uniformDistribution (T (0), T (1), seed);
126 } while (u1 <= std::numeric_limits<T>::epsilon());
127
128 // from these values two normally distributed values are calculated
129 // these values are then transformed to a general gaussian value to achieve the desired mean and sigma
130 // z1 = sqrt(-2 * ln(u1)) * cos (2 * PI * u2)
131 // z1 = sigma * z1 + mean
132 // z2 = sqrt(-2 * ln(u1)) * sin (2 * PI * u2)
133 // z2 = sigma * z2 + mean
134
135 auto mag = sigma * gcem::sqrt (T (-2) * gcem::log (u1));
136 auto twoPiU2 = std::numbers::pi_v<T> * 2 * u2;
137 dst[i] = mag * gcem::cos (twoPiU2) + mean;
138
139 // in case of odd array sizes, the last value is simply discarded
140 if (i + 1 < size)
141 dst[i + 1] = mag * gcem::sin (twoPiU2) + mean;
142 }
143
144 return dst;
145}
146} // namespace vctr::random::detail
147
148namespace vctr::random
149{
150
156template <size_t size, typename T>
157consteval auto makeArrayWithUniformDistribution (T min, T max, uint32_t seedOffset = 0)
158{
159 return detail::makeArrayWithUniformDistribution<size, T> (min, max, detail::getSeedFromCurrentTime() + seedOffset);
160}
161
165template <size_t size, std::floating_point T>
166consteval auto makeArrayWithNormalDistribution (T mean, T sigma)
167{
168 return detail::makeArrayWithNormalDistribution<size, T> (mean, sigma, detail::getSeedFromCurrentTime());
169}
170
171} // namespace vctr::random
constexpr ExpressionChainBuilder< expressions::Mean > mean
Computes the mean value of the source values.
Definition: Mean.h:242
constexpr ExpressionChainBuilder< expressions::Max > max
Computes the maximum value of the source values.
Definition: Max.h:194
constexpr ExpressionChainBuilder< expressions::Min > min
Computes the minimum value of the source values.
Definition: Min.h:194