/******************************************************************************* * Copyright 2011 See AUTHORS file. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. ******************************************************************************/ package com.badlogic.gdx.math; /** * A simple class keeping track of the mean of a stream of values within a certain window. the WindowedMean will only * return a value in case enough data has been sampled. After enough data has been sampled the oldest sample will be * replaced by the newest in case a new sample is added. * * @author badlogicgames@gmail.com */ public final class WindowedMean { float values[]; int added_values = 0; int last_value; float mean = 0; boolean dirty = true; /** * constructor, window_size specifies the number of samples we will continuously get the mean and variance from. the * class will only return meaning full values if at least window_size values have been added. * * @param window_size * size of the sample window */ public WindowedMean(int window_size) { values = new float[window_size]; } /** @return whether the value returned will be meaningfull */ public boolean hasEnoughData() { return added_values >= values.length; } /** clears this WindowedMean. The class will only return meaningfull values after enough data has been added again. */ public void clear() { added_values = 0; last_value = 0; for (int i = 0; i < values.length; i++) values[i] = 0; dirty = true; } /** * adds a new sample to this mean. in case the window is full the oldest value will be replaced by this new value. * * @param value * The value to add */ public void addValue(float value) { added_values++; values[last_value++] = value; if (last_value > values.length - 1) last_value = 0; dirty = true; } /** * returns the mean of the samples added to this instance. only returns meaningfull results when at least * window_size samples as specified in the constructor have been added. * * @return the mean */ public float getMean() { if (hasEnoughData()) { if (dirty == true) { float mean = 0; for (int i = 0; i < values.length; i++) mean += values[i]; this.mean = mean / values.length; dirty = false; } return this.mean; } else return 0; } /** @return the oldest value in the window */ public float getOldest() { return last_value == values.length - 1 ? values[0] : values[last_value + 1]; } /** @return the value last added */ public float getLatest() { return values[last_value - 1 == -1 ? values.length - 1 : last_value - 1]; } /** @return The standard deviation */ public float standardDeviation() { if (!hasEnoughData()) return 0; float mean = getMean(); float sum = 0; for (int i = 0; i < values.length; i++) { sum += (values[i] - mean) * (values[i] - mean); } return (float) Math.sqrt(sum / values.length); } }