/// <summary> /// Gets the transpose of a matrix. /// </summary> /// /// <param name="matrix">A matrix.</param> /// /// <returns>The transpose of the given matrix.</returns> /// public static TItem[][] Transpose <TCollection, TItem>(this TCollection matrix) where TCollection : ICollection, IEnumerable <TItem[]> { int rows = matrix.Count; if (rows == 0) { return(new TItem[rows][]); } int cols = matrix.Columns(); #if CHECKS if (!IsRectangular(matrix)) { throw new ArgumentException("Only rectangular matrices can be transposed."); } #endif TItem[][] result = Jagged.Zeros <TItem>(cols, rows); int i = 0; foreach (TItem[] row in matrix) { for (int j = 0; j < result.Length; j++) { result[j][i] = row[j]; } i++; } return(result); }
/// <summary> /// Removes dimensions of length 1 from the array. /// </summary> /// /// <param name="array">The array.</param> /// public static Array Squeeze(this Array array) { int[] dimensions = array.GetLength().Where(x => x != 1).ToArray(); if (dimensions.Length == 0) { dimensions = new[] { 1 } } ; Array res; if (array.IsJagged()) { #if NETSTANDARD1_4 throw new NotSupportedException("Squeeze with jagged arrays is not supported in .NET Standard 1.4."); #else res = Jagged.Zeros(array.GetInnerMostType(), dimensions); Copy(array, res); #endif } else { res = Matrix.Zeros(array.GetInnerMostType(), dimensions); Buffer.BlockCopy(array, 0, res, 0, res.GetNumberOfBytes()); } return(res); }
/// <summary> /// Calculates the scatter matrix of a sample matrix. /// </summary> /// /// <remarks> /// By dividing the Scatter matrix by the sample size, we get the population /// Covariance matrix. By dividing by the sample size minus one, we get the /// sample Covariance matrix. /// </remarks> /// /// <param name="matrix">A number multi-dimensional array containing the matrix values.</param> /// <param name="means">The mean value of the given values, if already known.</param> /// <param name="divisor">A real number to divide each member of the matrix.</param> /// <param name="dimension"> /// Pass 0 if the mean vector is a row vector, 1 otherwise. Default value is 0. /// </param> /// /// <returns>The covariance matrix.</returns> /// public static float[][] Scatter(this float[][] matrix, int dimension, float[] means) { int rows = matrix.Rows(); int cols = matrix.Columns(); float[][] cov; if (dimension == 0) { if (means.Length != cols) throw new ArgumentException("Length of the mean vector should equal the number of columns", "means"); cov = Jagged.Zeros<float>(cols, cols); for (int i = 0; i < cols; i++) { for (int j = i; j < cols; j++) { float s = 0; for (int k = 0; k < rows; k++) { var v = matrix[k][j] - means[j]; s += v * v; } cov[i][j] = s; cov[j][i] = s; } } } else if (dimension == 1) { if (means.Length != rows) throw new ArgumentException("Length of the mean vector should equal the number of rows", "means"); cov = Jagged.Zeros<float>(rows, rows); for (int i = 0; i < rows; i++) { for (int j = i; j < rows; j++) { float s = 0; for (int k = 0; k < cols; k++) { var v = matrix[j][k] - means[j]; s += v * v; } cov[i][j] = s; cov[j][i] = s; } } } else { throw new ArgumentException("Invalid dimension.", "dimension"); } return cov; }
/// <summary> /// Converts a matrix represented as a nested list of lists into a jagged matrix. /// </summary> /// public static T[][] ToJagged <T>(this IList <IList <T> > values) { int rows = values.Rows(); int cols = values.Columns(); T[][] result = Jagged.Zeros <T>(rows, cols); for (int i = 0; i < values.Count; i++) { for (int j = 0; j < values[i].Count; j++) { result[i][j] = values[i][j]; } } return(result); }