The OpenD Programming Language

centralMoment

Calculates the n-th central moment of the input.

By default, if F is not floating point type or complex type, then the result will have a double type if F is implicitly convertible to a floating point type or a type for which isComplex!F is true.

Parameters

N

controls n-th central moment

summation

algorithm for calculating sums (default: Summation.appropriate)

Return Value

The n-th central moment of the input, must be floating point or complex type

Examples

Basic implementation

import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;

assert(centralMoment!2([1.0, 2, 3]).approxEqual(2.0 / 3));
assert(centralMoment!3([1.0, 2, 3]).approxEqual(0.0 / 3));

assert(centralMoment!(float, 2)([0, 1, 2, 3, 4, 5].sliced(3, 2)).approxEqual(17.5f / 6));
static assert(is(typeof(centralMoment!(float, 2)([1, 2, 3])) == float));

Central Moment of vector

import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;

auto x = [0.0, 1.0, 1.5, 2.0, 3.5, 4.25,
          2.0, 7.5, 5.0, 1.0, 1.5, 0.0].sliced;

assert(x.centralMoment!2.approxEqual(54.76562 / 12));

Central Moment of matrix

import mir.math.common: approxEqual;
import mir.ndslice.fuse: fuse;

auto x = [
    [0.0, 1.0, 1.5, 2.0, 3.5, 4.25],
    [2.0, 7.5, 5.0, 1.0, 1.5, 0.0]
].fuse;

assert(x.centralMoment!2.approxEqual(54.76562 / 12));

Can also set algorithm or output type

import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;
import mir.ndslice.topology: repeat;
import mir.stat.transform: center;

//Set sum algorithm or output type

auto a = [1.0, 1e100, 1, -1e100].sliced;
auto b = a * 10_000;
auto x = b.center;

/++
Due to Floating Point precision, when centering `x`, subtracting the mean 
from the second and fourth numbers has no effect. Further, after centering 
and squaring `x`, the first and third numbers in the slice have precision 
too low to be included in the centered sum of squares. 
+/
assert(x.centralMoment!2.approxEqual(2.0e208 / 4));

assert(x.centralMoment!(2, "kbn").approxEqual(2.0e208 / 4));
assert(x.centralMoment!(2, "kb2").approxEqual(2.0e208 / 4));
assert(x.centralMoment!(2, "precise").approxEqual(2.0e208 / 4));
assert(x.centralMoment!(double, 2, "precise").approxEqual(2.0e208 / 4));

auto y = uint.max.repeat(3);
auto z = y.centralMoment!(ulong, 2);
assert(z.approxEqual(0.0));
static assert(is(typeof(z) == double));

centralMoment works for complex numbers and other user-defined types (that are either implicitly convertible to floating point or if isComplex is true)

import mir.ndslice.slice: sliced;
import std.complex: Complex;
import std.math.operations: isClose;

auto x = [Complex!double(1, 2), Complex!double(2, 3), Complex!double(3, 4), Complex!double(4, 5)].sliced;
assert(x.centralMoment!2.isClose(Complex!double(0, 10) / 4));

Arbitrary central moment

import mir.math.common: approxEqual;

assert(centralMoment!2(1.0, 2, 3).approxEqual(2.0 / 3));
assert(centralMoment!(float, 2)(1, 2, 3).approxEqual(2f / 3));

Meta