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 {
35
36 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
37 Container<Number> uniform(SizeT n, const Number& a, const Number& b) {
38 if (n == 1)
39 return {(a+b)/2};
40 Container<Number> points(n);
41 for (SizeT i = 0; i < n; ++i) {
42 points[i] = a + (b - a) * static_cast<Number>(i) / static_cast<Number>(n - 1);
43 }
44 return points;
45 }
46
65 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
66 Container<Number> quadratic(SizeT n, const Number& a, const Number& b) {
67 if (n == 1)
68 return {(a+b)/2};
69 Container<Number> points(n);
70 for (SizeT i = 0; i < n; ++i) {
71 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
72 const Number value = x <= 0 ? x * (x + 2) : -x * (x - 2);
73 points[i] = a + (b - a) * (1 + value) / 2;
74 }
75 return points;
76 }
77
93 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
94 Container<Number> cubic(SizeT n, const Number& a, const Number& b) {
95 if (n == 1)
96 return {(a+b)/2};
97 Container<Number> points(n);
98 for (SizeT i = 0; i < n; ++i) {
99 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
100 const Number value = (3 - x*x) * x / 2;
101 points[i] = a + (b - a) * (1 + value) / 2;
102 }
103 return points;
104 }
105
106 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
107 Container<Number> chebyshev(SizeT n, const Number& a, const Number& b) {
108 if (n == 1)
109 return {(a+b)/2};
110 Container<Number> points(n);
111 for (SizeT i = 0; i < n; ++i) {
112 const Number x = std::cos(M_PI * (2 * (static_cast<Number>(n) - static_cast<Number>(i)) - 1) / (2 * static_cast<Number>(n)));
113 points[i] = a + (x + 1) * (b - a) / 2;
114 }
115 return points;
116 }
117
118 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
119 Container<Number> chebyshev_stretched(SizeT n, const Number& a, const Number& b) {
120 return points::stretched<Number,Container>(chebyshev(n, a, b), a, b);
121 }
122
123 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
124 Container<Number> chebyshev_augmented(SizeT n, const Number& a, const Number& b) {
125 if (n == 0) {
126 return {};
127 }
128 if (n == 1) {
129 return {(a+b)/2};
130 }
131 Container<Number> points(n);
132 Container<Number> c = chebyshev(n - 2, a, b);
133 std::move(c.begin(), c.end(), points.begin() + 1);
134 points[0] = a;
135 points[n-1] = b;
136 return points;
137 }
138
139 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
140 Container<Number> chebyshev_2(SizeT n, const Number& a, const Number& b) {
141 if (n == 1)
142 return {(a+b)/2};
143 Container<Number> points(n);
144 for (SizeT i = 0; i < n; ++i) {
145 const Number x = 1 - std::cos(M_PI * static_cast<Number>(i) / (static_cast<Number>(n) - 1));
146 points[i] = a + (b - a) * x / 2;
147 }
148 return points;
149 }
150
151 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
152 Container<Number> chebyshev_3(SizeT n, const Number& a, const Number& b) {
153 Container<Number> points(n);
154 for (SizeT i = 0; i < n; ++i) {
155 const Number x = 1 - std::cos(M_PI * static_cast<Number>(2*i) / static_cast<Number>(2*n - 1));
156 points[i] = a + (b - a) * x / 2;
157 }
158 return points;
159 }
160
161 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
162 Container<Number> chebyshev_3_stretched(SizeT n, const Number& a, const Number& b) {
164 }
165
166 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
167 Container<Number> chebyshev_4(SizeT n, const Number& a, const Number& b) {
168 Container<Number> points(n);
169 for (SizeT i = 0; i < n; ++i) {
170 const Number x = 1 - std::cos(M_PI * static_cast<Number>(2*i + 1) / static_cast<Number>(2*n - 1));
171 points[i] = a + (b - a) * x / 2;
172 }
173 return points;
174 }
175
176 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
177 Container<Number> chebyshev_4_stretched(SizeT n, const Number& a, const Number& b) {
179 }
180
181 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
182 Container<Number> chebyshev_ellipse(SizeT n, const Number& a, const Number& b, const Number& ratio) {
183 Container<Number> points(n);
184 for (SizeT i = 0; i < n / 2; ++i) {
185 const Number theta = M_PI * (2 * static_cast<Number>(i) + 1) / (2 * static_cast<Number>(n));
186 const Number x = 1 / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
187 points[i] = a + (1 - x) * (b - a) / 2;
188 points[n-1-i] = a + (1 + x) * (b - a) / 2;
189 }
190 if (n % 2 == 1)
191 points[n/2] = (a+b)/2;
192 return points;
193 }
194
195 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
196 Container<Number> chebyshev_ellipse_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
197 return points::stretched<Number,Container>(chebyshev_ellipse(n, a, b, ratio), a, b);
198 }
199
200 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
201 Container<Number> chebyshev_ellipse_augmented(SizeT n, const Number& a, const Number& b, const Number& ratio) {
202 if (n == 0) {
203 return {};
204 }
205 if (n == 1) {
206 return {(a+b)/2};
207 }
208 Container<Number> points(n);
209 Container<Number> c = chebyshev_ellipse(n - 2, a, b, ratio);
210 std::move(c.begin(), c.end(), points.begin() + 1);
211 points[0] = a;
212 points[n-1] = b;
213 return points;
214 }
215
216 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
217 Container<Number> chebyshev_ellipse_2(SizeT n, const Number& a, const Number& b, const Number& ratio) {
218 Container<Number> points(n);
219 for (SizeT i = 0; i < n / 2; ++i) {
220 const Number theta = M_PI * static_cast<Number>(i) / (static_cast<Number>(n) - 1);
221 const Number x = 1 / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
222 points[i] = (1 - x) * (b - a) / 2 + a;
223 points[n-1-i] = (1 + x) * (b - a) / 2 + a;
224 }
225 if (n % 2 == 1)
226 points[n/2] = (a+b)/2;
227 return points;
228 }
229
230 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
231 Container<Number> chebyshev_ellipse_3(SizeT n, const Number& a, const Number& b, const Number& ratio) {
232 Container<Number> points(n);
233 for (SizeT i = 0; i < n; ++i) {
234 const Number theta = M_PI * static_cast<Number>(2*i) / static_cast<Number>(2*n - 1);
235 const Number x = (theta < M_PI/2 ? 1 : -1) / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
236 points[i] = (1 - x) * (b - a) / 2 + a;
237 }
238 return points;
239 }
240
241 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
242 Container<Number> chebyshev_ellipse_3_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
243 return points::stretched<Number,Container>(chebyshev_ellipse_3(n, a, b, ratio), a, b);
244 }
245
246 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
247 Container<Number> chebyshev_ellipse_4(SizeT n, const Number& a, const Number& b, const Number& ratio) {
248 Container<Number> points(n);
249 for (SizeT i = 0; i < n; ++i) {
250 const Number theta = M_PI * static_cast<Number>(2*i + 1) / static_cast<Number>(2*n - 1);
251 const Number x = (theta < M_PI/2 ? 1 : -1) / std::sqrt(1 + std::pow(std::tan(theta) / ratio, 2));
252 points[i] = (1 - x) * (b - a) / 2 + a;
253 }
254 return points;
255 }
256
257 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
258 Container<Number> chebyshev_ellipse_4_stretched(SizeT n, const Number& a, const Number& b, const Number& ratio) {
259 return points::stretched<Number,Container>(chebyshev_ellipse_4(n, a, b, ratio), a, b);
260 }
261
285 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
286 Container<Number> logistic(SizeT n, const Number& a, const Number& b, const Number& steepness) {
287 if (n == 1)
288 return {(a+b)/2};
289 Container<Number> points(n);
290 for (SizeT i = 0; i < n; ++i) {
291 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
292 const Number logisticValue = 1 / (1 + std::exp(-steepness * x));
293 points[i] = a + (b - a) * logisticValue;
294 }
295 return points;
296 }
297
298 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
299 Container<Number> logistic_stretched(SizeT n, const Number& a, const Number& b, const Number& steepness) {
300 if (n == 0)
301 return {};
302 if (n == 1)
303 return {(a+b)/2};
304 Container<Number> points(n);
305 const Number stretch_factor = 1 - 2 / (1 + std::exp(steepness));
306 for (SizeT i = 1; i < n - 1; ++i) {
307 const Number x = 2 * static_cast<double>(i) / (static_cast<Number>(n) - 1) - 1;
308 const Number logisticValue = 1 / (1 + std::exp(-steepness * x));
309 const Number stretched = (logisticValue - 1 / (1 + std::exp(steepness))) / stretch_factor;
310 points[i] = a + (b - a) * stretched;
311 }
312 points[0] = a;
313 points[n-1] = b;
314 return points;
315 }
316
340 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
341 Container<Number> erf(SizeT n, const Number& a, const Number& b, const Number& steepness) {
342 if (n == 0)
343 return {};
344 if (n == 1)
345 return {(a+b)/2};
346 Container<Number> points(n);
347 for (SizeT i = 0; i < n; ++i) {
348 const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
349 const Number erf_value = std::erf(steepness * x);
350 points[i] = a + (b - a) * (1 + erf_value) / 2;
351 }
352 return points;
353 }
354
355 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
356 Container<Number> erf_stretched(SizeT n, const Number& a, const Number& b, const Number& steepness) {
357 return points::stretched<Number,Container>(erf(n, a, b, steepness), a, b);
358 }
359
360 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
361 Container<Number> of_type(Type type, SizeT n, const Number& a, const Number& b, const Number& parameter = NAN) {
362 switch (type) {
363 case Type::QUADRATIC:
364 return quadratic(n, a, b);
365 case Type::CUBIC:
366 return cubic(n, a, b);
367 case Type::CHEBYSHEV:
368 return chebyshev(n, a, b);
370 return chebyshev_stretched(n, a, b);
372 return chebyshev_augmented(n, a, b);
374 return chebyshev_2(n, a, b);
376 return chebyshev_3(n, a, b);
378 return chebyshev_3_stretched(n, a, b);
380 return chebyshev_4(n, a, b);
382 return chebyshev_4_stretched(n, a, b);
384 return chebyshev_ellipse(n, a, b, parameter);
386 return chebyshev_ellipse_stretched(n, a, b, parameter);
388 return chebyshev_ellipse_augmented(n, a, b, parameter);
390 return chebyshev_ellipse_2(n, a, b, parameter);
392 return chebyshev_ellipse_3(n, a, b, parameter);
394 return chebyshev_ellipse_3_stretched(n, a, b, parameter);
396 return chebyshev_ellipse_4(n, a, b, parameter);
398 return chebyshev_ellipse_4_stretched(n, a, b, parameter);
399 case Type::LOGISTIC:
400 return logistic(n, a, b, parameter);
402 return logistic_stretched(n, a, b, parameter);
403 case Type::ERF:
404 return erf(n, a, b, parameter);
406 return erf_stretched(n, a, b, parameter);
407 case Type::UNIFORM:
408 case Type::GENERAL:
409 default:
410 return uniform(n, a, b);
411 }
412 }
413}
Definition dist.h:8
Container< Number > chebyshev_ellipse_4_stretched(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:258
Container< Number > uniform(SizeT n, const Number &a, const Number &b)
Definition dist.h:37
Container< Number > chebyshev(SizeT n, const Number &a, const Number &b)
Definition dist.h:107
Container< Number > chebyshev_3(SizeT n, const Number &a, const Number &b)
Definition dist.h:152
Container< Number > chebyshev_ellipse_2(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:217
Container< Number > chebyshev_ellipse(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:182
Container< Number > chebyshev_stretched(SizeT n, const Number &a, const Number &b)
Definition dist.h:119
Type
Definition dist.h:9
@ LOGISTIC_STRETCHED
Definition dist.h:31
@ ERF_STRETCHED
Definition dist.h:33
@ CHEBYSHEV_ELLIPSE_4_STRETCHED
Definition dist.h:29
@ CHEBYSHEV_ELLIPSE_4
Definition dist.h:28
@ ERF
Definition dist.h:32
@ CHEBYSHEV_ELLIPSE_AUGMENTED
Definition dist.h:24
@ CHEBYSHEV_ELLIPSE_3_STRETCHED
Definition dist.h:27
@ LOGISTIC
Definition dist.h:30
@ UNIFORM
Definition dist.h:11
@ CHEBYSHEV_ELLIPSE_3
Definition dist.h:26
@ CHEBYSHEV_3_STRETCHED
Definition dist.h:19
@ CHEBYSHEV_4
Definition dist.h:20
@ QUADRATIC
Definition dist.h:12
@ CHEBYSHEV_4_STRETCHED
Definition dist.h:21
@ GENERAL
Definition dist.h:10
@ CHEBYSHEV_STRETCHED
Definition dist.h:15
@ CUBIC
Definition dist.h:13
@ CHEBYSHEV_AUGMENTED
Definition dist.h:16
@ CHEBYSHEV_ELLIPSE_STRETCHED
Definition dist.h:23
@ CHEBYSHEV_ELLIPSE
Definition dist.h:22
@ CHEBYSHEV_3
Definition dist.h:18
@ CHEBYSHEV_ELLIPSE_2
Definition dist.h:25
@ CHEBYSHEV_2
Definition dist.h:17
@ CHEBYSHEV
Definition dist.h:14
Container< Number > of_type(Type type, SizeT n, const Number &a, const Number &b, const Number &parameter=NAN)
Definition dist.h:361
Container< Number > logistic_stretched(SizeT n, const Number &a, const Number &b, const Number &steepness)
Definition dist.h:299
Container< Number > cubic(SizeT n, const Number &a, const Number &b)
Generates a distribution of n points on the segment [a, b] using cubic polynomial.
Definition dist.h:94
Container< Number > logistic(SizeT n, const Number &a, const Number &b, const Number &steepness)
Generates a distribution of n points on the interval (a, b) using the logistic function.
Definition dist.h:286
Container< Number > chebyshev_ellipse_4(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:247
Container< Number > quadratic(SizeT n, const Number &a, const Number &b)
Generates a distribution of n points on the segment [a, b] using two quadratic polynomials.
Definition dist.h:66
Container< Number > erf(SizeT n, const Number &a, const Number &b, const Number &steepness)
Generates a distribution of n points on the interval (a, b) using the error function.
Definition dist.h:341
Container< Number > chebyshev_ellipse_3(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:231
Container< Number > chebyshev_4_stretched(SizeT n, const Number &a, const Number &b)
Definition dist.h:177
Container< Number > erf_stretched(SizeT n, const Number &a, const Number &b, const Number &steepness)
Definition dist.h:356
Container< Number > chebyshev_augmented(SizeT n, const Number &a, const Number &b)
Definition dist.h:124
Container< Number > chebyshev_ellipse_stretched(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:196
Container< Number > chebyshev_ellipse_augmented(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:201
Container< Number > chebyshev_2(SizeT n, const Number &a, const Number &b)
Definition dist.h:140
Container< Number > chebyshev_3_stretched(SizeT n, const Number &a, const Number &b)
Definition dist.h:162
Container< Number > chebyshev_4(SizeT n, const Number &a, const Number &b)
Definition dist.h:167
Container< Number > chebyshev_ellipse_3_stretched(SizeT n, const Number &a, const Number &b, const Number &ratio)
Definition dist.h:242
Definition points.h:5
Container< Number > stretched(const Container< Number > &points, const Number &a, const 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