controls type of output
algorithm for calculating covariance (default: CovarianceAlgo.hybrid)
algorithm for calculating sums (default: Summation.appropriate)
The covariance of the inputs
Covariance of vectors
import mir.ndslice.slice: sliced; import mir.test: shouldApprox; 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 y = [-0.75, 6.0, -0.25, 8.25, 5.75, 3.5, 9.25, -0.75, 2.5, 1.25, -1, 2.25].sliced; x.covariance(y, true).shouldApprox == -5.5 / 12; x.covariance(y).shouldApprox == -5.5 / 11;
Can also set algorithm type
import mir.math.common: approxEqual; import mir.ndslice.slice: sliced; import mir.test: shouldApprox; auto a = [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 b = [-0.75, 6.0, -0.25, 8.25, 5.75, 3.5, 9.25, -0.75, 2.5, 1.25, -1, 2.25].sliced; auto x = a + 10.0 ^^ 9; auto y = b + 10.0 ^^ 9; x.covariance(y).shouldApprox == -5.5 / 11; // The naive algorithm is numerically unstable in this case assert(!x.covariance!"naive"(y).approxEqual(-5.5 / 11)); // The two-pass algorithm provides the same answer as hybrid x.covariance!"twoPass"(y).shouldApprox == -5.5 / 11; // And the assumeZeroMean algorithm is way off assert(!x.covariance!"assumeZeroMean"(y).approxEqual(-5.5 / 11));
Can also set algorithm or output type
import mir.ndslice.slice: sliced; import mir.ndslice.topology: repeat; import mir.test: shouldApprox; //Set population covariance, covariance algorithm, sum algorithm or output type auto a = [1.0, 1e100, 1, -1e100].sliced; auto b = [1.0e100, 1, 1, -1e100].sliced; auto x = a * 10_000; auto y = b * 10_000; /++ Due to Floating Point precision, when centering `x`, subtracting the mean from the second and fourth numbers has no effect (for `y` the same is true for the first and fourth). Further, after centering and multiplying `x` and `y`, the third numbers in the slice has precision too low to be included in the centered sum of the products. +/ x.covariance(y).shouldApprox == 1.0e208 / 3; x.covariance(y, true).shouldApprox == 1.0e208 / 4; x.covariance!("online")(y).shouldApprox == 1.0e208 / 3; x.covariance!("online", "kbn")(y).shouldApprox == 1.0e208 / 3; x.covariance!("online", "kb2")(y).shouldApprox == 1.0e208 / 3; x.covariance!("online", "precise")(y).shouldApprox == 1.0e208 / 3; x.covariance!(double, "online", "precise")(y).shouldApprox == 1.0e208 / 3; auto z = uint.max.repeat(3); z.covariance!float(z).shouldApprox == 0.0; static assert(is(typeof(z.covariance!float(z)) == float));
For integral slices, pass output type as template parameter to ensure output type is correct.
import mir.ndslice.slice: sliced; import mir.test: shouldApprox; auto x = [0, 1, 1, 2, 4, 4, 2, 7, 5, 1, 2, 0].sliced; auto y = [6, 3, 7, 1, 1, 1, 9, 5, 3, 1, 3, 7].sliced; x.covariance(y).shouldApprox == -18.583333 / 11; static assert(is(typeof(x.covariance(y)) == double)); x.covariance!float(y).shouldApprox == -18.583333 / 11; static assert(is(typeof(x.covariance!float(y)) == float));
Works with @nogc
import mir.ndslice.allocation: mininitRcslice; import mir.test: shouldApprox; static immutable a = [ 0.0, 1.0, 1.5, 2.0, 3.5, 4.25, 2.0, 7.5, 5.0, 1.0, 1.5, 0.0]; static immutable b = [-0.75, 6.0, -0.25, 8.25, 5.75, 3.5, 9.25, -0.75, 2.5, 1.25, -1, 2.25]; auto x = mininitRcslice!double(12); auto y = mininitRcslice!double(12); x[] = a; y[] = b; x.covariance(y, true).shouldApprox == -5.5 / 12; x.covariance(y).shouldApprox == -5.5 / 11;
Calculates the covariance of the inputs.
If x and y are both slices or convertible to slices, then they must be one-dimensional.
By default, if F is not floating point type, then the result will have a double type if F is implicitly convertible to a floating point type.