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] + ")"); }   LinearFilterRepresentation[] expandedReps = new LinearFilterRepresentation[filterCount]; int totalCols = 0;  for (int i=0; i<filterCount; i++) { LinearPrinter.println("  expanding filter with " + this.filterExpansionFactors[i]); expandedReps[i] = this.linearRepresentations[i].expand(this.filterExpansionFactors[i].peek, this.filterExpansionFactors[i].pop, this.filterExpansionFactors[i].push); totalCols += expandedReps[i].getPushCount(); }   int strideLength = 0; for (int i=0; i<filterCount; i++) { strideLength += this.roundRobinJoinerWeights[i]; }     FilterMatrix expandedA = new FilterMatrix(expandedReps[0].getPeekCount(), totalCols); FilterVector expandedb = new FilterVector(totalCols);   for (int i=0; i<filterCount; i++) { if (expandedA.getRows() != expandedReps[i].getPeekCount()) { throw new RuntimeException("inconsistency -- expanded reps don't all have the same peek!"); } }       int startOffset = 0; for (int i=(filterCount-1); i>=0; i--) {  int numGroups = expandedReps[i].getPushCount() / this.roundRobinJoinerWeights[i]; LinearPrinter.println("  number of groups for filter " + i + " is " + numGroups);  for (int j=0; j<numGroups; j++) { LinearPrinter.println("  doing group : " + j + " of filter " + i); LinearPrinter.println("  combination weight: " + this.roundRobinJoinerWeights[i]);  int currentOffset = startOffset + j*strideLength;   expandedA.copyColumnsAt(currentOffset, expandedReps[i].getA(), j*this.roundRobinJoinerWeights[i], this.roundRobinJoinerWeights[i]); expandedb.copyColumnsAt(currentOffset, expandedReps[i].getb(), j*this.roundRobinJoinerWeights[i], this.roundRobinJoinerWeights[i]);  }  startOffset += this.roundRobinJoinerWeights[i]; }     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"); } }    return new LinearFilterRepresentation(expandedA, expandedb, newPopCount);
at.dms.util.Utils.fail("Not implemented yet."); return null;
    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 totalCols = 0; // totalCols keeps track of the total number of columns in the expanded reps		for (int i=0; i<filterCount; i++) {	    LinearPrinter.println("  expanding filter with " + this.filterExpansionFactors[i]);	    expandedReps[i] = this.linearRepresentations[i].expand(this.filterExpansionFactors[i].peek,								   this.filterExpansionFactors[i].pop,								   this.filterExpansionFactors[i].push);	    totalCols += expandedReps[i].getPushCount();	}	// 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 a new matrix and vector that have the appropriate size:	// cols = the sum of the number of columns in the expanded representations	// rows = (all expanded matrices have the same number of rows)	FilterMatrix expandedA = new FilterMatrix(expandedReps[0].getPeekCount(), totalCols);	FilterVector expandedb = new FilterVector(totalCols);	// just do a little paranoia check and ensure that all of the peek counts are the same	for (int i=0; i<filterCount; i++) {	    if (expandedA.getRows() != expandedReps[i].getPeekCount()) {		throw new RuntimeException("inconsistency -- expanded reps don't all have the same peek!");	    }	}		// now, copy the cols of the matrices (and vectors) into the expanded versions	// for each expanded matrix, copy joinWeight[i] cols into the new matrix and vector	// at an offset that makes the output work out correctly.	// See paper (http://cag.lcs.mit.edu/commit/papers/03/pldi-linear.pdf) Figure 9	// start copying the cols of the right most filter at the appropriate start offset	int startOffset = 0;	for (int i=(filterCount-1); i>=0; i--) { // iterate through filters from right to left	    // figure out how many groups of joinWeight cols 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 columns		int currentOffset = startOffset + j*strideLength;		// the offset into the current source matrix is (size-j-1)*joinWeights[i]		// the number of columns that we are copying is combination weights[i]		expandedA.copyColumnsAt(currentOffset, expandedReps[i].getA(),					j*this.roundRobinJoinerWeights[i],					this.roundRobinJoinerWeights[i]);		expandedb.copyColumnsAt(currentOffset, expandedReps[i].getb(),					j*this.roundRobinJoinerWeights[i],					this.roundRobinJoinerWeights[i]);						    }	    // update start of the offset for the next expanded rep. 	    startOffset += this.roundRobinJoinerWeights[i];	}	// 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 A and b, along with the new pop count.	return new LinearFilterRepresentation(expandedA, expandedb, newPopCount);    }