home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 9 / 09.iso / l / l042 / 2.ddi / CHAP10.ARC / FFTPROGS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-12-30  |  17.5 KB  |  508 lines

  1. program FFTPrograms;
  2.  
  3. {----------------------------------------------------------------------------}
  4. {-                                                                          -}
  5. {-     Turbo Pascal Numerical Methods Toolbox                               -}
  6. {-     Copyright (c) 1986, 87 by Borland International, Inc.                -}
  7. {-                                                                          -}
  8. {-       Purpose:  This procedure provides I/O routines for using the       -}
  9. {-                 fast Fourier transform, convolution and correlation      -}
  10. {-                 routines.                                                -}
  11. {-                                                                          -}
  12. {-       Unit   :  FFT????.TPU       procedure MakeSinCosTable              -}
  13. {-                                             BitInvert                    -}
  14. {-                                             FFT                          -}
  15. {-                                   procedure RealFFT                      -}
  16. {-                                   procedure RealConvolution              -}
  17. {-                                   procedure RealCorrelation              -}
  18. {-                                   procedure ComplexFFT                   -}
  19. {-                                   procedure ComplexConvolution           -}
  20. {-                                   procedure ComplexCorrelation           -}
  21. {-                                                                          -}
  22. {----------------------------------------------------------------------------}
  23.  
  24. {$I-}      { Disable I/O error trapping  }
  25.  
  26. uses
  27.   FFTB2, Dos, Crt, Common;
  28.  
  29. type
  30.   Analyses = (RF, RN, RC, RA, CF, CN, CC, CA);
  31.  
  32. var
  33.   WhichAnalysis : Analyses;         { Indicates which application  }
  34.                                     { will be run                  }
  35.   NumPoints : integer;              { Number of points  }
  36.   XReal, XImag : TNvectorPtr;       { One set of complex data points  }
  37.   HReal, HImag : TNvectorPtr;       { Another set of complex data points  }
  38.   Inverse : boolean;                { False ==> forward Fourier transform  }
  39.                                     { True ===> inverse Fourier transform  }
  40.   Auto : boolean;                   { False ==> crosscorrelation  }
  41.                                     { True ===> autocorrelation  }
  42.   Error : byte;                     { Flags if something went wrong  }
  43.  
  44. procedure Initialize(var NumPoints : integer;
  45.                      var XReal     : TNvectorPtr;
  46.                      var XImag     : TNvectorPtr;
  47.                      var HReal     : TNvectorPtr;
  48.                      var HImag     : TNvectorPtr;
  49.                      var Error     : byte);
  50.  
  51. {----------------------------------------------------------}
  52. {- Output: NumPoints, XReal, XImag, HReal, HImag, Error   -}
  53. {-                                                        -}
  54. {- This procedure initializes the above variables to zero -}
  55. {----------------------------------------------------------}
  56.  
  57. begin
  58.   NumPoints := 0;
  59.   New(XReal);
  60.   New(XImag);
  61.   New(HReal);
  62.   New(HImag);
  63.   FillChar(XReal^, SizeOf(XReal^), 0);
  64.   FillChar(XImag^, SizeOf(XImag^), 0);
  65.   FillChar(HReal^, SizeOf(HReal^), 0);
  66.   FillChar(HImag^, SizeOf(HImag^), 0);
  67.   Error := 0;
  68. end; { procedure Initialize }
  69.  
  70. procedure GetData(var NumPoints     : integer;
  71.                   var WhichAnalysis : Analyses;
  72.                   var Auto          : boolean;
  73.                   var XReal         : TNvectorPtr;
  74.                   var XImag         : TNvectorPtr;
  75.                   var HReal         : TNvectorPtr;
  76.                   var HImag         : TNvectorPtr);
  77.  
  78. {--------------------------------------------------------------}
  79. {- Output: NumPoints, WhichAnalysis, Auto, XReal, XImag,      -}
  80. {-         HReal, HImag                                       -}
  81. {-                                                            -}
  82. {- This procedure reads in data from either the keyboard      -}
  83. {- or a data file.                                            -}
  84. {--------------------------------------------------------------}
  85.  
  86. var
  87.   Ch : char;
  88.   NumPoints1 : integer;
  89.   NumPoints2 : integer;
  90.  
  91. function TestForPowersOfTwo(NumPoints : integer) : boolean;
  92.  
  93. {---------------------------------------------------------}
  94. {- Input: NumPoints                                      -}
  95. {- Output: TestForPowersOfTwo                            -}
  96. {-                                                       -}
  97. {- This procedure checks if NumPoints is a power of two. -}
  98. {- It returns True if it is, False if it isn't.          -}
  99. {---------------------------------------------------------}
  100.  
  101. type
  102.   ShortArray = array[1..13] of integer;
  103.  
  104. const
  105.   PowersOfTwo : ShortArray = (2, 4, 8, 16, 32, 64, 128, 256,
  106.                               512, 1024, 2048, 4096, 8192);
  107.  
  108. var
  109.   Term : integer;
  110.   Test : boolean;
  111.  
  112. begin
  113.   Test := false; { Assume NumPoints not a power of two  }
  114.   Term := 1;
  115.   while (Term <= 13) and (not Test) do
  116.   begin
  117.     if NumPoints = PowersOfTwo[Term] then
  118.       Test := true; { NumPoints is a power of two  }
  119.     Term := Succ(Term);
  120.   end;
  121.   TestForPowersOfTwo := Test;
  122. end; { function TestForPowersOfTwo }
  123.  
  124. procedure GetRealVectorFromFile(var NumPoints : integer;
  125.                                 var XReal     : TNvectorPtr);
  126.  
  127. {-----------------------------------------------}
  128. {- Output: NumPoints, X                        -}
  129. {-                                             -}
  130. {- This procedure reads in a real vector of    -}
  131. {- data points from a data file.               -}
  132. {-----------------------------------------------}
  133.  
  134. var
  135.   FileName : string[255];
  136.   InFile : text;
  137.  
  138. begin
  139.   Writeln;
  140.   repeat
  141.     Write('File name? ');
  142.     Readln(FileName);
  143.     Assign(InFile, FileName);
  144.     Reset(InFile);
  145.     IOCheck;
  146.   until not IOerr ;
  147.   NumPoints := 0;
  148.   while not EOF(InFile)  do
  149.   begin
  150.     Readln(InFile, XReal^[NumPoints]);
  151.     NumPoints := Succ(NumPoints);
  152.     IOCheck;
  153.   end;
  154.   Close(InFile);
  155. end; { procedure GetRealVectorFromFile }
  156.  
  157. procedure GetComplexVectorFromFile(var NumPoints : integer;
  158.                                    var XReal     : TNvectorPtr;
  159.                                    var XImag     : TNvectorPtr);
  160.  
  161. {-----------------------------------------------}
  162. {- Output: NumPoints, XReal, XImag             -}
  163. {-                                             -}
  164. {- This procedure reads in a complex vector    -}
  165. {- of data points from a data file.            -}
  166. {-----------------------------------------------}
  167.  
  168. var
  169.   FileName : string[255];
  170.   InFile : text;
  171.  
  172. begin
  173.   Writeln;
  174.   repeat
  175.     Write('File name? ');
  176.     Readln(FileName);
  177.     Assign(InFile, FileName);
  178.     Reset(InFile);
  179.     IOCheck;
  180.   until not IOerr;
  181.   NumPoints := 0;
  182.   while not EOF(InFile) do
  183.   begin
  184.     Readln(InFile, XReal^[NumPoints], XImag^[NumPoints]);
  185.     NumPoints := Succ(NumPoints);
  186.     IOCheck;
  187.   end;
  188.   Close(InFile);
  189. end; { procedure GetComplexVectorFromFile }
  190.  
  191. procedure GetRealVectorFromKeyboard(var NumPoints : integer;
  192.                                     var XReal     : TNvectorPtr);
  193.  
  194. {----------------------------------------------}
  195. {- Output: NumPoints, X                       -}
  196. {-                                            -}
  197. {- This procedure reads in a real vector of   -}
  198. {- data points from the keyboard.             -}
  199. {----------------------------------------------}
  200.  
  201. var
  202.   Term : integer;
  203.  
  204. begin
  205.   NumPoints := 0;
  206.   Writeln;
  207.   repeat
  208.     Write('Number of points (a power of two between 2-', TNArraySize + 1,')? ');
  209.     Readln(NumPoints);
  210.     IOCheck;
  211.     IOerr := not TestForPowersOfTwo(NumPoints);
  212.   until (NumPoints >= 2) and (NumPoints <= TNArraySize + 1) and not IOerr;
  213.   Writeln;
  214.   Writeln('Type in the X values:');
  215.   for Term := 0 to NumPoints - 1  do
  216.   repeat
  217.     Write('Real(X[', Term, ']): ');
  218.     Readln(XReal^[Term]);
  219.     IOCheck;
  220.   until not IOerr;
  221. end; { procedure GetRealVectorFromKeyboard }
  222.  
  223. procedure GetComplexVectorFromKeyboard(var NumPoints : integer;
  224.                                        var XReal     : TNvectorPtr;
  225.                                        var XImag     : TNvectorPtr);
  226.  
  227. {-----------------------------------------------}
  228. {- Output: NumPoints, XReal, XImag             -}
  229. {-                                             -}
  230. {- This procedure reads in a complex vector of -}
  231. {- data points from the keyboard.              -}
  232. {-----------------------------------------------}
  233.  
  234. var
  235.   Term : integer;
  236.  
  237. begin
  238.   NumPoints := 0;
  239.   repeat
  240.     Write('Number of points (a power of two between 2-', TNArraySize + 1,')? ');
  241.     Readln(NumPoints);
  242.     IOCheck;
  243.     IOerr := not TestForPowersOfTwo(NumPoints);
  244.   until (NumPoints >= 2) and (NumPoints <= TNArraySize + 1) and not IOerr;
  245.   Writeln;
  246.   Writeln('Type in the X values:');
  247.   for Term := 0 to NumPoints - 1  do
  248.   begin
  249.     repeat
  250.       Write('Real(X[', Term, ']): ');
  251.       Readln(XReal^[Term]);
  252.       IOCheck;
  253.     until not IOerr;
  254.     repeat
  255.       Write('Imaginary(X[', Term, ']): ');
  256.       Readln(XImag^[Term]);
  257.       IOCheck;
  258.     until not IOerr;
  259.   end;
  260. end; { procedure GetComplexVectorFromKeyboard }
  261.  
  262. procedure GetInverse(var Inverse : boolean);
  263.  
  264. var
  265.   Ch : char;
  266.  
  267. begin
  268.   Writeln;
  269.   Write('(F)orward or (I)nverse transform? ');
  270.   repeat
  271.     Ch := UpCase(ReadKey);
  272.   until Ch in ['F', 'I'];
  273.   Writeln(Ch);
  274.   if Ch = 'F' then
  275.     Inverse := false  { Forward transform  }
  276.   else
  277.     Inverse := true;  { Inverse transform  }
  278. end; { procedure GetInverse }
  279.  
  280. begin { procedure GetData }
  281.   Writeln('   1) Real Fast Fourier Transform');
  282.   Writeln('   2) Real Convolution');
  283.   Writeln('   3) Real Autocorrelation');
  284.   Writeln('   4) Real Crosscorrelation');
  285.   Writeln('   5) Complex Fast Fourier Transform');
  286.   Writeln('   6) Complex Convolution');
  287.   Writeln('   7) Complex Autocorrelation');
  288.   Writeln('   8) Complex Crosscorrelation');
  289.   Writeln;
  290.   Write('   Select a number (1-8): ');
  291.   repeat
  292.     Ch := ReadKey;
  293.   until Ch in ['1'..'8'];
  294.  
  295.   Writeln;
  296.   case Ch of
  297.     '1' : begin
  298.             Writeln('********* Real fast Fourier transform *********');
  299.             GetInverse(Inverse);
  300.             WhichAnalysis := RF;
  301.           end;
  302.  
  303.     '2' : begin
  304.             Writeln('********* Real Convolution *********');
  305.             WhichAnalysis := RN;
  306.           end;
  307.  
  308.     '3' : begin
  309.             Writeln('********* Real Autocorrelation *********');
  310.             Auto := true;            { Autocorrelation  }
  311.             WhichAnalysis := RA;
  312.           end;
  313.  
  314.     '4' : begin
  315.             Writeln('********* Real Crosscorrelation *********');
  316.             Auto := false;           { Crosscorrelation  }
  317.             WhichAnalysis := RC;
  318.           end;
  319.  
  320.     '5' : begin
  321.             Writeln('********* Complex fast Fourier transform *********');
  322.             GetInverse(Inverse);
  323.             WhichAnalysis := CF;
  324.           end;
  325.  
  326.     '6' : begin
  327.             Writeln('********* Complex Convolution *********');
  328.             WhichAnalysis := CN;
  329.           end;
  330.  
  331.     '7' : begin
  332.             Writeln('********* Complex Autocorrelation *********');
  333.             Auto := true;            { Autocorrelation  }
  334.             WhichAnalysis := CA;
  335.           end;
  336.  
  337.     '8' : begin
  338.             Writeln('********* Complex Crosscorrelation *********');
  339.             Auto := false;           { Crosscorrelation  }
  340.             WhichAnalysis := CC;
  341.           end;
  342.   end; { case }
  343.  
  344.   Writeln;
  345.   Ch := InputChannel('Input Data From');
  346.   if Ch = 'K' then
  347.     repeat  { Until NumPoints1 := NumPoints2  }
  348.       NumPoints1 := NumPoints2;
  349.       case WhichAnalysis of
  350.         RF, RA : GetRealVectorFromKeyboard(NumPoints, XReal);
  351.  
  352.         RN, RC : begin
  353.                    Writeln;
  354.                    Writeln('The first function:');
  355.                    GetRealVectorFromKeyboard(NumPoints1, XReal);
  356.                    Writeln;
  357.                    Writeln('The 2nd function:');
  358.                    GetRealVectorFromKeyboard(NumPoints2, HReal);
  359.                    if NumPoints1 <> NumPoints2 then
  360.                    begin
  361.                      Writeln;
  362.                      Write('The number of points in these two files');
  363.                      Writeln(' are different.');
  364.                    end;
  365.                    NumPoints := NumPoints1;
  366.                  end;
  367.  
  368.         CF, CA : GetComplexVectorFromKeyboard(NumPoints, XReal, XImag);
  369.  
  370.         CN, CC : begin
  371.                    Writeln;
  372.                    Writeln('The first function:');
  373.                    GetComplexVectorFromKeyboard(NumPoints1, XReal, XImag);
  374.                    Writeln;
  375.                    Writeln('The 2nd function:');
  376.                    GetComplexVectorFromKeyboard(NumPoints2, HReal, HImag);
  377.                    if NumPoints1 <> NumPoints2 then
  378.                    begin
  379.                      Writeln;
  380.                      Write('The number of points in these two files');
  381.                      Writeln(' are different.');
  382.                    end;
  383.                    NumPoints := NumPoints1;
  384.                  end;
  385.       end { case }
  386.     until NumPoints1 = NumPoints2
  387.   else { Ch = 'F' }
  388.     repeat
  389.       NumPoints2 := NumPoints1;
  390.       case WhichAnalysis of
  391.         RF, RA : GetRealVectorFromFile(NumPoints, XReal);
  392.  
  393.         RN, RC : begin
  394.                    Writeln;
  395.                    Writeln('The first function:');
  396.                    GetRealVectorFromFile(NumPoints1, XReal);
  397.                    Writeln;
  398.                    Writeln('The 2nd function:');
  399.                    GetRealVectorFromFile(NumPoints2, HReal);
  400.                    if NumPoints1 <> NumPoints2 then
  401.                    begin
  402.                      Writeln;
  403.                      Write('The number of points in these two files');
  404.                      Writeln(' are different.');
  405.                    end;
  406.                    NumPoints := NumPoints1;
  407.                  end;
  408.  
  409.         CF, CA : GetComplexVectorFromFile(NumPoints, XReal, XImag);
  410.  
  411.         CN, CC : begin
  412.                    Writeln;
  413.                    Writeln('The first function:');
  414.                    GetComplexVectorFromFile(NumPoints1, XReal, XImag);
  415.                    Writeln;
  416.                    Writeln('The 2nd function:');
  417.                    GetComplexVectorFromFile(NumPoints2, HReal, HImag);
  418.                    if NumPoints1 <> NumPoints2 then
  419.                    begin
  420.                      Writeln;
  421.                      Write('The number of points in these two files');
  422.                      Writeln(' are different.');
  423.                    end;
  424.                    NumPoints := NumPoints1;
  425.                  end;
  426.       end; { case }
  427.     until NumPoints1 = NumPoints2;
  428.   GetOutputFile(OutFile);
  429. end; { procedure GetData }
  430.  
  431. procedure Results(NumPoints     : integer;
  432.                   WhichAnalysis : Analyses;
  433.               var XReal         : TNvectorPtr;
  434.               var XImag         : TNvectorPtr;
  435.                   Error         : byte);
  436.  
  437. {------------------------------------------------------------}
  438. {- This procedure outputs the results to the device OutFile -}
  439. {------------------------------------------------------------}
  440.  
  441. var
  442.   Index : integer;
  443.  
  444. begin
  445.   Writeln(OutFile);
  446.   Writeln(OutFile);
  447.   if Error >= 1 then
  448.     DisplayError;
  449.  
  450.   case Error of
  451.     0 : begin
  452.           case WhichAnalysis of
  453.             RF : Writeln(OutFile, 'Results of real Fourier transform:');
  454.             RN : Writeln(OutFile, 'Results of real convolution:');
  455.             RC : Writeln(OutFile, 'Results of real crosscorrelation:');
  456.             RA : Writeln(OutFile, 'Results of real autocorrelation:');
  457.             CF : Writeln(OutFile, 'Results of complex Fourier transform:');
  458.             CN : Writeln(OutFile, 'Results of complex convolution:');
  459.             CC : Writeln(OutFile, 'Results of complex crosscorrelation:');
  460.             CA : Writeln(OutFile, 'Results of complex autocorrelation:');
  461.           end; { case }
  462.  
  463.           for Index := 0 to NumPoints - 1 do
  464.             Writeln(OutFile, XReal^[Index], '    ',  XImag^[Index]);
  465.           Writeln;
  466.         end;
  467.  
  468.     1 : begin
  469.           Writeln(OutFile, 'The number of data points: ', NumPoints);
  470.           Writeln(OutFile, 'There are too few data points.');
  471.         end;
  472.  
  473.     2 : begin
  474.           Writeln(OutFile, 'The number of data points: ', NumPoints);
  475.           Writeln(OutFile,
  476.                   'The number of data points must be a power of two for a');
  477.           Writeln(OutFile,
  478.              'radix-2 transform or a power of four for a radix-4 transform.');
  479.         end;
  480.   end; { case }
  481. end; { procedure Results }
  482.  
  483. begin { program FFTPrograms }
  484.   ClrScr;
  485.   Initialize(NumPoints, XReal, XImag, HReal, HImag, Error);
  486.   GetData(NumPoints, WhichAnalysis, Auto, XReal, XImag, HReal, HImag);
  487.  
  488.   case WhichAnalysis of
  489.     RF : RealFFT(NumPoints, Inverse, XReal, XImag, Error);
  490.     RN : RealConvolution(NumPoints, XReal, XImag, HReal, Error);
  491.     RC : RealCorrelation(NumPoints, Auto, XReal, XImag, HReal, Error);
  492.     RA : RealCorrelation(NumPoints, Auto, XReal, XImag, XReal, Error);
  493.     CF : ComplexFFT(NumPoints, Inverse, XReal, XImag, Error);
  494.     CN : ComplexConvolution(NumPoints, XReal, XImag, HReal, HImag, Error);
  495.     CC : ComplexCorrelation(NumPoints, Auto, XReal, XImag,
  496.                             HReal, HImag, Error);
  497.     CA : ComplexCorrelation(NumPoints, Auto, XReal, XImag,
  498.                             XReal, XImag, Error);
  499.   end; { case }
  500.  
  501.   Results(NumPoints, WhichAnalysis, XReal, XImag, Error);
  502.   Close(OutFile);
  503.   Dispose(XReal);
  504.   Dispose(XImag);
  505.   Dispose(HReal);
  506.   Dispose(HImag);
  507. end. { program FFTPrograms }
  508.