/// <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> /// Replaces all cell values of the receiver with the values of another matrix. /// Both matrices must have the same number of Slices, Rows and Columns. /// If both matrices share the same cells (as is the case if they are views derived from the same matrix) and intersect in an ambiguous way, then replaces <i>as if</i> using an intermediate auxiliary deep copy of <i>other</i>. /// </summary> /// <param name="source">the source matrix to copy from (may be identical to the receiver).</param> /// <returns><i>this</i> (for convenience only).</returns> /// <exception cref="ArgumentException">if <i>Slices != source.Slices || Rows != source.Rows || Columns != source.Columns</i></exception> public override ObjectMatrix3D Assign(ObjectMatrix3D source) { // overriden for performance only if (!(source is DenseObjectMatrix3D)) { return(base.Assign(source)); } DenseObjectMatrix3D other = (DenseObjectMatrix3D)source; if (other == this) { return(this); } CheckShape(other); if (HaveSharedCells(other)) { ObjectMatrix3D c = other.Copy(); if (!(c is DenseObjectMatrix3D)) { // should not happen return(base.Assign(source)); } other = (DenseObjectMatrix3D)c; } if (!this.IsView && !other.IsView) { // quickest Array.Copy(other.Elements, 0, this.Elements, 0, this.Elements.Length); return(this); } return(base.Assign(other)); }
/// <summary> /// Returns <i>true</i> if both matrices share at least one identical cell. /// </summary> protected new Boolean HaveSharedCellsRaw(ObjectMatrix3D other) { if (other is SelectedSparseObjectMatrix3D) { SelectedSparseObjectMatrix3D otherMatrix = (SelectedSparseObjectMatrix3D)other; return(this.Elements == otherMatrix.Elements); } else if (other is SparseObjectMatrix3D) { SparseObjectMatrix3D otherMatrix = (SparseObjectMatrix3D)other; return(this.Elements == otherMatrix.Elements); } return(false); }
/// <summary> /// Returns a string <i>s</i> such that <i>Object[] m = s</i> is a legal C# statement. /// </summary> /// <param name="matrix">the matrix to format.</param> /// <returns></returns> public String ToSourceCode(ObjectMatrix3D matrix) { Formatter copy = (Formatter)this.Clone(); String b3 = Blanks(3); String b6 = Blanks(6); copy.SetPrintShape(false); copy.SetColumnSeparator(", "); copy.SetRowSeparator("},\n" + b6 + "{"); copy.SetSliceSeparator("}\n" + b3 + "},\n" + b3 + "{\n" + b6 + "{"); String lead = "{\n" + b3 + "{\n" + b6 + "{"; String trail = "}\n" + b3 + "}\n}"; return(lead + copy.ToString(matrix) + trail); }
/// <summary> /// Returns a string representation of the given matrix with axis as well as rows and columns labeled. /// Pass <i>null</i> to one or more parameters to indicate that the corresponding decoration element shall not appear in the string converted matrix. /// </summary> /// <param name="matrix">The matrix to format.</param> /// <param name="sliceNames">The headers of all slices (to be put above each slice).</param> /// <param name="rowNames">The headers of all rows (to be put to the left of the matrix).</param> /// <param name="columnNames">The headers of all columns (to be put to above the matrix).</param> /// <param name="sliceAxisName">The label of the z-axis (to be put above each slice).</param> /// <param name="rowAxisName">The label of the y-axis.</param> /// <param name="columnAxisName">The label of the x-axis.</param> /// <param name="title">The overall title of the matrix to be formatted.</param> /// <returns>the matrix converted to a string.</returns> public String ToTitleString(ObjectMatrix3D matrix, String[] sliceNames, String[] rowNames, String[] columnNames, String sliceAxisName, String rowAxisName, String columnAxisName, String title) { if (matrix.Size == 0) { return("Empty matrix"); } StringBuilder buf = new StringBuilder(); for (int i = 0; i < matrix.Slices; i++) { if (i != 0) { buf.Append(sliceSeparator); } buf.Append(ToTitleString(matrix.ViewSlice(i), rowNames, columnNames, rowAxisName, columnAxisName, title + "\n" + sliceAxisName + "=" + sliceNames[i])); } return(buf.ToString()); }
/// <summary> /// Returns a string representation of the given matrix. /// </summary> /// <param name="matrix">the matrix to convert.</param> /// <returns></returns> public String ToString(ObjectMatrix3D matrix) { StringBuilder buf = new StringBuilder(); Boolean oldPrintShape = this.printShape; this.printShape = false; for (int slice = 0; slice < matrix.Slices; slice++) { if (slice != 0) { buf.Append(sliceSeparator); } buf.Append(ToString(matrix.ViewSlice(slice))); } this.printShape = oldPrintShape; if (printShape) { buf.Insert(0, Shape(matrix) + "\n"); } return(buf.ToString()); }
/// <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)); }