Browse Source

Statistics: Min/Max Absolute, MagnitudePhase (complex)

netstandard
Christoph Ruegg 11 years ago
parent
commit
df15a21782
  1. 1
      src/Numerics/Numerics.csproj
  2. 167
      src/Numerics/Statistics/ArrayStatistics.Complex.cs
  3. 48
      src/Numerics/Statistics/ArrayStatistics.Single.cs
  4. 52
      src/Numerics/Statistics/ArrayStatistics.cs
  5. 124
      src/Numerics/Statistics/Statistics.cs
  6. 226
      src/Numerics/Statistics/StreamingStatistics.cs
  7. 28
      src/UnitTests/StatisticsTests/StatisticsTests.cs

1
src/Numerics/Numerics.csproj

@ -230,6 +230,7 @@
<Compile Include="SpecialFunctions\Logistic.cs" />
<Compile Include="SpecialFunctions\TestFunctions.cs" />
<Compile Include="Statistics\ArrayStatistics.cs" />
<Compile Include="Statistics\ArrayStatistics.Complex.cs" />
<Compile Include="Statistics\ArrayStatistics.Int32.cs" />
<Compile Include="Statistics\ArrayStatistics.Single.cs" />
<Compile Include="Statistics\MovingStatistics.cs" />

167
src/Numerics/Statistics/ArrayStatistics.Complex.cs

@ -0,0 +1,167 @@
// <copyright file="ArrayStatistics.Complex.cs" company="Math.NET">
// 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-2015 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>
using System;
namespace MathNet.Numerics.Statistics
{
#if NOSYSNUMERICS
using Complex64 = Numerics.Complex;
#else
using Complex64 = System.Numerics.Complex;
#endif
public static partial class ArrayStatistics
{
/// <summary>
/// Returns the smallest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static Complex64 MinimumMagnitudePhase(Complex64[] data)
{
if (data.Length == 0)
{
return new Complex64(double.NaN, double.NaN);
}
double minMagnitude = double.PositiveInfinity;
Complex64 min = new Complex64(double.PositiveInfinity, double.PositiveInfinity);
for (int i = 0; i < data.Length; i++)
{
double magnitude = data[i].Magnitude;
if (double.IsNaN(magnitude))
{
return new Complex64(double.NaN, double.NaN);
}
if (magnitude < minMagnitude || magnitude == minMagnitude && data[i].Phase < min.Phase)
{
minMagnitude = magnitude;
min = data[i];
}
}
return min;
}
/// <summary>
/// Returns the smallest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static Complex32 MinimumMagnitudePhase(Complex32[] data)
{
if (data.Length == 0)
{
return new Complex32(float.NaN, float.NaN);
}
float minMagnitude = float.PositiveInfinity;
Complex32 min = new Complex32(float.PositiveInfinity, float.PositiveInfinity);
for (int i = 0; i < data.Length; i++)
{
float magnitude = data[i].Magnitude;
if (float.IsNaN(magnitude))
{
return new Complex32(float.NaN, float.NaN);
}
if (magnitude < minMagnitude || magnitude == minMagnitude && data[i].Phase < min.Phase)
{
minMagnitude = magnitude;
min = data[i];
}
}
return min;
}
/// <summary>
/// Returns the largest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static Complex64 MaximumMagnitudePhase(Complex64[] data)
{
if (data.Length == 0)
{
return new Complex64(double.NaN, double.NaN);
}
double maxMagnitude = 0.0d;
Complex64 max = Complex64.Zero;
for (int i = 0; i < data.Length; i++)
{
double magnitude = data[i].Magnitude;
if (double.IsNaN(magnitude))
{
return new Complex64(double.NaN, double.NaN);
}
if (magnitude > maxMagnitude || magnitude == maxMagnitude && data[i].Phase > max.Phase)
{
maxMagnitude = magnitude;
max = data[i];
}
}
return max;
}
/// <summary>
/// Returns the largest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static Complex32 MaximumMagnitudePhase(Complex32[] data)
{
if (data.Length == 0)
{
return new Complex32(float.NaN, float.NaN);
}
float maxMagnitude = 0.0f;
Complex32 max = Complex32.Zero;
for (int i = 0; i < data.Length; i++)
{
float magnitude = data[i].Magnitude;
if (float.IsNaN(magnitude))
{
return new Complex32(float.NaN, float.NaN);
}
if (magnitude > maxMagnitude || magnitude == maxMagnitude && data[i].Phase > max.Phase)
{
maxMagnitude = magnitude;
max = data[i];
}
}
return max;
}
}
}

48
src/Numerics/Statistics/ArrayStatistics.Single.cs

@ -83,6 +83,54 @@ namespace MathNet.Numerics.Statistics
return max;
}
/// <summary>
/// Returns the smallest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static float MinimumAbsolute(float[] data)
{
if (data.Length == 0)
{
return float.NaN;
}
float min = float.PositiveInfinity;
for (int i = 0; i < data.Length; i++)
{
if (Math.Abs(data[i]) < min || float.IsNaN(data[i]))
{
min = Math.Abs(data[i]);
}
}
return min;
}
/// <summary>
/// Returns the largest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static float MaximumAbsolute(float[] data)
{
if (data.Length == 0)
{
return float.NaN;
}
float max = 0.0f;
for (int i = 0; i < data.Length; i++)
{
if (Math.Abs(data[i]) > max || float.IsNaN(data[i]))
{
max = Math.Abs(data[i]);
}
}
return max;
}
/// <summary>
/// Estimates the arithmetic sample mean from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.

52
src/Numerics/Statistics/ArrayStatistics.cs

@ -57,7 +57,7 @@ namespace MathNet.Numerics.Statistics
return double.NaN;
}
var min = double.PositiveInfinity;
double min = double.PositiveInfinity;
for (int i = 0; i < data.Length; i++)
{
if (data[i] < min || double.IsNaN(data[i]))
@ -81,7 +81,7 @@ namespace MathNet.Numerics.Statistics
return double.NaN;
}
var max = double.NegativeInfinity;
double max = double.NegativeInfinity;
for (int i = 0; i < data.Length; i++)
{
if (data[i] > max || double.IsNaN(data[i]))
@ -93,6 +93,54 @@ namespace MathNet.Numerics.Statistics
return max;
}
/// <summary>
/// Returns the smallest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static double MinimumAbsolute(double[] data)
{
if (data.Length == 0)
{
return double.NaN;
}
double min = double.PositiveInfinity;
for (int i = 0; i < data.Length; i++)
{
if (Math.Abs(data[i]) < min || double.IsNaN(data[i]))
{
min = Math.Abs(data[i]);
}
}
return min;
}
/// <summary>
/// Returns the largest absolute value from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static double MaximumAbsolute(double[] data)
{
if (data.Length == 0)
{
return double.NaN;
}
double max = 0.0d;
for (int i = 0; i < data.Length; i++)
{
if (Math.Abs(data[i]) > max || double.IsNaN(data[i]))
{
max = Math.Abs(data[i]);
}
}
return max;
}
/// <summary>
/// Estimates the arithmetic sample mean from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.

124
src/Numerics/Statistics/Statistics.cs

@ -28,11 +28,17 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System;
using System.Collections.Generic;
using System.Linq;
namespace MathNet.Numerics.Statistics
{
using System;
using System.Collections.Generic;
using System.Linq;
#if NOSYSNUMERICS
using Complex64 = Numerics.Complex;
#else
using Complex64 = System.Numerics.Complex;
#endif
/// <summary>
/// Extension methods to return basic statistics on set of data.
@ -120,6 +126,118 @@ namespace MathNet.Numerics.Statistics
return StreamingStatistics.Maximum(data.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Returns the minimum absolute value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double MinimumAbsolute(this IEnumerable<double> data)
{
var array = data as double[];
return array != null
? ArrayStatistics.MinimumAbsolute(array)
: StreamingStatistics.MinimumAbsolute(data);
}
/// <summary>
/// Returns the minimum absolute value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static float MinimumAbsolute(this IEnumerable<float> data)
{
var array = data as float[];
return array != null
? ArrayStatistics.MinimumAbsolute(array)
: StreamingStatistics.MinimumAbsolute(data);
}
/// <summary>
/// Returns the maximum absolute value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double MaximumAbsolute(this IEnumerable<double> data)
{
var array = data as double[];
return array != null
? ArrayStatistics.MaximumAbsolute(array)
: StreamingStatistics.MaximumAbsolute(data);
}
/// <summary>
/// Returns the maximum absolute value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static float MaximumAbsolute(this IEnumerable<float> data)
{
var array = data as float[];
return array != null
? ArrayStatistics.MaximumAbsolute(array)
: StreamingStatistics.MaximumAbsolute(data);
}
/// <summary>
/// Returns the minimum magnitude and phase value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static Complex64 MinimumMagnitudePhase(this IEnumerable<Complex64> data)
{
var array = data as Complex64[];
return array != null
? ArrayStatistics.MinimumMagnitudePhase(array)
: StreamingStatistics.MinimumMagnitudePhase(data);
}
/// <summary>
/// Returns the minimum magnitude and phase value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static Complex32 MinimumMagnitudePhase(this IEnumerable<Complex32> data)
{
var array = data as Complex32[];
return array != null
? ArrayStatistics.MinimumMagnitudePhase(array)
: StreamingStatistics.MinimumMagnitudePhase(data);
}
/// <summary>
/// Returns the maximum magnitude and phase value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static Complex64 MaximumMagnitudePhase(this IEnumerable<Complex64> data)
{
var array = data as Complex64[];
return array != null
? ArrayStatistics.MaximumMagnitudePhase(array)
: StreamingStatistics.MaximumMagnitudePhase(data);
}
/// <summary>
/// Returns the maximum magnitude and phase value in the sample data.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static Complex32 MaximumMagnitudePhase(this IEnumerable<Complex32> data)
{
var array = data as Complex32[];
return array != null
? ArrayStatistics.MaximumMagnitudePhase(array)
: StreamingStatistics.MaximumMagnitudePhase(data);
}
/// <summary>
/// Evaluates the sample mean, an estimate of the population mean.
/// Returns NaN if data is empty or if any entry is NaN.

226
src/Numerics/Statistics/StreamingStatistics.cs

@ -35,6 +35,12 @@ using MathNet.Numerics.Properties;
namespace MathNet.Numerics.Statistics
{
#if NOSYSNUMERICS
using Complex64 = Numerics.Complex;
#else
using Complex64 = System.Numerics.Complex;
#endif
/// <summary>
/// Statistics operating on an IEnumerable in a single pass, without keeping the full data in memory.
/// Can be used in a streaming way, e.g. on large datasets not fitting into memory.
@ -51,7 +57,7 @@ namespace MathNet.Numerics.Statistics
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static double Minimum(IEnumerable<double> stream)
{
var min = double.PositiveInfinity;
double min = double.PositiveInfinity;
bool any = false;
foreach (var d in stream)
@ -74,7 +80,7 @@ namespace MathNet.Numerics.Statistics
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static float Minimum(IEnumerable<float> stream)
{
var min = float.PositiveInfinity;
float min = float.PositiveInfinity;
bool any = false;
foreach (var d in stream)
@ -97,7 +103,7 @@ namespace MathNet.Numerics.Statistics
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static double Maximum(IEnumerable<double> stream)
{
var max = double.NegativeInfinity;
double max = double.NegativeInfinity;
bool any = false;
foreach (var d in stream)
@ -120,7 +126,7 @@ namespace MathNet.Numerics.Statistics
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static float Maximum(IEnumerable<float> stream)
{
var max = float.NegativeInfinity;
float max = float.NegativeInfinity;
bool any = false;
foreach (var d in stream)
@ -136,6 +142,218 @@ namespace MathNet.Numerics.Statistics
return any ? max : float.NaN;
}
/// <summary>
/// Returns the smallest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static double MinimumAbsolute(IEnumerable<double> stream)
{
double min = double.PositiveInfinity;
bool any = false;
foreach (var d in stream)
{
if (Math.Abs(d) < min || double.IsNaN(d))
{
min = Math.Abs(d);
}
any = true;
}
return any ? min : double.NaN;
}
/// <summary>
/// Returns the smallest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static float MinimumAbsolute(IEnumerable<float> stream)
{
float min = float.PositiveInfinity;
bool any = false;
foreach (var d in stream)
{
if (Math.Abs(d) < min || float.IsNaN(d))
{
min = Math.Abs(d);
}
any = true;
}
return any ? min : float.NaN;
}
/// <summary>
/// Returns the largest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static double MaximumAbsolute(IEnumerable<double> stream)
{
double max = 0.0d;
bool any = false;
foreach (var d in stream)
{
if (Math.Abs(d) > max || double.IsNaN(d))
{
max = Math.Abs(d);
}
any = true;
}
return any ? max : double.NaN;
}
/// <summary>
/// Returns the largest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static float MaximumAbsolute(IEnumerable<float> stream)
{
float max = 0.0f;
bool any = false;
foreach (var d in stream)
{
if (Math.Abs(d) > max || float.IsNaN(d))
{
max = Math.Abs(d);
}
any = true;
}
return any ? max : float.NaN;
}
/// <summary>
/// Returns the smallest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static Complex64 MinimumMagnitudePhase(IEnumerable<Complex64> stream)
{
double minMagnitude = double.PositiveInfinity;
Complex64 min = new Complex64(double.PositiveInfinity, double.PositiveInfinity);
bool any = false;
foreach (var d in stream)
{
double magnitude = d.Magnitude;
if (double.IsNaN(magnitude))
{
return new Complex64(double.NaN, double.NaN);
}
if (magnitude < minMagnitude || magnitude == minMagnitude && d.Phase < min.Phase)
{
minMagnitude = magnitude;
min = d;
}
any = true;
}
return any ? min : new Complex64(double.NaN, double.NaN);
}
/// <summary>
/// Returns the smallest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static Complex32 MinimumMagnitudePhase(IEnumerable<Complex32> stream)
{
float minMagnitude = float.PositiveInfinity;
Complex32 min = new Complex32(float.PositiveInfinity, float.PositiveInfinity);
bool any = false;
foreach (var d in stream)
{
float magnitude = d.Magnitude;
if (float.IsNaN(magnitude))
{
return new Complex32(float.NaN, float.NaN);
}
if (magnitude < minMagnitude || magnitude == minMagnitude && d.Phase < min.Phase)
{
minMagnitude = magnitude;
min = d;
}
any = true;
}
return any ? min : new Complex32(float.NaN, float.NaN);
}
/// <summary>
/// Returns the largest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static Complex64 MaximumMagnitudePhase(IEnumerable<Complex64> stream)
{
double maxMagnitude = 0.0d;
Complex64 max = Complex64.Zero;
bool any = false;
foreach (var d in stream)
{
double magnitude = d.Magnitude;
if (double.IsNaN(magnitude))
{
return new Complex64(double.NaN, double.NaN);
}
if (magnitude > maxMagnitude || magnitude == maxMagnitude && d.Phase > max.Phase)
{
maxMagnitude = magnitude;
max = d;
}
any = true;
}
return any ? max : new Complex64(double.NaN, double.NaN);
}
/// <summary>
/// Returns the largest absolute value from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static Complex32 MaximumMagnitudePhase(IEnumerable<Complex32> stream)
{
float maxMagnitude = 0.0f;
Complex32 max = Complex32.Zero;
bool any = false;
foreach (var d in stream)
{
float magnitude = d.Magnitude;
if (float.IsNaN(magnitude))
{
return new Complex32(float.NaN, float.NaN);
}
if (magnitude > maxMagnitude || magnitude == maxMagnitude && d.Phase > max.Phase)
{
maxMagnitude = magnitude;
max = d;
}
any = true;
}
return any ? max : new Complex32(float.NaN, float.NaN);
}
/// <summary>
/// Estimates the arithmetic sample mean from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.

28
src/UnitTests/StatisticsTests/StatisticsTests.cs

@ -1107,6 +1107,34 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
var data = new double[] { 1, 2, double.NaN };
Assert.That(double.IsNaN(StreamingStatistics.Entropy(data)));
}
[Test]
public void MinimumMagnitudePhase()
{
var a = new[] { new Complex32(1.0f, 2.0f), new Complex32(float.PositiveInfinity, float.NegativeInfinity), new Complex32(-2.0f, 4.0f) };
Assert.That(ArrayStatistics.MinimumMagnitudePhase(a), Is.EqualTo(a[0]));
}
[Test]
public void MinimumMagnitudePhaseOfNaNIsNaN()
{
var a = new[] { new Complex32(1.0f, 2.0f), new Complex32(float.NaN, float.NegativeInfinity), new Complex32(-2.0f, 4.0f) };
Assert.That(ArrayStatistics.MinimumMagnitudePhase(a).IsNaN(), Is.True);
}
[Test]
public void MaximumMagnitudePhase()
{
var a = new[] { new Complex32(1.0f, 2.0f), new Complex32(float.PositiveInfinity, float.NegativeInfinity), new Complex32(-2.0f, 4.0f) };
Assert.That(ArrayStatistics.MaximumMagnitudePhase(a), Is.EqualTo(a[1]));
}
[Test]
public void MaximumMagnitudePhaseOfNaNIsNaN()
{
var a = new[] { new Complex32(1.0f, 2.0f), new Complex32(float.NaN, float.NegativeInfinity), new Complex32(-2.0f, 4.0f) };
Assert.That(ArrayStatistics.MaximumMagnitudePhase(a).IsNaN(), Is.True);
}
}
}

Loading…
Cancel
Save