code: package edu.berkeley.nlp.syntax;
  
  import edu.berkeley.nlp.util.Numberer;
  import edu.berkeley.nlp.util.ScalingTools;
  
  /**
   * Represent parsetrees, with each node consisting of a label and a list of
   * children. The score tables are not allocated by the constructor and
   * allocate() and deallocate() must be called manually. This is to allow more
   * control over memory usage.
   * 
   * @author Slav Petrov
   * @author Romain Thibaux
   */
  public class StateSet {
  	public static final double SCALE = Math.exp(100);
  
  	double[] iScores; // the log-probabilities for each sublabels
  	double[] oScores;
  	int iScale;
  	int oScale;
  	String word;
  	/** the word of this node, if it is a terminal node; else null */
  	public int wordIndex, sigIndex;
  
  	short numSubStates;
  	short state;
  	public short from, to;
  
  	// Run allocate() before any other operation
  	public void allocate() {
  		iScores = new double[numSubStates];
  		oScores = new double[numSubStates];
  	}
  
  	// run deallocate() if the scores are no longer needed and
  	// this object will not be used for a long time
  	public void deallocate() {
  		iScores = null;
  		oScores = null;
  	}
  
  	@Override
  	public String toString() {
  		if (word != null)
  			return word + " " + from + "-" + to;// + " " + substates.length;
  		String s = Numberer.getGlobalNumberer("tags").object(state) + " ";// "[";
  		// for (int i = 0; i < numSubStates; i++){
  		// NumberFormat f = NumberFormat.getInstance();
  		// f.setMaximumFractionDigits(5);
  		// String iS = "";
  		// String oS = "";
  		// if (iScores != null && iScores[i]!=0)
  		// iS = ": iS="+f.format(iScores[i]);//Math.log(iScores[i])+100*iScale);
  		// if (oScores != null && oScores[i]!=0)
  		// oS = " oS="+f.format(oScores[i]);//Math.log(oScores[i])+100*oScale);
  		// // String iS = Double.toString(Math.log(iScores[i])+100*iScale);
  		// // String oS = Double.toString(Math.log(oScores[i])+100*oScale);
  		// // String iS = "";
  		// // String oS = "";
  		// if (iScores != null && DoubleArrays.max(iScores)==0) iS = ", iS=0";
  		// if (oScores != null && DoubleArrays.max(oScores)==0) oS = ", oS=0";
  		// s=s.concat(" ["+state+"-"+i+iS+oS+"]");
  		// }
  		// s=s.concat(" ]");
  		return s;
  	}
  
  	public final short getState() {
  		return state;
  	}
  
  	public final double getIScore(int i) {
  		return iScores[i];
  	}
  
  	public final double[] getIScores() {
  		return iScores;
  	}
  
  	public final double getOScore(int i) {
  		return oScores[i];
  	}
  
  	public final double[] getOScores() {
  		return oScores;
  	}
  
  	public final void setIScores(double[] s) {
  		iScores = s;
  	}
  
  	public final void setIScore(int i, double s) {
  		if (iScores == null)
  			iScores = new double[numSubStates];
  		iScores[i] = s;
  	}
  
  	public final void setOScores(double[] s) {
  		oScores = s;
  	}
  
  	public final void setOScore(int i, double s) {
  		if (oScores == null)
  			oScores = new double[numSubStates];
  		oScores[i] = s;
  	}
  
  	/*
  	 * public void logAddIScore(short i, double s) { iScores[i] =
  	 * SloppyMath.logAdd(iScores[i], s); }
  	 * 
  	 * public void logAddOScore(short i,double s) { oScores[i] =
  	 * SloppyMath.logAdd(oScores[i], s); }
  	 */
  
  	public final int numSubStates() {
  		return numSubStates;
  	}
  
  	/*
  	 * public StateSet(int nSubStates) { this.numSubStates = nSubStates;
  	 * this.iScores = new double[nSubStates]; this.oScores = new
  	 * double[nSubStates]; for ( int i = 0; i < nSubStates; i++ ) { iScores[i] =
  	 * Double.NEGATIVE_INFINITY; oScores[i] = Double.NEGATIVE_INFINITY; } }
  	 */
  
  	public StateSet(short state, short nSubStates) {
  		this.numSubStates = nSubStates;
  		this.state = state;
  	}
  
  	public StateSet(short s, short nSubStates, String word, short from, short to) {
  		this.numSubStates = nSubStates;
  		this.state = s;
  		this.word = word;
  		this.from = from;
  		this.to = to;
  
  	}
  
  	public StateSet(StateSet oldS, short nSubStates) {
  		this.numSubStates = nSubStates;
  		this.state = oldS.state;
  		this.word = oldS.word;
  		this.from = oldS.from;
  		this.to = oldS.to;
  
  	}
  
  	public String getWord() {
  		return word;
  	}
  
  	public void setWord(String word) {
  		this.word = word;
  	}
  
  	public void scaleIScores(int previousScale) {
  		iScale = ScalingTools.scaleArray(iScores, previousScale);
  		// int logScale = 0;
  		// double scale = 1.0;
  		// double max = ArrayMath.max(iScores);
  		// //if (max==0) System.out.println("All iScores are 0!");
  		// if (SloppyMath.isVeryDangerous(max)) return;
  		// while (max > SCALE) {
  		// max /= SCALE;
  		// scale *= SCALE;
  		// logScale += 1;
  		// }
  		// while (max > 0.0 && max < 1.0 / SCALE) {
  		// max *= SCALE;
  		// scale /= SCALE;
  		// logScale -= 1;
  		// }
  		// if (logScale != 0) {
  		// for (int i = 0; i < numSubStates; i++) {
  		// iScores[i] /= scale;
  		// }
  		// }
  		// if ((max!=0) && ArrayMath.max(iScores)==0){
  		// System.out.println("Undeflow when scaling iScores!");
  		// }
  		// iScale = previousScale + logScale;
  	}
  
  	public void scaleOScores(int previousScale) {
  		oScale = ScalingTools.scaleArray(oScores, previousScale);
  		// int logScale = 0;
  		// double scale = 1.0;
  		// double max = ArrayMath.max(oScores);
  		// if (SloppyMath.isVeryDangerous(max)) return;
  		// //if (max==0) System.out.println("All oScores are 0!");
  		// while (max > SCALE) {
  		// max /= SCALE;
  		// scale *= SCALE;
  		// logScale += 1;
  		// }
  		// while (max > 0.0 && max < 1.0 / SCALE) {
  		// max *= SCALE;
  		// scale /= SCALE;
  		// logScale -= 1;
  		// }
  		// if (logScale != 0) {
  		// for (int i = 0; i < numSubStates; i++) {
  		// oScores[i] /= scale;
  		// }
  		// }
  		// if ((max!=0) && ArrayMath.max(oScores)==0){
  		// System.out.println("Undeflow when scaling oScores!");
  		// }
  		// oScale = previousScale + logScale;
  	}
  
  	public int getIScale() {
  		return iScale;
  	}
  
  	public void setIScale(int scale) {
  		iScale = scale;
  	}
  
  	public int getOScale() {
  		return oScale;
  	}
  
  	public void setOScale(int scale) {
  		oScale = scale;
  	}
  
  	/**
  	 * @return
  	 */
  	public StateSet copy() {
  		return new StateSet(this, this.numSubStates);
  	}
  }
  