public SafeMatrix Transpose() { SafeMatrix M = new SafeMatrix(m_ColumnCount, m_RowCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_RowCount; j++) { M.m_Elements[i * M.m_ColumnCount + j] = m_Elements[j * m_ColumnCount + i]; } } return M; }
/// <summary> /// Inverts square matrix as long as det != 0. /// </summary> /// <returns>Inverse of matrix.</returns> public SafeMatrix Inverse() { if (!this.IsSquare()) throw new InvalidOperationException("Cannot invert non-square matrix."); double det = this.Determinant(); if (det == 0) throw new InvalidOperationException("Cannot invert (nearly) singular matrix."); SafeMatrix buf = new SafeMatrix(m_ColumnCount, m_ColumnCount); for (int i = 0; i < m_ColumnCount; i++) { for (int j = 0; j < m_ColumnCount; j++) { buf.m_Elements[i * buf.m_ColumnCount + j] = (Math.Pow(-1, i + j) * this.Minor(j, i).Determinant()) / det; } } return buf; }
public SafeMatrix Minor(int row, int col) { // THIS IS THE LOW-LEVEL SOLUTION ~ O(n^2) SafeMatrix buf = new SafeMatrix(m_RowCount - 1, m_ColumnCount - 1); int r = 0; int c = 0; for (int i = 0; i < m_RowCount; i++) { if (i != row) { for (int j = 0; j < m_ColumnCount; j++) { if (j != col) { buf.m_Elements[r * buf.m_ColumnCount + c] = m_Elements[i * m_ColumnCount + j]; c++; } } c = 0; r++; } } return buf; }
public SafeMatrix Clone() { SafeMatrix A = new SafeMatrix(m_RowCount, m_ColumnCount); for (int i = 0; i < m_MatrixSize; i++) A.m_Elements[i] = m_Elements[i]; return A; }
public static double Dot(SafeMatrix v, int vRow, SafeMatrix w, int wCol) { if (v.ColumnCount != w.RowCount) throw new ArgumentException("Vectors must be of the same length."); double buf = 0; for (int i = 0; i < v.ColumnCount; i++) { buf += v.m_Elements[vRow * v.m_ColumnCount + i] * w.m_Elements[i * w.m_ColumnCount + wCol]; } return buf; }
public static SafeMatrix operator *(double x, SafeMatrix A) { SafeMatrix B = new SafeMatrix(A.RowCount, A.ColumnCount); for (int i = 0; i < A.m_MatrixSize; i++) { B.m_Elements[i] = A.m_Elements[i] * x; } return B; }
public static SafeMatrix operator *(SafeMatrix A, SafeMatrix B) { if (A.ColumnCount != B.RowCount) throw new ArgumentException("Inner matrix dimensions must agree."); SafeMatrix C = new SafeMatrix(A.RowCount, B.ColumnCount); for (int i = 0; i < A.RowCount; i++) { for (int j = 0; j < B.ColumnCount; j++) { C.m_Elements[i * C.m_ColumnCount + j] = Dot(A, i, B, j); } } return C; }
public void Solve() { if (m_XValues.Count < 3) throw new InvalidOperationException("Cannot get a linear fit from less than 3 points."); SafeMatrix A = new SafeMatrix(m_XValues.Count, 3); SafeMatrix X = new SafeMatrix(m_XValues.Count, 1); for (int i = 0; i < m_XValues.Count; i++) { A[i, 0] = m_XValues[i] * m_XValues[i]; A[i, 1] = m_XValues[i]; A[i, 2] = 1; X[i, 0] = m_YValues[i]; } SafeMatrix a_T = A.Transpose(); SafeMatrix aa = a_T * A; SafeMatrix aa_inv = aa.Inverse(); SafeMatrix bx = (aa_inv * a_T) * X; m_A = bx[0, 0]; m_B = bx[1, 0]; m_C = bx[2, 0]; m_IsSolved = true; }