Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

fft.c

Go to the documentation of this file.
00001 
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <math.h>
00011 #include <malloc.h>
00012 #include <sys/time.h>
00013 #include "tuple.h"
00014 
00015 /************************************************************************************/
00016 
00017 static void compute_W(int n, double *W_re, double *W_im);
00018 static void permute_bitrev(int n, double *A_re, double *A_im);
00019 static int bitrev(int inp, int numbits);
00020 static int log_2(int n);
00021 static void fft(int n, double *A_re, double *A_im, double *W_re, double *W_im);
00022 
00023 /************************************************************************************/
00024 
00035 int main(int argc, char *argv[])
00036 {
00037         struct context ctx;
00038         struct tuple *s, *t, *u;
00039         double *A_re, *A_im, *W_re, *W_im;
00040 
00041         if (get_server_portnumber(&ctx)) {
00042                 if (argc < 3) {
00043                         /* help message */
00044                         fprintf(stderr,
00045                                 "Usage: %s <server> <pornumber>\n",
00046                                 argv[0]);
00047                         return 1;
00048                 }
00049                 strcpy(ctx.servername, argv[1]);
00050                 ctx.portnumber = atoi(argv[2]);
00051         }
00052 
00053         s = make_tuple("s?????", "fft");
00054         t = make_tuple("s???ss", "fft done", "", "");
00055 
00056         while (1) {
00057                 int n;
00058                 u = get_tuple(s, &ctx);
00059                 if (u == NULL) {
00060                         perror("get_tuple failed");
00061                         exit(1);
00062                 }
00063                 A_re = (double*) tuple_string_field(u, &n, 4);
00064                 n /= sizeof(double);
00065                 A_im = (double*) tuple_string_field(u, NULL, 5);
00066 
00067                 W_re = (double*)malloc(sizeof(double)*n/2);
00068                 if (W_re == NULL) {
00069                         fprintf(stderr, "out of memory\n");
00070                         return 1;
00071                 }
00072                 W_im = (double*)malloc(sizeof(double)*n/2);
00073                 if (W_im == NULL) {
00074                         fprintf(stderr, "out of memory\n");
00075                         return 1;
00076                 }
00077 
00078                 compute_W(n, W_re, W_im);
00079                 fft(n, A_re, A_im, W_re, W_im);
00080                 permute_bitrev(n, A_re, A_im);
00081 
00082                 t->elements[1] = u->elements[1];
00083                 t->elements[2] = u->elements[2];
00084                 t->elements[3] = u->elements[3];
00085 
00086                 t->elements[4].data.s.len = n * sizeof(double);
00087                 t->elements[5].data.s.len = n * sizeof(double);
00088                 t->elements[4].data.s.ptr = (char*) A_re;
00089                 t->elements[5].data.s.ptr = (char*) A_im;
00090 
00091                 if (put_tuple(t, &ctx)) {
00092                         perror("put_tuple failed");
00093                         exit(1);
00094                 }
00095                 free(W_re);
00096                 free(W_im);
00097         }
00098 
00099         return 0;
00100 }
00101 
00102 
00103 
00113 static void compute_W(int n, double *W_re, double *W_im)
00114 {
00115         int i, br;
00116         int log2n = log_2(n);
00117 
00118         for (i = 0; i < (n/2); i++) {
00119                 br = bitrev(i,log2n-1);
00120                 W_re[br] = cos(((double)i*2.0*M_PI)/((double)n));
00121                 W_im[br] = sin(((double)i*2.0*M_PI)/((double)n));
00122         }
00123 }
00124 
00125 
00129 static void permute_bitrev(int n, double *A_re, double *A_im)
00130 {
00131         int i, bri, log2n;
00132         double t_re, t_im;
00133 
00134         log2n = log_2(n);
00135 
00136         for (i = 0; i < n; i++) {
00137                 bri = bitrev(i, log2n);
00138 
00139                 /* skip already swapped elements */
00140                 if (bri <= i) continue;
00141 
00142                 t_re = A_re[i];
00143                 t_im = A_im[i];
00144                 A_re[i]= A_re[bri];
00145                 A_im[i]= A_im[bri];
00146                 A_re[bri]= t_re;
00147                 A_im[bri]= t_im;
00148         }
00149 }
00150 
00151 
00156 static int bitrev(int inp, int numbits)
00157 {
00158         int i, rev = 0;
00159         for (i = 0; i < numbits; i++) {
00160                 rev = (rev << 1) | (inp & 1);
00161                 inp >>= 1;
00162         }
00163         return rev;
00164 }
00165 
00166 
00170 static int log_2(int n)
00171 {
00172         int res;
00173         for (res = 0; n >= 2; res++)
00174                 n = n >> 1;
00175         return res;
00176 }
00177 
00188 static void fft(int n, double *A_re, double *A_im, double *W_re, double *W_im)
00189 {
00190         double w_re, w_im, u_re, u_im, t_re, t_im;
00191         int m, g, b;
00192         int mt, k;
00193 
00194         /* for each stage */
00195         for (m = n; m >= 2; m >>= 1) {
00196                 mt = m >> 1;
00197 
00198                 /* for each group of butterfly */
00199                 for (g = 0, k = 0; g < n; g += m, k++) {
00200                         /* each butterfly group uses only one root of
00201                          * unity. actually, it is the bitrev of this
00202                          * group's number k. BUT 'bitrev' it as a
00203                          * log2n-1 bit number because we are using a
00204                          * lookup array of nth root of unity and using
00205                          * cancellation lemma to scale nth root to
00206                          * n/2, n/4,... th root.
00207                          *
00208                          * It turns out like the foll.
00209                          *   w.re = W[bitrev(k, log2n-1)].re;
00210                          *   w.im = W[bitrev(k, log2n-1)].im;
00211                          *
00212                          * Still, we just use k, because the lookup
00213                          * array itself is bit-reversal permuted.
00214                          */
00215                         w_re = W_re[k];
00216                         w_im = W_im[k];
00217 
00218                         /* for each butterfly */
00219                         for (b = g; b < (g+mt); b++) {
00220                                 t_re = w_re * A_re[b+mt] - w_im * A_im[b+mt];
00221                                 t_im = w_re * A_im[b+mt] + w_im * A_re[b+mt];
00222 
00223                                 u_re = A_re[b];
00224                                 u_im = A_im[b];
00225                                 A_re[b] = u_re + t_re;
00226                                 A_im[b] = u_im + t_im;
00227                                 A_re[b+mt] = u_re - t_re;
00228                                 A_im[b+mt] = u_im - t_im;
00229 
00230                         }
00231                 }
00232         }
00233 }

Generated on Sun Mar 30 23:46:49 2003 by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002