What algorithm is the following?
What I understand from the following source code is:
dir is the direction of FFT: forward=1, inverse=-1.
x is the real part
y is the imaginary part
What is m here?
If x = {1, 1, 1, 1, 0, 0, 0, 0}, and, y = {0,0,0,0,0,0,0,0,0}, what would be the value of m?
//Inplace 1D FFT
public static void FFT1D(int dir, int m, ref double[] x, ref double[] y)
{
long nn, i, i1, j, k, i2, l, l1, l2;
double c1, c2, tx, ty, t1, t2, u1, u2, z;
/* Calculate the number of points */
nn = 1;
for (i = 0; i < m; i++)
nn *= 2;
/* Do the bit reversal */
i2 = nn >> 1;
j = 0;
for (i = 0; i < nn - 1; i++)
{
if (i < j)
{
tx = x[i];
ty = y[i];
x[i] = x[j];
y[i] = y[j];
x[j] = tx;
y[j] = ty;
}
k = i2;
while (k <= j)
{
j -= k;
k >>= 1;
}
j += k;
}
/* Compute the FFT */
c1 = -1.0;
c2 = 0.0;
l2 = 1;
for (l = 0; l < m; l++)
{
l1 = l2;
l2 <<= 1;
u1 = 1.0;
u2 = 0.0;
for (j = 0; j < l1; j++)
{
for (i = j; i < nn; i += l2)
{
i1 = i + l1;
t1 = u1 * x[i1] - u2 * y[i1];
t2 = u1 * y[i1] + u2 * x[i1];
x[i1] = x[i] - t1;
y[i1] = y[i] - t2;
x[i] += t1;
y[i] += t2;
}
z = u1 * c1 - u2 * c2;
u2 = u1 * c2 + u2 * c1;
u1 = z;
}
c2 = Math.Sqrt((1.0 - c1) / 2.0);
if (dir == 1)
c2 = -c2;
c1 = Math.Sqrt((1.0 + c1) / 2.0);
}
/* Scaling for forward transform */
if (dir == 1)
{
for (i = 0; i < nn; i++)
{
x[i] /= (double)nn;
y[i] /= (double)nn;
}
}
}
The implementation of the FFT you have posted is limited to inputs of size 2m. Here m thus indirectly specify the size of the FFT block size. So, for your example with x = {1,1,1,1,0,0,0,0} and y={1,1,1,1,0,0,0,0} being arrays of size 8=23, m would be equal to 3.
Note that there are no additional checks for the size of the arrays x and y so make sure they are at least that size.
Related
I'm getting x,y,z values from gyro-sensor. Each variable is being sent 10 values per second. In 3 seconds I have;
x=[30values]
y=[30values]
z=[30values]
Some of the values are too different from the others cause of noise. With laplace transform I need to get the most frequent value from my array.
I need to filter the array with Laplace Transform equation. I need to build the equation in C#. How can I implement the array with the equation?
Since this kind of filter (Laplace) is very specialized to certain area of Engineering and needs a person who has good understanding on both the programming language (in this case is C#) and the filter itself, I would recommend you to use such source, rather than code the filter by yourself.
Here is the snippet of the source code:
class Laplace
{
const int DefaultStehfest = 14;
public delegate double FunctionDelegate(double t);
static double[] V; // Stehfest coefficients
static double ln2; // log of 2
public static void InitStehfest(int N)
{
ln2 = Math.Log(2.0);
int N2 = N / 2;
int NV = 2 * N2;
V = new double[NV];
int sign = 1;
if ((N2 % 2) != 0)
sign = -1;
for (int i = 0; i < NV; i++)
{
int kmin = (i + 2) / 2;
int kmax = i + 1;
if (kmax > N2)
kmax = N2;
V[i] = 0;
sign = -sign;
for (int k = kmin; k <= kmax; k++)
{
V[i] = V[i] + (Math.Pow(k, N2) / Factorial(k)) * (Factorial(2 * k)
/ Factorial(2 * k - i - 1)) / Factorial(N2 - k)
/ Factorial(k - 1) / Factorial(i + 1 - k);
}
V[i] = sign * V[i];
}
}
public static double InverseTransform(FunctionDelegate f, double t)
{
double ln2t = ln2 / t;
double x = 0;
double y = 0;
for (int i = 0; i < V.Length; i++)
{
x += ln2t;
y += V[i] * f(x);
}
return ln2t * y;
}
public static double Factorial(int N)
{
double x = 1;
if (N > 1)
{
for (int i = 2; i <= N; i++)
x = i * x;
}
return x;
}
}
coded by Mr. Walt Fair Jr. in CodeProject.
I purchased the book Numerical Methods, Algorithms and Tools in C# by Waldemar Dos Passos.
On page 463, there is the method:
public static double FactorialLn(int n)
{
if(n < 0)
{
throw new Exception("Input value must be > 0");
}
else
{
return GammaLn(n+1.0);
}
}
I found the namespace where the function GammaLn resides: MicrosoftResearch.Infer.Maths
but Visual Studio 2010 does not recognize it and I was unable to find it in the .NET reference.
Please help me get the program to compile.
Thank you in advance.
I finally found the dource code of the GammaLn method itself here: http://seungwon.tistory.com/9
One does need nothing else when one possesses the very real thing, as Andrey correctly pointed out, but until then ...
I reproduce the method here for future reference, in case the site above stops from functioning.
/// <summary>
/// http://seungwon.tistory.com/9
/// GammaLn函数
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
public static double GammaLn(double x)
{
double result = 0.0;
double d1 = -5.772156649015328605195174e-1;
double[,] p1 = {{4.945235359296727046734888e0},{ 2.018112620856775083915565e2},
{2.290838373831346393026739e3},{ 1.131967205903380828685045e4},
{2.855724635671635335736389e4},{ 3.848496228443793359990269e4},
{2.637748787624195437963534e4},{ 7.225813979700288197698961e3}};
double[,] q1 = {{6.748212550303777196073036e1},{ 1.113332393857199323513008e3},
{7.738757056935398733233834e3},{ 2.763987074403340708898585e4},
{5.499310206226157329794414e4},{ 6.161122180066002127833352e4},
{3.635127591501940507276287e4},{ 8.785536302431013170870835e3}};
double d2 = 4.227843350984671393993777e-1;
double[,] p2 = {{4.974607845568932035012064e0},{ 5.424138599891070494101986e2},
{1.550693864978364947665077e4},{ 1.847932904445632425417223e5},
{1.088204769468828767498470e6},{ 3.338152967987029735917223e6},
{5.106661678927352456275255e6},{ 3.074109054850539556250927e6}};
double[,] q2 = {{1.830328399370592604055942e2},{ 7.765049321445005871323047e3},
{1.331903827966074194402448e5},{ 1.136705821321969608938755e6},
{5.267964117437946917577538e6},{ 1.346701454311101692290052e7},
{1.782736530353274213975932e7},{ 9.533095591844353613395747e6}};
double d4 = 1.791759469228055000094023e0;
double[,] p4 = {{1.474502166059939948905062e4},{ 2.426813369486704502836312e6},
{1.214755574045093227939592e8},{ 2.663432449630976949898078e9},
{2.940378956634553899906876e10},{ 1.702665737765398868392998e11},
{4.926125793377430887588120e11},{5.606251856223951465078242e11}};
double[,] q4 = {{2.690530175870899333379843e3},{ 6.393885654300092398984238e5},
{4.135599930241388052042842e7},{ 1.120872109616147941376570e9},
{1.488613728678813811542398e10},{1.016803586272438228077304e11},
{3.417476345507377132798597e11},{ 4.463158187419713286462081e11}};
double[,] c = {{-1.910444077728e-03},{ 8.4171387781295e-04},
{-5.952379913043012e-04},{ 7.93650793500350248e-04},
{-2.777777777777681622553e-03},{ 8.333333333333333331554247e-02},
{ 5.7083835261e-03}};
double eps = 2.2204e-016;
if (x <= 0)
{
//报错!
}
else
{
double xden = 0.0;
double xnum = 0.0;
result = x;
if (x > 0 && x <= eps)
{
result = -Math.Log(x);
}
else if ((x > eps) && (x <= 0.5))
{
double y = x;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * y + p1[i, 0];
xden = xden * y + q1[i, 0];
}
result = -Math.Log(y) + (y * (d1 + y * (xnum / xden)));
}
else if ((x > 0.5) && (x <= 0.6796875))
{
double xm1 = (x - 0.5) - 0.5;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm1 + p2[i, 0];
xden = xden * xm1 + q2[i, 0];
}
result = -Math.Log(x) + xm1 * (d2 + xm1 * (xnum / xden));
}
else if ((x > 0.6796875) && (x <= 1.5))
{
double xm1 = (x - 0.5) - 0.5;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm1 + p1[i, 0];
xden = xden * xm1 + q1[i, 0];
}
result = xm1 * (d1 + xm1 * (xnum / xden));
}
else if ((x > 1.5) && (x <= 4))
{
double xm2 = x - 2;
xden = 1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm2 + p2[i, 0];
xden = xden * xm2 + q2[i, 0];
}
result = xm2 * (d2 + xm2 * (xnum / xden));
}
else if ((x > 4) && (x <= 12))
{
double xm4 = x - 4;
xden = -1;
xnum = 0;
for (int i = 0; i < 8; i++)
{
xnum = xnum * xm4 + p4[i, 0];
xden = xden * xm4 + q4[i, 0];
}
result = d4 + xm4 * (xnum / xden);
}
else if (x > 12)
{
double y = x;
double r = c[6, 0];// 等于:double r = repmat(c[6, 0], 1)[0,0];
double ysq = y * y;
for (int i = 0; i < 6; i++)
{
r = r / ysq + c[i, 0];
}
r = r / y;
double corr = Math.Log(y);
double spi = 0.9189385332046727417803297;
result = r + spi - 0.5 * corr + y * (corr - 1);
}
}
return result;
}
I'm trying to transform a function to make it execute in parallel instead of sequential in C#, but I'm not sure what I'm doing wrong:
// sequential
static void Romberg(double a, double b, int n, double[,] R)
{
int i, j, k;
double h, sum;
h = b - a;
R[0, 0] = (h / 2) * (f(a) + f(b));
for (i = 1; i <= n; i++)
{
h = h / 2;
sum = 0;
for (k = 1; k <= (Math.Pow(2.0, i) - 1); k += 2)
{
sum += f(a + k * h);
}
R[i, 0] = R[i - 1, 0] / 2 + sum * h;
for (j = 1; j <= i; j++)
{
R[i, j] = R[i, j - 1] + (R[i, j - 1] - R[i - 1, j - 1]) / (Math.Pow(4.0, j) - 1);
}
}
}
// parallel
static void RombergCP(double a, double b, int n, double[,] R)
{
int i,j, k;
double h, sum;
h = b - a;
R[0, 0] = (h / 2) * (f(a) + f(b));
Parallel.For(0, n, options, i =>
{
h = h / 2;
sum = 0;
for (k = 1; k <= (Math.Pow(2.0, i) - 1); k += 2)
{
sum += f(a + k * h);
};
R[i, 0] = R[i - 1, 0] / 2 + sum * h;
for (j = 1; j <= i; j++)
{
R[i, j] = R[i, j - 1] + (R[i, j - 1] - R[i - 1, j - 1]) / (Math.Pow(4.0, j) - 1);
}
});
}
The error I'm getting is that "i" cannot be declared because it would give a different meaning to "i", which is used in a "parent or current" scope.
I tried renaming it to i2 in the parallel function but it gives the same error. Thanks in advance!
Remove the declaration of int i at the very top. It is declared by the lambda below.
A couple of issues:
declare variables in the smallest scope possible.
Your outer loop goes from for (i = 1; i <= n; i++) to Parallel.For(0, n, options, ...), that means R[i-1, ...] will throw in the Parallel version.
h = h / 2; is not thread-safe.
// parallel
static void RombergCP(double a, double b, int n, double[,] R)
{
//int i,j, k;
//double h, sum;
double h0 = b - a;
R[0, 0] = (h0 / 2) * (f(a) + f(b));
Parallel.For(1, n, options, i => // start at 1
{
//h = h / 2;
double h = (b - a) / Math.Pow(2, i); // derive from i
double sum = 0;
for (int k = 1; k <= (Math.Pow(2.0, i) - 1); k += 2) // keep k local
...
I've done a fft to get fundamental frequency in real time and to implement high and low pass filters.
Now I want to be able to record to a .wav file after I apply a filter.
First I'll have to invert the fft and that is my question.
What are the steps to do this?
I use the FFT defined in this project.
Here is the code for it:
using System;
using System.Collections.Generic;
using System.Text;
namespace SoundLog
{
public class FourierTransform
{
static private int n, nu;
static private int BitReverse(int j)
{
int j2;
int j1 = j;
int k = 0;
for (int i = 1; i <= nu; i++)
{
j2 = j1 / 2;
k = 2 * k + j1 - 2 * j2;
j1 = j2;
}
return k;
}
static public double[] FFT(ref double[] x)
{
// Assume n is a power of 2
n = x.Length;
nu = (int)(Math.Log(n) / Math.Log(2));
int n2 = n / 2;
int nu1 = nu - 1;
double[] xre = new double[n];
double[] xim = new double[n];
double[] magnitude = new double[n2];
double[] decibel = new double[n2];
double tr, ti, p, arg, c, s;
for (int i = 0; i < n; i++)
{
xre[i] = x[i];
xim[i] = 0.0f;
}
int k = 0;
for (int l = 1; l <= nu; l++)
{
while (k < n)
{
for (int i = 1; i <= n2; i++)
{
p = BitReverse(k >> nu1);
arg = 2 * (double)Math.PI * p / n;
c = (double)Math.Cos(arg);
s = (double)Math.Sin(arg);
tr = xre[k + n2] * c + xim[k + n2] * s;
ti = xim[k + n2] * c - xre[k + n2] * s;
xre[k + n2] = xre[k] - tr;
xim[k + n2] = xim[k] - ti;
xre[k] += tr;
xim[k] += ti;
k++;
}
k += n2;
}
k = 0;
nu1--;
n2 = n2 / 2;
}
k = 0;
int r;
while (k < n)
{
r = BitReverse(k);
if (r > k)
{
tr = xre[k];
ti = xim[k];
xre[k] = xre[r];
xim[k] = xim[r];
xre[r] = tr;
xim[r] = ti;
}
k++;
}
for (int i = 0; i < n / 2; i++)
//magnitude[i] = (float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i])));
decibel[i] = 10.0 * Math.Log10((float)(Math.Sqrt((xre[i] * xre[i]) + (xim[i] * xim[i]))));
//return magnitude;
return decibel;
}
}
}
There are so many really good fft implementations around such as FFTW that I highly recommend using one. They come with ifft as well. Yours, as implemented, will be excruciatingly slow.
I'm trying to implement, in C#, for my own learning, an FFT algorithm described here:
https://en.wikipedia.org/wiki/Cooley%E2%80%93Tukey_FFT_algorithm
under "Data reordering, bit reversal, and in-place algorithms".
My code is as follows, with some background operator overloading for the "cplx" structure to allow me to do arithmetic on these objects.
Bitreverse seems to work fine, and so does the "twiddle factor" calculation, so I'm not sure where I've gone wrong. The code looks awfully similar to the pseudocode given on the wiki page.
public cplx[] FFT(cplx[] x)
{
//Bitreverse Copy
cplx[] a = BitReverse(x);
//Number of points
int n = a.Length;
for (int s = 1; s <= Math.Log(n); s++)
{
int m = (int)Math.Pow(2,s);
cplx w_m = Omega(m);
for (int k = 0; k < n; k += m)
{
cplx w = new cplx(1, 0);
for(int j = 0; j < m/2; j++)
{
cplx t = w * a[k + j + (m / 2)];
cplx u = a[k + j];
a[k + j] = u + t;
a[k + j + (m / 2)] = u - t;
w = w * w_m;
}
}
}
return a;
}
I'm testing it with an input array of an origin-impulse with 8 samples, which should produce a constant output.
Instead, I'm getting 4 ones and 4 zeros, in that order.
As an aside, I assume that in the pseudocode:
for k = 0 to n-1 by m
Refers to for(k = 0; k < n; k += m) although I'm not sure that's right.
Hopefully someone can shed some light on my incompetence!
Cheers.
Here's the code for bitreversal and the omega calculation.
private int Rev(int x, int k)
{
int reversed = 0;
for (int i = 0; i < k; i++)
{
reversed |= (x & (1 << i)) != 0 ? 1 << (k - 1 - i) : 0;
}
return reversed;
}
public cplx[] BitReverse(cplx[] x)
{
cplx[] r = new cplx[x.Length];
int bits = (int)Math.Log(x.Length, 2);
for(int k = 0; k < x.Length; k++)
{
r[Rev(k, bits)] = x[k];
}
return r;
}
private cplx Omega(int m)
{
float x = (- 2 * (float)Math.PI) / m;
return new cplx((float)Math.Cos(x), (float)(Math.Sin(x)));
}
I should have been using log2(n) when I was using Math.Log().