
#include "fft/fft-default.h"  // needs fft
#include "aux1/arith1.h"  // multiply_val()
#include "fxttypes.h"  // ulong

#include <cmath>  // sqrt()



static const int is = +1;

void
harmonic_wavelet(double *fr, double *fi, ulong ldn)
// harmonic wavelet transform
// Cf. Crandall, "topics in advanced
// scientific computation", p.177
// here real input is not assumed
{
    ulong n = (1UL<<ldn);
    if ( n<4 )  return;

    fft(fr, fi, ldn, +is);
    multiply_val(fr, n, 1.0/sqrt(n));
    multiply_val(fi, n, 1.0/sqrt(n));

    for (ulong ldm=1; ldm<=ldn-1; ++ldm)
    {
        ulong m = (1UL<<ldm);  // m=2, 4, 8, ..., n/2

        fft(fr+m, fi+m, ldm, +is);
        multiply_val(fr+m, m, 1.0/sqrt(m));
        multiply_val(fi+m, m, 1.0/sqrt(m));
    }

    for (ulong k=n/2+1; k<n; ++k)  fi[k] = -fi[k];
}
// -------------------------


void
inverse_harmonic_wavelet(double *fr, double *fi, ulong ldn)
// inverse of harmonic_wavelet()
{
    ulong n = (1UL<<ldn);
    if ( n<4 )  return;

    for (ulong k=n/2+1; k<n; ++k)  fi[k] = -fi[k];

    for (ulong ldm=ldn-1; ldm>=1; --ldm)
    {
        ulong m = (1UL<<ldm);  // m=n/2, n/4, ..., 4, 2
        fft(fr+m, fi+m, ldm, -is);
        multiply_val(fr+m, m, 1.0/sqrt(m));
        multiply_val(fi+m, m, 1.0/sqrt(m));
    }

    fft(fr, fi, ldn, -is);
    multiply_val(fr, n, 1.0/sqrt(n));
    multiply_val(fi, n, 1.0/sqrt(n));
}
// -------------------------

