diff --git a/ALFI/ALFI/dist.h b/ALFI/ALFI/dist.h index 243c99e..8e19865 100644 --- a/ALFI/ALFI/dist.h +++ b/ALFI/ALFI/dist.h @@ -9,6 +9,8 @@ namespace alfi::dist { enum class Type { GENERAL, UNIFORM, + QUADRATIC, + CUBIC, CHEBYSHEV, CHEBYSHEV_STRETCHED, CHEBYSHEV_ELLIPSE, @@ -32,6 +34,65 @@ namespace alfi::dist { return points; } + /** + @brief Generates a distribution of \p n points on the segment `[a, b]` using two quadratic polynomials. + + The following transform function \f(f\f): + \f[ + f(x) = \begin{cases} + (x+1)^2 - 1, & x \leq 0 \\ + -(x-1)^2 + 1, & x > 0 + \end{cases} + \f] + is applied to `n` points uniformly distributed on the segment `[-1, 1]`, mapping them onto the same segment.\n + The resulting points are then linearly mapped to the target segment `[a, b]`. + + @param n number of points + @param a left boundary of the segment + @param b right boundary of the segment + @return a container with \p n points distributed on the segment `[a, b]` according to the transform function + */ + template class Container = DefaultContainer> + Container quadratic(SizeT n, Number a, Number b) { + if (n == 1) + return {(a+b)/2}; + Container points(n); + for (SizeT i = 0; i < n; ++i) { + const Number x = 2 * static_cast(i) / (static_cast(n) - 1) - 1; + const Number value = x <= 0 ? x * (x + 2) : -x * (x - 2); + points[i] = a + (b - a) * (1 + value) / 2; + } + return points; + } + + /** + @brief Generates a distribution of \p n points on the segment `[a, b]` using cubic polynomial. + + The following transform function \f(f\f): + \f[ + f(x) = -0.5x^3 + 1.5x + \f] + is applied to `n` points uniformly distributed on the segment `[-1, 1]`, mapping them onto the same segment.\n + The resulting points are then linearly mapped to the target segment `[a, b]`. + + @param n number of points + @param a left boundary of the segment + @param b right boundary of the segment + @return a container with \p n points distributed on the segment `[a, b]` according to the transform function + */ + template class Container = DefaultContainer> + Container cubic(SizeT n, Number a, Number b) { + if (n == 1) + return {(a+b)/2}; + Container points(n); + for (SizeT i = 0; i < n; ++i) { + const Number x = 2 * static_cast(i) / (static_cast(n) - 1) - 1; + const Number value = (3 - x*x) * x / 2; + points[i] = a + (b - a) * (1 + value) / 2; + } + return points; + } + template class Container = DefaultContainer> Container chebyshev(SizeT n, Number a, Number b) { if (n == 1) @@ -195,6 +256,10 @@ namespace alfi::dist { template class Container = DefaultContainer> Container of_type(Type type, SizeT n, Number a, Number b, Number parameter = NAN) { switch (type) { + case Type::QUADRATIC: + return quadratic(n, a, b); + case Type::CUBIC: + return cubic(n, a, b); case Type::CHEBYSHEV: return chebyshev(n, a, b); case Type::CHEBYSHEV_STRETCHED: diff --git a/examples/dist_QCustomPlot/dist_QCustomPlot.cpp b/examples/dist_QCustomPlot/dist_QCustomPlot.cpp index 59d9751..0117770 100644 --- a/examples/dist_QCustomPlot/dist_QCustomPlot.cpp +++ b/examples/dist_QCustomPlot/dist_QCustomPlot.cpp @@ -183,6 +183,8 @@ class PlotWindow final : public QWidget { const QVector>> distributions = { {"Uniform", alfi::dist::uniform(n, a, b)}, + {"Quadratic", alfi::dist::quadratic(n, a, b)}, + {"Cubic", alfi::dist::cubic(n, a, b)}, {"Chebyshev", alfi::dist::chebyshev(n, a, b)}, {"Stretched Chebyshev", alfi::dist::chebyshev_stretched(n, a, b)}, {"Chebyshev Ellipse", alfi::dist::chebyshev_ellipse(n, a, b, B)}, diff --git a/examples/dist_gnuplot/dist_gnuplot.cpp b/examples/dist_gnuplot/dist_gnuplot.cpp index 83e171e..02f9908 100644 --- a/examples/dist_gnuplot/dist_gnuplot.cpp +++ b/examples/dist_gnuplot/dist_gnuplot.cpp @@ -67,6 +67,8 @@ int main() { plot_data({ {"Uniform", alfi::dist::uniform(n, a, b)}, + {"Quadratic", alfi::dist::quadratic(n, a, b)}, + {"Cubic", alfi::dist::cubic(n, a, b)}, {"Chebyshev", alfi::dist::chebyshev(n, a, b)}, {"Stretched Chebyshev", alfi::dist::chebyshev_stretched(n, a, b)}, {"Chebyshev Ellipse", alfi::dist::chebyshev_ellipse(n, a, b, ratio)}, diff --git a/examples/interpolation/interpolation.cpp b/examples/interpolation/interpolation.cpp index f538e41..cc80a1b 100644 --- a/examples/interpolation/interpolation.cpp +++ b/examples/interpolation/interpolation.cpp @@ -73,9 +73,9 @@ class PlotWindow final : public QWidget { PlotWindow() { static const QStringList distribution_types { - "Uniform", "Chebyshev", "Chebyshev Stretched", "Chebyshev Ellipse", "Chebyshev Ellipse Stretched", - "Circle Projection", "Ellipse Projection", "Logistic", "Stretched Logistic", - "Error Function", "Stretched Error Function" + "Uniform", "Quadratic", "Cubic", "Chebyshev", "Stretched Chebyshev", + "Chebyshev Ellipse", "Stretched Chebyshev Ellipse", "Circle Projection", "Ellipse Projection", + "Logistic", "Stretched Logistic", "Error Function", "Stretched Error Function" }; _plot = new QCustomPlot(); @@ -262,6 +262,8 @@ class PlotWindow final : public QWidget { std::vector X; switch (static_cast(dist_type)) { case alfi::dist::Type::UNIFORM: X = alfi::dist::uniform(N, a, b); break; + case alfi::dist::Type::QUADRATIC: X = alfi::dist::quadratic(N, a, b); break; + case alfi::dist::Type::CUBIC: X = alfi::dist::cubic(N, a, b); break; case alfi::dist::Type::CHEBYSHEV: X = alfi::dist::chebyshev(N, a, b); break; case alfi::dist::Type::CHEBYSHEV_STRETCHED: X = alfi::dist::chebyshev_stretched(N, a, b); break; case alfi::dist::Type::CHEBYSHEV_ELLIPSE: X = alfi::dist::chebyshev_ellipse(N, a, b, 2.0); break; diff --git a/tests/dist/test_dist.cpp b/tests/dist/test_dist.cpp index 40bc59f..6e67a06 100644 --- a/tests/dist/test_dist.cpp +++ b/tests/dist/test_dist.cpp @@ -38,6 +38,14 @@ TEST(DistributionsTest, Uniform) { test_distribution("uniform", alfi::dist::Type::UNIFORM, 1e-15); } +TEST(DistributionsTest, Quadratic) { + test_distribution("quadratic", alfi::dist::Type::QUADRATIC, 1e-15); +} + +TEST(DistributionsTest, Cubic) { + test_distribution("cubic", alfi::dist::Type::CUBIC, 1e-15); +} + TEST(DistributionsTest, Chebyshev) { test_distribution("chebyshev", alfi::dist::Type::CHEBYSHEV, 1e-15); } diff --git a/tests/test_data b/tests/test_data index 087b5c7..183aff9 160000 --- a/tests/test_data +++ b/tests/test_data @@ -1 +1 @@ -Subproject commit 087b5c7a2ec21c7d1a8ef1d10c700429184de1a6 +Subproject commit 183aff9875c4203c60bd5ed90cd6c20618babed3