The OpenD Programming Language

center

Centers slice, which must be a finite iterable.

By default, slice is centered by the mean. A custom function may also be provided using centralTendency.

  1. auto center(Slice!(Iterator, N, kind) slice)
    template center(alias centralTendency = mean!(Summation.appropriate))
    center
    (
    Iterator
    size_t N
    SliceKind kind
    )
    (
    Slice!(Iterator, N, kind) slice
    )
  2. auto center(T x)

Members

Functions

center
auto center(Slice!(Iterator, N, kind) slice)
auto center(T x)

Return Value

The elements in the slice with the average subtracted from them.

Examples

Center vector

import mir.algorithm.iteration: all;
import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;

auto x = [1.0, 2, 3, 4, 5, 6].sliced;
assert(x.center.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));

// Can center using different functions
assert(x.center!hmean.all!approxEqual([-1.44898, -0.44898, 0.55102, 1.55102, 2.55102, 3.55102]));
assert(x.center!gmean.all!approxEqual([-1.99379516, -0.99379516, 0.00620483, 1.00620483, 2.00620483, 3.00620483]));
assert(x.center!median.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));

// center operates lazily, if original slice is changed, then 
auto y = x.center;
assert(y.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));
x[0]++;
assert(y.all!approxEqual([-1.5, -1.5, -0.5, 0.5, 1.5, 2.5]));

Example of lazy behavior of center

import mir.algorithm.iteration: all;
import mir.math.common: approxEqual;
import mir.ndslice.allocation: slice;
import mir.ndslice.slice: sliced;

auto x = [1.0, 2, 3, 4, 5, 6].sliced;
auto y = x.center;
auto z = x.center.slice;
assert(y.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));
x[0]++;
// y changes, while z does not
assert(y.all!approxEqual([-1.5, -1.5, -0.5, 0.5, 1.5, 2.5]));
assert(z.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));   

Center dynamic array

import mir.algorithm.iteration: all;
import mir.math.common: approxEqual;

auto x = [1.0, 2, 3, 4, 5, 6];
assert(x.center.all!approxEqual([-2.5, -1.5, -0.5, 0.5, 1.5, 2.5]));

Center matrix

import mir.algorithm.iteration: all;
import mir.math.common: approxEqual;
import mir.ndslice: fuse;

auto x = [
    [0.0, 1, 2], 
    [3.0, 4, 5]
].fuse;

auto y = [
    [-2.5, -1.5, -0.5], 
    [ 0.5,  1.5,  2.5]
].fuse;

assert(x.center.all!approxEqual(y));

Column center matrix

import mir.algorithm.iteration: all, equal;
import mir.math.common: approxEqual;
import mir.ndslice: fuse;
import mir.ndslice.topology: alongDim, byDim, map;

auto x = [
    [20.0, 100.0, 2000.0],
    [10.0,   5.0,    2.0]
].fuse;

auto result = [
    [ 5.0,  47.5,  999],
    [-5.0, -47.5, -999]
].fuse;

// Use byDim with map to compute average of row/column.
auto xCenterByDim = x.byDim!1.map!center;
auto resultByDim = result.byDim!1;
assert(xCenterByDim.equal!(equal!approxEqual)(resultByDim));

auto xCenterAlongDim = x.alongDim!0.map!center;
auto resultAlongDim = result.alongDim!0;
assert(xCenterByDim.equal!(equal!approxEqual)(resultAlongDim));

Can also pass arguments to average function used by center

import mir.ndslice.slice: sliced;

//Set sum algorithm or output type
auto a = [1, 1e100, 1, -1e100];

auto x = a.sliced * 10_000;

//Due to Floating Point precision, subtracting the mean from the second
//and fourth numbers in `x` does not change the value of the result
auto result = [5000, 1e104, 5000, -1e104].sliced;

assert(x.center!(mean!"kbn") == result);
assert(x.center!(mean!"kb2") == result);
assert(x.center!(mean!"precise") == result);

Passing a centered input to variance or standardDeviation with the assumeZeroMean algorithm is equivalent to calculating variance or standardDeviation on the original input.

import mir.algorithm.iteration: all;
import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;

auto x = [1.0, 2, 3, 4, 5, 6].sliced;
assert(x.center.variance!"assumeZeroMean".approxEqual(x.variance));
assert(x.center.standardDeviation!"assumeZeroMean".approxEqual(x.standardDeviation));

Meta