// file: $PDSP/class/fourier_transform/v3.0/ft_qf_1.cc
//

// system include files
//
#include <math.h>

// isip include files
//
#include "fourier_transform.h"
#include "ft_qf.h"

#include "fourier_transform_constants.h"

// method: qf_complex_cc
//
// This code is based on the algorithm described in
//   H.Guo et.al,"The Quick Discrete Fourier Transform",  Proceedings of
//   ICASSP 1994, pp. 453-456, SanFrancisco, CA, April 1994.
//
// arguments:
// float_8* output_a :(output) output data array 
//                      length of output array will always be 2*N
//                      memory is allocated internally, not by the calling
//                      program.
// float_8* input_a : (input) input data array
//                      length of input array is 2*N
//                      memory is allocated by the calling
//                      program.
//
// return: a logical_1 value indicating status
//
// implements a complex quick fourier transform
//
logical_1 Fourier_transform::qf_complex_cc(float_8* output_a,
					   float_8* input_a) {

  // declare local variables
  //
  int_4	i, m;
  
  // initialize lookup tables and temporary memory
  //
  if (qf_init_cc(N_d) == ISIP_FALSE) {
    error_handler_cc((char_1*)"qf_complex_cc",
		     (char_1*)"error generating the lookup table");
    return ISIP_FALSE;
  }

  // check if input data is a power of 2
  //
  if (is_power_cc((int_4&)m, (int_4)2) == ISIP_FALSE) {
    error_handler_cc((char_1*)"qf_complex_cc",
		     (char_1*)"order must be a power of 2");
    return ISIP_FALSE;
  }

  // copy input imaginary data to temporary memory and input real data
  // into output so that the input data is retained
  // after calculations.
  //
  for (i = 0; i < N_d; i++) {
    qf_comp_real_temp_d[i] = input_a[i*2];
    qf_comp_imag_temp_d[i] = input_a[(i*2) + 1];
  }

  // Compute packed QFT of the real and imaginary parts; as stated on page 447
  //
  qf_real_cc((float_8*)qf_comp_real_coeff_d,(float_8*)qf_comp_real_temp_d);
  qf_real_cc((float_8*)qf_comp_imag_coeff_d,(float_8*)qf_comp_imag_temp_d);

  // interlace the output data into output_a
  //
  for (i = 0; i < N_d; ++i){
    output_a[i*2] = qf_comp_real_coeff_d[i*2] - qf_comp_imag_coeff_d[i*2+1];
    output_a[i*2+1] = qf_comp_real_coeff_d[i*2+1] + qf_comp_imag_coeff_d[i*2];
  }

  // exit gracefully
  //
  return ISIP_TRUE;
} 
