// -*- C++ -*-

// ===== FUNCTIONS declared in include/fxt.h: =====
// ... matching "convol|correl"

// ----- SRCFILE=fht/twodimfhtcnvl.cc: -----
inline void fht_cnvl_core_core(const double *fp, const double *fm, double *gp, double *gm);

void twodim_fht_convolution_core(const double *f, double *g, ulong r, ulong c);
//   ! UNTESTED !


// ----- SRCFILE=matrix/rowcnvls.cc: -----
void row_weighted_auto_convolutions(double *fr, double *fi, ulong r, ulong c, double v); // aux
// r x c matrix (r rows, c columns)
// v!=0.0 chooses alternative normalization

void row_weighted_auto_convolutions(Complex *f, ulong r, ulong c, double v); // aux
// r x c matrix (r rows, c columns)
// v!=0.0 chooses alternative normalization

// ----- SRCFILE=matrix/matrixcnvla.cc: -----
void matrix_auto_convolution(double *fr, ulong ldn);
// fr[] = fr[] (*) fr[]

void matrix_auto_convolution0(double *fr, ulong ldn);
// fr[] = fr[] (*) fr[]
// version for zero padded data (i.e. linear convolution)

void matrix_auto_convolution(double *fr, ulong r, ulong c, int zp/*=0*/);
// fr[] = fr[] (*) fr[]
// call with zp==1 if high half of data is zero (for linear convolution)

// ----- SRCFILE=matrix/matrixcnvl.cc: -----
void matrix_convolution(double *fr, double *fi, ulong ldn);
// fi[] = fr[] (*) fi[]

void matrix_convolution0(double *fr, double *fi, ulong ldn);
// fi[] = fr[] (*) fi[]
// version for zero padded data (i.e. linear convolution)

void matrix_convolution(double *fr, double *fi, ulong r, ulong c, int zp/*=0*/);
// fi[] = fr[] (*) fi[]
// call with zp==1 if high half of data is zero (for linear convolution)

// ----- SRCFILE=matrix/matrixcocnvla.cc: -----
void matrix_auto_convolution(Complex *f, ulong ldn);
// f[] = f[] (*) f[]

void matrix_auto_convolution0(Complex *f, ulong ldn);
// f[] = f[] (*) f[]
// version for zero padded data

void matrix_auto_convolution(Complex *f, ulong r, ulong c, int zp/*=0*/);
// f[] = f[] (*) f[]

void matrix_complex_auto_convolution(double *fr, double *fi, ulong ldn);
// f[] = f[] (*) f[]  where f[] := (fr[], fi[])

void matrix_complex_auto_convolution0(double *fr, double *fi, ulong ldn);
// f[] = f[] (*) f[]  where f[] := (fr[], fi[])
// version for zero padded data

void matrix_complex_auto_convolution(double *fr, double *fi, ulong r, ulong c, int zp/*=0*/);
// f[] = f[] (*) f[]  where f[] := (fr[], fi[])

// ----- SRCFILE=fht/fhtcnvl.cc: -----
void fht_convolution(double *x, double *y, ulong ldn);
// y[] = x[] (*) y[]

void fht_convolution0(double *x, double *y, ulong ldn);
// y[] = x[] (*) y[]
// version for zero padded data (i.e. linear convolution)

void fht_convolution_core(double *x, double *y, ulong ldn,
                     double v/*=0.0*/); // aux
// v!=0.0 chooses alternative normalization

void fht_convolution_revbin_permuted_core(double *f, double *g, ulong ldn,
                               double v/*=0.0*/); // aux
// as fht_convolution_core() with data access in revbin order

// ----- SRCFILE=fht/fhtcnvla.cc: -----
void fht_auto_convolution(double *x, ulong ldn);
// y[] = x[] (*) x[]

void fht_auto_convolution0(double *x, ulong ldn);
// y[] = x[] (*) x[]
// version for zero padded data (i.e. linear convolution)

void fht_auto_convolution_core(double *x, ulong ldn,
                          double v/*=0.0*/); // aux
// v!=0.0 chooses alternative normalization

void fht_auto_convolution_revbin_permuted_core(double *f, ulong ldn,
                                    double v/*=0.0*/); // aux
// as above with data access in revbin order

// ----- SRCFILE=fht/fhtnegacnvla.cc: -----
void fht_negacyclic_auto_convolution(double *x, ulong ldn, double v/*=0.0*/);
// v!=0.0 chooses alternative normalization

void fht_negacyclic_auto_convolution_core(double *x, ulong ldn, double v/*=0.0*/); // aux
// v!=0.0 chooses alternative normalization

// ----- SRCFILE=fft/fftcnvl.cc: -----
void fht_fft_convolution(double *f, double *g, ulong ldn);
// g[] = f[] (*) g[]

void split_radix_fft_convolution(double *f, double *g, ulong ldn);
// g[] = f[] (*) g[]

void fht_fft_convolution0(double *f, double *g, ulong ldn);
// g[] = f[] (*) g[]

void split_radix_fft_convolution0(double *f, double *g, ulong ldn);
// g[] = f[] (*) g[]

void fft_convolution_core1(double *f, double *g, ulong ldn, double v/*=0.0*/); // aux

void fft_convolution_core2(double *f, double *g, ulong ldn, double v/*=0.0*/); // aux

// ----- SRCFILE=fft/fftcnvla.cc: -----
void fht_fft_auto_convolution(double *f, ulong ldn);
// f[] = f[] (*) f[]

void split_radix_fft_auto_convolution(double *f, ulong ldn);
// f[] = f[] (*) f[]

void fht_fft_auto_convolution0(double *f, ulong ldn);
// f[] = f[] (*) f[]

void split_radix_fft_auto_convolution0(double *f, ulong ldn);
// f[] = f[] (*) f[]

void fft_auto_convolution_core1(double *f, ulong ldn, double v/*=0.0*/); // aux

void fft_auto_convolution_core2(double *f, ulong ldn, double v/*=0.0*/); // aux

// ----- SRCFILE=mult/diskcnvla.cc: -----
void disk_weighted_complex_auto_convolution(int fd1, int fd2,
                                       double *fr, ulong fn, ulong al,
                                       double w,
                                       double nx,
                                       int zq1/*=0*/, int zq3/*=0*/);
// fd1/fd2: real/imag part of data  (#= fn*al)
// fr[0,...,fn-1]: workspace
// w:  weight for whole convolution
// nx: additional normalization factor (cf. disk_row_pass())

// ----- SRCFILE=fht/fhtcorr.cc: -----
void fht_correlation0(double *f, double *g, ulong ldn);
// result in g

void fht_auto_correlation0(double *f, ulong ldn);

// ----- SRCFILE=fft/fftcorr.cc: -----
void fft_correlation0(double *f, double *g, ulong ldn);
// result in g

void fft_auto_correlation0(double *f, ulong ldn);

// ----- SRCFILE=fht/cfhtcnvl.cc: -----
void fht_convolution(Complex *x, Complex *y, ulong ldn);
// y[] = x[] (*) y[]

void fht_convolution0(Complex *x, Complex *y, ulong ldn);
// y[] = x[] (*) y[]
// version for zero padded data (i.e. linear convolution)

void fht_convolution_core(Complex *x, Complex *y, ulong ldn,
                     double v/*=0.0*/); // aux
// v!=0.0 chooses alternative normalization

void fht_convolution_revbin_permuted_core(Complex *f, Complex *g, ulong ldn,
                               double v/*=0.0*/); // aux
// as fht_convolution_core() with data access in revbin order

// ----- SRCFILE=fht/cfhtcnvla.cc: -----
void fht_auto_convolution(Complex *x, ulong ldn);
// y[] = x[] (*) x[]

void fht_auto_convolution0(Complex *x, ulong ldn);
// y[] = x[] (*) x[]
// version for zero padded data (i.e. linear convolution)

void fht_auto_convolution_core(Complex *x, ulong ldn,
                          double v/*=0.0*/); // aux
// v!=0.0 chooses alternative normalization

void fht_auto_convolution_revbin_permuted_core(Complex *f, ulong ldn,
                                    double v/*=0.0*/); // aux
// as above with data access in revbin order

// ----- SRCFILE=fft/fftcocnvl.cc: -----
void fft_auto_convolution(Complex *f, ulong ldn,
                     double v/*=0.0*/);

void fft_convolution(Complex *f, Complex *g,
                ulong ldn, double v/*=0.0*/);
// _cyclic_ convolution
// (use zero padded data for usual conv.)
// f, g  must not overlap
// result in g

void fft_complex_auto_convolution(double *fr, double *fi,
                             ulong ldn, double v/*=0.0*/);
// _cyclic_ (self-)convolution
// (use zero padded data for usual conv.)
// fr,fi must not overlap

void fft_complex_convolution(double *fr, double *fi,
                        double *gr, double *gi,
                        ulong ldn, double v/*=0.0*/);
// _cyclic_ convolution
// (use zero padded data for usual conv.)
// fr,fi,gr,gi must be pairwise non-overlapping
// result in gr,gi

// ----- SRCFILE=fft/fftcocorr.cc: -----
void fft_complex_auto_correlation(double *fr, double *fi, ulong ldn);
// _cyclic_ (self-)correlation
// (use zero padded data for usual corr.)
// fr,fi must not overlap

void fft_complex_correlation(double *fr, double *fi,
                        double *gr, double *gi,
                        ulong ldn);
// _cyclic_ correlation
// (use zero padded data for usual conv.)
// fr,fi,gr,gi must be pairwise non-overlapping
// result in gr,gi

// ----- SRCFILE=walsh/dyadiccnvl.cc: -----
void dyadic_convolution(double *f, double *g, ulong ldn);

void dyadic_auto_convolution(double *f, ulong ldn);

void dyadic_convolution0(double *f, double *g, ulong ldn);

void dyadic_auto_convolution0(double *f, ulong ldn);


// ----- SRCFILE=weighted/weightedconv.cc: -----
void weighted_complex_auto_convolution(double *fr, double *fi, ulong ldn,
                                  double w, double v/*=0.0*/);
// w = weight:
// +0.25 for right angle convolution (-0.25 negates result in fi[])
// +0.5  for negacyclic  convolution (also -0.5)
// +1.0  for cyclic  convolution (also -1.0)
// v!=0.0 chooses alternative normalization

void negacyclic_complex_auto_convolution(double *fr, double *fi, ulong ldn,
                                    double v/*=0.0*/);
// negacyclic autoconvolution of fr[],fi[]
// v!=0.0 chooses alternative normalization

void right_angle_complex_auto_convolution(double *fr, double *fi, ulong ldn,
                                     double v/*=0.0*/);
// right angle autoconvolution of fr[],fi[]
// useful if fi[] all zero: then the result is the
//   acyclic autoconvolution of fr[]
//   result is in fr[] (index 0,1,...,n-1) and fi[] (index n,...,2*n-1)
// v!=0.0 chooses alternative normalization

void weighted_complex_auto_convolution(Complex *f, ulong ldn, double w, double v/*=0.0*/);
// w = weight:
// +0.25 for right angle convolution (-0.25 negates result in fi[])
// +0.5  for negacyclic  convolution (also -0.5)
// +1.0  for cyclic  convolution (also -1.0)
// v!=0.0 chooses alternative normalization

void negacyclic_complex_auto_convolution(Complex *f, ulong ldn, double v/*=0.0*/);
// negacyclic autoconvolution of f[]
// v!=0.0 chooses alternative normalization

void right_angle_complex_auto_convolution(Complex *f, ulong ldn, double v/*=0.0*/);
// right angle autoconvolution of f[]
// v!=0.0 chooses alternative normalization

// ----- SRCFILE=slow/slowcnvl.cc: -----
void slow_convolution(const double *f, const double *g, double *r, ulong nu);
// _cyclic_ convolution
// result in g

void slow_convolution0(const double *f, const double *g, double *r, ulong nu);
// linear convolution
// (zero padded data expected)

void slow_auto_convolution(const double *f, double *r, ulong nu);
// _cyclic_ self-convolution

void slow_auto_convolution0(const double *f, double *r, ulong nu);
// linear self-convolution
// (zero padded data expected)

// ----- SRCFILE=slow/slowtwodimcnvl.cc: -----
void slow_twodim_convolution(const double *f, double *g, ulong ru, ulong cu);
// _cyclic_ convolution
// result in g

// ----- SRCFILE=slow/slowcorr.cc: -----
void slow_correlation(const double *f, double *g, ulong nu);
// _cyclic_ correlation
// (use zero padded data for usual co.)
// result in g

void slow_correlation0(const double *f, double *g, ulong nu);
// correlation
// (expects zero padded data)
// result in g

void slow_auto_correlation(double *f, ulong nu);
// _cyclic_ self-correlation

void slow_auto_correlation0(double *f, ulong nu);
// _cyclic_ self-correlation
// (expects zero padded data)

// ----- SRCFILE=slow/slowcocorr.cc: -----
void slow_complex_correlation(const double *wr, const double *wi,
                         double *fr, double *fi, ulong nu);
// _cyclic_ correlation
// (use zero padded data for usual co.)
// result in fr,fi

void slow_complex_auto_correlation(double *fr, double *fi, ulong nu);
// _cyclic_ self-correlation
// (use zero padded data for usual co.)

// ----- SRCFILE=slow/slowcocnvl.cc: -----
void slow_convolution(const Complex *w , Complex *f, ulong nu);
// _cyclic_ convolution
// (use zero padded data for usual co.)
// result in f

void slow_complex_convolution(const double *wr, const double *wi,
                         double *fr, double *fi, ulong nu);
// _cyclic_ convolution
// (use zero padded data for usual co.)
// result in fr,fi

void slow_complex_auto_convolution(double *fr, double *fi, ulong nu);
// _cyclic_ self-convolution
// (use zero padded data for usual co.)

void slow_auto_convolution(Complex *f, ulong nu);
// _cyclic_ self-convolution
// (use zero padded data for usual co.)

