#
# A Maple Package for the calculation of the Fast Fourier Transform.
# 
# COPYRIGHT NOTICE:
# Copyright (c) September 1993 by Stephen Earl.
#  
# Permission is granted to anyone to to use, modify, or redistribute this
# software freely, subject to the following restrictions:
# 
# 1. The author accepts no responsibility for any consequences of this
#    software and makes no guarantee that the software is free of defects.
#
# 2. The origin of this software must not be misrepresented, either by
#    explicit claim or by omission.
#
# 3. This notice and the copyright must be included in all copies or
#    altered versions of this software.
#
# 4. This software may not be included or redistributed as part of any
#    package to be sold for profit unless the author has given explicit 
#    written permission to do so.
# 
# Stephen Earl
# 3 Faygate Crescent
# Bexleyheath
# Kent DA6 7NS
# England
#
# Telephone 0332 529615 
#
#############################################################################


fft := proc(datasize : integer, Rin : array, Iin : array,
            Rtrans : array, Itrans : array, domain : boolean)

local csn,expt,j,k,m,n,omega,p,perm,pwr,sign,size,sne,temp,total,u,v;

  if nargs <> 6 then 
    ERROR(`Incorrect number of arguments`);
  elif domain = true then 
    sign := -1;
  elif domain = false then 
    sign := 1;
  fi;

    n := datasize;

  while n > 1 do
    n := n / 2;
  od;

  if n <> 1 then 
    ERROR(`The length of the data is not an exact power of 2`);
  fi;

    expt := round(ln(datasize)/ln(2));

  for j from 1 to datasize do
    size := j - 1;
    total := 0;

    for k from 1 to expt do
      temp := floor(size / 2);
      total := total + total + size - temp - temp;
      size := temp;
    od:

    perm := total + 1;

    Rtrans[perm] := Rin[j];
    Itrans[perm] := Iin[j];
  od;

    pwr := 2;

  for j from 1 to expt do
    p := pwr / 2;

      for k from 1 to p do
        n := k;
        omega := evalf(Pi) * (k - 1) / p;
        sne := sign * evalf(-sin(omega));
        csn := evalf(cos(omega));

        while n < datasize do
          m := n + p;
          u := Rtrans[m] * csn + Itrans[m] * sne;
          v := Itrans[m] * csn - Rtrans[m] * sne;
          Rtrans[m] := Rtrans[n] - u;
          Itrans[m] := Itrans[n] - v;
          Rtrans[n] := Rtrans[n] + u;
          Itrans[n] := Itrans[n] + v;
          n := n + pwr;
        od;

      od;

    pwr := pwr + pwr;
  od;

  if domain = false then
    for j from 1 to datasize do
      Rtrans[j] := Rtrans[j] / datasize;
      Itrans[j] := Itrans[j] / datasize;
    od;
  fi;

  RETURN(datasize);
	
end:

`help/text/fft` := TEXT(
`   `,
`FUNCTION: - Fast Fourier Transform`,
`   `,
`CALLING SEQUENCE:`,
`   fft(datasize, Rin, Iin, Rtrans, Itrans, domain)`,
`   evalhf(fft(datasize, Rin, Iin, var(Rtrans), var(Itrans), domain))`,
`   `,
`PARAMETERS:`,
`   datasize       - a non negative integer`,
`   Rin, Iin       - arrays of floats indexed from 1 to n`,
`   Rtrans, Itrans - arrays of floats indexed from 1 to n`,
`   domain         - boolean`,
`   `,
`SYNOPSIS:`,
`- The procedure fft is for computing the fast Fourier and inverse Fourier`,
`  transform of a complex sequence of length n.`,
`  `,
`- Arrays Rin and Iin contain the real and imaginary data to be transformed,`,
`  arrays Rtrans and Itrans contain the real and imaginary results of the`,
`  transform. The value datasize is the length of the arrays, and MUST be `,
`  an exact power of 2.`,
`  `,
`- Domain is a boolean value indicating the direction of the transform, if`,
`  domain is true then Rtrans and Itrans contain the Fourier transform of Rin`,
`  and Iin, if domain is false then Rtrans and Itrans contain the inverse`,
`  Fourier transform of Rin and Iin.`,
`  `,
`- You must use readlib(fft) before invoking fft.`,
`  `,
`EXAMPLES:`,
`> readlib(fft):`,
`  `,
`> u := array([1,2,3,4]):`,
`  `,
`> v := array([0,0,0,0]):`,
`  `,
`> x := array([0,0,0,0]):`,
`  `,
`> y := array([0,0,0,0]):`,
`  `,
`> fft(4,u,v,x,y,true);`,
`                                    4`,
`> print(x,y);`,
`         [ 10.  -2.000000000  -2  -2.000000000 ], [ 0  2.  0  -2. ]`,
`> m := array([0,0,0,0]):`,
`  `,
`> n := array([0,0,0,0]):`,
`  `,
`> fft(4,x,y,m,n,false);`,
`                                    4`,
`> print(m,n);`,
`          [ 1.000000000   2.000000000   3.000000000  4.000000000 ]`,
`               [0  -.2051033807 10E-9  0  .2051033807 10E-9]`,
`  `,
`SEE ALSO:  fht and FFT.`
):

#save `fft.m`;
#quit
