Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions ALFI/ALFI/dist.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace alfi::dist {
enum class Type {
GENERAL,
UNIFORM,
QUADRATIC,
CUBIC,
CHEBYSHEV,
CHEBYSHEV_STRETCHED,
CHEBYSHEV_ELLIPSE,
Expand All @@ -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 <typename Number = DefaultNumber, template <typename> class Container = DefaultContainer>
Container<Number> quadratic(SizeT n, Number a, Number b) {
if (n == 1)
return {(a+b)/2};
Container<Number> points(n);
for (SizeT i = 0; i < n; ++i) {
const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(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 <typename Number = DefaultNumber, template <typename> class Container = DefaultContainer>
Container<Number> cubic(SizeT n, Number a, Number b) {
if (n == 1)
return {(a+b)/2};
Container<Number> points(n);
for (SizeT i = 0; i < n; ++i) {
const Number x = 2 * static_cast<Number>(i) / (static_cast<Number>(n) - 1) - 1;
const Number value = (3 - x*x) * x / 2;
points[i] = a + (b - a) * (1 + value) / 2;
}
return points;
}

template <typename Number = DefaultNumber, template <typename> class Container = DefaultContainer>
Container<Number> chebyshev(SizeT n, Number a, Number b) {
if (n == 1)
Expand Down Expand Up @@ -195,6 +256,10 @@ namespace alfi::dist {
template <typename Number = DefaultNumber, template <typename> class Container = DefaultContainer>
Container<Number> 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:
Expand Down
2 changes: 2 additions & 0 deletions examples/dist_QCustomPlot/dist_QCustomPlot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class PlotWindow final : public QWidget {

const QVector<std::pair<QString, std::vector<double>>> 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)},
Expand Down
2 changes: 2 additions & 0 deletions examples/dist_gnuplot/dist_gnuplot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)},
Expand Down
8 changes: 5 additions & 3 deletions examples/interpolation/interpolation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -262,6 +262,8 @@ class PlotWindow final : public QWidget {
std::vector<double> X;
switch (static_cast<alfi::dist::Type>(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;
Expand Down
8 changes: 8 additions & 0 deletions tests/dist/test_dist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/test_data
Submodule test_data updated 2 files
+22 −0 dist/dist.toml
+12 −4 dist/generate.py