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    
034    public class Mean extends AbstractDoubleCalculation {
035            private static final long serialVersionUID = 4116408128004680574L;
036    
037            private Matrix sum = null;
038    
039            private Matrix missingCount = null;
040    
041            private boolean ignoreNaN = false;
042    
043            public Mean(int dimension, boolean ignoreNaN, Matrix matrix) {
044                    super(dimension, matrix);
045                    this.ignoreNaN = ignoreNaN;
046                    Annotation aold = matrix.getAnnotation();
047                    if (aold != null) {
048                            Annotation a = new DefaultAnnotation(getSize());
049                            a.setMatrixAnnotation(aold.getMatrixAnnotation());
050                            if (dimension == ROW) {
051                                    a.setDimensionMatrix(ROW, aold.getDimensionMatrix(ROW));
052                            } else if (dimension == COLUMN) {
053                                    a.setDimensionMatrix(COLUMN, aold.getDimensionMatrix(COLUMN));
054                            }
055                            setAnnotation(a);
056                    }
057            }
058    
059            public double getDouble(long... coordinates) throws MatrixException {
060                    if (sum == null) {
061                            sum = new Sum(getDimension(), ignoreNaN, getSource()).calcNew();
062                    }
063                    if (ignoreNaN && missingCount == null) {
064                            missingCount = new CountMissing(getDimension(), getSource()).calcNew();
065                    }
066    
067                    if (ignoreNaN) {
068                            switch (getDimension()) {
069                            case ALL:
070                                    return sum.getAsDouble(0, 0)
071                                                    / (Coordinates.product(getSource().getSize()) - missingCount.getAsDouble(0,
072                                                                    0));
073                            case ROW:
074                                    return sum.getAsDouble(0, coordinates[COLUMN])
075                                                    / (getSource().getRowCount() - missingCount.getAsDouble(0,
076                                                                    coordinates[COLUMN]));
077                            case COLUMN:
078                                    return sum.getAsDouble(coordinates[ROW], 0)
079                                                    / (getSource().getColumnCount() - missingCount.getAsDouble(
080                                                                    coordinates[ROW], 0));
081                            default:
082                                    return Double.NaN;
083                            }
084    
085                    } else {
086    
087                            switch (getDimension()) {
088                            case ALL:
089                                    return sum.getAsDouble(0, 0) / (Coordinates.product(getSource().getSize()));
090                            case ROW:
091                                    return sum.getAsDouble(0, coordinates[COLUMN]) / (getSource().getRowCount());
092                            case COLUMN:
093                                    return sum.getAsDouble(coordinates[ROW], 0) / (getSource().getColumnCount());
094                            default:
095                                    return Double.NaN;
096                            }
097    
098                    }
099            }
100    
101            public long[] getSize() {
102                    switch (getDimension()) {
103                    case ROW:
104                            return new long[] { 1, getSource().getSize()[COLUMN] };
105                    case COLUMN:
106                            return new long[] { getSource().getSize()[ROW], 1 };
107                    case ALL:
108                            return new long[] { 1, 1 };
109                    }
110                    return null;
111            }
112    
113            public static double calc(Matrix m) throws MatrixException {
114                    double sum = 0.0;
115                    for (long[] c : m.availableCoordinates()) {
116                            sum += m.getAsDouble(c);
117                    }
118                    return sum / Coordinates.product(m.getSize());
119            }
120    
121    }