Report a bug
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

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)[]));
}
```
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.
enum uint `derivativeOrder`;
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);