blob: 1791ea10edc2bdbfd6f9098fa81b1d7d5e92e901 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.analysis.timing.core.tests.statistics;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.function.Function;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.tracecompass.analysis.timing.core.statistics.IStatistics;
import org.eclipse.tracecompass.common.core.NonNullUtils;
/**
* This calculates the statistics of a segment store in an offline manner to
* validate online calculations.
*
* @author Matthew Khouzam
* @param <E>
* The type of object to calculate statistics on
*/
public class OfflineStatisticsCalculator<@NonNull E> implements IStatistics<E> {
private final Collection<E> fElements;
private final @NonNull Function<E, @NonNull Long> fMapper;
/**
* Constructor
*
* @param elements
* collection of elements
* @param mapper
* A mapper function that takes an object to computes statistics
* for and returns the value to use for the statistics
*/
public OfflineStatisticsCalculator(Collection<E> elements, @NonNull Function<E, @NonNull Long> mapper) {
fElements = elements;
fMapper = mapper;
}
/**
* Get the max value
*
* @return the max value
*/
@Override
public long getMax() {
long max = Long.MIN_VALUE;
for (E element : fElements) {
max = Math.max(max, fMapper.apply(element));
}
return max;
}
/**
* Get the min value
*
* @return the min value
*/
@Override
public long getMin() {
long min = Long.MAX_VALUE;
for (E element : fElements) {
min = Math.min(min, fMapper.apply(element));
}
return min;
}
@Override
public @NonNull E getMinObject() {
@Nullable E obj = null;
for (E element : fElements) {
if (obj == null) {
obj = element;
continue;
}
Long value = fMapper.apply(element);
if (value <= fMapper.apply(obj)) {
obj = element;
}
}
if (obj == null) {
throw new NoSuchElementException("There are no elements in the collection");
}
return obj;
}
@Override
public @NonNull E getMaxObject() {
@Nullable E obj = null;
for (E element : fElements) {
if (obj == null) {
obj = element;
continue;
}
Long value = fMapper.apply(element);
if (value >= fMapper.apply(obj)) {
obj = element;
}
}
if (obj == null) {
throw new NoSuchElementException("There are no elements in the collection");
}
return obj;
}
/**
* Get the average value
*
* @return the average value
*/
@Override
public double getMean() {
double total = 0;
for (E element : fElements) {
total += (double) NonNullUtils.checkNotNull(fMapper.apply(element)) / (double) fElements.size();
}
return total;
}
/**
* Get the standard deviation.
*
* @return the standard deviation
*/
@Override
public double getStdDev() {
if (fElements.size() < 3) {
return Double.NaN;
}
double mean = getMean();
double totalVariance = 0;
for (E element : fElements) {
double result = NonNullUtils.checkNotNull(fMapper.apply(element)) - mean;
totalVariance += result * result / (fElements.size() - 1);
}
return Math.sqrt(totalVariance);
}
/**
* Get the total
*
* @return the total
*/
@Override
public double getTotal() {
double total = 0.0;
for (E element : fElements) {
total += fMapper.apply(element);
}
return total;
}
@Override
public long getNbElements() {
return fElements.size();
}
@Override
public void update(@NonNull E object) {
throw new UnsupportedOperationException("Offline statistics should not update"); //$NON-NLS-1$
}
@Override
public void merge(@NonNull IStatistics<@NonNull E> other) {
throw new UnsupportedOperationException("Offline statistics should not merge"); //$NON-NLS-1$
}
}