#include "AdvGslFFTComplex.hh"

const std::string AdvGslFFTComplex::className("AdvGslFFTComplex");

AdvGslFFTComplex::AdvGslFFTComplex(UInt4 n) : dataLength(n) {
    this->allocateWorkSpace(n);
}

AdvGslFFTComplex::~AdvGslFFTComplex() {
    this->freeWorkSpace();
}

void AdvGslFFTComplex::allocateWorkSpace(UInt4 n) {

    if (this->isRadix2(n)) {
        this->waveTable=NULL;
        this->workSpace=NULL;
    } else {
        this->waveTable = gsl_fft_complex_wavetable_alloc(n);
        this->workSpace = gsl_fft_complex_workspace_alloc(n);
    }
}

void AdvGslFFTComplex::freeWorkSpace() {
    if (! this->isRadix2(this->dataLength)) {
        gsl_fft_complex_wavetable_free(this->waveTable);
        gsl_fft_complex_workspace_free(this->workSpace);
    }
}

void AdvGslFFTComplex::setDataLength(UInt4 n) {
    freeWorkSpace();
    allocateWorkSpace(n);
    this->dataLength=n;
}

Int4 AdvGslFFTComplex::forward(gsl_vector_complex* v) {
    Int4 retval;

    if ( this->isRadix2(v->size) ) {
        retval=gsl_fft_complex_radix2_forward(v->data, v->stride, v->size);
    } else {
        retval=gsl_fft_complex_forward(v->data, v->stride, v->size, this->waveTable, this->workSpace);
    }

    return retval;
}

Int4 AdvGslFFTComplex::backward(gsl_vector_complex* v) {
    Int4 retval;

    if ( this->isRadix2(v->size) ) {
        retval=gsl_fft_complex_radix2_backward(v->data, v->stride, v->size);
    } else {
        retval=gsl_fft_complex_backward(v->data, v->stride, v->size, this->waveTable, this->workSpace);
    }

    return retval;
}

Int4 AdvGslFFTComplex::inverse(gsl_vector_complex* v) {
    Int4 retval;

    if ( this->isRadix2(v->size) ) {
        retval=gsl_fft_complex_radix2_inverse(v->data, v->stride, v->size);
    } else {
        retval=gsl_fft_complex_inverse(v->data, v->stride, v->size, this->waveTable, this->workSpace);
    }

    return retval;
}

Int4 AdvGslFFTComplex::transform(gsl_vector_complex* v, gsl_fft_direction sign) {
    Int4 retval;

    if ( this->isRadix2(v->size) ) {
        retval=gsl_fft_complex_radix2_transform(v->data, v->stride, v->size, sign);
    } else {
        retval=gsl_fft_complex_transform(v->data, v->stride, v->size, this->waveTable, this->workSpace, sign);
    }

    return retval;
}
