#
# A Maple Package for the calculation of the Fast Hartley 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 
#
#############################################################################


fht := proc(datasize : integer,Hin : array,Htrans : array,domain : boolean)

local a, angle, b, csn, expt, finish, i, j, k, l, m, n, omega, p,
      power, pwr, section, sect, size, sne, start, sum, temp, total;

  if nargs <> 4 then 
    ERROR(`Incorrect number of arguments`);
  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));

    csn := array(1..datasize);
    sne := array(1..datasize);
    sum := array(1..2,1..datasize);

  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;

    sum[1,total + 1] := Hin[j];
  od;

    angle := 0;
    omega := 2 * evalf(Pi) / datasize;

  for j from 1 to datasize do
    sne[j] := evalf(sin(angle));
    csn[j] := evalf(cos(angle));
    angle := angle + omega;
  od;

    a := 2;
    b := 1;
    power := 1;

  for i from 1 to expt do
    j := 1;
    section := 1;
    pwr := floor(datasize / (power + power));

    while j < datasize do
      l := 1;
      sect := section * power;
      start := sect + 1;
      finish := sect + power;

      for n from 1 to power do
        k := j + power;

        if start = k or power < 3 then
          m := k;
        else 
          m := start + finish - k + 1;
        fi;

        sum[a,j] := sum[b,j] + sum[b,k] * csn[l] + sum[b,m] * sne[l];
        p := l + datasize / 2;
        sum[a,k] := sum[b,j] + sum[b,k] * csn[p] + sum[b,m] * sne[p];

        l := l + pwr;
        j := j + 1;
      od;

      j := j + power;
      section := section + 2;
    od;

    power := power + power;
    temp := a;
    a := b;
    b := temp;
  od;

  if domain = true then
    for j from 1 to datasize do
      Htrans[j] := sum[b,j] / datasize;
    od;
  else
    for j from 1 to datasize do
      Htrans[j] := sum[b,j];
    od;
  fi;

  RETURN(datasize);

end:

`help/text/fht` := TEXT(
`   `,
`FUNCTION: - Fast Hartley Transform`,
`   `,
`CALLING SEQUENCE:`,
`   fht(datasize, Hin, Htrans, domain)`,
`   evalf(fht(datasize, Hin, var(Htrans), domain))`,
`   `,
`PARAMETERS:`,
`   datasize - a non negative integer`,
`   Hin      - array of floats indexed from 1 to n`,
`   Htrans   - array of floats indexed from 1 to n`,
`   domain   - boolean`,
`   `,
`SYNOPSIS:`,
`- The procedure fht is for computing the fast Hartley and inverse Hartley`,
`  transform of a real sequence of length n.`,
`  `,
`- Array Hin contains the data to be transformed, and array Htrans contains`,
`  the 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 Htrans contains the Hartley transform of Hin, if domain`,
`  is false then Htrans contains the inverse Hartley transform of Hin.`,
`  `,
`- You must use readlib(fht) before invoking fht.`,
`  `,
`EXAMPLES:`,
`> readlib(fht):`,
`  `,
`> a := array([1,2,3,4]):`,
`  `,
`> b := array([0,0,0,0]):`,
`  `,
`> fht(4,a,b,true);`,
`                                    4`,
`> print(b);`,
`             [ 2.500000000, -1.000000001, -.5000000005, 0 ]`,
`> c := array([0,0,0,0]):`,
`  `,
`> fht(4,b,c,false);`,
`                                    4`,
`> print(c);`,
`         [ 0.999999999   2.000000000   3.000000001  4.000000001]`,
`  `,
`SEE ALSO:  fft and FFT.`
):
                                                   
#save `fht.m`;
#quit
