From 31eda8d8b07fdde276d3d6e7311ba5a849f7dd5a Mon Sep 17 00:00:00 2001 From: Christoph Ruegg Date: Sun, 22 Sep 2013 15:22:11 +0200 Subject: [PATCH] LA: Make builder much more complete --- src/Numerics/LinearAlgebra/Builder.cs | 863 ++++++++++++++++-- .../LinearAlgebra/Factorization/LU.cs | 2 +- .../LinearAlgebra/Matrix.Arithmetic.cs | 4 +- src/Numerics/LinearAlgebra/Matrix.Solve.cs | 26 +- src/Numerics/LinearAlgebra/Matrix.cs | 10 +- .../LinearAlgebra/Solvers/Iterator.cs | 2 +- .../LinearAlgebra/Storage/MatrixStorage.cs | 2 +- .../LinearAlgebra/Storage/VectorStorage.cs | 2 +- .../LinearAlgebra/Vector.Arithmetic.cs | 4 +- src/Numerics/LinearAlgebra/Vector.cs | 2 +- 10 files changed, 821 insertions(+), 96 deletions(-) diff --git a/src/Numerics/LinearAlgebra/Builder.cs b/src/Numerics/LinearAlgebra/Builder.cs index a63bfd15..c9cc55a0 100644 --- a/src/Numerics/LinearAlgebra/Builder.cs +++ b/src/Numerics/LinearAlgebra/Builder.cs @@ -29,45 +29,64 @@ // using System; +using System.Collections.Generic; +using System.Linq; +using MathNet.Numerics.Distributions; using MathNet.Numerics.LinearAlgebra.Solvers; +using MathNet.Numerics.LinearAlgebra.Storage; namespace MathNet.Numerics.LinearAlgebra.Double { using Solvers; - internal class GenericBuilder : IGenericBuilder + internal class Builder : Builder { - public double Zero + public override double Zero { get { return 0d; } } - public double One + public override double One { get { return 1d; } } - public Matrix DenseMatrix(int rows, int columns) + public override Matrix DenseMatrix(DenseColumnMajorMatrixStorage storage) { - return new DenseMatrix(rows, columns); + return new DenseMatrix(storage); } - public Matrix SparseMatrix(int rows, int columns) + public override Matrix SparseMatrix(SparseCompressedRowMatrixStorage storage) { - return new SparseMatrix(rows, columns); + return new SparseMatrix(storage); } - public Vector DenseVector(int size) + public override Matrix DiagonalMatrix(DiagonalMatrixStorage storage) { - return new DenseVector(size); + return new DiagonalMatrix(storage); } - public Vector SparseVector(int size) + public override Vector DenseVector(DenseVectorStorage storage) { - return new SparseVector(size); + return new DenseVector(storage); } - public IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations) + public override Vector SparseVector(SparseVectorStorage storage) + { + return new SparseVector(storage); + } + + public override Matrix DenseMatrixRandom(int rows, int columns, IContinuousDistribution distribution) + { + return Double.DenseMatrix.CreateRandom(rows, columns, distribution); + } + + public override Vector DenseVectorRandom(int length, IContinuousDistribution distribution) + { + return new DenseVector(DenseVectorStorage.OfInit(length, i => distribution.Sample())); + } + + public override IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000) { return new IIterationStopCriterium[] { @@ -84,39 +103,54 @@ namespace MathNet.Numerics.LinearAlgebra.Single { using Solvers; - internal class GenericBuilder : IGenericBuilder + internal class Builder : Builder { - public float Zero + public override float Zero { get { return 0f; } } - public float One + public override float One { get { return 1f; } } - public Matrix DenseMatrix(int rows, int columns) + public override Matrix DenseMatrix(DenseColumnMajorMatrixStorage storage) + { + return new DenseMatrix(storage); + } + + public override Matrix SparseMatrix(SparseCompressedRowMatrixStorage storage) { - return new DenseMatrix(rows, columns); + return new SparseMatrix(storage); } - public Matrix SparseMatrix(int rows, int columns) + public override Matrix DiagonalMatrix(DiagonalMatrixStorage storage) { - return new SparseMatrix(rows, columns); + return new DiagonalMatrix(storage); } - public Vector DenseVector(int size) + public override Vector DenseVector(DenseVectorStorage storage) { - return new DenseVector(size); + return new DenseVector(storage); } - public Vector SparseVector(int size) + public override Vector SparseVector(SparseVectorStorage storage) { - return new SparseVector(size); + return new SparseVector(storage); } - public IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations) + public override Matrix DenseMatrixRandom(int rows, int columns, IContinuousDistribution distribution) + { + return Single.DenseMatrix.CreateRandom(rows, columns, distribution); + } + + public override Vector DenseVectorRandom(int length, IContinuousDistribution distribution) + { + return new DenseVector(DenseVectorStorage.OfInit(length, i => (float)distribution.Sample())); + } + + public override IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000) { return new IIterationStopCriterium[] { @@ -137,41 +171,57 @@ namespace MathNet.Numerics.LinearAlgebra.Complex using Complex = Numerics.Complex; #else using Complex = System.Numerics.Complex; + #endif - internal class GenericBuilder : IGenericBuilder + internal class Builder : Builder { - public Complex Zero + public override Complex Zero { get { return Complex.Zero; } } - public Complex One + public override Complex One { get { return Complex.One; } } - public Matrix DenseMatrix(int rows, int columns) + public override Matrix DenseMatrix(DenseColumnMajorMatrixStorage storage) { - return new DenseMatrix(rows, columns); + return new DenseMatrix(storage); } - public Matrix SparseMatrix(int rows, int columns) + public override Matrix SparseMatrix(SparseCompressedRowMatrixStorage storage) { - return new SparseMatrix(rows, columns); + return new SparseMatrix(storage); } - public Vector DenseVector(int size) + public override Matrix DiagonalMatrix(DiagonalMatrixStorage storage) { - return new DenseVector(size); + return new DiagonalMatrix(storage); } - public Vector SparseVector(int size) + public override Vector DenseVector(DenseVectorStorage storage) { - return new SparseVector(size); + return new DenseVector(storage); } - public IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations) + public override Vector SparseVector(SparseVectorStorage storage) + { + return new SparseVector(storage); + } + + public override Matrix DenseMatrixRandom(int rows, int columns, IContinuousDistribution distribution) + { + return LinearAlgebra.Complex.DenseMatrix.CreateRandom(rows, columns, distribution); + } + + public override Vector DenseVectorRandom(int length, IContinuousDistribution distribution) + { + return new DenseVector(DenseVectorStorage.OfInit(length, i => new Complex(distribution.Sample(), distribution.Sample()))); + } + + public override IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000) { return new IIterationStopCriterium[] { @@ -188,39 +238,54 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 { using Solvers; - internal class GenericBuilder : IGenericBuilder + internal class Builder : Builder { - public Numerics.Complex32 Zero + public override Numerics.Complex32 Zero { get { return Numerics.Complex32.Zero; } } - public Numerics.Complex32 One + public override Numerics.Complex32 One { get { return Numerics.Complex32.One; } } - public Matrix DenseMatrix(int rows, int columns) + public override Matrix DenseMatrix(DenseColumnMajorMatrixStorage storage) + { + return new DenseMatrix(storage); + } + + public override Matrix SparseMatrix(SparseCompressedRowMatrixStorage storage) + { + return new SparseMatrix(storage); + } + + public override Matrix DiagonalMatrix(DiagonalMatrixStorage storage) { - return new DenseMatrix(rows, columns); + return new DiagonalMatrix(storage); } - public Matrix SparseMatrix(int rows, int columns) + public override Vector DenseVector(DenseVectorStorage storage) { - return new SparseMatrix(rows, columns); + return new DenseVector(storage); } - public Vector DenseVector(int size) + public override Vector SparseVector(SparseVectorStorage storage) { - return new DenseVector(size); + return new SparseVector(storage); } - public Vector SparseVector(int size) + public override Matrix DenseMatrixRandom(int rows, int columns, IContinuousDistribution distribution) { - return new SparseVector(size); + return Complex32.DenseMatrix.CreateRandom(rows, columns, distribution); } - public IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations) + public override Vector DenseVectorRandom(int length, IContinuousDistribution distribution) + { + return new DenseVector(DenseVectorStorage.OfInit(length, i => new Numerics.Complex32((float)distribution.Sample(), (float)distribution.Sample()))); + } + + public override IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000) { return new IIterationStopCriterium[] { @@ -240,6 +305,7 @@ namespace MathNet.Numerics.LinearAlgebra using Complex64 = Numerics.Complex; #else using Complex64 = System.Numerics.Complex; + #endif /// @@ -247,82 +313,741 @@ namespace MathNet.Numerics.LinearAlgebra /// must be created in a generic way. Usage of generic builders should not be /// required in normal user code. /// - public interface IGenericBuilder where T : struct, IEquatable, IFormattable + public abstract class Builder where T : struct, IEquatable, IFormattable { /// /// Gets the value of 0.0 for type T. /// - T Zero { get; } + public abstract T Zero { get; } /// /// Gets the value of 1.0 for type T. /// - T One { get; } + public abstract T One { get; } /// - /// Create a dense matrix of T with the given number of rows and columns. + /// Create a new matrix straight from an initialized matrix storage instance. + /// If you have an instance of a discrete storage type instead, use their direct methods instead. /// - /// The number of rows. - /// The number of columns. - Matrix DenseMatrix(int rows, int columns); + public Matrix Matrix(MatrixStorage storage) + { + var dense = storage as DenseColumnMajorMatrixStorage; + if (dense != null) return DenseMatrix(dense); + + var sparse = storage as SparseCompressedRowMatrixStorage; + if (sparse != null) return SparseMatrix(sparse); + + var diagonal = storage as DiagonalMatrixStorage; + if (diagonal != null) return DiagonalMatrix(diagonal); + + throw new NotSupportedException(); + } + + /// + /// Create a new vector straight from an initialized matrix storage instance. + /// If you have an instance of a discrete storage type instead, use their direct methods instead. + /// + public Vector Vector(VectorStorage storage) + { + var dense = storage as DenseVectorStorage; + if (dense != null) return DenseVector(dense); + + var sparse = storage as SparseVectorStorage; + if (sparse != null) return SparseVector(sparse); + + throw new NotSupportedException(); + } + + /// + /// Create a new dense matrix straight from an initialized matrix storage instance. + /// The storage is used directly without copying. + /// Intended for advanced scenarios where you're working directly with + /// storage for performance or interop reasons. + /// + public abstract Matrix DenseMatrix(DenseColumnMajorMatrixStorage storage); + + /// + /// Create a new dense matrix with the given number of rows and columns. + /// All cells of the matrix will be initialized to zero. + /// Zero-length matrices are not supported. + /// + public Matrix DenseMatrix(int rows, int columns) + { + return DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns)); + } + + /// + /// Create a new dense matrix with the given number of rows and columns directly binding to a raw array. + /// The array is assumed to be in column-major order (column by column) and is used directly without copying. + /// Very efficient, but changes to the array and the matrix will affect each other. + /// + /// + public Matrix DenseMatrix(int rows, int columns, T[] storage) + { + return DenseMatrix(new DenseColumnMajorMatrixStorage(rows, columns, storage)); + } + + /// + /// Create a new dense matrix and initialize each value to the same provided value. + /// + public Matrix DenseMatrix(int rows, int columns, T value) + { + if (Zero.Equals(value)) return DenseMatrix(rows, columns); + return DenseMatrix(DenseColumnMajorMatrixStorage.OfInit(rows, columns, (i, j) => value)); + } + + /// + /// Create a new dense matrix and initialize each value using the provided init function. + /// + public Matrix DenseMatrix(int rows, int columns, Func init) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfInit(rows, columns, init)); + } + + /// + /// Create a new diagonal dense matrix and initialize each diagonal value to the same provided value. + /// + public Matrix DenseMatrixDiagonal(int rows, int columns, T value) + { + if (Zero.Equals(value)) return DenseMatrix(rows, columns); + return DenseMatrix(DenseColumnMajorMatrixStorage.OfDiagonalInit(rows, columns, i => value)); + } + + /// + /// Create a new diagonal dense matrix and initialize each diagonal value using the provided init function. + /// + public Matrix DenseMatrixDiagonal(int rows, int columns, Func init) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfDiagonalInit(rows, columns, init)); + } + + /// + /// Create a new dense matrix with values sampled from the provided random distribution. + /// + public abstract Matrix DenseMatrixRandom(int rows, int columns, IContinuousDistribution distribution); + + /// + /// Create a new dense matrix as a copy of the given other matrix. + /// This new matrix will be independent from the other matrix. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfMatrix(Matrix matrix) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfMatrix(matrix.Storage)); + } + + /// + /// Create a new dense matrix as a copy of the given two-dimensional array. + /// This new matrix will be independent from the provided array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfArray(T[,] array) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfArray(array)); + } + + /// + /// Create a new dense matrix as a copy of the given indexed enumerable. + /// Keys must be provided at most once, zero is assumed if a key is omitted. + /// This new matrix will be independent from the enumerable. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfIndexed(int rows, int columns, IEnumerable> enumerable) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfIndexedEnumerable(rows, columns, enumerable)); + } + + /// + /// Create a new dense matrix as a copy of the given enumerable. + /// The enumerable is assumed to be in column-major order (column by column). + /// This new matrix will be independent from the enumerable. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfColumnMajor(int rows, int columns, IEnumerable columnMajor) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfColumnMajorEnumerable(rows, columns, columnMajor)); + } + + /// + /// Create a new dense matrix as a copy of the given enumerable of enumerable columns. + /// Each enumerable in the master enumerable specifies a column. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfColumns(IEnumerable> data) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfColumnArrays(data.Select(v => v.ToArray()).ToArray())); + } + + /// + /// Create a new dense matrix as a copy of the given enumerable of enumerable columns. + /// Each enumerable in the master enumerable specifies a column. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfColumns(int rows, int columns, IEnumerable> data) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfColumnEnumerables(rows, columns, data)); + } + + /// + /// Create a new dense matrix of T as a copy of the given column arrays. + /// This new matrix will be independent from the arrays. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfColumnArrays(params T[][] columns) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfColumnArrays(columns)); + } + + /// + /// Create a new dense matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return DenseMatrix(DenseColumnMajorMatrixStorage.OfColumnVectors(storage)); + } + + /// + /// Create a new dense matrix as a copy of the given enumerable of enumerable rows. + /// Each enumerable in the master enumerable specifies a row. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfRows(IEnumerable> data) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfRowArrays(data.Select(v => v.ToArray()).ToArray())); + } + + /// + /// Create a new dense matrix as a copy of the given enumerable of enumerable rows. + /// Each enumerable in the master enumerable specifies a row. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfRows(int rows, int columns, IEnumerable> data) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfRowEnumerables(rows, columns, data)); + } + + /// + /// Create a new dense matrix of T as a copy of the given row arrays. + /// This new matrix will be independent from the arrays. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfRowArrays(params T[][] rows) + { + return DenseMatrix(DenseColumnMajorMatrixStorage.OfRowArrays(rows)); + } + + /// + /// Create a new dense matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return DenseMatrix(DenseColumnMajorMatrixStorage.OfRowVectors(storage)); + } + + /// + /// Create a new dense matrix with the diagonal as a copy of the given vector. + /// This new matrix will be independent from the vector. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfDiagonalVector(Vector diagonal) + { + var m = DenseMatrix(diagonal.Count, diagonal.Count); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new dense matrix with the diagonal as a copy of the given vector. + /// This new matrix will be independent from the vector. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfDiagonalVector(int rows, int columns, Vector diagonal) + { + var m = DenseMatrix(rows, columns); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new dense matrix with the diagonal as a copy of the given array. + /// This new matrix will be independent from the array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfDiagonalArray(T[] diagonal) + { + var m = DenseMatrix(diagonal.Length, diagonal.Length); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new dense matrix with the diagonal as a copy of the given array. + /// This new matrix will be independent from the array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix DenseMatrixOfDiagonalArray(int rows, int columns, T[] diagonal) + { + var m = DenseMatrix(rows, columns); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new sparse matrix straight from an initialized matrix storage instance. + /// The storage is used directly without copying. + /// Intended for advanced scenarios where you're working directly with + /// storage for performance or interop reasons. + /// + public abstract Matrix SparseMatrix(SparseCompressedRowMatrixStorage storage); /// /// Create a sparse matrix of T with the given number of rows and columns. /// /// The number of rows. /// The number of columns. - Matrix SparseMatrix(int rows, int columns); + public Matrix SparseMatrix(int rows, int columns) + { + return SparseMatrix(new SparseCompressedRowMatrixStorage(rows, columns)); + } + + /// + /// Create a new sparse matrix and initialize each value to the same provided value. + /// + public Matrix SparseMatrix(int rows, int columns, T value) + { + if (Zero.Equals(value)) return SparseMatrix(rows, columns); + return SparseMatrix(SparseCompressedRowMatrixStorage.OfInit(rows, columns, (i, j) => value)); + } + + /// + /// Create a new sparse matrix and initialize each value using the provided init function. + /// + public Matrix SparseMatrix(int rows, int columns, Func init) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfInit(rows, columns, init)); + } + + /// + /// Create a new diagonal sparse matrix and initialize each diagonal value to the same provided value. + /// + public Matrix SparseMatrixDiagonal(int rows, int columns, T value) + { + if (Zero.Equals(value)) return SparseMatrix(rows, columns); + return SparseMatrix(SparseCompressedRowMatrixStorage.OfDiagonalInit(rows, columns, i => value)); + } + + /// + /// Create a new diagonal sparse matrix and initialize each diagonal value using the provided init function. + /// + public Matrix SparseMatrixDiagonal(int rows, int columns, Func init) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfDiagonalInit(rows, columns, init)); + } + + /// + /// Create a new sparse matrix as a copy of the given other matrix. + /// This new matrix will be independent from the other matrix. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfMatrix(Matrix matrix) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfMatrix(matrix.Storage)); + } + + /// + /// Create a new sparse matrix as a copy of the given two-dimensional array. + /// This new matrix will be independent from the provided array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfArray(T[,] array) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfArray(array)); + } + + /// + /// Create a new sparse matrix as a copy of the given indexed enumerable. + /// Keys must be provided at most once, zero is assumed if a key is omitted. + /// This new matrix will be independent from the enumerable. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfIndexed(int rows, int columns, IEnumerable> enumerable) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfIndexedEnumerable(rows, columns, enumerable)); + } + + /// + /// Create a new sparse matrix as a copy of the given enumerable. + /// The enumerable is assumed to be in row-major order (row by row). + /// This new matrix will be independent from the enumerable. + /// A new memory block will be allocated for storing the vector. + /// + /// + public Matrix SparseMatrixOfRowMajor(int rows, int columns, IEnumerable rowMajor) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfRowMajorEnumerable(rows, columns, rowMajor)); + } + + /// + /// Create a new sparse matrix with the given number of rows and columns as a copy of the given array. + /// The array is assumed to be in column-major order (column by column). + /// This new matrix will be independent from the provided array. + /// A new memory block will be allocated for storing the matrix. + /// + /// + public Matrix SparseMatrixOfColumnMajor(int rows, int columns, IList columnMajor) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnMajorList(rows, columns, columnMajor)); + } + + /// + /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. + /// Each enumerable in the master enumerable specifies a column. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfColumns(IEnumerable> data) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnArrays(data.Select(v => v.ToArray()).ToArray())); + } + + /// + /// Create a new sparse matrix as a copy of the given enumerable of enumerable columns. + /// Each enumerable in the master enumerable specifies a column. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfColumns(int rows, int columns, IEnumerable> data) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnEnumerables(rows, columns, data)); + } + + /// + /// Create a new sparse matrix as a copy of the given column arrays. + /// This new matrix will be independent from the arrays. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfColumnArrays(params T[][] columns) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnArrays(columns)); + } + + /// + /// Create a new sparse matrix as a copy of the given column vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfColumnVectors(params Vector[] columns) + { + var storage = new VectorStorage[columns.Length]; + for (int i = 0; i < columns.Length; i++) + { + storage[i] = columns[i].Storage; + } + return SparseMatrix(SparseCompressedRowMatrixStorage.OfColumnVectors(storage)); + } + + /// + /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. + /// Each enumerable in the master enumerable specifies a row. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfRows(IEnumerable> data) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfRowArrays(data.Select(v => v.ToArray()).ToArray())); + } + + /// + /// Create a new sparse matrix as a copy of the given enumerable of enumerable rows. + /// Each enumerable in the master enumerable specifies a row. + /// This new matrix will be independent from the enumerables. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfRows(int rows, int columns, IEnumerable> data) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfRowEnumerables(rows, columns, data)); + } + + /// + /// Create a new sparse matrix as a copy of the given row arrays. + /// This new matrix will be independent from the arrays. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfRowArrays(params T[][] rows) + { + return SparseMatrix(SparseCompressedRowMatrixStorage.OfRowArrays(rows)); + } + + /// + /// Create a new sparse matrix as a copy of the given row vectors. + /// This new matrix will be independent from the vectors. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfRowVectors(params Vector[] rows) + { + var storage = new VectorStorage[rows.Length]; + for (int i = 0; i < rows.Length; i++) + { + storage[i] = rows[i].Storage; + } + return SparseMatrix(SparseCompressedRowMatrixStorage.OfRowVectors(storage)); + } + + /// + /// Create a new sparse matrix with the diagonal as a copy of the given vector. + /// This new matrix will be independent from the vector. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfDiagonalVector(Vector diagonal) + { + var m = SparseMatrix(diagonal.Count, diagonal.Count); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new sparse matrix with the diagonal as a copy of the given vector. + /// This new matrix will be independent from the vector. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfDiagonalVector(int rows, int columns, Vector diagonal) + { + var m = SparseMatrix(rows, columns); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new sparse matrix with the diagonal as a copy of the given array. + /// This new matrix will be independent from the array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfDiagonalArray(T[] diagonal) + { + var m = SparseMatrix(diagonal.Length, diagonal.Length); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new sparse matrix with the diagonal as a copy of the given array. + /// This new matrix will be independent from the array. + /// A new memory block will be allocated for storing the matrix. + /// + public Matrix SparseMatrixOfDiagonalArray(int rows, int columns, T[] diagonal) + { + var m = SparseMatrix(rows, columns); + m.SetDiagonal(diagonal); + return m; + } + + /// + /// Create a new diagonal matrix straight from an initialized matrix storage instance. + /// The storage is used directly without copying. + /// Intended for advanced scenarios where you're working directly with + /// storage for performance or interop reasons. + /// + public abstract Matrix DiagonalMatrix(DiagonalMatrixStorage storage); + + /// + /// Create a new dense vector straight from an initialized vector storage instance. + /// The storage is used directly without copying. + /// Intended for advanced scenarios where you're working directly with + /// storage for performance or interop reasons. + /// + public abstract Vector DenseVector(DenseVectorStorage storage); /// /// Create a dense vector of T with the given size. /// /// The size of the vector. - Vector DenseVector(int size); + public Vector DenseVector(int size) + { + return DenseVector(new DenseVectorStorage(size)); + } + + /// + /// Create a dense vector of T that is directly bound to the specified array. + /// + public Vector DenseVector(T[] array) + { + return DenseVector(new DenseVectorStorage(array.Length, array)); + } + + /// + /// Create a new dense vector and initialize each value using the provided value. + /// + public Vector DenseVector(int length, T value) + { + if (Zero.Equals(value)) return DenseVector(length); + return DenseVector(DenseVectorStorage.OfInit(length, i => value)); + } + + /// + /// Create a new dense vector and initialize each value using the provided init function. + /// + public Vector DenseVector(int length, Func init) + { + return DenseVector(DenseVectorStorage.OfInit(length, init)); + } + + /// + /// Create a new dense vector with values sampled from the provided random distribution. + /// + public abstract Vector DenseVectorRandom(int length, IContinuousDistribution distribution); + + /// + /// Create a new dense vector as a copy of the given other vector. + /// This new vector will be independent from the other vector. + /// A new memory block will be allocated for storing the vector. + /// + public Vector DenseVectorOfVector(Vector vector) + { + return DenseVector(DenseVectorStorage.OfVector(vector.Storage)); + } + + /// + /// Create a new dense vector as a copy of the given enumerable. + /// This new vector will be independent from the enumerable. + /// A new memory block will be allocated for storing the vector. + /// + public Vector DenseVectorOfEnumerable(IEnumerable enumerable) + { + return DenseVector(DenseVectorStorage.OfEnumerable(enumerable)); + } + + /// + /// Create a new dense vector as a copy of the given indexed enumerable. + /// Keys must be provided at most once, zero is assumed if a key is omitted. + /// This new vector will be independent from the enumerable. + /// A new memory block will be allocated for storing the vector. + /// + public Vector DenseVectorOfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return DenseVector(DenseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } + + /// + /// Create a new sparse vector straight from an initialized vector storage instance. + /// The storage is used directly without copying. + /// Intended for advanced scenarios where you're working directly with + /// storage for performance or interop reasons. + /// + public abstract Vector SparseVector(SparseVectorStorage storage); /// /// Create a sparse vector of T with the given size. /// /// The size of the vector. - Vector SparseVector(int size); + public Vector SparseVector(int size) + { + return SparseVector(new SparseVectorStorage(size)); + } + + /// + /// Create a new sparse vector and initialize each value using the provided value. + /// + public Vector SparseVector(int length, T value) + { + if (Zero.Equals(value)) return SparseVector(length); + return SparseVector(SparseVectorStorage.OfInit(length, i => value)); + } + + /// + /// Create a new sparse vector and initialize each value using the provided init function. + /// + public Vector SparseVector(int length, Func init) + { + return SparseVector(SparseVectorStorage.OfInit(length, init)); + } + + /// + /// Create a new sparse vector as a copy of the given other vector. + /// This new vector will be independent from the other vector. + /// A new memory block will be allocated for storing the vector. + /// + public Vector SparseVectorOfVector(Vector vector) + { + return SparseVector(SparseVectorStorage.OfVector(vector.Storage)); + } + + /// + /// Create a new sparse vector as a copy of the given enumerable. + /// This new vector will be independent from the enumerable. + /// A new memory block will be allocated for storing the vector. + /// + public Vector SparseVectorOfEnumerable(IEnumerable enumerable) + { + return SparseVector(SparseVectorStorage.OfEnumerable(enumerable)); + } + + /// + /// Create a new sparse vector as a copy of the given indexed enumerable. + /// Keys must be provided at most once, zero is assumed if a key is omitted. + /// This new vector will be independent from the enumerable. + /// A new memory block will be allocated for storing the vector. + /// + public Vector SparseVectorOfIndexedEnumerable(int length, IEnumerable> enumerable) + { + return SparseVector(SparseVectorStorage.OfIndexedEnumerable(length, enumerable)); + } - IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000); + public abstract IIterationStopCriterium[] IterativeSolverStopCriteria(int maxIterations = 1000); } - internal static class Builder where T : struct, IEquatable, IFormattable + internal static class BuilderInstance where T : struct, IEquatable, IFormattable { - static Lazy> _singleton = new Lazy>(Create); + static Lazy> _singleton = new Lazy>(Create); - static IGenericBuilder Create() + static Builder Create() { if (typeof (T) == typeof (Complex64)) { - return (IGenericBuilder) new Complex.GenericBuilder(); + return (Builder) (object) new Complex.Builder(); } if (typeof (T) == typeof (Numerics.Complex32)) { - return (IGenericBuilder) new Complex32.GenericBuilder(); + return (Builder) (object) new Complex32.Builder(); } if (typeof (T) == typeof (double)) { - return (IGenericBuilder) new Double.GenericBuilder(); + return (Builder) (object) new Double.Builder(); } if (typeof (T) == typeof (float)) { - return (IGenericBuilder) new Single.GenericBuilder(); + return (Builder) (object) new Single.Builder(); } throw new NotSupportedException(); } - public static void Register(IGenericBuilder builder) + public static void Register(Builder builder) { - _singleton = new Lazy>(() => builder); + _singleton = new Lazy>(() => builder); } - public static IGenericBuilder Instance + public static Builder Instance { get { return _singleton.Value; } } diff --git a/src/Numerics/LinearAlgebra/Factorization/LU.cs b/src/Numerics/LinearAlgebra/Factorization/LU.cs index 85e581b4..d83e6b24 100644 --- a/src/Numerics/LinearAlgebra/Factorization/LU.cs +++ b/src/Numerics/LinearAlgebra/Factorization/LU.cs @@ -46,7 +46,7 @@ namespace MathNet.Numerics.LinearAlgebra.Factorization public abstract class LU : ISolver where T : struct, IEquatable, IFormattable { - static readonly T One = Builder.Instance.One; + static readonly T One = BuilderInstance.Instance.One; readonly Lazy> _lazyL; readonly Lazy> _lazyU; diff --git a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs index ce7ab0c9..ed53733d 100644 --- a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs +++ b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs @@ -41,12 +41,12 @@ namespace MathNet.Numerics.LinearAlgebra /// /// The value of 1.0. /// - public static readonly T One = Builder.Instance.One; + public static readonly T One = BuilderInstance.Instance.One; /// /// The value of 0.0. /// - public static readonly T Zero = Builder.Instance.Zero; + public static readonly T Zero = BuilderInstance.Instance.Zero; /// /// Negate each element of this matrix and place the results into the result matrix. diff --git a/src/Numerics/LinearAlgebra/Matrix.Solve.cs b/src/Numerics/LinearAlgebra/Matrix.Solve.cs index 3154276b..f85cb443 100644 --- a/src/Numerics/LinearAlgebra/Matrix.Solve.cs +++ b/src/Numerics/LinearAlgebra/Matrix.Solve.cs @@ -161,7 +161,7 @@ namespace MathNet.Numerics.LinearAlgebra { if (iterator == null) { - iterator = new Iterator(Builder.IterativeSolverStopCriteria()); + iterator = new Iterator(Build.IterativeSolverStopCriteria()); } if (preconditioner == null) @@ -191,7 +191,7 @@ namespace MathNet.Numerics.LinearAlgebra if (iterator == null) { - iterator = new Iterator(Builder.IterativeSolverStopCriteria()); + iterator = new Iterator(Build.IterativeSolverStopCriteria()); } if (preconditioner == null) @@ -201,7 +201,7 @@ namespace MathNet.Numerics.LinearAlgebra for (var column = 0; column < input.ColumnCount; column++) { - var solution = Builder.DenseVector(RowCount); + var solution = Build.DenseVector(RowCount); solver.Solve(this, input.Column(column), solution, iterator, preconditioner); @@ -225,7 +225,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The preconditioner to use for approximations. public IterationStatus TrySolveIterative(Vector input, Vector result, IIterativeSolver solver, IPreconditioner preconditioner, params IIterationStopCriterium[] stopCriteria) { - var iterator = new Iterator(stopCriteria.Length == 0 ? Builder.IterativeSolverStopCriteria() : stopCriteria); + var iterator = new Iterator(stopCriteria.Length == 0 ? Build.IterativeSolverStopCriteria() : stopCriteria); return TrySolveIterative(input, result, solver, iterator, preconditioner); } @@ -239,7 +239,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The preconditioner to use for approximations. public IterationStatus TrySolveIterative(Matrix input, Matrix result, IIterativeSolver solver, IPreconditioner preconditioner, params IIterationStopCriterium[] stopCriteria) { - var iterator = new Iterator(stopCriteria.Length == 0 ? Builder.IterativeSolverStopCriteria() : stopCriteria); + var iterator = new Iterator(stopCriteria.Length == 0 ? Build.IterativeSolverStopCriteria() : stopCriteria); return TrySolveIterative(input, result, solver, iterator, preconditioner); } @@ -252,7 +252,7 @@ namespace MathNet.Numerics.LinearAlgebra /// Criteria to control when to stop iterating. public IterationStatus TrySolveIterative(Vector input, Vector result, IIterativeSolver solver, params IIterationStopCriterium[] stopCriteria) { - var iterator = new Iterator(stopCriteria.Length == 0 ? Builder.IterativeSolverStopCriteria() : stopCriteria); + var iterator = new Iterator(stopCriteria.Length == 0 ? Build.IterativeSolverStopCriteria() : stopCriteria); return TrySolveIterative(input, result, solver, iterator); } @@ -265,7 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra /// Criteria to control when to stop iterating. public IterationStatus TrySolveIterative(Matrix input, Matrix result, IIterativeSolver solver, params IIterationStopCriterium[] stopCriteria) { - var iterator = new Iterator(stopCriteria.Length == 0 ? Builder.IterativeSolverStopCriteria() : stopCriteria); + var iterator = new Iterator(stopCriteria.Length == 0 ? Build.IterativeSolverStopCriteria() : stopCriteria); return TrySolveIterative(input, result, solver, iterator); } @@ -283,7 +283,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result vector x. public Vector SolveIterative(Vector input, IIterativeSolver solver, Iterator iterator = null, IPreconditioner preconditioner = null) { - var result = Builder.DenseVector(RowCount); + var result = Build.DenseVector(RowCount); TrySolveIterative(input, result, solver, iterator, preconditioner); return result; } @@ -298,7 +298,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result matrix X. public Matrix SolveIterative(Matrix input, IIterativeSolver solver, Iterator iterator = null, IPreconditioner preconditioner = null) { - var result = Builder.DenseMatrix(input.RowCount, input.ColumnCount); + var result = Build.DenseMatrix(input.RowCount, input.ColumnCount); TrySolveIterative(input, result, solver, iterator, preconditioner); return result; } @@ -313,7 +313,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result vector x. public Vector SolveIterative(Vector input, IIterativeSolver solver, IPreconditioner preconditioner, params IIterationStopCriterium[] stopCriteria) { - var result = Builder.DenseVector(RowCount); + var result = Build.DenseVector(RowCount); TrySolveIterative(input, result, solver, preconditioner, stopCriteria); return result; } @@ -328,7 +328,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result matrix X. public Matrix SolveIterative(Matrix input, IIterativeSolver solver, IPreconditioner preconditioner, params IIterationStopCriterium[] stopCriteria) { - var result = Builder.DenseMatrix(input.RowCount, input.ColumnCount); + var result = Build.DenseMatrix(input.RowCount, input.ColumnCount); TrySolveIterative(input, result, solver, preconditioner, stopCriteria); return result; } @@ -342,7 +342,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result vector x. public Vector SolveIterative(Vector input, IIterativeSolver solver, params IIterationStopCriterium[] stopCriteria) { - var result = Builder.DenseVector(RowCount); + var result = Build.DenseVector(RowCount); TrySolveIterative(input, result, solver, stopCriteria); return result; } @@ -356,7 +356,7 @@ namespace MathNet.Numerics.LinearAlgebra /// The result matrix X. public Matrix SolveIterative(Matrix input, IIterativeSolver solver, params IIterationStopCriterium[] stopCriteria) { - var result = Builder.DenseMatrix(input.RowCount, input.ColumnCount); + var result = Build.DenseMatrix(input.RowCount, input.ColumnCount); TrySolveIterative(input, result, solver, stopCriteria); return result; } diff --git a/src/Numerics/LinearAlgebra/Matrix.cs b/src/Numerics/LinearAlgebra/Matrix.cs index 623be4a3..76058d53 100644 --- a/src/Numerics/LinearAlgebra/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Matrix.cs @@ -58,7 +58,7 @@ namespace MathNet.Numerics.LinearAlgebra ColumnCount = storage.ColumnCount; } - public static readonly IGenericBuilder Builder = Builder.Instance; + public static readonly Builder Build = BuilderInstance.Instance; /// /// Gets the raw matrix data storage. @@ -244,8 +244,8 @@ namespace MathNet.Numerics.LinearAlgebra public Matrix CreateMatrix(int rows, int columns) { return Storage.IsDense - ? Builder.DenseMatrix(rows, columns) - : Builder.SparseMatrix(rows, columns); + ? Build.DenseMatrix(rows, columns) + : Build.SparseMatrix(rows, columns); } /// @@ -256,8 +256,8 @@ namespace MathNet.Numerics.LinearAlgebra public Vector CreateVector(int size) { return Storage.IsDense - ? Builder.DenseVector(size) - : Builder.SparseVector(size); + ? Build.DenseVector(size) + : Build.SparseVector(size); } /// diff --git a/src/Numerics/LinearAlgebra/Solvers/Iterator.cs b/src/Numerics/LinearAlgebra/Solvers/Iterator.cs index 405a7b9a..a0b6b9d0 100644 --- a/src/Numerics/LinearAlgebra/Solvers/Iterator.cs +++ b/src/Numerics/LinearAlgebra/Solvers/Iterator.cs @@ -56,7 +56,7 @@ namespace MathNet.Numerics.LinearAlgebra.Solvers /// public Iterator() { - _stopCriteria = new List>(Matrix.Builder.IterativeSolverStopCriteria()); + _stopCriteria = new List>(Matrix.Build.IterativeSolverStopCriteria()); } /// diff --git a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs index f54cf663..c5997dd4 100644 --- a/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/MatrixStorage.cs @@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage { // [ruegg] public fields are OK here - protected static readonly T Zero = Builder.Instance.Zero; + protected static readonly T Zero = BuilderInstance.Instance.Zero; public readonly int RowCount; public readonly int ColumnCount; diff --git a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs index 9ce40fa2..a1d66337 100644 --- a/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs +++ b/src/Numerics/LinearAlgebra/Storage/VectorStorage.cs @@ -40,7 +40,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage { // [ruegg] public fields are OK here - protected static readonly T Zero = Builder.Instance.Zero; + protected static readonly T Zero = BuilderInstance.Instance.Zero; public readonly int Length; protected VectorStorage(int length) diff --git a/src/Numerics/LinearAlgebra/Vector.Arithmetic.cs b/src/Numerics/LinearAlgebra/Vector.Arithmetic.cs index c948d592..75f5aa3d 100644 --- a/src/Numerics/LinearAlgebra/Vector.Arithmetic.cs +++ b/src/Numerics/LinearAlgebra/Vector.Arithmetic.cs @@ -38,12 +38,12 @@ namespace MathNet.Numerics.LinearAlgebra /// /// The zero value for type T. /// - public static readonly T Zero = Builder.Instance.Zero; + public static readonly T Zero = BuilderInstance.Instance.Zero; /// /// The value of 1.0 for type T. /// - public static readonly T One = Builder.Instance.One; + public static readonly T One = BuilderInstance.Instance.One; /// /// Negates vector and save result to diff --git a/src/Numerics/LinearAlgebra/Vector.cs b/src/Numerics/LinearAlgebra/Vector.cs index e10a1828..7c4e99fe 100644 --- a/src/Numerics/LinearAlgebra/Vector.cs +++ b/src/Numerics/LinearAlgebra/Vector.cs @@ -58,7 +58,7 @@ namespace MathNet.Numerics.LinearAlgebra Count = storage.Length; } - public static readonly IGenericBuilder Builder = Builder.Instance; + public static readonly Builder Builder = BuilderInstance.Instance; /// /// Gets the raw vector data storage.