001    /*
002     * Copyright (C) 2008-2010 by Holger Arndt
003     *
004     * This file is part of the Universal Java Matrix Package (UJMP).
005     * See the NOTICE file distributed with this work for additional
006     * information regarding copyright ownership and licensing.
007     *
008     * UJMP is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU Lesser General Public License as
010     * published by the Free Software Foundation; either version 2
011     * of the License, or (at your option) any later version.
012     *
013     * UJMP is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016     * GNU Lesser General Public License for more details.
017     *
018     * You should have received a copy of the GNU Lesser General Public
019     * License along with UJMP; if not, write to the
020     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
021     * Boston, MA  02110-1301  USA
022     */
023    
024    package org.ujmp.core.doublematrix.calculation.general.statistical;
025    
026    import org.ujmp.core.Coordinates;
027    import org.ujmp.core.Matrix;
028    import org.ujmp.core.annotation.Annotation;
029    import org.ujmp.core.annotation.DefaultAnnotation;
030    import org.ujmp.core.doublematrix.calculation.AbstractDoubleCalculation;
031    import org.ujmp.core.doublematrix.calculation.general.missingvalues.CountMissing;
032    import org.ujmp.core.exceptions.MatrixException;
033    import org.ujmp.core.util.MathUtil;
034    
035    public class Var extends AbstractDoubleCalculation {
036            private static final long serialVersionUID = -6376910948253374396L;
037    
038            private Matrix mean = null;
039    
040            private Matrix missingCount = null;
041    
042            private boolean ignoreNaN = false;
043    
044            public Var(int dimension, boolean ignoreNaN, Matrix matrix) {
045                    super(dimension, matrix);
046                    this.ignoreNaN = ignoreNaN;
047                    Annotation aold = matrix.getAnnotation();
048                    if (aold != null) {
049                            Annotation a = new DefaultAnnotation(getSize());
050                            a.setMatrixAnnotation(aold.getMatrixAnnotation());
051                            if (dimension == ROW) {
052                                    a.setDimensionMatrix(ROW, aold.getDimensionMatrix(ROW));
053                            } else if (dimension == COLUMN) {
054                                    a.setDimensionMatrix(COLUMN, aold.getDimensionMatrix(COLUMN));
055                            }
056                            setAnnotation(a);
057                    }
058            }
059    
060            public double getDouble(long... coordinates) throws MatrixException {
061                    if (mean == null) {
062                            mean = new Mean(getDimension(), ignoreNaN, getSource()).calcNew();
063                    }
064                    if (missingCount == null) {
065                            missingCount = new CountMissing(getDimension(), getSource()).calcNew();
066                    }
067    
068                    double sum = 0;
069    
070                    if (ignoreNaN) {
071                            double count = 0;
072                            switch (getDimension()) {
073                            case ROW:
074                                    for (long r = getSource().getSize()[ROW] - 1; r != -1; r--) {
075                                            sum += Math.pow(MathUtil.ignoreNaN(getSource().getAsDouble(r,
076                                                            coordinates[COLUMN]))
077                                                            - mean.getAsDouble(0, coordinates[COLUMN]), 2.0);
078                                    }
079                                    count = getSource().getRowCount()
080                                                    - missingCount.getAsDouble(0, coordinates[COLUMN]) - 1;
081                                    count = count == 0 ? 1 : count;
082                                    return sum / count;
083                            case COLUMN:
084                                    for (long c = getSource().getSize()[COLUMN] - 1; c != -1; c--) {
085                                            sum += Math.pow(MathUtil
086                                                            .ignoreNaN(getSource().getAsDouble(coordinates[ROW], c))
087                                                            - mean.getAsDouble(coordinates[ROW], 0), 2.0);
088                                    }
089                                    count = getSource().getColumnCount()
090                                                    - missingCount.getAsDouble(coordinates[ROW], 0) - 1;
091                                    count = count == 0 ? 1 : count;
092                                    return sum / count;
093                            case ALL:
094                                    for (long r = getSource().getSize()[ROW] - 1; r != -1; r--) {
095                                            for (long c = getSource().getSize()[COLUMN] - 1; c != -1; c--) {
096                                                    sum += Math.pow(MathUtil.ignoreNaN(getSource().getAsDouble(r, c))
097                                                                    - mean.getAsDouble(0, 0), 2.0);
098                                            }
099                                    }
100                                    count = (Coordinates.product(getSource().getSize())
101                                                    - missingCount.getAsDouble(0, 0) - 1);
102                                    count = count == 0 ? 1 : count;
103                                    return sum / count;
104                            default:
105                                    return 0.0;
106                            }
107                    } else {
108                            double count = 0;
109                            switch (getDimension()) {
110                            case ROW:
111                                    for (long r = getSource().getSize()[ROW] - 1; r != -1; r--) {
112                                            sum += Math.pow((getSource().getAsDouble(r, coordinates[COLUMN]))
113                                                            - mean.getAsDouble(0, coordinates[COLUMN]), 2.0);
114                                    }
115                                    count = getSource().getRowCount() - 1;
116                                    count = count == 0 ? 1 : count;
117                                    return sum / count;
118                            case COLUMN:
119                                    for (long c = getSource().getSize()[COLUMN] - 1; c != -1; c--) {
120                                            sum += Math.pow((getSource().getAsDouble(coordinates[ROW], c))
121                                                            - mean.getAsDouble(coordinates[ROW], 0), 2.0);
122                                    }
123                                    count = getSource().getColumnCount() - 1;
124                                    count = count == 0 ? 1 : count;
125                                    return sum / count;
126                            case ALL:
127                                    for (long r = getSource().getSize()[ROW] - 1; r != -1; r--) {
128                                            for (long c = getSource().getSize()[COLUMN] - 1; c != -1; c--) {
129                                                    sum += Math.pow((getSource().getAsDouble(r, c)) - mean.getAsDouble(0, 0),
130                                                                    2.0);
131                                            }
132                                    }
133                                    count = Coordinates.product(getSource().getSize()) - 1;
134                                    count = count == 0 ? 1 : count;
135                                    return sum / count;
136                            default:
137                                    return 0.0;
138                            }
139    
140                    }
141    
142            }
143    
144            public long[] getSize() {
145                    switch (getDimension()) {
146                    case ROW:
147                            return new long[] { 1, getSource().getSize()[COLUMN] };
148                    case COLUMN:
149                            return new long[] { getSource().getSize()[ROW], 1 };
150                    case ALL:
151                            return new long[] { 1, 1 };
152                    }
153                    return null;
154            }
155    
156    }