Report a bug
If you spot a problem with this page, click here to create a Github issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

mir.interpolate.polynomial

Lagrange Barycentric Interpolation

See Also:
Authors:
Ilya Yaroshenko
Examples:
import mir.algorithm.iteration: all;
import mir.math;
import mir.ndslice;

auto f(double x) { return (x-2) * (x-5) * (x-9); }
auto fd(double x) { return (x-5) * (x-9) + (x-2) * (x-5) + (x-2) * (x-9); }
auto fd2(double x) { return (x-5) + (x-9) + (x-2) + (x-5) + (x-2) + (x-9); }
double[2] fWithDerivative(double x) { return [f(x), fd(x)]; }
double[3] fWithTwoDerivatives(double x) { return [f(x), fd(x), fd2(x)]; }

// 
auto x = [0.0, 3, 5, 10];
auto y = x.map!f.slice.field;
// `!2` adds first two derivatives: f, f', and f''
// default parameter is 0
auto l = x.lagrange!2(y);

foreach(test; x ~ [2.0, 5, 9] ~ [double(PI), double(E), 10, 100, 1e3])
foreach(scale; [-1, +1, 1 + double.epsilon, 1 + double.epsilon.sqrt])
foreach(shift; [0, double.min_normal/2, double.min_normal*2, double.epsilon, double.epsilon.sqrt])
{
    auto testX = test * scale + shift;

    auto lx = l(testX);
    auto l_ldx = l.withDerivative(testX);
    auto l_ld_ld2x = l.withTwoDerivatives(testX);

    assert(lx.approxEqual(f(testX)));
    assert(l_ldx[].all!approxEqual(fWithDerivative(testX)[]));
    assert(l_ld_ld2x[].all!approxEqual(fWithTwoDerivatives(testX)[]));
}
public import mir.interpolate : atInterval;
Lagrange!(T, maxDerivative) lagrange(uint maxDerivative = 0, T, X)(scope const X[] x, scope const T[] y)
if (maxDerivative < 16);

@trusted Lagrange!(Unqual!(Slice!(Iterator, 1, kind).DeepElement), maxDerivative, X) lagrange(uint maxDerivative = 0, X, Iterator, SliceKind kind)(Slice!(RCI!(immutable(X))) x, Slice!(Iterator, 1, kind) y)
if (maxDerivative < 16);
Constructs barycentric lagrange interpolant.
struct Lagrange(T, uint maxAdditionalFunctions = 0, X = T) if (isFloatingPoint!T && (maxAdditionalFunctions < 16));
Slice!(RCI!(immutable(X))) _grid;
for internal use only.
RCArray!(immutable(T)) _inversedBarycentricWeights;
for internal use only.
RCArray!T[maxAdditionalFunctions + 1] _normalizedValues;
for internal use only.
T[maxAdditionalFunctions + 1] _asums;
for internal use only.
this(Slice!(RCI!(immutable(X))) grid, RCArray!T values, RCArray!(immutable(T)) inversedBarycentricWeights);

Complexity O(N)

this(Slice!(RCI!(immutable(X))) grid, RCArray!T values);

Complexity O(N^^2)

const @property @trusted Lagrange lightConst()();
immutable @property @trusted Lagrange lightImmutable()();
ref const(Slice!(RCI!(immutable(X)))) grid();
const @property scope @trusted immutable(X)[] gridScopeView() return;
ref const(RCArray!(immutable(T))) inversedBarycentricWeights();
ref const(RCArray!T)[maxAdditionalFunctions + 1] normalizedValues();
ref const(T)[maxAdditionalFunctions + 1] asums();
size_t intervalCount(size_t dimension = 0)();
alias withDerivative = opCall!1;
alias withTwoDerivatives = opCall!2;
@nogc RCArray!(immutable(T)) inversedBarycentricWeights(T)(Slice!(const(T)*) x)
if (isFloatingPoint!T);
@nogc Slice!(T*) polynomialDerivativeValues(T)(return Slice!(T*) d, Slice!(const(T)*) x, Slice!(const(T)*) y, Slice!(const(T)*) w)
if (isFloatingPoint!T);
Computes derivative values in the same points
Parameters:
Slice!(T*) d derivative values (output)
Slice!(const(T)*) y values
Slice!(const(T)*) x grid
Slice!(const(T)*) w inversed barycentric weights
Returns:
Derivative values in the same points
@nogc Slice!(T*) polynomialDerivativeValues(T)(return Slice!(T*) d, Slice!(const(T)*) x, Slice!(const(T)*) y)
if (isFloatingPoint!T);