blob: 3f4d9f4d13f60c809e62be899a2632df78a3b749 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pierre Allard,
* Regent L'Archeveque,
* Sebastien Gemme - initial API and implementation
*
* SPDX-License-Identifier: EPL-1.0
*
*******************************************************************************/
package org.eclipse.apogy.common.math.statistics.impl;
import java.util.Collections;
import org.eclipse.apogy.common.math.statistics.ApogyCommonMathStatisticsPackage;
import org.eclipse.apogy.common.math.statistics.Population;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EDataTypeEList;
public class PopulationCustomImpl extends PopulationImpl {
private boolean averageDirty = true;
private boolean sumDirty = true;
private boolean medianDirty = true;
private boolean sumSquaredDirty = true;
private boolean stdDirty = true;
private boolean isDirty = true;
// private boolean isMinMaxDirty = true;
private Adapter populationListener;
protected PopulationCustomImpl() {
super();
this.eAdapters().add(getPopulationListener());
}
@Override
@SuppressWarnings("serial")
public EList<Double> getData() {
if (this.data == null) {
this.data = new EDataTypeEList<Double>(Double.class, this,
ApogyCommonMathStatisticsPackage.POPULATION__DATA) {
@Override
protected boolean isUnique() {
return false;
}
};
}
return this.data;
}
@Override
public double getStandardDeviation() {
if (this.stdDirty) {
if (getData().isEmpty()) {
this.standardDeviation = 0.0;
} else {
double averageEltSquared = getSumSquared() / getData().size();
double averageSquared = getAverage() * getAverage();
this.standardDeviation = Math.sqrt(averageEltSquared - averageSquared);
}
this.stdDirty = false;
}
return this.standardDeviation;
}
@Override
public double getAverage() {
if (this.averageDirty) {
// If population is empty, average is 0.0.
if (getData().isEmpty()) {
this.average = 0.0;
} else {
this.average = getSum() / getData().size();
}
this.averageDirty = false;
}
return this.average;
}
@Override
public double getSum() {
if (this.sumDirty) {
this.sum = 0.0;
for (Double element : getData()) {
this.sum += element.doubleValue();
}
this.sumDirty = false;
}
return this.sum;
}
@Override
public double getMedian() {
sort();
if (this.medianDirty) {
int middle = getData().size() / 2;
this.median = getData().get(middle).doubleValue();
this.medianDirty = false;
}
return this.median;
}
@Override
public double getSumSquared() {
if (this.sumSquaredDirty) {
this.sumSquared = 0.0;
for (Double element : getData()) {
double eltSquared = element.doubleValue() * element.doubleValue();
this.sumSquared += eltSquared;
}
this.sumSquaredDirty = false;
}
return this.sumSquared;
}
@Override
public double getVariance() {
this.variance = getStandardDeviation() * getStandardDeviation();
return this.variance;
}
@Override
public double getMin() {
sort();
if (getData().size() == 0) {
return Double.MAX_VALUE;
} else {
return getData().get(0).doubleValue();
}
}
@Override
public double getMax() {
sort();
if (getData().size() == 0) {
return Double.MIN_VALUE;
} else {
int size = getData().size();
return getData().get(size - 1).doubleValue();
}
}
private Adapter getPopulationListener() {
if (this.populationListener == null) {
this.populationListener = new Adapter() {
@Override
public Notifier getTarget() {
return null;
}
@Override
public boolean isAdapterForType(Object type) {
return false;
}
@Override
public void notifyChanged(Notification notification) {
if (notification.getNotifier() instanceof Population) {
int featureID = notification.getFeatureID(Population.class);
if (featureID == ApogyCommonMathStatisticsPackage.POPULATION__DATA) {
if (!notification.isTouch()) {
PopulationCustomImpl.this.averageDirty = true;
PopulationCustomImpl.this.sumDirty = true;
PopulationCustomImpl.this.medianDirty = true;
PopulationCustomImpl.this.sumSquaredDirty = true;
PopulationCustomImpl.this.stdDirty = true;
PopulationCustomImpl.this.isDirty = true;
}
}
}
}
@Override
public void setTarget(Notifier newTarget) {
}
};
}
return this.populationListener;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
this.eAdapters().remove(getPopulationListener());
}
private void sort() {
if (this.isDirty) {
Collections.sort(getData());
this.isDirty = false;
}
}
} // PopulationImpl