/** * Same as {@link cern.colt.Partitioning#partition(int[],int,int,int[],int,int,int[])} except that * it <i>synchronously</i> partitions the rows of the given matrix by the values of the given * matrix column; This is essentially the same as partitioning a list of composite objects by some * instance variable; In other words, two entire rows of the matrix are swapped, whenever two * column values indicate so. * * <p>Let's say, a "row" is an "object" (tuple, d-dimensional point). A "column" is the list of * "object" values of a given variable (field, dimension). A "matrix" is a list of "objects" * (tuples, points). * * <p>Now, rows (objects, tuples) are partially sorted according to their values in one given * variable (dimension). Two entire rows of the matrix are swapped, whenever two column values * indicate so. * * <p>Note that arguments are not checked for validity. * * <p><b>Example:</b> * * <table border="1" cellspacing="0"> * <tr nowrap> * <td valign="top"><tt>8 x 3 matrix:<br> * 23, 22, 21<br> * 20, 19, 18<br> * 17, 16, 15<br> * 14, 13, 12<br> * 11, 10, 9<br> * 8, 7, 6<br> * 5, 4, 3<br> * 2, 1, 0 </tt></td> * <td align="left" valign="top"> * <p> * <tt>column = 0;<br> * rowIndexes = {0,1,2,..,matrix.rows()-1}; * rowFrom = 0;<br> * rowTo = matrix.rows()-1;<br> * splitters = {5,10,12}<br> * c = 0; <br> * d = splitters.length-1;<br> * partition(matrix,rowIndexes,rowFrom,rowTo,column,splitters,c,d,splitIndexes);<br> * ==><br> * splitIndexes == {0, 2, 3}<br> * rowIndexes == {7, 6, 5, 4, 0, 1, 2, 3}</tt> * </p> * </td> * <td valign="top">The matrix IS NOT REORDERED.<br> * Here is how it would look<br> * like, if it would be reordered<br> * accoring to <tt>rowIndexes</tt>.<br> * <tt>8 x 3 matrix:<br> * 2, 1, 0<br> * 5, 4, 3<br> * 8, 7, 6<br> * 11, 10, 9<br> * 23, 22, 21<br> * 20, 19, 18<br> * 17, 16, 15<br> * 14, 13, 12 </tt></td> * </tr> * </table> * * @param matrix the matrix to be partitioned. * @param rowIndexes the index of the i-th row; is modified by this method to reflect partitioned * indexes. * @param rowFrom the index of the first row (inclusive). * @param rowTo the index of the last row (inclusive). * @param column the index of the column to partition on. * @param splitters the values at which the rows shall be split into intervals. Must be sorted * ascending and must not contain multiple identical values. These preconditions are not * checked; be sure that they are met. * @param splitFrom the index of the first splitter element to be considered. * @param splitTo the index of the last splitter element to be considered. The method considers * the splitter elements <tt>splitters[splitFrom] .. splitters[splitTo]</tt>. * @param splitIndexes a list into which this method fills the indexes of rows delimiting * intervals. Upon return <tt>splitIndexes[splitFrom..splitTo]</tt> will be set accordingly. * Therefore, must satisfy <tt>splitIndexes.length >= splitters.length</tt>. */ public static void partition( ObjectMatrix2D matrix, int[] rowIndexes, int rowFrom, int rowTo, int column, final Object[] splitters, int splitFrom, int splitTo, int[] splitIndexes) { if (rowFrom < 0 || rowTo >= matrix.rows() || rowTo >= rowIndexes.length) throw new IllegalArgumentException(); if (column < 0 || column >= matrix.columns()) throw new IllegalArgumentException(); if (splitFrom < 0 || splitTo >= splitters.length) throw new IllegalArgumentException(); if (splitIndexes.length < splitters.length) throw new IllegalArgumentException(); // this one knows how to swap two row indexes (a,b) final int[] g = rowIndexes; Swapper swapper = new Swapper() { public void swap(int b, int c) { int tmp = g[b]; g[b] = g[c]; g[c] = tmp; } }; // compare splitter[a] with columnView[rowIndexes[b]] final ObjectMatrix1D columnView = matrix.viewColumn(column); IntComparator comp = new IntComparator() { public int compare(int a, int b) { Comparable av = (Comparable) (splitters[a]); Comparable bv = (Comparable) (columnView.getQuick(g[b])); int r = av.compareTo(bv); return r < 0 ? -1 : (r == 0 ? 0 : 1); } }; // compare columnView[rowIndexes[a]] with columnView[rowIndexes[b]] IntComparator comp2 = new IntComparator() { public int compare(int a, int b) { Comparable av = (Comparable) (columnView.getQuick(g[a])); Comparable bv = (Comparable) (columnView.getQuick(g[b])); int r = av.compareTo(bv); return r < 0 ? -1 : (r == 0 ? 0 : 1); } }; // compare splitter[a] with splitter[b] IntComparator comp3 = new IntComparator() { public int compare(int a, int b) { Comparable av = (Comparable) (splitters[a]); Comparable bv = (Comparable) (splitters[b]); int r = av.compareTo(bv); return r < 0 ? -1 : (r == 0 ? 0 : 1); } }; // generic partitioning does the main work of reordering row indexes cern.colt.Partitioning.genericPartition( rowFrom, rowTo, splitFrom, splitTo, splitIndexes, comp, comp2, comp3, swapper); }