View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.stat.descriptive.moment;
18  
19  import java.util.Arrays;
20  
21  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
22  import org.apache.commons.math4.legacy.linear.MatrixUtils;
23  import org.apache.commons.math4.legacy.linear.RealMatrix;
24  
25  /**
26   * Returns the covariance matrix of the available vectors.
27   * @since 1.2
28   */
29  public class VectorialCovariance {
30      /** Sums for each component. */
31      private final double[] sums;
32  
33      /** Sums of products for each component. */
34      private final double[] productsSums;
35  
36      /** Indicator for bias correction. */
37      private final boolean isBiasCorrected;
38  
39      /** Number of vectors in the sample. */
40      private long n;
41  
42      /** Constructs a VectorialCovariance.
43       * @param dimension vectors dimension
44       * @param isBiasCorrected if true, computed the unbiased sample covariance,
45       * otherwise computes the biased population covariance
46       */
47      public VectorialCovariance(int dimension, boolean isBiasCorrected) {
48          sums         = new double[dimension];
49          productsSums = new double[dimension * (dimension + 1) / 2];
50          n            = 0;
51          this.isBiasCorrected = isBiasCorrected;
52      }
53  
54      /**
55       * Add a new vector to the sample.
56       * @param v vector to add
57       * @throws DimensionMismatchException if the vector does not have the right dimension
58       */
59      public void increment(double[] v) throws DimensionMismatchException {
60          if (v.length != sums.length) {
61              throw new DimensionMismatchException(v.length, sums.length);
62          }
63          int k = 0;
64          for (int i = 0; i < v.length; ++i) {
65              sums[i] += v[i];
66              for (int j = 0; j <= i; ++j) {
67                  productsSums[k++] += v[i] * v[j];
68              }
69          }
70          n++;
71      }
72  
73      /**
74       * Get the covariance matrix.
75       * @return covariance matrix
76       */
77      public RealMatrix getResult() {
78  
79          int dimension = sums.length;
80          RealMatrix result = MatrixUtils.createRealMatrix(dimension, dimension);
81  
82          if (n > 1) {
83              double c = 1.0 / (n * (isBiasCorrected ? (n - 1) : n));
84              int k = 0;
85              for (int i = 0; i < dimension; ++i) {
86                  for (int j = 0; j <= i; ++j) {
87                      double e = c * (n * productsSums[k++] - sums[i] * sums[j]);
88                      result.setEntry(i, j, e);
89                      result.setEntry(j, i, e);
90                  }
91              }
92          }
93  
94          return result;
95      }
96  
97      /**
98       * Get the number of vectors in the sample.
99       * @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 }