private void mergeStates(int rowNum,short[] newValues,Vector<Integer> rowsBeingUpdated){
  short[] oldValues=tempStateTable.elementAt(rowNum);
  boolean isLoopingState=loopingStates.contains(new Integer(rowNum));
  for (int i=0; i < oldValues.length; i++) {
    if (oldValues[i] == newValues[i]) {
      continue;
    }
 else     if (isLoopingState && loopingStates.contains(new Integer(oldValues[i]))) {
      if (newValues[i] != 0) {
        if (oldValues[i] == 0) {
          clearLoopingStates=true;
        }
        oldValues[i]=newValues[i];
      }
    }
 else     if (oldValues[i] == 0) {
      oldValues[i]=newValues[i];
    }
 else     if (i == numCategories) {
      oldValues[i]=(short)((newValues[i] & ALL_FLAGS) | oldValues[i]);
    }
 else     if (oldValues[i] != 0 && newValues[i] != 0) {
      int combinedRowNum=searchMergeList(oldValues[i],newValues[i]);
      if (combinedRowNum != 0) {
        oldValues[i]=(short)combinedRowNum;
      }
 else {
        int oldRowNum=oldValues[i];
        int newRowNum=newValues[i];
        combinedRowNum=tempStateTable.size();
        if (mergeList == null) {
          mergeList=new Vector<>();
        }
        mergeList.addElement(new int[]{oldRowNum,newRowNum,combinedRowNum});
        short[] newRow=new short[numCategories + 1];
        short[] oldRow=tempStateTable.elementAt(oldRowNum);
        System.arraycopy(oldRow,0,newRow,0,numCategories + 1);
        tempStateTable.addElement(newRow);
        oldValues[i]=(short)combinedRowNum;
        if ((decisionPointList.contains(new Integer(oldRowNum)) || decisionPointList.contains(new Integer(newRowNum))) && !decisionPointList.contains(new Integer(combinedRowNum))) {
          decisionPointList.addElement(new Integer(combinedRowNum));
        }
        if ((rowsBeingUpdated.contains(new Integer(oldRowNum)) || rowsBeingUpdated.contains(new Integer(newRowNum))) && !rowsBeingUpdated.contains(new Integer(combinedRowNum))) {
          decisionPointList.addElement(new Integer(combinedRowNum));
        }
        for (int k=0; k < decisionPointStack.size(); k++) {
          Vector<Integer> dpl=decisionPointStack.elementAt(k);
          if ((dpl.contains(new Integer(oldRowNum)) || dpl.contains(new Integer(newRowNum))) && !dpl.contains(new Integer(combinedRowNum))) {
            dpl.addElement(new Integer(combinedRowNum));
          }
        }
        mergeStates(combinedRowNum,tempStateTable.elementAt(newValues[i]),rowsBeingUpdated);
      }
    }
  }
  return;
}

private void mergeStates ( int rowNum , short [ ] newValues , Vector < Integer > rowsBeingUpdated ) { short [ ] oldValues = tempStateTable . elementAt ( rowNum ) ; boolean isLoopingState = loopingStates . contains ( new Integer ( rowNum ) ) ; for ( int i = 0 ; i < oldValues . length ; i ++ ) { if ( oldValues [ i ] == newValues [ i ] ) { continue ; } else if ( isLoopingState && loopingStates . contains ( new Integer ( oldValues [ i ] ) ) ) { if ( newValues [ i ] != 0 ) { if ( oldValues [ i ] == 0 ) { clearLoopingStates = true ; } oldValues [ i ] = newValues [ i ] ; } } else if ( oldValues [ i ] == 0 ) { oldValues [ i ] = newValues [ i ] ; } else if ( i == numCategories ) { oldValues [ i ] = ( short ) ( ( newValues [ i ] & ALL_FLAGS ) | oldValues [ i ] ) ; } else if ( oldValues [ i ] != 0 && newValues [ i ] != 0 ) { int combinedRowNum = searchMergeList ( oldValues [ i ] , newValues [ i ] ) ; if ( combinedRowNum != 0 ) { oldValues [ i ] = ( short ) combinedRowNum ; } else { int oldRowNum = oldValues [ i ] ; int newRowNum = newValues [ i ] ; combinedRowNum = tempStateTable . size ( ) ; if ( mergeList == null ) { mergeList = new Vector < > ( ) ; } mergeList . addElement ( new int [ ] { oldRowNum , newRowNum , combinedRowNum } ) ; short [ ] newRow = new short [ numCategories + 1 ] ; short [ ] oldRow = tempStateTable . elementAt ( oldRowNum ) ; System . arraycopy ( oldRow , 0 , newRow , 0 , numCategories + 1 ) ; tempStateTable . addElement ( newRow ) ; oldValues [ i ] = ( short ) combinedRowNum ; if ( ( decisionPointList . contains ( new Integer ( oldRowNum ) ) || decisionPointList . contains ( new Integer ( newRowNum ) ) ) && ! decisionPointList . contains ( new Integer ( combinedRowNum ) ) ) { decisionPointList . addElement ( new Integer ( combinedRowNum ) ) ; } if ( ( rowsBeingUpdated . contains ( new Integer ( oldRowNum ) ) || rowsBeingUpdated . contains ( new Integer ( newRowNum ) ) ) && ! rowsBeingUpdated . contains ( new Integer ( combinedRowNum ) ) ) { decisionPointList . addElement ( new Integer ( combinedRowNum ) ) ; } for ( int k = 0 ; k < decisionPointStack . size ( ) ; k ++ ) { Vector < Integer > dpl = decisionPointStack . elementAt ( k ) ; if ( ( dpl . contains ( new Integer ( oldRowNum ) ) || dpl . contains ( new Integer ( newRowNum ) ) ) && ! dpl . contains ( new Integer ( combinedRowNum ) ) ) { dpl . addElement ( new Integer ( combinedRowNum ) ) ; } } mergeStates ( combinedRowNum , tempStateTable . elementAt ( newValues [ i ] ) , rowsBeingUpdated ) ; } } } return ; }
the real work of making the state table deterministic happens here . this function merges a state in the state table ( specified by rownum ) with a state that is passed in ( newvalues ) . the basic process is to copy the nonzero cells in newstates into the state in the state table ( we ' ll call that oldvalues ) . if there ' s a collision ( i . e . , if the same cell has a nonzero value in both states , and it ' s not the same value ) , then we have to reconcile the collision . we do this by creating a new state , adding it to the end of the state table , and using this function recursively to merge the original two states into a single , combined state . this process may happen recursively ( i . e . , each successive level may involve collisions ) . to prevent infinite recursion , we keep a log of merge operations . any time we ' re merging two states we ' ve merged before , we can just supply the row number for the result of that merge operation rather than creating a new state just like it .
