/// <summary> /// Sorts the matrix slices into ascending order, according to the <i>natural ordering</i> of the matrix values in the given <i>[row,column]</i> position. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// To sort ranges use sub-ranging viewsd To sort by other dimensions, use dice viewsd To sort descending, use flip views ... /// <p> /// The algorithm compares two 2-d slices at a time, determinining whether one is smaller, equal or larger than the other. /// Comparison is based on the cell <i>[row,column]</i> within a slice. /// Let <i>A</i> and <i>B</i> be two 2-d slicesd Then we have the following rules /// <ul> /// <li><i>A < B iff A.Get(row,column) < B.Get(row,column)</i> /// <li><i>A == B iff A.Get(row,column) == B.Get(row,column)</i> /// <li><i>A > B iff A.Get(row,column) > B.Get(row,column)</i> /// </ul> /// /// @param matrix the matrix to be sorted. /// @param row the index of the row inducing the order. /// @param column the index of the column inducing the order. /// @return a new matrix view having slices sorted by the values of the slice view <i>matrix.viewRow(row).viewColumn(column)</i>. /// <b>Note that the original matrix is left unaffected.</b> /// @throws IndexOutOfRangeException if <i>row %lt; 0 || row >= matrix.Rows || column %lt; 0 || column >= matrix.Columns</i>. /// </summary> public ObjectMatrix3D sort(ObjectMatrix3D matrix, int row, int column) { if (row < 0 || row >= matrix.Rows) { throw new IndexOutOfRangeException("row=" + row + ", matrix=" + Formatter.Shape(matrix)); } if (column < 0 || column >= matrix.Columns) { throw new IndexOutOfRangeException("column=" + column + ", matrix=" + Formatter.Shape(matrix)); } int[] sliceIndexes = new int[matrix.Slices]; // indexes to reorder instead of matrix itself for (int i = sliceIndexes.Length; --i >= 0;) { sliceIndexes[i] = i; } ObjectMatrix1D sliceView = matrix.ViewRow(row).ViewColumn(column); IntComparator comp = new IntComparator((a, b) => { IComparable av = (IComparable)(sliceView[a]); IComparable bv = (IComparable)(sliceView[b]); int r = av.CompareTo(bv); return(r < 0 ? -1 : (r > 0 ? 1 : 0)); }); RunSort(sliceIndexes, 0, sliceIndexes.Length, comp); // view the matrix according to the reordered slice indexes // take all rows and columns in the original order return(matrix.ViewSelection(sliceIndexes, null, null)); }
/// <summary> /// Sorts the matrix slices according to the order induced by the specified comparator. /// The returned view is backed by this matrix, so changes in the returned view are reflected in this matrix, and vice-versa. /// The algorithm compares two slices (2-d matrices) at a time, determinining whether one is smaller, equal or larger than the other. /// To sort ranges use sub-ranging viewsd To sort by other dimensions, use dice viewsd To sort descending, use flip views ... /// <p> /// <b>Example:</b> /// <pre> /// sort by sum of values in a slice /// ObjectMatrix2DComparator comp = new ObjectMatrix2DComparator() { /// public int compare(ObjectMatrix2D a, ObjectMatrix2D b) { /// Object as = a.zSum(); Object bs = b.zSum(); /// return as %lt; bs ? -1 : as == bs ? 0 : 1; /// } /// }; /// sorted = quickSort(matrix,comp); /// </pre> /// /// @param matrix the matrix to be sorted. /// @param c the comparator to determine the order. /// @return a new matrix view having slices sorted as specified. /// <b>Note that the original matrix is left unaffected.</b> /// </summary> public ObjectMatrix3D sort(ObjectMatrix3D matrix, ObjectMatrix2DComparator c) { int[] sliceIndexes = new int[matrix.Slices]; // indexes to reorder instead of matrix itself for (int i = sliceIndexes.Length; --i >= 0;) { sliceIndexes[i] = i; } ObjectMatrix2D[] views = new ObjectMatrix2D[matrix.Slices]; // precompute views for speed for (int i = views.Length; --i >= 0;) { views[i] = matrix.ViewSlice(i); } IntComparator comp = new IntComparator((a, b) => { return(c(views[a], views[b])); }); RunSort(sliceIndexes, 0, sliceIndexes.Length, comp); // view the matrix according to the reordered slice indexes // take all rows and columns in the original order return(matrix.ViewSelection(sliceIndexes, null, null)); }