Browse Source

LA: migrate mixed-storage fallback implementations to use higher order functions

cuda
Christoph Ruegg 12 years ago
parent
commit
fbfe077552
  1. 486
      src/Numerics/LinearAlgebra/Complex/Matrix.cs
  2. 85
      src/Numerics/LinearAlgebra/Complex/Vector.cs
  3. 484
      src/Numerics/LinearAlgebra/Complex32/Matrix.cs
  4. 85
      src/Numerics/LinearAlgebra/Complex32/Vector.cs
  5. 526
      src/Numerics/LinearAlgebra/Double/Matrix.cs
  6. 122
      src/Numerics/LinearAlgebra/Double/Vector.cs
  7. 18
      src/Numerics/LinearAlgebra/Matrix.cs
  8. 525
      src/Numerics/LinearAlgebra/Single/Matrix.cs
  9. 122
      src/Numerics/LinearAlgebra/Single/Vector.cs
  10. 4
      src/Numerics/LinearAlgebra/Vector.cs

486
src/Numerics/LinearAlgebra/Complex/Matrix.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -65,201 +65,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
MapInplace(x => x.Magnitude < threshold ? Complex.Zero : x, Zeros.AllowSkip);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = ConjugateTranspose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i).Magnitude;
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<Complex> RowSums()
{
var ret = new Complex[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<Complex> RowAbsoluteSums()
{
var ret = new Complex[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// Returns the conjugate transpose of this matrix.
/// </summary>
public override Vector<Complex> ColumnSums()
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<Complex> ConjugateTranspose()
{
var ret = new Complex[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
var ret = Transpose();
ret.MapInplace(c => c.Conjugate(), Zeros.AllowSkip);
return ret;
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
public override Vector<Complex> ColumnAbsoluteSums()
/// <param name="result">The result of the conjugation.</param>
protected override void DoConjugate(Matrix<Complex> result)
{
var ret = new Complex[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
Map(Complex.Conjugate, result, Zeros.AllowSkip);
}
/// <summary>
/// Returns the conjugate transpose of this matrix.
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<Complex> ConjugateTranspose()
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<Complex> result)
{
var ret = Transpose();
ret.MapInplace(c => c.Conjugate(), Zeros.AllowSkip);
return ret;
Map(Complex.Negate, result, Zeros.AllowSkip);
}
/// <summary>
@ -269,13 +101,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex scalar, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -287,13 +113,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoAdd(Matrix<Complex> other, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + other.At(i, j));
}
}
Map2(Complex.Add, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -303,13 +123,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex scalar, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -321,13 +135,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoSubtract(Matrix<Complex> other, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - other.At(i, j));
}
}
Map2(Complex.Subtract, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -337,13 +145,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the multiplication.</param>
protected override void DoMultiply(Complex scalar, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j)*scalar);
}
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -392,23 +194,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex divisor, Matrix<Complex> result)
{
DoMultiply(1.0/divisor, result);
Map(x => x/divisor, result, divisor.IsZero() ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="dividend">The scalar to divide by each element of the matrix.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(Complex dividend, Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend/At(i, j));
}
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -531,36 +327,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
}
}
/// <summary>
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, -At(i, j));
}
}
}
/// <summary>
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the conjugation.</param>
protected override void DoConjugate(Matrix<Complex> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j).Conjugate());
}
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -568,13 +334,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Matrix<Complex> other, Matrix<Complex> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)*other.At(i, j));
}
}
Map2(Complex.Multiply, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -584,13 +344,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex> divisor, Matrix<Complex> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
Map2(Complex.Divide, divisor, result, Zeros.Include);
}
/// <summary>
@ -600,7 +354,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(Complex exponent, Matrix<Complex> result)
{
Map(x => x.Power(exponent), result, Zeros.AllowSkip);
Map(x => x.Power(exponent), result, Zeros.Include);
}
/// <summary>
@ -687,6 +441,194 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
Map(Complex.Log, result, Zeros.Include);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = ConjugateTranspose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i).Magnitude;
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<Complex> RowSums()
{
var ret = new Complex[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<Complex> RowAbsoluteSums()
{
var ret = new Complex[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<Complex> ColumnSums()
{
var ret = new Complex[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<Complex> ColumnAbsoluteSums()
{
var ret = new Complex[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex>.Build.Dense(ret);
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -63,6 +63,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
MapInplace(x => x.Magnitude < threshold ? Complex.Zero : x, Zeros.AllowSkip);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<Complex> result)
{
Map(Complex.Conjugate, result, Zeros.AllowSkip);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<Complex> result)
{
Map(Complex.Negate, result, Zeros.AllowSkip);
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -74,10 +92,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoAdd(Complex scalar, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + scalar);
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -91,10 +106,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoAdd(Vector<Complex> other, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + other.At(index));
}
Map2(Complex.Add, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -108,7 +120,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoSubtract(Complex scalar, Vector<Complex> result)
{
DoAdd(-scalar, result);
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -122,10 +134,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoSubtract(Vector<Complex> other, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) - other.At(index));
}
Map2(Complex.Subtract, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -139,10 +148,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoMultiply(Complex scalar, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * scalar);
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -156,7 +162,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// </param>
protected override void DoDivide(Complex divisor, Vector<Complex> result)
{
DoMultiply(1 / divisor, result);
Map(x => x/divisor, result, divisor.IsZero() ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
@ -166,10 +172,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(Complex dividend, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend / At(index));
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -179,10 +182,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<Complex> other, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * other.At(index));
}
Map2(Complex.Multiply, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -192,10 +192,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<Complex> divisor, Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / divisor.At(index));
}
Map2(Complex.Divide, divisor, result, Zeros.Include);
}
/// <summary>
@ -205,7 +202,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(Complex exponent, Vector<Complex> result)
{
Map(x => x.Power(exponent), result, Zeros.AllowSkip);
Map(x => x.Power(exponent), result, Zeros.Include);
}
/// <summary>
@ -453,30 +450,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex
return Math.Pow(sum, 1.0/p);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index).Conjugate());
}
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<Complex> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, -At(index));
}
}
/// <summary>
/// Returns the index of the absolute maximum element.
/// </summary>

484
src/Numerics/LinearAlgebra/Complex32/Matrix.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -60,201 +60,33 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
MapInplace(x => x.Magnitude < threshold ? Complex32.Zero : x, Zeros.AllowSkip);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = ConjugateTranspose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i).Magnitude;
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex32> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => ((float)norminv[i])*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex32> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => ((float)norminv[j])*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<Complex32> RowSums()
{
var ret = new Complex32[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<Complex32> RowAbsoluteSums()
{
var ret = new Complex32[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// Returns the conjugate transpose of this matrix.
/// </summary>
public override Vector<Complex32> ColumnSums()
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<Complex32> ConjugateTranspose()
{
var ret = new Complex32[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
var ret = Transpose();
ret.MapInplace(c => c.Conjugate(), Zeros.AllowSkip);
return ret;
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
public override Vector<Complex32> ColumnAbsoluteSums()
/// <param name="result">The result of the conjugation.</param>
protected override void DoConjugate(Matrix<Complex32> result)
{
var ret = new Complex32[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
Map(Complex32.Conjugate, result, Zeros.AllowSkip);
}
/// <summary>
/// Returns the conjugate transpose of this matrix.
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<Complex32> ConjugateTranspose()
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<Complex32> result)
{
var ret = Transpose();
ret.MapInplace(c => c.Conjugate(), Zeros.AllowSkip);
return ret;
Map(Complex32.Negate, result, Zeros.AllowSkip);
}
/// <summary>
@ -264,13 +96,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(Complex32 scalar, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -282,13 +108,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoAdd(Matrix<Complex32> other, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + other.At(i, j));
}
}
Map2(Complex32.Add, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -298,13 +118,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(Complex32 scalar, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -316,13 +130,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoSubtract(Matrix<Complex32> other, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - other.At(i, j));
}
}
Map2(Complex32.Subtract, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -332,13 +140,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the multiplication.</param>
protected override void DoMultiply(Complex32 scalar, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j)*scalar);
}
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -366,23 +168,17 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(Complex32 divisor, Matrix<Complex32> result)
{
DoMultiply(1.0f/divisor, result);
Map(x => x/divisor, result, divisor.IsZero() ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="dividend">The scalar to divide by each element of the matrix.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(Complex32 dividend, Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend/At(i, j));
}
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -526,36 +322,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
}
}
/// <summary>
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, -At(i, j));
}
}
}
/// <summary>
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the conjugation.</param>
protected override void DoConjugate(Matrix<Complex32> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j).Conjugate());
}
}
}
/// <summary>
/// Pointwise multiplies this matrix with another matrix and stores the result into the result matrix.
/// </summary>
@ -563,13 +329,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Matrix<Complex32> other, Matrix<Complex32> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)*other.At(i, j));
}
}
Map2(Complex32.Multiply, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -579,13 +339,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<Complex32> divisor, Matrix<Complex32> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
Map2(Complex32.Divide, divisor, result, Zeros.Include);
}
/// <summary>
@ -595,7 +349,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(Complex32 exponent, Matrix<Complex32> result)
{
Map(x => x.Power(exponent), result, Zeros.AllowSkip);
Map(x => x.Power(exponent), result, Zeros.Include);
}
/// <summary>
@ -682,6 +436,192 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
Map(Complex32.Log, result, Zeros.Include);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += At(i, j).Magnitude;
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = ConjugateTranspose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i).Magnitude;
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex32> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => ((float)norminv[i])*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<Complex32> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => ((float)norminv[j])*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<Complex32> RowSums()
{
var ret = new Complex32[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<Complex32> RowAbsoluteSums()
{
var ret = new Complex32[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<Complex32> ColumnSums()
{
var ret = new Complex32[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<Complex32> ColumnAbsoluteSums()
{
var ret = new Complex32[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x.Magnitude, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<Complex32>.Build.Dense(ret);
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -58,6 +58,24 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
MapInplace(x => x.Magnitude < threshold ? Complex32.Zero : x, Zeros.AllowSkip);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<Complex32> result)
{
Map(Complex32.Conjugate, result, Zeros.AllowSkip);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<Complex32> result)
{
Map(Complex32.Negate, result, Zeros.AllowSkip);
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -69,10 +87,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoAdd(Complex32 scalar, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + scalar);
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -86,10 +101,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoAdd(Vector<Complex32> other, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + other.At(index));
}
Map2(Complex32.Add, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -103,7 +115,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoSubtract(Complex32 scalar, Vector<Complex32> result)
{
DoAdd(-scalar, result);
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -117,10 +129,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoSubtract(Vector<Complex32> other, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) - other.At(index));
}
Map2(Complex32.Subtract, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -134,10 +143,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoMultiply(Complex32 scalar, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * scalar);
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -151,7 +157,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// </param>
protected override void DoDivide(Complex32 divisor, Vector<Complex32> result)
{
DoMultiply(1 / divisor, result);
Map(x => x/divisor, result, divisor.IsZero() ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
@ -161,10 +167,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(Complex32 dividend, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend / At(index));
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -174,10 +177,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<Complex32> other, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * other.At(index));
}
Map2(Complex32.Multiply, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -187,10 +187,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<Complex32> divisor, Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / divisor.At(index));
}
Map2(Complex32.Divide, divisor, result, Zeros.Include);
}
/// <summary>
@ -200,7 +197,7 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(Complex32 exponent, Vector<Complex32> result)
{
Map(x => x.Power(exponent), result, Zeros.AllowSkip);
Map(x => x.Power(exponent), result, Zeros.Include);
}
/// <summary>
@ -448,30 +445,6 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32
return Math.Pow(sum, 1.0/p);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index).Conjugate());
}
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<Complex32> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, -At(index));
}
}
/// <summary>
/// Returns the index of the absolute maximum element.
/// </summary>

526
src/Numerics/LinearAlgebra/Double/Matrix.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -58,199 +58,36 @@ namespace MathNet.Numerics.LinearAlgebra.Double
MapInplace(x => Math.Abs(x) < threshold ? 0d : x, Zeros.AllowSkip);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = Transpose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i);
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// Returns the conjugate transpose of this matrix.
/// </summary>
public override sealed Matrix<double> NormalizeRows(double norm)
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<double> ConjugateTranspose()
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
return Transpose();
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
public override sealed Matrix<double> NormalizeColumns(double norm)
/// <param name="result">The result of the conjugation.</param>
protected override sealed void DoConjugate(Matrix<double> result)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
if (ReferenceEquals(this, result))
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
return;
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<double> RowSums()
{
var ret = new double[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<double> RowAbsoluteSums()
{
var ret = new double[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<double> ColumnSums()
{
var ret = new double[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<double> ColumnAbsoluteSums()
{
var ret = new double[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
CopyTo(result);
}
/// <summary>
/// Returns the conjugate transpose of this matrix.
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<double> ConjugateTranspose()
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<double> result)
{
return Transpose();
Map(x => -x, result, Zeros.AllowSkip);
}
/// <summary>
@ -260,13 +97,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(double scalar, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -278,13 +109,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoAdd(Matrix<double> other, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + other.At(i, j));
}
}
Map2((x, y) => x + y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -294,13 +119,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(double scalar, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -312,13 +131,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoSubtract(Matrix<double> other, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - other.At(i, j));
}
}
Map2((x, y) => x - y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -328,13 +141,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the multiplication.</param>
protected override void DoMultiply(double scalar, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j)*scalar);
}
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -362,23 +169,17 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(double divisor, Matrix<double> result)
{
DoMultiply(1.0/divisor, result);
Map(x => x/divisor, result, divisor == 0.0 ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="dividend">The scalar to divide by each element of the matrix.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(double dividend, Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend/At(i, j));
}
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -492,35 +293,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
DoTransposeThisAndMultiply(rightSide, result);
}
/// <summary>
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<double> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, -At(i, j));
}
}
}
/// <summary>
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the conjugation.</param>
protected override sealed void DoConjugate(Matrix<double> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
}
/// <summary>
/// Computes the canonical modulus, where the result has the sign of the divisor,
/// for the given divisor each element of the matrix.
@ -529,13 +301,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(double divisor, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, Euclid.Modulus(At(row, column), divisor));
}
}
Map(x => Euclid.Modulus(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -546,13 +312,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(double dividend, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, Euclid.Modulus(dividend, At(row, column)));
}
}
Map(x => Euclid.Modulus(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -563,13 +323,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">Matrix to store the results in.</param>
protected override void DoRemainder(double divisor, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, At(row, column)%divisor);
}
}
Map(x => Euclid.Remainder(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -580,13 +334,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainderByThis(double dividend, Matrix<double> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, dividend%At(row, column));
}
}
Map(x => Euclid.Remainder(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -596,13 +344,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Matrix<double> other, Matrix<double> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)*other.At(i, j));
}
}
Map2((x, y) => x*y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -612,13 +354,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<double> divisor, Matrix<double> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
Map2((x, y) => x/y, divisor, result, Zeros.Include);
}
/// <summary>
@ -628,7 +364,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(double exponent, Matrix<double> result)
{
Map(x => Math.Pow(x, exponent), result, Zeros.AllowSkip);
Map(x => Math.Pow(x, exponent), result, exponent > 0.0 ? Zeros.AllowSkip : Zeros.Include);
}
/// <summary>
@ -639,13 +375,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<double> divisor, Matrix<double> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, Euclid.Modulus(At(i, j), divisor.At(i, j)));
}
}
Map2(Euclid.Modulus, divisor, result, Zeros.Include);
}
/// <summary>
@ -656,13 +386,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseRemainder(Matrix<double> divisor, Matrix<double> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)%divisor.At(i, j));
}
}
Map2(Euclid.Remainder, divisor, result, Zeros.Include);
}
/// <summary>
@ -683,6 +407,192 @@ namespace MathNet.Numerics.LinearAlgebra.Double
Map(Math.Log, result, Zeros.Include);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = Transpose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i);
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<double> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<double> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<double> RowSums()
{
var ret = new double[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<double> RowAbsoluteSums()
{
var ret = new double[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<double> ColumnSums()
{
var ret = new double[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<double> ColumnAbsoluteSums()
{
var ret = new double[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Computes the trace of this matrix.
/// </summary>

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -56,6 +56,29 @@ namespace MathNet.Numerics.LinearAlgebra.Double
MapInplace(x => Math.Abs(x) < threshold ? 0d : x, Zeros.AllowSkip);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override sealed void DoConjugate(Vector<double> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<double> result)
{
Map(x => -x, result, Zeros.AllowSkip);
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -67,10 +90,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoAdd(double scalar, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + scalar);
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -84,10 +104,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoAdd(Vector<double> other, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + other.At(index));
}
Map2((x, y) => x + y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -101,7 +118,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoSubtract(double scalar, Vector<double> result)
{
DoAdd(-scalar, result);
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -115,10 +132,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoSubtract(Vector<double> other, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) - other.At(index));
}
Map2((x, y) => x - y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -132,10 +146,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoMultiply(double scalar, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * scalar);
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -149,7 +160,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// </param>
protected override void DoDivide(double divisor, Vector<double> result)
{
DoMultiply(1 / divisor, result);
Map(x => x/divisor, result, divisor == 0.0 ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
@ -159,10 +170,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(double dividend, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend / At(index));
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -172,10 +180,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<double> other, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * other.At(index));
}
Map2((x, y) => x*y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -185,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<double> divisor, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / divisor.At(index));
}
Map2((x, y) => x/y, divisor, result, Zeros.Include);
}
/// <summary>
@ -198,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(double exponent, Vector<double> result)
{
Map(x => Math.Pow(x, exponent), result, Zeros.AllowSkip);
Map(x => Math.Pow(x, exponent), result, exponent > 0.0 ? Zeros.AllowSkip : Zeros.Include);
}
/// <summary>
@ -209,10 +211,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<double> divisor, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, Euclid.Modulus(At(index), divisor.At(index)));
}
Map2(Euclid.Modulus, divisor, result, Zeros.Include);
}
/// <summary>
@ -223,10 +222,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseRemainder(Vector<double> divisor, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index)%divisor.At(index));
}
Map2(Euclid.Remainder, divisor, result, Zeros.Include);
}
/// <summary>
@ -280,10 +276,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(double divisor, Vector<double> result)
{
for (int i = 0; i < Count; i++)
{
result.At(i, Euclid.Modulus(At(i), divisor));
}
Map(x => Euclid.Modulus(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -294,10 +287,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(double dividend, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, Euclid.Modulus(dividend, At(index)));
}
Map(x => Euclid.Modulus(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -308,10 +298,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainder(double divisor, Vector<double> result)
{
for (int i = 0; i < Count; i++)
{
result.At(i, At(i)%divisor);
}
Map(x => Euclid.Remainder(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -322,10 +309,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainderByThis(double dividend, Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend%At(index));
}
Map(x => Euclid.Remainder(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -459,32 +443,6 @@ namespace MathNet.Numerics.LinearAlgebra.Double
return Math.Pow(sum, 1.0/p);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<double> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<double> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, -At(index));
}
}
/// <summary>
/// Returns the index of the absolute maximum element.
/// </summary>

18
src/Numerics/LinearAlgebra/Matrix.cs

@ -1736,6 +1736,24 @@ namespace MathNet.Numerics.LinearAlgebra
return EnumerateColumns().Aggregate(f);
}
/// <summary>
/// Applies a function to each value pair of two matrices and replaces the value in the result vector.
/// </summary>
public void Map2(Func<T, T, T> f, Matrix<T> other, Matrix<T> result, Zeros zeros = Zeros.AllowSkip)
{
Storage.Map2To(result.Storage, other.Storage, f, zeros, ExistingData.Clear);
}
/// <summary>
/// Applies a function to each value pair of two matrices and returns the results as a new vector.
/// </summary>
public Matrix<T> Map2(Func<T, T, T> f, Matrix<T> other, Zeros zeros = Zeros.AllowSkip)
{
var result = Build.SameAs(this);
Storage.Map2To(result.Storage, other.Storage, f, zeros, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Applies a function to update the status with each value pair of two matrices and returns the resulting status.
/// </summary>

525
src/Numerics/LinearAlgebra/Single/Matrix.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -58,198 +58,36 @@ namespace MathNet.Numerics.LinearAlgebra.Single
MapInplace(x => Math.Abs(x) < threshold ? 0f : x, Zeros.AllowSkip);
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = Transpose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i);
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// Returns the conjugate transpose of this matrix.
/// </summary>
public override sealed Matrix<float> NormalizeRows(double norm)
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<float> ConjugateTranspose()
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => (float)norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
return Transpose();
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
public override sealed Matrix<float> NormalizeColumns(double norm)
/// <param name="result">The result of the conjugation.</param>
protected override sealed void DoConjugate(Matrix<float> result)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
if (ReferenceEquals(this, result))
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
return;
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => (float)norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<float> RowSums()
{
var ret = new float[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<float> RowAbsoluteSums()
{
var ret = new float[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<float> ColumnSums()
{
var ret = new float[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<float> ColumnAbsoluteSums()
{
var ret = new float[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
CopyTo(result);
}
/// <summary>
/// Returns the conjugate transpose of this matrix.
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <returns>The conjugate transpose of this matrix.</returns>
public override sealed Matrix<float> ConjugateTranspose()
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<float> result)
{
return Transpose();
Map(x => -x, result, Zeros.AllowSkip);
}
/// <summary>
@ -259,13 +97,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the addition.</param>
protected override void DoAdd(float scalar, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + scalar);
}
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -277,13 +109,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoAdd(Matrix<float> other, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) + other.At(i, j));
}
}
Map2((x, y) => x + y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -293,13 +119,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the subtraction.</param>
protected override void DoSubtract(float scalar, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - scalar);
}
}
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -311,13 +131,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <exception cref="ArgumentOutOfRangeException">If the two matrices don't have the same dimensions.</exception>
protected override void DoSubtract(Matrix<float> other, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j) - other.At(i, j));
}
}
Map2((x, y) => x - y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -327,13 +141,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the multiplication.</param>
protected override void DoMultiply(float scalar, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, At(i, j)*scalar);
}
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -382,23 +190,17 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivide(float divisor, Matrix<float> result)
{
DoMultiply(1.0f/divisor, result);
Map(x => x/divisor, result, divisor == 0.0f ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
/// Divides a scalar by each element of the matrix and stores the result in the result matrix.
/// </summary>
/// <param name="dividend">The scalar to add.</param>
/// <param name="dividend">The scalar to divide by each element of the matrix.</param>
/// <param name="result">The matrix to store the result of the division.</param>
protected override void DoDivideByThis(float dividend, Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, dividend/At(i, j));
}
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -499,13 +301,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">Matrix to store the results in.</param>
protected override void DoModulus(float divisor, Matrix<float> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, Euclid.Modulus(At(row, column), divisor));
}
}
Map(x => Euclid.Modulus(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -516,13 +312,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(float dividend, Matrix<float> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, Euclid.Modulus(dividend, At(row, column)));
}
}
Map(x => Euclid.Modulus(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -533,13 +323,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">Matrix to store the results in.</param>
protected override void DoRemainder(float divisor, Matrix<float> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, At(row, column)%divisor);
}
}
Map(x => Euclid.Remainder(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -550,42 +334,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainderByThis(float dividend, Matrix<float> result)
{
for (var row = 0; row < RowCount; row++)
{
for (var column = 0; column < ColumnCount; column++)
{
result.At(row, column, dividend%At(row, column));
}
}
}
/// <summary>
/// Negate each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the negation.</param>
protected override void DoNegate(Matrix<float> result)
{
for (var i = 0; i < RowCount; i++)
{
for (var j = 0; j < ColumnCount; j++)
{
result.At(i, j, -At(i, j));
}
}
}
/// <summary>
/// Complex conjugates each element of this matrix and place the results into the result matrix.
/// </summary>
/// <param name="result">The result of the conjugation.</param>
protected override sealed void DoConjugate(Matrix<float> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
Map(x => Euclid.Remainder(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -595,13 +344,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Matrix<float> other, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)*other.At(i, j));
}
}
Map2((x, y) => x*y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -611,13 +354,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The matrix to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Matrix<float> divisor, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)/divisor.At(i, j));
}
}
Map2((x, y) => x/y, divisor, result, Zeros.Include);
}
/// <summary>
@ -627,7 +364,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(float exponent, Matrix<float> result)
{
Map(x => (float)Math.Pow(x, exponent), result, Zeros.AllowSkip);
Map(x => (float)Math.Pow(x, exponent), result, exponent > 0.0f ? Zeros.AllowSkip : Zeros.Include);
}
/// <summary>
@ -638,13 +375,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Matrix<float> divisor, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, Euclid.Modulus(At(i, j), divisor.At(i, j)));
}
}
Map2(Euclid.Modulus, divisor, result, Zeros.Include);
}
/// <summary>
@ -655,13 +386,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseRemainder(Matrix<float> divisor, Matrix<float> result)
{
for (var j = 0; j < ColumnCount; j++)
{
for (var i = 0; i < RowCount; i++)
{
result.At(i, j, At(i, j)%divisor.At(i, j));
}
}
Map2(Euclid.Remainder, divisor, result, Zeros.Include);
}
/// <summary>
@ -703,6 +428,192 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return sum;
}
/// <summary>Calculates the induced L1 norm of this matrix.</summary>
/// <returns>The maximum absolute column sum of the matrix.</returns>
public override double L1Norm()
{
var norm = 0d;
for (var j = 0; j < ColumnCount; j++)
{
var s = 0d;
for (var i = 0; i < RowCount; i++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the induced infinity norm of this matrix.</summary>
/// <returns>The maximum absolute row sum of the matrix.</returns>
public override double InfinityNorm()
{
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
var s = 0d;
for (var j = 0; j < ColumnCount; j++)
{
s += Math.Abs(At(i, j));
}
norm = Math.Max(norm, s);
}
return norm;
}
/// <summary>Calculates the entry-wise Frobenius norm of this matrix.</summary>
/// <returns>The square root of the sum of the squared values.</returns>
public override double FrobeniusNorm()
{
var transpose = Transpose();
var aat = this*transpose;
var norm = 0d;
for (var i = 0; i < RowCount; i++)
{
norm += aat.At(i, i);
}
return Math.Sqrt(norm);
}
/// <summary>
/// Calculates the p-norms of all row vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> RowNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[RowCount];
if (norm == 2.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByRowUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Calculates the p-norms of all column vectors.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override Vector<double> ColumnNorms(double norm)
{
if (norm <= 0.0)
{
throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive);
}
var ret = new double[ColumnCount];
if (norm == 2.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret, Zeros.AllowSkip);
}
else if (norm == 1.0)
{
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
}
else if (double.IsPositiveInfinity(norm))
{
Storage.FoldByColumnUnchecked(ret, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret, Zeros.AllowSkip);
}
else
{
double invnorm = 1.0/norm;
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret, Zeros.AllowSkip);
}
return Vector<double>.Build.Dense(ret);
}
/// <summary>
/// Normalizes all row vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<float> NormalizeRows(double norm)
{
var norminv = ((DenseVectorStorage<double>)RowNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => (float)norminv[i]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Normalizes all column vectors to a unit p-norm.
/// Typical values for p are 1.0 (L1, Manhattan norm), 2.0 (L2, Euclidean norm) and positive infinity (infinity norm)
/// </summary>
public override sealed Matrix<float> NormalizeColumns(double norm)
{
var norminv = ((DenseVectorStorage<double>)ColumnNorms(norm).Storage).Data;
for (int i = 0; i < norminv.Length; i++)
{
norminv[i] = norminv[i] == 0d ? 1d : 1d/norminv[i];
}
var result = Build.SameAs(this, RowCount, ColumnCount);
Storage.MapIndexedTo(result.Storage, (i, j, x) => (float)norminv[j]*x, Zeros.AllowSkip, ExistingData.AssumeZeros);
return result;
}
/// <summary>
/// Calculates the value sum of each row vector.
/// </summary>
public override Vector<float> RowSums()
{
var ret = new float[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each row vector.
/// </summary>
public override Vector<float> RowAbsoluteSums()
{
var ret = new float[RowCount];
Storage.FoldByRowUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the value sum of each column vector.
/// </summary>
public override Vector<float> ColumnSums()
{
var ret = new float[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + x, (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Calculates the absolute value sum of each column vector.
/// </summary>
public override Vector<float> ColumnAbsoluteSums()
{
var ret = new float[ColumnCount];
Storage.FoldByColumnUnchecked(ret, (s, x) => s + Math.Abs(x), (x, c) => x, ret, Zeros.AllowSkip);
return Vector<float>.Build.Dense(ret);
}
/// <summary>
/// Evaluates whether this matrix is hermitian (conjugate symmetric).
/// </summary>

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

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2015 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -56,6 +56,29 @@ namespace MathNet.Numerics.LinearAlgebra.Single
MapInplace(x => Math.Abs(x) < threshold ? 0f : x, Zeros.AllowSkip);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override sealed void DoConjugate(Vector<float> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<float> result)
{
Map(x => -x, result, Zeros.AllowSkip);
}
/// <summary>
/// Adds a scalar to each element of the vector and stores the result in the result vector.
/// </summary>
@ -67,10 +90,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoAdd(float scalar, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + scalar);
}
Map(x => x + scalar, result, Zeros.Include);
}
/// <summary>
@ -84,10 +104,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoAdd(Vector<float> other, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) + other.At(index));
}
Map2((x, y) => x + y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -101,7 +118,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoSubtract(float scalar, Vector<float> result)
{
DoAdd(-scalar, result);
Map(x => x - scalar, result, Zeros.Include);
}
/// <summary>
@ -115,10 +132,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoSubtract(Vector<float> other, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) - other.At(index));
}
Map2((x, y) => x - y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -132,10 +146,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoMultiply(float scalar, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * scalar);
}
Map(x => x*scalar, result, Zeros.AllowSkip);
}
/// <summary>
@ -149,7 +160,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// </param>
protected override void DoDivide(float divisor, Vector<float> result)
{
DoMultiply(1 / divisor, result);
Map(x => x/divisor, result, divisor == 0.0f ? Zeros.Include : Zeros.AllowSkip);
}
/// <summary>
@ -159,10 +170,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the division.</param>
protected override void DoDivideByThis(float dividend, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend / At(index));
}
Map(x => dividend/x, result, Zeros.Include);
}
/// <summary>
@ -172,10 +180,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the pointwise multiplication.</param>
protected override void DoPointwiseMultiply(Vector<float> other, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) * other.At(index));
}
Map2((x, y) => x*y, other, result, Zeros.AllowSkip);
}
/// <summary>
@ -185,10 +190,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the pointwise division.</param>
protected override void DoPointwiseDivide(Vector<float> divisor, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index) / divisor.At(index));
}
Map2((x, y) => x/y, divisor, result, Zeros.Include);
}
/// <summary>
@ -198,7 +200,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The vector to store the result of the pointwise power.</param>
protected override void DoPointwisePower(float exponent, Vector<float> result)
{
Map(x => (float)Math.Pow(x, exponent), result, Zeros.AllowSkip);
Map(x => (float)Math.Pow(x, exponent), result, exponent > 0.0f ? Zeros.AllowSkip : Zeros.Include);
}
/// <summary>
@ -209,10 +211,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseModulus(Vector<float> divisor, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, Euclid.Modulus(At(index), divisor.At(index)));
}
Map2(Euclid.Modulus, divisor, result, Zeros.Include);
}
/// <summary>
@ -223,10 +222,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">The result of the modulus.</param>
protected override void DoPointwiseRemainder(Vector<float> divisor, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, At(index)%divisor.At(index));
}
Map2(Euclid.Remainder, divisor, result, Zeros.Include);
}
/// <summary>
@ -280,10 +276,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulus(float divisor, Vector<float> result)
{
for (int i = 0; i < Count; i++)
{
result.At(i, Euclid.Modulus(At(i), divisor));
}
Map(x => Euclid.Modulus(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -294,10 +287,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoModulusByThis(float dividend, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, Euclid.Modulus(dividend, At(index)));
}
Map(x => Euclid.Modulus(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -308,10 +298,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainder(float divisor, Vector<float> result)
{
for (int i = 0; i < Count; i++)
{
result.At(i, At(i)%divisor);
}
Map(x => Euclid.Remainder(x, divisor), result, Zeros.Include);
}
/// <summary>
@ -322,10 +309,7 @@ namespace MathNet.Numerics.LinearAlgebra.Single
/// <param name="result">A vector to store the results in.</param>
protected override void DoRemainderByThis(float dividend, Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, dividend%At(index));
}
Map(x => Euclid.Remainder(dividend, x), result, Zeros.Include);
}
/// <summary>
@ -459,32 +443,6 @@ namespace MathNet.Numerics.LinearAlgebra.Single
return Math.Pow(sum, 1.0/p);
}
/// <summary>
/// Conjugates vector and save result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoConjugate(Vector<float> result)
{
if (ReferenceEquals(this, result))
{
return;
}
CopyTo(result);
}
/// <summary>
/// Negates vector and saves result to <paramref name="result"/>
/// </summary>
/// <param name="result">Target vector</param>
protected override void DoNegate(Vector<float> result)
{
for (var index = 0; index < Count; index++)
{
result.At(index, -At(index));
}
}
/// <summary>
/// Returns the index of the absolute maximum element.
/// </summary>

4
src/Numerics/LinearAlgebra/Vector.cs

@ -369,6 +369,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// </summary>
public void MapInplace(Func<T, T> f, Zeros zeros = Zeros.AllowSkip)
{
// TODO: actual in-place
Storage.MapToUnchecked(Storage, f, zeros, ExistingData.AssumeZeros);
}
@ -380,6 +381,7 @@ namespace MathNet.Numerics.LinearAlgebra
/// </summary>
public void MapIndexedInplace(Func<int, T, T> f, Zeros zeros = Zeros.AllowSkip)
{
// TODO: actual in-place
Storage.MapIndexedToUnchecked(Storage, f, zeros, ExistingData.AssumeZeros);
}
@ -392,6 +394,7 @@ namespace MathNet.Numerics.LinearAlgebra
where TU : struct, IEquatable<TU>, IFormattable
{
// TODO: in v4 update this method to replace TU with T (consistent with Matrix, see MapConvert)
// then automatically do in-place if possible.
Storage.MapTo(result.Storage, f, zeros, zeros == Zeros.Include ? ExistingData.AssumeZeros : ExistingData.Clear);
}
@ -405,6 +408,7 @@ namespace MathNet.Numerics.LinearAlgebra
where TU : struct, IEquatable<TU>, IFormattable
{
// TODO: in v4 update this method to replace TU with T (consistent with Matrix, see MapIndexedConvert)
// then automatically do in-place if possible.
Storage.MapIndexedTo(result.Storage, f, zeros, zeros == Zeros.Include ? ExistingData.AssumeZeros : ExistingData.Clear);
}

Loading…
Cancel
Save