Here you can find the source of covariance(final double[][] data)
public static final double[][] covariance(final double[][] data)
//package com.java2s; /*/*from www . jav a2 s . c o m*/ * ==================================================== * Copyright (C) 2013 by Idylwood Technologies, LLC. All rights reserved. * * Developed at Idylwood Technologies, LLC. * Permission to use, copy, modify, and distribute this * software is freely granted, provided that this notice * is preserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * The License should have been distributed to you with the source tree. * If not, it can be found at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Author: Charles Cooper * Date: 2013 * ==================================================== */ public class Main { public static final double[][] covariance(final double[][] data) { final int len = data.length; final double[] means = new double[len]; // precalculate the means final double[][] ret = new double[len][len]; for (int i = 0; i < len; i++) { means[i] = mean(data[i]); for (int j = 0; j <= i; j++) { final double d = sum(multiply(shift(data[i], -means[i]), shift(data[j], -means[j]))) / (len); ret[i][j] = d; ret[j][i] = d; } } return ret; } public final static double mean(final double[] values) { return sum(values) / values.length; } /** * Implementation of sum which is both more numerically * stable _and faster_ than the naive implementation * which is used in all standard numerical libraries I know of: * Colt, OpenGamma, Apache Commons Math, EJML. * * Implementation uses variant of Kahan's algorithm keeping a running error * along with the accumulator to try to cancel out the error at the end. * This is much faster than Schewchuk's algorithm but not * guaranteed to be perfectly precise * In most cases, however, it is just as precise. * Due to optimization it is about 30% faster * even than the naive implementation on my machine. * @param values * @return * Side Effects: none */ public static final double sum(final double... values) { double sum = 0; double err = 0; final int unroll = 6; // empirically it doesn't get much better than this final int len = values.length - values.length % unroll; // unroll the loop. due to IEEE 754 restrictions // the JIT shouldn't be allowed to unroll it dynamically, so it's // up to us to do it by hand ;) int i = 0; for (; i < len; i += unroll) { final double val = values[i] + values[i + 1] + values[i + 2] + values[i + 3] + values[i + 4] + values[i + 5]; final double partial = val - err; final double hi = sum + val; err = (hi - sum) - partial; sum = hi; } for (; i < values.length; i++) { final double val = values[i]; final double partial = val - err; final double hi = sum + val; err = (hi - sum) - partial; sum = hi; } return sum; } /** * Returns newly allocated array which is the result * of termwise multiplication of the input arrays * @param first * @param second * @throws ArrayIndexOutOfBoundsException if the arrays are of unequal length * @return * Side Effects: Allocation of the returned array */ final public static double[] multiply(final double[] x, final double[] y) { final int len = x.length; if (len != y.length) throw new ArrayIndexOutOfBoundsException("Tried to multiply two vectors of unequal length!"); final double ret[] = new double[len]; for (int i = 0; i < len; i++) ret[i] = x[i] * y[i]; return ret; } /** * Shifts all the elements of <code>values</code> by <code>constant</code>. * @param values * @param constant * @return Newly allocated array whose values are values[i]+constant * Side Effects: Allocation of new array */ public static final double[] shift(final double[] values, final double constant) { final double ret[] = new double[values.length]; for (int i = values.length; i-- != 0;) ret[i] = values[i] + constant; return ret; } }