/// <summary>Extracts this object.</summary> /// <param name="m">Input Matrix.</param> /// <param name="x">Matrix x.</param> /// <param name="y">The y coordinate.</param> /// <param name="width">The width.</param> /// <param name="height">The height.</param> /// <param name="safe">(Optional) true to safe.</param> /// <returns>A Matrix.</returns> public static Matrix Extract(Matrix m, int x, int y, int width, int height, bool safe = true) { Matrix m2 = Matrix.Zeros(height, width); for (int i = y; i < y + height; i++) { for (int j = x; j < x + width; j++) { if (safe && i < m.Rows && j < m.Cols) { m2[i - y, j - x] = m[i, j]; } } } return(m2); }
/// <summary>Subtraction operator.</summary> /// <exception cref="InvalidOperationException">Thrown when the requested operation is invalid.</exception> /// <param name="m1">The first Matrix.</param> /// <param name="m2">The second Matrix.</param> /// <returns>The result of the operation.</returns> public static Matrix operator -(Matrix m1, Matrix m2) { if (m1.Rows != m2.Rows || m1.Cols != m2.Cols) { throw new InvalidOperationException("Dimensions do not match"); } var result = Matrix.Zeros(m1.Rows, m1.Cols); for (int i = 0; i < m1.Rows; i++) { for (int j = 0; j < m1.Cols; j++) { result[i, j] = m1[i, j] - m2[i, j]; } } return(result); }
/// <summary>Modified Gram-Schmidt QR Factorization.</summary> /// <param name="A">Matrix A.</param> /// <returns>Tuple(Q, R)</returns> public static Tuple <Matrix, Matrix> QR(Matrix A) { int n = A.Rows; Matrix R = Matrix.Zeros(n); Matrix Q = A.Copy(); for (int k = 0; k < n; k++) { R[k, k] = Q[k, VectorType.Col].Norm(); Q[k, VectorType.Col] = Q[k, VectorType.Col] / R[k, k]; for (int j = k + 1; j < n; j++) { R[k, j] = Vector.Dot(Q[k, VectorType.Col], A[j, VectorType.Col]); Q[j, VectorType.Col] = Q[j, VectorType.Col] - (R[k, j] * Q[k, VectorType.Col]); } } return(new Tuple <Matrix, Matrix>(Q, R)); }
/// <summary>matrix multiplication.</summary> /// <exception cref="InvalidOperationException">Thrown when the requested operation is invalid.</exception> /// <param name="m1">left hand side.</param> /// <param name="m2">right hand side.</param> /// <returns>matrix.</returns> public static Matrix operator *(Matrix m1, Matrix m2) { if (m1.Cols != m2.Rows) { throw new InvalidOperationException("Invalid multiplication dimenstion"); } var result = Matrix.Zeros(m1.Rows, m2.Cols); for (int i = 0; i < m1.Rows; i++) { for (int j = 0; j < m2.Cols; j++) { for (int k = 0; k < m1.Cols; k++) { result[i, j] += m1[i, k] * m2[k, j]; } } } return(result); }
//---------------- structural /// <summary>Stack a set of vectors into a matrix.</summary> /// <exception cref="InvalidOperationException">Thrown when the requested operation is invalid.</exception> /// <param name="type">.</param> /// <param name="vectors">.</param> /// <returns>A Matrix.</returns> internal static Matrix Stack(VectorType type, params Vector[] vectors) { if (vectors.Length == 0) { throw new InvalidOperationException("Cannot construct Matrix from empty vector set!"); } if (!vectors.All(v => v.Length == vectors[0].Length)) { throw new InvalidOperationException("Vectors must all be of the same length!"); } int n = type == VectorType.Row ? vectors.Length : vectors[0].Length; int d = type == VectorType.Row ? vectors[0].Length : vectors.Length; Matrix m = Matrix.Zeros(n, d); for (int i = 0; i < vectors.Length; i++) { m[i, type] = vectors[i]; } return(m); }