LinearPrinter.println("i,states: " + i + " " + expandedReps[i].getStateCount());
    public LinearFilterRepresentation transform() throws NoTransformPossibleException {		int filterCount = linearRepresentations.length;	LinearPrinter.println(" preparing to combine splitjoin of " +			      filterCount +			      " filters");	LinearPrinter.println(" Filter (expansion) factors:");	for (int i=0; i<filterCount; i++) {	    LinearPrinter.println("   " +				  "(" + this.filterExpansionFactors[i] + ")");	}		// do the expansion of each of the linear reps.	LinearFilterRepresentation[] expandedReps = new LinearFilterRepresentation[filterCount];	int totalOutputs = 0;	int totalStates = 0;	int totalInputs = this.filterExpansionFactors[0].pop;	int peekVal = this.filterExpansionFactors[0].peek;	int currPeek;	int factor;	LinearFilterRepresentation tempRep;	for (int i=0; i<filterCount; i++) {	    LinearPrinter.println("  expanding filter with " + this.filterExpansionFactors[i]);	    factor = this.filterExpansionFactors[i].pop / this.linearRepresentations[i].getPopCount(); 	    tempRep = this.linearRepresentations[i].expand(factor);	    currPeek = tempRep.getPeekCount();	    if(peekVal > currPeek)		expandedReps[i] = tempRep.changePeek(peekVal);	    else		expandedReps[i] = tempRep;	    totalOutputs += expandedReps[i].getPushCount();	    totalStates += expandedReps[i].getStateCount();	}	// figure how how many columns the "stride" is (eg the sum of the weights)	int strideLength = 0;	for (int i=0; i<filterCount; i++) {	    strideLength += this.roundRobinJoinerWeights[i];	}	// now, create new matrices that have the appropriate size:	FilterMatrix expandedA = new FilterMatrix(totalStates, totalStates);	FilterMatrix expandedB = new FilterMatrix(totalStates, totalInputs);	FilterMatrix expandedC = new FilterMatrix(totalOutputs, totalStates);	FilterMatrix expandedD = new FilterMatrix(totalOutputs, totalInputs);	FilterVector expandedInit = new FilterVector(totalStates);	FilterMatrix expandedPreA, expandedPreB;	expandedPreA = null;	expandedPreB = null;	boolean overallPreNeeded = peekVal > totalInputs; 	if(overallPreNeeded) {	    expandedPreA = new FilterMatrix(totalStates, totalStates);	    expandedPreB = new FilterMatrix(totalStates, peekVal-totalInputs);	}	// just do a little paranoia check and ensure that all of the pop counts are the same	for (int i=0; i<filterCount; i++) {	    if (expandedB.getCols() != expandedReps[i].getPopCount()) {		throw new RuntimeException("inconsistency -- expanded reps don't all have the same pop!");	    }	}		// now, copy the rows of the matrices into the expanded versions	// for each expanded matrix, copy joinWeight[i] rows into the new matrix	int startOffset = 0;	int stateOffset = 0;	for (int i=0; i<filterCount; i++) {	    int currStateValue = expandedReps[i].getStateCount();	    // put the filter's state update matrices in the expanded state update matrices	    expandedInit.copyAt(0, stateOffset, expandedReps[i].getInit());	    expandedA.copyAt(stateOffset, stateOffset, expandedReps[i].getA());	    expandedB.copyAt(stateOffset, 0, expandedReps[i].getB());	    if(overallPreNeeded) {		if(expandedReps[i].preworkNeeded()) {		    expandedPreA.copyAt(stateOffset, stateOffset, expandedReps[i].getPreWorkA());		    expandedPreB.copyAt(stateOffset, 0, expandedReps[i].getPreWorkB());		}	    } 	    // figure out how many groups of joinWeight rows that we have	    int numGroups = expandedReps[i].getPushCount() / this.roundRobinJoinerWeights[i]; // total # of groups	    LinearPrinter.println("  number of groups for filter " + i + " is " + numGroups);	    // copy the groups from left (in groups of this.roundRobinJoinerWeights) into the new matrix	    for (int j=0; j<numGroups; j++) {		LinearPrinter.println("  doing group : " + j + " of filter " + i);		LinearPrinter.println("  combination weight: " + this.roundRobinJoinerWeights[i]);		// figure out offset into expanded A to copy the rows		int currentOffset = startOffset + j*strideLength;		// the offset into the current source matrix is (size-j-1)*joinWeights[i]		// the number of rows that we are copying is combination weights[i]		expandedC.copyRowsAndColsAt(currentOffset, stateOffset, expandedReps[i].getC(),					j*this.roundRobinJoinerWeights[i], 0,					this.roundRobinJoinerWeights[i], currStateValue);		expandedD.copyRowsAt(currentOffset, expandedReps[i].getD(),					j*this.roundRobinJoinerWeights[i],					this.roundRobinJoinerWeights[i]);							    }	    // update start of the offset for the next expanded rep. 	    startOffset += this.roundRobinJoinerWeights[i];	    stateOffset += currStateValue;	}	// calculate what the new pop rate is (it needs to the the same for all expanded filters)	// if it is not the same, then we have a problem (specifically, this splitjoin is not	// schedulable....)	int newPopCount = expandedReps[0].getPopCount();	for (int i=0; i<filterCount; i++) {	    if (newPopCount != expandedReps[i].getPopCount()) {		throw new RuntimeException("Inconsistency -- pop counts are not all the same");	    }	}	// now, return a new LinearRepresentation that represents the transformed	// splitjoin with the new matrices, along with the new init vector and peek count.	if(overallPreNeeded)	    return new LinearFilterRepresentation(expandedA,expandedB,expandedC,expandedD,expandedPreA,expandedPreB,expandedInit);	else	    return new LinearFilterRepresentation(expandedA,expandedB,expandedC,expandedD,expandedInit,peekVal);    }