Browse Source

LA: migrate vectors to storage classes (major)

pull/61/merge
Christoph Ruegg 14 years ago
parent
commit
78a933aaf3
  1. 4
      src/Examples/LinearAlgebra/VectorDataAccessor.cs
  2. 9
      src/Numerics.IO/LinearAlgebra/IO/MatlabWriter.cs
  3. 75
      src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs
  4. 248
      src/Numerics/LinearAlgebra/Complex/DenseVector.cs
  5. 4
      src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs
  6. 4
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs
  7. 2
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseEvd.cs
  8. 2
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs
  9. 4
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs
  10. 2
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs
  11. 6
      src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs
  12. 1
      src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs
  13. 459
      src/Numerics/LinearAlgebra/Complex/SparseVector.cs
  14. 11
      src/Numerics/LinearAlgebra/Complex/Vector.cs
  15. 75
      src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs
  16. 257
      src/Numerics/LinearAlgebra/Complex32/DenseVector.cs
  17. 4
      src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs
  18. 4
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs
  19. 2
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseEvd.cs
  20. 2
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs
  21. 4
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseLU.cs
  22. 2
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseQR.cs
  23. 6
      src/Numerics/LinearAlgebra/Complex32/Factorization/DenseSvd.cs
  24. 1
      src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs
  25. 489
      src/Numerics/LinearAlgebra/Complex32/SparseVector.cs
  26. 11
      src/Numerics/LinearAlgebra/Complex32/Vector.cs
  27. 77
      src/Numerics/LinearAlgebra/Double/DenseMatrix.cs
  28. 268
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  29. 4
      src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs
  30. 4
      src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs
  31. 2
      src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs
  32. 4
      src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs
  33. 2
      src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs
  34. 6
      src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs
  35. 1
      src/Numerics/LinearAlgebra/Double/SparseMatrix.cs
  36. 483
      src/Numerics/LinearAlgebra/Double/SparseVector.cs
  37. 11
      src/Numerics/LinearAlgebra/Double/Vector.cs
  38. 288
      src/Numerics/LinearAlgebra/Generic/Vector.cs
  39. 77
      src/Numerics/LinearAlgebra/Single/DenseMatrix.cs
  40. 268
      src/Numerics/LinearAlgebra/Single/DenseVector.cs
  41. 4
      src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs
  42. 4
      src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs
  43. 2
      src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs
  44. 4
      src/Numerics/LinearAlgebra/Single/Factorization/DenseLU.cs
  45. 2
      src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs
  46. 6
      src/Numerics/LinearAlgebra/Single/Factorization/DenseSvd.cs
  47. 1
      src/Numerics/LinearAlgebra/Single/SparseMatrix.cs
  48. 503
      src/Numerics/LinearAlgebra/Single/SparseVector.cs
  49. 12
      src/Numerics/LinearAlgebra/Single/Vector.cs
  50. 8
      src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs
  51. 333
      src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs
  52. 16
      src/Numerics/LinearAlgebra/Storage/VectorStorage.cs
  53. 1
      src/Numerics/Numerics.csproj
  54. 3
      src/Portable/Portable.csproj
  55. 25
      src/UnitTests/LinearAlgebraTests/Complex/SparseVectorTest.cs
  56. 69
      src/UnitTests/LinearAlgebraTests/Complex/UserDefinedVector.cs
  57. 4
      src/UnitTests/LinearAlgebraTests/Complex/VectorTests.cs
  58. 25
      src/UnitTests/LinearAlgebraTests/Complex32/SparseVectorTest.cs
  59. 69
      src/UnitTests/LinearAlgebraTests/Complex32/UserDefinedVector.cs
  60. 4
      src/UnitTests/LinearAlgebraTests/Complex32/VectorTests.cs
  61. 25
      src/UnitTests/LinearAlgebraTests/Double/SparseVectorTest.cs
  62. 69
      src/UnitTests/LinearAlgebraTests/Double/UserDefinedVector.cs
  63. 4
      src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs
  64. 26
      src/UnitTests/LinearAlgebraTests/Single/SparseVectorTest.cs
  65. 69
      src/UnitTests/LinearAlgebraTests/Single/UserDefinedVector.cs
  66. 4
      src/UnitTests/LinearAlgebraTests/Single/VectorTests.cs

4
src/Examples/LinearAlgebra/VectorDataAccessor.cs

@ -30,6 +30,8 @@ using MathNet.Numerics.LinearAlgebra.Double;
namespace Examples.LinearAlgebraExamples
{
using MathNet.Numerics.LinearAlgebra.Generic;
/// <summary>
/// Vector data access, copying and conversion examples
/// </summary>
@ -124,7 +126,7 @@ namespace Examples.LinearAlgebraExamples
Console.WriteLine();
// 8. Copy part of vector into another vector. If you need to copy all data then use CopoTy(vector) method.
vectorA.CopyTo(cloneA, 3, 3, 4);
vectorA.CopySubVectorTo(cloneA, 3, 3, 4);
Console.WriteLine(@"8. Copy part of vector into another vector");
Console.WriteLine(cloneA.ToString("#0.00\t", formatProvider));
Console.WriteLine();

9
src/Numerics.IO/LinearAlgebra/IO/MatlabWriter.cs

@ -37,6 +37,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO
using Generic;
using Matlab;
using Properties;
using Storage;
/// <summary>
/// Writes matrices to a Matlab file.
@ -500,7 +501,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO
int count = 0;
foreach (var column in matrix.ColumnEnumerator())
{
count += ((Double.SparseVector)column.Item2).NonZerosCount;
count += ((SparseVectorStorage<double>)column.Item2.Storage).ValueCount;
dataWriter.Write(count);
}
@ -568,7 +569,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO
int count = 0;
foreach (var column in matrix.ColumnEnumerator())
{
count += ((Single.SparseVector)column.Item2).NonZerosCount;
count += ((SparseVectorStorage<float>)column.Item2.Storage).ValueCount;
dataWriter.Write(count);
}
@ -639,7 +640,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO
int count = 0;
foreach (var column in matrix.ColumnEnumerator())
{
count += ((Complex.SparseVector)column.Item2).NonZerosCount;
count += ((SparseVectorStorage<System.Numerics.Complex>)column.Item2.Storage).ValueCount;
dataWriter.Write(count);
}
@ -718,7 +719,7 @@ namespace MathNet.Numerics.LinearAlgebra.IO
int count = 0;
foreach (var column in matrix.ColumnEnumerator())
{
count += ((Complex32.SparseVector)column.Item2).NonZerosCount;
count += ((SparseVectorStorage<Numerics.Complex32>)column.Item2.Storage).ValueCount;
dataWriter.Write(count);
}

75
src/Numerics/LinearAlgebra/Complex/DenseMatrix.cs

@ -39,8 +39,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
[Serializable]
public class DenseMatrix : Matrix
{
readonly DenseColumnMajorMatrixStorage<Complex> _storage;
/// <summary>
/// Number of rows.
/// </summary>
@ -59,15 +57,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// Gets the matrix's data.
/// </summary>
/// <value>The matrix's data.</value>
readonly Complex[] _data;
readonly Complex[] _values;
internal DenseMatrix(DenseColumnMajorMatrixStorage<Complex> storage)
: base(storage)
{
_storage = storage;
_rowCount = _storage.RowCount;
_columnCount = _storage.ColumnCount;
_data = _storage.Data;
_rowCount = storage.RowCount;
_columnCount = storage.ColumnCount;
_values = storage.Data;
}
/// <summary>
@ -109,9 +106,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public DenseMatrix(int rows, int columns, Complex value)
: this(rows, columns)
{
for (var i = 0; i < _data.Length; i++)
for (var i = 0; i < _values.Length; i++)
{
_data[i] = value;
_values[i] = value;
}
}
@ -139,7 +136,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
for (var j = 0; j < _columnCount; j++)
{
_data[(j * _rowCount) + i] = array[i, j];
_values[(j * _rowCount) + i] = array[i, j];
}
}
}
@ -161,7 +158,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <value>The matrix's data.</value>
public Complex[] Data
{
get { return _data; }
get { return _values; }
}
/// <summary>
@ -203,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i];
ret._values[(i * _columnCount) + j] = _values[index + i];
}
}
@ -214,21 +211,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>The L1 norm of the matrix.</returns>
public override Complex L1Norm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the Frobenius norm of this matrix.</summary>
/// <returns>The Frobenius norm of this matrix.</returns>
public override Complex FrobeniusNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the infinity norm of this matrix.</summary>
/// <returns>The infinity norm of this matrix.</returns>
public override Complex InfinityNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values);
}
#region Static constructors for special matrices.
@ -246,7 +243,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var m = new DenseMatrix(order);
for (var i = 0; i < order; i++)
{
m._data[(i * order) + i] = 1.0;
m._values[(i * order) + i] = 1.0;
}
return m;
@ -268,7 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult._values);
}
}
@ -292,14 +289,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0,
denseResult.Data);
denseResult.Values);
}
}
@ -323,14 +320,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -354,14 +351,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.Transpose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -385,14 +382,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0,
denseResult.Data);
denseResult.Values);
}
}
@ -416,14 +413,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -441,7 +438,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(-1, _values, denseResult._values);
}
}
@ -461,7 +458,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_values, denseOther._values, denseResult._values);
}
}
@ -481,7 +478,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.PointWiseDivideArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseDivideArrays(_values, denseOther._values, denseResult._values);
}
}
@ -502,7 +499,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.AddArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.AddArrays(_values, denseOther._values, denseResult._values);
}
}
@ -521,7 +518,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.SubtractArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.SubtractArrays(_values, denseOther._values, denseResult._values);
}
}
@ -537,7 +534,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i].Conjugate();
ret._values[(i * _columnCount) + j] = _values[index + i].Conjugate();
}
}
@ -559,7 +556,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var sum = Complex.Zero;
for (var i = 0; i < _rowCount; i++)
{
sum += _data[(i * _rowCount) + i];
sum += _values[(i * _rowCount) + i];
}
return sum;

248
src/Numerics/LinearAlgebra/Complex/DenseVector.cs

@ -33,6 +33,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -41,6 +42,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
[Serializable]
public class DenseVector : Vector
{
/// <summary>
/// Number of elements
/// </summary>
readonly int _length;
/// <summary>
/// Gets the vector's data.
/// </summary>
readonly Complex[] _values;
internal DenseVector(DenseVectorStorage<Complex> storage)
: base(storage)
{
_length = storage.Length;
_values = storage.Data;
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
/// </summary>
@ -50,9 +68,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size) : base(size)
public DenseVector(int size)
: this(new DenseVectorStorage<Complex>(size))
{
Data = new Complex[size];
}
/// <summary>
@ -68,11 +86,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size, Complex value) : this(size)
public DenseVector(int size, Complex value)
: this(size)
{
for (var index = 0; index < Data.Length; index++)
for (var index = 0; index < _values.Length; index++)
{
Data[index] = value;
_values[index] = value;
}
}
@ -83,27 +102,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(Vector<Complex> other) : this(other.Count)
{
CommonParallel.For(
0,
Data.Length,
index => this[index] = other[index]);
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(DenseVector other) : this(other.Count)
public DenseVector(Vector<Complex> other)
: this(other.Count)
{
CommonParallel.For(
0,
Data.Length,
index => Data[index] = other.Data[index]);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -112,20 +114,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector does not copy the array, but keeps a reference to it. Any
/// changes to the vector will also change the array.</remarks>
public DenseVector(Complex[] array) : base(array.Length)
public DenseVector(Complex[] array)
: this(new DenseVectorStorage<Complex>(array.Length, array))
{
Data = array;
}
/// <summary>
/// Gets the vector's internal data.
/// Gets the vector's data.
/// </summary>
/// <value>The vector's internal data.</value>
/// <remarks>Changing values in the array also changes the corresponding value in vector. Use with care.</remarks>
internal Complex[] Data
/// <value>The vector's data.</value>
public Complex[] Values
{
get;
private set;
get { return _values; }
}
/// <summary>
@ -136,14 +136,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>
/// A reference to the internal date of the given vector.
/// </returns>
public static implicit operator Complex[](DenseVector vector)
public static explicit operator Complex[](DenseVector vector)
{
if (vector == null)
{
throw new ArgumentNullException();
}
return vector.Data;
return vector.Values;
}
/// <summary>
@ -169,10 +169,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>This vector as a column matrix.</returns>
public override Matrix<Complex> ToColumnMatrix()
{
var matrix = new DenseMatrix(Count, 1);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(_length, 1);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(i, 0, Data[i]);
matrix.At(i, 0, _values[i]);
}
return matrix;
@ -184,33 +184,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>This vector as a row matrix.</returns>
public override Matrix<Complex> ToRowMatrix()
{
var matrix = new DenseMatrix(1, Count);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(1, _length);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(0, i, Data[i]);
matrix.At(0, i, _values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override Complex this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -244,49 +226,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new DenseVector(size);
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<Complex> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as DenseVector;
if (otherVector == null)
{
CommonParallel.For(
0,
Data.Length,
index => target[index] = Data[index]);
}
else
{
Array.Copy(Data, 0, otherVector.Data, 0, Data.Length);
}
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -303,8 +242,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] + scalar);
_values.Length,
index => dense._values[index] = _values[index] + scalar);
}
}
@ -319,7 +258,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, Complex.One, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, Complex.One, odense.Values, rdense.Values);
}
else
{
@ -388,8 +327,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] - scalar);
_values.Length,
index => dense._values[index] = _values[index] - scalar);
}
}
@ -404,7 +343,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, -1.0, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, -1.0, odense.Values, rdense.Values);
}
else
{
@ -463,11 +402,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<Complex> Negate()
{
var result = new DenseVector(Count);
var result = new DenseVector(_length);
CommonParallel.For(
0,
Data.Length,
index => result[index] = -Data[index]);
_values.Length,
index => result[index] = -_values[index]);
return result;
}
@ -487,7 +426,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, Data, denseResult.Data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult.Values);
}
}
@ -501,7 +440,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(Data, denseVector.Data);
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -563,7 +502,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
}
return Control.LinearAlgebraProvider.DotProduct(leftSide.Data, rightSide.Data);
return Control.LinearAlgebraProvider.DotProduct(leftSide.Values, rightSide.Values);
}
/// <summary>
@ -590,10 +529,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override int AbsoluteMinimumIndex()
{
var index = 0;
var min = Data[index].Magnitude;
for (var i = 1; i < Count; i++)
var min = _values[index].Magnitude;
for (var i = 1; i < _length; i++)
{
var test = Data[i].Magnitude;
var test = _values[i].Magnitude;
if (test < min)
{
index = i;
@ -610,7 +549,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>The value of the absolute minimum element.</returns>
public override Complex AbsoluteMinimum()
{
return Data[AbsoluteMinimumIndex()].Magnitude;
return _values[AbsoluteMinimumIndex()].Magnitude;
}
/// <summary>
@ -619,7 +558,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>The value of the absolute maximum element.</returns>
public override Complex AbsoluteMaximum()
{
return Data[AbsoluteMaximumIndex()].Magnitude;
return _values[AbsoluteMaximumIndex()].Magnitude;
}
/// <summary>
@ -629,10 +568,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override int AbsoluteMaximumIndex()
{
var index = 0;
var max = Data[index].Magnitude;
for (var i = 1; i < Count; i++)
var max = _values[index].Magnitude;
for (var i = 1; i < _length; i++)
{
var test = Data[i].Magnitude;
var test = _values[i].Magnitude;
if (test > max)
{
index = i;
@ -656,7 +595,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception>
public override Vector<Complex> SubVector(int index, int length)
{
if (index < 0 || index >= Count)
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
@ -666,7 +605,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
throw new ArgumentOutOfRangeException("length");
}
if (index + length > Count)
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
@ -675,8 +614,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
CommonParallel.For(
index,
index + length,
i => result.Data[i - index] = Data[i]);
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
@ -693,7 +632,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
throw new ArgumentNullException("values");
}
if (values.Length != Count)
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
@ -701,7 +640,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
CommonParallel.For(
0,
values.Length,
i => Data[i] = values[i]);
i => _values[i] = values[i]);
}
/// <summary>
@ -712,9 +651,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
var sum = Complex.Zero;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Data[i];
sum += _values[i];
}
return sum;
@ -728,9 +667,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
var sum = Complex.Zero;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Data[i].Magnitude;
sum += _values[i].Magnitude;
}
return sum;
@ -752,8 +691,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] * other[index]);
_values.Length,
index => dense._values[index] = _values[index] * other[index]);
}
}
@ -774,8 +713,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] / other[index]);
_values.Length,
index => dense._values[index] = _values[index] / other[index]);
}
}
@ -807,7 +746,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u.Data[i] * v.Data[j]);
matrix.At(i, j, u._values[i] * v._values[j]);
}
});
return matrix;
@ -845,19 +784,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (2.0 == p)
{
return Data.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
return _values.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(Data, (i, v) => v.Magnitude, Math.Max, 0d);
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0d);
}
var sum = 0.0;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(Data[i].Magnitude, p);
sum += Math.Pow(_values[i].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
@ -1022,14 +961,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
#endregion
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
Array.Clear(Data, 0, Data.Length);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="target"/>
/// </summary>
@ -1046,24 +977,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
CommonParallel.For(
0,
Count,
index => denseTarget.Data[index] = Data[index].Conjugate());
_length,
index => denseTarget._values[index] = _values[index].Conjugate());
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
internal protected override Complex At(int index)
{
return Data[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
internal protected override void At(int index, Complex value)
{
Data[index] = value;
}
}
}

4
src/Numerics/LinearAlgebra/Complex/DiagonalMatrix.cs

@ -378,12 +378,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return;
}
if (_data.Length != denseSource.Data.Length)
if (_data.Length != denseSource.Values.Length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source");
}
Array.Copy(denseSource.Data, _data, denseSource.Data.Length);
Array.Copy(denseSource.Values, _data, denseSource.Values.Length);
}
/// <summary>

4
src/Numerics/LinearAlgebra/Complex/Factorization/DenseCholesky.cs

@ -169,11 +169,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
}
// Copy the contents of input to result.
CommonParallel.For(0, dinput.Data.Length, index => dresult.Data[index] = dinput.Data[index]);
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, 1);
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Values, 1);
}
}
}

2
src/Numerics/LinearAlgebra/Complex/Factorization/DenseEvd.cs

@ -107,7 +107,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
{
var matrixH = matrix.ToArray();
NonsymmetricReduceToHessenberg(((DenseMatrix)MatrixEv).Data, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((DenseVector)VectorEv).Data, ((DenseMatrix)MatrixEv).Data, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((DenseVector)VectorEv).Values, ((DenseMatrix)MatrixEv).Data, matrixH, order);
}
MatrixD.SetDiagonal(VectorEv);

2
src/Numerics/LinearAlgebra/Complex/Factorization/DenseGramSchmidt.cs

@ -217,7 +217,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Data, 1, dresult.Data);
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Values, 1, dresult.Values);
}
}
}

4
src/Numerics/LinearAlgebra/Complex/Factorization/DenseLU.cs

@ -170,11 +170,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
}
// Copy the contents of input to result.
CommonParallel.For(0, dinput.Data.Length, index => dresult.Data[index] = dinput.Data[index]);
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]);
// LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors;
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Values);
}
/// <summary>

2
src/Numerics/LinearAlgebra/Complex/Factorization/DenseQR.cs

@ -188,7 +188,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values);
}
}
}

6
src/Numerics/LinearAlgebra/Complex/Factorization/DenseSvd.cs

@ -70,7 +70,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
VectorS = new DenseVector(nm);
MatrixU = new DenseMatrix(matrix.RowCount);
MatrixVT = new DenseMatrix(matrix.ColumnCount);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
}
/// <summary>
@ -126,7 +126,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
}
/// <summary>
@ -176,7 +176,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Values, 1, dresult.Values);
}
}
}

1
src/Numerics/LinearAlgebra/Complex/SparseMatrix.cs

@ -98,6 +98,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// The number of columns.
/// </param>
/// <param name="value">The value which we assign to each element of the matrix.</param>
[Obsolete("Use a dense matrix instead.")]
public SparseMatrix(int rows, int columns, Complex value)
: this(rows, columns)
{

459
src/Numerics/LinearAlgebra/Complex/SparseVector.cs

@ -37,6 +37,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -46,24 +47,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
[Serializable]
public class SparseVector : Vector
{
/// <summary>
/// Gets the vector's internal data. The array containing the actual values; only the non-zero values are stored.
/// </summary>
private Complex[] _nonZeroValues = new Complex[0];
readonly SparseVectorStorage<Complex> _storage;
/// <summary>
/// The indices of the non-zero entries.
/// </summary>
private int[] _nonZeroIndices = new int[0];
/// <summary>
/// Gets the number of non zero elements in the vector.
/// </summary>
/// <value>The number of non zero elements.</value>
public int NonZerosCount
internal SparseVector(SparseVectorStorage<Complex> storage)
: base(storage)
{
get;
private set;
_storage = storage;
}
#region Constructors
@ -77,7 +66,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size) : base(size)
public SparseVector(int size)
: this(new SparseVectorStorage<Complex>(size))
{
}
@ -94,58 +84,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size, Complex value) : this(size)
[Obsolete("Use a dense vector instead.")]
public SparseVector(int size, Complex value)
: this(new SparseVectorStorage<Complex>(size))
{
if (value == Complex.Zero)
{
// Skip adding values
return;
}
// We already know that this vector is "full", let's allocate all needed memory
_nonZeroValues = new Complex[size];
_nonZeroIndices = new int[size];
NonZerosCount = size;
var valueCount = _storage.ValueCount = size;
var indices = _storage.Indices = new int[valueCount];
var values = _storage.Values = new Complex[valueCount];
CommonParallel.For(
0,
Count,
index =>
{
_nonZeroValues[index] = value;
_nonZeroIndices[index] = index;
});
}
/// <summary>
/// Initializes a new instance of the <see cref="SparseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(Vector<Complex> other) : this(other.Count)
{
var vector = other as SparseVector;
if (vector == null)
for (int i = 0; i < values.Length; i++)
{
for (var i = 0; i < other.Count; i++)
{
this[i] = other.At(i);
}
}
else
{
_nonZeroValues = new Complex[vector.NonZerosCount];
_nonZeroIndices = new int[vector.NonZerosCount];
NonZerosCount = vector.NonZerosCount;
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
if (vector.NonZerosCount != 0)
{
CommonParallel.For(0, vector.NonZerosCount, index => _nonZeroValues[index] = vector._nonZeroValues[index]);
Buffer.BlockCopy(vector._nonZeroIndices, 0, _nonZeroIndices, 0, vector.NonZerosCount * Constants.SizeOfInt);
}
values[i] = value;
indices[i] = i;
}
}
@ -156,18 +111,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(SparseVector other) : this(other.Count)
public SparseVector(Vector<Complex> other)
: this(new SparseVectorStorage<Complex>(other.Count))
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
_nonZeroValues = new Complex[other.NonZerosCount];
_nonZeroIndices = new int[other.NonZerosCount];
NonZerosCount = other.NonZerosCount;
if (other.NonZerosCount != 0)
{
CommonParallel.For(0, other.NonZerosCount, index => _nonZeroValues[index] = other._nonZeroValues[index]);
Buffer.BlockCopy(other._nonZeroIndices, 0, _nonZeroIndices, 0, other.NonZerosCount * Constants.SizeOfInt);
}
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -175,11 +122,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </summary>
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector copy the array. Any changes to the vector will NOT change the array.</remarks>
public SparseVector(IList<Complex> array) : this(array.Count)
public SparseVector(IList<Complex> array)
: this(new SparseVectorStorage<Complex>(array.Count))
{
for (var i = 0; i < array.Count; i++)
{
this[i] = array[i];
Storage.At(i, array[i]);
}
}
@ -192,9 +140,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Matrix<Complex> ToColumnMatrix()
{
var matrix = new SparseMatrix(Count, 1);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(_nonZeroIndices[i], 0, _nonZeroValues[i]);
matrix.At(_storage.Indices[i], 0, _storage.Values[i]);
}
return matrix;
@ -207,9 +155,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Matrix<Complex> ToRowMatrix()
{
var matrix = new SparseMatrix(1, Count);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(0, _nonZeroIndices[i], _nonZeroValues[i]);
matrix.At(0, _storage.Indices[i], _storage.Values[i]);
}
return matrix;
@ -248,68 +196,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return new SparseVector(size);
}
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
NonZerosCount = 0;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<Complex> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as SparseVector;
if (otherVector == null)
{
target.Clear();
for (var index = 0; index < NonZerosCount; index++)
{
target.At(_nonZeroIndices[index], _nonZeroValues[index]);
}
}
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new Complex[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
if (NonZerosCount != 0)
{
Array.Copy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount);
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
}
}
}
/// <summary>
/// Conjugates vector and save result to <paramref name="target"/>
/// </summary>
@ -341,14 +227,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new Complex[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
otherVector._storage.Values = new Complex[_storage.ValueCount];
otherVector._storage.Indices = new int[_storage.ValueCount];
otherVector._storage.ValueCount = _storage.ValueCount;
if (NonZerosCount != 0)
if (_storage.ValueCount != 0)
{
CommonParallel.For(0, NonZerosCount, index => otherVector._nonZeroValues[index] = _nonZeroValues[index].Conjugate());
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, _storage.ValueCount, index => otherVector._storage.Values[index] = _storage.Values[index].Conjugate());
Buffer.BlockCopy(_storage.Indices, 0, otherVector._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
}
}
}
@ -390,15 +276,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
//populate the non zero values from this
for (int j = 0; j < NonZerosCount; j++)
for (int j = 0; j < _storage.ValueCount; j++)
{
vnonZeroValues[_nonZeroIndices[j]] = _nonZeroValues[j] + scalar;
vnonZeroValues[_storage.Indices[j]] = _storage.Values[j] + scalar;
}
//assign this vectors arrary to the new arrays.
_nonZeroValues = vnonZeroValues;
_nonZeroIndices = vnonZeroIndices;
NonZerosCount = Count;
_storage.Values = vnonZeroValues;
_storage.Indices = vnonZeroIndices;
_storage.ValueCount = Count;
}
else
{
@ -439,22 +325,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] += otherSparse._nonZeroValues[j++];
_storage.Values[i++] += otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != Complex.Zero)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], otherValue);
}
j++;
}
@ -464,25 +350,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] + otherSparse.At(next));
result.At(next, _storage.Values[i] + otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) + otherSparse._nonZeroValues[j]);
result.At(next, At(next) + otherSparse._storage.Values[j]);
}
j++;
}
@ -585,22 +471,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] -= otherSparse._nonZeroValues[j++];
_storage.Values[i++] -= otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != Complex.Zero)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], -otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], -otherValue);
}
j++;
}
@ -610,25 +496,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] - otherSparse.At(next));
result.At(next, _storage.Values[i] - otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) - otherSparse._nonZeroValues[j]);
result.At(next, At(next) - otherSparse._storage.Values[j]);
}
j++;
}
@ -687,23 +573,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<Complex> Negate()
{
var result = new SparseVector(Count)
{
_nonZeroValues = new Complex[NonZerosCount],
_nonZeroIndices = new int[NonZerosCount],
NonZerosCount = NonZerosCount
};
var result = new SparseVectorStorage<Complex>(Count);
var valueCount = result.ValueCount = _storage.ValueCount;
var indices = result.Indices = new int[valueCount];
var values = result.Values = new Complex[valueCount];
if (NonZerosCount != 0)
if (valueCount != 0)
{
CommonParallel.For(
0,
NonZerosCount,
index => result._nonZeroValues[index] = -_nonZeroValues[index]);
Buffer.BlockCopy(_nonZeroIndices, 0, result._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, valueCount, index => values[index] = -_storage.Values[index]);
Buffer.BlockCopy(_storage.Indices, 0, indices, 0, valueCount * Constants.SizeOfInt);
}
return result;
return new SparseVector(result);
}
/// <summary>
@ -724,7 +605,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
var copy = new SparseVector(this);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._nonZeroValues, copy._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._storage.Values, copy._storage.Values);
return copy;
}
@ -759,23 +640,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (sparseResult == null)
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], scalar * _nonZeroValues[index]);
result.At(_storage.Indices[index], scalar * _storage.Values[index]);
}
}
else
{
if (!ReferenceEquals(this, result))
{
sparseResult.NonZerosCount = NonZerosCount;
sparseResult._nonZeroIndices = new int[NonZerosCount];
Buffer.BlockCopy(_nonZeroIndices, 0, sparseResult._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
sparseResult._nonZeroValues = new Complex[NonZerosCount];
Array.Copy(_nonZeroValues, sparseResult._nonZeroValues, NonZerosCount);
sparseResult._storage.ValueCount = _storage.ValueCount;
sparseResult._storage.Indices = new int[_storage.ValueCount];
Buffer.BlockCopy(_storage.Indices, 0, sparseResult._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
sparseResult._storage.Values = new Complex[_storage.ValueCount];
Array.Copy(_storage.Values, sparseResult._storage.Values, _storage.ValueCount);
}
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._nonZeroValues, sparseResult._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
}
}
@ -794,16 +675,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * _nonZeroValues[i];
result += _storage.Values[i] * _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * other.At(_nonZeroIndices[i]);
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
@ -895,17 +776,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <returns>The index of absolute minimum element.</returns>
public override int AbsoluteMinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
// No non-zero elements. Return 0
return 0;
}
var index = 0;
var min = _nonZeroValues[index].Magnitude;
for (var i = 1; i < NonZerosCount; i++)
var min = _storage.Values[index].Magnitude;
for (var i = 1; i < _storage.ValueCount; i++)
{
var test = _nonZeroValues[i].Magnitude;
var test = _storage.Values[i].Magnitude;
if (test < min)
{
index = i;
@ -913,7 +794,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -984,9 +865,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex Sum()
{
var result = Complex.Zero;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i];
result += _storage.Values[i];
}
return result;
@ -999,9 +880,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex SumMagnitudes()
{
double result = 0;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i].Magnitude;
result += _storage.Values[i].Magnitude;
}
return result;
@ -1016,17 +897,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] *= _nonZeroValues[i];
_storage.Values[i] *= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, other.At(index) * _nonZeroValues[i]);
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
@ -1040,17 +921,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] /= _nonZeroValues[i];
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, _nonZeroValues[i] / other.At(index));
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
}
}
}
@ -1076,13 +957,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
var matrix = new SparseMatrix(u.Count, v.Count);
for (var i = 0; i < u.NonZerosCount; i++)
for (var i = 0; i < u._storage.ValueCount; i++)
{
for (var j = 0; j < v.NonZerosCount; j++)
for (var j = 0; j < v._storage.ValueCount; j++)
{
if (u._nonZeroIndices[i] == v._nonZeroIndices[j])
if (u._storage.Indices[i] == v._storage.Indices[j])
{
matrix.At(i, j, u._nonZeroValues[i] * v._nonZeroValues[j]);
matrix.At(i, j, u._storage.Values[i] * v._storage.Values[j]);
}
}
}
@ -1118,25 +999,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
throw new ArgumentOutOfRangeException("p");
}
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0.0;
}
if (2.0 == p)
{
return _nonZeroValues.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
return _storage.Values.Aggregate(Complex.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, NonZerosCount, i => _nonZeroValues[i].Magnitude, Math.Max, 0d);
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_nonZeroValues[index].Magnitude, p);
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return Math.Pow(sum, 1.0 / p);
@ -1302,97 +1183,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
#endregion
/// <summary>
/// Gets the value at the given index.
/// </summary>
/// <param name="index">Value real index in array</param>
/// <returns>The value at the given index.</returns>
internal protected override Complex At(int index)
{
// Search if item idex exists in NonZeroIndices array in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
return itemIndex >= 0 ? _nonZeroValues[itemIndex] : Complex.Zero;
}
/// <summary>
/// Delete, Add or Update the value in NonZeroValues and NonZeroIndices
/// </summary>
/// <param name="index">Value real index in array</param>
/// <param name="value">The value to set.</param>
/// <remarks>This method assume that index is between 0 and Array Size</remarks>
internal protected override void At(int index, Complex value)
{
// Search if "index" already exists in range "0 - complex nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
if (itemIndex >= 0)
{
// Item already exist at itemIndex
if (value == Complex.Zero)
{
RemoveAtUnchecked(itemIndex);
}
else
{
_nonZeroValues[itemIndex] = value;
}
}
else
{
if (value != Complex.Zero)
{
InsertAtUnchecked(~itemIndex, index, value);
}
}
}
private void InsertAtUnchecked(int itemIndex, int index, Complex value)
{
// Check if the storage needs to be increased
if ((NonZerosCount == _nonZeroValues.Length) && (NonZerosCount < Count))
if ((_storage.ValueCount == _storage.Values.Length) && (_storage.ValueCount < Count))
{
// Value and Indices arrays are completely full so we increase the size
var size = Math.Min(_nonZeroValues.Length + GrowthSize(), Count);
Array.Resize(ref _nonZeroValues, size);
Array.Resize(ref _nonZeroIndices, size);
var size = Math.Min(_storage.Values.Length + GrowthSize(), Count);
Array.Resize(ref _storage.Values, size);
Array.Resize(ref _storage.Indices, size);
}
// Move all values (with a position larger than index) in the value array
// to the next position
// Move all values (with a position larger than index) in the columIndices
// array to the next position
for (var i = NonZerosCount - 1; i > itemIndex - 1; i--)
for (var i = _storage.ValueCount - 1; i > itemIndex - 1; i--)
{
_nonZeroValues[i + 1] = _nonZeroValues[i];
_nonZeroIndices[i + 1] = _nonZeroIndices[i];
_storage.Values[i + 1] = _storage.Values[i];
_storage.Indices[i + 1] = _storage.Indices[i];
}
// Add the value and the column index
_nonZeroValues[itemIndex] = value;
_nonZeroIndices[itemIndex] = index;
_storage.Values[itemIndex] = value;
_storage.Indices[itemIndex] = index;
// increase the number of non-zero numbers by one
NonZerosCount += 1;
}
private void RemoveAtUnchecked(int itemIndex)
{
// Value is zero. Let's delete it from Values and Indices array
for (var i = itemIndex + 1; i < NonZerosCount; i++)
{
_nonZeroValues[i - 1] = _nonZeroValues[i];
_nonZeroIndices[i - 1] = _nonZeroIndices[i];
}
NonZerosCount -= 1;
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((NonZerosCount > 1024) && (NonZerosCount < _nonZeroIndices.Length / 2))
{
Array.Resize(ref _nonZeroValues, NonZerosCount);
Array.Resize(ref _nonZeroIndices, NonZerosCount);
}
_storage.ValueCount += 1;
}
/// <summary>
@ -1403,19 +1220,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
private int GrowthSize()
{
int delta;
if (_nonZeroValues.Length > 1024)
if (_storage.Values.Length > 1024)
{
delta = _nonZeroValues.Length / 4;
delta = _storage.Values.Length / 4;
}
else
{
if (_nonZeroValues.Length > 256)
if (_storage.Values.Length > 256)
{
delta = 512;
}
else
{
delta = _nonZeroValues.Length > 64 ? 128 : 32;
delta = _storage.Values.Length > 64 ? 128 : 32;
}
}
@ -1428,7 +1245,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
if (Count > 20)
{
return String.Format("SparseVectorOfComplex({0},{1},{2})", Count, NonZerosCount, GetHashCode());
return String.Format("SparseVectorOfComplex({0},{1},{2})", Count, _storage.ValueCount, GetHashCode());
}
return base.ToString(format, formatProvider);
@ -1442,14 +1259,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(NonZerosCount, 20);
var hashNum = Math.Min(_storage.ValueCount, 20);
long hash = 0;
for (var i = 0; i < hashNum; i++)
{
#if PORTABLE
hash ^= Precision.DoubleToInt64Bits(this._nonZeroValues[i].GetHashCode());
hash ^= Precision.DoubleToInt64Bits(this._storage.Values[i].GetHashCode());
#else
hash ^= BitConverter.DoubleToInt64Bits(_nonZeroValues[i].GetHashCode());
hash ^= BitConverter.DoubleToInt64Bits(_storage.Values[i].GetHashCode());
#endif
}
@ -1493,27 +1310,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
if (_nonZeroValues[i++] != Complex.Zero)
if (_storage.Values[i++] != Complex.Zero)
{
return false;
}
continue;
}
if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i])
if (i >= _storage.ValueCount || j < otherSparse._storage.ValueCount && otherSparse._storage.Indices[j] < _storage.Indices[i])
{
if (otherSparse._nonZeroValues[j++] != Complex.Zero)
if (otherSparse._storage.Values[j++] != Complex.Zero)
{
return false;
}
continue;
}
if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j]))
if (!_storage.Values[i].AlmostEqual(otherSparse._storage.Values[j]))
{
return false;
}
@ -1541,9 +1358,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </remarks>
public override IEnumerable<Tuple<int, Complex>> GetIndexedEnumerator()
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
yield return new Tuple<int, Complex>(_nonZeroIndices[i], _nonZeroValues[i]);
yield return new Tuple<int, Complex>(_storage.Indices[i], _storage.Values[i]);
}
}
@ -1556,9 +1373,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
public override Complex[] ToArray()
{
var ret = new Complex[Count];
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
ret[_nonZeroIndices[i]] = _nonZeroValues[i];
ret[_storage.Indices[i]] = _storage.Values[i];
}
return ret;

11
src/Numerics/LinearAlgebra/Complex/Vector.cs

@ -31,6 +31,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
using Distributions;
using Generic;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -41,15 +42,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
{
/// <summary>
/// Initializes a new instance of the Vector class.
/// Constructs a <strong>Vector</strong> with the given size.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to construct.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
protected Vector(int size) : base(size)
protected Vector(VectorStorage<Complex> storage)
: base(storage)
{
}

75
src/Numerics/LinearAlgebra/Complex32/DenseMatrix.cs

@ -39,8 +39,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
[Serializable]
public class DenseMatrix : Matrix
{
readonly DenseColumnMajorMatrixStorage<Complex32> _storage;
/// <summary>
/// Number of rows.
/// </summary>
@ -59,15 +57,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// Gets the matrix's data.
/// </summary>
/// <value>The matrix's data.</value>
readonly Complex32[] _data;
readonly Complex32[] _values;
internal DenseMatrix(DenseColumnMajorMatrixStorage<Complex32> storage)
: base(storage)
{
_storage = storage;
_rowCount = _storage.RowCount;
_columnCount = _storage.ColumnCount;
_data = _storage.Data;
_rowCount = storage.RowCount;
_columnCount = storage.ColumnCount;
_values = storage.Data;
}
/// <summary>
@ -109,9 +106,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public DenseMatrix(int rows, int columns, Complex32 value)
: this(rows, columns)
{
for (var i = 0; i < _data.Length; i++)
for (var i = 0; i < _values.Length; i++)
{
_data[i] = value;
_values[i] = value;
}
}
@ -139,7 +136,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
for (var j = 0; j < _columnCount; j++)
{
_data[(j * _rowCount) + i] = array[i, j];
_values[(j * _rowCount) + i] = array[i, j];
}
}
}
@ -161,7 +158,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <value>The matrix's data.</value>
public Complex32[] Data
{
get { return _data; }
get { return _values; }
}
/// <summary>
@ -203,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i];
ret._values[(i * _columnCount) + j] = _values[index + i];
}
}
@ -214,21 +211,21 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>The L1 norm of the matrix.</returns>
public override Complex32 L1Norm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the Frobenius norm of this matrix.</summary>
/// <returns>The Frobenius norm of this matrix.</returns>
public override Complex32 FrobeniusNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the infinity norm of this matrix.</summary>
/// <returns>The infinity norm of this matrix.</returns>
public override Complex32 InfinityNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values);
}
#region Static constructors for special matrices.
@ -246,7 +243,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var m = new DenseMatrix(order);
for (var i = 0; i < order; i++)
{
m._data[(i * order) + i] = 1.0f;
m._values[(i * order) + i] = 1.0f;
}
return m;
@ -268,7 +265,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult._values);
}
}
@ -292,14 +289,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0f,
denseResult.Data);
denseResult.Values);
}
}
@ -323,14 +320,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -354,14 +351,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.Transpose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -385,14 +382,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0f,
denseResult.Data);
denseResult.Values);
}
}
@ -416,14 +413,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -441,7 +438,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(-1, _values, denseResult._values);
}
}
@ -461,7 +458,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_values, denseOther._values, denseResult._values);
}
}
@ -481,7 +478,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.PointWiseDivideArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseDivideArrays(_values, denseOther._values, denseResult._values);
}
}
@ -502,7 +499,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.AddArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.AddArrays(_values, denseOther._values, denseResult._values);
}
}
@ -521,7 +518,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.SubtractArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.SubtractArrays(_values, denseOther._values, denseResult._values);
}
}
@ -537,7 +534,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i].Conjugate();
ret._values[(i * _columnCount) + j] = _values[index + i].Conjugate();
}
}
@ -559,7 +556,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var sum = Complex32.Zero;
for (var i = 0; i < _rowCount; i++)
{
sum += _data[(i * _rowCount) + i];
sum += _values[(i * _rowCount) + i];
}
return sum;

257
src/Numerics/LinearAlgebra/Complex32/DenseVector.cs

@ -34,6 +34,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
using NumberTheory;
using Numerics;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -42,6 +43,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
[Serializable]
public class DenseVector : Vector
{
/// <summary>
/// Number of elements
/// </summary>
readonly int _length;
/// <summary>
/// Gets the vector's data.
/// </summary>
readonly Complex32[] _values;
internal DenseVector(DenseVectorStorage<Complex32> storage)
: base(storage)
{
_length = storage.Length;
_values = storage.Data;
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
/// </summary>
@ -51,9 +69,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size) : base(size)
public DenseVector(int size)
: this(new DenseVectorStorage<Complex32>(size))
{
Data = new Complex32[size];
}
/// <summary>
@ -69,11 +87,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size, Complex32 value) : this(size)
public DenseVector(int size, Complex32 value)
: this(size)
{
for (var index = 0; index < Data.Length; index++)
for (var index = 0; index < _values.Length; index++)
{
Data[index] = value;
_values[index] = value;
}
}
@ -84,27 +103,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(Vector<Complex32> other) : this(other.Count)
public DenseVector(Vector<Complex32> other)
: this(other.Count)
{
CommonParallel.For(
0,
Data.Length,
index => this[index] = other[index]);
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(DenseVector other) : this(other.Count)
{
CommonParallel.For(
0,
Data.Length,
index => Data[index] = other.Data[index]);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -113,20 +115,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector does not copy the array, but keeps a reference to it. Any
/// changes to the vector will also change the array.</remarks>
public DenseVector(Complex32[] array) : base(array.Length)
public DenseVector(Complex32[] array)
: this(new DenseVectorStorage<Complex32>(array.Length, array))
{
Data = array;
}
/// <summary>
/// Gets the vector's internal data.
/// Gets the vector's data.
/// </summary>
/// <value>The vector's internal data.</value>
/// <remarks>Changing values in the array also changes the corresponding value in vector. Use with care.</remarks>
internal Complex32[] Data
/// <value>The vector's data.</value>
public Complex32[] Values
{
get;
private set;
get { return _values; }
}
/// <summary>
@ -137,14 +137,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>
/// A reference to the internal date of the given vector.
/// </returns>
public static implicit operator Complex32[](DenseVector vector)
public static explicit operator Complex32[](DenseVector vector)
{
if (vector == null)
{
throw new ArgumentNullException();
}
return vector.Data;
return vector.Values;
}
/// <summary>
@ -170,10 +170,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>This vector as a column matrix.</returns>
public override Matrix<Complex32> ToColumnMatrix()
{
var matrix = new DenseMatrix(Count, 1);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(_length, 1);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(i, 0, Data[i]);
matrix.At(i, 0, _values[i]);
}
return matrix;
@ -185,33 +185,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>This vector as a row matrix.</returns>
public override Matrix<Complex32> ToRowMatrix()
{
var matrix = new DenseMatrix(1, Count);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(1, _length);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(0, i, Data[i]);
matrix.At(0, i, _values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override Complex32 this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -245,49 +227,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new DenseVector(size);
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<Complex32> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as DenseVector;
if (otherVector == null)
{
CommonParallel.For(
0,
Data.Length,
index => target[index] = Data[index]);
}
else
{
Array.Copy(Data, 0, otherVector.Data, 0, Data.Length);
}
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -304,8 +243,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] + scalar);
_values.Length,
index => dense._values[index] = _values[index] + scalar);
}
}
@ -320,7 +259,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, Complex32.One, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, Complex32.One, odense.Values, rdense.Values);
}
else
{
@ -389,8 +328,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] - scalar);
_values.Length,
index => dense._values[index] = _values[index] - scalar);
}
}
@ -405,7 +344,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, -1.0f, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, -1.0f, odense.Values, rdense.Values);
}
else
{
@ -464,11 +403,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<Complex32> Negate()
{
var result = new DenseVector(Count);
var result = new DenseVector(_length);
CommonParallel.For(
0,
Data.Length,
index => result[index] = -Data[index]);
_values.Length,
index => result[index] = -_values[index]);
return result;
}
@ -488,7 +427,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, Data, denseResult.Data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult.Values);
}
}
@ -502,7 +441,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(Data, denseVector.Data);
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -564,7 +503,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
}
return Control.LinearAlgebraProvider.DotProduct(leftSide.Data, rightSide.Data);
return Control.LinearAlgebraProvider.DotProduct(leftSide.Values, rightSide.Values);
}
/// <summary>
@ -591,10 +530,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override int AbsoluteMinimumIndex()
{
var index = 0;
var min = Data[index].Magnitude;
for (var i = 1; i < Count; i++)
var min = _values[index].Magnitude;
for (var i = 1; i < _length; i++)
{
var test = Data[i].Magnitude;
var test = _values[i].Magnitude;
if (test < min)
{
index = i;
@ -611,7 +550,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>The value of the absolute minimum element.</returns>
public override Complex32 AbsoluteMinimum()
{
return Data[AbsoluteMinimumIndex()].Magnitude;
return _values[AbsoluteMinimumIndex()].Magnitude;
}
/// <summary>
@ -620,7 +559,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>The value of the absolute maximum element.</returns>
public override Complex32 AbsoluteMaximum()
{
return Data[AbsoluteMaximumIndex()].Magnitude;
return _values[AbsoluteMaximumIndex()].Magnitude;
}
/// <summary>
@ -630,10 +569,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override int AbsoluteMaximumIndex()
{
var index = 0;
var max = Data[index].Magnitude;
for (var i = 1; i < Count; i++)
var max = _values[index].Magnitude;
for (var i = 1; i < _length; i++)
{
var test = Data[i].Magnitude;
var test = _values[i].Magnitude;
if (test > max)
{
index = i;
@ -657,7 +596,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception>
public override Vector<Complex32> SubVector(int index, int length)
{
if (index < 0 || index >= Count)
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
@ -667,7 +606,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
throw new ArgumentOutOfRangeException("length");
}
if (index + length > Count)
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
@ -676,8 +615,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
CommonParallel.For(
index,
index + length,
i => result.Data[i - index] = Data[i]);
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
@ -694,7 +633,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
throw new ArgumentNullException("values");
}
if (values.Length != Count)
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
@ -702,7 +641,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
CommonParallel.For(
0,
values.Length,
i => Data[i] = values[i]);
i => _values[i] = values[i]);
}
/// <summary>
@ -713,9 +652,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
var sum = Complex32.Zero;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Data[i];
sum += _values[i];
}
return sum;
@ -729,9 +668,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
var sum = Complex32.Zero;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Data[i].Magnitude;
sum += _values[i].Magnitude;
}
return sum;
@ -753,8 +692,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] * other[index]);
_values.Length,
index => dense._values[index] = _values[index] * other[index]);
}
}
@ -775,8 +714,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] / other[index]);
_values.Length,
index => dense._values[index] = _values[index] / other[index]);
}
}
@ -808,7 +747,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u.Data[i] * v.Data[j]);
matrix.At(i, j, u._values[i] * v._values[j]);
}
});
return matrix;
@ -832,9 +771,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
var v = (DenseVector)CreateVector(length);
for (var index = 0; index < v.Data.Length; index++)
for (var index = 0; index < v._values.Length; index++)
{
v.Data[index] = new Complex32((float)randomDistribution.Sample(), (float)randomDistribution.Sample());
v._values[index] = new Complex32((float)randomDistribution.Sample(), (float)randomDistribution.Sample());
}
return v;
@ -858,9 +797,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
var v = (DenseVector)CreateVector(length);
for (var index = 0; index < v.Data.Length; index++)
for (var index = 0; index < v._values.Length; index++)
{
v.Data[index] = new Complex32(randomDistribution.Sample(), randomDistribution.Sample());
v._values[index] = new Complex32(randomDistribution.Sample(), randomDistribution.Sample());
}
return v;
@ -898,19 +837,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (2.0 == p)
{
return Data.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
return _values.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(Data, (i, v) => v.Magnitude, Math.Max, 0f);
return CommonParallel.Aggregate(_values, (i, v) => v.Magnitude, Math.Max, 0f);
}
var sum = 0.0;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Math.Pow(Data[i].Magnitude, p);
sum += Math.Pow(_values[i].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
@ -1075,14 +1014,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
#endregion
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
Array.Clear(Data, 0, Data.Length);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="target"/>
/// </summary>
@ -1099,25 +1030,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
CommonParallel.For(
0,
Count,
index => denseTarget.Data[index] = Data[index].Conjugate());
_length,
index => denseTarget._values[index] = _values[index].Conjugate());
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
internal protected override Complex32 At(int index)
{
return Data[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
internal protected override void At(int index, Complex32 value)
{
Data[index] = value;
}
}
}

4
src/Numerics/LinearAlgebra/Complex32/DiagonalMatrix.cs

@ -378,12 +378,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return;
}
if (_data.Length != denseSource.Data.Length)
if (_data.Length != denseSource.Values.Length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source");
}
Array.Copy(denseSource.Data, _data, denseSource.Data.Length);
Array.Copy(denseSource.Values, _data, denseSource.Values.Length);
}
/// <summary>

4
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseCholesky.cs

@ -169,11 +169,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
}
// Copy the contents of input to result.
CommonParallel.For(0, dinput.Data.Length, index => dresult.Data[index] = dinput.Data[index]);
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, 1);
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Values, 1);
}
}
}

2
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseEvd.cs

@ -108,7 +108,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
{
var matrixH = matrix.ToArray();
NonsymmetricReduceToHessenberg(((DenseMatrix)MatrixEv).Data, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((LinearAlgebra.Complex.DenseVector)VectorEv).Data, ((DenseMatrix)MatrixEv).Data, matrixH, order);
NonsymmetricReduceHessenberToRealSchur(((LinearAlgebra.Complex.DenseVector)VectorEv).Values, ((DenseMatrix)MatrixEv).Data, matrixH, order);
}
for (var i = 0; i < VectorEv.Count; i++)

2
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseGramSchmidt.cs

@ -217,7 +217,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Data, 1, dresult.Data);
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Values, 1, dresult.Values);
}
}
}

4
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseLU.cs

@ -170,11 +170,11 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
}
// Copy the contents of input to result.
CommonParallel.For(0, dinput.Data.Length, index => dresult.Data[index] = dinput.Data[index]);
CommonParallel.For(0, dinput.Values.Length, index => dresult.Values[index] = dinput.Values[index]);
// LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors;
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Values);
}
/// <summary>

2
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseQR.cs

@ -188,7 +188,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values);
}
}
}

6
src/Numerics/LinearAlgebra/Complex32/Factorization/DenseSvd.cs

@ -70,7 +70,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
VectorS = new DenseVector(nm);
MatrixU = new DenseMatrix(matrix.RowCount);
MatrixVT = new DenseMatrix(matrix.ColumnCount);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
}
/// <summary>
@ -126,7 +126,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
}
/// <summary>
@ -176,7 +176,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Values, 1, dresult.Values);
}
}
}

1
src/Numerics/LinearAlgebra/Complex32/SparseMatrix.cs

@ -98,6 +98,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// The number of columns.
/// </param>
/// <param name="value">The value which we assign to each element of the matrix.</param>
[Obsolete("Use a dense matrix instead.")]
public SparseMatrix(int rows, int columns, Complex32 value)
: this(rows, columns)
{

489
src/Numerics/LinearAlgebra/Complex32/SparseVector.cs

@ -37,6 +37,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
using NumberTheory;
using Numerics;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -46,24 +47,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
[Serializable]
public class SparseVector : Vector
{
/// <summary>
/// Gets the vector's internal data. The array containing the actual values; only the non-zero values are stored.
/// </summary>
private Complex32[] _nonZeroValues = new Complex32[0];
/// <summary>
/// The indices of the non-zero entries.
/// </summary>
private int[] _nonZeroIndices = new int[0];
readonly SparseVectorStorage<Complex32> _storage;
/// <summary>
/// Gets the number of non zero elements in the vector.
/// </summary>
/// <value>The number of non zero elements.</value>
public int NonZerosCount
internal SparseVector(SparseVectorStorage<Complex32> storage)
: base(storage)
{
get;
private set;
_storage = storage;
}
#region Constructors
@ -77,7 +66,8 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size) : base(size)
public SparseVector(int size)
: this(new SparseVectorStorage<Complex32>(size))
{
}
@ -94,58 +84,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size, Complex32 value) : this(size)
[Obsolete("Use a dense vector instead.")]
public SparseVector(int size, Complex32 value)
: this(new SparseVectorStorage<Complex32>(size))
{
if (value == Complex32.Zero)
{
// Skip adding values
return;
}
// We already know that this vector is "full", let's allocate all needed memory
_nonZeroValues = new Complex32[size];
_nonZeroIndices = new int[size];
NonZerosCount = size;
var valueCount = _storage.ValueCount = size;
var indices = _storage.Indices = new int[valueCount];
var values = _storage.Values = new Complex32[valueCount];
CommonParallel.For(
0,
Count,
index =>
{
_nonZeroValues[index] = value;
_nonZeroIndices[index] = index;
});
}
/// <summary>
/// Initializes a new instance of the <see cref="SparseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(Vector<Complex32> other) : this(other.Count)
{
var vector = other as SparseVector;
if (vector == null)
for (int i = 0; i < values.Length; i++)
{
for (var i = 0; i < other.Count; i++)
{
this[i] = other.At(i);
}
}
else
{
_nonZeroValues = new Complex32[vector.NonZerosCount];
_nonZeroIndices = new int[vector.NonZerosCount];
NonZerosCount = vector.NonZerosCount;
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
if (vector.NonZerosCount != 0)
{
CommonParallel.For(0, vector.NonZerosCount, index => _nonZeroValues[index] = vector._nonZeroValues[index]);
Buffer.BlockCopy(vector._nonZeroIndices, 0, _nonZeroIndices, 0, vector.NonZerosCount * Constants.SizeOfInt);
}
values[i] = value;
indices[i] = i;
}
}
@ -156,18 +111,10 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(SparseVector other) : this(other.Count)
public SparseVector(Vector<Complex32> other)
: this(new SparseVectorStorage<Complex32>(other.Count))
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
_nonZeroValues = new Complex32[other.NonZerosCount];
_nonZeroIndices = new int[other.NonZerosCount];
NonZerosCount = other.NonZerosCount;
if (other.NonZerosCount != 0)
{
CommonParallel.For(0, other.NonZerosCount, index => _nonZeroValues[index] = other._nonZeroValues[index]);
Buffer.BlockCopy(other._nonZeroIndices, 0, _nonZeroIndices, 0, other.NonZerosCount * Constants.SizeOfInt);
}
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -175,11 +122,12 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </summary>
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector copy the array. Any changes to the vector will NOT change the array.</remarks>
public SparseVector(IList<Complex32> array) : this(array.Count)
public SparseVector(IList<Complex32> array)
: this(new SparseVectorStorage<Complex32>(array.Count))
{
for (var i = 0; i < array.Count; i++)
{
this[i] = array[i];
Storage.At(i, array[i]);
}
}
@ -192,9 +140,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Matrix<Complex32> ToColumnMatrix()
{
var matrix = new SparseMatrix(Count, 1);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(_nonZeroIndices[i], 0, _nonZeroValues[i]);
matrix.At(_storage.Indices[i], 0, _storage.Values[i]);
}
return matrix;
@ -207,44 +155,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Matrix<Complex32> ToRowMatrix()
{
var matrix = new SparseMatrix(1, Count);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(0, _nonZeroIndices[i], _nonZeroValues[i]);
matrix.At(0, _storage.Indices[i], _storage.Values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override Complex32 this[int index]
{
get
{
// If index is out of bounds
if ((index < 0) || (index >= Count))
{
throw new IndexOutOfRangeException();
}
return At(index);
}
set
{
// If index is out of bounds
if ((index < 0) || (index >= Count))
{
throw new IndexOutOfRangeException();
}
At(index, value);
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -278,68 +196,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return new SparseVector(size);
}
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
NonZerosCount = 0;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<Complex32> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as SparseVector;
if (otherVector == null)
{
target.Clear();
for (var index = 0; index < NonZerosCount; index++)
{
target.At(_nonZeroIndices[index], _nonZeroValues[index]);
}
}
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new Complex32[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
if (NonZerosCount != 0)
{
Array.Copy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount);
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
}
}
}
/// <summary>
/// Conjugates vector and save result to <paramref name="target"/>
/// </summary>
@ -371,14 +227,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new Complex32[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
otherVector._storage.Values = new Complex32[_storage.ValueCount];
otherVector._storage.Indices = new int[_storage.ValueCount];
otherVector._storage.ValueCount = _storage.ValueCount;
if (NonZerosCount != 0)
if (_storage.ValueCount != 0)
{
CommonParallel.For(0, NonZerosCount, index => otherVector._nonZeroValues[index] = _nonZeroValues[index].Conjugate());
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, _storage.ValueCount, index => otherVector._storage.Values[index] = _storage.Values[index].Conjugate());
Buffer.BlockCopy(_storage.Indices, 0, otherVector._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
}
}
}
@ -420,15 +276,15 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
//populate the non zero values from this
for (int j = 0; j < NonZerosCount; j++)
for (int j = 0; j < _storage.ValueCount; j++)
{
vnonZeroValues[_nonZeroIndices[j]] = _nonZeroValues[j] + scalar;
vnonZeroValues[_storage.Indices[j]] = _storage.Values[j] + scalar;
}
//assign this vectors arrary to the new arrays.
_nonZeroValues = vnonZeroValues;
_nonZeroIndices = vnonZeroIndices;
NonZerosCount = Count;
_storage.Values = vnonZeroValues;
_storage.Indices = vnonZeroIndices;
_storage.ValueCount = Count;
}
else
{
@ -469,22 +325,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] += otherSparse._nonZeroValues[j++];
_storage.Values[i++] += otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != Complex32.Zero)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], otherValue);
}
j++;
}
@ -494,25 +350,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] + otherSparse.At(next));
result.At(next, _storage.Values[i] + otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) + otherSparse._nonZeroValues[j]);
result.At(next, At(next) + otherSparse._storage.Values[j]);
}
j++;
}
@ -615,22 +471,22 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] -= otherSparse._nonZeroValues[j++];
_storage.Values[i++] -= otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != Complex32.Zero)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], -otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], -otherValue);
}
j++;
}
@ -640,25 +496,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] - otherSparse.At(next));
result.At(next, _storage.Values[i] - otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) - otherSparse._nonZeroValues[j]);
result.At(next, At(next) - otherSparse._storage.Values[j]);
}
j++;
}
@ -717,23 +573,18 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<Complex32> Negate()
{
var result = new SparseVector(Count)
{
_nonZeroValues = new Complex32[NonZerosCount],
_nonZeroIndices = new int[NonZerosCount],
NonZerosCount = NonZerosCount
};
var result = new SparseVectorStorage<Complex32>(Count);
var valueCount = result.ValueCount = _storage.ValueCount;
var indices = result.Indices = new int[valueCount];
var values = result.Values = new Complex32[valueCount];
if (NonZerosCount != 0)
if (valueCount != 0)
{
CommonParallel.For(
0,
NonZerosCount,
index => result._nonZeroValues[index] = -_nonZeroValues[index]);
Buffer.BlockCopy(_nonZeroIndices, 0, result._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, valueCount, index => values[index] = -_storage.Values[index]);
Buffer.BlockCopy(_storage.Indices, 0, indices, 0, valueCount * Constants.SizeOfInt);
}
return result;
return new SparseVector(result);
}
/// <summary>
@ -754,7 +605,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
var copy = new SparseVector(this);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._nonZeroValues, copy._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._storage.Values, copy._storage.Values);
return copy;
}
@ -789,23 +640,23 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (sparseResult == null)
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], scalar * _nonZeroValues[index]);
result.At(_storage.Indices[index], scalar * _storage.Values[index]);
}
}
else
{
if (!ReferenceEquals(this, result))
{
sparseResult.NonZerosCount = NonZerosCount;
sparseResult._nonZeroIndices = new int[NonZerosCount];
Buffer.BlockCopy(_nonZeroIndices, 0, sparseResult._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
sparseResult._nonZeroValues = new Complex32[NonZerosCount];
Array.Copy(_nonZeroValues, sparseResult._nonZeroValues, NonZerosCount);
sparseResult._storage.ValueCount = _storage.ValueCount;
sparseResult._storage.Indices = new int[_storage.ValueCount];
Buffer.BlockCopy(_storage.Indices, 0, sparseResult._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
sparseResult._storage.Values = new Complex32[_storage.ValueCount];
Array.Copy(_storage.Values, sparseResult._storage.Values, _storage.ValueCount);
}
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._nonZeroValues, sparseResult._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
}
}
@ -824,16 +675,16 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * _nonZeroValues[i];
result += _storage.Values[i] * _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * other.At(_nonZeroIndices[i]);
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
@ -925,17 +776,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <returns>The index of absolute minimum element.</returns>
public override int AbsoluteMinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
// No non-zero elements. Return 0
return 0;
}
var index = 0;
var min = _nonZeroValues[index].Magnitude;
for (var i = 1; i < NonZerosCount; i++)
var min = _storage.Values[index].Magnitude;
for (var i = 1; i < _storage.ValueCount; i++)
{
var test = _nonZeroValues[i].Magnitude;
var test = _storage.Values[i].Magnitude;
if (test < min)
{
index = i;
@ -943,7 +794,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1014,9 +865,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 Sum()
{
var result = Complex32.Zero;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i];
result += _storage.Values[i];
}
return result;
@ -1029,9 +880,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32 SumMagnitudes()
{
var result = 0.0f;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i].Magnitude;
result += _storage.Values[i].Magnitude;
}
return result;
@ -1046,17 +897,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] *= _nonZeroValues[i];
_storage.Values[i] *= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, other.At(index) * _nonZeroValues[i]);
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
@ -1070,17 +921,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] /= _nonZeroValues[i];
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, _nonZeroValues[i] / other.At(index));
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
}
}
}
@ -1106,13 +957,13 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
var matrix = new SparseMatrix(u.Count, v.Count);
for (var i = 0; i < u.NonZerosCount; i++)
for (var i = 0; i < u._storage.ValueCount; i++)
{
for (var j = 0; j < v.NonZerosCount; j++)
for (var j = 0; j < v._storage.ValueCount; j++)
{
if (u._nonZeroIndices[i] == v._nonZeroIndices[j])
if (u._storage.Indices[i] == v._storage.Indices[j])
{
matrix.At(i, j, u._nonZeroValues[i] * v._nonZeroValues[j]);
matrix.At(i, j, u._storage.Values[i] * v._storage.Values[j]);
}
}
}
@ -1148,25 +999,25 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
throw new ArgumentOutOfRangeException("p");
}
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return Complex32.Zero;
}
if (2.0 == p)
{
return _nonZeroValues.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
return _storage.Values.Aggregate(Complex32.Zero, SpecialFunctions.Hypotenuse).Magnitude;
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, NonZerosCount, i => _nonZeroValues[i].Magnitude, Math.Max, 0f);
return CommonParallel.Aggregate(0, _storage.ValueCount, i => _storage.Values[i].Magnitude, Math.Max, 0f);
}
var sum = 0.0;
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(_nonZeroValues[index].Magnitude, p);
sum += Math.Pow(_storage.Values[index].Magnitude, p);
}
return (float)Math.Pow(sum, 1.0 / p);
@ -1332,97 +1183,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
#endregion
/// <summary>
/// Gets the value at the given index.
/// </summary>
/// <param name="index">Value real index in array</param>
/// <returns>The value at the given index.</returns>
internal protected override Complex32 At(int index)
{
// Search if item idex exists in NonZeroIndices array in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
return itemIndex >= 0 ? _nonZeroValues[itemIndex] : Complex32.Zero;
}
/// <summary>
/// Delete, Add or Update the value in NonZeroValues and NonZeroIndices
/// </summary>
/// <param name="index">Value real index in array</param>
/// <param name="value">The value to set.</param>
/// <remarks>This method assume that index is between 0 and Array Size</remarks>
internal protected override void At(int index, Complex32 value)
{
// Search if "index" already exists in range "0 - complex nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
if (itemIndex >= 0)
{
// Item already exist at itemIndex
if (value == Complex32.Zero)
{
RemoveAtUnchecked(itemIndex);
}
else
{
_nonZeroValues[itemIndex] = value;
}
}
else
{
if (value != Complex32.Zero)
{
InsertAtUnchecked(~itemIndex, index, value);
}
}
}
private void InsertAtUnchecked(int itemIndex, int index, Complex32 value)
{
// Check if the storage needs to be increased
if ((NonZerosCount == _nonZeroValues.Length) && (NonZerosCount < Count))
if ((_storage.ValueCount == _storage.Values.Length) && (_storage.ValueCount < Count))
{
// Value and Indices arrays are completely full so we increase the size
var size = Math.Min(_nonZeroValues.Length + GrowthSize(), Count);
Array.Resize(ref _nonZeroValues, size);
Array.Resize(ref _nonZeroIndices, size);
var size = Math.Min(_storage.Values.Length + GrowthSize(), Count);
Array.Resize(ref _storage.Values, size);
Array.Resize(ref _storage.Indices, size);
}
// Move all values (with a position larger than index) in the value array
// to the next position
// Move all values (with a position larger than index) in the columIndices
// array to the next position
for (var i = NonZerosCount - 1; i > itemIndex - 1; i--)
for (var i = _storage.ValueCount - 1; i > itemIndex - 1; i--)
{
_nonZeroValues[i + 1] = _nonZeroValues[i];
_nonZeroIndices[i + 1] = _nonZeroIndices[i];
_storage.Values[i + 1] = _storage.Values[i];
_storage.Indices[i + 1] = _storage.Indices[i];
}
// Add the value and the column index
_nonZeroValues[itemIndex] = value;
_nonZeroIndices[itemIndex] = index;
_storage.Values[itemIndex] = value;
_storage.Indices[itemIndex] = index;
// increase the number of non-zero numbers by one
NonZerosCount += 1;
}
private void RemoveAtUnchecked(int itemIndex)
{
// Value is zero. Let's delete it from Values and Indices array
for (var i = itemIndex + 1; i < NonZerosCount; i++)
{
_nonZeroValues[i - 1] = _nonZeroValues[i];
_nonZeroIndices[i - 1] = _nonZeroIndices[i];
}
NonZerosCount -= 1;
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((NonZerosCount > 1024) && (NonZerosCount < _nonZeroIndices.Length / 2))
{
Array.Resize(ref _nonZeroValues, NonZerosCount);
Array.Resize(ref _nonZeroIndices, NonZerosCount);
}
_storage.ValueCount += 1;
}
/// <summary>
@ -1433,19 +1220,19 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
private int GrowthSize()
{
int delta;
if (_nonZeroValues.Length > 1024)
if (_storage.Values.Length > 1024)
{
delta = _nonZeroValues.Length / 4;
delta = _storage.Values.Length / 4;
}
else
{
if (_nonZeroValues.Length > 256)
if (_storage.Values.Length > 256)
{
delta = 512;
}
else
{
delta = _nonZeroValues.Length > 64 ? 128 : 32;
delta = _storage.Values.Length > 64 ? 128 : 32;
}
}
@ -1458,7 +1245,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
if (Count > 20)
{
return String.Format("SparseVectorOfComplex32({0},{1},{2})", Count, NonZerosCount, GetHashCode());
return String.Format("SparseVectorOfComplex32({0},{1},{2})", Count, _storage.ValueCount, GetHashCode());
}
return base.ToString(format, formatProvider);
@ -1472,14 +1259,14 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(NonZerosCount, 20);
var hashNum = Math.Min(_storage.ValueCount, 20);
long hash = 0;
for (var i = 0; i < hashNum; i++)
{
#if PORTABLE
hash ^= Precision.DoubleToInt64Bits(this._nonZeroValues[i].GetHashCode());
hash ^= Precision.DoubleToInt64Bits(this._storage.Values[i].GetHashCode());
#else
hash ^= BitConverter.DoubleToInt64Bits(_nonZeroValues[i].GetHashCode());
hash ^= BitConverter.DoubleToInt64Bits(_storage.Values[i].GetHashCode());
#endif
}
@ -1523,27 +1310,27 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
if (_nonZeroValues[i++] != Complex32.Zero)
if (_storage.Values[i++] != Complex32.Zero)
{
return false;
}
continue;
}
if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i])
if (i >= _storage.ValueCount || j < otherSparse._storage.ValueCount && otherSparse._storage.Indices[j] < _storage.Indices[i])
{
if (otherSparse._nonZeroValues[j++] != Complex32.Zero)
if (otherSparse._storage.Values[j++] != Complex32.Zero)
{
return false;
}
continue;
}
if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j]))
if (!_storage.Values[i].AlmostEqual(otherSparse._storage.Values[j]))
{
return false;
}
@ -1571,9 +1358,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </remarks>
public override IEnumerable<Tuple<int, Complex32>> GetIndexedEnumerator()
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
yield return new Tuple<int, Complex32>(_nonZeroIndices[i], _nonZeroValues[i]);
yield return new Tuple<int, Complex32>(_storage.Indices[i], _storage.Values[i]);
}
}
@ -1586,9 +1373,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
public override Complex32[] ToArray()
{
var ret = new Complex32[Count];
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
ret[_nonZeroIndices[i]] = _nonZeroValues[i];
ret[_storage.Indices[i]] = _storage.Values[i];
}
return ret;

11
src/Numerics/LinearAlgebra/Complex32/Vector.cs

@ -30,6 +30,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
using Distributions;
using Generic;
using Properties;
using Storage;
using Threading;
using Complex32 = Numerics.Complex32;
@ -41,15 +42,9 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
{
/// <summary>
/// Initializes a new instance of the Vector class.
/// Constructs a <strong>Vector</strong> with the given size.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to construct.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
protected Vector(int size) : base(size)
protected Vector(VectorStorage<Complex32> storage)
: base(storage)
{
}

77
src/Numerics/LinearAlgebra/Double/DenseMatrix.cs

@ -39,8 +39,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
[Serializable]
public class DenseMatrix : Matrix
{
readonly DenseColumnMajorMatrixStorage<double> _storage;
/// <summary>
/// Number of rows.
/// </summary>
@ -59,15 +57,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// Gets the matrix's data.
/// </summary>
/// <value>The matrix's data.</value>
readonly double[] _data;
readonly double[] _values;
internal DenseMatrix(DenseColumnMajorMatrixStorage<double> storage)
: base(storage)
{
_storage = storage;
_rowCount = _storage.RowCount;
_columnCount = _storage.ColumnCount;
_data = _storage.Data;
_rowCount = storage.RowCount;
_columnCount = storage.ColumnCount;
_values = storage.Data;
}
/// <summary>
@ -109,9 +106,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public DenseMatrix(int rows, int columns, double value)
: this(rows, columns)
{
for (var i = 0; i < _data.Length; i++)
for (var i = 0; i < _values.Length; i++)
{
_data[i] = value;
_values[i] = value;
}
}
@ -139,7 +136,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
for (var j = 0; j < _columnCount; j++)
{
_data[(j * _rowCount) + i] = array[i, j];
_values[(j * _rowCount) + i] = array[i, j];
}
}
}
@ -161,7 +158,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <value>The matrix's data.</value>
public double[] Data
{
get { return _data; }
get { return _values; }
}
/// <summary>
@ -203,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i];
ret._values[(i * _columnCount) + j] = _values[index + i];
}
}
@ -214,21 +211,21 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The L1 norm of the matrix.</returns>
public override double L1Norm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the Frobenius norm of this matrix.</summary>
/// <returns>The Frobenius norm of this matrix.</returns>
public override double FrobeniusNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the infinity norm of this matrix.</summary>
/// <returns>The infinity norm of this matrix.</returns>
public override double InfinityNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values);
}
#region Static constructors for special matrices.
@ -246,7 +243,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var m = new DenseMatrix(order);
for (var i = 0; i < order; i++)
{
m._data[(i * order) + i] = 1.0;
m._values[(i * order) + i] = 1.0;
}
return m;
@ -271,7 +268,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.AddArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.AddArrays(_values, denseOther._values, denseResult._values);
}
}
@ -290,7 +287,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.SubtractArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.SubtractArrays(_values, denseOther._values, denseResult._values);
}
}
@ -308,7 +305,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult._values);
}
}
@ -332,14 +329,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0,
denseResult.Data);
denseResult.Values);
}
}
@ -363,14 +360,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -394,14 +391,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.Transpose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -425,14 +422,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0,
denseResult.Data);
denseResult.Values);
}
}
@ -456,14 +453,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0,
denseResult._data);
denseResult._values);
}
}
@ -481,7 +478,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(-1, _values, denseResult._values);
}
}
@ -501,7 +498,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_values, denseOther._values, denseResult._values);
}
}
@ -521,7 +518,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.PointWiseDivideArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseDivideArrays(_values, denseOther._values, denseResult._values);
}
}
@ -547,8 +544,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CommonParallel.For(
0,
_data.Length,
index => denseResult._data[index] %= divisor);
_values.Length,
index => denseResult._values[index] %= divisor);
}
}
@ -567,7 +564,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var sum = 0.0;
for (var i = 0; i < _rowCount; i++)
{
sum += _data[(i * _rowCount) + i];
sum += _values[(i * _rowCount) + i];
}
return sum;

268
src/Numerics/LinearAlgebra/Double/DenseVector.cs

@ -33,6 +33,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -41,6 +42,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double
[Serializable]
public class DenseVector : Vector
{
/// <summary>
/// Number of elements
/// </summary>
readonly int _length;
/// <summary>
/// Gets the vector's data.
/// </summary>
readonly double[] _values;
internal DenseVector(DenseVectorStorage<double> storage)
: base(storage)
{
_length = storage.Length;
_values = storage.Data;
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
/// </summary>
@ -51,9 +69,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size)
: base(size)
: this(new DenseVectorStorage<double>(size))
{
Data = new double[size];
}
/// <summary>
@ -72,9 +89,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public DenseVector(int size, double value)
: this(size)
{
for (var index = 0; index < Data.Length; index++)
for (var index = 0; index < _values.Length; index++)
{
Data[index] = value;
_values[index] = value;
}
}
@ -88,31 +105,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public DenseVector(Vector<double> other)
: this(other.Count)
{
var vector = other as DenseVector;
if (vector == null)
{
CommonParallel.For(
0,
Data.Length,
index => this[index] = other[index]);
}
else
{
Buffer.BlockCopy(vector.Data, 0, Data, 0, Data.Length * Constants.SizeOfDouble);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(DenseVector other)
: this(other.Count)
{
Buffer.BlockCopy(other.Data, 0, Data, 0, Data.Length * Constants.SizeOfDouble);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -121,20 +114,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector does not copy the array, but keeps a reference to it. Any
/// changes to the vector will also change the array.</remarks>
public DenseVector(double[] array) : base(array.Length)
public DenseVector(double[] array)
: this(new DenseVectorStorage<double>(array.Length, array))
{
Data = array;
}
/// <summary>
/// Gets the vector's internal data.
/// Gets the vector's data.
/// </summary>
/// <value>The vector's internal data.</value>
/// <remarks>Changing values in the array also changes the corresponding value in vector. Use with care.</remarks>
internal double[] Data
/// <value>The vector's data.</value>
public double[] Values
{
get;
private set;
get { return _values; }
}
/// <summary>
@ -145,14 +136,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>
/// A reference to the internal date of the given vector.
/// </returns>
public static implicit operator double[](DenseVector vector)
public static explicit operator double[](DenseVector vector)
{
if (vector == null)
{
throw new ArgumentNullException();
}
return vector.Data;
return vector.Values;
}
/// <summary>
@ -178,10 +169,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>This vector as a column matrix.</returns>
public override Matrix<double> ToColumnMatrix()
{
var matrix = new DenseMatrix(Count, 1);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(_length, 1);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(i, 0, Data[i]);
matrix.At(i, 0, _values[i]);
}
return matrix;
@ -193,33 +184,15 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>This vector as a row matrix.</returns>
public override Matrix<double> ToRowMatrix()
{
var matrix = new DenseMatrix(1, Count);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(1, _length);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(0, i, Data[i]);
matrix.At(0, i, _values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override double this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -253,49 +226,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new DenseVector(size);
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<double> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as DenseVector;
if (otherVector == null)
{
CommonParallel.For(
0,
Data.Length,
index => target[index] = Data[index]);
}
else
{
Buffer.BlockCopy(Data, 0, otherVector.Data, 0, Data.Length * Constants.SizeOfDouble);
}
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -312,8 +242,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] + scalar);
_values.Length,
index => dense._values[index] = _values[index] + scalar);
}
}
@ -328,7 +258,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, 1.0, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, 1.0, odense.Values, rdense.Values);
}
else
{
@ -397,8 +327,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] - scalar);
_values.Length,
index => dense._values[index] = _values[index] - scalar);
}
}
@ -413,7 +343,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, -1.0, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, -1.0, odense.Values, rdense.Values);
}
else
{
@ -472,11 +402,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<double> Negate()
{
var result = new DenseVector(Count);
var result = new DenseVector(_length);
CommonParallel.For(
0,
Data.Length,
index => result[index] = -Data[index]);
_values.Length,
index => result[index] = -_values[index]);
return result;
}
@ -496,7 +426,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, Data, denseResult.Data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult.Values);
}
}
@ -510,7 +440,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(Data, denseVector.Data);
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -572,7 +502,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
}
return Control.LinearAlgebraProvider.DotProduct(leftSide.Data, rightSide.Data);
return Control.LinearAlgebraProvider.DotProduct(leftSide.Values, rightSide.Values);
}
/// <summary>
@ -602,16 +532,16 @@ namespace MathNet.Numerics.LinearAlgebra.Double
var denseResult = result as DenseVector;
if (denseResult == null)
{
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
result.At(index, Data[index] % divisor);
result.At(index, _values[index] % divisor);
}
}
else
{
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
denseResult.Data[index] = Data[index] % divisor;
denseResult._values[index] = _values[index] % divisor;
}
}
}
@ -640,10 +570,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override int AbsoluteMinimumIndex()
{
var index = 0;
var min = Math.Abs(Data[index]);
for (var i = 1; i < Count; i++)
var min = Math.Abs(_values[index]);
for (var i = 1; i < _length; i++)
{
var test = Math.Abs(Data[i]);
var test = Math.Abs(_values[i]);
if (test < min)
{
index = i;
@ -660,7 +590,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The value of the absolute minimum element.</returns>
public override double AbsoluteMinimum()
{
return Math.Abs(Data[AbsoluteMinimumIndex()]);
return Math.Abs(_values[AbsoluteMinimumIndex()]);
}
/// <summary>
@ -669,7 +599,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The value of the absolute maximum element.</returns>
public override double AbsoluteMaximum()
{
return Math.Abs(Data[AbsoluteMaximumIndex()]);
return Math.Abs(_values[AbsoluteMaximumIndex()]);
}
/// <summary>
@ -679,10 +609,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override int AbsoluteMaximumIndex()
{
var index = 0;
var max = Math.Abs(Data[index]);
for (var i = 1; i < Count; i++)
var max = Math.Abs(_values[index]);
for (var i = 1; i < _length; i++)
{
var test = Math.Abs(Data[i]);
var test = Math.Abs(_values[i]);
if (test > max)
{
index = i;
@ -706,7 +636,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception>
public override Vector<double> SubVector(int index, int length)
{
if (index < 0 || index >= Count)
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
@ -716,7 +646,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
throw new ArgumentOutOfRangeException("length");
}
if (index + length > Count)
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
@ -725,8 +655,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CommonParallel.For(
index,
index + length,
i => result.Data[i - index] = Data[i]);
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
@ -743,7 +673,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
throw new ArgumentNullException("values");
}
if (values.Length != Count)
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
@ -751,7 +681,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
CommonParallel.For(
0,
values.Length,
i => Data[i] = values[i]);
i => _values[i] = values[i]);
}
/// <summary>
@ -761,13 +691,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override int MaximumIndex()
{
var index = 0;
var max = Data[0];
for (var i = 1; i < Count; i++)
var max = _values[0];
for (var i = 1; i < _length; i++)
{
if (max < Data[i])
if (max < _values[i])
{
index = i;
max = Data[i];
max = _values[i];
}
}
@ -781,13 +711,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override int MinimumIndex()
{
var index = 0;
var min = Data[0];
for (var i = 1; i < Count; i++)
var min = _values[0];
for (var i = 1; i < _length; i++)
{
if (min > Data[i])
if (min > _values[i])
{
index = i;
min = Data[i];
min = _values[i];
}
}
@ -802,9 +732,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
var sum = 0.0;
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
sum += Data[index];
sum += _values[index];
}
return sum;
@ -818,9 +748,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
var sum = 0.0;
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
sum += Math.Abs(Data[index]);
sum += Math.Abs(_values[index]);
}
return sum;
@ -842,8 +772,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] * other[index]);
_values.Length,
index => dense._values[index] = _values[index] * other[index]);
}
}
@ -864,8 +794,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] / other[index]);
_values.Length,
index => dense._values[index] = _values[index] / other[index]);
}
}
@ -897,7 +827,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u.Data[i] * v.Data[j]);
matrix.At(i, j, u._values[i] * v._values[j]);
}
});
return matrix;
@ -937,18 +867,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (2.0 == p)
{
return Data.Aggregate(0.0, SpecialFunctions.Hypotenuse);
return _values.Aggregate(0.0, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(Data, (i, v) => Math.Abs(v), Math.Max, 0d);
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(Data[index]), p);
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
@ -1114,29 +1044,5 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
#endregion
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
Array.Clear(Data, 0, Data.Length);
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
internal protected override double At(int index)
{
return Data[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
internal protected override void At(int index, double value)
{
Data[index] = value;
}
}
}

4
src/Numerics/LinearAlgebra/Double/DiagonalMatrix.cs

@ -377,12 +377,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return;
}
if (_data.Length != denseSource.Data.Length)
if (_data.Length != denseSource.Values.Length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source");
}
Buffer.BlockCopy(denseSource.Data, 0, _data, 0, denseSource.Data.Length * Constants.SizeOfDouble);
Buffer.BlockCopy(denseSource.Values, 0, _data, 0, denseSource.Values.Length * Constants.SizeOfDouble);
}
/// <summary>

4
src/Numerics/LinearAlgebra/Double/Factorization/DenseCholesky.cs

@ -167,11 +167,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfDouble);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfDouble);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, 1);
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Values, 1);
}
}
}

2
src/Numerics/LinearAlgebra/Double/Factorization/DenseGramSchmidt.cs

@ -216,7 +216,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Data, 1, dresult.Data);
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Values, 1, dresult.Values);
}
}
}

4
src/Numerics/LinearAlgebra/Double/Factorization/DenseLU.cs

@ -168,11 +168,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfDouble);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfDouble);
// LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors;
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Values);
}
/// <summary>

2
src/Numerics/LinearAlgebra/Double/Factorization/DenseQR.cs

@ -188,7 +188,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values);
}
}
}

6
src/Numerics/LinearAlgebra/Double/Factorization/DenseSvd.cs

@ -69,7 +69,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
VectorS = new DenseVector(nm);
MatrixU = new DenseMatrix(matrix.RowCount);
MatrixVT = new DenseMatrix(matrix.ColumnCount);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
}
/// <summary>
@ -125,7 +125,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
}
/// <summary>
@ -175,7 +175,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Values, 1, dresult.Values);
}
}
}

1
src/Numerics/LinearAlgebra/Double/SparseMatrix.cs

@ -97,6 +97,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// The number of columns.
/// </param>
/// <param name="value">The value which we assign to each element of the matrix.</param>
[Obsolete("Use a dense matrix instead.")]
public SparseMatrix(int rows, int columns, double value)
: this(rows, columns)
{

483
src/Numerics/LinearAlgebra/Double/SparseVector.cs

@ -37,6 +37,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -46,24 +47,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double
[Serializable]
public class SparseVector : Vector
{
/// <summary>
/// Gets the vector's internal data. The array containing the actual values; only the non-zero values are stored.
/// </summary>
private double[] _nonZeroValues = new double[0];
/// <summary>
/// The indices of the non-zero entries.
/// </summary>
private int[] _nonZeroIndices = new int[0];
readonly SparseVectorStorage<double> _storage;
/// <summary>
/// Gets the number of non zero elements in the vector.
/// </summary>
/// <value>The number of non zero elements.</value>
public int NonZerosCount
internal SparseVector(SparseVectorStorage<double> storage)
: base(storage)
{
get;
private set;
_storage = storage;
}
#region Constructors
@ -77,7 +66,8 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size) : base(size)
public SparseVector(int size)
: this(new SparseVectorStorage<double>(size))
{
}
@ -94,55 +84,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size, double value) : this(size)
[Obsolete("Use a dense vector instead.")]
public SparseVector(int size, double value)
: this(new SparseVectorStorage<double>(size))
{
if (value == 0.0)
{
// Skip adding values
return;
}
// We already know that this vector is "full", let's allocate all needed memory
_nonZeroValues = new double[size];
_nonZeroIndices = new int[size];
NonZerosCount = size;
CommonParallel.For(
0,
Count,
index =>
{
_nonZeroValues[index] = value;
_nonZeroIndices[index] = index;
});
}
var valueCount = _storage.ValueCount = size;
var indices = _storage.Indices = new int[valueCount];
var values = _storage.Values = new double[valueCount];
/// <summary>
/// Initializes a new instance of the <see cref="SparseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(Vector<double> other) : this(other.Count)
{
var vector = other as SparseVector;
if (vector == null)
for (int i = 0; i < values.Length; i++)
{
for (var i = 0; i < other.Count; i++)
{
this[i] = other.At(i);
}
}
else
{
_nonZeroValues = new double[vector.NonZerosCount];
_nonZeroIndices = new int[vector.NonZerosCount];
NonZerosCount = vector.NonZerosCount;
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
Buffer.BlockCopy(vector._nonZeroValues, 0, _nonZeroValues, 0, vector.NonZerosCount * Constants.SizeOfDouble);
Buffer.BlockCopy(vector._nonZeroIndices, 0, _nonZeroIndices, 0, vector.NonZerosCount * Constants.SizeOfInt);
values[i] = value;
indices[i] = i;
}
}
@ -153,15 +111,10 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(SparseVector other) : this(other.Count)
public SparseVector(Vector<double> other)
: this(new SparseVectorStorage<double>(other.Count))
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
_nonZeroValues = new double[other.NonZerosCount];
_nonZeroIndices = new int[other.NonZerosCount];
NonZerosCount = other.NonZerosCount;
Buffer.BlockCopy(other._nonZeroValues, 0, _nonZeroValues, 0, other.NonZerosCount * Constants.SizeOfDouble);
Buffer.BlockCopy(other._nonZeroIndices, 0, _nonZeroIndices, 0, other.NonZerosCount * Constants.SizeOfInt);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -169,11 +122,12 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </summary>
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector copy the array. Any changes to the vector will NOT change the array.</remarks>
public SparseVector(IList<double> array) : this(array.Count)
public SparseVector(IList<double> array)
: this(new SparseVectorStorage<double>(array.Count))
{
for (var i = 0; i < array.Count; i++)
{
this[i] = array[i];
Storage.At(i, array[i]);
}
}
@ -185,10 +139,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>This vector as a column matrix.</returns>
public override Matrix<double> ToColumnMatrix()
{
var indices = _storage.Indices;
var values = _storage.Values;
var matrix = new SparseMatrix(Count, 1);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(_nonZeroIndices[i], 0, _nonZeroValues[i]);
matrix.At(indices[i], 0, values[i]);
}
return matrix;
@ -200,10 +157,13 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>This vector as a row matrix.</returns>
public override Matrix<double> ToRowMatrix()
{
var indices = _storage.Indices;
var values = _storage.Values;
var matrix = new SparseMatrix(1, Count);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(0, _nonZeroIndices[i], _nonZeroValues[i]);
matrix.At(0, indices[i], values[i]);
}
return matrix;
@ -242,68 +202,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return new SparseVector(size);
}
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
NonZerosCount = 0;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<double> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as SparseVector;
if (otherVector == null)
{
target.Clear();
for (var index = 0; index < NonZerosCount; index++)
{
target.At(_nonZeroIndices[index], _nonZeroValues[index]);
}
}
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new double[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
if (NonZerosCount != 0)
{
Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount*Constants.SizeOfDouble);
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount*Constants.SizeOfInt);
}
}
}
#region Operators and supplementary functions
/// <summary>
@ -340,16 +238,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double
vnonZeroValues[index] = scalar;
}
var indices = _storage.Indices;
var values = _storage.Values;
//populate the non zero values from this
for (int j = 0; j < NonZerosCount; j++)
for (int j = 0; j < _storage.ValueCount; j++)
{
vnonZeroValues[_nonZeroIndices[j]] = _nonZeroValues[j] + scalar;
vnonZeroValues[indices[j]] = values[j] + scalar;
}
//assign this vectors arrary to the new arrays.
_nonZeroValues = vnonZeroValues;
_nonZeroIndices = vnonZeroIndices;
NonZerosCount = Count;
//assign this vectors arrary to the new arrays.
_storage.Values = vnonZeroValues;
_storage.Indices = vnonZeroIndices;
_storage.ValueCount = Count;
}
else
{
@ -390,22 +291,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] += otherSparse._nonZeroValues[j++];
_storage.Values[i++] += otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != 0.0)
{
InsertAtIndexUnchecked(i++, otherSparse._nonZeroIndices[j], otherValue);
InsertAtIndexUnchecked(i++, otherSparse._storage.Indices[j], otherValue);
}
j++;
}
@ -415,25 +316,25 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] + otherSparse.At(next));
result.At(next, _storage.Values[i] + otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) + otherSparse._nonZeroValues[j]);
result.At(next, At(next) + otherSparse._storage.Values[j]);
}
j++;
}
@ -536,22 +437,22 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] -= otherSparse._nonZeroValues[j++];
_storage.Values[i++] -= otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != 0.0)
{
InsertAtIndexUnchecked(i++, otherSparse._nonZeroIndices[j], -otherValue);
InsertAtIndexUnchecked(i++, otherSparse._storage.Indices[j], -otherValue);
}
j++;
}
@ -561,25 +462,25 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] - otherSparse.At(next));
result.At(next, _storage.Values[i] - otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) - otherSparse._nonZeroValues[j]);
result.At(next, At(next) - otherSparse._storage.Values[j]);
}
j++;
}
@ -638,24 +539,18 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<double> Negate()
{
var result = new SparseVector(Count)
{
_nonZeroValues = new double[NonZerosCount],
_nonZeroIndices = new int[NonZerosCount],
NonZerosCount = NonZerosCount
};
var result = new SparseVectorStorage<double>(Count);
var valueCount = result.ValueCount = _storage.ValueCount;
var indices = result.Indices = new int[valueCount];
var values = result.Values = new double[valueCount];
if (NonZerosCount != 0)
if (valueCount != 0)
{
CommonParallel.For(
0,
NonZerosCount,
index => result._nonZeroValues[index] = -_nonZeroValues[index]);
Buffer.BlockCopy(_nonZeroIndices, 0, result._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, valueCount, index => values[index] = -_storage.Values[index]);
Buffer.BlockCopy(_storage.Indices, 0, indices, 0, valueCount * Constants.SizeOfInt);
}
return result;
return new SparseVector(result);
}
/// <summary>
@ -676,7 +571,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
var copy = new SparseVector(this);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._nonZeroValues, copy._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._storage.Values, copy._storage.Values);
return copy;
}
@ -711,23 +606,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (sparseResult == null)
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], scalar * _nonZeroValues[index]);
result.At(_storage.Indices[index], scalar * _storage.Values[index]);
}
}
else
{
if (!ReferenceEquals(this, result))
{
sparseResult.NonZerosCount = NonZerosCount;
sparseResult._nonZeroIndices = new int[NonZerosCount];
Buffer.BlockCopy(_nonZeroIndices, 0, sparseResult._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
sparseResult._nonZeroValues = new double[NonZerosCount];
Buffer.BlockCopy(_nonZeroValues, 0, sparseResult._nonZeroValues, 0, NonZerosCount * Constants.SizeOfDouble);
sparseResult._storage.ValueCount = _storage.ValueCount;
sparseResult._storage.Indices = new int[_storage.ValueCount];
Buffer.BlockCopy(_storage.Indices, 0, sparseResult._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
sparseResult._storage.Values = new double[_storage.ValueCount];
Buffer.BlockCopy(_storage.Values, 0, sparseResult._storage.Values, 0, _storage.ValueCount * Constants.SizeOfDouble);
}
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._nonZeroValues, sparseResult._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
}
}
@ -746,16 +641,16 @@ namespace MathNet.Numerics.LinearAlgebra.Double
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * _nonZeroValues[i];
result += _storage.Values[i] * _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * other.At(_nonZeroIndices[i]);
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
@ -850,17 +745,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
if (ReferenceEquals(this, result))
{
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
_nonZeroValues[index] %= divisor;
_storage.Values[index] %= divisor;
}
}
else
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], _nonZeroValues[index] % divisor);
result.At(_storage.Indices[index], _storage.Values[index] % divisor);
}
}
}
@ -888,17 +783,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The index of absolute minimum element.</returns>
public override int AbsoluteMinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
// No non-zero elements. Return 0
return 0;
}
var index = 0;
var min = Math.Abs(_nonZeroValues[index]);
for (var i = 1; i < NonZerosCount; i++)
var min = Math.Abs(_storage.Values[index]);
for (var i = 1; i < _storage.ValueCount; i++)
{
var test = Math.Abs(_nonZeroValues[i]);
var test = Math.Abs(_storage.Values[i]);
if (test < min)
{
index = i;
@ -906,7 +801,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -976,23 +871,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The index of absolute maximum element.</returns>
public override int MaximumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0;
}
var index = 0;
var max = _nonZeroValues[0];
for (var i = 1; i < NonZerosCount; i++)
var max = _storage.Values[0];
for (var i = 1; i < _storage.ValueCount; i++)
{
if (max < _nonZeroValues[i])
if (max < _storage.Values[i])
{
index = i;
max = _nonZeroValues[i];
max = _storage.Values[i];
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1001,23 +896,23 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <returns>The index of minimum element.</returns>
public override int MinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0;
}
var index = 0;
var min = _nonZeroValues[0];
for (var i = 1; i < NonZerosCount; i++)
var min = _storage.Values[0];
for (var i = 1; i < _storage.ValueCount; i++)
{
if (min > _nonZeroValues[i])
if (min > _storage.Values[i])
{
index = i;
min = _nonZeroValues[i];
min = _storage.Values[i];
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1027,9 +922,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double Sum()
{
double result = 0;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i];
result += _storage.Values[i];
}
return result;
@ -1042,9 +937,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double SumMagnitudes()
{
double result = 0;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += Math.Abs(_nonZeroValues[i]);
result += Math.Abs(_storage.Values[i]);
}
return result;
@ -1059,17 +954,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] *= _nonZeroValues[i];
_storage.Values[i] *= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, other.At(index) * _nonZeroValues[i]);
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
@ -1083,17 +978,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] /= _nonZeroValues[i];
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, _nonZeroValues[i] / other.At(index));
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
}
}
}
@ -1119,11 +1014,11 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
var matrix = new SparseMatrix(u.Count, v.Count);
for (var i = 0; i < u.NonZerosCount; i++)
for (var i = 0; i < u._storage.ValueCount; i++)
{
for (var j = 0; j < v.NonZerosCount; j++)
for (var j = 0; j < v._storage.ValueCount; j++)
{
matrix.At(i, j, u._nonZeroValues[i] * v._nonZeroValues[j]);
matrix.At(i, j, u._storage.Values[i] * v._storage.Values[j]);
}
}
@ -1158,25 +1053,25 @@ namespace MathNet.Numerics.LinearAlgebra.Double
throw new ArgumentOutOfRangeException("p");
}
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0.0;
}
if (2.0 == p)
{
return _nonZeroValues.Aggregate(0.0, SpecialFunctions.Hypotenuse);
return _storage.Values.Aggregate(0.0, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, NonZerosCount, i => Math.Abs(_nonZeroValues[i]), Math.Max, 0d);
return CommonParallel.Aggregate(0, _storage.ValueCount, i => Math.Abs(_storage.Values[i]), Math.Max, 0d);
}
var sum = 0.0;
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(Math.Abs(_nonZeroValues[index]), p);
sum += Math.Pow(Math.Abs(_storage.Values[index]), p);
}
return Math.Pow(sum, 1.0 / p);
@ -1343,97 +1238,33 @@ namespace MathNet.Numerics.LinearAlgebra.Double
#endregion
/// <summary>
/// Gets the value at the given index.
/// </summary>
/// <param name="index">Value real index in array</param>
/// <returns>The value at the given index.</returns>
internal protected override double At(int index)
{
// Search if item idex exists in NonZeroIndices array in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
return itemIndex >= 0 ? _nonZeroValues[itemIndex] : 0.0;
}
/// <summary>
/// Delete, Add or Update the value in NonZeroValues and NonZeroIndices
/// </summary>
/// <param name="index">Value real index in array</param>
/// <param name="value">The value to set.</param>
/// <remarks>This method assume that index is between 0 and Array Size</remarks>
internal protected override void At(int index, double value)
{
// Search if "index" already exists in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
if (itemIndex >= 0)
{
// Item already exist at itemIndex
if (value == 0.0)
{
RemoveAtIndexUnchecked(itemIndex);
}
else
{
_nonZeroValues[itemIndex] = value;
}
}
else
{
if (value != 0.0)
{
InsertAtIndexUnchecked(~itemIndex, index, value);
}
}
}
private void InsertAtIndexUnchecked(int itemIndex, int index, double value)
{
// Check if the storage needs to be increased
if ((NonZerosCount == _nonZeroValues.Length) && (NonZerosCount < Count))
if ((_storage.ValueCount == _storage.Values.Length) && (_storage.ValueCount < Count))
{
// Value and Indices arrays are completely full so we increase the size
var size = Math.Min(_nonZeroValues.Length + GrowthSize(), Count);
Array.Resize(ref _nonZeroValues, size);
Array.Resize(ref _nonZeroIndices, size);
var size = Math.Min(_storage.Values.Length + GrowthSize(), Count);
Array.Resize(ref _storage.Values, size);
Array.Resize(ref _storage.Indices, size);
}
// Move all values (with a position larger than index) in the value array
// to the next position
// Move all values (with a position larger than index) in the columIndices
// array to the next position
for (var i = NonZerosCount - 1; i > itemIndex - 1; i--)
for (var i = _storage.ValueCount - 1; i > itemIndex - 1; i--)
{
_nonZeroValues[i + 1] = _nonZeroValues[i];
_nonZeroIndices[i + 1] = _nonZeroIndices[i];
_storage.Values[i + 1] = _storage.Values[i];
_storage.Indices[i + 1] = _storage.Indices[i];
}
// Add the value and the column index
_nonZeroValues[itemIndex] = value;
_nonZeroIndices[itemIndex] = index;
_storage.Values[itemIndex] = value;
_storage.Indices[itemIndex] = index;
// increase the number of non-zero numbers by one
NonZerosCount += 1;
}
private void RemoveAtIndexUnchecked(int itemIndex)
{
// Value is zero. Let's delete it from Values and Indices array
for (var i = itemIndex + 1; i < NonZerosCount; i++)
{
_nonZeroValues[i - 1] = _nonZeroValues[i];
_nonZeroIndices[i - 1] = _nonZeroIndices[i];
}
NonZerosCount -= 1;
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((NonZerosCount > 1024) && (NonZerosCount < _nonZeroIndices.Length / 2))
{
Array.Resize(ref _nonZeroValues, NonZerosCount);
Array.Resize(ref _nonZeroIndices, NonZerosCount);
}
_storage.ValueCount += 1;
}
/// <summary>
@ -1444,19 +1275,19 @@ namespace MathNet.Numerics.LinearAlgebra.Double
private int GrowthSize()
{
int delta;
if (_nonZeroValues.Length > 1024)
if (_storage.Values.Length > 1024)
{
delta = _nonZeroValues.Length / 4;
delta = _storage.Values.Length / 4;
}
else
{
if (_nonZeroValues.Length > 256)
if (_storage.Values.Length > 256)
{
delta = 512;
}
else
{
delta = _nonZeroValues.Length > 64 ? 128 : 32;
delta = _storage.Values.Length > 64 ? 128 : 32;
}
}
@ -1469,7 +1300,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
if (Count > 20)
{
return String.Format("SparseVectorOfDouble({0},{1},{2})", Count, NonZerosCount, GetHashCode());
return String.Format("SparseVectorOfDouble({0},{1},{2})", Count, _storage.ValueCount, GetHashCode());
}
return base.ToString(format, formatProvider);
@ -1483,14 +1314,14 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(NonZerosCount, 20);
var hashNum = Math.Min(_storage.ValueCount, 20);
long hash = 0;
for (var i = 0; i < hashNum; i++)
{
#if PORTABLE
hash ^= Precision.DoubleToInt64Bits(this._nonZeroValues[i].GetHashCode());
hash ^= Precision.DoubleToInt64Bits(this._storage.Values[i].GetHashCode());
#else
hash ^= BitConverter.DoubleToInt64Bits(_nonZeroValues[i].GetHashCode());
hash ^= BitConverter.DoubleToInt64Bits(_storage.Values[i].GetHashCode());
#endif
}
@ -1534,27 +1365,27 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
if (_nonZeroValues[i++] != 0d)
if (_storage.Values[i++] != 0d)
{
return false;
}
continue;
}
if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i])
if (i >= _storage.ValueCount || j < otherSparse._storage.ValueCount && otherSparse._storage.Indices[j] < _storage.Indices[i])
{
if (otherSparse._nonZeroValues[j++] != 0d)
if (otherSparse._storage.Values[j++] != 0d)
{
return false;
}
continue;
}
if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j]))
if (!_storage.Values[i].AlmostEqual(otherSparse._storage.Values[j]))
{
return false;
}
@ -1582,9 +1413,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </remarks>
public override IEnumerable<Tuple<int, double>> GetIndexedEnumerator()
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
yield return new Tuple<int, double>(_nonZeroIndices[i], _nonZeroValues[i]);
yield return new Tuple<int, double>(_storage.Indices[i], _storage.Values[i]);
}
}
@ -1597,9 +1428,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
public override double[] ToArray()
{
var ret = new double[Count];
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
ret[_nonZeroIndices[i]] = _nonZeroValues[i];
ret[_storage.Indices[i]] = _storage.Values[i];
}
return ret;

11
src/Numerics/LinearAlgebra/Double/Vector.cs

@ -30,6 +30,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
using Distributions;
using Generic;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -40,15 +41,9 @@ namespace MathNet.Numerics.LinearAlgebra.Double
{
/// <summary>
/// Initializes a new instance of the Vector class.
/// Constructs a <strong>Vector</strong> with the given size.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to construct.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
protected Vector(int size) : base(size)
protected Vector(VectorStorage<double> storage)
: base(storage)
{
}

288
src/Numerics/LinearAlgebra/Generic/Vector.cs

@ -34,6 +34,7 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
using Distributions;
using Numerics;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -60,60 +61,152 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
private static readonly T One = Common.SetOne<T>();
/// <summary>
/// Initializes a new instance of the Vector class.
/// Constructs a <strong>Vector</strong> with the given size.
/// Initializes a new instance of the Vector class.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to construct.
/// </param>
/// <exception cref="ArgumentOutOfRangeException">
/// If <paramref name="size"/> is less than one.
/// </exception>
protected Vector(int size)
protected Vector(VectorStorage<T> storage)
{
if (size < 1)
{
throw new ArgumentOutOfRangeException("size", Resources.ArgumentMustBePositive);
}
Count = size;
Storage = storage;
Count = storage.Length;
}
/// <summary>
/// Gets he number of elements in the vector.
/// Gets the raw vector data storage.
/// </summary>
public int Count
{
get;
private set;
}
public VectorStorage<T> Storage { get; private set; }
/// <summary>
/// Gets the number of items.
/// </summary>
public int Count { get; private set; }
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="ArgumentOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public virtual T this[int index]
public T this[int index]
{
get
get { return Storage[index]; }
set { Storage[index] = value;}
}
/// <summary>Gets the value at the given <paramref name="index"/> without range checking..</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
public T At(int index)
{
return Storage.At(index);
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/> without range checking..</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
public void At(int index, T value)
{
Storage.At(index, value);
}
/// <summary>
/// Resets all values to zero.
/// </summary>
public void Clear()
{
Storage.Clear();
}
/// <summary>
/// Sets all values of a subvector to zero.
/// </summary>
public void ClearSubVector(int index, int count)
{
if (count < 1)
{
if (index < 0 || index >= Count)
{
throw new ArgumentOutOfRangeException("index");
}
throw new ArgumentOutOfRangeException("count", Resources.ArgumentMustBePositive);
}
return At(index);
if (index + count > Count || index < 0)
{
throw new ArgumentOutOfRangeException("index");
}
set
Storage.Clear(index, count);
}
/// <summary>
/// Returns a deep-copy clone of the vector.
/// </summary>
/// <returns>
/// A deep-copy clone of the vector.
/// </returns>
public Vector<T> Clone()
{
var result = CreateVector(Count);
Storage.CopyTo(result.Storage, skipClearing: true);
return result;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public void CopyTo(Vector<T> target)
{
if (target == null)
{
if (index < 0 || index >= Count)
{
throw new ArgumentOutOfRangeException("index");
}
throw new ArgumentNullException("target");
}
if (ReferenceEquals(this, target) || ReferenceEquals(Storage, target.Storage))
{
return;
}
At(index, value);
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
Storage.CopyTo(target.Storage);
}
/// <summary>
/// Copies the requested elements from this vector to another.
/// </summary>
/// <param name="destination">
/// The vector to copy the elements to.
/// </param>
/// <param name="sourceIndex">
/// The element to start copying from.
/// </param>
/// <param name="targetIndex">
/// The element to start copying to.
/// </param>
/// <param name="count">
/// The number of elements to copy.
/// </param>
public void CopySubVectorTo(Vector<T> destination, int sourceIndex, int targetIndex, int count)
{
if (destination == null)
{
throw new ArgumentNullException("destination");
}
// TODO: refactor range checks
Storage.CopySubVectorTo(destination.Storage, sourceIndex, targetIndex, count);
}
[Obsolete("Use CopySubVectorTo instead.")]
public void CopyTo(Vector<T> destination, int sourceIndex, int targetIndex, int count)
{
CopySubVectorTo(destination, sourceIndex, targetIndex, count);
}
/// <summary>
@ -1166,115 +1259,6 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
#region Copying and Conversion
/// <summary>
/// Returns a deep-copy clone of the vector.
/// </summary>
/// <returns>
/// A deep-copy clone of the vector.
/// </returns>
public Vector<T> Clone()
{
var retrunVector = CreateVector(Count);
CopyTo(retrunVector);
return retrunVector;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public virtual void CopyTo(Vector<T> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
CommonParallel.For(
0,
Count,
index => target[index] = this[index]);
}
/// <summary>
/// Copies the requested elements from this vector to another.
/// </summary>
/// <param name="destination">
/// The vector to copy the elements to.
/// </param>
/// <param name="offset">
/// The element to start copying from.
/// </param>
/// <param name="destinationOffset">
/// The element to start copying to.
/// </param>
/// <param name="count">
/// The number of elements to copy.
/// </param>
public virtual void CopyTo(Vector<T> destination, int offset, int destinationOffset, int count)
{
if (destination == null)
{
throw new ArgumentNullException("destination");
}
if (offset >= Count)
{
throw new ArgumentOutOfRangeException("offset");
}
if (offset + count > Count)
{
throw new ArgumentOutOfRangeException("count");
}
if (destinationOffset >= destination.Count)
{
throw new ArgumentOutOfRangeException("destinationOffset");
}
if (destinationOffset + count > destination.Count)
{
throw new ArgumentOutOfRangeException("count");
}
if (ReferenceEquals(this, destination))
{
var tmpVector = destination.CreateVector(destination.Count);
CopyTo(tmpVector);
CommonParallel.For(
0,
count,
index => destination[destinationOffset + index] = tmpVector[offset + index]);
}
else
{
CommonParallel.For(
0,
count,
index => destination[destinationOffset + index] = this[offset + index]);
}
}
/// <summary>
/// Returns the data contained in the vector as an array.
/// </summary>
@ -1605,23 +1589,5 @@ namespace MathNet.Numerics.LinearAlgebra.Generic
}
#endregion
/// <summary>
/// Resets all values to zero.
/// </summary>
public virtual void Clear()
{
CommonParallel.For(0, Count, index => this[index] = default(T));
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
internal protected abstract T At(int index);
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
internal protected abstract void At(int index, T value);
}
}

77
src/Numerics/LinearAlgebra/Single/DenseMatrix.cs

@ -39,8 +39,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
[Serializable]
public class DenseMatrix : Matrix
{
readonly DenseColumnMajorMatrixStorage<float> _storage;
/// <summary>
/// Number of rows.
/// </summary>
@ -59,15 +57,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// Gets the matrix's data.
/// </summary>
/// <value>The matrix's data.</value>
readonly float[] _data;
readonly float[] _values;
internal DenseMatrix(DenseColumnMajorMatrixStorage<float> storage)
: base(storage)
{
_storage = storage;
_rowCount = _storage.RowCount;
_columnCount = _storage.ColumnCount;
_data = _storage.Data;
_rowCount = storage.RowCount;
_columnCount = storage.ColumnCount;
_values = storage.Data;
}
/// <summary>
@ -109,9 +106,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public DenseMatrix(int rows, int columns, float value)
: this(rows, columns)
{
for (var i = 0; i < _data.Length; i++)
for (var i = 0; i < _values.Length; i++)
{
_data[i] = value;
_values[i] = value;
}
}
@ -139,7 +136,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
for (var j = 0; j < _columnCount; j++)
{
_data[(j * _rowCount) + i] = array[i, j];
_values[(j * _rowCount) + i] = array[i, j];
}
}
}
@ -161,7 +158,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <value>The matrix's data.</value>
public float[] Data
{
get { return _data; }
get { return _values; }
}
/// <summary>
@ -203,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var index = j * _rowCount;
for (var i = 0; i < _rowCount; i++)
{
ret._data[(i * _columnCount) + j] = _data[index + i];
ret._values[(i * _columnCount) + j] = _values[index + i];
}
}
@ -214,21 +211,21 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The L1 norm of the matrix.</returns>
public override float L1Norm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.OneNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the Frobenius norm of this matrix.</summary>
/// <returns>The Frobenius norm of this matrix.</returns>
public override float FrobeniusNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.FrobeniusNorm, _rowCount, _columnCount, _values);
}
/// <summary>Calculates the infinity norm of this matrix.</summary>
/// <returns>The infinity norm of this matrix.</returns>
public override float InfinityNorm()
{
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _data);
return Control.LinearAlgebraProvider.MatrixNorm(Norm.InfinityNorm, _rowCount, _columnCount, _values);
}
#region Static constructors for special matrices.
@ -246,7 +243,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var m = new DenseMatrix(order);
for (var i = 0; i < order; i++)
{
m._data[(i * order) + i] = 1.0f;
m._values[(i * order) + i] = 1.0f;
}
return m;
@ -271,7 +268,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.AddArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.AddArrays(_values, denseOther._values, denseResult._values);
}
}
@ -290,7 +287,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.SubtractArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.SubtractArrays(_values, denseOther._values, denseResult._values);
}
}
@ -308,7 +305,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult._values);
}
}
@ -332,14 +329,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0f,
denseResult.Data);
denseResult.Values);
}
}
@ -363,14 +360,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -394,14 +391,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
Algorithms.LinearAlgebra.Transpose.DontTranspose,
Algorithms.LinearAlgebra.Transpose.Transpose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -425,14 +422,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseRight.Data,
denseRight.Values,
denseRight.Count,
1,
0.0f,
denseResult.Data);
denseResult.Values);
}
}
@ -456,14 +453,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
Algorithms.LinearAlgebra.Transpose.Transpose,
Algorithms.LinearAlgebra.Transpose.DontTranspose,
1.0f,
_data,
_values,
_rowCount,
_columnCount,
denseOther._data,
denseOther._values,
denseOther._rowCount,
denseOther._columnCount,
0.0f,
denseResult._data);
denseResult._values);
}
}
@ -481,7 +478,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.ScaleArray(-1, _data, denseResult._data);
Control.LinearAlgebraProvider.ScaleArray(-1, _values, denseResult._values);
}
}
@ -501,7 +498,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseMultiplyArrays(_values, denseOther._values, denseResult._values);
}
}
@ -521,7 +518,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.PointWiseDivideArrays(_data, denseOther._data, denseResult._data);
Control.LinearAlgebraProvider.PointWiseDivideArrays(_values, denseOther._values, denseResult._values);
}
}
@ -547,8 +544,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
CommonParallel.For(
0,
_data.Length,
index => denseResult._data[index] %= divisor);
_values.Length,
index => denseResult._values[index] %= divisor);
}
}
@ -567,7 +564,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var sum = 0.0f;
for (var i = 0; i < _rowCount; i++)
{
sum += _data[(i * _rowCount) + i];
sum += _values[(i * _rowCount) + i];
}
return sum;

268
src/Numerics/LinearAlgebra/Single/DenseVector.cs

@ -33,6 +33,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -41,6 +42,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single
[Serializable]
public class DenseVector : Vector
{
/// <summary>
/// Number of elements
/// </summary>
readonly int _length;
/// <summary>
/// Gets the vector's data.
/// </summary>
readonly float[] _values;
internal DenseVector(DenseVectorStorage<float> storage)
: base(storage)
{
_length = storage.Length;
_values = storage.Data;
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class with a given size.
/// </summary>
@ -51,9 +69,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// If <paramref name="size"/> is less than one.
/// </exception>
public DenseVector(int size)
: base(size)
: this(new DenseVectorStorage<float>(size))
{
Data = new float[size];
}
/// <summary>
@ -72,9 +89,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public DenseVector(int size, float value)
: this(size)
{
for (var index = 0; index < Data.Length; index++)
for (var index = 0; index < _values.Length; index++)
{
Data[index] = value;
_values[index] = value;
}
}
@ -88,31 +105,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public DenseVector(Vector<float> other)
: this(other.Count)
{
var vector = other as DenseVector;
if (vector == null)
{
CommonParallel.For(
0,
Data.Length,
index => this[index] = other[index]);
}
else
{
Buffer.BlockCopy(vector.Data, 0, Data, 0, Data.Length * Constants.SizeOfFloat);
}
}
/// <summary>
/// Initializes a new instance of the <see cref="DenseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public DenseVector(DenseVector other)
: this(other.Count)
{
Buffer.BlockCopy(other.Data, 0, Data, 0, Data.Length * Constants.SizeOfFloat);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -121,20 +114,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector does not copy the array, but keeps a reference to it. Any
/// changes to the vector will also change the array.</remarks>
public DenseVector(float[] array) : base(array.Length)
public DenseVector(float[] array)
: this(new DenseVectorStorage<float>(array.Length, array))
{
Data = array;
}
/// <summary>
/// Gets the vector's internal data.
/// Gets the vector's data.
/// </summary>
/// <value>The vector's internal data.</value>
/// <remarks>Changing values in the array also changes the corresponding value in vector. Use with care.</remarks>
internal float[] Data
/// <value>The vector's data.</value>
public float[] Values
{
get;
private set;
get { return _values; }
}
/// <summary>
@ -145,14 +136,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>
/// A reference to the internal date of the given vector.
/// </returns>
public static implicit operator float[](DenseVector vector)
public static explicit operator float[](DenseVector vector)
{
if (vector == null)
{
throw new ArgumentNullException();
}
return vector.Data;
return vector.Values;
}
/// <summary>
@ -178,10 +169,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>This vector as a column matrix.</returns>
public override Matrix<float> ToColumnMatrix()
{
var matrix = new DenseMatrix(Count, 1);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(_length, 1);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(i, 0, Data[i]);
matrix.At(i, 0, _values[i]);
}
return matrix;
@ -193,33 +184,15 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>This vector as a row matrix.</returns>
public override Matrix<float> ToRowMatrix()
{
var matrix = new DenseMatrix(1, Count);
for (var i = 0; i < Data.Length; i++)
var matrix = new DenseMatrix(1, _length);
for (var i = 0; i < _values.Length; i++)
{
matrix.At(0, i, Data[i]);
matrix.At(0, i, _values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override float this[int index]
{
get
{
return Data[index];
}
set
{
Data[index] = value;
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -253,49 +226,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new DenseVector(size);
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<float> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as DenseVector;
if (otherVector == null)
{
CommonParallel.For(
0,
Data.Length,
index => target[index] = Data[index]);
}
else
{
Buffer.BlockCopy(Data, 0, otherVector.Data, 0, Data.Length * Constants.SizeOfFloat);
}
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -312,8 +242,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] + scalar);
_values.Length,
index => dense._values[index] = _values[index] + scalar);
}
}
@ -328,7 +258,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, 1.0f, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, 1.0f, odense.Values, rdense.Values);
}
else
{
@ -397,8 +327,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] - scalar);
_values.Length,
index => dense._values[index] = _values[index] - scalar);
}
}
@ -413,7 +343,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var odense = other as DenseVector;
if (rdense != null && odense != null)
{
Control.LinearAlgebraProvider.AddVectorToScaledVector(Data, -1.0f, odense.Data, rdense.Data);
Control.LinearAlgebraProvider.AddVectorToScaledVector(_values, -1.0f, odense.Values, rdense.Values);
}
else
{
@ -472,11 +402,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<float> Negate()
{
var result = new DenseVector(Count);
var result = new DenseVector(_length);
CommonParallel.For(
0,
Data.Length,
index => result[index] = -Data[index]);
_values.Length,
index => result[index] = -_values[index]);
return result;
}
@ -496,7 +426,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
else
{
Control.LinearAlgebraProvider.ScaleArray(scalar, Data, denseResult.Data);
Control.LinearAlgebraProvider.ScaleArray(scalar, _values, denseResult.Values);
}
}
@ -510,7 +440,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
var denseVector = other as DenseVector;
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(Data, denseVector.Data);
return denseVector == null ? base.DoDotProduct(other) : Control.LinearAlgebraProvider.DotProduct(_values, denseVector.Values);
}
/// <summary>
@ -572,7 +502,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "rightSide");
}
return Control.LinearAlgebraProvider.DotProduct(leftSide.Data, rightSide.Data);
return Control.LinearAlgebraProvider.DotProduct(leftSide.Values, rightSide.Values);
}
/// <summary>
@ -602,16 +532,16 @@ namespace MathNet.Numerics.LinearAlgebra.Single
var denseResult = result as DenseVector;
if (denseResult == null)
{
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
result.At(index, Data[index] % divisor);
result.At(index, _values[index] % divisor);
}
}
else
{
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
denseResult.Data[index] = Data[index] % divisor;
denseResult._values[index] = _values[index] % divisor;
}
}
}
@ -640,10 +570,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override int AbsoluteMinimumIndex()
{
var index = 0;
var min = Math.Abs(Data[index]);
for (var i = 1; i < Count; i++)
var min = Math.Abs(_values[index]);
for (var i = 1; i < _length; i++)
{
var test = Math.Abs(Data[i]);
var test = Math.Abs(_values[i]);
if (test < min)
{
index = i;
@ -660,7 +590,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The value of the absolute minimum element.</returns>
public override float AbsoluteMinimum()
{
return Math.Abs(Data[AbsoluteMinimumIndex()]);
return Math.Abs(_values[AbsoluteMinimumIndex()]);
}
/// <summary>
@ -669,7 +599,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The value of the absolute maximum element.</returns>
public override float AbsoluteMaximum()
{
return Math.Abs(Data[AbsoluteMaximumIndex()]);
return Math.Abs(_values[AbsoluteMaximumIndex()]);
}
/// <summary>
@ -679,10 +609,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override int AbsoluteMaximumIndex()
{
var index = 0;
var max = Math.Abs(Data[index]);
for (var i = 1; i < Count; i++)
var max = Math.Abs(_values[index]);
for (var i = 1; i < _length; i++)
{
var test = Math.Abs(Data[i]);
var test = Math.Abs(_values[i]);
if (test > max)
{
index = i;
@ -706,7 +636,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <exception cref="ArgumentException">If <paramref name="length"/> is not positive.</exception>
public override Vector<float> SubVector(int index, int length)
{
if (index < 0 || index >= Count)
if (index < 0 || index >= _length)
{
throw new ArgumentOutOfRangeException("index");
}
@ -716,7 +646,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
throw new ArgumentOutOfRangeException("length");
}
if (index + length > Count)
if (index + length > _length)
{
throw new ArgumentOutOfRangeException("length");
}
@ -725,8 +655,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
CommonParallel.For(
index,
index + length,
i => result.Data[i - index] = Data[i]);
index + length,
i => result._values[i - index] = _values[i]);
return result;
}
@ -743,7 +673,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
throw new ArgumentNullException("values");
}
if (values.Length != Count)
if (values.Length != _length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "values");
}
@ -751,7 +681,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
CommonParallel.For(
0,
values.Length,
i => Data[i] = values[i]);
i => _values[i] = values[i]);
}
/// <summary>
@ -761,13 +691,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override int MaximumIndex()
{
var index = 0;
var max = Data[0];
for (var i = 1; i < Count; i++)
var max = _values[0];
for (var i = 1; i < _length; i++)
{
if (max < Data[i])
if (max < _values[i])
{
index = i;
max = Data[i];
max = _values[i];
}
}
@ -781,13 +711,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override int MinimumIndex()
{
var index = 0;
var min = Data[0];
for (var i = 1; i < Count; i++)
var min = _values[0];
for (var i = 1; i < _length; i++)
{
if (min > Data[i])
if (min > _values[i])
{
index = i;
min = Data[i];
min = _values[i];
}
}
@ -802,9 +732,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
var sum = 0.0f;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Data[i];
sum += _values[i];
}
return sum;
@ -818,9 +748,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
var sum = 0.0f;
for (var i = 0; i < Count; i++)
for (var i = 0; i < _length; i++)
{
sum += Math.Abs(Data[i]);
sum += Math.Abs(_values[i]);
}
return sum;
@ -842,8 +772,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] * other[index]);
_values.Length,
index => dense._values[index] = _values[index] * other[index]);
}
}
@ -864,8 +794,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
CommonParallel.For(
0,
Data.Length,
index => dense.Data[index] = Data[index] / other[index]);
_values.Length,
index => dense._values[index] = _values[index] / other[index]);
}
}
@ -897,7 +827,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
for (var j = 0; j < v.Count; j++)
{
matrix.At(i, j, u.Data[i] * v.Data[j]);
matrix.At(i, j, u._values[i] * v._values[j]);
}
});
return matrix;
@ -937,19 +867,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single
if (2.0 == p)
{
return Data.Aggregate(0f, SpecialFunctions.Hypotenuse);
return _values.Aggregate(0f, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(Data, (i, v) => Math.Abs(v), Math.Max, 0f);
return CommonParallel.Aggregate(_values, (i, v) => Math.Abs(v), Math.Max, 0f);
}
var sum = 0.0;
for (var index = 0; index < Count; index++)
for (var index = 0; index < _length; index++)
{
sum += Math.Pow(Math.Abs(Data[index]), p);
sum += Math.Pow(Math.Abs(_values[index]), p);
}
return (float)Math.Pow(sum, 1.0 / p);
@ -1115,29 +1045,5 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
#endregion
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
Array.Clear(Data, 0, Data.Length);
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
internal protected override float At(int index)
{
return Data[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
internal protected override void At(int index, float value)
{
Data[index] = value;
}
}
}

4
src/Numerics/LinearAlgebra/Single/DiagonalMatrix.cs

@ -377,12 +377,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return;
}
if (_data.Length != denseSource.Data.Length)
if (_data.Length != denseSource.Values.Length)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "source");
}
Buffer.BlockCopy(denseSource.Data, 0, _data, 0, denseSource.Data.Length * Constants.SizeOfFloat);
Buffer.BlockCopy(denseSource.Values, 0, _data, 0, denseSource.Values.Length * Constants.SizeOfFloat);
}
/// <summary>

4
src/Numerics/LinearAlgebra/Single/Factorization/DenseCholesky.cs

@ -167,11 +167,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfFloat);
// Cholesky solve by overwriting result.
var dfactor = (DenseMatrix)CholeskyFactor;
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Data, 1);
Control.LinearAlgebraProvider.CholeskySolveFactored(dfactor.Data, dfactor.RowCount, dresult.Values, 1);
}
}
}

2
src/Numerics/LinearAlgebra/Single/Factorization/DenseGramSchmidt.cs

@ -216,7 +216,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do GramSchmidt factorization for dense vectors at the moment.");
}
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Data, 1, dresult.Data);
_provider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixQ.RowCount, MatrixQ.ColumnCount, null, dinput.Values, 1, dresult.Values);
}
}
}

4
src/Numerics/LinearAlgebra/Single/Factorization/DenseLU.cs

@ -168,11 +168,11 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
}
// Copy the contents of input to result.
Buffer.BlockCopy(dinput.Data, 0, dresult.Data, 0, dinput.Data.Length * Constants.SizeOfFloat);
Buffer.BlockCopy(dinput.Values, 0, dresult.Values, 0, dinput.Values.Length * Constants.SizeOfFloat);
// LU solve by overwriting result.
var dfactors = (DenseMatrix)Factors;
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Data);
Control.LinearAlgebraProvider.LUSolveFactored(1, dfactors.Data, dfactors.RowCount, Pivots, dresult.Values);
}
/// <summary>

2
src/Numerics/LinearAlgebra/Single/Factorization/DenseQR.cs

@ -187,7 +187,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do QR factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.QRSolveFactored(((DenseMatrix)MatrixQ).Data, ((DenseMatrix)MatrixR).Data, MatrixR.RowCount, MatrixR.ColumnCount, Tau, dinput.Values, 1, dresult.Values);
}
}
}

6
src/Numerics/LinearAlgebra/Single/Factorization/DenseSvd.cs

@ -69,7 +69,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
VectorS = new DenseVector(nm);
MatrixU = new DenseMatrix(matrix.RowCount);
MatrixVT = new DenseMatrix(matrix.ColumnCount);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
Control.LinearAlgebraProvider.SingularValueDecomposition(computeVectors, ((DenseMatrix)matrix.Clone()).Data, matrix.RowCount, matrix.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data);
}
/// <summary>
@ -125,7 +125,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense matrices at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, input.ColumnCount, dresult.Data);
}
/// <summary>
@ -175,7 +175,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single.Factorization
throw new NotSupportedException("Can only do SVD factorization for dense vectors at the moment.");
}
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Data, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Data, 1, dresult.Data);
Control.LinearAlgebraProvider.SvdSolveFactored(MatrixU.RowCount, MatrixVT.ColumnCount, ((DenseVector)VectorS).Values, ((DenseMatrix)MatrixU).Data, ((DenseMatrix)MatrixVT).Data, dinput.Values, 1, dresult.Values);
}
}
}

1
src/Numerics/LinearAlgebra/Single/SparseMatrix.cs

@ -97,6 +97,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// The number of columns.
/// </param>
/// <param name="value">The value which we assign to each element of the matrix.</param>
[Obsolete("Use a dense matrix instead.")]
public SparseMatrix(int rows, int columns, float value)
: this(rows, columns)
{

503
src/Numerics/LinearAlgebra/Single/SparseVector.cs

@ -37,6 +37,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
using Generic;
using NumberTheory;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -46,24 +47,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single
[Serializable]
public class SparseVector : Vector
{
/// <summary>
/// Gets the vector's internal data. The array containing the actual values; only the non-zero values are stored.
/// </summary>
private float[] _nonZeroValues = new float[0];
readonly SparseVectorStorage<float> _storage;
/// <summary>
/// The indices of the non-zero entries.
/// </summary>
private int[] _nonZeroIndices = new int[0];
/// <summary>
/// Gets the number of non zero elements in the vector.
/// </summary>
/// <value>The number of non zero elements.</value>
public int NonZerosCount
internal SparseVector(SparseVectorStorage<float> storage)
: base(storage)
{
get;
private set;
_storage = storage;
}
#region Constructors
@ -77,7 +66,8 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size) : base(size)
public SparseVector(int size)
: this(new SparseVectorStorage<float>(size))
{
}
@ -94,55 +84,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
public SparseVector(int size, float value) : this(size)
[Obsolete("Use a dense vector instead.")]
public SparseVector(int size, float value)
: this(new SparseVectorStorage<float>(size))
{
if (value == 0.0)
{
// Skip adding values
return;
}
// We already know that this vector is "full", let's allocate all needed memory
_nonZeroValues = new float[size];
_nonZeroIndices = new int[size];
NonZerosCount = size;
var valueCount = _storage.ValueCount = size;
var indices = _storage.Indices = new int[valueCount];
var values = _storage.Values = new float[valueCount];
CommonParallel.For(
0,
Count,
index =>
{
_nonZeroValues[index] = value;
_nonZeroIndices[index] = index;
});
}
/// <summary>
/// Initializes a new instance of the <see cref="SparseVector"/> class by
/// copying the values from another.
/// </summary>
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(Vector<float> other) : this(other.Count)
{
var vector = other as SparseVector;
if (vector == null)
for (int i = 0; i < values.Length; i++)
{
for (var i = 0; i < other.Count; i++)
{
this[i] = other.At(i);
}
}
else
{
_nonZeroValues = new float[vector.NonZerosCount];
_nonZeroIndices = new int[vector.NonZerosCount];
NonZerosCount = vector.NonZerosCount;
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
Buffer.BlockCopy(vector._nonZeroValues, 0, _nonZeroValues, 0, vector.NonZerosCount * Constants.SizeOfFloat);
Buffer.BlockCopy(vector._nonZeroIndices, 0, _nonZeroIndices, 0, vector.NonZerosCount * Constants.SizeOfInt);
values[i] = value;
indices[i] = i;
}
}
@ -153,15 +111,10 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="other">
/// The vector to create the new vector from.
/// </param>
public SparseVector(SparseVector other) : this(other.Count)
public SparseVector(Vector<float> other)
: this(new SparseVectorStorage<float>(other.Count))
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
_nonZeroValues = new float[other.NonZerosCount];
_nonZeroIndices = new int[other.NonZerosCount];
NonZerosCount = other.NonZerosCount;
Buffer.BlockCopy(other._nonZeroValues, 0, _nonZeroValues, 0, other.NonZerosCount * Constants.SizeOfFloat);
Buffer.BlockCopy(other._nonZeroIndices, 0, _nonZeroIndices, 0, other.NonZerosCount * Constants.SizeOfInt);
other.Storage.CopyTo(Storage, skipClearing: true);
}
/// <summary>
@ -169,11 +122,12 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </summary>
/// <param name="array">The array to create this vector from.</param>
/// <remarks>The vector copy the array. Any changes to the vector will NOT change the array.</remarks>
public SparseVector(IList<float> array) : this(array.Count)
public SparseVector(IList<float> array)
: this(new SparseVectorStorage<float>(array.Count))
{
for (var i = 0; i < array.Count; i++)
{
this[i] = array[i];
Storage.At(i, array[i]);
}
}
@ -186,9 +140,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override Matrix<float> ToColumnMatrix()
{
var matrix = new SparseMatrix(Count, 1);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(_nonZeroIndices[i], 0, _nonZeroValues[i]);
matrix.At(_storage.Indices[i], 0, _storage.Values[i]);
}
return matrix;
@ -201,44 +155,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override Matrix<float> ToRowMatrix()
{
var matrix = new SparseMatrix(1, Count);
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
matrix.At(0, _nonZeroIndices[i], _nonZeroValues[i]);
matrix.At(0, _storage.Indices[i], _storage.Values[i]);
}
return matrix;
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
/// <exception cref="IndexOutOfRangeException">If <paramref name="index"/> is negative or
/// greater than the size of the vector.</exception>
public override float this[int index]
{
get
{
// If index is out of bounds
if ((index < 0) || (index >= Count))
{
throw new IndexOutOfRangeException();
}
return At(index);
}
set
{
// If index is out of bounds
if ((index < 0) || (index >= Count))
{
throw new IndexOutOfRangeException();
}
At(index, value);
}
}
/// <summary>
/// Creates a matrix with the given dimensions using the same storage type
/// as this vector.
@ -272,68 +196,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return new SparseVector(size);
}
/// <summary>
/// Resets all values to zero.
/// </summary>
public override void Clear()
{
NonZerosCount = 0;
}
/// <summary>
/// Copies the values of this vector into the target vector.
/// </summary>
/// <param name="target">
/// The vector to copy elements into.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="target"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// If <paramref name="target"/> is not the same size as this vector.
/// </exception>
public override void CopyTo(Vector<float> target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
if (Count != target.Count)
{
throw new ArgumentException(Resources.ArgumentVectorsSameLength, "target");
}
if (ReferenceEquals(this, target))
{
return;
}
var otherVector = target as SparseVector;
if (otherVector == null)
{
target.Clear();
for (var index = 0; index < NonZerosCount; index++)
{
target.At(_nonZeroIndices[index], _nonZeroValues[index]);
}
}
else
{
// Lets copy only needed data. Portion of needed data is determined by NonZerosCount value
otherVector._nonZeroValues = new float[NonZerosCount];
otherVector._nonZeroIndices = new int[NonZerosCount];
otherVector.NonZerosCount = NonZerosCount;
if (NonZerosCount != 0)
{
Buffer.BlockCopy(_nonZeroValues, 0, otherVector._nonZeroValues, 0, NonZerosCount*Constants.SizeOfFloat);
Buffer.BlockCopy(_nonZeroIndices, 0, otherVector._nonZeroIndices, 0, NonZerosCount*Constants.SizeOfInt);
}
}
}
#region Operators and supplementary functions
/// <summary>
@ -371,15 +233,15 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
//populate the non zero values from this
for (int j = 0; j < NonZerosCount; j++)
for (int j = 0; j < _storage.ValueCount; j++)
{
vnonZeroValues[_nonZeroIndices[j]] = _nonZeroValues[j] + scalar;
vnonZeroValues[_storage.Indices[j]] = _storage.Values[j] + scalar;
}
//assign this vectors arrary to the new arrays.
_nonZeroValues = vnonZeroValues;
_nonZeroIndices = vnonZeroIndices;
NonZerosCount = Count;
_storage.Values = vnonZeroValues;
_storage.Indices = vnonZeroIndices;
_storage.ValueCount = Count;
}
else
@ -421,22 +283,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] += otherSparse._nonZeroValues[j++];
_storage.Values[i++] += otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != 0.0)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], otherValue);
}
j++;
}
@ -446,25 +308,25 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] + otherSparse.At(next));
result.At(next, _storage.Values[i] + otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) + otherSparse._nonZeroValues[j]);
result.At(next, At(next) + otherSparse._storage.Values[j]);
}
j++;
}
@ -567,22 +429,22 @@ namespace MathNet.Numerics.LinearAlgebra.Single
if (ReferenceEquals(this, resultSparse))
{
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (i < NonZerosCount && j < otherSparse.NonZerosCount && _nonZeroIndices[i] == otherSparse._nonZeroIndices[j])
if (i < _storage.ValueCount && j < otherSparse._storage.ValueCount && _storage.Indices[i] == otherSparse._storage.Indices[j])
{
_nonZeroValues[i++] -= otherSparse._nonZeroValues[j++];
_storage.Values[i++] -= otherSparse._storage.Values[j++];
}
else if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
else if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
i++;
}
else
{
var otherValue = otherSparse._nonZeroValues[j];
var otherValue = otherSparse._storage.Values[j];
if (otherValue != 0.0)
{
InsertAtUnchecked(i++, otherSparse._nonZeroIndices[j], -otherValue);
InsertAtUnchecked(i++, otherSparse._storage.Indices[j], -otherValue);
}
j++;
}
@ -592,25 +454,25 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
result.Clear();
int i = 0, j = 0, last = -1;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] <= otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] <= otherSparse._storage.Indices[j])
{
var next = _nonZeroIndices[i];
var next = _storage.Indices[i];
if (next != last)
{
last = next;
result.At(next, _nonZeroValues[i] - otherSparse.At(next));
result.At(next, _storage.Values[i] - otherSparse.At(next));
}
i++;
}
else
{
var next = otherSparse._nonZeroIndices[j];
var next = otherSparse._storage.Indices[j];
if (next != last)
{
last = next;
result.At(next, At(next) - otherSparse._nonZeroValues[j]);
result.At(next, At(next) - otherSparse._storage.Values[j]);
}
j++;
}
@ -669,23 +531,18 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <remarks>Added as an alternative to the unary negation operator.</remarks>
public override Vector<float> Negate()
{
var result = new SparseVector(Count)
{
_nonZeroValues = new float[NonZerosCount],
_nonZeroIndices = new int[NonZerosCount],
NonZerosCount = NonZerosCount
};
var result = new SparseVectorStorage<float>(Count);
var valueCount = result.ValueCount = _storage.ValueCount;
var indices = result.Indices = new int[valueCount];
var values = result.Values = new float[valueCount];
if (NonZerosCount != 0)
if (valueCount != 0)
{
CommonParallel.For(
0,
NonZerosCount,
index => result._nonZeroValues[index] = -_nonZeroValues[index]);
Buffer.BlockCopy(_nonZeroIndices, 0, result._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
CommonParallel.For(0, valueCount, index => values[index] = -_storage.Values[index]);
Buffer.BlockCopy(_storage.Indices, 0, indices, 0, valueCount * Constants.SizeOfInt);
}
return result;
return new SparseVector(result);
}
/// <summary>
@ -706,7 +563,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
var copy = new SparseVector(this);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._nonZeroValues, copy._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, copy._storage.Values, copy._storage.Values);
return copy;
}
@ -741,23 +598,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single
if (sparseResult == null)
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], scalar * _nonZeroValues[index]);
result.At(_storage.Indices[index], scalar * _storage.Values[index]);
}
}
else
{
if (!ReferenceEquals(this, result))
{
sparseResult.NonZerosCount = NonZerosCount;
sparseResult._nonZeroIndices = new int[NonZerosCount];
Buffer.BlockCopy(_nonZeroIndices, 0, sparseResult._nonZeroIndices, 0, NonZerosCount * Constants.SizeOfInt);
sparseResult._nonZeroValues = new float[NonZerosCount];
Buffer.BlockCopy(_nonZeroValues, 0, sparseResult._nonZeroValues, 0, NonZerosCount * Constants.SizeOfFloat);
sparseResult._storage.ValueCount = _storage.ValueCount;
sparseResult._storage.Indices = new int[_storage.ValueCount];
Buffer.BlockCopy(_storage.Indices, 0, sparseResult._storage.Indices, 0, _storage.ValueCount * Constants.SizeOfInt);
sparseResult._storage.Values = new float[_storage.ValueCount];
Buffer.BlockCopy(_storage.Values, 0, sparseResult._storage.Values, 0, _storage.ValueCount * Constants.SizeOfFloat);
}
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._nonZeroValues, sparseResult._nonZeroValues);
Control.LinearAlgebraProvider.ScaleArray(scalar, sparseResult._storage.Values, sparseResult._storage.Values);
}
}
@ -776,16 +633,16 @@ namespace MathNet.Numerics.LinearAlgebra.Single
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * _nonZeroValues[i];
result += _storage.Values[i] * _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i] * other.At(_nonZeroIndices[i]);
result += _storage.Values[i] * other.At(_storage.Indices[i]);
}
}
@ -880,17 +737,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
if (ReferenceEquals(this, result))
{
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
_nonZeroValues[index] %= divisor;
_storage.Values[index] %= divisor;
}
}
else
{
result.Clear();
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
result.At(_nonZeroIndices[index], _nonZeroValues[index] % divisor);
result.At(_storage.Indices[index], _storage.Values[index] % divisor);
}
}
}
@ -918,17 +775,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The index of absolute minimum element.</returns>
public override int AbsoluteMinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
// No non-zero elements. Return 0
return 0;
}
var index = 0;
var min = Math.Abs(_nonZeroValues[index]);
for (var i = 1; i < NonZerosCount; i++)
var min = Math.Abs(_storage.Values[index]);
for (var i = 1; i < _storage.ValueCount; i++)
{
var test = Math.Abs(_nonZeroValues[i]);
var test = Math.Abs(_storage.Values[i]);
if (test < min)
{
index = i;
@ -936,7 +793,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1006,23 +863,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The index of absolute maximum element.</returns>
public override int MaximumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0;
}
var index = 0;
var max = _nonZeroValues[0];
for (var i = 1; i < NonZerosCount; i++)
var max = _storage.Values[0];
for (var i = 1; i < _storage.ValueCount; i++)
{
if (max < _nonZeroValues[i])
if (max < _storage.Values[i])
{
index = i;
max = _nonZeroValues[i];
max = _storage.Values[i];
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1031,23 +888,23 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <returns>The index of minimum element.</returns>
public override int MinimumIndex()
{
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0;
}
var index = 0;
var min = _nonZeroValues[0];
for (var i = 1; i < NonZerosCount; i++)
var min = _storage.Values[0];
for (var i = 1; i < _storage.ValueCount; i++)
{
if (min > _nonZeroValues[i])
if (min > _storage.Values[i])
{
index = i;
min = _nonZeroValues[i];
min = _storage.Values[i];
}
}
return _nonZeroIndices[index];
return _storage.Indices[index];
}
/// <summary>
@ -1057,9 +914,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override float Sum()
{
var result = 0.0f;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += _nonZeroValues[i];
result += _storage.Values[i];
}
return result;
@ -1072,9 +929,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override float SumMagnitudes()
{
var result = 0.0f;
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
result += Math.Abs(_nonZeroValues[i]);
result += Math.Abs(_storage.Values[i]);
}
return result;
@ -1089,17 +946,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] *= _nonZeroValues[i];
_storage.Values[i] *= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, other.At(index) * _nonZeroValues[i]);
var index = _storage.Indices[i];
result.At(index, other.At(index) * _storage.Values[i]);
}
}
}
@ -1113,17 +970,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
if (ReferenceEquals(this, other))
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
_nonZeroValues[i] /= _nonZeroValues[i];
_storage.Values[i] /= _storage.Values[i];
}
}
else
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
var index = _nonZeroIndices[i];
result.At(index, _nonZeroValues[i] / other.At(index));
var index = _storage.Indices[i];
result.At(index, _storage.Values[i] / other.At(index));
}
}
}
@ -1149,13 +1006,13 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
var matrix = new SparseMatrix(u.Count, v.Count);
for (var i = 0; i < u.NonZerosCount; i++)
for (var i = 0; i < u._storage.ValueCount; i++)
{
for (var j = 0; j < v.NonZerosCount; j++)
for (var j = 0; j < v._storage.ValueCount; j++)
{
if (u._nonZeroIndices[i] == v._nonZeroIndices[j])
if (u._storage.Indices[i] == v._storage.Indices[j])
{
matrix.At(i, j, u._nonZeroValues[i] * v._nonZeroValues[j]);
matrix.At(i, j, u._storage.Values[i] * v._storage.Values[j]);
}
}
}
@ -1191,25 +1048,25 @@ namespace MathNet.Numerics.LinearAlgebra.Single
throw new ArgumentOutOfRangeException("p");
}
if (NonZerosCount == 0)
if (_storage.ValueCount == 0)
{
return 0.0f;
}
if (2.0 == p)
{
return _nonZeroValues.Aggregate(0f, SpecialFunctions.Hypotenuse);
return _storage.Values.Aggregate(0f, SpecialFunctions.Hypotenuse);
}
if (Double.IsPositiveInfinity(p))
{
return CommonParallel.Aggregate(0, NonZerosCount, i => Math.Abs(_nonZeroValues[i]), Math.Max, 0f);
return CommonParallel.Aggregate(0, _storage.ValueCount, i => Math.Abs(_storage.Values[i]), Math.Max, 0f);
}
var sum = 0.0;
for (var index = 0; index < NonZerosCount; index++)
for (var index = 0; index < _storage.ValueCount; index++)
{
sum += Math.Pow(Math.Abs(_nonZeroValues[index]), p);
sum += Math.Pow(Math.Abs(_storage.Values[index]), p);
}
return (float)Math.Pow(sum, 1.0 / p);
@ -1376,97 +1233,33 @@ namespace MathNet.Numerics.LinearAlgebra.Single
#endregion
/// <summary>
/// Gets the value at the given index.
/// </summary>
/// <param name="index">Value real index in array</param>
/// <returns>The value at the given index.</returns>
internal protected override float At(int index)
{
// Search if item idex exists in NonZeroIndices array in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
return itemIndex >= 0 ? _nonZeroValues[itemIndex] : 0.0f;
}
/// <summary>
/// Delete, Add or Update the value in NonZeroValues and NonZeroIndices
/// </summary>
/// <param name="index">Value real index in array</param>
/// <param name="value">The value to set.</param>
/// <remarks>This method assume that index is between 0 and Array Size</remarks>
internal protected override void At(int index, float value)
{
// Search if "index" already exists in range "0 - real nonzero values count"
var itemIndex = Array.BinarySearch(_nonZeroIndices, 0, NonZerosCount, index);
if (itemIndex >= 0)
{
// Item already exist at itemIndex
if (value == 0.0)
{
RemoveAtUnchecked(itemIndex);
}
else
{
_nonZeroValues[itemIndex] = value;
}
}
else
{
if (value != 0.0)
{
InsertAtUnchecked(~itemIndex, index, value);
}
}
}
private void InsertAtUnchecked(int itemIndex, int index, float value)
{
// Check if the storage needs to be increased
if ((NonZerosCount == _nonZeroValues.Length) && (NonZerosCount < Count))
if ((_storage.ValueCount == _storage.Values.Length) && (_storage.ValueCount < Count))
{
// Value and Indices arrays are completely full so we increase the size
var size = Math.Min(_nonZeroValues.Length + GrowthSize(), Count);
Array.Resize(ref _nonZeroValues, size);
Array.Resize(ref _nonZeroIndices, size);
var size = Math.Min(_storage.Values.Length + GrowthSize(), Count);
Array.Resize(ref _storage.Values, size);
Array.Resize(ref _storage.Indices, size);
}
// Move all values (with a position larger than index) in the value array
// to the next position
// Move all values (with a position larger than index) in the columIndices
// array to the next position
for (var i = NonZerosCount - 1; i > itemIndex - 1; i--)
for (var i = _storage.ValueCount - 1; i > itemIndex - 1; i--)
{
_nonZeroValues[i + 1] = _nonZeroValues[i];
_nonZeroIndices[i + 1] = _nonZeroIndices[i];
_storage.Values[i + 1] = _storage.Values[i];
_storage.Indices[i + 1] = _storage.Indices[i];
}
// Add the value and the column index
_nonZeroValues[itemIndex] = value;
_nonZeroIndices[itemIndex] = index;
_storage.Values[itemIndex] = value;
_storage.Indices[itemIndex] = index;
// increase the number of non-zero numbers by one
NonZerosCount += 1;
}
private void RemoveAtUnchecked(int itemIndex)
{
// Value is zero. Let's delete it from Values and Indices array
for (var i = itemIndex + 1; i < NonZerosCount; i++)
{
_nonZeroValues[i - 1] = _nonZeroValues[i];
_nonZeroIndices[i - 1] = _nonZeroIndices[i];
}
NonZerosCount -= 1;
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((NonZerosCount > 1024) && (NonZerosCount < _nonZeroIndices.Length / 2))
{
Array.Resize(ref _nonZeroValues, NonZerosCount);
Array.Resize(ref _nonZeroIndices, NonZerosCount);
}
_storage.ValueCount += 1;
}
/// <summary>
@ -1477,19 +1270,19 @@ namespace MathNet.Numerics.LinearAlgebra.Single
private int GrowthSize()
{
int delta;
if (_nonZeroValues.Length > 1024)
if (_storage.Values.Length > 1024)
{
delta = _nonZeroValues.Length / 4;
delta = _storage.Values.Length / 4;
}
else
{
if (_nonZeroValues.Length > 256)
if (_storage.Values.Length > 256)
{
delta = 512;
}
else
{
delta = _nonZeroValues.Length > 64 ? 128 : 32;
delta = _storage.Values.Length > 64 ? 128 : 32;
}
}
@ -1502,7 +1295,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
if (Count > 20)
{
return String.Format("SparseVectorOfSingle({0},{1},{2})", Count, NonZerosCount, GetHashCode());
return String.Format("SparseVectorOfSingle({0},{1},{2})", Count, _storage.ValueCount, GetHashCode());
}
return base.ToString(format, formatProvider);
@ -1516,14 +1309,14 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </returns>
public override int GetHashCode()
{
var hashNum = Math.Min(NonZerosCount, 20);
var hashNum = Math.Min(_storage.ValueCount, 20);
long hash = 0;
for (var i = 0; i < hashNum; i++)
{
#if PORTABLE
hash ^= Precision.DoubleToInt64Bits(this._nonZeroValues[i].GetHashCode());
hash ^= Precision.DoubleToInt64Bits(this._storage.Values[i].GetHashCode());
#else
hash ^= BitConverter.DoubleToInt64Bits(_nonZeroValues[i].GetHashCode());
hash ^= BitConverter.DoubleToInt64Bits(_storage.Values[i].GetHashCode());
#endif
}
@ -1567,27 +1360,27 @@ namespace MathNet.Numerics.LinearAlgebra.Single
}
int i = 0, j = 0;
while (i < NonZerosCount || j < otherSparse.NonZerosCount)
while (i < _storage.ValueCount || j < otherSparse._storage.ValueCount)
{
if (j >= otherSparse.NonZerosCount || i < NonZerosCount && _nonZeroIndices[i] < otherSparse._nonZeroIndices[j])
if (j >= otherSparse._storage.ValueCount || i < _storage.ValueCount && _storage.Indices[i] < otherSparse._storage.Indices[j])
{
if (_nonZeroValues[i++] != 0f)
if (_storage.Values[i++] != 0f)
{
return false;
}
continue;
}
if (i >= NonZerosCount || j < otherSparse.NonZerosCount && otherSparse._nonZeroIndices[j] < _nonZeroIndices[i])
if (i >= _storage.ValueCount || j < otherSparse._storage.ValueCount && otherSparse._storage.Indices[j] < _storage.Indices[i])
{
if (otherSparse._nonZeroValues[j++] != 0f)
if (otherSparse._storage.Values[j++] != 0f)
{
return false;
}
continue;
}
if (!_nonZeroValues[i].AlmostEqual(otherSparse._nonZeroValues[j]))
if (!_storage.Values[i].AlmostEqual(otherSparse._storage.Values[j]))
{
return false;
}
@ -1615,9 +1408,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </remarks>
public override IEnumerable<Tuple<int, float>> GetIndexedEnumerator()
{
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
yield return new Tuple<int, float>(_nonZeroIndices[i], _nonZeroValues[i]);
yield return new Tuple<int, float>(_storage.Indices[i], _storage.Values[i]);
}
}
@ -1630,9 +1423,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
public override float[] ToArray()
{
var ret = new float[Count];
for (var i = 0; i < NonZerosCount; i++)
for (var i = 0; i < _storage.ValueCount; i++)
{
ret[_nonZeroIndices[i]] = _nonZeroValues[i];
ret[_storage.Indices[i]] = _storage.Values[i];
}
return ret;

12
src/Numerics/LinearAlgebra/Single/Vector.cs

@ -30,6 +30,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
using Distributions;
using Generic;
using Properties;
using Storage;
using Threading;
/// <summary>
@ -40,16 +41,9 @@ namespace MathNet.Numerics.LinearAlgebra.Single
{
/// <summary>
/// Initializes a new instance of the Vector class.
/// Constructs a <strong>Vector</strong> with the given size.
/// </summary>
/// <param name="size">
/// The size of the <strong>Vector</strong> to construct.
/// </param>
/// <exception cref="ArgumentException">
/// If <paramref name="size"/> is less than one.
/// </exception>
protected Vector(int size)
: base(size)
protected Vector(VectorStorage<float> storage)
: base(storage)
{
}

8
src/Numerics/LinearAlgebra/Storage/DenseVectorStorage.cs

@ -90,7 +90,6 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
throw new ArgumentException(message, "target");
}
//Buffer.BlockCopy(Data, 0, target.Data, 0, Data.Length * System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)));
Array.Copy(Data, 0, target.Data, 0, Data.Length);
}
@ -113,14 +112,7 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
void CopySubVectorTo(DenseVectorStorage<T> target,
int sourceIndex, int targetIndex, int count)
{
if (ReferenceEquals(this, target))
{
throw new NotSupportedException();
}
ValidateSubVectorRange(target, sourceIndex, targetIndex, count);
//Buffer.BlockCopy(Data, sourceIndex, target.Data, targetIndex, count * System.Runtime.InteropServices.Marshal.SizeOf(typeof(T)));
Array.Copy(Data, sourceIndex, target.Data, targetIndex, count);
}
}

333
src/Numerics/LinearAlgebra/Storage/SparseVectorStorage.cs

@ -0,0 +1,333 @@
using System;
using MathNet.Numerics.Properties;
namespace MathNet.Numerics.LinearAlgebra.Storage
{
[Serializable]
public class SparseVectorStorage<T> : VectorStorage<T>
where T : struct, IEquatable<T>, IFormattable
{
// [ruegg] public fields are OK here
readonly T _zero;
/// <summary>
/// Array that contains the indices of the non-zero values.
/// </summary>
public int[] Indices;
/// <summary>
/// Array that contains the non-zero elements of the vector.
/// </summary>
public T[] Values;
/// <summary>
/// Gets the number of non-zero elements in the vector.
/// </summary>
public int ValueCount;
internal SparseVectorStorage(int length, T zero = default(T))
: base(length)
{
_zero = zero;
Indices = new int[0];
Values = new T[0];
ValueCount = 0;
}
/// <summary>
/// Retrieves the requested element without range checking.
/// </summary>
public override T At(int index)
{
// Search if item idex exists in NonZeroIndices array in range "0 - nonzero values count"
var itemIndex = Array.BinarySearch(Indices, 0, ValueCount, index);
return itemIndex >= 0 ? Values[itemIndex] : _zero;
}
/// <summary>
/// Sets the element without range checking.
/// </summary>
public override void At(int index, T value)
{
// Search if "index" already exists in range "0 - nonzero values count"
var itemIndex = Array.BinarySearch(Indices, 0, ValueCount, index);
if (itemIndex >= 0)
{
// Non-zero item found in matrix
if (_zero.Equals(value))
{
// Delete existing item
RemoveAtIndexUnchecked(itemIndex);
}
else
{
// Update item
Values[itemIndex] = value;
}
}
else
{
// Item not found. Add new value
if (!_zero.Equals(value))
{
InsertAtIndexUnchecked(~itemIndex, index, value);
}
}
}
void InsertAtIndexUnchecked(int itemIndex, int index, T value)
{
// Check if the storage needs to be increased
if ((ValueCount == Values.Length) && (ValueCount < Length))
{
// Value and Indices arrays are completely full so we increase the size
var size = Math.Min(Values.Length + GrowthSize(), Length);
Array.Resize(ref Values, size);
Array.Resize(ref Indices, size);
}
// Move all values (with a position larger than index) in the value array to the next position
// Move all values (with a position larger than index) in the columIndices array to the next position
Array.Copy(Values, itemIndex, Values, itemIndex + 1, ValueCount - itemIndex);
Array.Copy(Indices, itemIndex, Indices, itemIndex + 1, ValueCount - itemIndex);
// Add the value and the column index
Values[itemIndex] = value;
Indices[itemIndex] = index;
// increase the number of non-zero numbers by one
ValueCount += 1;
}
void RemoveAtIndexUnchecked(int itemIndex)
{
// Value is zero. Let's delete it from Values and Indices array
Array.Copy(Values, itemIndex + 1, Values, itemIndex, ValueCount - itemIndex - 1);
Array.Copy(Indices, itemIndex + 1, Indices, itemIndex, ValueCount - itemIndex - 1);
ValueCount -= 1;
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((ValueCount > 1024) && (ValueCount < Indices.Length / 2))
{
Array.Resize(ref Values, ValueCount);
Array.Resize(ref Indices, ValueCount);
}
}
/// <summary>
/// Calculates the amount with which to grow the storage array's if they need to be
/// increased in size.
/// </summary>
/// <returns>The amount grown.</returns>
int GrowthSize()
{
int delta;
if (Values.Length > 1024)
{
delta = Values.Length / 4;
}
else
{
if (Values.Length > 256)
{
delta = 512;
}
else
{
delta = Values.Length > 64 ? 128 : 32;
}
}
return delta;
}
public override void Clear()
{
ValueCount = 0;
}
public override void Clear(int index, int count)
{
if (index == 0 && count == Length)
{
Clear();
return;
}
var first = Array.BinarySearch(Indices, 0, ValueCount, index);
var last = Array.BinarySearch(Indices, 0, ValueCount, index + count - 1);
if (first < 0) first = ~first;
if (last < 0) last = ~last - 1;
int itemCount = last - first + 1;
if (itemCount > 0)
{
Array.Copy(Values, first + count, Values, first, ValueCount - first - count);
Array.Copy(Indices, first + count, Indices, first, ValueCount - first - count);
ValueCount -= count;
}
// Check whether we need to shrink the arrays. This is reasonable to do if
// there are a lot of non-zero elements and storage is two times bigger
if ((ValueCount > 1024) && (ValueCount < Indices.Length / 2))
{
Array.Resize(ref Values, ValueCount);
Array.Resize(ref Indices, ValueCount);
}
}
/// <remarks>Parameters assumed to be validated already.</remarks>
public override void CopyTo(VectorStorage<T> target, bool skipClearing = false)
{
var sparseTarget = target as SparseVectorStorage<T>;
if (sparseTarget != null)
{
CopyTo(sparseTarget);
return;
}
// FALL BACK
if (!skipClearing)
{
target.Clear();
}
if (ValueCount != 0)
{
for (int i = 0; i < ValueCount; i++)
{
target.At(Indices[i], Values[i]);
}
}
}
void CopyTo(SparseVectorStorage<T> target)
{
if (ReferenceEquals(this, target))
{
return;
}
if (Length != target.Length)
{
var message = string.Format(Resources.ArgumentMatrixDimensions2, Length, target.Length);
throw new ArgumentException(message, "target");
}
target.ValueCount = ValueCount;
target.Values = new T[ValueCount];
target.Indices = new int[ValueCount];
if (ValueCount != 0)
{
Array.Copy(Values, target.Values, ValueCount);
Buffer.BlockCopy(Indices, 0, target.Indices, 0, ValueCount * Constants.SizeOfInt);
}
}
public override void CopySubVectorTo(VectorStorage<T> target,
int sourceIndex, int targetIndex, int count,
bool skipClearing = false)
{
ValidateSubVectorRange(target, sourceIndex, targetIndex, count);
var sparseTarget = target as SparseVectorStorage<T>;
if (sparseTarget != null)
{
CopySubVectorTo(sparseTarget, sourceIndex, targetIndex, count, skipClearing);
return;
}
// FALL BACK
var offset = targetIndex - sourceIndex;
var sourceFirst = Array.BinarySearch(Indices, 0, ValueCount, sourceIndex);
var sourceLast = Array.BinarySearch(Indices, 0, ValueCount, sourceIndex + count - 1);
if (sourceFirst < 0) sourceFirst = ~sourceFirst;
if (sourceLast < 0) sourceLast = ~sourceLast - 1;
if (!skipClearing)
{
target.Clear(targetIndex, count);
}
for (int i = sourceFirst; i <= sourceLast; i++)
{
target.At(Indices[i] + offset, Values[i]);
}
}
void CopySubVectorTo(SparseVectorStorage<T> target,
int sourceIndex, int targetIndex, int count,
bool skipClearing)
{
var offset = targetIndex - sourceIndex;
var sourceFirst = Array.BinarySearch(Indices, 0, ValueCount, sourceIndex);
var sourceLast = Array.BinarySearch(Indices, 0, ValueCount, sourceIndex + count - 1);
if (sourceFirst < 0) sourceFirst = ~sourceFirst;
if (sourceLast < 0) sourceLast = ~sourceLast - 1;
int sourceCount = sourceLast - sourceFirst + 1;
// special case when copying to itself
if (ReferenceEquals(this, target))
{
var values = new T[sourceCount];
var indices = new int[sourceCount];
Array.Copy(Values, sourceFirst, values, 0, sourceCount);
for (int i = 0; i < indices.Length; i++)
{
indices[i] = Indices[i + sourceFirst];
}
if (!skipClearing)
{
Clear(targetIndex, count);
}
for (int i = sourceFirst; i <= sourceLast; i++)
{
At(indices[i] + offset, values[i]);
}
return;
}
// special case for empty target - much faster
if (target.ValueCount == 0)
{
var values = new T[sourceCount];
var indices = new int[sourceCount];
Array.Copy(Values, sourceFirst, values, 0, sourceCount);
for (int i = 0; i < indices.Length; i++)
{
indices[i] = Indices[i + sourceFirst] + offset;
}
target.ValueCount = sourceCount;
target.Values = values;
target.Indices = indices;
return;
}
if (!skipClearing)
{
target.Clear(targetIndex, count);
}
for (int i = sourceFirst; i <= sourceLast; i++)
{
target.At(Indices[i] + offset, Values[i]);
}
}
}
}

16
src/Numerics/LinearAlgebra/Storage/VectorStorage.cs

@ -184,12 +184,22 @@ namespace MathNet.Numerics.LinearAlgebra.Storage
throw new ArgumentNullException("target");
}
ValidateSubVectorRange(target, sourceIndex, targetIndex, count);
if (ReferenceEquals(this, target))
{
throw new NotSupportedException();
}
var tmp = new T[count];
for (int i = 0; i < tmp.Length; i++)
{
tmp[i] = At(i + sourceIndex);
}
for (int i = 0; i < tmp.Length; i++)
{
At(i + targetIndex, tmp[i]);
}
ValidateSubVectorRange(target, sourceIndex, targetIndex, count);
return;
}
for (int i = sourceIndex, ii = targetIndex; i < sourceIndex + count; i++, ii++)
{

1
src/Numerics/Numerics.csproj

@ -124,6 +124,7 @@
<Compile Include="Distributions\Multivariate\InverseWishart.cs" />
<Compile Include="Distributions\Multivariate\MatrixNormal.cs" />
<Compile Include="Distributions\Multivariate\Wishart.cs" />
<Compile Include="LinearAlgebra\Storage\SparseVectorStorage.cs" />
<Compile Include="LinearAlgebra\Storage\DenseVectorStorage.cs" />
<Compile Include="LinearAlgebra\Storage\MatrixStorage.Validation.cs" />
<Compile Include="LinearAlgebra\Complex32\ExtensionMethods.cs" />

3
src/Portable/Portable.csproj

@ -906,6 +906,9 @@
<Compile Include="..\Numerics\LinearAlgebra\Storage\SparseCompressedRowMatrixStorage.cs">
<Link>LinearAlgebra\Storage\SparseCompressedRowMatrixStorage.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Storage\SparseVectorStorage.cs">
<Link>LinearAlgebra\Storage\SparseVectorStorage.cs</Link>
</Compile>
<Compile Include="..\Numerics\LinearAlgebra\Storage\VectorStorage.cs">
<Link>LinearAlgebra\Storage\VectorStorage.cs</Link>
</Compile>

25
src/UnitTests/LinearAlgebraTests/Complex/SparseVectorTest.cs

@ -35,6 +35,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
using System.Numerics;
using LinearAlgebra.Complex;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
using NUnit.Framework;
/// <summary>
@ -273,40 +274,41 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
public void CheckSparseMechanismBySettingValues()
{
var vector = new SparseVector(10000);
var storage = (SparseVectorStorage<Complex>)vector.Storage;
// Add non-zero elements
vector[200] = new Complex(1.5, 1);
Assert.AreEqual(new Complex(1.5, 1), vector[200]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[500] = new Complex(3.5, 1);
Assert.AreEqual(new Complex(3.5, 1), vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = new Complex(5.5, 1);
Assert.AreEqual(new Complex(5.5, 1), vector[800]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[0] = new Complex(7.5, 1);
Assert.AreEqual(new Complex(7.5, 1), vector[0]);
Assert.AreEqual(4, vector.NonZerosCount);
Assert.AreEqual(4, storage.ValueCount);
// Remove non-zero elements
vector[200] = Complex.Zero;
Assert.AreEqual(Complex.Zero, vector[200]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[500] = Complex.Zero;
Assert.AreEqual(Complex.Zero, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = Complex.Zero;
Assert.AreEqual(Complex.Zero, vector[800]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[0] = Complex.Zero;
Assert.AreEqual(Complex.Zero, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -325,11 +327,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
// Multiply by 0
vector *= 0;
var storage = (SparseVectorStorage<Complex>)vector.Storage;
Assert.AreEqual(Complex.Zero, vector[200]);
Assert.AreEqual(Complex.Zero, vector[500]);
Assert.AreEqual(Complex.Zero, vector[800]);
Assert.AreEqual(Complex.Zero, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -371,7 +375,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
Assert.AreEqual(Data[i] * zeroArray[i], result[i]);
}
Assert.AreEqual(2, result.NonZerosCount);
var resultStorage = (SparseVectorStorage<Complex>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>

69
src/UnitTests/LinearAlgebraTests/Complex/UserDefinedVector.cs

@ -29,65 +29,56 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
using System.Numerics;
using LinearAlgebra.Complex;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
/// <summary>
/// User-defined vector implementation (internal class for testing purposes)
/// </summary>
internal class UserDefinedVector : Vector
{
/// <summary>
/// Values storage
/// </summary>
private readonly Complex[] _data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size) : base(size)
class UserDefinedVectorStorage : VectorStorage<Complex>
{
_data = new Complex[size];
}
public readonly Complex[] Data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(Complex[] data) : base(data.Length)
{
_data = (Complex[])data.Clone();
}
public UserDefinedVectorStorage(int size)
: base(size)
{
Data = new Complex[size];
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
public override Complex this[int index]
{
get
public UserDefinedVectorStorage(int size, Complex[] data)
: base(size)
{
return _data[index];
Data = data;
}
set
public override Complex At(int index)
{
_data[index] = value;
return Data[index];
}
public override void At(int index, Complex value)
{
Data[index] = value;
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
protected internal override Complex At(int index)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size)
: base(new UserDefinedVectorStorage(size))
{
return this[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
protected internal override void At(int index, Complex value)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(Complex[] data)
: base(new UserDefinedVectorStorage(data.Length, (Complex[])data.Clone()))
{
this[index] = value;
}
/// <summary>

4
src/UnitTests/LinearAlgebraTests/Complex/VectorTests.cs

@ -97,7 +97,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopyTo(other, 2, 2, 2);
vector.CopySubVectorTo(other, 2, 2, 2);
AssertHelpers.AreEqual(Complex.Zero, other[0]);
AssertHelpers.AreEqual(Complex.Zero, other[1]);
@ -113,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex
public void CanCopyPartialVectorToSelf()
{
var vector = CreateVector(Data);
vector.CopyTo(vector, 0, 2, 2);
vector.CopySubVectorTo(vector, 0, 2, 2);
AssertHelpers.AreEqual(new Complex(1, 1), vector[0]);
AssertHelpers.AreEqual(new Complex(2, 1), vector[1]);

25
src/UnitTests/LinearAlgebraTests/Complex32/SparseVectorTest.cs

@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
using System.Collections.Generic;
using LinearAlgebra.Complex32;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
using NUnit.Framework;
using Complex32 = Numerics.Complex32;
@ -273,40 +274,41 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
public void CheckSparseMechanismBySettingValues()
{
var vector = new SparseVector(10000);
var storage = (SparseVectorStorage<Complex32>)vector.Storage;
// Add non-zero elements
vector[200] = new Complex32(1.5f, 1);
Assert.AreEqual(new Complex32(1.5f, 1), vector[200]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[500] = new Complex32(3.5f, 1);
Assert.AreEqual(new Complex32(3.5f, 1), vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = new Complex32(5.5f, 1);
Assert.AreEqual(new Complex32(5.5f, 1), vector[800]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[0] = new Complex32(7.5f, 1);
Assert.AreEqual(new Complex32(7.5f, 1), vector[0]);
Assert.AreEqual(4, vector.NonZerosCount);
Assert.AreEqual(4, storage.ValueCount);
// Remove non-zero elements
vector[200] = Complex32.Zero;
Assert.AreEqual(Complex32.Zero, vector[200]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[500] = Complex32.Zero;
Assert.AreEqual(Complex32.Zero, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = Complex32.Zero;
Assert.AreEqual(Complex32.Zero, vector[800]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[0] = Complex32.Zero;
Assert.AreEqual(Complex32.Zero, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -325,11 +327,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
// Multiply by 0
vector *= 0;
var storage = (SparseVectorStorage<Complex32>)vector.Storage;
Assert.AreEqual(Complex32.Zero, vector[200]);
Assert.AreEqual(Complex32.Zero, vector[500]);
Assert.AreEqual(Complex32.Zero, vector[800]);
Assert.AreEqual(Complex32.Zero, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -371,7 +375,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
Assert.AreEqual(Data[i] * zeroArray[i], result[i]);
}
Assert.AreEqual(2, result.NonZerosCount);
var resultStorage = (SparseVectorStorage<Complex32>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>

69
src/UnitTests/LinearAlgebraTests/Complex32/UserDefinedVector.cs

@ -28,6 +28,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
{
using LinearAlgebra.Complex32;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
using Complex32 = Numerics.Complex32;
/// <summary>
@ -35,59 +36,49 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
/// </summary>
internal class UserDefinedVector : Vector
{
/// <summary>
/// Values storage
/// </summary>
private readonly Complex32[] _data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size) : base(size)
class UserDefinedVectorStorage : VectorStorage<Complex32>
{
_data = new Complex32[size];
}
public readonly Complex32[] Data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(Complex32[] data) : base(data.Length)
{
_data = (Complex32[])data.Clone();
}
public UserDefinedVectorStorage(int size)
: base(size)
{
Data = new Complex32[size];
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
public override Complex32 this[int index]
{
get
public UserDefinedVectorStorage(int size, Complex32[] data)
: base(size)
{
return _data[index];
Data = data;
}
set
public override Complex32 At(int index)
{
_data[index] = value;
return Data[index];
}
public override void At(int index, Complex32 value)
{
Data[index] = value;
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
protected internal override Complex32 At(int index)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size)
: base(new UserDefinedVectorStorage(size))
{
return this[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
protected internal override void At(int index, Complex32 value)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(Complex32[] data)
: base(new UserDefinedVectorStorage(data.Length, (Complex32[])data.Clone()))
{
this[index] = value;
}
/// <summary>

4
src/UnitTests/LinearAlgebraTests/Complex32/VectorTests.cs

@ -97,7 +97,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopyTo(other, 2, 2, 2);
vector.CopySubVectorTo(other, 2, 2, 2);
AssertHelpers.AreEqual(Complex32.Zero, other[0]);
AssertHelpers.AreEqual(Complex32.Zero, other[1]);
@ -113,7 +113,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Complex32
public void CanCopyPartialVectorToSelf()
{
var vector = CreateVector(Data);
vector.CopyTo(vector, 0, 2, 2);
vector.CopySubVectorTo(vector, 0, 2, 2);
AssertHelpers.AreEqual(new Complex32(1, 1), vector[0]);
AssertHelpers.AreEqual(new Complex32(2, 1), vector[1]);

25
src/UnitTests/LinearAlgebraTests/Double/SparseVectorTest.cs

@ -34,6 +34,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
using System.Collections.Generic;
using LinearAlgebra.Double;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
using NUnit.Framework;
/// <summary>
@ -272,40 +273,41 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public void CheckSparseMechanismBySettingValues()
{
var vector = new SparseVector(10000);
var storage = (SparseVectorStorage<double>)vector.Storage;
// Add non-zero elements
vector[200] = 1.5;
Assert.AreEqual(1.5, vector[200]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[500] = 3.5;
Assert.AreEqual(3.5, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = 5.5;
Assert.AreEqual(5.5, vector[800]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[0] = 7.5;
Assert.AreEqual(7.5, vector[0]);
Assert.AreEqual(4, vector.NonZerosCount);
Assert.AreEqual(4, storage.ValueCount);
// Remove non-zero elements
vector[200] = 0;
Assert.AreEqual(0, vector[200]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[500] = 0;
Assert.AreEqual(0, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = 0;
Assert.AreEqual(0, vector[800]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[0] = 0;
Assert.AreEqual(0, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -324,11 +326,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
// Multiply by 0
vector *= 0;
var storage = (SparseVectorStorage<double>)vector.Storage;
Assert.AreEqual(0, vector[200]);
Assert.AreEqual(0, vector[500]);
Assert.AreEqual(0, vector[800]);
Assert.AreEqual(0, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -370,7 +374,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
Assert.AreEqual(Data[i] * zeroArray[i], result[i]);
}
Assert.AreEqual(2, result.NonZerosCount);
var resultStorage = (SparseVectorStorage<double>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>

69
src/UnitTests/LinearAlgebraTests/Double/UserDefinedVector.cs

@ -28,65 +28,56 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
using LinearAlgebra.Double;
using LinearAlgebra.Generic;
using LinearAlgebra.Storage;
/// <summary>
/// User-defined vector implementation (internal class for testing purposes)
/// </summary>
internal class UserDefinedVector : Vector
{
/// <summary>
/// Values storage
/// </summary>
private readonly double[] _data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size) : base(size)
class UserDefinedVectorStorage : VectorStorage<double>
{
_data = new double[size];
}
public readonly double[] Data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(double[] data) : base(data.Length)
{
_data = (double[])data.Clone();
}
public UserDefinedVectorStorage(int size)
: base(size)
{
Data = new double[size];
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
public override double this[int index]
{
get
public UserDefinedVectorStorage(int size, double[] data)
: base(size)
{
return _data[index];
Data = data;
}
set
public override double At(int index)
{
_data[index] = value;
return Data[index];
}
public override void At(int index, double value)
{
Data[index] = value;
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
protected internal override double At(int index)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size)
: base(new UserDefinedVectorStorage(size))
{
return this[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
protected internal override void At(int index, double value)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(double[] data)
: base(new UserDefinedVectorStorage(data.Length, (double[])data.Clone()))
{
this[index] = value;
}
/// <summary>

4
src/UnitTests/LinearAlgebraTests/Double/VectorTests.cs

@ -95,7 +95,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopyTo(other, 2, 2, 2);
vector.CopySubVectorTo(other, 2, 2, 2);
Assert.AreEqual(0.0, other[0]);
Assert.AreEqual(0.0, other[1]);
@ -111,7 +111,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
public void CanCopyPartialVectorToSelf()
{
var vector = CreateVector(Data);
vector.CopyTo(vector, 0, 2, 2);
vector.CopySubVectorTo(vector, 0, 2, 2);
Assert.AreEqual(1.0, vector[0]);
Assert.AreEqual(2.0, vector[1]);

26
src/UnitTests/LinearAlgebraTests/Single/SparseVectorTest.cs

@ -34,7 +34,9 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
using System.Collections.Generic;
using LinearAlgebra.Generic;
using LinearAlgebra.Single;
using LinearAlgebra.Storage;
using NUnit.Framework;
using Complex32 = Numerics.Complex32;
/// <summary>
/// Sparse vector tests.
@ -272,40 +274,41 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
public void CheckSparseMechanismBySettingValues()
{
var vector = new SparseVector(10000);
var storage = (SparseVectorStorage<float>)vector.Storage;
// Add non-zero elements
vector[200] = 1.5f;
Assert.AreEqual(1.5f, vector[200]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[500] = 3.5f;
Assert.AreEqual(3.5f, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = 5.5f;
Assert.AreEqual(5.5f, vector[800]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[0] = 7.5f;
Assert.AreEqual(7.5f, vector[0]);
Assert.AreEqual(4, vector.NonZerosCount);
Assert.AreEqual(4, storage.ValueCount);
// Remove non-zero elements
vector[200] = 0;
Assert.AreEqual(0, vector[200]);
Assert.AreEqual(3, vector.NonZerosCount);
Assert.AreEqual(3, storage.ValueCount);
vector[500] = 0;
Assert.AreEqual(0, vector[500]);
Assert.AreEqual(2, vector.NonZerosCount);
Assert.AreEqual(2, storage.ValueCount);
vector[800] = 0;
Assert.AreEqual(0, vector[800]);
Assert.AreEqual(1, vector.NonZerosCount);
Assert.AreEqual(1, storage.ValueCount);
vector[0] = 0;
Assert.AreEqual(0, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -324,11 +327,13 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
// Multiply by 0
vector *= 0;
var storage = (SparseVectorStorage<float>)vector.Storage;
Assert.AreEqual(0, vector[200]);
Assert.AreEqual(0, vector[500]);
Assert.AreEqual(0, vector[800]);
Assert.AreEqual(0, vector[0]);
Assert.AreEqual(0, vector.NonZerosCount);
Assert.AreEqual(0, storage.ValueCount);
}
/// <summary>
@ -370,7 +375,8 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
Assert.AreEqual(Data[i] * zeroArray[i], result[i]);
}
Assert.AreEqual(2, result.NonZerosCount);
var resultStorage = (SparseVectorStorage<float>)result.Storage;
Assert.AreEqual(2, resultStorage.ValueCount);
}
/// <summary>

69
src/UnitTests/LinearAlgebraTests/Single/UserDefinedVector.cs

@ -28,65 +28,56 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
{
using LinearAlgebra.Generic;
using LinearAlgebra.Single;
using LinearAlgebra.Storage;
/// <summary>
/// User-defined vector implementation (internal class for testing purposes)
/// </summary>
internal class UserDefinedVector : Vector
{
/// <summary>
/// Values storage
/// </summary>
private readonly float[] _data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size) : base(size)
class UserDefinedVectorStorage : VectorStorage<float>
{
_data = new float[size];
}
public readonly float[] Data;
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(float[] data) : base(data.Length)
{
_data = (float[])data.Clone();
}
public UserDefinedVectorStorage(int size)
: base(size)
{
Data = new float[size];
}
/// <summary>Gets or sets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
public override float this[int index]
{
get
public UserDefinedVectorStorage(int size, float[] data)
: base(size)
{
return _data[index];
Data = data;
}
set
public override float At(int index)
{
_data[index] = value;
return Data[index];
}
public override void At(int index, float value)
{
Data[index] = value;
}
}
/// <summary>Gets the value at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <returns>The value of the vector at the given <paramref name="index"/>.</returns>
protected internal override float At(int index)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class with a given size.
/// </summary>
/// <param name="size">The size of the vector.</param>
public UserDefinedVector(int size)
: base(new UserDefinedVectorStorage(size))
{
return this[index];
}
/// <summary>Sets the <paramref name="value"/> at the given <paramref name="index"/>.</summary>
/// <param name="index">The index of the value to get or set.</param>
/// <param name="value">The value to set.</param>
protected internal override void At(int index, float value)
/// <summary>
/// Initializes a new instance of the <see cref="UserDefinedVector"/> class for an array.
/// </summary>
/// <param name="data">The array to create this vector from.</param>
public UserDefinedVector(float[] data)
: base(new UserDefinedVectorStorage(data.Length, (float[])data.Clone()))
{
this[index] = value;
}
/// <summary>

4
src/UnitTests/LinearAlgebraTests/Single/VectorTests.cs

@ -95,7 +95,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
var vector = CreateVector(Data);
var other = CreateVector(Data.Length);
vector.CopyTo(other, 2, 2, 2);
vector.CopySubVectorTo(other, 2, 2, 2);
Assert.AreEqual(0.0f, other[0]);
Assert.AreEqual(0.0f, other[1]);
@ -111,7 +111,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Single
public void CanCopyPartialVectorToSelf()
{
var vector = CreateVector(Data);
vector.CopyTo(vector, 0, 2, 2);
vector.CopySubVectorTo(vector, 0, 2, 2);
Assert.AreEqual(1.0f, vector[0]);
Assert.AreEqual(2.0f, vector[1]);

Loading…
Cancel
Save