8 changed files with 621 additions and 329 deletions
@ -1,290 +0,0 @@ |
|||
// <copyright file="DftTest.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.IntegralTransformsTests |
|||
{ |
|||
using System; |
|||
using System.Linq; |
|||
using MbUnit.Framework; |
|||
using IntegralTransforms; |
|||
using IntegralTransforms.Algorithms; |
|||
using Statistics; |
|||
|
|||
[TestFixture] |
|||
public class DftTest |
|||
{ |
|||
private static readonly Random _random = new Random(); |
|||
|
|||
private static Complex[] ProvideSamples(int count) |
|||
{ |
|||
var samples = new Complex[count]; |
|||
for (int i = 0; i < samples.Length; i++) |
|||
{ |
|||
samples[i] = Complex.WithRealImaginary( |
|||
1 - (2 * _random.NextDouble()), |
|||
1 - (2 * _random.NextDouble())); |
|||
} |
|||
|
|||
return samples; |
|||
} |
|||
|
|||
[Test] |
|||
public void NaiveTransformsRealSineCorrectly() |
|||
{ |
|||
var realSine = new Complex[16]; |
|||
for (int i = 0; i < realSine.Length; i++) |
|||
{ |
|||
realSine[i] = Math.Sin(i / 8.0 * Constants.Pi); |
|||
} |
|||
|
|||
// real-odd transforms to imaginary odd
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrum = dft.NaiveForward(realSine, FourierOptions.Matlab); |
|||
|
|||
// all real components must be zero
|
|||
foreach (var c in spectrum) |
|||
{ |
|||
Assert.AreApproximatelyEqual(0, c.Real, 1e-12, "real"); |
|||
} |
|||
|
|||
// all imaginary components except second and last musth be zero
|
|||
for(int i = 0; i<spectrum.Length; i++) |
|||
{ |
|||
if(i == 1) |
|||
{ |
|||
Assert.AreApproximatelyEqual(-8, spectrum[i].Imaginary, 1e-12, "imag second"); |
|||
} |
|||
else if (i == spectrum.Length - 1) |
|||
{ |
|||
Assert.AreApproximatelyEqual(8, spectrum[i].Imaginary, 1e-12, "imag last"); |
|||
} |
|||
else |
|||
{ |
|||
Assert.AreApproximatelyEqual(0, spectrum[i].Imaginary, 1e-12, "imag"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void NaiveIsReversible(FourierOptions options) |
|||
{ |
|||
var samples = ProvideSamples(0x80); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
work = dft.NaiveForward(work, options); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
work = dft.NaiveInverse(work, options); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void Radix2MatchesNaiveOnRealSine() |
|||
{ |
|||
var realSine = new Complex[16]; |
|||
for (int i = 0; i < realSine.Length; i++) |
|||
{ |
|||
realSine[i] = Math.Sin(i / 8.0 * Constants.Pi); |
|||
} |
|||
|
|||
// real-odd transforms to imaginary odd
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrumNaive = dft.NaiveForward(realSine, FourierOptions.Matlab); |
|||
|
|||
var spectrumRadix2 = new Complex[realSine.Length]; |
|||
realSine.CopyTo(spectrumRadix2, 0); |
|||
dft.Radix2Forward(spectrumRadix2, FourierOptions.Matlab); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, spectrumRadix2, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void Radix2MatchesNaiveOnRandom() |
|||
{ |
|||
var samples = ProvideSamples(0x80); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrumNaive = dft.NaiveForward(samples, FourierOptions.Matlab); |
|||
dft.Radix2Forward(work, FourierOptions.Matlab); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void Radix2IsReversible(FourierOptions options) |
|||
{ |
|||
var samples = ProvideSamples(0x8000); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
dft.Radix2Forward(work, options); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
dft.Radix2Inverse(work, options); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void Radix2ThrowsWhenNotPowerOfTwo() |
|||
{ |
|||
var samples = ProvideSamples(0x7F); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
|
|||
Assert.Throws( |
|||
typeof(ArgumentException), |
|||
() => dft.Radix2Forward(samples, FourierOptions.Default)); |
|||
|
|||
Assert.Throws( |
|||
typeof(ArgumentException), |
|||
() => dft.Radix2Inverse(samples, FourierOptions.Default)); |
|||
} |
|||
|
|||
[Test] |
|||
public void BluesteinMatchesNaiveOnRealSine() |
|||
{ |
|||
var realSine = new Complex[14]; |
|||
for (int i = 0; i < realSine.Length; i++) |
|||
{ |
|||
realSine[i] = Math.Sin(i / 7.0 * Constants.Pi); |
|||
} |
|||
|
|||
// real-odd transforms to imaginary odd
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrumNaive = dft.NaiveForward(realSine, FourierOptions.Matlab); |
|||
|
|||
var spectrumBluestein = new Complex[realSine.Length]; |
|||
realSine.CopyTo(spectrumBluestein, 0); |
|||
dft.BluesteinForward(spectrumBluestein, FourierOptions.Matlab); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, spectrumBluestein, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void BluesteinMatchesNaiveOnRandomPowerOfTwo() |
|||
{ |
|||
var samples = ProvideSamples(0x80); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrumNaive = dft.NaiveForward(samples, FourierOptions.Matlab); |
|||
dft.BluesteinForward(work, FourierOptions.Matlab); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void BluesteinMatchesNaiveOnRandomNonPowerOfTwo() |
|||
{ |
|||
var samples = ProvideSamples(0x7F); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrumNaive = dft.NaiveForward(samples, FourierOptions.Matlab); |
|||
dft.BluesteinForward(work, FourierOptions.Matlab); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void BluesteinIsReversible(FourierOptions options) |
|||
{ |
|||
var samples = ProvideSamples(0x7FFF); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
dft.BluesteinForward(work, options); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
dft.BluesteinInverse(work, options); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void DefaultTransformIsReversible() |
|||
{ |
|||
var samples = ProvideSamples(0x7FFF); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
Transform.FourierForward(work); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
Transform.FourierInverse(work); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
|
|||
Transform.FourierInverse(work, FourierOptions.Default); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
Transform.FourierForward(work, FourierOptions.Default); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
public void TransformSatisfiesParsevalsTheorem() |
|||
{ |
|||
var samples = ProvideSamples(0x1000); |
|||
|
|||
var timeSpaceEnergy = (from s in samples select s.ModulusSquared).Mean(); |
|||
|
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
// Only symmetric scaling scaling satisfies the theorem, hence FourierOptions.Default.
|
|||
Transform.FourierForward(work, FourierOptions.Default); |
|||
|
|||
var frequencySpaceEnergy = (from s in work select s.ModulusSquared).Mean(); |
|||
|
|||
Assert.AreApproximatelyEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,96 @@ |
|||
// <copyright file="FourierTest.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.IntegralTransformsTests |
|||
{ |
|||
using System; |
|||
using MbUnit.Framework; |
|||
using IntegralTransforms; |
|||
using IntegralTransforms.Algorithms; |
|||
|
|||
[TestFixture] |
|||
public class FourierTest |
|||
{ |
|||
[Test] |
|||
public void NaiveTransformsRealSineCorrectly() |
|||
{ |
|||
var samples = SampleProvider.ProvideComplexRealSine(16); |
|||
|
|||
// real-odd transforms to imaginary odd
|
|||
var dft = new DiscreteFourierTransform(); |
|||
var spectrum = dft.NaiveForward(samples, FourierOptions.Matlab); |
|||
|
|||
// all real components must be zero
|
|||
foreach (var c in spectrum) |
|||
{ |
|||
Assert.AreApproximatelyEqual(0, c.Real, 1e-12, "real"); |
|||
} |
|||
|
|||
// all imaginary components except second and last musth be zero
|
|||
for(int i = 0; i<spectrum.Length; i++) |
|||
{ |
|||
if(i == 1) |
|||
{ |
|||
Assert.AreApproximatelyEqual(-8, spectrum[i].Imaginary, 1e-12, "imag second"); |
|||
} |
|||
else if (i == spectrum.Length - 1) |
|||
{ |
|||
Assert.AreApproximatelyEqual(8, spectrum[i].Imaginary, 1e-12, "imag last"); |
|||
} |
|||
else |
|||
{ |
|||
Assert.AreApproximatelyEqual(0, spectrum[i].Imaginary, 1e-12, "imag"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Test] |
|||
public void Radix2ThrowsWhenNotPowerOfTwo() |
|||
{ |
|||
var samples = SampleProvider.ProvideComplexSamples(0x7F); |
|||
|
|||
var dft = new DiscreteFourierTransform(); |
|||
|
|||
Assert.Throws( |
|||
typeof(ArgumentException), |
|||
() => dft.Radix2Forward(samples, FourierOptions.Default)); |
|||
|
|||
Assert.Throws( |
|||
typeof(ArgumentException), |
|||
() => dft.Radix2Inverse(samples, FourierOptions.Default)); |
|||
|
|||
Assert.Throws( |
|||
typeof (ArgumentException), |
|||
() => DiscreteFourierTransform.Radix2(samples, -1)); |
|||
|
|||
Assert.Throws( |
|||
typeof(ArgumentException), |
|||
() => DiscreteFourierTransform.Radix2Parallel(samples, -1)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,173 @@ |
|||
// <copyright file="InverseTransformTest.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.IntegralTransformsTests |
|||
{ |
|||
using System; |
|||
using IntegralTransforms; |
|||
using IntegralTransforms.Algorithms; |
|||
using MbUnit.Framework; |
|||
|
|||
[TestFixture] |
|||
public class InverseTransformTest |
|||
{ |
|||
private static void VerifyIsReversibleComplex( |
|||
int count, |
|||
double maximumError, |
|||
Func<Complex[], Complex[]> forward, |
|||
Func<Complex[], Complex[]> inverse) |
|||
{ |
|||
var samples = SampleProvider.ProvideComplexSamples(count); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
work = forward(work); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, maximumError)); |
|||
|
|||
work = inverse(work); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, maximumError); |
|||
} |
|||
|
|||
private static void VerifyIsReversibleReal( |
|||
int count, |
|||
double maximumError, |
|||
Func<double[], double[]> forward, |
|||
Func<double[], double[]> inverse) |
|||
{ |
|||
var samples = SampleProvider.ProvideRealSamples(count); |
|||
var work = new double[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
work = forward(work); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, maximumError)); |
|||
|
|||
work = inverse(work); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, maximumError); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void FourierNaiveIsReversible(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
|
|||
VerifyIsReversibleComplex( |
|||
0x80, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.NaiveInverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void FourierRadix2IsReversible(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
|
|||
VerifyIsReversibleComplex( |
|||
0x8000, |
|||
1e-12, |
|||
s => |
|||
{ |
|||
dft.Radix2Forward(s, options); |
|||
return s; |
|||
}, |
|||
s => |
|||
{ |
|||
dft.Radix2Inverse(s, options); |
|||
return s; |
|||
}); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
public void FourierBluesteinIsReversible(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
|
|||
VerifyIsReversibleComplex( |
|||
0x7FFF, |
|||
1e-12, |
|||
s => |
|||
{ |
|||
dft.BluesteinForward(s, options); |
|||
return s; |
|||
}, |
|||
s => |
|||
{ |
|||
dft.BluesteinInverse(s, options); |
|||
return s; |
|||
}); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(HartleyOptions.Default)] |
|||
[Row(HartleyOptions.AsymmetricScaling)] |
|||
public void HartleyNaiveIsReversible(HartleyOptions options) |
|||
{ |
|||
var dht = new DiscreteHartleyTransform(); |
|||
|
|||
VerifyIsReversibleReal( |
|||
0x80, |
|||
1e-10, |
|||
s => dht.NaiveForward(s, options), |
|||
s => dht.NaiveInverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
public void FourierDefaultTransformIsReversible() |
|||
{ |
|||
var samples = SampleProvider.ProvideComplexSamples(0x7FFF); |
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
Transform.FourierForward(work); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
Transform.FourierInverse(work); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
|
|||
Transform.FourierInverse(work, FourierOptions.Default); |
|||
|
|||
Assert.IsFalse(work.AlmostEqualListWithError(samples, 1e-12)); |
|||
|
|||
Transform.FourierForward(work, FourierOptions.Default); |
|||
|
|||
AssertHelpers.AlmostEqualList(samples, work, 1e-12); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,164 @@ |
|||
// <copyright file="MatchingNaiveTransformTest.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.IntegralTransformsTests |
|||
{ |
|||
using System; |
|||
using IntegralTransforms; |
|||
using IntegralTransforms.Algorithms; |
|||
using MbUnit.Framework; |
|||
|
|||
[TestFixture] |
|||
public class MatchingNaiveTransformTest |
|||
{ |
|||
private static void VerifyMatchesNaiveComplex( |
|||
Complex[] samples, |
|||
double maximumError, |
|||
Func<Complex[], Complex[]> naive, |
|||
Action<Complex[]> fast) |
|||
{ |
|||
var spectrumNaive = naive(samples); |
|||
|
|||
var spectrumFast = new Complex[samples.Length]; |
|||
samples.CopyTo(spectrumFast, 0); |
|||
fast(spectrumFast); |
|||
|
|||
AssertHelpers.AlmostEqualList(spectrumNaive, spectrumFast, maximumError); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
[Row(FourierOptions.NumericalRecipes)] |
|||
public void FourierRadix2MatchesNaiveOnRealSine(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
var samples = SampleProvider.ProvideComplexRealSine(16); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.Radix2Forward(s, options)); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveInverse(s, options), |
|||
s => dft.Radix2Inverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
[Row(FourierOptions.NumericalRecipes)] |
|||
public void FourierRadix2MatchesNaiveOnRandom(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
var samples = SampleProvider.ProvideComplexSamples(0x80); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.Radix2Forward(s, options)); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveInverse(s, options), |
|||
s => dft.Radix2Inverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
[Row(FourierOptions.NumericalRecipes)] |
|||
public void FourierBluesteinMatchesNaiveOnRealSineNonPowerOfTwo(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
var samples = SampleProvider.ProvideComplexRealSine(14); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.BluesteinForward(s, options)); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveInverse(s, options), |
|||
s => dft.BluesteinInverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
[Row(FourierOptions.NumericalRecipes)] |
|||
public void FourierBluesteinMatchesNaiveOnRandomPowerOfTwo(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
var samples = SampleProvider.ProvideComplexSamples(0x80); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.BluesteinForward(s, options)); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveInverse(s, options), |
|||
s => dft.BluesteinInverse(s, options)); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(FourierOptions.Default)] |
|||
[Row(FourierOptions.Matlab)] |
|||
[Row(FourierOptions.NumericalRecipes)] |
|||
public void FourierBluesteinMatchesNaiveOnRandomNonPowerOfTwo(FourierOptions options) |
|||
{ |
|||
var dft = new DiscreteFourierTransform(); |
|||
var samples = SampleProvider.ProvideComplexSamples(0x7F); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveForward(s, options), |
|||
s => dft.BluesteinForward(s, options)); |
|||
|
|||
VerifyMatchesNaiveComplex( |
|||
samples, |
|||
1e-12, |
|||
s => dft.NaiveInverse(s, options), |
|||
s => dft.BluesteinInverse(s, options)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,82 @@ |
|||
// <copyright file="ParsevalTheoremTest.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>
|
|||
|
|||
using MathNet.Numerics.IntegralTransforms.Algorithms; |
|||
|
|||
namespace MathNet.Numerics.UnitTests.IntegralTransformsTests |
|||
{ |
|||
using System.Linq; |
|||
using MbUnit.Framework; |
|||
using IntegralTransforms; |
|||
using Statistics; |
|||
|
|||
[TestFixture] |
|||
public class ParsevalTheoremTest |
|||
{ |
|||
[Test] |
|||
[Row(0x1000)] |
|||
[Row(0x7FF)] |
|||
public void FourierDefaultTransformSatisfiesParsevalsTheorem(int count) |
|||
{ |
|||
var samples = SampleProvider.ProvideComplexSamples(count); |
|||
|
|||
var timeSpaceEnergy = (from s in samples select s.ModulusSquared).Mean(); |
|||
|
|||
var work = new Complex[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
// Default -> Symmetric Scaling
|
|||
Transform.FourierForward(work); |
|||
|
|||
var frequencySpaceEnergy = (from s in work select s.ModulusSquared).Mean(); |
|||
|
|||
Assert.AreApproximatelyEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); |
|||
} |
|||
|
|||
[Test] |
|||
[Row(0x40)] |
|||
[Row(0x1F)] |
|||
public void HartleyDefaultNaiveSatisfiesParsevalsTheorem(int count) |
|||
{ |
|||
var samples = SampleProvider.ProvideRealSamples(count); |
|||
|
|||
var timeSpaceEnergy = (from s in samples select s * s).Mean(); |
|||
|
|||
var work = new double[samples.Length]; |
|||
samples.CopyTo(work, 0); |
|||
|
|||
// Default -> Symmetric Scaling
|
|||
var dht = new DiscreteHartleyTransform(); |
|||
work = dht.NaiveForward(work, HartleyOptions.Default); |
|||
|
|||
var frequencySpaceEnergy = (from s in work select s * s).Mean(); |
|||
|
|||
Assert.AreApproximatelyEqual(timeSpaceEnergy, frequencySpaceEnergy, 1e-12); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,73 @@ |
|||
// <copyright file="SampleProvider.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.IntegralTransformsTests |
|||
{ |
|||
using System; |
|||
|
|||
internal static class SampleProvider |
|||
{ |
|||
private static readonly Random _random = new Random(); |
|||
|
|||
internal static Complex[] ProvideComplexSamples(int count) |
|||
{ |
|||
var samples = new Complex[count]; |
|||
for (int i = 0; i < samples.Length; i++) |
|||
{ |
|||
samples[i] = Complex.WithRealImaginary( |
|||
1 - (2 * _random.NextDouble()), |
|||
1 - (2 * _random.NextDouble())); |
|||
} |
|||
|
|||
return samples; |
|||
} |
|||
|
|||
internal static double[] ProvideRealSamples(int count) |
|||
{ |
|||
var samples = new double[count]; |
|||
for (int i = 0; i < samples.Length; i++) |
|||
{ |
|||
samples[i] = 1 - (2 * _random.NextDouble()); |
|||
} |
|||
|
|||
return samples; |
|||
} |
|||
|
|||
internal static Complex[] ProvideComplexRealSine(int count) |
|||
{ |
|||
double halfPeriod = count / 2.0; |
|||
var samples = new Complex[count]; |
|||
for (int i = 0; i < samples.Length; i++) |
|||
{ |
|||
samples[i] = Math.Sin(i * Constants.Pi / halfPeriod); |
|||
} |
|||
|
|||
return samples; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue