Home | History | Annotate | Download | only in math
      1 /*******************************************************************************
      2  * Copyright 2011 See AUTHORS file.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *   http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  ******************************************************************************/
     16 
     17 package com.badlogic.gdx.math;
     18 
     19 /** A simple class keeping track of the mean of a stream of values within a certain window. the WindowedMean will only return a
     20  * value in case enough data has been sampled. After enough data has been sampled the oldest sample will be replaced by the newest
     21  * in case a new sample is added.
     22  *
     23  * @author badlogicgames (at) gmail.com */
     24 public final class WindowedMean {
     25 	float values[];
     26 	int added_values = 0;
     27 	int last_value;
     28 	float mean = 0;
     29 	boolean dirty = true;
     30 
     31 	/** constructor, window_size specifies the number of samples we will continuously get the mean and variance from. the class will
     32 	 * only return meaning full values if at least window_size values have been added.
     33 	 *
     34 	 * @param window_size size of the sample window */
     35 	public WindowedMean (int window_size) {
     36 		values = new float[window_size];
     37 	}
     38 
     39 	/** @return whether the value returned will be meaningful */
     40 	public boolean hasEnoughData () {
     41 		return added_values >= values.length;
     42 	}
     43 
     44 	/** clears this WindowedMean. The class will only return meaningful values after enough data has been added again. */
     45 	public void clear () {
     46 		added_values = 0;
     47 		last_value = 0;
     48 		for (int i = 0; i < values.length; i++)
     49 			values[i] = 0;
     50 		dirty = true;
     51 	}
     52 
     53 	/** adds a new sample to this mean. In case the window is full the oldest value will be replaced by this new value.
     54 	 *
     55 	 * @param value The value to add */
     56 	public void addValue (float value) {
     57 		if (added_values < values.length)
     58 			added_values++;
     59 		values[last_value++] = value;
     60 		if (last_value > values.length - 1) last_value = 0;
     61 		dirty = true;
     62 	}
     63 
     64 	/** returns the mean of the samples added to this instance. Only returns meaningful results when at least window_size samples
     65 	 * as specified in the constructor have been added.
     66 	 * @return the mean */
     67 	public float getMean () {
     68 		if (hasEnoughData()) {
     69 			if (dirty == true) {
     70 				float mean = 0;
     71 				for (int i = 0; i < values.length; i++)
     72 					mean += values[i];
     73 
     74 				this.mean = mean / values.length;
     75 				dirty = false;
     76 			}
     77 			return this.mean;
     78 		} else
     79 			return 0;
     80 	}
     81 
     82 	/** @return the oldest value in the window */
     83 	public float getOldest () {
     84 		return last_value == values.length - 1 ? values[0] : values[last_value + 1];
     85 	}
     86 
     87 	/** @return the value last added */
     88 	public float getLatest () {
     89 		return values[last_value - 1 == -1 ? values.length - 1 : last_value - 1];
     90 	}
     91 
     92 	/** @return The standard deviation */
     93 	public float standardDeviation () {
     94 		if (!hasEnoughData()) return 0;
     95 
     96 		float mean = getMean();
     97 		float sum = 0;
     98 		for (int i = 0; i < values.length; i++) {
     99 			sum += (values[i] - mean) * (values[i] - mean);
    100 		}
    101 
    102 		return (float)Math.sqrt(sum / values.length);
    103 	}
    104 
    105 	public int getWindowSize () {
    106 		return values.length;
    107 	}
    108 }
    109