// required implementations of abstract methods /// <inheritdoc /> public override double this[int r, int c] { get { if ((r < 0) || (r >= rows)) { throw new ArgumentOutOfRangeException(nameof(r)); } if ((c < 0) || (c >= cols)) { throw new ArgumentOutOfRangeException(nameof(c)); } return(store[MatrixAlgorithms.GetIndex(offset, rowStride, colStride, r, c)]); } set { if ((r < 0) || (r >= rows)) { throw new ArgumentOutOfRangeException(nameof(r)); } if ((c < 0) || (c >= cols)) { throw new ArgumentOutOfRangeException(nameof(c)); } if (IsReadOnly) { throw new InvalidOperationException(); } store[MatrixAlgorithms.GetIndex(offset, rowStride, colStride, r, c)] = value; } }
/// <summary> /// Gets or sets an entry of the matrix. /// </summary> /// <param name="r">The (zero-based) row number.</param> /// <param name="c">The (zero-based) column number.</param> /// <returns>The value of the specified matrix entry M<sub>r c</sub>.</returns> public override double this[int r, int c] { get { CheckBounds(r, c); return(store[MatrixAlgorithms.GetIndex(offset, rowStride, colStride, r, c)]); } set { CheckBounds(r, c); if (IsReadOnly) { throw new InvalidOperationException(); } store[MatrixAlgorithms.GetIndex(offset, rowStride, colStride, r, c)] = value; } }
/// <summary> /// Initializes a rectangular matrix from the given 2D array. /// </summary> /// <param name="source">The source 2D array.</param> public RectangularMatrix(double[,] source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } rows = source.GetLength(0); cols = source.GetLength(1); store = MatrixAlgorithms.AllocateStorage(rows, cols, ref offset, ref rowStride, ref colStride); for (int r = 0; r < rows; r++) { for (int c = 0; c < cols; c++) { store[MatrixAlgorithms.GetIndex(rows, cols, r, c)] = source[r, c]; } } }
// EIGENVALUE ALGORITHMS // public static Complex[] ReduceToRealSchurForm(double[] aStore, double[] qStore, int dimension) { // keep track of eigenvalues Complex[] eigenvalues = new Complex[dimension]; // keep track of interations int count = 0; // isolate the upper and lower boundaries of the curent subproblem // p is the upper index, n the lower index int n = dimension - 1; while (n >= 0) { // move up the matrix from endpoint n, looking for subdiagonal elements negligible compared to the neighboring diagonal elements // if we find one, that reduces the problem to the submatrix between p and n int p = n; while (p > 0) { double d = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p)) + Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p - 1)); double e = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p - 1)); if (d + e == d) { // double f = d * Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p, p) - MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p - 1)); // double g = e * Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, p - 1, p)); // if (f + g == f) { MatrixAlgorithms.SetEntry(aStore, dimension, dimension, p, p - 1, 0.0); break; // } } p--; } /* * if (p == n) { * // one eigenvalue * // reduce n and re-set count * } else { * // compute m, matrix elements * // reduce n and re-set count * if (p == m) { * // two eigenvalues * } else { * // do step * } * } */ //Print(a, dimension, p, n); // get the (indexes for) the entries in the trailing 2x2 matrix int m = n - 1; int ammi = MatrixAlgorithms.GetIndex(dimension, dimension, m, m); int amni = MatrixAlgorithms.GetIndex(dimension, dimension, m, n); int anmi = MatrixAlgorithms.GetIndex(dimension, dimension, n, m); int anni = MatrixAlgorithms.GetIndex(dimension, dimension, n, n); if (n - p > 1) { count++; if (count > 32) { throw new NonconvergenceException(); } double tr = aStore[ammi] + aStore[anni]; double det = aStore[ammi] * aStore[anni] - aStore[amni] * aStore[anmi]; // ad hoc shift if ((count == 8) || (count == 16) || (count == 24)) { double w = Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n, n - 1)) + Math.Abs(MatrixAlgorithms.GetEntry(aStore, dimension, dimension, n - 1, n - 2)); tr = 2.0 * w; det = w * w; } FrancisTwoStep(aStore, qStore, dimension, p, n, tr, det); } else { if (p == n) { eigenvalues[n] = aStore[anni]; } else if (p == m) { double sn, cn; TwoByTwoRealSchur(ref aStore[ammi], ref aStore[amni], ref aStore[anmi], ref aStore[anni], out sn, out cn, out eigenvalues[m], out eigenvalues[n]); // Multiply A from left by the rotation matrix R for (int cc = p + 2; cc < dimension; cc++) { int i = MatrixAlgorithms.GetIndex(dimension, dimension, p, cc); int j = MatrixAlgorithms.GetIndex(dimension, dimension, p + 1, cc); double t = aStore[i]; aStore[i] = cn * t + sn * aStore[j]; aStore[j] = cn * aStore[j] - sn * t; } // Multiply A from the right by R^T for (int rr = 0; rr < p; rr++) { int i = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p); int j = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p + 1); double t = aStore[i]; aStore[i] = cn * t + sn * aStore[j]; aStore[j] = cn * aStore[j] - sn * t; } // Multiply Q^T from the left by R if (qStore != null) { for (int rr = 0; rr < dimension; rr++) { int i = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p); int j = MatrixAlgorithms.GetIndex(dimension, dimension, rr, p + 1); double t = qStore[i]; qStore[i] = cn * t + sn * qStore[j]; qStore[j] = cn * qStore[j] - sn * t; } } } n = p - 1; count = 0; } } return(eigenvalues); }