diff --git a/src/Numerics/LinearAlgebra/Vector.BCL.cs b/src/Numerics/LinearAlgebra/Vector.BCL.cs index 74a0b856..f7cdd553 100644 --- a/src/Numerics/LinearAlgebra/Vector.BCL.cs +++ b/src/Numerics/LinearAlgebra/Vector.BCL.cs @@ -258,10 +258,11 @@ namespace MathNet.Numerics.LinearAlgebra return string.Format("{0} {1}-{2}", GetType().Name, Count, typeof (T).Name); } - public string[,] ToVectorStringArray(int maxPerColumn, int maxWidth, int padding, string ellipsis, Func formatValue) + public string[,] ToVectorStringArray(int maxPerColumn, int maxCharactersWidth, int padding, string ellipsis, Func formatValue) { - maxPerColumn = Math.Max(maxPerColumn, 1); - maxWidth = Math.Max(maxWidth, 12); + // enforce minima to avoid pathetic cases + maxPerColumn = Math.Max(maxPerColumn, 3); + maxCharactersWidth = Math.Max(maxCharactersWidth, 16); var columns = new List>(); int chars = 0; @@ -272,7 +273,7 @@ namespace MathNet.Numerics.LinearAlgebra int height = Math.Min(maxPerColumn, Count - offset); var candidate = FormatCompleteColumn(offset, height, formatValue); chars += candidate.Item1 + padding; - if (chars > maxWidth) + if (chars > maxCharactersWidth && offset > 0) { break; } @@ -285,9 +286,7 @@ namespace MathNet.Numerics.LinearAlgebra // --> make the last column partial var last = columns[columns.Count - 1]; var c = last.Item2; - c[c.Length - 4] = ellipsis; - c[c.Length - 3] = ellipsis; - c[c.Length - 2] = formatValue(At(Count - 2)); + c[c.Length - 2] = ellipsis; c[c.Length - 1] = formatValue(At(Count - 1)); } @@ -353,29 +352,41 @@ namespace MathNet.Numerics.LinearAlgebra /// /// Returns a string that represents the content of this vector, column by column. /// - public string ToVectorString(int maxPerColumn, int maxWidth, string ellipsis, string columnSeparator, string rowSeparator, Func formatValue) + /// Maximum number of entries and thus lines per column. Typical value: 12; Minimum: 3. + /// Maximum number of chatacters per line over all columns. Typical value: 80; Minimum: 16. + /// Character to use to print if there is not enough space to print all entries. Typical value: "..". + /// Character to use to separate two coluns on a line. Typical value: " " (2 spaces). + /// Character to use to separate two rows/lines. Typical value: Environment.NewLine. + /// Function to provide a string for any given entry value. + public string ToVectorString(int maxPerColumn, int maxCharactersWidth, string ellipsis, string columnSeparator, string rowSeparator, Func formatValue) { return FormatStringArrayToString( - ToVectorStringArray(maxPerColumn, maxWidth, columnSeparator.Length, ellipsis, formatValue), + ToVectorStringArray(maxPerColumn, maxCharactersWidth, columnSeparator.Length, ellipsis, formatValue), columnSeparator, rowSeparator); } /// /// Returns a string that represents the content of this vector, column by column. /// - public string ToVectorString(int maxPerColumn, int maxWidth, string format = null, IFormatProvider provider = null) + /// Maximum number of entries and thus lines per column. Typical value: 12; Minimum: 3. + /// Maximum number of chatacters per line over all columns. Typical value: 80; Minimum: 16. + /// Floating point format string. Can be null. Default value: G6. + /// Format provider or culture. Can be null. + public string ToVectorString(int maxPerColumn, int maxCharactersWidth, string format = null, IFormatProvider provider = null) { if (format == null) { format = "G6"; } - return ToVectorString(maxPerColumn, maxWidth, "..", " ", Environment.NewLine, x => x.ToString(format, provider)); + return ToVectorString(maxPerColumn, maxCharactersWidth, "..", " ", Environment.NewLine, x => x.ToString(format, provider)); } /// /// Returns a string that represents the content of this vector, column by column. /// + /// Floating point format string. Can be null. Default value: G6. + /// Format provider or culture. Can be null. public string ToVectorString(string format = null, IFormatProvider provider = null) { if (format == null) @@ -387,11 +398,15 @@ namespace MathNet.Numerics.LinearAlgebra } /// - /// Returns a string that summarizes this vector. + /// Returns a string that summarizes this vector, column by column and with a type header. /// - public string ToString(int maxPerColumn, int maxColumns, string format = null, IFormatProvider provider = null) + /// Maximum number of entries and thus lines per column. Typical value: 12; Minimum: 3. + /// Maximum number of chatacters per line over all columns. Typical value: 80; Minimum: 16. + /// Floating point format string. Can be null. Default value: G6. + /// Format provider or culture. Can be null. + public string ToString(int maxPerColumn, int maxCharactersWidth, string format = null, IFormatProvider provider = null) { - return string.Concat(ToTypeString(), Environment.NewLine, ToVectorString(maxPerColumn, maxColumns, format, provider)); + return string.Concat(ToTypeString(), Environment.NewLine, ToVectorString(maxPerColumn, maxCharactersWidth, format, provider)); } /// diff --git a/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs b/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs index 2b8acb9c..ab728dbf 100644 --- a/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs +++ b/src/UnitTests/LinearAlgebraTests/Double/DenseVectorTests.cs @@ -326,7 +326,7 @@ namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double var v = Vector.Build.Dense(20); for (int i = 1; i < 25; i++) { - GC.KeepAlive(v.ToVectorString(i, 80)); + Assert.NotNull(v.ToVectorString(i, 80)); } } } diff --git a/src/UnitTests/LinearAlgebraTests/VectorToStringTests.cs b/src/UnitTests/LinearAlgebraTests/VectorToStringTests.cs new file mode 100644 index 00000000..f170735e --- /dev/null +++ b/src/UnitTests/LinearAlgebraTests/VectorToStringTests.cs @@ -0,0 +1,35 @@ +using System; +using MathNet.Numerics.LinearAlgebra; +using NUnit.Framework; + +namespace MathNet.Numerics.UnitTests.LinearAlgebraTests +{ + [TestFixture] + public class VectorToStringTests + { + Vector v1 = Vector.Build.Dense(1, i => (i + 1)*Constants.Pi); + Vector v2 = Vector.Build.Dense(2, i => (i + 1)*Constants.Pi); + Vector v100 = Vector.Build.Dense(100, i => (i + 1)*Constants.Pi); + readonly string NL = Environment.NewLine; + + [Test] + public void MinimumLimits() + { + Assert.That(v1.ToVectorString(3, 16, "G6"), Is.EqualTo("3.14159" + NL)); + Assert.That(v2.ToVectorString(3, 16, "G6"), Is.EqualTo("3.14159" + NL + "6.28319" + NL)); + Assert.That(v100.ToVectorString(3, 16, "G6"), Is.EqualTo("3.14159" + NL + " .." + NL + "314.159" + NL)); + } + + [Test] + public void GitHubIssue387() + { + Vector v = Vector.Build.DenseOfArray(new[] + { + 0.607142857142857, + 1.17857142857143 + }); + + Assert.That(v.ToVectorString(12, 12, "..", " ", "\n", x => x.ToString()), Is.EqualTo("0.607142857142857\n 1.17857142857143\n")); + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index aeecda1f..735d4a80 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -361,6 +361,7 @@ +