/* GeoGebra - Dynamic Mathematics for Everyone http://www.geogebra.org This file is part of GeoGebra. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. */ package org.geogebra.common.kernel.statistics; import org.geogebra.common.kernel.Construction; import org.geogebra.common.kernel.algos.AlgoElement; import org.geogebra.common.kernel.algos.Algos; import org.geogebra.common.kernel.arithmetic.NumberValue; import org.geogebra.common.kernel.geos.GeoAngle; import org.geogebra.common.kernel.geos.GeoElement; import org.geogebra.common.kernel.geos.GeoList; import org.geogebra.common.kernel.geos.GeoNumeric; /** * @author Kamalaruban Parameswaran * @version 2012-03-06 */ public abstract class AlgoStats1DGrouped extends AlgoElement { private GeoList geoList; // input private GeoList geoList2; // input public GeoNumeric truncate; // input public GeoNumeric result; // output private int stat; final static int STATS_MEAN = 0; final static int STATS_VARIANCE = 1; final static int STATS_SIGMAX = 2; final static int STATS_SIGMAXX = 3; final static int STATS_SD = 4; final static int STATS_PRODUCT = 5; final static int STATS_SXX = 6; final static int STATS_SAMPLE_VARIANCE = 7; final static int STATS_SAMPLE_SD = 8; // OK public AlgoStats1DGrouped(Construction cons, String label, GeoList geoList, GeoList geoList2, int stat) { this(cons, label, geoList, geoList2, null, stat); } // OK AlgoStats1DGrouped(Construction cons, String label, GeoList geoList, GeoList geoList2, GeoNumeric Truncate, int stat) { this(cons, geoList, geoList2, Truncate, stat); result.setLabel(label); } // OK AlgoStats1DGrouped(Construction cons, GeoList geoList, GeoList geoList2, GeoNumeric truncate, int stat) { super(cons); this.geoList = geoList; this.geoList2 = geoList2; this.stat = stat; this.truncate = truncate; if (geoList.size() > 0 && geoList.get(0).isAngle()) { result = new GeoAngle(cons); } else { result = new GeoNumeric(cons); } setInputOutput(); compute(); } // OK public AlgoStats1DGrouped(Construction cons, GeoList geoList, GeoList geoList2, int stat) { this(cons, geoList, geoList2, null, stat); } // OK @Override public abstract Algos getClassName(); // OK @Override protected void setInputOutput() { if (truncate == null) { input = new GeoElement[2]; input[0] = geoList; input[1] = geoList2; } else { input = new GeoElement[3]; input[0] = geoList; input[1] = geoList2; input[2] = truncate; } setOnlyOutput(result); setDependencies(); // done by AlgoElement } // OK public GeoNumeric getResult() { return result; } @Override public final void compute() { // TODO: remove // Application.debug("compute: " + geoList); if (!geoList.isDefined()) { result.setUndefined(); return; } int truncateVal; int size = geoList.size(); if (truncate != null) { truncateVal = (int) truncate.getDouble(); if (truncateVal == 0) { result.setValue(0); return; } if (truncateVal < 1 || truncateVal > size) { result.setUndefined(); return; } size = truncateVal; // truncate the list } if (size == 0) { switch (stat) { case STATS_SIGMAX: case STATS_SIGMAXX: result.setValue(0); return; case STATS_PRODUCT: result.setValue(1); return; default: result.setUndefined(); return; } } double sumVal = 0; double sumFreq = 0; double sumSquares = 0; double product = 1; double val; double frequency; double val_by_freq; for (int i = 0; i < size; i++) { GeoElement geo = geoList.get(i); GeoElement geo2 = geoList2.get(i); if (geo instanceof NumberValue && geo2 instanceof NumberValue) { NumberValue num = (NumberValue) geo; NumberValue freq = (NumberValue) geo2; val = num.getDouble(); frequency = freq.getDouble(); val_by_freq = val * frequency; sumVal += val_by_freq; sumSquares += val * val_by_freq; sumFreq += frequency; product *= Math.pow(val, frequency); } else { result.setUndefined(); return; } } double mu = sumVal / sumFreq; // OK double var; switch (stat) { default: result.setValue(Double.NaN); break; case STATS_MEAN: // OK result.setValue(mu); break; case STATS_SD: // OK var = sumSquares / sumFreq - mu * mu; result.setValue(Math.sqrt(var)); break; case STATS_SAMPLE_SD: // OK var = (sumSquares - sumVal * sumVal / sumFreq) / (sumFreq - 1); result.setValue(Math.sqrt(var)); break; case STATS_VARIANCE: // OK var = sumSquares / sumFreq - mu * mu; result.setValue(var); break; case STATS_SAMPLE_VARIANCE: // OK var = (sumSquares - sumVal * sumVal / sumFreq) / (sumFreq - 1); result.setValue(var); break; case STATS_SXX: // OK var = sumSquares - (sumVal * sumVal) / sumFreq; result.setValue(var); break; case STATS_SIGMAX: // OK result.setValue(sumVal); break; case STATS_SIGMAXX: // OK result.setValue(sumSquares); break; case STATS_PRODUCT: // OK result.setValue(product); break; } } }