diff --git a/src/Numerics/Distance.cs b/src/Numerics/Distance.cs
index 05ddd6ff..2456e988 100644
--- a/src/Numerics/Distance.cs
+++ b/src/Numerics/Distance.cs
@@ -3,9 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
-//
+//
// Copyright (c) 2009-2013 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
@@ -14,10 +14,10 @@
// 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
@@ -36,6 +36,9 @@ using MathNet.Numerics.Statistics;
namespace MathNet.Numerics
{
+ ///
+ /// Metrics to measure the distance between two structures.
+ ///
public static class Distance
{
///
diff --git a/src/Numerics/Statistics/ArrayStatistics.cs b/src/Numerics/Statistics/ArrayStatistics.cs
index 5b883953..55bd3e52 100644
--- a/src/Numerics/Statistics/ArrayStatistics.cs
+++ b/src/Numerics/Statistics/ArrayStatistics.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// 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
@@ -317,6 +317,28 @@ namespace MathNet.Numerics.Statistics
return covariance/population1.Length;
}
+ ///
+ /// Estimates the root mean square (RMS) also known as quadratic mean from the unsorted data array.
+ /// Returns NaN if data is empty or any entry is NaN.
+ ///
+ /// Sample array, no sorting is assumed.
+ public static double RootMeanSquare(double[] data)
+ {
+ if (data.Length == 0)
+ {
+ return double.NaN;
+ }
+
+ double mean = 0;
+ ulong m = 0;
+ for (int i = 0; i < data.Length; i++)
+ {
+ mean += (data[i]*data[i] - mean)/++m;
+ }
+
+ return Math.Sqrt(mean);
+ }
+
///
/// Returns the order statistic (order 1..N) from the unsorted data array.
/// WARNING: Works inplace and can thus causes the data array to be reordered.
diff --git a/src/Numerics/Statistics/Statistics.cs b/src/Numerics/Statistics/Statistics.cs
index 945ad582..3fe30641 100644
--- a/src/Numerics/Statistics/Statistics.cs
+++ b/src/Numerics/Statistics/Statistics.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// 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
@@ -423,6 +423,30 @@ namespace MathNet.Numerics.Statistics
return StreamingStatistics.PopulationCovariance(population1.Where(d => d.HasValue).Select(d => d.Value), population2.Where(d => d.HasValue).Select(d => d.Value));
}
+ ///
+ /// Evaluates the root mean square (RMS) also known as quadratic mean.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ ///
+ /// The data to calculate the RMS of.
+ public static double RootMeanSquare(this IEnumerable data)
+ {
+ var array = data as double[];
+ return array != null
+ ? ArrayStatistics.RootMeanSquare(array)
+ : StreamingStatistics.RootMeanSquare(data);
+ }
+
+ ///
+ /// Evaluates the root mean square (RMS) also known as quadratic mean.
+ /// Returns NaN if data is empty or if any entry is NaN.
+ /// Null-entries are ignored.
+ ///
+ /// The data to calculate the mean of.
+ public static double RootMeanSquare(this IEnumerable data)
+ {
+ return StreamingStatistics.RootMeanSquare(data.Where(d => d.HasValue).Select(d => d.Value));
+ }
+
///
/// Estimates the sample median from the provided samples (R8).
///
diff --git a/src/Numerics/Statistics/StreamingStatistics.cs b/src/Numerics/Statistics/StreamingStatistics.cs
index 4c593740..ae9a2886 100644
--- a/src/Numerics/Statistics/StreamingStatistics.cs
+++ b/src/Numerics/Statistics/StreamingStatistics.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// 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
@@ -328,6 +328,26 @@ namespace MathNet.Numerics.Statistics
return comoment/n;
}
+ ///
+ /// Estimates the root mean square (RMS) also known as quadratic mean from the enumerable, in a single pass without memoization.
+ /// Returns NaN if data is empty or any entry is NaN.
+ ///
+ /// Sample stream, no sorting is assumed.
+ public static double RootMeanSquare(IEnumerable stream)
+ {
+ double mean = 0;
+ ulong m = 0;
+ bool any = false;
+
+ foreach (var d in stream)
+ {
+ mean += (d*d - mean)/++m;
+ any = true;
+ }
+
+ return any ? Math.Sqrt(mean) : double.NaN;
+ }
+
///
/// Calculates the entropy of a stream of double values.
/// Returns NaN if any of the values in the stream are NaN.
diff --git a/src/UnitTests/StatisticsTests/StatisticsTests.cs b/src/UnitTests/StatisticsTests/StatisticsTests.cs
index 39b5a92d..92748ea2 100644
--- a/src/UnitTests/StatisticsTests/StatisticsTests.cs
+++ b/src/UnitTests/StatisticsTests/StatisticsTests.cs
@@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
-// Copyright (c) 2009-2013 Math.NET
+// 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
@@ -78,6 +78,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => Statistics.PopulationStandardDeviation(data), Throws.Exception);
Assert.That(() => Statistics.Covariance(data, data), Throws.Exception);
Assert.That(() => Statistics.PopulationCovariance(data, data), Throws.Exception);
+ Assert.That(() => Statistics.RootMeanSquare(data), Throws.Exception);
Assert.That(() => SortedArrayStatistics.Minimum(data), Throws.Exception.TypeOf());
Assert.That(() => SortedArrayStatistics.Minimum(data), Throws.Exception.TypeOf());
@@ -103,6 +104,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => ArrayStatistics.PopulationStandardDeviation(data), Throws.Exception.TypeOf());
Assert.That(() => ArrayStatistics.Covariance(data, data), Throws.Exception.TypeOf());
Assert.That(() => ArrayStatistics.PopulationCovariance(data, data), Throws.Exception.TypeOf());
+ Assert.That(() => ArrayStatistics.RootMeanSquare(data), Throws.Exception.TypeOf());
Assert.That(() => ArrayStatistics.MedianInplace(data), Throws.Exception.TypeOf());
Assert.That(() => ArrayStatistics.QuantileInplace(data, 0.3), Throws.Exception.TypeOf());
@@ -115,6 +117,7 @@ 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(() => StreamingStatistics.RootMeanSquare(data), Throws.Exception.TypeOf());
Assert.That(() => StreamingStatistics.Entropy(data), Throws.Exception.TypeOf());
Assert.That(() => new RunningStatistics(data), Throws.Exception);
@@ -138,6 +141,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => Statistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => Statistics.Covariance(data, data));
Assert.DoesNotThrow(() => Statistics.PopulationCovariance(data, data));
+ Assert.DoesNotThrow(() => Statistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => SortedArrayStatistics.Minimum(data));
Assert.DoesNotThrow(() => SortedArrayStatistics.Maximum(data));
@@ -162,6 +166,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => ArrayStatistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => ArrayStatistics.Covariance(data, data));
Assert.DoesNotThrow(() => ArrayStatistics.PopulationCovariance(data, data));
+ Assert.DoesNotThrow(() => ArrayStatistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => ArrayStatistics.MedianInplace(data));
Assert.DoesNotThrow(() => ArrayStatistics.QuantileInplace(data, 0.3));
@@ -174,6 +179,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => StreamingStatistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => StreamingStatistics.Covariance(data, data));
Assert.DoesNotThrow(() => StreamingStatistics.PopulationCovariance(data, data));
+ Assert.DoesNotThrow(() => StreamingStatistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => StreamingStatistics.Entropy(data));
Assert.That(() => new RunningStatistics(data), Throws.Nothing);
@@ -780,14 +786,17 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqualRelative(1e+9, Statistics.Mean(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(4d, Statistics.Variance(gaussian.Samples().Take(10000)), 0);
AssertHelpers.AlmostEqualRelative(2d, Statistics.StandardDeviation(gaussian.Samples().Take(10000)), 1);
+ AssertHelpers.AlmostEqualRelative(1e+9, Statistics.RootMeanSquare(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(1e+9, ArrayStatistics.Mean(gaussian.Samples().Take(10000).ToArray()), 10);
AssertHelpers.AlmostEqualRelative(4d, ArrayStatistics.Variance(gaussian.Samples().Take(10000).ToArray()), 0);
AssertHelpers.AlmostEqualRelative(2d, ArrayStatistics.StandardDeviation(gaussian.Samples().Take(10000).ToArray()), 1);
+ AssertHelpers.AlmostEqualRelative(1e+9, ArrayStatistics.RootMeanSquare(gaussian.Samples().Take(10000).ToArray()), 10);
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, StreamingStatistics.RootMeanSquare(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(1e+9, new RunningStatistics(gaussian.Samples().Take(10000)).Mean, 10);
AssertHelpers.AlmostEqualRelative(4d, new RunningStatistics(gaussian.Samples().Take(10000)).Variance, 0);
@@ -852,6 +861,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(ArrayStatistics.PopulationStandardDeviation(data.Data), Is.EqualTo(StreamingStatistics.PopulationStandardDeviation(data.Data)).Within(1e-15), "PopulationStandardDeviation");
Assert.That(ArrayStatistics.Covariance(data.Data, data.Data), Is.EqualTo(StreamingStatistics.Covariance(data.Data, data.Data)).Within(1e-10), "Covariance");
Assert.That(ArrayStatistics.PopulationCovariance(data.Data, data.Data), Is.EqualTo(StreamingStatistics.PopulationCovariance(data.Data, data.Data)).Within(1e-10), "PopulationCovariance");
+ Assert.That(ArrayStatistics.RootMeanSquare(data.Data), Is.EqualTo(StreamingStatistics.RootMeanSquare(data.Data)).Within(1e-15), "RootMeanSquare");
}
[TestCase("lottery")]
@@ -918,6 +928,17 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new RunningStatistics(new[] { 2d }).Mean, Is.Not.NaN);
}
+ [Test]
+ public void RootMeanSquareOfEmptyMustBeNaN()
+ {
+ Assert.That(Statistics.RootMeanSquare(new double[0]), Is.NaN);
+ Assert.That(Statistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
+ Assert.That(ArrayStatistics.RootMeanSquare(new double[0]), Is.NaN);
+ Assert.That(ArrayStatistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
+ Assert.That(StreamingStatistics.RootMeanSquare(new double[0]), Is.NaN);
+ Assert.That(StreamingStatistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
+ }
+
[Test]
public void SampleVarianceOfEmptyAndSingleMustBeNaN()
{
@@ -1005,6 +1026,9 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new DescriptiveStatistics(shorter).Mean, Is.EqualTo(0.375).Within(1e-14), "DescriptiveStatistics.Mean: shorter");
Assert.That(new DescriptiveStatistics(longer).Mean, Is.EqualTo(00.375).Within(1e-14), "DescriptiveStatistics.Mean: longer");
+ Assert.That(Statistics.RootMeanSquare(shorter), Is.EqualTo(Math.Sqrt(0.21875)).Within(1e-14), "Statistics.RootMeanSquare: shorter");
+ Assert.That(Statistics.RootMeanSquare(longer), Is.EqualTo(Math.Sqrt(0.21875)).Within(1e-14), "Statistics.RootMeanSquare: longer");
+
Assert.That(Statistics.Skewness(shorter), Is.EqualTo(0.0).Within(1e-12), "Statistics.Skewness: shorter");
Assert.That(Statistics.Skewness(longer), Is.EqualTo(0.0).Within(1e-12), "Statistics.Skewness: longer");
Assert.That(new DescriptiveStatistics(shorter).Skewness, Is.EqualTo(0.0).Within(1e-12), "DescriptiveStatistics.Skewness: shorter");
@@ -1016,6 +1040,13 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new DescriptiveStatistics(longer).Kurtosis, Is.EqualTo(-1.36).Within(1e-4), "DescriptiveStatistics.Kurtosis: longer");
}
+ [Test]
+ public void RootMeanSquareOfSinusoidal()
+ {
+ var data = Generate.Sinusoidal(128, 64, 16, 2.0);
+ Assert.That(Statistics.RootMeanSquare(data), Is.EqualTo(2.0/Constants.Sqrt2).Within(1e-12));
+ }
+
[Test]
public void EntropyIsMinimum()
{