001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.math4.legacy.stat.descriptive.moment; 018 019import java.util.Arrays; 020 021import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 022import org.apache.commons.math4.legacy.linear.MatrixUtils; 023import org.apache.commons.math4.legacy.linear.RealMatrix; 024 025/** 026 * Returns the covariance matrix of the available vectors. 027 * @since 1.2 028 */ 029public class VectorialCovariance { 030 /** Sums for each component. */ 031 private final double[] sums; 032 033 /** Sums of products for each component. */ 034 private final double[] productsSums; 035 036 /** Indicator for bias correction. */ 037 private final boolean isBiasCorrected; 038 039 /** Number of vectors in the sample. */ 040 private long n; 041 042 /** Constructs a VectorialCovariance. 043 * @param dimension vectors dimension 044 * @param isBiasCorrected if true, computed the unbiased sample covariance, 045 * otherwise computes the biased population covariance 046 */ 047 public VectorialCovariance(int dimension, boolean isBiasCorrected) { 048 sums = new double[dimension]; 049 productsSums = new double[dimension * (dimension + 1) / 2]; 050 n = 0; 051 this.isBiasCorrected = isBiasCorrected; 052 } 053 054 /** 055 * Add a new vector to the sample. 056 * @param v vector to add 057 * @throws DimensionMismatchException if the vector does not have the right dimension 058 */ 059 public void increment(double[] v) throws DimensionMismatchException { 060 if (v.length != sums.length) { 061 throw new DimensionMismatchException(v.length, sums.length); 062 } 063 int k = 0; 064 for (int i = 0; i < v.length; ++i) { 065 sums[i] += v[i]; 066 for (int j = 0; j <= i; ++j) { 067 productsSums[k++] += v[i] * v[j]; 068 } 069 } 070 n++; 071 } 072 073 /** 074 * Get the covariance matrix. 075 * @return covariance matrix 076 */ 077 public RealMatrix getResult() { 078 079 int dimension = sums.length; 080 RealMatrix result = MatrixUtils.createRealMatrix(dimension, dimension); 081 082 if (n > 1) { 083 double c = 1.0 / (n * (isBiasCorrected ? (n - 1) : n)); 084 int k = 0; 085 for (int i = 0; i < dimension; ++i) { 086 for (int j = 0; j <= i; ++j) { 087 double e = c * (n * productsSums[k++] - sums[i] * sums[j]); 088 result.setEntry(i, j, e); 089 result.setEntry(j, i, e); 090 } 091 } 092 } 093 094 return result; 095 } 096 097 /** 098 * Get the number of vectors in the sample. 099 * @return number of vectors in the sample 100 */ 101 public long getN() { 102 return n; 103 } 104 105 /** 106 * Clears the internal state of the Statistic. 107 */ 108 public void clear() { 109 n = 0; 110 Arrays.fill(sums, 0.0); 111 Arrays.fill(productsSums, 0.0); 112 } 113 114 /** {@inheritDoc} */ 115 @Override 116 public int hashCode() { 117 final int prime = 31; 118 int result = 1; 119 result = prime * result + (isBiasCorrected ? 1231 : 1237); 120 result = prime * result + (int) (n ^ (n >>> 32)); 121 result = prime * result + Arrays.hashCode(productsSums); 122 result = prime * result + Arrays.hashCode(sums); 123 return result; 124 } 125 126 /** {@inheritDoc} */ 127 @Override 128 public boolean equals(Object obj) { 129 if (this == obj) { 130 return true; 131 } 132 if (!(obj instanceof VectorialCovariance)) { 133 return false; 134 } 135 VectorialCovariance other = (VectorialCovariance) obj; 136 if (isBiasCorrected != other.isBiasCorrected) { 137 return false; 138 } 139 if (n != other.n) { 140 return false; 141 } 142 if (!Arrays.equals(productsSums, other.productsSums)) { 143 return false; 144 } 145 return Arrays.equals(sums, other.sums); 146 } 147}