package extractors.hog;

/**
 * This class provides an implementation for the {@link NormalizationMethod} realizing L2-Normalization with
 * hysteresis step.
 * 
 * 
 */
public class L2HysNormalization implements NormalizationMethod {

	// parameters
	private double epsilon, epsilonHys, clippingThres;

	/**
	 * Constructs a {@link L2HysNormalization} object with the specified parameters.
	 * 
	 * @param epsilon
	 * @param epsilonHys
	 * @param clippingThres
	 */
	public L2HysNormalization(double epsilon, double epsilonHys, double clippingThres) {
		this.epsilon = epsilon;
		this.epsilonHys = epsilonHys;
		this.clippingThres = clippingThres;
	}

	@Override
	public void normalize(double[] values) {
		double sumOfSquares = 0.0;
		for (int i = 0; i < values.length; i++) {
			sumOfSquares += values[i] * values[i];
		}
		double normalizationFactor = 1.0 / Math.sqrt(sumOfSquares + epsilon * epsilon);

		double sumOfSquares2 = 0.0;
		for (int i = 0; i < values.length; i++) {
			values[i] *= normalizationFactor;

			if (values[i] > clippingThres) {
				values[i] = clippingThres;
			}
			sumOfSquares2 += values[i] * values[i];
		}

		normalizationFactor = 1.0 / Math.sqrt(sumOfSquares2 + epsilonHys * epsilonHys);
		for (int i = 0; i < values.length; i++) {
			values[i] *= normalizationFactor;
		}
	}

	@Override
	public String toString() {
		return "L2Hys_e" + (int) epsilon + "_eHys" + getStringOfDouble(epsilonHys, 3) + "_thr"
				+ getStringOfDouble(clippingThres, 3);
	}

	// utility method used by toString
	private String getStringOfDouble(double d, int num) {
		String s = Double.toString(d);
		return s.substring(0, num);
	}

}
