/*
 * License: FreeBSD (Berkeley Software Distribution)
 * Copyright (c) 2013, Sara Sheehan, Kelley Harris, Yun Song
 * 
 * based on:
 * Copyright (c) 2011, Joshua Paul, Matthias SteinrŸcken, Yun Song
 */

package edu.berkeley.utility;

public class LogSum {
	
	private final double[] logSummandArray;
	private int currSize;
	private double maxLogSummand;
	
	public LogSum(int maxEntries) {
		this.logSummandArray = new double[maxEntries];
		reset();
	}
	
	public void reset() {
		this.currSize = 0;
		this.maxLogSummand = Double.NEGATIVE_INFINITY;
	}
	
	public void addLogSummand(double logSummand) {
		this.logSummandArray[this.currSize++] = logSummand;
		this.maxLogSummand = Math.max(this.maxLogSummand, logSummand);
	}
	
	public double retrieveLogSum() {
		if (this.maxLogSummand == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
		
		double factorSum = 0;
		for (int i = 0; i < this.currSize; i++) {
			factorSum += Math.exp(this.logSummandArray[i] - this.maxLogSummand);
		}
		
		return Math.log(factorSum) + this.maxLogSummand;
	}
	
	public double retrieveLogSumVerbose() {
		if (this.maxLogSummand == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
		System.out.println("max log summand " + this.maxLogSummand);
		
		double factorSum = 0;
		for (int i = 0; i < this.currSize; i++) {
			factorSum += Math.exp(this.logSummandArray[i] - this.maxLogSummand);
			System.out.println("factorSum " + factorSum);
		}
		
		return Math.log(factorSum) + this.maxLogSummand;
	}
	
	public static double computePairLogSum(double ls1, double ls2) {
		double maxLogSummand = Math.max(ls1, ls2);
		if (maxLogSummand == Double.NEGATIVE_INFINITY) return Double.NEGATIVE_INFINITY;
		
		double factorSum = Math.exp(ls1 - maxLogSummand) + Math.exp(ls2 - maxLogSummand);
		return Math.log(factorSum) + maxLogSummand;
	}
}
