RandLib 2.0.0
Probability distributions, fitting, and heavy-tail tools for C++20
Loading...
Searching...
No Matches
triangular.hpp
Go to the documentation of this file.
1#pragma once
2
7
8namespace randlib
9{
10
17template <typename RealType>
18class TriangularRand final : public ContinuousDistribution<RealType>
19{
20 RealType variate(detail::EngineRef g) const override { return (*this)(g); }
21
22 double a = 0;
23 double b = 2;
24 double c = 1;
25 double constForGenerator = 1;
26 double coefGenerator1 = 1;
27 double coefGenerator2 = 1;
28
29 void SetConstantsForGenerator();
30
31public:
32 TriangularRand(double lowerLimit = 0, double mode = 0.5, double upperLimit = 1);
33
34 [[nodiscard]] std::string Name() const override;
35 [[nodiscard]] Support SupportType() const override { return Support::Finite; }
36 [[nodiscard]] RealType MinValue() const override { return a; }
37 [[nodiscard]] RealType MaxValue() const override { return b; }
38
39 void SetParameters(double lowerLimit, double mode, double upperLimit);
40
41 [[nodiscard]] double f(const RealType &x) const override;
42 [[nodiscard]] double logf(const RealType &x) const override;
43 [[nodiscard]] double F(const RealType &x) const override;
44 [[nodiscard]] double S(const RealType &x) const override;
45 template <std::uniform_random_bit_generator G>
46 [[nodiscard]] RealType operator()(G &g) const;
47
48 [[nodiscard]] long double Mean() const override;
49 [[nodiscard]] long double Variance() const override;
50 [[nodiscard]] RealType Median() const override;
51 [[nodiscard]] RealType Mode() const override;
52 [[nodiscard]] long double Skewness() const override;
53 [[nodiscard]] long double ExcessKurtosis() const override;
54
55private:
56 std::complex<double> CFImpl(double t) const override;
57};
58
59} // namespace randlib
60
62
63namespace randlib
64{
65
66template <typename RealType>
67TriangularRand<RealType>::TriangularRand(double lowerLimit, double mode, double upperLimit)
68{
69 SetParameters(lowerLimit, mode, upperLimit);
70}
71
72template <typename RealType>
74{
75 return "Triangular(" + this->toStringWithPrecision(MinValue()) + ", " + this->toStringWithPrecision(Mode()) + ", " +
76 this->toStringWithPrecision(MaxValue()) + ")";
77}
78
79template <typename RealType>
80void TriangularRand<RealType>::SetParameters(double lowerLimit, double mode, double upperLimit)
81{
82 if (!(lowerLimit < upperLimit))
83 throw std::invalid_argument("Triangular distribution: lower limit should be smaller than upper limit");
84 if (!(lowerLimit <= mode && mode <= upperLimit))
85 throw std::invalid_argument("Triangular distribution: mode should lie between the lower and upper limits");
86 a = lowerLimit;
87 c = mode;
88 b = upperLimit;
89 SetConstantsForGenerator();
90}
91
92template <typename RealType>
94{
95 constForGenerator = (c - a) / (b - a);
96 coefGenerator1 = (b - a) * (c - a);
97 coefGenerator2 = (b - a) * (b - c);
98}
99
100template <typename RealType>
101double TriangularRand<RealType>::f(const RealType &x) const
102{
103 if (x < a || x > b)
104 return 0;
105 if (x < c)
106 return 2.0 * (x - a) / coefGenerator1;
107 if (x == c)
108 return 2.0 / (b - a);
109 if (x < b)
110 return 2.0 * (b - x) / coefGenerator2;
111 return 0;
112}
113
114template <typename RealType>
115double TriangularRand<RealType>::logf(const RealType &x) const
116{
117 return std::log(f(x));
118}
119
120template <typename RealType>
121double TriangularRand<RealType>::F(const RealType &x) const
122{
123 if (x <= a)
124 return 0.0;
125 if (x <= c)
126 return (x - a) * (x - a) / coefGenerator1;
127 if (x < b)
128 return 1.0 - (b - x) * (b - x) / coefGenerator2;
129 return 1.0;
130}
131
132template <typename RealType>
133double TriangularRand<RealType>::S(const RealType &x) const
134{
135 if (x <= a)
136 return 1.0;
137 if (x <= c)
138 return 1.0 - (x - a) * (x - a) / coefGenerator1;
139 if (x < b)
140 return (b - x) * (b - x) / coefGenerator2;
141 return 0.0;
142}
143
144template <typename RealType>
145template <std::uniform_random_bit_generator G>
147{
148 RealType U = detail::uniform01<RealType>(g);
149 if (U < constForGenerator)
150 return a + std::sqrt(U * coefGenerator1);
151 return b - std::sqrt((1 - U) * coefGenerator2);
152}
153
154template <typename RealType>
156{
157 return (a + b + c) / 3.0;
158}
159
160template <typename RealType>
162{
163 return (a * (a - b) + b * (b - c) + c * (c - a)) / 18.0;
164}
165
166template <typename RealType>
167std::complex<double> TriangularRand<RealType>::CFImpl(double t) const
168{
169 if (c == a || c == b) {
172 double h = b - a, s = (c == a) ? t : -t;
173 std::complex<double> eish(std::cos(s * h), std::sin(s * h));
174 std::complex<double> y = 2.0 / (h * h) * ((1.0 - eish) / (s * s) + std::complex<double>(0.0, h / s));
175 double shift = (c == a) ? a * t : b * t;
176 return std::complex<double>(std::cos(shift), std::sin(shift)) * y;
177 }
178 double bmc = b - c, bma = b - a, cma = c - a;
179 double at = a * t, bt = b * t, ct = c * t;
180 std::complex<double> x(bmc * std::cos(at), bmc * std::sin(at));
181 std::complex<double> y(bma * std::cos(ct), bma * std::sin(ct));
182 std::complex<double> z(cma * std::cos(bt), cma * std::sin(bt));
183 std::complex<double> numerator = x - y + z;
185 if (t < 1e-10 && std::fabs(numerator.real()) < 1e-10)
186 return 1;
187 double denominator = bma * cma * bmc * t * t;
188 std::complex<double> frac = -numerator / denominator;
189 return frac + frac;
190}
191
192template <typename RealType>
194{
195 if (c + c > a + b)
196 return a + std::sqrt(0.5 * coefGenerator1);
197 return b - std::sqrt(0.5 * coefGenerator2);
198}
199
200template <typename RealType>
202{
203 return c;
204}
205
206template <typename RealType>
208{
209 double numerator = randlib::consts::sqrt2;
210 numerator *= (a + b - c - c);
211 numerator *= (a + a - b - c);
212 numerator *= (a - b - b + c);
213 double denominator = a * (a - b);
214 denominator += b * (b - c);
215 denominator += c * (c - a);
216 denominator *= std::sqrt(denominator);
217 return 0.2 * numerator / denominator;
218}
219
220template <typename RealType>
222{
223 return -0.6;
224}
225
226} // namespace randlib
The ContinuousDistribution class Abstract class for all continuous distributions.
Definition continuous.hpp:22
The TriangularRand class Triangular distribution.
Definition triangular.hpp:19
double F(const RealType &x) const override
Definition triangular.hpp:121
long double Variance() const override
Definition triangular.hpp:161
RealType MinValue() const override
Definition triangular.hpp:36
void SetParameters(double lowerLimit, double mode, double upperLimit)
Definition triangular.hpp:80
long double Mean() const override
Definition triangular.hpp:155
RealType operator()(G &g) const
Definition triangular.hpp:146
double logf(const RealType &x) const override
Definition triangular.hpp:115
double S(const RealType &x) const override
Definition triangular.hpp:133
RealType Median() const override
Definition triangular.hpp:193
RealType Mode() const override
Mode is the value, which has the largest probability to happen, or, in the case of continuous distrib...
Definition triangular.hpp:201
long double ExcessKurtosis() const override
Definition triangular.hpp:221
Support SupportType() const override
Definition triangular.hpp:35
TriangularRand(double lowerLimit=0, double mode=0.5, double upperLimit=1)
Definition triangular.hpp:67
std::string Name() const override
Definition triangular.hpp:73
RealType MaxValue() const override
Definition triangular.hpp:37
double f(const RealType &x) const override
Definition triangular.hpp:101
long double Skewness() const override
Definition triangular.hpp:207
The EngineRef class Non-owning, type-erased reference to any uniform random bit generator.
Definition engine/uniform.hpp:116
constexpr long double sqrt2
Definition constants.hpp:27
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Definition bivariate_normal.hpp:10
Support
Shape of the support of a univariate distribution.
Definition univariate.hpp:15