/*******************************************************************************
 * 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 meaningful */
	public boolean hasEnoughData () {
		return added_values >= values.length;
	}

	/** clears this WindowedMean. The class will only return meaningful 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) {
		if (added_values < values.length)
			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 meaningful 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);
	}
	
	public int getWindowSize () {
		return values.length;
	}
}

@@ -3074,16 +3074,12 @@
 alue
- + 1
 %5D;%0D%0A
+
 %09%7D%0D%0A
@@ -3579,24 +3579,24 @@
 wSize () %7B%0D%0A
-
 %09%09return val
@@ -3611,12 +3611,602 @@
 th;%0D%0A%09%7D%0D
+%0A%0D%0A%09/** @return A new %3Ccode%3Efloat%5B%5D%3C/code%3E containing all values currently in the window of the stream, in order from oldest to%0D%0A%09 *         latest. The length of the array is smaller than the window size if not enough data has been added. */%0D%0A%09public float%5B%5D getWindowValues () %7B%0D%0A%09%09float%5B%5D windowValues = new float%5Badded_values%5D;%0D%0A%09%09if (hasEnoughData()) %7B%0D%0A%09%09%09for (int i = 0; i %3C windowValues.length; i++) %7B%0D%0A%09%09%09%09windowValues%5Bi%5D = values%5B(i + last_value) %25 values.length%5D;%0D%0A%09%09%09%7D%0D%0A%09%09%7D else %7B%0D%0A%09%09%09System.arraycopy(values, 0, windowValues, 0, added_values);%0D%0A%09%09%7D%0D%0A%09%09return windowValues;%0D%0A%09%7D%0D
 %0A%7D%0D%0A

Fix getOldest() and add getWindowValues() (#4728)