From 8bcdbf2918d2e4098d66b1ae7080539514a53770 Mon Sep 17 00:00:00 2001 From: Panayotis Skordos Date: Thu, 7 Jan 1988 21:32:15 +0000 Subject: [PATCH] added array-czt (chirp-z-transform) added array-hanning (windowing) fixed DFT definition to agree with Seibert --- v7/src/microcode/fft.c | 672 +++++++++++++++++++---------------------- 1 file changed, 314 insertions(+), 358 deletions(-) diff --git a/v7/src/microcode/fft.c b/v7/src/microcode/fft.c index da82006ab..f33cfb251 100644 --- a/v7/src/microcode/fft.c +++ b/v7/src/microcode/fft.c @@ -30,9 +30,13 @@ Technology nor of any adaptation thereof in any advertising, promotional, or sales literature without prior written consent from MIT in each case. */ -/* $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/fft.c,v 9.22 1987/12/12 19:13:51 pas Rel $ */ +/* $Header: /Users/cph/tmp/foo/mit-scheme/mit-scheme/v7/src/microcode/Attic/fft.c,v 9.23 1988/01/07 21:32:15 pas Rel $ */ -/* Fast Fourier Transforms (pas) */ +/* Fourier Transforms (pas) + 1. DFT (FFT), + 2. CZT (chirp-z-transform). + 3. 2D DFT + */ #include "scheme.h" #include "primitive.h" @@ -41,10 +45,36 @@ MIT in each case. */ #include #include "array.h" #include "image.h" - + +/* The following implement the DFT as defined in Seibert's Book (6003). + FORWARD DFT ---- Negative exponent and division by N + BACKWARD DFT --- Positive exponent + Note: Seibert's Forward DFT is Oppenheim's Backward DFT. + */ + +#define PI 3.141592653589793238462643 +#define TWOPI 6.283185307179586476925287 +/* Abramowitz and Stegun */ + +void Make_FFT_Tables(w1, w2, n, flag) + REAL *w1, *w2; long n, flag; /* n = length of data */ +{ long m, n2=n/2; /* n2 = length of w1,w2 */ + double tm; + if (flag==1) /* FORWARD FFT */ + for (m=0; m>1, a; long i, l, m; - REAL twopi = 6.28318530717958, tm, k; - - a = n; /* initially equal to length */ - if (flag == 1) k=1.0; - else k = -1.0; - /* if ( nu > 12 ) Primitive_Error(ERR_ARG_2_BAD_RANGE); */ /* maximum power FFT */ + REAL tm; + a = n; /* initially equal to length of data */ - for (m=0; m do one more mult */ - mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ - }} - else { /* backward fft */ - tm = 1. / ((REAL) n); /* normalizing factor */ - if (l==1) { /* even power */ - for (m=0; m do one more mult */ - mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ - for (m=0; m do one more mult */ + mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ + for (m=0; m do one more mult */ + mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ } } - -C_Array_FFT_With_Given_Tables(flag, nu, n, f1, f2, g1,g2,w1,w2) - long flag, nu, n; REAL f1[], f2[], g1[], g2[], w1[], w2[]; + +void C_Array_FFT_With_Given_Tables(flag, power, n, f1, f2, g1,g2,w1,w2) + long flag, power, n; REAL f1[], f2[], g1[], g2[], w1[], w2[]; { long n2=n>>1, a; long i, l, m; - REAL twopi = 6.28318530717958, tm, k; + REAL tm; + a = n; /* initially equal to length */ + + for (m=0; m do one more mult */ + mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ + for (m=0; m do one more mult */ + mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ } - +} + + +/* CHIRP-Z-TRANSFORM (for complex data) + */ + +#define take_modulo_one(x, answer) \ +{ long ignore_integral_part; \ + double modf(); \ + answer = (REAL) modf( ((double) x), &ignore_integral_part); } + +#define power_of_2_to_power(n,power) \ +{ long i; \ + for (power=0,i=n; i>1; power++) \ + { if ((i%2) == 1) { printf("\nNot a power of 2--- %d\n",n); exit(1); } \ + i=i/2; }} + +long smallest_power_of_2_ge(n) + long n; +{ long i,power; + if (n<0) { printf("\nsmallest_pwr_of_2_ge negative argument--- %d\n", n); exit(1); } + power=0; i=1; + while (i do one more mult */ - mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ - }} - else { /* backward fft */ - tm = 1. / ((REAL) n); /* normalizing factor */ - if (l==1) { /* even power */ - for (m=0; m do one more mult */ - mult(g1,g2,f1,f2,w1,w2); /* f1 and f2 contain the result now */ - for (m=0; m1; ncols_power++) { /* FIND/CHECK POWERS OF ROWS,COLS */ + + for (ncols_power=0, i=ncols; i>1; ncols_power++) { /* FIND/CHECK POWERS OF ROWS,COLS */ if ( (i % 2) == 1) Primitive_Error(ERR_ARG_2_BAD_RANGE); i=i/2; } for (nrows_power=0, i=nrows; i>1; nrows_power++) { @@ -210,8 +323,8 @@ C_Array_2D_FFT_In_Scheme_Heap(flag, nrows, ncols, Real_Array, Imag_Array) g2 = Work_Here + ncols; w1 = Work_Here + (ncols<<1); w2 = Work_Here + (ncols<<1) + (ncols>>1); - Make_Twiddle_Tables(w1,w2,ncols, flag); - for (i=0;i>1); - Make_Twiddle_Tables(w1,w2,nrows,flag); - for (i=0;i1; nrows_power++) { /* FIND/CHECK POWERS OF ROWS */ + for (nrows_power=0, i=nrows; i>1; nrows_power++) { /* FIND/CHECK POWERS OF ROWS */ if ( (i % 2) == 1) Primitive_Error(ERR_ARG_2_BAD_RANGE); i=i/2; } Primitive_GC_If_Needed(nrows*3*REAL_SIZE); @@ -253,21 +366,21 @@ Square_Image_2D_FFT_In_Scheme_Heap(flag, nrows, Real_Array, Imag_Array) g2 = Work_Here + nrows; w1 = Work_Here + (nrows<<1); w2 = Work_Here + (nrows<<1) + (nrows>>1); - Make_Twiddle_Tables(w1, w2, nrows, flag); /* MAKE TABLES */ - for (i=0;i>1); - Make_Twiddle_Tables(w1, w2, ndeps, flag); /* MAKE TABLES */ + Make_FFT_Tables(w1, w2, ndeps, flag); /* MAKE TABLES */ Surface_Length=ndeps*ndeps; From_Real = Real_Array; From_Imag = Imag_Array; @@ -337,38 +450,35 @@ Cube_Space_3D_FFT_In_Scheme_Heap(flag, ndeps, Real_Array, Imag_Array) } -/********************** below scheme primitives **********************/ +/*----------------------- scheme primitives ------------------------- */ -/* NOTE: IF Arg2 and Arg3 are EQ?, then it signals an error! */ -/* (Arg1 = 1 ==> forward FFT), otherwise inverse FFT */ +/* Real and Imag arrays must be different. + Arg1=1 --> forward FFT, otherwise backward. + */ Define_Primitive(Prim_Array_FFT, 3, "ARRAY-FFT!") -{ long length, length1, power, flag, i; +{ long length, power, flag, i; Pointer answer; REAL *f1,*f2,*g1,*g2,*w1,*w2; REAL *Work_Here; - Primitive_3_Args(); - Arg_1_Type(TC_FIXNUM); /* flag */ - Arg_2_Type(TC_ARRAY); /* real */ - Arg_3_Type(TC_ARRAY); /* imag */ + Arg_1_Type(TC_FIXNUM); /* flag */ + Arg_2_Type(TC_ARRAY); /* real */ + Arg_3_Type(TC_ARRAY); /* imag */ Set_Time_Zone(Zone_Math); - flag = Get_Integer(Arg1); + flag = Get_Integer(Arg1); length = Array_Length(Arg2); - length1 = Array_Length(Arg3); - - if (length != length1) Primitive_Error(ERR_ARG_2_BAD_RANGE); + if (length != (Array_Length(Arg3))) Primitive_Error(ERR_ARG_2_BAD_RANGE); power=0; for (power=0, i=length; i>1; power++) { if ( (i % 2) == 1) Primitive_Error(ERR_ARG_2_BAD_RANGE); - i=i/2; - } + i=i/2; } f1 = Scheme_Array_To_C_Array(Arg2); f2 = Scheme_Array_To_C_Array(Arg3); if (f1==f2) Primitive_Error(ERR_ARG_2_WRONG_TYPE); - + Primitive_GC_If_Needed(length*3*REAL_SIZE); Work_Here = (REAL *) Free; g1 = Work_Here; @@ -387,235 +497,83 @@ Define_Primitive(Prim_Array_FFT, 3, "ARRAY-FFT!") *Free++ = NIL; return answer; } - -Define_Primitive(Prim_Array_2D_FFT, 5, "ARRAY-2D-FFT!") -{ long flag, i, j; - Pointer answer; - REAL *Real_Array, *Imag_Array, *Temp_Array; - REAL *f1,*f2,*g1,*g2,*w1,*w2; - REAL *Work_Here; - long Length, nrows, ncols, nrows_power, ncols_power; - - Primitive_5_Args(); - Arg_1_Type(TC_FIXNUM); /* flag */ - Range_Check(nrows, Arg2, 1, 512, ERR_ARG_2_BAD_RANGE); - Range_Check(ncols, Arg3, 1, 512, ERR_ARG_3_BAD_RANGE); - Arg_4_Type(TC_ARRAY); /* real image */ - Arg_5_Type(TC_ARRAY); /* imag image */ - Set_Time_Zone(Zone_Math); /* for timing */ - - Sign_Extend(Arg1, flag); /* should be 1 or -1 */ - Length = Array_Length(Arg4); - if (Length != (nrows*ncols)) Primitive_Error(ERR_ARG_5_BAD_RANGE); - if (Length != (Array_Length(Arg5))) Primitive_Error(ERR_ARG_5_BAD_RANGE); - Real_Array = Scheme_Array_To_C_Array(Arg4); - Imag_Array = Scheme_Array_To_C_Array(Arg5); - if (f1==f2) Primitive_Error(ERR_ARG_5_WRONG_TYPE); - - for (ncols_power=0, i=ncols; i>1; ncols_power++) { /* FIND/CHECK POWERS OF ROWS,COLS */ - if ( (i % 2) == 1) Primitive_Error(ERR_ARG_2_BAD_RANGE); - i=i/2; } - for (nrows_power=0, i=nrows; i>1; nrows_power++) { - if ( (i % 2) == 1) Primitive_Error(ERR_ARG_1_BAD_RANGE); - i=i/2; } - - if (nrows==ncols) { /* SQUARE IMAGE, OPTIMIZE... */ - Primitive_GC_If_Needed(nrows*3*REAL_SIZE); - Work_Here = (REAL *) Free; - g1 = Work_Here; - g2 = Work_Here + ncols; - w1 = Work_Here + (ncols<<1); - w2 = Work_Here + (ncols<<1) + (ncols>>1); - for (i=0;i>1); - for (i=0;i>1); - for (i=0;i1; ncols_power++) { /* FIND/CHECK POWERS OF ROWS,COLS */ - if ( (i % 2) == 1) Primitive_Error(ERR_ARG_2_BAD_RANGE); - i=i/2; } - for (nrows_power=0, i=nrows; i>1; nrows_power++) { - if ( (i % 2) == 1) Primitive_Error(ERR_ARG_1_BAD_RANGE); - i=i/2; } - - if (nrows==ncols) { /* SQUARE IMAGE, OPTIMIZE... */ - Primitive_GC_If_Needed(nrows*3*REAL_SIZE); - Work_Here = (REAL *) Free; - g1 = Work_Here; - g2 = Work_Here + ncols; - w1 = Work_Here + (ncols<<1); - w2 = Work_Here + (ncols<<1) + (ncols>>1); - Make_Twiddle_Tables(w1, w2, ncols, flag); /* MAKE TABLES */ - for (i=0;i>1); - Make_Twiddle_Tables(w1,w2,ncols, flag); - for (i=0;i>1); - Make_Twiddle_Tables(w1,w2,nrows,flag); - for (i=0;i