algorithm for calculating correlation (default: CorrelationAlgo.hybrid)
algorithm for calculating sums (default: Summation.appropriate)
The correlation of the inputs
Correlation 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.correlation(y).shouldApprox == -0.0623684;
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.correlation(y).shouldApprox == -0.0623684; // The naive algorithm is numerically unstable in this case //assert(!x.correlation!"naive"(y).approxEqual(-0.0623684)); // The two-pass algorithm provides the same answer as hybrid x.correlation!"twoPass"(y).shouldApprox == -0.0623684; // And the assumeZeroMean algorithm is way off assert(!x.correlation!"assumeZeroMean"(y).approxEqual(-0.0623684));
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. For the calculations below, the "true" correlation should be a tiny amount above 0.5, but it is as if the calculation happens between [0, 1, 0, -1] and [1, 0, 0, -1]. +/ x.correlation(y).shouldApprox == 0.5; x.correlation!("online")(y).shouldApprox == 0.5; x.correlation!("online", "kbn")(y).shouldApprox == 0.5; x.correlation!("online", "kb2")(y).shouldApprox == 0.5; x.correlation!("online", "precise")(y).shouldApprox == 0.5; x.correlation!(double, "online", "precise")(y).shouldApprox == 0.5; auto z1 = [uint.max - 2, uint.max - 1, uint.max].sliced; auto z2 = [uint.max - 3, uint.max - 2, uint.max - 1].sliced; z1.correlation(z2).shouldApprox == 1.0; static assert(is(typeof(z1.correlation!float(z2)) == 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.correlation(y).shouldApprox == -0.27934577; static assert(is(typeof(x.correlation(y)) == double)); x.correlation!float(y).shouldApprox == -0.27934577; static assert(is(typeof(x.correlation!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.correlation(y).shouldApprox == -0.0623684;
Calculates the correlation of the inputs.
If x and y are both slices or convertible to slices, then they must be one-dimensional.