ALFI
Advanced Library for Function Interpolation
Loading...
Searching...
No Matches
misc.h
Go to the documentation of this file.
1#pragma once
2
3#include <iostream>
4
5#include "config.h"
6#include "dist.h"
7#include "util/numeric.h"
8
9namespace alfi::misc {
10
11 template <typename Number = DefaultNumber, template <typename, typename...> class Container = DefaultContainer>
12 Container<Number> barycentric(
13 const Container<Number>& X,
14 const Container<Number>& Y,
15 const Container<Number>& xx,
17 Number epsilon = std::numeric_limits<Number>::epsilon()
18 ) {
19 if (X.size() != Y.size()) {
20 std::cerr << "Error in function " << __FUNCTION__
21 << ": Vectors X (of size " << X.size()
22 << ") and Y (of size " << Y.size()
23 << ") are not the same size. Returning an empty array..." << std::endl;
24 return {};
25 }
26
27 if (X.empty()) {
28 std::cerr << "Error in function " << __FUNCTION__
29 << ": Vectors X and Y are empty. Cannot interpolate. Returning an empty array..." << std::endl;
30 return {};
31 }
32
33 const auto N = X.size();
34
35 Container<Number> c(N);
36 if (dist_type == dist::Type::UNIFORM) {
37 c[0] = 1;
38 for (SizeT j = 1; j <= N / 2; ++j) {
39 c[j] = -c[j-1] * (static_cast<Number>(N - j)) / static_cast<Number>(j);
40 }
41 for (SizeT j = N / 2 + 1; j < N; ++j) {
42 if (c[j-1] < 0) {
43 c[j] = std::abs(c[N-1-j]);
44 } else {
45 c[j] = -std::abs(c[N-1-j]);
46 }
47 }
48 // TODO: Investigate if normalization is needed.
49 // Normalization is needed because the middle coefficients grow as O(2^n),
50 // while the edges grow as O(1). Dividing by 2^(N/2) balances the exponents,
51 // reducing numerical instability.
52 // const Number norm_factor = std::pow(static_cast<Number>(2), static_cast<Number>(N / 2));
53 // for (SizeT j = 0; j < N; ++j) {
54 // c[j] /= norm_factor;
55 // }
56 } else if (dist_type == dist::Type::CHEBYSHEV) {
57 for (SizeT j = 0; j < N; ++j) {
58 c[j] = (j % 2 == 0 ? 1 : -1) * sin(((2 * static_cast<Number>(j) + 1) * M_PI) / (2 * static_cast<Number>(N)));
59 }
60 } else if (dist_type == dist::Type::CIRCLE_PROJECTION) {
61 for (SizeT j = 0; j < N; ++j) {
62 c[j] = (j % 2 == 0 ? 1 : -1) * (j == 0 || j == N - 1 ? static_cast<Number>(1)/static_cast<Number>(2) : static_cast<Number>(1));
63 }
64 } else {
65 // The factor scales the coefficients to prevent excessive growth or shrinkage, reducing numerical instability.
66 // TODO: Investigate if normalization is needed and refine the scaling factor.
67 // const Number norm_factor = (X[N-1] - X[0]) / static_cast<Number>(2);
68 for (SizeT j = 0; j < N; ++j) {
69 c[j] = 1;
70 for (SizeT k = 0; k < N; ++k) {
71 if (j != k) {
72 // c[i] *= norm_factor / (X[j] - X[k]); // with normalization
73 c[j] /= (X[j] - X[k]);
74 }
75 }
76 }
77 }
78
79 const auto nn = xx.size();
80
81 Container<Number> result(nn);
82
83#if defined(_OPENMP) && !defined(ALFI_DISABLE_OPENMP)
84#pragma omp parallel for
85#endif
86 for (SizeT k = 0; k < nn; ++k) {
87 Number numerator = 0, denominator = 0;
88 SizeT exact_idx = N;
89
90 for (SizeT i = 0; i < N; ++i) {
91 if (util::numeric::are_equal(xx[k], X[i], epsilon)) {
92 exact_idx = i;
93 break;
94 }
95 const auto x_diff = xx[k] - X[i];
96 const auto temp = c[i] / x_diff;
97 numerator += temp * Y[i];
98 denominator += temp;
99 }
100
101 if (exact_idx != N) {
102 result[k] = Y[exact_idx];
103 } else {
104 result[k] = numerator / denominator;
105 }
106 }
107
108 return result;
109 }
110}
Type
Definition dist.h:9
@ UNIFORM
Definition dist.h:11
@ GENERAL
Definition dist.h:10
@ CIRCLE_PROJECTION
Definition dist.h:18
@ CHEBYSHEV
Definition dist.h:14
Definition misc.h:9
Container< Number > barycentric(const Container< Number > &X, const Container< Number > &Y, const Container< Number > &xx, dist::Type dist_type=dist::Type::GENERAL, Number epsilon=std::numeric_limits< Number >::epsilon())
Definition misc.h:12
bool are_equal(Number a, Number b, Number epsilon=std::numeric_limits< Number >::epsilon())
Definition numeric.h:7
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