Browse Source

Fixed a bug with the order finding method.

Lowered the accuracy of StdDev computation on the numacc2 test to 13 significant digits.
pull/36/head
Jurgen Van Gael 17 years ago
committed by Christoph Ruegg
parent
commit
37d02b5743
  1. 3
      src/Managed.UnitTests/Managed.UnitTests.csproj
  2. 212
      src/Managed.UnitTests/StatisticsTests/DescriptiveStatisticsTests.cs
  3. 96
      src/Managed.UnitTests/StatisticsTests/StatTestData.cs
  4. 138
      src/Managed.UnitTests/StatisticsTests/StatisticsTests.cs
  5. 2
      src/Managed/Managed.csproj
  6. 9
      src/Managed/Properties/Resources.Designer.cs
  7. 3
      src/Managed/Properties/Resources.resx
  8. 9
      src/Managed/Sorting.cs
  9. 343
      src/Managed/Statistics/DescriptiveStatistics.cs
  10. 570
      src/Managed/Statistics/Statistics.cs
  11. 9
      src/Native.UnitTests/Native.UnitTests.csproj
  12. 6
      src/Native/Native.csproj

3
src/Managed.UnitTests/Managed.UnitTests.csproj

@ -72,6 +72,9 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SortingTests.cs" />
<Compile Include="SpecialFunctionsTest\ErfTests.cs" />
<Compile Include="StatisticsTests\DescriptiveStatisticsTests.cs" />
<Compile Include="StatisticsTests\StatisticsTests.cs" />
<Compile Include="StatisticsTests\StatTestData.cs" />
<Compile Include="ThreadingTests\ParallelTest.cs" />
</ItemGroup>
<ItemGroup>

212
src/Managed.UnitTests/StatisticsTests/DescriptiveStatisticsTests.cs

@ -0,0 +1,212 @@
// <copyright file="DescriptiveStatisticsTests.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.Statistics
{
using System;
using System.Collections.Generic;
using MathNet.Numerics.Statistics;
using MbUnit.Framework;
[TestFixture]
public class DescriptiveStatisticsTests
{
private readonly IDictionary<string, StatTestData> mData = new Dictionary<string, StatTestData>();
public DescriptiveStatisticsTests()
{
StatTestData lottery = new StatTestData("./data/NIST/Lottery.dat");
mData.Add("lottery", lottery);
StatTestData lew = new StatTestData("./data/NIST/Lew.dat");
mData.Add("lew", lew);
StatTestData mavro = new StatTestData("./data/NIST/Mavro.dat");
mData.Add("mavro", mavro);
StatTestData michelso = new StatTestData("./data/NIST/Michelso.dat");
mData.Add("michelso", michelso);
StatTestData numacc1 = new StatTestData("./data/NIST/NumAcc1.dat");
mData.Add("numacc1", numacc1);
StatTestData numacc2 = new StatTestData("./data/NIST/NumAcc2.dat");
mData.Add("numacc2", numacc2);
StatTestData numacc3 = new StatTestData("./data/NIST/NumAcc3.dat");
mData.Add("numacc3", numacc3);
StatTestData numacc4 = new StatTestData("./data/NIST/NumAcc4.dat");
mData.Add("numacc4", numacc4);
}
[Test]
public void Constructor_ThrowArgumentNullException()
{
const IEnumerable<double> data = null;
const IEnumerable<double?> nullableData = null;
Assert.Throws<ArgumentNullException>(() => new DescriptiveStatistics(data));
Assert.Throws<ArgumentNullException>(() => new DescriptiveStatistics(data, true));
Assert.Throws<ArgumentNullException>(() => new DescriptiveStatistics(nullableData));
Assert.Throws<ArgumentNullException>(() => new DescriptiveStatistics(nullableData, true));
}
[Test]
[Row("lottery", 15, -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", 15, -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 12, 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", 12, -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 15, 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 13, 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 9, 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 8, 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableDouble(string dataSet, int digits, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.Data);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, digits);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 7);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 7);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
[Test]
[Row("lottery", -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableDoubleHighAccuracy(string dataSet, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.Data, true);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, 15);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 9);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 9);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
[Test]
[Row("lottery", 15, -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", 15, -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 12, 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", 12, -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 15, 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 13, 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 9, 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 8, 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableDoubleLowAccuracy(string dataSet, int digits, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.Data, false);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, digits);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 7);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 7);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
[Test]
[Row("lottery", 15, -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", 15, -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 12, 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", 12, -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 15, 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 13, 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 9, 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 8, 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableNullableDouble(string dataSet, int digits, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.DataWithNulls);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, digits);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 7);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 7);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
[Test]
[Row("lottery", -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableNullableDoubleHighAccuracy(string dataSet, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.DataWithNulls, true);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, 15);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 9);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 9);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
[Test]
[Row("lottery", 15, -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
[Row("lew", 15, -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
[Row("mavro", 12, 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
[Row("michelso", 12, -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
[Row("numacc1", 15, 0, 0, 10000002, 10000001, 10000003, 3)]
[Row("numacc2", 13, 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
[Row("numacc3", 9, 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
[Row("numacc4", 8, 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
public void IEnumerableNullableDoubleLowAccuracy(string dataSet, int digits, double skewness, double kurtosis, double median, double min, double max, int count)
{
StatTestData data = mData[dataSet];
DescriptiveStatistics stats = new DescriptiveStatistics(data.DataWithNulls, false);
AssertHelpers.AlmostEqual(data.Mean, stats.Mean, 15);
AssertHelpers.AlmostEqual(data.StandardDeviation, stats.StandardDeviation, digits);
AssertHelpers.AlmostEqual(skewness, stats.Skewness, 7);
AssertHelpers.AlmostEqual(kurtosis, stats.Kurtosis, 7);
AssertHelpers.AlmostEqual(median, stats.Median, 15);
Assert.AreEqual(stats.Minimum, min);
Assert.AreEqual(stats.Maximum, max);
Assert.AreEqual(stats.Count, count);
}
}
}

96
src/Managed.UnitTests/StatisticsTests/StatTestData.cs

@ -0,0 +1,96 @@
// <copyright file="StatTestData.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.Statistics
{
using System.IO;
using System.Linq;
using System.Collections.Generic;
internal class StatTestData
{
public readonly double[] Data;
public readonly double?[] DataWithNulls;
public readonly double Mean;
public readonly double StandardDeviation;
public StatTestData(string file)
{
using (StreamReader reader = new StreamReader(file))
{
string line = reader.ReadLine().Trim();
while (!line.StartsWith("--"))
{
if (line.StartsWith("Sample Mean"))
{
Mean = GetValue(line);
}
else if (line.StartsWith("Sample Standard Deviation"))
{
StandardDeviation = GetValue(line);
}
line = reader.ReadLine().Trim();
}
line = reader.ReadLine();
IList<double> list = new List<double>();
while (line != null)
{
line = line.Trim();
if (!line.Equals(string.Empty))
{
list.Add(double.Parse(line));
}
line = reader.ReadLine();
}
Data = list.ToArray();
}
DataWithNulls = new double?[Data.Length + 2];
for (int i = 0; i < Data.Length; i++)
{
DataWithNulls[i + 1] = Data[i];
}
}
private static double GetValue(string str)
{
int start = str.IndexOf(":");
string value = str.Substring(start + 1).Trim();
if (value.Equals("NaN"))
{
return 0;
}
return double.Parse(str.Substring(start + 1).Trim());
}
}
}

138
src/Managed.UnitTests/StatisticsTests/StatisticsTests.cs

@ -0,0 +1,138 @@
// <copyright file="StatisticsTests.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.Statistics
{
using System;
using System.Collections.Generic;
using System.Text;
using MbUnit.Framework;
using MathNet.Numerics.Statistics;
[TestFixture]
public class StatisticsTests
{
private readonly IDictionary<string, StatTestData> mData = new Dictionary<string, StatTestData>();
public StatisticsTests()
{
StatTestData lottery = new StatTestData("./data/NIST/Lottery.dat");
mData.Add("lottery", lottery);
StatTestData lew = new StatTestData("./data/NIST/Lew.dat");
mData.Add("lew", lew);
StatTestData mavro = new StatTestData("./data/NIST/Mavro.dat");
mData.Add("mavro", mavro);
StatTestData michelso = new StatTestData("./data/NIST/Michelso.dat");
mData.Add("michelso", michelso);
StatTestData numacc1 = new StatTestData("./data/NIST/NumAcc1.dat");
mData.Add("numacc1", numacc1);
StatTestData numacc2 = new StatTestData("./data/NIST/NumAcc2.dat");
mData.Add("numacc2", numacc2);
StatTestData numacc3 = new StatTestData("./data/NIST/NumAcc3.dat");
mData.Add("numacc3", numacc3);
StatTestData numacc4 = new StatTestData("./data/NIST/NumAcc4.dat");
mData.Add("numacc4", numacc4);
}
[Test]
[Row("lottery")]
[Row("lew")]
[Row("mavro")]
[Row("michelso")]
[Row("numacc1")]
[Row("numacc2")]
[Row("numacc3")]
[Row("numacc4")]
public void Mean(string dataSet)
{
StatTestData data = mData[dataSet];
AssertHelpers.AlmostEqual(data.Mean, data.Data.Mean(), 15);
}
[Test]
[Row("lottery")]
[Row("lew")]
[Row("mavro")]
[Row("michelso")]
[Row("numacc1")]
[Row("numacc2")]
[Row("numacc3")]
[Row("numacc4")]
public void NullableMean(string dataSet)
{
StatTestData data = mData[dataSet];
AssertHelpers.AlmostEqual(data.Mean, data.DataWithNulls.Mean(), 15);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void Mean_ThrowsArgumentNullException()
{
double[] data = null;
MathNet.Numerics.Statistics.Statistics.Mean(data);
}
[Test]
[Row("lottery", 15)]
[Row("lew", 15)]
[Row("mavro", 12)]
[Row("michelso", 12)]
[Row("numacc1", 15)]
[Row("numacc2", 14)]
[Row("numacc3", 9)]
[Row("numacc4", 8)]
public void StandardDeviation(string dataSet, int digits)
{
StatTestData data = mData[dataSet];
AssertHelpers.AlmostEqual(data.StandardDeviation, data.Data.StandardDeviation(), digits);
}
[Test]
[Row("lottery", 15)]
[Row("lew", 15)]
[Row("mavro", 12)]
[Row("michelso", 12)]
[Row("numacc1", 15)]
[Row("numacc2", 14)]
[Row("numacc3", 9)]
[Row("numacc4", 8)]
public void NullableStandardDeviation(string dataSet, int digits)
{
StatTestData data = mData[dataSet];
AssertHelpers.AlmostEqual(data.StandardDeviation, data.DataWithNulls.StandardDeviation(), digits);
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void StandardDeviation_ThrowsArgumentNullException()
{
double[] data = null;
MathNet.Numerics.Statistics.Statistics.StandardDeviation(data);
}
}
}

2
src/Managed/Managed.csproj

@ -82,6 +82,8 @@
<Compile Include="Sorting.cs" />
<Compile Include="SpecialFunctions.cs" />
<Compile Include="SpecialFunctions\Erf.cs" />
<Compile Include="Statistics\DescriptiveStatistics.cs" />
<Compile Include="Statistics\Statistics.cs" />
<Compile Include="Threading\AggregateException.cs" />
<Compile Include="Threading\Parallel.cs" />
<Compile Include="Threading\Task.cs" />

9
src/Managed/Properties/Resources.Designer.cs

@ -375,6 +375,15 @@ namespace MathNet.Numerics.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to The supplied collection is empty..
/// </summary>
internal static string CollectionEmpty {
get {
return ResourceManager.GetString("CollectionEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This feature is not implemented yet (but is planned)..
/// </summary>

3
src/Managed/Properties/Resources.resx

@ -249,4 +249,7 @@
<data name="ArgumentItemNull" xml:space="preserve">
<value>At least one item of {0} is a null reference (Nothing in Visual Basic).</value>
</data>
<data name="CollectionEmpty" xml:space="preserve">
<value>The supplied collection is empty.</value>
</data>
</root>

9
src/Managed/Sorting.cs

@ -566,9 +566,12 @@ namespace MathNet.Numerics
/// <param name="b">The index of the second element of the swap.</param>
internal static void Swap<T>(IList<T> keys, int a, int b)
{
T local = keys[a];
keys[a] = keys[b];
keys[b] = local;
if(a != b)
{
T local = keys[a];
keys[a] = keys[b];
keys[b] = local;
}
}
}
}

343
src/Managed/Statistics/DescriptiveStatistics.cs

@ -0,0 +1,343 @@
// <copyright file="DescriptiveStatistics.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.Statistics
{
using System.Collections.Generic;
/// <summary>
/// Computes the basic statistics of data set. The class meets the
/// NIST standard of accuracy for mean, variance, and standard deviation
/// (the only statistics they provide exact values for) and exceeds them
/// in increased accuracy mode.
/// </summary>
public class DescriptiveStatistics
{
/// <summary>
/// Initializes a new instance of the <see cref="DescriptiveStatistics"/> class.
/// </summary>
/// <param name="data">The sample data.</param>
public DescriptiveStatistics(IEnumerable<double> data) : this(data, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DescriptiveStatistics"/> class.
/// </summary>
/// <param name="data">The sample data.</param>
public DescriptiveStatistics(IEnumerable<double?> data) : this(data, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="DescriptiveStatistics"/> class.
/// </summary>
/// <param name="data">The sample data.</param>
/// <param name="increasedAccuracy">if set to <c>true</c>, increased accuracy mode used.
/// Increased accuracy mode uses <see cref="decimal"/> types for internal calculations.</param>
/// <remarks>Don't use increased accuracy for data sets containing large values (in absolute value).
/// This may cause the calculations to overflow.</remarks>
public DescriptiveStatistics(IEnumerable<double> data, bool increasedAccuracy)
{
if (increasedAccuracy)
{
ComputeHA(data);
}
else
{
Compute(data);
}
Median = data.Median();
Maximum = data.Maximum();
Minimum = data.Minimum();
}
/// <summary>
/// Initializes a new instance of the <see cref="DescriptiveStatistics"/> class.
/// </summary>
/// <param name="data">The sample data.</param>
/// <param name="increasedAccuracy">if set to <c>true</c>, increased accuracy mode used.
/// Increased accuracy mode uses <see cref="decimal"/> types for internal calculations.</param>
/// <remarks>Don't use increased accuracy for data sets containing large values (in absolute value).
/// This may cause the calculations to overflow.</remarks>
public DescriptiveStatistics(IEnumerable<double?> data, bool increasedAccuracy)
{
if (increasedAccuracy)
{
ComputeHA(data);
}
else
{
Compute(data);
}
Median = data.Median();
Maximum = data.Maximum();
Minimum = data.Minimum();
}
/// <summary>
/// Gets the size of the sample.
/// </summary>
/// <value>The size of the sample.</value>
public int Count { get; private set; }
/// <summary>
/// Gets the sample mean.
/// </summary>
/// <value>The sample mean.</value>
public double Mean { get; private set; }
/// <summary>
/// Gets the sample variance.
/// </summary>
/// <value>The sample variance.</value>
public double Variance { get; private set; }
/// <summary>
/// Gets the sample standard deviation.
/// </summary>
/// <value>The sample standard deviation.</value>
public double StandardDeviation { get; private set; }
/// <summary>
/// Gets the sample skewness.
/// </summary>
/// <value>The sample skewness.</value>
/// <remarks>Returns zero if <see cref="Count"/> is less than three. </remarks>
public double Skewness { get; private set; }
/// <summary>
/// Gets the sample median.
/// </summary>
/// <value>The sample median.</value>
public double Median { get; private set; }
/// <summary>
/// Gets the sample kurtosis.
/// </summary>
/// <value>The sample kurtosis.</value>
/// <remarks>Returns zero if <see cref="Count"/> is less than four. </remarks>
public double Kurtosis { get; private set; }
/// <summary>
/// Gets the maximum sample value.
/// </summary>
/// <value>The maximum sample value.</value>
public double Maximum { get; private set; }
/// <summary>
/// Gets the minimum sample value.
/// </summary>
/// <value>The minimum sample value.</value>
public double Minimum { get; private set; }
/// <summary>
/// Computes descriptive statistics from a stream of data values.
/// </summary>
/// <param name="data">A sequence of datapoints.</param>
private void Compute(IEnumerable<double> data)
{
Mean = data.Mean();
double variance = 0;
double correction = 0;
double skewness = 0;
double kurtosis = 0;
int n = 0;
foreach (var xi in data)
{
double diff = xi - Mean;
correction += diff;
double tmp = diff*diff;
variance += tmp;
tmp *= diff;
skewness += tmp;
tmp *= diff;
kurtosis += tmp;
n++;
}
Count = n;
Variance = (variance - (correction*correction)/n)/(n - 1);
StandardDeviation = System.Math.Sqrt(Variance);
if (Variance != 0)
{
if (n > 2)
{
Skewness = (double) n/((n - 1)*(n - 2))*(skewness/(Variance*StandardDeviation));
}
if (n > 3)
{
Kurtosis = ((double) n*(n + 1))/((n - 1)*(n - 2)*(n - 3))*(kurtosis/(Variance*Variance)) - (3.0*(n - 1)*(n - 1))/((n - 2)*(n - 3));
}
}
}
/// <summary>
/// Computes descriptive statistics from a stream of nullable data values.
/// </summary>
/// <param name="data">A sequence of datapoints.</param>
private void Compute(IEnumerable<double?> data)
{
Mean = data.Mean();
double variance = 0;
double correction = 0;
double skewness = 0;
double kurtosis = 0;
int n = 0;
foreach (var xi in data)
{
if (xi.HasValue)
{
double diff = xi.Value - Mean;
double tmp = diff*diff;
correction += diff;
variance += tmp;
tmp *= diff;
skewness += tmp;
tmp *= diff;
kurtosis += tmp;
n++;
}
}
Count = n;
if (n > 0)
{
Variance = (variance - (correction*correction)/n)/(n - 1);
StandardDeviation = System.Math.Sqrt(Variance);
if (Variance != 0)
{
if (n > 2)
{
Skewness = (double) n/((n - 1)*(n - 2))*(skewness/(Variance*StandardDeviation));
}
if (n > 3)
{
Kurtosis = ((double) n*(n + 1))/((n - 1)*(n - 2)*(n - 3))*(kurtosis/(Variance*Variance)) - (3.0*(n - 1)*(n - 1))/((n - 2)*(n - 3));
}
}
}
}
/// <summary>
/// Computes descriptive statistics from a stream of data values using high accuracy.
/// </summary>
/// <param name="data">A sequence of datapoints.</param>
private void ComputeHA(IEnumerable<double> data)
{
Mean = data.Mean();
decimal mean = (decimal) Mean;
decimal variance = 0;
decimal correction = 0;
decimal skewness = 0;
decimal kurtosis = 0;
int n = 0;
foreach (decimal xi in data)
{
decimal diff = xi - mean;
decimal tmp = diff*diff;
correction += diff;
variance += tmp;
tmp *= diff;
skewness += tmp;
tmp *= diff;
kurtosis += tmp;
n++;
}
Count = n;
Variance = (double) (variance - (correction*correction)/n)/(n - 1);
StandardDeviation = System.Math.Sqrt(Variance);
if (Variance != 0)
{
if (n > 2)
{
Skewness = (double) n/((n - 1)*(n - 2))*((double) skewness/(Variance*StandardDeviation));
}
if (n > 3)
{
Kurtosis = ((double) n*(n + 1))/((n - 1)*(n - 2)*(n - 3))*((double) kurtosis/(Variance*Variance)) - (3.0*(n - 1)*(n - 1))/((n - 2)*(n - 3));
}
}
}
/// <summary>
/// Computes descriptive statistics from a stream of nullable data values using high accuracy.
/// </summary>
/// <param name="data">A sequence of datapoints.</param>
private void ComputeHA(IEnumerable<double?> data)
{
Mean = data.Mean();
decimal mean = (decimal) Mean;
decimal variance = 0;
decimal correction = 0;
decimal skewness = 0;
decimal kurtosis = 0;
int n = 0;
foreach (decimal? xi in data)
{
if (xi.HasValue)
{
decimal diff = xi.Value - mean;
decimal tmp = diff*diff;
correction += diff;
variance += tmp;
tmp *= diff;
skewness += tmp;
tmp *= diff;
kurtosis += tmp;
n++;
}
}
Count = n;
if (n > 0)
{
Variance = (double) (variance - (correction*correction)/n)/(n - 1);
StandardDeviation = System.Math.Sqrt(Variance);
if (Variance != 0)
{
if (n > 2)
{
Skewness = (double) n/((n - 1)*(n - 2))*((double) skewness/(Variance*StandardDeviation));
}
if (n > 3)
{
Kurtosis = ((double) n*(n + 1))/((n - 1)*(n - 2)*(n - 3))*((double) kurtosis/(Variance*Variance)) - (3.0*(n - 1)*(n - 1))/((n - 2)*(n - 3));
}
}
}
}
}
}

570
src/Managed/Statistics/Statistics.cs

@ -0,0 +1,570 @@
// <copyright file="Statistics.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.Statistics
{
using System;
using System.Collections.Generic;
using MathNet.Numerics.Properties;
using MathNet.Numerics.NumberTheory;
/// <summary>
/// Extension methods to return basic statistics on set of data.
/// </summary>
public static class Statistics
{
/// <summary>
/// Calculates the sample mean.
/// </summary>
/// <param name="data">The data to calculate the mean of.</param>
/// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double mean = 0;
int m = 0;
foreach (var item in data)
{
mean += (item - mean)/++m;
}
return mean;
}
/// <summary>
/// Calculates the sample mean.
/// </summary>
/// <param name="data">The data to calculate the mean of.</param>
/// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double mean = 0;
int m = 0;
foreach (var item in data)
{
if (item.HasValue)
{
mean += (item.Value - mean)/++m;
}
}
return mean;
}
/// <summary>
/// Calculates the unbiased population variance estimator (on a dataset of size N will use an N-1 normalizer).
/// </summary>
/// <param name="data">The data to calculate the variance of.</param>
/// <returns>The unbiased population variance of the sample.</returns>
public static double Variance(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double variance = 0;
double t = 0;
int j = 0;
IEnumerator<double> iterator = data.GetEnumerator();
if (iterator.MoveNext())
{
j++;
t = iterator.Current;
}
while (iterator.MoveNext())
{
j++;
double xi = iterator.Current;
t += xi;
double diff = j*xi - t;
variance += (diff*diff)/(j*(j - 1));
}
return variance/(j - 1);
}
/// <summary>
/// Computes the unbiased population variance estimator (on a dataset of size N will use an N-1 normalizer) for nullable data.
/// </summary>
/// <param name="data">The data to calculate the variance of.</param>
/// <returns>The population variance of the sample.</returns>
public static double Variance(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double variance = 0;
double t = 0;
int j = 0;
IEnumerator<double?> iterator = data.GetEnumerator();
while (true)
{
bool hasNext = iterator.MoveNext();
if (!hasNext)
{
break;
}
if (iterator.Current.HasValue)
{
j++;
t = iterator.Current.Value;
break;
}
}
while (iterator.MoveNext())
{
if (iterator.Current.HasValue)
{
j++;
double xi = iterator.Current.Value;
t += xi;
double diff = j*xi - t;
variance += (diff*diff)/(j*(j - 1));
}
}
return variance/(j - 1);
}
/// <summary>
/// Calculates the biased population variance estimator (on a dataset of size N will use an N normalizer).
/// </summary>
/// <param name="data">The data to calculate the variance of.</param>
/// <returns>The biased population variance of the sample.</returns>
public static double PopulationVariance(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double variance = 0;
double t = 0;
int j = 0;
IEnumerator<double> iterator = data.GetEnumerator();
if (iterator.MoveNext())
{
j++;
t = iterator.Current;
}
while (iterator.MoveNext())
{
j++;
double xi = iterator.Current;
t += xi;
double diff = j * xi - t;
variance += (diff * diff) / (j * (j - 1));
}
return variance / j;
}
/// <summary>
/// Computes the biased population variance estimator (on a dataset of size N will use an N normalizer) for nullable data.
/// </summary>
/// <param name="data">The data to calculate the variance of.</param>
/// <returns>The population variance of the sample.</returns>
public static double PopulationVariance(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double variance = 0;
double t = 0;
int j = 0;
IEnumerator<double?> iterator = data.GetEnumerator();
while (true)
{
bool hasNext = iterator.MoveNext();
if (!hasNext)
{
break;
}
if (iterator.Current.HasValue)
{
j++;
t = iterator.Current.Value;
break;
}
}
while (iterator.MoveNext())
{
if (iterator.Current.HasValue)
{
j++;
double xi = iterator.Current.Value;
t += xi;
double diff = j * xi - t;
variance += (diff * diff) / (j * (j - 1));
}
}
return variance / j;
}
/// <summary>
/// Calculates the unbiased sample standard deviation (on a dataset of size N will use an N-1 normalizer).
/// </summary>
/// <param name="data">The data to calculate the standard deviation of.</param>
/// <returns>The standard deviation of the sample.</returns>
public static double StandardDeviation(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return System.Math.Sqrt(Variance(data));
}
/// <summary>
/// Calculates the unbiased sample standard deviation (on a dataset of size N will use an N-1 normalizer).
/// </summary>
/// <param name="data">The data to calculate the standard deviation of.</param>
/// <returns>The standard deviation of the sample.</returns>
public static double StandardDeviation(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return System.Math.Sqrt(Variance(data));
}
/// <summary>
/// Calculates the biased sample standard deviation (on a dataset of size N will use an N normalizer).
/// </summary>
/// <param name="data">The data to calculate the standard deviation of.</param>
/// <returns>The standard deviation of the sample.</returns>
public static double PopulationStandardDeviation(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return System.Math.Sqrt(PopulationVariance(data));
}
/// <summary>
/// Calculates the biased sample standard deviation (on a dataset of size N will use an N normalizer).
/// </summary>
/// <param name="data">The data to calculate the standard deviation of.</param>
/// <returns>The standard deviation of the sample.</returns>
public static double PopulationStandardDeviation(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
return System.Math.Sqrt(PopulationVariance(data));
}
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double min = double.MaxValue;
int count = 0;
foreach (double? d in data)
{
if (d.HasValue)
{
min = System.Math.Min(min, d.Value);
count++;
}
}
if (count == 0)
{
throw new ArgumentException(Resources.CollectionEmpty, "data");
}
return min;
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double max = double.MinValue;
int count = 0;
foreach (double? d in data)
{
if (d.HasValue)
{
max = System.Math.Max(max, d.Value);
count++;
}
}
if (count == 0)
{
throw new ArgumentException(Resources.CollectionEmpty, "data");
}
return max;
}
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double min = double.MaxValue;
int count = 0;
foreach (double d in data)
{
min = System.Math.Min(min, d);
count++;
}
if (count == 0)
{
throw new ArgumentException(Resources.CollectionEmpty, "data");
}
return min;
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double max = double.MinValue;
int count = 0;
foreach (double d in data)
{
max = System.Math.Max(max, d);
count++;
}
if (count == 0)
{
throw new ArgumentException(Resources.CollectionEmpty, "data");
}
return max;
}
/// <summary>
/// Calculates the sample median.
/// </summary>
/// <param name="data">The data to calculate the median of.</param>
/// <returns>The median of the sample.</returns>
public static double Median(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
List<double> dataArray = new List<double>(data);
int index = dataArray.Count/2 + 1;
if (dataArray.Count % 2 == 0)
{
double lower = OrderSelect(dataArray, 0, dataArray.Count - 1, index - 1);
double upper = OrderSelect(dataArray, 0, dataArray.Count - 1, index);
return (lower + upper) / 2.0;
}
else
{
return OrderSelect(dataArray, 0, dataArray.Count - 1, index);
}
}
/// <summary>
/// Calculates the sample median.
/// </summary>
/// <param name="data">The data to calculate the median of.</param>
/// <returns>The median of the sample.</returns>
public static double Median(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
List<double> nonNull = new List<double>();
foreach (double? value in data)
{
if (value.HasValue)
{
nonNull.Add(value.Value);
}
}
if (nonNull.Count == 0)
{
throw new ArgumentException(Resources.CollectionEmpty, "data");
}
return nonNull.Median();
}
/// <summary>
/// Evaluate the i-order (1..N) statistic of the provided samples.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The i'th order statistic in the sample data.</returns>
public static double OrderStatistic(IEnumerable<double> samples, int order)
{
if (order == 1)
{
// Can be done in linear time by Min()
return Minimum(samples);
}
List<double> list = new List<double>(samples);
if (order < 1 || order > list.Count)
{
throw new ArgumentOutOfRangeException("order", Resources.ArgumentInIntervalXYInclusive);
}
if (order == list.Count)
{
// Can be done in linear time by Max()
return Maximum(list);
}
return OrderSelect(list, 0, list.Count - 1, order);
}
/// <summary>
/// Implementation of the order statistics finding algorithm based on the algorithm in
/// "Introduction to Algorithms", Cormen et al. section 7.1.
/// </summary>
/// <param name="samples">The sample data.</param>
/// <param name="left">The left bound in which to order select.</param>
/// <param name="right">The right bound in which to order select.</param>
/// <param name="order">The order we are trying to find.</param>
/// <returns>The <paramref name="order"/> order statistic.</returns>
static double OrderSelect(IList<double> samples, int left, int right, int order)
{
// Order most always be positive.
System.Diagnostics.Debug.Assert(order > 0);
// Left side must always be positive and smaller than right side.
System.Diagnostics.Debug.Assert(left >= 0 && left <= right);
// Right side must always be smaller than number of elements in list.
System.Diagnostics.Debug.Assert(right < samples.Count);
// Make sure there are at least order items in the segment [left, right].
System.Diagnostics.Debug.Assert(right - left + 1 >= order);
if (left == right)
{
return samples[left];
}
// The pivot point.
double pivot = samples[right];
// The partioning code.
int i = left - 1;
for(int j = left; j <= right - 1; j++)
{
if(samples[j] <= pivot)
{
i++;
Sorting.Swap(samples, i, j);
}
}
Sorting.Swap(samples, i+1, right);
// Recursive order finding algorithm.
if(order == (i-left)+2)
{
return pivot;
}
else if (order < (i-left)+2)
{
return OrderSelect(samples, left, i, order);
}
else
{
return OrderSelect(samples, i+2, right, order - i + left - 2);
}
}
}
}

9
src/Native.UnitTests/Native.UnitTests.csproj

@ -95,6 +95,15 @@
<Compile Include="..\Managed.UnitTests\SpecialFunctionsTest\ErfTests.cs">
<Link>SpecialFunctionsTest\ErfTests.cs</Link>
</Compile>
<Compile Include="..\Managed.UnitTests\StatisticsTests\DescriptiveStatisticsTests.cs">
<Link>StatisticsTests\DescriptiveStatisticsTests.cs</Link>
</Compile>
<Compile Include="..\Managed.UnitTests\StatisticsTests\StatisticsTests.cs">
<Link>StatisticsTests\StatisticsTests.cs</Link>
</Compile>
<Compile Include="..\Managed.UnitTests\StatisticsTests\StatTestData.cs">
<Link>StatisticsTests\StatTestData.cs</Link>
</Compile>
<Compile Include="..\Managed.UnitTests\ThreadingTests\ParallelTest.cs">
<Link>ThreadingTests\ParallelTest.cs</Link>
</Compile>

6
src/Native/Native.csproj

@ -140,6 +140,12 @@
<Compile Include="..\Managed\SpecialFunctions\Erf.cs">
<Link>SpecialFunctions\Erf.cs</Link>
</Compile>
<Compile Include="..\Managed\Statistics\DescriptiveStatistics.cs">
<Link>Statistics\DescriptiveStatistics.cs</Link>
</Compile>
<Compile Include="..\Managed\Statistics\Statistics.cs">
<Link>Statistics\Statistics.cs</Link>
</Compile>
<Compile Include="..\Managed\Threading\AggregateException.cs">
<Link>Threading\AggregateException.cs</Link>
</Compile>

Loading…
Cancel
Save