The OpenD Programming Language

wsum

Computes the weighted sum of the input.

Parameters

summation

algorithm for calculating sums (default: Summation.appropriate)

Return Value

The weighted sum of all the elements in the input

Examples

import mir.complex;
import mir.math.common: approxEqual;
import mir.ndslice.slice: sliced;
import mir.test: should;
alias C = Complex!double;

wsum([1, 2, 3], [1, 2, 3]).should == (1 + 4 + 9);
wsum([C(1, 3), C(2), C(3)], [1, 2, 3]).should == C((1 + 4 + 9), 3);

wsum!float([0, 1, 2, 3, 4, 5].sliced(3, 2), [1, 2, 3, 4, 5, 6].sliced(3, 2)).should == 70;

static assert(is(typeof(wmean!float([1, 2, 3], [1, 2, 3])) == float));

If weights are not provided, then behaves like sum

import mir.complex;
import mir.ndslice.slice: sliced;
import mir.test: should;
alias C = Complex!double;

wsum([1.0, 2, 3]).should == 6;
wsum([C(1, 3), C(2), C(3)]).should == C(6, 3);

wsum!float([0, 1, 2, 3, 4, 5].sliced(3, 2)).should == 15;

static assert(is(typeof(wsum!float([1, 2, 3])) == float));

Weighted sum of vector

import mir.ndslice.slice: sliced;
import mir.ndslice.topology: iota, map;
import mir.test: should;

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;
auto w = iota([12], 1);

x.wsum.should == 29.25;
x.wsum(w).should == 203;

Weighted sum of matrix

import mir.ndslice.fuse: fuse;
import mir.ndslice.topology: iota;
import mir.test: should;

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;
auto w = iota([2, 6], 1);

x.wsum.should == 29.25;
x.wsum(w).should == 203;

Column sum of matrix

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

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;
auto w = iota([2], 1).universal;
auto result = [4, 16, 11.5, 4, 6.5, 4.25];

// Use byDim or alongDim with map to compute sum of row/column.
assert(x.byDim!1.map!(a => a.wsum(w)).all!approxEqual(result));
assert(x.alongDim!0.map!(a => a.wsum(w)).all!approxEqual(result));

// FIXME
// Without using map, computes the sum of the whole slice
// assert(x.byDim!1.wsum(w) == x.sliced.wsum);
// assert(x.alongDim!0.wsum(w) == x.sliced.wsum);

Can also set algorithm or output type

import mir.ndslice.slice: sliced;
import mir.ndslice.topology: repeat, universal;
import mir.test: should;

//Set sum algorithm (also for weights) or output type

auto a = [1, 1e100, 1, -1e100].sliced;

auto x = a * 10_000;
auto w1 = [1, 1, 1, 1].sliced;
auto w2 = [0.25, 0.25, 0.25, 0.25].sliced;

x.wsum!"kbn"(w1).should == 20_000;
x.wsum!"kbn"(w2).should == 20_000 / 4;
x.wsum!"kb2"(w1).should == 20_000;
x.wsum!"precise"(w1).should == 20_000;
x.wsum!(double, "precise")(w1).should == 20_000;

auto y = uint.max.repeat(3);
y.wsum!ulong([1, 1, 1].sliced.universal).should == 12884901885;

wsum works for complex numbers and other user-defined types

import mir.complex;
import mir.ndslice.slice: sliced;
import mir.test: should;
alias C = Complex!double;

auto x = [C(1.0, 2), C(2, 3), C(3, 4), C(4, 5)].sliced;
auto w = [1, 2, 3, 4].sliced;
x.wsum(w).should == C(30, 40);

Compute weighted sum tensors along specified dimention of tensors

import mir.ndslice.fuse: fuse;
import mir.ndslice.slice: sliced;
import mir.ndslice.topology: alongDim, as, iota, map, universal;
/++
  [[0,1,2],
   [3,4,5]]
 +/
auto x = [
    [0, 1, 2],
    [3, 4, 5]
].fuse.as!double;
auto w = [
    [1, 2, 3],
    [4, 5, 6]
].fuse;
auto w1 = [1, 2].sliced.universal;
auto w2 = [1, 2, 3].sliced;

assert(x.wsum(w) == 70);

auto m0 = [(0 + 6), (1 + 8), (2 + 10)];
assert(x.alongDim!0.map!(a => a.wsum(w1)) == m0);
assert(x.alongDim!(-2).map!(a => a.wsum(w1)) == m0);

auto m1 = [(0 + 2 + 6), (3 + 8 + 15)];
assert(x.alongDim!1.map!(a => a.wsum(w2)) == m1);
assert(x.alongDim!(-1).map!(a => a.wsum(w2)) == m1);

See Also

$(MATHREF sum, Summation)

Meta