Browse Source

globalization: double dense vector parsing

Signed-off-by: Christoph Ruegg <git@cdrnet.ch>
la-knuth
Christoph Ruegg 17 years ago
parent
commit
61cb43ed81
  1. 2
      src/MathNet.Numerics.4.5.resharper
  2. 163
      src/Numerics/LinearAlgebra/Double/DenseVector.cs
  3. 16
      src/Numerics/LinearAlgebra/Double/Vector.cs
  4. 2
      src/Numerics/Properties/Resources.Designer.cs
  5. 2
      src/Numerics/Properties/Resources.resx
  6. 6
      src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs
  7. 131
      src/UnitTests/LinearAlgebraTests/Double/DenseVectorTest.TextHandling.cs
  8. 3
      src/UnitTests/UnitTests.csproj

2
src/MathNet.Numerics.4.5.resharper

@ -33,7 +33,7 @@ Bluestein
</CommentMatch>
<CommentNotMatch />
<SuppressIfBaseHasComment>false</SuppressIfBaseHasComment>
<MaxLineLength>80</MaxLineLength>
<MaxLineLength>120</MaxLineLength>
</CommentsSettings>
<NamingConventionSettings>
<Rules>

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

@ -29,9 +29,11 @@
namespace MathNet.Numerics.LinearAlgebra.Double
{
using System;
using System.Collections.Generic;
using System.Globalization;
using Algorithms;
using Algorithms.LinearAlgebra;
using NumberTheory;
using Properties;
using Threading;
@ -627,5 +629,164 @@ namespace MathNet.Numerics.LinearAlgebra.Double
}
#endregion
#region Parse Functions
/// <summary>
/// Creates a double dense vector based on a string. The string can be in the following formats (without the
/// quotes): 'n', 'n,n,..', '(n,n,..)', '[n,n,...]', where n is a double.
/// </summary>
/// <returns>
/// A double dense vector containing the values specified by the given string.
/// </returns>
/// <param name="value">
/// The string to parse.
/// </param>
public static DenseVector Parse(string value)
{
return Parse(value, null);
}
/// <summary>
/// Creates a double dense vector based on a string. The string can be in the following formats (without the
/// quotes): 'n', 'n,n,..', '(n,n,..)', '[n,n,...]', where n is a double.
/// </summary>
/// <returns>
/// A double dense vector containing the values specified by the given string.
/// </returns>
/// <param name="value">
/// the string to parse.
/// </param>
/// <param name="formatProvider">
/// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.
/// </param>
public static DenseVector Parse(string value, IFormatProvider formatProvider)
{
if (value == null)
{
throw new ArgumentNullException(value);
}
value = value.Trim();
if (value.Length == 0)
{
throw new FormatException();
}
// strip out parens
if (value.StartsWith("(", StringComparison.Ordinal))
{
if (!value.EndsWith(")", StringComparison.Ordinal))
{
throw new FormatException();
}
value = value.Substring(1, value.Length - 2).Trim();
}
if (value.StartsWith("[", StringComparison.Ordinal))
{
if (!value.EndsWith("]", StringComparison.Ordinal))
{
throw new FormatException();
}
value = value.Substring(1, value.Length - 2).Trim();
}
// keywords
var textInfo = formatProvider.GetTextInfo();
var keywords = new[] { textInfo.ListSeparator };
// lexing
var tokens = new LinkedList<string>();
GlobalizationHelper.Tokenize(tokens.AddFirst(value), keywords, 0);
var token = tokens.First;
if (token == null || tokens.Count.IsEven())
{
throw new FormatException();
}
// parsing
var data = new double[(tokens.Count + 1) >> 1];
for (int i = 0; i < data.Length; i++)
{
if (token == null || token.Value == textInfo.ListSeparator)
{
throw new FormatException();
}
data[i] = Double.Parse(token.Value, NumberStyles.Any, formatProvider);
token = token.Next;
if(token != null)
{
token = token.Next;
}
}
return new DenseVector(data);
}
/// <summary>
/// Converts the string representation of a real dense vector to double-precision dense vector equivalent.
/// A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <param name="value">
/// A string containing a real vector to convert.
/// </param>
/// <param name="result">
/// The parsed value.
/// </param>
/// <returns>
/// If the conversion succeeds, the result will contain a complex number equivalent to value.
/// Otherwise the result will be <c>null</c>.
/// </returns>
public static bool TryParse(string value, out DenseVector result)
{
return TryParse(value, null, out result);
}
/// <summary>
/// Converts the string representation of a real dense vector to double-precision dense vector equivalent.
/// A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <param name="value">
/// A string containing a real vector to convert.
/// </param>
/// <param name="formatProvider">
/// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information about value.
/// </param>
/// <param name="result">
/// The parsed value.
/// </param>
/// <returns>
/// If the conversion succeeds, the result will contain a complex number equivalent to value.
/// Otherwise the result will be <c>null</c>.
/// </returns>
public static bool TryParse(string value, IFormatProvider formatProvider, out DenseVector result)
{
bool ret;
try
{
result = Parse(value, formatProvider);
ret = true;
}
catch (ArgumentNullException)
{
result = null;
ret = false;
}
catch (FormatException)
{
result = null;
ret = false;
}
return ret;
}
#endregion
}
}

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

@ -932,6 +932,20 @@ namespace MathNet.Numerics.LinearAlgebra.Double
#region IFormattable
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
/// <param name="formatProvider">
/// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.
/// </param>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.
/// </returns>
public string ToString(IFormatProvider formatProvider)
{
return ToString(null, formatProvider);
}
/// <summary>
/// Returns a <see cref="System.String"/> that represents this instance.
/// </summary>
@ -939,7 +953,7 @@ namespace MathNet.Numerics.LinearAlgebra.Double
/// The format to use.
/// </param>
/// <param name="formatProvider">
/// The format provider to use.
/// An <see cref="IFormatProvider"/> that supplies culture-specific formatting information.
/// </param>
/// <returns>
/// A <see cref="System.String"/> that represents this instance.

2
src/Numerics/Properties/Resources.Designer.cs

@ -223,7 +223,7 @@ namespace MathNet.Numerics.Properties {
}
/// <summary>
/// Looks up a localized string similar to Value must not be positive..
/// Looks up a localized string similar to Value must be positive..
/// </summary>
internal static string ArgumentMustBePositive {
get {

2
src/Numerics/Properties/Resources.resx

@ -259,7 +259,7 @@
<value>Value must be greater than or equal to one.</value>
</data>
<data name="ArgumentMustBePositive" xml:space="preserve">
<value>Value must not be positive.</value>
<value>Value must be positive.</value>
</data>
<data name="UserDefinedProviderNotSpecified" xml:space="preserve">
<value>A user defined provider has not been specified.</value>

6
src/UnitTests/ComplexTests/ComplexTextHandlingTest.cs → src/UnitTests/ComplexTests/ComplexTest.TextHandling.cs

@ -1,4 +1,4 @@
// <copyright file="ComplexGlobalizedTextTest.cs" company="Math.NET">
// <copyright file="ComplexTest.TextHandling.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
@ -270,7 +270,9 @@ namespace MathNet.Numerics.UnitTests.ComplexTests
[Row("1,")]
[Row(",1")]
[Row(null)]
public void TryParseReturnsFalseWhenGiveBadValueWithInvariant(string str)
[Row("()")]
[Row("( )")]
public void TryParseReturnsFalseWhenGivenBadValueWithInvariant(string str)
{
Complex z;
var ret = Complex.TryParse(str, CultureInfo.InvariantCulture, out z);

131
src/UnitTests/LinearAlgebraTests/Double/DenseVectorTest.TextHandling.cs

@ -0,0 +1,131 @@
// <copyright file="DenseVectorTest.TextHandling.cs" company="Math.NET">
// Math.NET Numerics, part of the Math.NET Project
// http://mathnet.opensourcedotnet.info
//
// Copyright (c) 2009 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
namespace MathNet.Numerics.UnitTests.LinearAlgebraTests.Double
{
using System;
using System.Globalization;
using LinearAlgebra.Double;
using MbUnit.Framework;
[TestFixture]
public class DenseVectorTextHandlingTest
{
[Test]
[Row("2", "2")]
[Row("(3)", "3")]
[Row("[1,2,3]", "1,2,3")]
[Row(" [ 1 , 2 , 3 ] ", "1,2,3")]
[Row(" [ -1 , 2 , +3 ] ", "-1,2,3")]
[Row(" [1.2,3.4 , 5.6] ", "1.2,3.4,5.6")]
public void CanParseDoubleDenseVectorsWithInvariant(string stringToParse, string expectedToString)
{
var formatProvider = CultureInfo.InvariantCulture;
DenseVector vector = DenseVector.Parse(stringToParse, formatProvider);
Assert.AreEqual(expectedToString, vector.ToString(formatProvider));
}
[Test]
[Row(" 1.2,3.4 , 5.6 ", "1.2,3.4,5.6", "en-US")]
[Row(" 1.2;3.4 ; 5.6 ", "1.2;3.4;5.6", "de-CH")]
[Row(" 1,2;3,4 ; 5,6 ", "1,2;3,4;5,6", "de-DE")]
public void CanParseDoubleDenseVectorsWithCulture(string stringToParse, string expectedToString, string culture)
{
var formatProvider = CultureInfo.GetCultureInfo(culture);
DenseVector vector = DenseVector.Parse(stringToParse, formatProvider);
Assert.AreEqual(expectedToString, vector.ToString(formatProvider));
}
[Test]
[Row("15")]
[Row("1{0}2{1}3{0}4{1}5{0}6")]
public void CanParseDoubleDenseVectors(string vectorAsString)
{
var mappedString = String.Format(
vectorAsString,
CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator,
CultureInfo.CurrentCulture.TextInfo.ListSeparator);
DenseVector vector = DenseVector.Parse(mappedString);
Assert.AreEqual(mappedString, vector.ToString());
}
[Test]
[MultipleAsserts]
public void ParseThrowsFormatExceptionIfMissingClosingParen()
{
Assert.Throws<FormatException>(() => DenseVector.Parse("(1"));
Assert.Throws<FormatException>(() => DenseVector.Parse("[1"));
}
[Test]
public void CanTryParseDoubleDenseVector()
{
var data = new[] { 1.2, 3.4, 5.6e-78 };
var text = String.Format(
"{1}{0}{2}{0}{3}",
CultureInfo.CurrentCulture.TextInfo.ListSeparator,
data[0],
data[1],
data[2]);
DenseVector vector;
var ret = DenseVector.TryParse(text, out vector);
Assert.IsTrue(ret);
AssertHelpers.AlmostEqualList(data, vector.Data, 1e-15);
ret = DenseVector.TryParse(text, CultureInfo.CurrentCulture, out vector);
Assert.IsTrue(ret);
AssertHelpers.AlmostEqualList(data, vector.Data, 1e-15);
}
[Test]
[Row(null)]
[Row("")]
[Row(",")]
[Row("1,")]
[Row(",1")]
[Row("1,2,")]
[Row(",1,2,")]
[Row("1,,2,,3")]
[Row("1e+")]
[Row("1e")]
[Row("()")]
[Row("[ ]")]
public void TryParseReturnsFalseWhenGivenBadValueWithInvariant(string str)
{
DenseVector vector;
var ret = DenseVector.TryParse(str, CultureInfo.InvariantCulture, out vector);
Assert.IsFalse(ret);
Assert.IsNull(vector);
}
}
}

3
src/UnitTests/UnitTests.csproj

@ -62,7 +62,7 @@
<Compile Include="ArgumentCheckContract.cs" />
<Compile Include="AssertHelpers.cs" />
<Compile Include="CombinatoricsTests\CombinatoricsCountingTest.cs" />
<Compile Include="ComplexTests\ComplexTextHandlingTest.cs" />
<Compile Include="ComplexTests\ComplexTest.TextHandling.cs" />
<Compile Include="ComplexTests\ComplexTest.cs" />
<Compile Include="DistributionTests\CommonDistributionTests.cs" />
<Compile Include="DistributionTests\Continuous\BetaTests.cs" />
@ -82,6 +82,7 @@
<Compile Include="InterpolationTests\InterpolationFunctionalContract.cs" />
<Compile Include="InterpolationTests\InterpolationInfrastructureContract.cs" />
<Compile Include="InterpolationTests\InterpolationFunctionalTest.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseVectorTest.TextHandling.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Arithmetic.cs" />
<Compile Include="LinearAlgebraTests\Double\VectorTests.Norm.cs" />
<Compile Include="LinearAlgebraTests\Double\DenseVectorTests.cs" />

Loading…
Cancel
Save