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().
Related
The number of can types to be distinguished is N, and each can has L types of characteristics that can be answered with 1 or 0. Your objective is to distinguish between all N types of can by memorizing the characteristics of as few of the L types as possible.
All test cases satisfy the following conditions:
2 ≤ N ≤ 100
1 ≤ L ≤ 8・0 ≤ X_{i, j} ≤ 1(1 ≤ i ≤ N
1 ≤ j ≤ L)
definitely distinguishable.
using System;
namespace CanDistinguisher
{
class Program
{
static void Main(string[] args)
{
// Read the number of can types and number of features
string[] input = Console.ReadLine().Split();
int N = int.Parse(input[0]);
int L = int.Parse(input[1]);
// Read the answers to the questions for each feature
int[,] cans= new int[N, L];
for (int i = 0; i < N; i++)
{
input = Console.ReadLine().Split();
for (int j = 0; j < L; j++)
{
cans[i, j] = int.Parse(input[j]);
}
}
// Find the minimum number of features required to distinguish all N types of can
int result = L;
for (int i = 0; i < (1 << L); i++)
{
int[] group = new int[N];
for (int j = 0; j < N; j++)
{
for (int k = 0; k < L; k++)
{
if (((i >> k) & 1) == 1)
{
group[j] |= (cans[j, k] << k);
}
}
}
bool flag = true;
for (int j = 0; j < N; j++)
{
for (int k = j + 1; k < N; k++)
{
if (group[j] == group[k])
{
flag = false;
break;
}
}
}
if (flag)
{
int count = 0;
for (int j = 0; j < L; j++)
{
if (((i >> j) & 1) == 1)
{
count++;
}
}
result = Math.Min(result, count);
}
}
// Output the result
Console.WriteLine(result);
}
}
}
In this program I did not understand the logic. If someone can help me understand the logic. For example why are they doing this particular line.
if (((i >> k) & 1) == 1)
{
group[j] |= (cans[j, k] << k);
}
I still don't understand the bitwise operators and its use cases. If someone can help me understand the complete code and its logic would be very helpful.
Thank you in advance.
I recently translated some python code into c#. The c# function is working fine and results in the same output as the python one. However, it takes about 15 times longer. This is mostly due to one of my functions which calculates the cross-correlation of two vectors and takes much longer than numpy's correlate(a,b,"full")
I wrote (assume a and b are of the same length):
double[] CrossCorr(double[] a, double[] b)
{
int l = a.Length;
int jmin, jmax, index;
index = 0;
int lmax = 2*l - 1;
double[] z = new double[lmax];
for (int i = 0; i < lmax; i++)
{
if (i >= l)
{
jmin = i - l + 1;
jmax = l - 1;
}
else
{
jmax = i;
jmin = 0;
}
for (int j = jmin; j <= jmax; j++)
{
index = l - i + j - 1;
z[i] += (a[j] * b[index]);
}
}
return z;
}
Another attempt was to use the known equation:
corr(a, b) = ifft(fft(a_and_zeros) * conj(fft(b_and_zeros)))
which resulted in this function (using Math.Net):
double[] Corrcorfour(double[] a, double[] b)
{
//Fourier transformation
Complex[] distrib_Pr_Com = new Complex[a.Count()];
Complex[] distrib_Pi_noise_Com = new Complex[b.Count()];
for (int k = 0; k < x_count; k++)
{
distrib_Pr_Com[k] = (Complex)a[k];
distrib_Pi_noise_Com[k] = (Complex)b[k];
}
MathNet.Numerics.IntegralTransforms.Fourier.Forward(distrib_Pi_noise_Com);
MathNet.Numerics.IntegralTransforms.Fourier.Forward(distrib_Pr_Com);
//complex conj
for (int k = 0; k < distrib_Pi_noise_Com.Count(); k++)
{
distrib_Pi_noise_Com[k] = Complex.Conjugate(distrib_Pi_noise_Com[k]);
}
//multiply results
Complex[] test = new Complex[distrib_Pr_Com.Count()];
for (int k = 0; k < distrib_Pr_Com.Count(); k++)
{
test[k] = Complex.Multiply(distrib_Pr_Com[k], distrib_Pi_noise_Com[k]);
}
//transformierenback
MathNet.Numerics.IntegralTransforms.Fourier.Inverse(test);
//transform to double
double[] finish = new double[test.Count()];
for (int k = 0; k < test.Count(); k++)
{
finish[k] = test[k].Real;
}
return finish;
}
However, this function somehow throws out an array of different lengths and with different results (so it's wrong). It is also only 2 times quicker than the first function, which would still not be enough.
I tried to look up some other people functions but they didn't seem to do it much differently from either of the two. is there a shortcut I'm not seeing, or an error?
I found a few similar questions but I didn't find a satisfying answer in any of them.
One option to speed this up significantly would just be to run it in a parallel loop since every output index is not affected by the others. I believe that numpy does use parallelism as well. I'm sure there's some other optimizations per thread, but this should be a good start.
public static double[] CrossCorrParallel(double[] a, double[] b)
{
int l = a.Length;
int lmax = 2 * l - 1;
double[] z = new double[lmax];
Parallel.For(0, lmax, (i) =>
{
int jmin, jmax, index;
if (i >= l)
{
jmin = i - l + 1;
jmax = l - 1;
}
else
{
jmax = i;
jmin = 0;
}
for (int j = jmin; j <= jmax; j++)
{
index = l - i + j - 1;
z[i] += (a[j] * b[index]);
}
});
return z;
}
My benchmarks are here, note that I am using a 10850k with 10 cores (20 threads):
| Method | Mean | Error | StdDev |
|------------- |----------:|---------:|---------:|
| TestOrig | 189.32 ms | 0.150 ms | 0.133 ms |
| TestParallel | 11.49 ms | 0.221 ms | 0.206 ms |
I am trying to perform Cross Correlation on these 2 images in C#:
Image, Template
Matlab says the result is supposed to look like: Matlab result
But this is my result: My result
Here is my Cross Correlation function:
public static Signal2D CrossCorrelation2D(Signal2D signal, Signal2D pulse) {
return InverseFFT2D(FFT2D(signal) * FFT2D(pulse).GetConjugate());
}
Here is my FFT2D:
public static Signal2D FFT2D(Signal2D signal) {
Signal2D result = new Signal2D(signal.Height, signal.Width);
for (int i = 0; i < result.Height; i++)
result[i] = new ComplexNumber[signal[i].Length];
//rows
for (int n = 0; n < signal.Height; n++) {
result[n] = FFT(signal[n]);
}
//columns
for (int i = 0; i < signal[0].Length; i++) {
ComplexNumber[] col = new ComplexNumber[signal.Height];
for (int j = 0; j < col.Length; j++) {
col[j] = result[j][i];
}
col = FFT(col);
for (int j = 0; j < col.Length; j++) {
result[j][i] = col[j];
}
}
return result;
}
Here is my FFT:
public static Signal FFT(Signal signal) {
int N = signal.Length;
if (N == 1)
return signal;
if ((N & (N - 1)) != 0)
throw new ArgumentOutOfRangeException("signal length must be a power of 2");
Signal evenArr = new Signal(N / 2);
Signal oddArr = new Signal(N / 2);
for (int i = 0; i < N / 2; i++) {
evenArr[i] = signal[2 * i];
}
evenArr = FFT(evenArr);
for (int i = 0; i < N / 2; i++) {
oddArr[i] = signal[2 * i + 1];
}
oddArr = FFT(oddArr);
Signal result = new Signal(N);
for (int k = 0; k < N / 2; k++) {
double w = -2.0 * k * Math.PI / N;
ComplexNumber wk = new ComplexNumber(Math.Cos(w), Math.Sin(w));
ComplexNumber even = evenArr[k];
ComplexNumber odd = oddArr[k];
result[k] = even + (wk * odd);
result[k + N / 2] = even - (wk * odd);
}
return result;
}
Here is my Signal multiplication (using pointwise multiplication):
public static Signal2D operator* (Signal2D a, Signal2D b) {
if (a.Height != b.Height || a.Width != b.Width)
throw new ArgumentException("Sizes must be equal");
Signal2D result = new Signal2D(a.Height, a.Width);
for (int y = 0; y < a.Height; y++) {
for (int x = 0; x < a.Width; x++) {
result[y][x] = a[y][x] * b[y][x];
}
}
return result;
}
Any help is appreciated, thanks.
Edit: I left the matlab image at the original size of 1023 by 1023 and overlayed my result. It looks like I may already be at the result, I am just not sure how Matlab pads the image. Overlayed results (The red is the white part from my result, the grey is the black part from my result. Black/white is from Matlab)
I'm trying to solve homework for school, it concerns KMP algorithm. Here is my compute prefix function, it is suppose to output a prefix table, however all it does is every time it returns all 0s. Could help me understand what am I doing wrong? Thanks!
static int[] computePrefixFunction(string P)
{
int m = P.Length;
int[] pi = new int[m];
pi[1] = 0;
int k = 0;
for (int j = 2; j < m; j++)
{
while (k > 0 && P[k + 1] != P[j])
{
k = pi[k];
}
if (P[k+1] == P[j])
{ k = k + 1; };
pi[j] = k;
}
for (int i = 0; i < pi.Length; i++)
{
Console.WriteLine(pi[i]);
}
return pi;
}
You a have messed up indexes offsets. Here is fixed version:
static int[] computePrefixFunction(string P)
{
int m = P.Length;
int[] pi = new int[m];
int k = 0;
for (int j = 1; j < m; j++)
{
k = pi[j - 1];
while (k > 0 && P[k] != P[j])
k = pi[k-1];
if (P[k] == P[j])
k = k + 1;
pi[j] = k;
}
return pi;
}
Live demo: https://dotnetfiddle.net/YQknMp
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.