//
// Math.NET Numerics, part of the Math.NET Project
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
//
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Linq;
using IStation.Numerics.Distributions;
using IStation.Numerics.LinearAlgebra.Solvers;
using IStation.Numerics.LinearAlgebra.Storage;
using IStation.Numerics.Random;
namespace IStation.Numerics.LinearAlgebra.Double
{
internal class MatrixBuilder : MatrixBuilder
{
public override double Zero => 0d;
public override double One => 1d;
public override Matrix Dense(DenseColumnMajorMatrixStorage storage)
{
return new DenseMatrix(storage);
}
public override Matrix Sparse(SparseCompressedRowMatrixStorage storage)
{
return new SparseMatrix(storage);
}
public override Matrix Diagonal(DiagonalMatrixStorage storage)
{
return new DiagonalMatrix(storage);
}
public override Matrix Random(int rows, int columns, IContinuousDistribution distribution)
{
return Dense(rows, columns, Generate.Random(rows*columns, distribution));
}
public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000)
{
return new IIterationStopCriterion[]
{
new FailureStopCriterion(),
new DivergenceStopCriterion(),
new IterationCountStopCriterion(maxIterations),
new ResidualStopCriterion(1e-12)
};
}
internal override double Add(double x, double y)
{
return x + y;
}
}
internal class VectorBuilder : VectorBuilder
{
public override double Zero => 0d;
public override double One => 1d;
public override Vector Dense(DenseVectorStorage storage)
{
return new DenseVector(storage);
}
public override Vector Sparse(SparseVectorStorage storage)
{
return new SparseVector(storage);
}
public override Vector Random(int length, IContinuousDistribution distribution)
{
return Dense(Generate.Random(length, distribution));
}
}
}
namespace IStation.Numerics.LinearAlgebra.Single
{
internal class MatrixBuilder : MatrixBuilder
{
public override float Zero => 0f;
public override float One => 1f;
public override Matrix Dense(DenseColumnMajorMatrixStorage storage)
{
return new DenseMatrix(storage);
}
public override Matrix Sparse(SparseCompressedRowMatrixStorage storage)
{
return new SparseMatrix(storage);
}
public override Matrix Diagonal(DiagonalMatrixStorage storage)
{
return new DiagonalMatrix(storage);
}
public override Matrix Random(int rows, int columns, IContinuousDistribution distribution)
{
return Dense(rows, columns, Generate.RandomSingle(rows*columns, distribution));
}
public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000)
{
return new IIterationStopCriterion[]
{
new FailureStopCriterion(),
new DivergenceStopCriterion(),
new IterationCountStopCriterion(maxIterations),
new ResidualStopCriterion(1e-6)
};
}
internal override float Add(float x, float y)
{
return x + y;
}
}
internal class VectorBuilder : VectorBuilder
{
public override float Zero => 0f;
public override float One => 1f;
public override Vector Dense(DenseVectorStorage storage)
{
return new DenseVector(storage);
}
public override Vector Sparse(SparseVectorStorage storage)
{
return new SparseVector(storage);
}
public override Vector Random(int length, IContinuousDistribution distribution)
{
return Dense(Generate.RandomSingle(length, distribution));
}
}
}
namespace IStation.Numerics.LinearAlgebra.Complex
{
using Complex = System.Numerics.Complex;
internal class MatrixBuilder : MatrixBuilder
{
public override Complex Zero => Complex.Zero;
public override Complex One => Complex.One;
public override Matrix Dense(DenseColumnMajorMatrixStorage storage)
{
return new DenseMatrix(storage);
}
public override Matrix Sparse(SparseCompressedRowMatrixStorage storage)
{
return new SparseMatrix(storage);
}
public override Matrix Diagonal(DiagonalMatrixStorage storage)
{
return new DiagonalMatrix(storage);
}
public override Matrix Random(int rows, int columns, IContinuousDistribution distribution)
{
return Dense(rows, columns, Generate.RandomComplex(rows*columns, distribution));
}
public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000)
{
return new IIterationStopCriterion[]
{
new FailureStopCriterion(),
new DivergenceStopCriterion(),
new IterationCountStopCriterion(maxIterations),
new ResidualStopCriterion(1e-12)
};
}
internal override Complex Add(Complex x, Complex y)
{
return x + y;
}
}
internal class VectorBuilder : VectorBuilder
{
public override Complex Zero => Complex.Zero;
public override Complex One => Complex.One;
public override Vector Dense(DenseVectorStorage storage)
{
return new DenseVector(storage);
}
public override Vector Sparse(SparseVectorStorage storage)
{
return new SparseVector(storage);
}
public override Vector Random(int length, IContinuousDistribution distribution)
{
return Dense(Generate.RandomComplex(length, distribution));
}
}
}
namespace IStation.Numerics.LinearAlgebra.Complex32
{
internal class MatrixBuilder : MatrixBuilder
{
public override Numerics.Complex32 Zero => Numerics.Complex32.Zero;
public override Numerics.Complex32 One => Numerics.Complex32.One;
public override Matrix Dense(DenseColumnMajorMatrixStorage storage)
{
return new DenseMatrix(storage);
}
public override Matrix Sparse(SparseCompressedRowMatrixStorage storage)
{
return new SparseMatrix(storage);
}
public override Matrix Diagonal(DiagonalMatrixStorage storage)
{
return new DiagonalMatrix(storage);
}
public override Matrix Random(int rows, int columns, IContinuousDistribution distribution)
{
return Dense(rows, columns, Generate.RandomComplex32(rows*columns, distribution));
}
public override IIterationStopCriterion[] IterativeSolverStopCriteria(int maxIterations = 1000)
{
return new IIterationStopCriterion[]
{
new FailureStopCriterion(),
new DivergenceStopCriterion(),
new IterationCountStopCriterion(maxIterations),
new ResidualStopCriterion(1e-6)
};
}
internal override Numerics.Complex32 Add(Numerics.Complex32 x, Numerics.Complex32 y)
{
return x + y;
}
}
internal class VectorBuilder : VectorBuilder
{
public override Numerics.Complex32 Zero => Numerics.Complex32.Zero;
public override Numerics.Complex32 One => Numerics.Complex32.One;
public override Vector Dense(DenseVectorStorage storage)
{
return new DenseVector(storage);
}
public override Vector Sparse(SparseVectorStorage storage)
{
return new SparseVector(storage);
}
public override Vector Random(int length, IContinuousDistribution distribution)
{
return Dense(Generate.RandomComplex32(length, distribution));
}
}
}
namespace IStation.Numerics.LinearAlgebra
{
///
/// Generic linear algebra type builder, for situations where a matrix or vector
/// must be created in a generic way. Usage of generic builders should not be
/// required in normal user code.
///
public abstract class MatrixBuilder where T : struct, IEquatable, IFormattable
{
///
/// Gets the value of 0.0 for type T.
///
public abstract T Zero { get; }
///
/// Gets the value of 1.0 for type T.
///
public abstract T One { get; }
internal abstract T Add(T x, T y);
///
/// 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.
///
public Matrix OfStorage(MatrixStorage storage)
{
if (storage == null) throw new ArgumentNullException(nameof(storage));
if (storage is DenseColumnMajorMatrixStorage dense) return Dense(dense);
if (storage is SparseCompressedRowMatrixStorage sparse) return Sparse(sparse);
if (storage is DiagonalMatrixStorage diagonal) return Diagonal(diagonal);
throw new NotSupportedException(FormattableString.Invariant($"Matrix storage type '{storage.GetType().Name}' is not supported. Only DenseColumnMajorMatrixStorage, SparseCompressedRowMatrixStorage and DiagonalMatrixStorage are supported as this point."));
}
///
/// Create a new matrix with the same kind of the provided example.
///
public Matrix SameAs(Matrix example, int rows, int columns, bool fullyMutable = false)
where TU : struct, IEquatable, IFormattable
{
var storage = example.Storage;
if (storage is DenseColumnMajorMatrixStorage) return Dense(rows, columns);
if (storage is DiagonalMatrixStorage) return fullyMutable ? Sparse(rows, columns) : Diagonal(rows, columns);
if (storage is SparseCompressedRowMatrixStorage) return Sparse(rows, columns);
return Dense(rows, columns);
}
///
/// Create a new matrix with the same kind and dimensions of the provided example.
///
public Matrix SameAs(Matrix example)
where TU : struct, IEquatable, IFormattable
{
return SameAs(example, example.RowCount, example.ColumnCount);
}
///
/// Create a new matrix with the same kind of the provided example.
///
public Matrix SameAs(Vector example, int rows, int columns)
{
return example.Storage.IsDense ? Dense(rows, columns) : Sparse(rows, columns);
}
///
/// Create a new matrix with a type that can represent and is closest to both provided samples.
///
public Matrix SameAs(Matrix example, Matrix otherExample, int rows, int columns, bool fullyMutable = false)
{
var storage1 = example.Storage;
var storage2 = otherExample.Storage;
if (storage1 is DenseColumnMajorMatrixStorage || storage2 is DenseColumnMajorMatrixStorage) return Dense(rows, columns);
if (storage1 is DiagonalMatrixStorage && storage2 is DiagonalMatrixStorage) return fullyMutable ? Sparse(rows, columns) : Diagonal(rows, columns);
if (storage1 is SparseCompressedRowMatrixStorage || storage2 is SparseCompressedRowMatrixStorage) return Sparse(rows, columns);
return Dense(rows, columns);
}
///
/// Create a new matrix with a type that can represent and is closest to both provided samples and the dimensions of example.
///
public Matrix SameAs(Matrix example, Matrix otherExample)
{
return SameAs(example, otherExample, example.RowCount, example.ColumnCount);
}
///
/// Create a new dense matrix with values sampled from the provided random distribution.
///
public abstract Matrix Random(int rows, int columns, IContinuousDistribution distribution);
///
/// Create a new dense matrix with values sampled from the standard distribution with a system random source.
///
public Matrix Random(int rows, int columns)
{
return Random(rows, columns, new Normal(SystemRandomSource.Default));
}
///
/// Create a new dense matrix with values sampled from the standard distribution with a system random source.
///
public Matrix Random(int rows, int columns, int seed)
{
return Random(rows, columns, new Normal(new SystemRandomSource(seed, true)));
}
///
/// Create a new positive definite dense matrix where each value is the product
/// of two samples from the provided random distribution.
///
public Matrix RandomPositiveDefinite(int order, IContinuousDistribution distribution)
{
var a = Random(order, order, distribution);
return a.ConjugateTransposeThisAndMultiply(a);
}
///
/// Create a new positive definite dense matrix where each value is the product
/// of two samples from the standard distribution.
///
public Matrix RandomPositiveDefinite(int order)
{
var a = Random(order, order, new Normal(SystemRandomSource.Default));
return a.ConjugateTransposeThisAndMultiply(a);
}
///
/// Create a new positive definite dense matrix where each value is the product
/// of two samples from the provided random distribution.
///
public Matrix RandomPositiveDefinite(int order, int seed)
{
var a = Random(order, order, new Normal(new SystemRandomSource(seed, true)));
return a.ConjugateTransposeThisAndMultiply(a);
}
///
/// 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 Dense(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.
///
public Matrix Dense(int rows, int columns)
{
return Dense(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 Dense(int rows, int columns, T[] storage)
{
return Dense(new DenseColumnMajorMatrixStorage(rows, columns, storage));
}
///
/// Create a new dense matrix and initialize each value to the same provided value.
///
public Matrix Dense(int rows, int columns, T value)
{
if (Zero.Equals(value)) return Dense(rows, columns);
return Dense(DenseColumnMajorMatrixStorage.OfValue(rows, columns, value));
}
///
/// Create a new dense matrix and initialize each value using the provided init function.
///
public Matrix Dense(int rows, int columns, Func init)
{
return Dense(DenseColumnMajorMatrixStorage.OfInit(rows, columns, init));
}
///
/// Create a new diagonal dense matrix and initialize each diagonal value to the same provided value.
///
public Matrix DenseDiagonal(int rows, int columns, T value)
{
if (Zero.Equals(value)) return Dense(rows, columns);
return Dense(DenseColumnMajorMatrixStorage.OfDiagonalInit(rows, columns, i => value));
}
///
/// Create a new diagonal dense matrix and initialize each diagonal value to the same provided value.
///
public Matrix DenseDiagonal(int order, T value)
{
if (Zero.Equals(value)) return Dense(order, order);
return Dense(DenseColumnMajorMatrixStorage.OfDiagonalInit(order, order, i => value));
}
///
/// Create a new diagonal dense matrix and initialize each diagonal value using the provided init function.
///
public Matrix DenseDiagonal(int rows, int columns, Func init)
{
return Dense(DenseColumnMajorMatrixStorage.OfDiagonalInit(rows, columns, init));
}
///
/// Create a new diagonal dense identity matrix with a one-diagonal.
///
public Matrix DenseIdentity(int rows, int columns)
{
return Dense(DenseColumnMajorMatrixStorage.OfDiagonalInit(rows, columns, i => One));
}
///
/// Create a new diagonal dense identity matrix with a one-diagonal.
///
public Matrix DenseIdentity(int order)
{
return Dense(DenseColumnMajorMatrixStorage.OfDiagonalInit(order, order, i => One));
}
///
/// 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 DenseOfMatrix(Matrix matrix)
{
return Dense(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 DenseOfArray(T[,] array)
{
return Dense(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 DenseOfIndexed(int rows, int columns, IEnumerable> enumerable)
{
return Dense(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 DenseOfColumnMajor(int rows, int columns, IEnumerable columnMajor)
{
return Dense(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 DenseOfColumns(IEnumerable> data)
{
return Dense(DenseColumnMajorMatrixStorage.OfColumnArrays(data.Select(v => (v as T[]) ?? 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 DenseOfColumns(int rows, int columns, IEnumerable> data)
{
return Dense(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 DenseOfColumnArrays(params T[][] columns)
{
return Dense(DenseColumnMajorMatrixStorage.OfColumnArrays(columns));
}
///
/// 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 DenseOfColumnArrays(IEnumerable columns)
{
return Dense(DenseColumnMajorMatrixStorage.OfColumnArrays((columns as T[][]) ?? columns.ToArray()));
}
///
/// 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 DenseOfColumnVectors(params Vector[] columns)
{
var storage = new VectorStorage[columns.Length];
for (int i = 0; i < columns.Length; i++)
{
storage[i] = columns[i].Storage;
}
return Dense(DenseColumnMajorMatrixStorage.OfColumnVectors(storage));
}
///
/// 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 DenseOfColumnVectors(IEnumerable> columns)
{
return Dense(DenseColumnMajorMatrixStorage.OfColumnVectors(columns.Select(c => c.Storage).ToArray()));
}
///
/// Create a new dense 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 matrix.
///
public Matrix DenseOfRowMajor(int rows, int columns, IEnumerable columnMajor)
{
return Dense(DenseColumnMajorMatrixStorage.OfRowMajorEnumerable(rows, columns, columnMajor));
}
///
/// 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 DenseOfRows(IEnumerable> data)
{
return Dense(DenseColumnMajorMatrixStorage.OfRowArrays(data.Select(v => (v as T[]) ?? 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 DenseOfRows(int rows, int columns, IEnumerable> data)
{
return Dense(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 DenseOfRowArrays(params T[][] rows)
{
return Dense(DenseColumnMajorMatrixStorage.OfRowArrays(rows));
}
///
/// 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 DenseOfRowArrays(IEnumerable rows)
{
return Dense(DenseColumnMajorMatrixStorage.OfRowArrays((rows as T[][]) ?? rows.ToArray()));
}
///
/// 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 DenseOfRowVectors(params Vector[] rows)
{
var storage = new VectorStorage[rows.Length];
for (int i = 0; i < rows.Length; i++)
{
storage[i] = rows[i].Storage;
}
return Dense(DenseColumnMajorMatrixStorage.OfRowVectors(storage));
}
///
/// 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 DenseOfRowVectors(IEnumerable> rows)
{
return Dense(DenseColumnMajorMatrixStorage.OfRowVectors(rows.Select(r => r.Storage).ToArray()));
}
///
/// 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 DenseOfDiagonalVector(Vector diagonal)
{
var m = Dense(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 DenseOfDiagonalVector(int rows, int columns, Vector diagonal)
{
var m = Dense(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 DenseOfDiagonalArray(T[] diagonal)
{
var m = Dense(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 DenseOfDiagonalArray(int rows, int columns, T[] diagonal)
{
var m = Dense(rows, columns);
m.SetDiagonal(diagonal);
return m;
}
///
/// Create a new dense matrix from a 2D array of existing matrices.
/// The matrices in the array are not required to be dense already.
/// If the matrices do not align properly, they are placed on the top left
/// corner of their cell with the remaining fields left zero.
///
public Matrix DenseOfMatrixArray(Matrix[,] matrices)
{
var rowspans = new int[matrices.GetLength(0)];
var colspans = new int[matrices.GetLength(1)];
for (int i = 0; i < rowspans.Length; i++)
{
for (int j = 0; j < colspans.Length; j++)
{
rowspans[i] = Math.Max(rowspans[i], matrices[i, j].RowCount);
colspans[j] = Math.Max(colspans[j], matrices[i, j].ColumnCount);
}
}
var m = Dense(rowspans.Sum(), colspans.Sum());
int rowoffset = 0;
for (int i = 0; i < rowspans.Length; i++)
{
int coloffset = 0;
for (int j = 0; j < colspans.Length; j++)
{
m.SetSubMatrix(rowoffset, coloffset, matrices[i, j]);
coloffset += colspans[j];
}
rowoffset += rowspans[i];
}
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.
///
/// The SparseCompressedRowMatrixStorage
public abstract Matrix Sparse(SparseCompressedRowMatrixStorage storage);
///
/// Create a sparse matrix of T with the given number of rows and columns.
///
/// The number of rows.
/// The number of columns.
public Matrix Sparse(int rows, int columns)
{
return Sparse(new SparseCompressedRowMatrixStorage(rows, columns));
}
///
/// Create a new sparse matrix and initialize each value to the same provided value.
///
public Matrix Sparse(int rows, int columns, T value)
{
if (Zero.Equals(value)) return Sparse(rows, columns);
return Sparse(SparseCompressedRowMatrixStorage.OfValue(rows, columns, value));
}
///
/// Create a new sparse matrix and initialize each value using the provided init function.
///
public Matrix Sparse(int rows, int columns, Func init)
{
return Sparse(SparseCompressedRowMatrixStorage.OfInit(rows, columns, init));
}
///
/// Create a new diagonal sparse matrix and initialize each diagonal value to the same provided value.
///
public Matrix SparseDiagonal(int rows, int columns, T value)
{
if (Zero.Equals(value)) return Sparse(rows, columns);
return Sparse(SparseCompressedRowMatrixStorage.OfDiagonalInit(rows, columns, i => value));
}
///
/// Create a new diagonal sparse matrix and initialize each diagonal value to the same provided value.
///
public Matrix SparseDiagonal(int order, T value)
{
if (Zero.Equals(value)) return Sparse(order, order);
return Sparse(SparseCompressedRowMatrixStorage.OfDiagonalInit(order, order, i => value));
}
///
/// Create a new diagonal sparse matrix and initialize each diagonal value using the provided init function.
///
public Matrix SparseDiagonal(int rows, int columns, Func init)
{
return Sparse(SparseCompressedRowMatrixStorage.OfDiagonalInit(rows, columns, init));
}
///
/// Create a new diagonal dense identity matrix with a one-diagonal.
///
public Matrix SparseIdentity(int rows, int columns)
{
return Sparse(SparseCompressedRowMatrixStorage.OfDiagonalInit(rows, columns, i => One));
}
///
/// Create a new diagonal dense identity matrix with a one-diagonal.
///
public Matrix SparseIdentity(int order)
{
return Sparse(SparseCompressedRowMatrixStorage.OfDiagonalInit(order, order, i => One));
}
///
/// 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 SparseOfMatrix(Matrix matrix)
{
return Sparse(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 SparseOfArray(T[,] array)
{
return Sparse(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 SparseOfIndexed(int rows, int columns, IEnumerable> enumerable)
{
return Sparse(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 SparseOfRowMajor(int rows, int columns, IEnumerable rowMajor)
{
return Sparse(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 SparseOfColumnMajor(int rows, int columns, IList columnMajor)
{
return Sparse(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 SparseOfColumns(IEnumerable> data)
{
return Sparse(SparseCompressedRowMatrixStorage.OfColumnArrays(data.Select(v => (v as T[]) ?? 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 SparseOfColumns(int rows, int columns, IEnumerable> data)
{
return Sparse(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 SparseOfColumnArrays(params T[][] columns)
{
return Sparse(SparseCompressedRowMatrixStorage.OfColumnArrays(columns));
}
///
/// 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 SparseOfColumnArrays(IEnumerable columns)
{
return Sparse(SparseCompressedRowMatrixStorage.OfColumnArrays((columns as T[][]) ?? columns.ToArray()));
}
///
/// 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 SparseOfColumnVectors(params Vector[] columns)
{
var storage = new VectorStorage[columns.Length];
for (int i = 0; i < columns.Length; i++)
{
storage[i] = columns[i].Storage;
}
return Sparse(SparseCompressedRowMatrixStorage.OfColumnVectors(storage));
}
///
/// 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 SparseOfColumnVectors(IEnumerable> columns)
{
return Sparse(SparseCompressedRowMatrixStorage.OfColumnVectors(columns.Select(c => c.Storage).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 SparseOfRows(IEnumerable> data)
{
return Sparse(SparseCompressedRowMatrixStorage.OfRowArrays(data.Select(v => (v as T[]) ?? 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 SparseOfRows(int rows, int columns, IEnumerable