diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj
index ec0826ec..0d27b347 100644
--- a/src/Numerics/Numerics.csproj
+++ b/src/Numerics/Numerics.csproj
@@ -206,6 +206,7 @@
+
diff --git a/src/Numerics/Statistics/RunningStatistics.cs b/src/Numerics/Statistics/RunningStatistics.cs
new file mode 100644
index 00000000..bb5746e4
--- /dev/null
+++ b/src/Numerics/Statistics/RunningStatistics.cs
@@ -0,0 +1,240 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2014 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.
+//
+//
+// Adapted from the old DescriptiveStatistics and inspired in design
+// among others by http://www.johndcook.com/skewness_kurtosis.html
+
+using System;
+using System.Collections.Generic;
+
+namespace MathNet.Numerics.Statistics
+{
+ ///
+ /// Running statistics, allows updating by adding values,
+ /// or combining
+ ///
+ public class RunningStatistics
+ {
+ long _n;
+ double _m1;
+ double _m2;
+ double _m3;
+ double _m4;
+ double _min = Double.PositiveInfinity;
+ double _max = Double.NegativeInfinity;
+
+ public RunningStatistics()
+ {
+ }
+
+ public RunningStatistics(IEnumerable values)
+ {
+ PushRange(values);
+ }
+
+ ///
+ /// Gets the total number of samples.
+ ///
+ public long Count
+ {
+ get { return _n; }
+ }
+
+ ///
+ /// Returns the minimum value in the sample data.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ public double Minimum
+ {
+ get { return _n > 0 ? _min : double.NaN; }
+ }
+
+ ///
+ /// Returns the maximum value in the sample data.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ public double Maximum
+ {
+ get { return _n > 0 ? _max : double.NaN; }
+ }
+
+ ///
+ /// Evaluates the sample mean, an estimate of the population mean.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ public double Mean
+ {
+ get { return _n > 0 ? _m1 : double.NaN; }
+ }
+
+ ///
+ /// Estimates the unbiased population variance from the provided samples.
+ /// On a dataset of size N will use an N-1 normalizer (Bessel's correction).
+ /// Returns NaN if data has less than two entries or if any entry is NaN.
+ ///
+ public double Variance
+ {
+ get { return _n < 2 ? double.NaN : _m2/(_n - 1); }
+ }
+
+ ///
+ /// Evaluates the variance from the provided full population.
+ /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ public double PopulationVariance
+ {
+ get { return _n < 2 ? double.NaN : _m2/_n; }
+ }
+
+ ///
+ /// Estimates the unbiased population standard deviation from the provided samples.
+ /// On a dataset of size N will use an N-1 normalizer (Bessel's correction).
+ /// Returns NaN if data has less than two entries or if any entry is NaN.
+ ///
+ public double StandardDeviation
+ {
+ get { return _n < 2 ? double.NaN : Math.Sqrt(_m2/(_n - 1)); }
+ }
+
+ ///
+ /// Evaluates the standard deviation from the provided full population.
+ /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ public double PopulationStandardDeviation
+ {
+ get { return _n < 2 ? double.NaN : Math.Sqrt(_m2/_n); }
+ }
+
+ ///
+ /// Estimates the unbiased population skewness from the provided samples.
+ /// Uses a normalizer (Bessel's correction; type 2).
+ /// Returns NaN if data has less than three entries or if any entry is NaN.
+ ///
+ public double Skewness
+ {
+ get { return _n < 3 ? double.NaN : (_n*_m3*Math.Sqrt(_m2/(_n - 1))/(_m2*_m2*(_n - 2)))*(_n - 1); }
+ }
+
+ ///
+ /// Evaluates the population skewness from the full population.
+ /// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
+ /// Returns NaN if data has less than two entries or if any entry is NaN.
+ ///
+ public double PopulationSkewness
+ {
+ get { return _n < 2 ? double.NaN : _m3*Math.Sqrt(_n*(_n - 1))*Math.Sqrt(_m2/(_n - 1))/(_m2*_m2); }
+ }
+
+ ///
+ /// Estimates the unbiased population kurtosis from the provided samples.
+ /// Uses a normalizer (Bessel's correction; type 2).
+ /// Returns NaN if data has less than four entries or if any entry is NaN.
+ ///
+ public double Kurtosis
+ {
+ get { return _n < 4 ? double.NaN : ((double)_n*_n - 1)/((_n - 2)*(_n - 3))*(_n*_m4/(_m2*_m2) - 3 + 6.0/(_n + 1)); }
+ }
+
+ ///
+ /// Evaluates the population kurtosis from the full population.
+ /// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
+ /// Returns NaN if data has less than three entries or if any entry is NaN.
+ ///
+ public double PopulationKurtosis
+ {
+ get { return _n < 3 ? double.NaN : (_m4*_n - 3*_m2*_m2)/(_m2*_m2); }
+ }
+
+ ///
+ /// Update the running statistics by adding another observed sample (in-place).
+ ///
+ public void Push(double value)
+ {
+ _n++;
+ double d = value - _m1;
+ double s = d/_n;
+ double s2 = s*s;
+ double t = d*s*(_n - 1);
+
+ _m1 += s;
+ _m4 += t*s2*(_n*_n - 3*_n + 3) + 6*s2*_m2 - 4*s*_m3;
+ _m3 += t*s*(_n - 2) - 3*s*_m2;
+ _m2 += t;
+
+ if (_min > value)
+ {
+ _min = value;
+ }
+ if (_max < value)
+ {
+ _max = value;
+ }
+ }
+
+ ///
+ /// Update the running statistics by adding a sequence of observed sample (in-place).
+ ///
+ public void PushRange(IEnumerable values)
+ {
+ foreach (double value in values)
+ {
+ Push(value);
+ }
+ }
+
+ ///
+ /// Create a new running statistics over the combined samples of two existing running statistics.
+ ///
+ public static RunningStatistics Combine(RunningStatistics a, RunningStatistics b)
+ {
+ long n = a._n + b._n;
+ double d = b._m1 - a._m1;
+ double d2 = d*d;
+ double d3 = d2*d;
+ double d4 = d2*d2;
+
+ double m1 = (a._n*a._m1 + b._n*b._m1)/n;
+ double m2 = a._m2 + b._m2 + d2*a._n*b._n/n;
+ double m3 = a._m3 + b._m3 + d3*a._n*b._n*(a._n - b._n)/(n*n)
+ + 3*d3*(a._n*b._m2 - b._n*a._m2)/n;
+ double m4 = a._m4 + b._m4 + d4*a._n*b._n*(a._n*a._n - a._n*b._n + b._n*b._n)/(n*n*n)
+ + 6*d2*(a._n*a._n*b._m2 + b._n*b._n*a._m2)/(n*n) + 4*d*(a._n*b._m3 - b._n*a._m3)/n;
+
+ return new RunningStatistics { _n = n, _m1 = m1, _m2 = m2, _m3 = m3, _m4 = m4 };
+ }
+
+ public static RunningStatistics operator +(RunningStatistics a, RunningStatistics b)
+ {
+ return Combine(a, b);
+ }
+ }
+}
diff --git a/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs b/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs
new file mode 100644
index 00000000..cc8e7d03
--- /dev/null
+++ b/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs
@@ -0,0 +1,170 @@
+//
+// Math.NET Numerics, part of the Math.NET Project
+// http://numerics.mathdotnet.com
+// http://github.com/mathnet/mathnet-numerics
+// http://mathnetnumerics.codeplex.com
+//
+// Copyright (c) 2009-2014 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.
+//
+
+namespace MathNet.Numerics.UnitTests.StatisticsTests
+{
+#if !PORTABLE
+ using System.Collections.Generic;
+ using NUnit.Framework;
+ using Statistics;
+
+ ///
+ /// Running statistics tests.
+ ///
+ /// NOTE: this class is not included into Silverlight version, because it uses data from local files.
+ /// In Silverlight access to local files is forbidden, except several cases.
+ [TestFixture, Category("Statistics")]
+ public class RunningStatisticsTests
+ {
+ ///
+ /// Statistics data.
+ ///
+ readonly IDictionary _data = new Dictionary();
+
+ ///
+ /// Initializes a new instance of the DescriptiveStatisticsTests class.
+ ///
+ public RunningStatisticsTests()
+ {
+ _data.Add("lottery", new StatTestData("./data/NIST/Lottery.dat"));
+ _data.Add("lew", new StatTestData("./data/NIST/Lew.dat"));
+ _data.Add("mavro", new StatTestData("./data/NIST/Mavro.dat"));
+ _data.Add("michelso", new StatTestData("./data/NIST/Michelso.dat"));
+ _data.Add("numacc1", new StatTestData("./data/NIST/NumAcc1.dat"));
+ _data.Add("numacc2", new StatTestData("./data/NIST/NumAcc2.dat"));
+ _data.Add("numacc3", new StatTestData("./data/NIST/NumAcc3.dat"));
+ _data.Add("numacc4", new StatTestData("./data/NIST/NumAcc4.dat"));
+ _data.Add("meixner", new StatTestData("./data/NIST/Meixner.dat"));
+ }
+
+ ///
+ /// IEnumerable Double.
+ ///
+ /// Dataset name.
+ /// Digits count.
+ /// Skewness value.
+ /// Kurtosis value.
+ /// Median value.
+ /// Min value.
+ /// Max value.
+ /// Count value.
+ [TestCase("lottery", 14, -0.09333165310779, -1.19256091074856, 522.5, 4, 999, 218)]
+ [TestCase("lew", 14, -0.050606638756334, -1.49604979214447, -162, -579, 300, 200)]
+ [TestCase("mavro", 11, 0.64492948110824, -0.82052379677456, 2.0018, 2.0013, 2.0027, 50)]
+ [TestCase("michelso", 11, -0.0185388637725746, 0.33968459842539, 299.85, 299.62, 300.07, 100)]
+ [TestCase("numacc1", 15, 0, double.NaN, 10000002, 10000001, 10000003, 3)]
+ [TestCase("numacc2", 13, 0, -2.003003003003, 1.2, 1.1, 1.3, 1001)]
+ [TestCase("numacc3", 9, 0, -2.003003003003, 1000000.2, 1000000.1, 1000000.3, 1001)]
+ [TestCase("numacc4", 7, 0, -2.00300300299913, 10000000.2, 10000000.1, 10000000.3, 1001)]
+ [TestCase("meixner", 8, -0.016649617280859657, 0.8171318629552635, -0.002042931016531602, -4.825626912281697, 5.3018298664184913, 10000)]
+ public void ConsistentWithNist(string dataSet, int digits, double skewness, double kurtosis, double median, double min, double max, int count)
+ {
+ var data = _data[dataSet];
+ var stats = new RunningStatistics(data.Data);
+
+ AssertHelpers.AlmostEqualRelative(data.Mean, stats.Mean, 10);
+ AssertHelpers.AlmostEqualRelative(data.StandardDeviation, stats.StandardDeviation, digits);
+ AssertHelpers.AlmostEqualRelative(skewness, stats.Skewness, 8);
+ AssertHelpers.AlmostEqualRelative(kurtosis, stats.Kurtosis, 8);
+ Assert.AreEqual(stats.Minimum, min);
+ Assert.AreEqual(stats.Maximum, max);
+ Assert.AreEqual(stats.Count, count);
+ }
+
+ [TestCase("lottery", 1e-8, -0.09268823, -0.09333165)]
+ [TestCase("lew", 1e-8, -0.0502263, -0.05060664)]
+ [TestCase("mavro", 1e-6, 0.6254181, 0.6449295)]
+ [TestCase("michelso", 1e-8, -0.01825961, -0.01853886)]
+ [TestCase("numacc1", 1e-8, 0, 0)]
+ //[TestCase("numacc2", 1e-20, 3.254232e-15, 3.259118e-15)] TODO: accuracy
+ //[TestCase("numacc3", 1e-14, 1.747103e-09, 1.749726e-09)] TODO: accuracy
+ //[TestCase("numacc4", 1e-13, 2.795364e-08, 2.799561e-08)] TODO: accuracy
+ [TestCase("meixner", 1e-8, -0.01664712, -0.01664962)]
+ public void SkewnessConsistentWithR_e1071(string dataSet, double delta, double skewnessType1, double skewnessType2)
+ {
+ var data = _data[dataSet];
+ var stats = new RunningStatistics(data.Data);
+
+ Assert.That(stats.Skewness, Is.EqualTo(skewnessType2).Within(delta), "Skewness");
+ Assert.That(stats.PopulationSkewness, Is.EqualTo(skewnessType1).Within(delta), "PopulationSkewness");
+ }
+
+ [TestCase("lottery", -1.192781, -1.192561)]
+ [TestCase("lew", -1.48876, -1.49605)]
+ [TestCase("mavro", -0.858384, -0.8205238)]
+ [TestCase("michelso", 0.2635305, 0.3396846)]
+ [TestCase("numacc1", -1.5, double.NaN)]
+ [TestCase("numacc2", -1.999, -2.003003)]
+ [TestCase("numacc3", -1.999, -2.003003)]
+ [TestCase("numacc4", -1.999, -2.003003)]
+ [TestCase("meixner", 0.8161234, 0.8171319)]
+ public void KurtosisConsistentWithR_e1071(string dataSet, double kurtosisType1, double kurtosisType2)
+ {
+ var data = _data[dataSet];
+ var stats = new RunningStatistics(data.Data);
+
+ Assert.That(stats.Kurtosis, Is.EqualTo(kurtosisType2).Within(1e-6), "Kurtosis");
+ Assert.That(stats.PopulationKurtosis, Is.EqualTo(kurtosisType1).Within(1e-6), "PopulationKurtosis");
+ }
+
+ [Test]
+ public void ShortSequences()
+ {
+ var stats0 = new RunningStatistics(new double[0]);
+ Assert.That(stats0.Skewness, Is.NaN);
+ Assert.That(stats0.Kurtosis, Is.NaN);
+
+ var stats1 = new RunningStatistics(new[] { 1.0 });
+ Assert.That(stats1.Skewness, Is.NaN);
+ Assert.That(stats1.Kurtosis, Is.NaN);
+
+ var stats2 = new RunningStatistics(new[] { 1.0, 2.0 });
+ Assert.That(stats2.Skewness, Is.NaN);
+ Assert.That(stats2.Kurtosis, Is.NaN);
+
+ var stats3 = new RunningStatistics(new[] { 1.0, 2.0, -3.0 });
+ Assert.That(stats3.Skewness, Is.Not.NaN);
+ Assert.That(stats3.Kurtosis, Is.NaN);
+
+ var stats4 = new RunningStatistics(new[] { 1.0, 2.0, -3.0, -4.0 });
+ Assert.That(stats4.Skewness, Is.Not.NaN);
+ Assert.That(stats4.Kurtosis, Is.Not.NaN);
+ }
+
+ [Test]
+ public void ZeroVarianceSequence()
+ {
+ var stats = new RunningStatistics(new[] { 2.0, 2.0, 2.0, 2.0 });
+ Assert.That(stats.Skewness, Is.NaN);
+ Assert.That(stats.Kurtosis, Is.NaN);
+ }
+ }
+#endif
+}
diff --git a/src/UnitTests/StatisticsTests/StatisticsTests.cs b/src/UnitTests/StatisticsTests/StatisticsTests.cs
index 690afc8d..a55b6083 100644
--- a/src/UnitTests/StatisticsTests/StatisticsTests.cs
+++ b/src/UnitTests/StatisticsTests/StatisticsTests.cs
@@ -113,6 +113,9 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => StreamingStatistics.PopulationStandardDeviation(data), Throws.Exception.TypeOf());
Assert.That(() => StreamingStatistics.Covariance(data, data), Throws.Exception.TypeOf());
Assert.That(() => StreamingStatistics.PopulationCovariance(data, data), Throws.Exception.TypeOf());
+
+ Assert.That(() => new RunningStatistics(data), Throws.Exception);
+ Assert.That(() => new RunningStatistics().PushRange(data), Throws.Exception);
}
[Test]
@@ -167,6 +170,20 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => StreamingStatistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => StreamingStatistics.Covariance(data, data));
Assert.DoesNotThrow(() => StreamingStatistics.PopulationCovariance(data, data));
+
+ Assert.That(() => new RunningStatistics(data), Throws.Nothing);
+ Assert.That(() => new RunningStatistics().PushRange(data), Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Minimum, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Maximum, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Mean, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Variance, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).StandardDeviation, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Skewness, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).Kurtosis, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).PopulationVariance, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).PopulationStandardDeviation, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).PopulationSkewness, Throws.Nothing);
+ Assert.That(() => new RunningStatistics(data).PopulationKurtosis, Throws.Nothing);
}
[TestCase("lottery")]
@@ -186,6 +203,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqualRelative(data.Mean, Statistics.MeanVariance(data.Data).Item1, 14);
AssertHelpers.AlmostEqualRelative(data.Mean, ArrayStatistics.MeanVariance(data.Data).Item1, 14);
AssertHelpers.AlmostEqualRelative(data.Mean, StreamingStatistics.MeanVariance(data.Data).Item1, 14);
+ AssertHelpers.AlmostEqualRelative(data.Mean, new RunningStatistics(data.Data).Mean, 14);
}
[TestCase("lottery")]
@@ -219,6 +237,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqualRelative(data.StandardDeviation, Math.Sqrt(Statistics.MeanVariance(data.Data).Item2), digits);
AssertHelpers.AlmostEqualRelative(data.StandardDeviation, Math.Sqrt(ArrayStatistics.MeanVariance(data.Data).Item2), digits);
AssertHelpers.AlmostEqualRelative(data.StandardDeviation, Math.Sqrt(StreamingStatistics.MeanVariance(data.Data).Item2), digits);
+ AssertHelpers.AlmostEqualRelative(data.StandardDeviation, new RunningStatistics(data.Data).StandardDeviation, digits);
}
[TestCase("lottery", 14)]
@@ -245,6 +264,8 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(ArrayStatistics.Maximum(samples), Is.EqualTo(10), "Max");
Assert.That(StreamingStatistics.Minimum(samples), Is.EqualTo(-3), "Min");
Assert.That(StreamingStatistics.Maximum(samples), Is.EqualTo(10), "Max");
+ Assert.That(new RunningStatistics(samples).Minimum, Is.EqualTo(-3), "Min");
+ Assert.That(new RunningStatistics(samples).Maximum, Is.EqualTo(10), "Max");
Array.Sort(samples);
Assert.That(SortedArrayStatistics.Minimum(samples), Is.EqualTo(-3), "Min");
@@ -762,6 +783,10 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqualRelative(1e+9, StreamingStatistics.Mean(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(4d, StreamingStatistics.Variance(gaussian.Samples().Take(10000)), 0);
AssertHelpers.AlmostEqualRelative(2d, StreamingStatistics.StandardDeviation(gaussian.Samples().Take(10000)), 1);
+
+ AssertHelpers.AlmostEqualRelative(1e+9, new RunningStatistics(gaussian.Samples().Take(10000)).Mean, 10);
+ AssertHelpers.AlmostEqualRelative(4d, new RunningStatistics(gaussian.Samples().Take(10000)).Variance, 0);
+ AssertHelpers.AlmostEqualRelative(2d, new RunningStatistics(gaussian.Samples().Take(10000)).StandardDeviation, 1);
}
[TestCase("lottery")]
@@ -832,7 +857,9 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(SortedArrayStatistics.Minimum(new double[0]), Is.NaN);
Assert.That(SortedArrayStatistics.Minimum(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Minimum(new double[0]), Is.NaN);
- Assert.That(StreamingStatistics.Minimum(new[] {2d }), Is.Not.NaN);
+ Assert.That(StreamingStatistics.Minimum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(new RunningStatistics(new double[0]).Minimum, Is.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d }).Minimum, Is.Not.NaN);
}
[Test]
@@ -846,6 +873,8 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(SortedArrayStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Maximum(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
+ Assert.That(new RunningStatistics(new double[0]).Maximum, Is.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d }).Maximum, Is.Not.NaN);
}
[Test]
@@ -857,6 +886,8 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(ArrayStatistics.Mean(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Mean(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Mean(new[] { 2d }), Is.Not.NaN);
+ Assert.That(new RunningStatistics(new double[0]).Mean, Is.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d }).Mean, Is.Not.NaN);
}
[Test]
@@ -871,6 +902,8 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(StreamingStatistics.Variance(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Variance(new[] { 2d }), Is.NaN);
Assert.That(StreamingStatistics.Variance(new[] { 2d, 3d }), Is.Not.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d }).Variance, Is.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d, 3d }).Variance, Is.Not.NaN);
}
[Test]
@@ -885,6 +918,8 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(StreamingStatistics.PopulationVariance(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.PopulationVariance(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.PopulationVariance(new[] { 2d, 3d }), Is.Not.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d }).PopulationVariance, Is.NaN);
+ Assert.That(new RunningStatistics(new[] { 2d, 3d }).PopulationVariance, Is.Not.NaN);
}
///
@@ -911,6 +946,9 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.AreEqual(21.578697, a.Variance(), 1e-5);
Assert.AreEqual(21.578231, a.PopulationVariance(), 1e-5);
+
+ Assert.AreEqual(21.578697, new RunningStatistics(a).Variance, 1e-5);
+ Assert.AreEqual(21.578231, new RunningStatistics(a).PopulationVariance, 1e-5);
}
[Test]
diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj
index 9dba09e9..7cf5ee5e 100644
--- a/src/UnitTests/UnitTests.csproj
+++ b/src/UnitTests/UnitTests.csproj
@@ -392,6 +392,7 @@
+