ALFI
Advanced Library for Function Interpolation
Loading...
Searching...
No Matches
dist.h
Go to the documentation of this file.
1#pragma once
2
3#include <cmath>
4
5#include "config.h"
6#include "util/points.h"
7
8namespace alfi::dist {
25
26 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
27 Container<Number> uniform(SizeT n, Number a, Number b) {
28 if (n == 1)
29 return {(a+b)/2};
30 Container<Number> points(n);
31 for (SizeT i = 0; i < n; ++i) {
32 points[i] = a + (b - a) * static_cast<Number>(i) / static_cast<Number>(n - 1);
33 }
34 return points;
35 }
36
55 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
56 Container<Number> quadratic(SizeT n, Number a, Number b) {
57 if (n == 1)
58 return {(a+b)/2};
59 Container<Number> points(n);
60 for (SizeT i = 0; i < n; ++i) {
61 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
62 const Number value = x <= 0 ? x * (x + 2) : -x * (x - 2);
63 points[i] = a + (b - a) * (1 + value) / 2;
64 }
65 return points;
66 }
67
83 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
84 Container<Number> cubic(SizeT n, Number a, Number b) {
85 if (n == 1)
86 return {(a+b)/2};
87 Container<Number> points(n);
88 for (SizeT i = 0; i < n; ++i) {
89 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
90 const Number value = (3 - x*x) * x / 2;
91 points[i] = a + (b - a) * (1 + value) / 2;
92 }
93 return points;
94 }
95
96 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
97 Container<Number> chebyshev(SizeT n, Number a, Number b) {
98 if (n == 1)
99 return {(a+b)/2};
100 Container<Number> points(n);
101 for (SizeT i = 0; i < n; ++i) {
102 const Number x = std::cos(M_PI * (2 * (static_cast<Number>(n) - static_cast<Number>(i)) - 1) / (2 * static_cast<Number>(n)));
103 points[i] = a + (x + 1) * (b - a) / 2;
104 }
105 return points;
106 }
107
108 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
109 Container<Number> chebyshev_stretched(SizeT n, Number a, Number b) {
110 return points::stretched<Number,Container>(chebyshev(n, a, b), a, b);
111 }
112
113 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
114 Container<Number> chebyshev_ellipse(SizeT n, Number a, Number b, Number ratio) {
115 Container<Number> points(n);
116 for (SizeT i = 0; i < n / 2; ++i) {
117 const Number theta = M_PI * (2 * static_cast<Number>(i) + 1) / (2 * static_cast<Number>(n));
118 const Number x = 1 / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
119 points[i] = a + (1 - x) * (b - a) / 2;
120 points[n-1-i] = a + (1 + x) * (b - a) / 2;
121 }
122 if (n % 2 == 1)
123 points[n/2] = (a+b)/2;
124 return points;
125 }
126
127 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
128 Container<Number> chebyshev_ellipse_stretched(SizeT n, Number a, Number b, Number ratio) {
129 return points::stretched<Number,Container>(chebyshev_ellipse(n, a, b, ratio), a, b);
130 }
131
132 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
133 Container<Number> circle_proj(SizeT n, Number a, Number b) {
134 if (n == 1)
135 return {(a+b)/2};
136 Container<Number> points(n);
137 for (SizeT i = 0; i < n; ++i) {
138 const Number x = 1 - std::cos(M_PI * static_cast<Number>(i) / (static_cast<Number>(n) - 1));
139 points[i] = a + (b - a) * x / 2;
140 }
141 return points;
142 }
143
144 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
145 Container<Number> ellipse_proj(SizeT n, Number a, Number b, Number ratio) {
146 Container<Number> points(n);
147 for (SizeT i = 0; i < n / 2; ++i) {
148 const Number theta = M_PI * static_cast<Number>(i) / (static_cast<Number>(n) - 1);
149 const Number x = 1 / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
150 points[i] = (1 - x) * (b - a) / 2 + a;
151 points[n-1-i] = (1 + x) * (b - a) / 2 + a;
152 }
153 if (n % 2 == 1)
154 points[n/2] = (a+b)/2;
155 return points;
156 }
157
181 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
182 Container<Number> logistic(SizeT n, Number a, Number b, Number steepness) {
183 if (n == 1)
184 return {(a+b)/2};
185 Container<Number> points(n);
186 for (SizeT i = 0; i < n; ++i) {
187 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
188 const Number logisticValue = 1 / (1 + std::exp(-steepness * x));
189 points[i] = a + (b - a) * logisticValue;
190 }
191 return points;
192 }
193
194 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
195 Container<Number> logistic_stretched(SizeT n, Number a, Number b, Number steepness) {
196 if (n == 0)
197 return {};
198 if (n == 1)
199 return {(a+b)/2};
200 Container<Number> points(n);
201 const Number stretch_factor = 1 - 2 / (1 + std::exp(steepness));
202 for (SizeT i = 1; i < n - 1; ++i) {
203 const Number x = 2 * static_cast<double>(i) / (static_cast<Number>(n) - 1) - 1;
204 const Number logisticValue = 1 / (1 + std::exp(-steepness * x));
205 const Number stretched = (logisticValue - 1 / (1 + std::exp(steepness))) / stretch_factor;
206 points[i] = a + (b - a) * stretched;
207 }
208 points[0] = a;
209 points[n-1] = b;
210 return points;
211 }
212
236 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
237 Container<Number> erf(SizeT n, Number a, Number b, Number steepness) {
238 if (n == 0)
239 return {};
240 if (n == 1)
241 return {(a+b)/2};
242 Container<Number> points(n);
243 for (SizeT i = 0; i < n; ++i) {
244 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
245 const Number erf_value = std::erf(steepness * x);
246 points[i] = a + (b - a) * (1 + erf_value) / 2;
247 }
248 return points;
249 }
250
251 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
252 Container<Number> erf_stretched(SizeT n, Number a, Number b, Number steepness) {
253 return points::stretched<Number,Container>(erf(n, a, b, steepness), a, b);
254 }
255
256 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
257 Container<Number> of_type(Type type, SizeT n, Number a, Number b, Number parameter = NAN) {
258 switch (type) {
259 case Type::QUADRATIC:
260 return quadratic(n, a, b);
261 case Type::CUBIC:
262 return cubic(n, a, b);
263 case Type::CHEBYSHEV:
264 return chebyshev(n, a, b);
266 return chebyshev_stretched(n, a, b);
268 return chebyshev_ellipse(n, a, b, parameter);
270 return chebyshev_ellipse_stretched(n, a, b, parameter);
272 return circle_proj(n, a, b);
274 return ellipse_proj(n, a, b, parameter);
275 case Type::LOGISTIC:
276 return logistic(n, a, b, parameter);
278 return logistic_stretched(n, a, b, parameter);
279 case Type::ERF:
280 return erf(n, a, b, parameter);
282 return erf_stretched(n, a, b, parameter);
283 case Type::UNIFORM:
284 case Type::GENERAL:
285 default:
286 return uniform(n, a, b);
287 }
288 }
289}
Definition dist.h:8
Container< Number > chebyshev_ellipse_stretched(SizeT n, Number a, Number b, Number ratio)
Definition dist.h:128
Container< Number > of_type(Type type, SizeT n, Number a, Number b, Number parameter=NAN)
Definition dist.h:257
Container< Number > logistic(SizeT n, Number a, Number b, Number steepness)
Generates a distribution of n points on the interval (a, b) using the logistic function.
Definition dist.h:182
Container< Number > erf_stretched(SizeT n, Number a, Number b, Number steepness)
Definition dist.h:252
Type
Definition dist.h:9
@ LOGISTIC_STRETCHED
Definition dist.h:21
@ ERF_STRETCHED
Definition dist.h:23
@ ERF
Definition dist.h:22
@ ELLIPSE_PROJECTION
Definition dist.h:19
@ LOGISTIC
Definition dist.h:20
@ UNIFORM
Definition dist.h:11
@ QUADRATIC
Definition dist.h:12
@ GENERAL
Definition dist.h:10
@ CHEBYSHEV_STRETCHED
Definition dist.h:15
@ CUBIC
Definition dist.h:13
@ CHEBYSHEV_ELLIPSE_STRETCHED
Definition dist.h:17
@ CHEBYSHEV_ELLIPSE
Definition dist.h:16
@ CIRCLE_PROJECTION
Definition dist.h:18
@ CHEBYSHEV
Definition dist.h:14
Container< Number > chebyshev(SizeT n, Number a, Number b)
Definition dist.h:97
Container< Number > circle_proj(SizeT n, Number a, Number b)
Definition dist.h:133
Container< Number > ellipse_proj(SizeT n, Number a, Number b, Number ratio)
Definition dist.h:145
Container< Number > uniform(SizeT n, Number a, Number b)
Definition dist.h:27
Container< Number > cubic(SizeT n, Number a, Number b)
Generates a distribution of n points on the segment [a, b] using cubic polynomial.
Definition dist.h:84
Container< Number > chebyshev_ellipse(SizeT n, Number a, Number b, Number ratio)
Definition dist.h:114
Container< Number > logistic_stretched(SizeT n, Number a, Number b, Number steepness)
Definition dist.h:195
Container< Number > erf(SizeT n, Number a, Number b, Number steepness)
Generates a distribution of n points on the interval (a, b) using the error function.
Definition dist.h:237
Container< Number > quadratic(SizeT n, Number a, Number b)
Generates a distribution of n points on the segment [a, b] using two quadratic polynomials.
Definition dist.h:56
Container< Number > chebyshev_stretched(SizeT n, Number a, Number b)
Definition dist.h:109
Definition points.h:5
Container< Number > stretched(const Container< Number > &points, Number a, Number b)
Definition points.h:38
ALFI_DEFAULT_NUMBER DefaultNumber
Definition config.h:17
ALFI_SIZE_TYPE SizeT
Definition config.h:22
ALFI_DEFAULT_CONTAINER< Number > DefaultContainer
Definition config.h:20