-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathFFT.cs
121 lines (105 loc) · 3.43 KB
/
FFT.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// FFT benchmark adapted from a Fortran routine from the book
// Digital Signal Analysis, Samuel Stearns, Hayden Book Co.
using BenchmarkDotNet.Attributes;
using System.Runtime.CompilerServices;
using MicroBenchmarks;
namespace Benchstone.BenchF
{
[BenchmarkCategory(Categories.Runtime, Categories.Benchstones, Categories.JIT, Categories.BenchF)]
public class FFT
{
public const int Iterations = 300000;
private static readonly int s_points = 16;
[MethodImpl(MethodImplOptions.NoInlining)]
private static void Escape(object _) { }
[Benchmark(Description = nameof(FFT))]
public bool Test()
{
double[] fr = new double[17];
double[] fi = new double[17];
int i;
double t;
for (int iter = 1; iter <= Iterations; iter++)
{
for (i = 1; i <= s_points; ++i)
{
t = ((double)0.375) * ((double)(i - 1));
fr[i] = System.Math.Exp(-t) * System.Math.Sin(t);
fi[i] = 0.0;
}
FastFourierT(fr, fi, s_points);
}
// Escape the results to live-out.
Escape(fr);
Escape(fi);
return true;
}
private static void FastFourierT(double[] fr, double[] fi, int n)
{
int i, j, l, m;
int istep, mr, nn;
double a, el, tr, ti, wr, wi;
mr = 0;
nn = n - 1;
m = 1;
do
{
l = n;
for (l = l / 2; ((mr + l) > nn); l = l / 2)
{
}
// l <= n/2
// mr <= (mr % l) + l ==> mr <= (l - 1) + l = 2l - 1
// ==> mr <= n - 1
mr = (mr % l) + l;
if (mr > m)
{
// Accessing upto m + 1 ==> nn + 1 ==> n - 1 + 1 ==> n
tr = fr[m + 1];
// Accessing upto mr + 1 ==> n - 1 + 1 ==> n
fr[m + 1] = fr[mr + 1];
fr[mr + 1] = tr;
ti = fi[m + 1];
fi[m + 1] = fi[mr + 1];
fi[mr + 1] = ti;
}
++m;
} while (m <= nn);
for (l = 1; l < n; l = istep)
{
istep = 2 * l;
el = ((double)l);
m = 1;
do
{
a = ((double)3.1415926535) * (((double)(1 - m)) / el);
wr = System.Math.Cos(a);
wi = System.Math.Sin(a);
i = m;
do
{
// l can have a maximum value of 2^x where 2^x < n and 2^(x+1) = n, since n is even
// ==> istep <= 2^(x+1) ==> i can only take the value of m and m <= l
// Therefore, j <= l + l
// or j <= 2^x + 2^x = 2^(x+1) = n
// i.e. j <= n
j = i + l;
// Accessing upto j <= n, i <= n
tr = wr * fr[j] - wi * fi[j];
ti = wr * fi[j] + wi * fr[j];
fr[j] = fr[i] - tr;
fi[j] = fi[i] - ti;
fr[i] = fr[i] + tr;
fi[i] = fi[i] + ti;
i += istep;
} while (i <= n);
++m;
} while (m <= l);
}
}
}
}