diff --git a/src/Numerics/LinearAlgebra/Complex/Matrix.cs b/src/Numerics/LinearAlgebra/Complex/Matrix.cs index fa72859b..46a1daad 100644 --- a/src/Numerics/LinearAlgebra/Complex/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex/Matrix.cs @@ -106,6 +106,104 @@ namespace MathNet.Numerics.LinearAlgebra.Complex return Math.Sqrt(norm); } + /// + /// 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) + /// + public override Vector RowNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(RowCount); + if (norm == 2.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x.Magnitude, (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override Vector ColumnNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(ColumnCount); + if (norm == 2.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x.MagnitudeSquared(), (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x.Magnitude, (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeRows(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeColumns(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + /// /// Returns the conjugate transpose of this matrix. /// diff --git a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs index 859dbddd..7bd2179d 100644 --- a/src/Numerics/LinearAlgebra/Complex32/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Complex32/Matrix.cs @@ -100,6 +100,104 @@ namespace MathNet.Numerics.LinearAlgebra.Complex32 return Math.Sqrt(norm); } + /// + /// 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) + /// + public override Vector RowNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(RowCount); + if (norm == 2.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x.Magnitude, (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override Vector ColumnNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(ColumnCount); + if (norm == 2.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x.MagnitudeSquared, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x.Magnitude, (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => Math.Max(s, x.Magnitude), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Pow(x.Magnitude, norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeRows(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeColumns(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + /// /// Returns the conjugate transpose of this matrix. /// diff --git a/src/Numerics/LinearAlgebra/Double/Matrix.cs b/src/Numerics/LinearAlgebra/Double/Matrix.cs index 669197cf..2285e5bc 100644 --- a/src/Numerics/LinearAlgebra/Double/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Double/Matrix.cs @@ -98,6 +98,104 @@ namespace MathNet.Numerics.LinearAlgebra.Double return Math.Sqrt(norm); } + /// + /// 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) + /// + public override Vector RowNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(RowCount); + if (norm == 2.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Abs(x), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override Vector ColumnNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(ColumnCount); + if (norm == 2.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Abs(x), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeRows(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeColumns(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + /// /// Returns the conjugate transpose of this matrix. /// diff --git a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs index afe767a8..11fe471f 100644 --- a/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs +++ b/src/Numerics/LinearAlgebra/Matrix.Arithmetic.cs @@ -1627,50 +1627,6 @@ namespace MathNet.Numerics.LinearAlgebra } } - /// - /// Normalizes the columns of a matrix. - /// - /// The norm under which to normalize the columns under. - /// A normalized version of the matrix. - /// If the parameter p is not positive. - public Matrix NormalizeColumns(int p) - { - if (p < 1) - { - throw new ArgumentOutOfRangeException("p", Resources.ArgumentMustBePositive); - } - - var result = Build.SameAs(this); - for (var index = 0; index < ColumnCount; index++) - { - result.SetColumn(index, Column(index).Normalize(p)); - } - - return result; - } - - /// - /// Normalizes the rows of a matrix. - /// - /// The norm under which to normalize the rows under. - /// A normalized version of the matrix. - /// If the parameter p is not positive. - public Matrix NormalizeRows(int p) - { - if (p < 1) - { - throw new ArgumentOutOfRangeException("p", Resources.ArgumentMustBePositive); - } - - var ret = Build.SameAs(this); - for (var index = 0; index < RowCount; index++) - { - ret.SetRow(index, Row(index).Normalize(p)); - } - - return ret; - } - /// Calculates the induced L1 norm of this matrix. /// The maximum absolute column sum of the matrix. public abstract double L1Norm(); @@ -1694,7 +1650,29 @@ namespace MathNet.Numerics.LinearAlgebra /// The square root of the sum of the squared values. public abstract double FrobeniusNorm(); + /// + /// 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) + /// + public abstract Vector RowNorms(double norm); + /// + /// 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) + /// + public abstract Vector ColumnNorms(double norm); + + /// + /// 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) + /// + public abstract Matrix NormalizeRows(double norm); + + /// + /// 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) + /// + public abstract Matrix NormalizeColumns(double norm); #region Exceptions - possibly move elsewhere? diff --git a/src/Numerics/LinearAlgebra/Single/Matrix.cs b/src/Numerics/LinearAlgebra/Single/Matrix.cs index bbd4fe5c..ee0f66ea 100644 --- a/src/Numerics/LinearAlgebra/Single/Matrix.cs +++ b/src/Numerics/LinearAlgebra/Single/Matrix.cs @@ -98,6 +98,104 @@ namespace MathNet.Numerics.LinearAlgebra.Single return Math.Sqrt(norm); } + /// + /// 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) + /// + public override Vector RowNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(RowCount); + if (norm == 2.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Abs(x), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldRowsUnchecked(ret.Storage, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override Vector ColumnNorms(double norm) + { + if (norm <= 0.0) + { + throw new ArgumentOutOfRangeException("norm", Resources.ArgumentMustBePositive); + } + + var ret = Vector.Build.Dense(ColumnCount); + if (norm == 2.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + x*x, (x, c) => Math.Sqrt(x), ret.Storage, Zeros.AllowSkip); + } + else if (norm == 1.0) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Abs(x), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else if (double.IsPositiveInfinity(norm)) + { + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => Math.Max(s, Math.Abs(x)), (x, c) => x, ret.Storage, Zeros.AllowSkip); + } + else + { + double invnorm = 1.0/norm; + Storage.FoldColumnsUnchecked(ret.Storage, (s, x) => s + Math.Pow(Math.Abs(x), norm), (x, c) => Math.Pow(x, invnorm), ret.Storage, Zeros.AllowSkip); + } + return ret; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeRows(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + + /// + /// 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) + /// + public override sealed Matrix NormalizeColumns(double norm) + { + var norminv = ((DenseVectorStorage)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; + } + /// /// Returns the conjugate transpose of this matrix. ///