/******************************************************************************* * Copyright (c) 2016 Ericsson * * 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 *******************************************************************************/ 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$ } }