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