I want to show you an iterative algorithm to convert a signal to a Fourier series. When I ran unit tests I gaven following results:
- one iteration: 1 sec, passed;
- ten iterations: 3 sec, passed.
I use Visual Studio Community 2015 environment. I'm writing this library in C# and MathNet NuGet package.
How can I optimize this algorithm, and what are your opinions about this library?
The unit tests:
[TestMethod]
public void OneIterationTest()
{
double[] points = new double[628];
FourierSeries fourier = new FourierSeries((x) => Math.Sign(Math.Sin(x)), 1);
for (int current = 0; current < 628; current++)
{
points[current] = fourier.GetHarmonicWavePoint(current);
}
}
[TestMethod]
public void TenIterationTest()
{
double[] points = new double[628];
FourierSeries fourier = new FourierSeries((x) => Math.Sign(Math.Sin(x)), 10);
for (int current = 0; current < 628; current++)
{
points[current] = fourier.GetHarmonicWavePoint(current);
}
}
This is my implementation:
using MathNet.Numerics.Integration;
using System;
namespace SignalProcessingLibrary
{
/**
* <summary>
* The assumption of following class is distribution signals to Fourier Series.
* First, we calculate the coefficient a_0 by integrate function in -T/2 to T/2 interval
* and multiply it by 2/T. Next, we apply iterative algorithm to superposition of harmonic waves.
* At the beginning this algorithm, we calculate coefficient a_n and b_n and sum it using
* math formula. We substitute to n index of the loop and loop is performed until reach N.
* </summary>
*/
public class FourierSeries
{
/**
* <summary>
* Initalizes fields by default values.
* </summary>
*/
public FourierSeries() : this((x) => Math.Sign(Math.Sin(x)), 10, 2 * Math.PI)
{
}
/**
* <summary>
* Sets function and iterations. This leaves the default value of _period.
* </summary>
* <param name="function">Analyzed function</param>
* <param name="iterations">Degree of approximation</param>
*/
public FourierSeries(Func<double, double> function, double iterations) : this(function, iterations, 2 * Math.PI)
{
}
/**
* <summary>
* Sets all fields.
* </summary>
* <param name="function">Analyzed function</param>
* <param name="iterations">Degree of approximation</param>
* <param name="period">Period of analyzed function</param>
*/
public FourierSeries(Func<double, double> function, double iterations, double period)
{
Function = function;
Iterations = iterations;
Period = period;
}
/**
* <summary>
* Implements a_n coefficient.
* </summary>
* <param name="n">Number of iteration</param>
* <returns>a_n coefficient</returns>
*/
private double GetA(double n)
{
return (2 / Period) *
GaussLegendreRule.Integrate(
(x) => (Function.Invoke(x) * Math.Cos((2 * n * Math.PI * x) / Period)),
-Period / 2,
Period / 2,
1024);
}
/**
* <summary>
* Implements b_n coefficient.
* </summary>
* <param name="n">Number of iteration</param>
* <returns>b_n coefficient</returns>
*/
private double GetB(double n)
{
return (2 / Period) *
GaussLegendreRule.Integrate(
(x) => (Function.Invoke(x) * Math.Sin((2 * n * Math.PI * x) / Period)),
-Period / 2,
Period / 2,
1024);
}
/**
* <summary>
* Implements a_0 coefficient.
* </summary>
* <returns>a_0 coefficient</returns>
*/
private double GetA0()
{
return (2 / Period) *
GaussLegendreRule.Integrate(
(x) => (Function.Invoke(x)),
-Period / 2,
Period / 2,
1024);
}
/**
* <summary>
* This does superposition of harmonics waves.
* </summary>
* <param name="x">Desired point</param>
* <returns>Superposition of harmonics waves</returns>
*/
public double GetHarmonicWavePoint(double x)
{
double sum = this.GetA0() / 2;
for (int i = 0; i < Iterations; i++)
{
sum = sum +
(GetA(i) * Math.Cos((2 * i * Math.PI * x) / Period) +
GetB(i) * Math.Sin((2 * i * Math.PI * x) / Period));
}
return sum;
}
public Func<double, double> Function { get; set; }
public double Iterations { get; set; }
public double Period { get; set; }
}
}