/* * in: array of n/2 + 1 complex numbers (* howmany). * out: array of n real numbers (* howmany). * work: array of n real numbers (stride 1) * * We must have out != in if dist < stride. */ void rfftw_c2real_aux(fftw_plan plan, int howmany, fftw_complex *in, int istride, int idist, fftw_real *out, int ostride, int odist, fftw_real *work) { fftw_plan_node *p = plan->root; switch (p->type) { case FFTW_HC2REAL: { fftw_hc2real_codelet *codelet = p->nodeu.hc2real.codelet; int j; HACK_ALIGN_STACK_ODD(); for (j = 0; j < howmany; ++j) codelet(&c_re(*(in + j * idist)), &c_im(*(in + j * idist)), out + j * odist, istride * 2, istride * 2, ostride); break; } default: { int j, n = plan->n; for (j = 0; j < howmany; ++j, in += idist, out += odist) { rfftw_c2hc(n, in, istride, work); rfftw_executor_simple(n, work, out, p, 1, ostride); } break; } } }
static void rexecutor_many_inplace(int n, fftw_real *in, fftw_real *out, fftw_plan_node *p, int istride, int howmany, int idist, fftw_recurse_kind recurse_kind) { switch (p->type) { case FFTW_REAL2HC: { fftw_real2hc_codelet *codelet = p->nodeu.real2hc.codelet; int s; HACK_ALIGN_STACK_ODD; for (s = 0; s < howmany; ++s) codelet(in + s * idist, in + s * idist, in + n * istride + s * idist, istride, istride, -istride); break; } case FFTW_HC2REAL: { fftw_hc2real_codelet *codelet = p->nodeu.hc2real.codelet; int s; HACK_ALIGN_STACK_ODD; for (s = 0; s < howmany; ++s) codelet(in + s * idist, in + n * istride + s * idist, in + s * idist, istride, -istride, istride); break; } default: { int s; fftw_real *tmp; if (out) tmp = out; else tmp = (fftw_real *) fftw_malloc(n * sizeof(fftw_real)); for (s = 0; s < howmany; ++s) { rfftw_executor_simple(n, in + s * idist, tmp, p, istride, 1, recurse_kind); rfftw_strided_copy(n, tmp, istride, in + s * idist); } if (!out) fftw_free(tmp); } } }
void rfftw_one(fftw_plan plan, fftw_real *in, fftw_real *out) { int n = plan->n; if (plan->flags & FFTW_IN_PLACE) rexecutor_simple_inplace(n, in, out, plan->root, 1, plan->recurse_kind); else rfftw_executor_simple(n, in, out, plan->root, 1, 1, plan->recurse_kind); }
/* user interface */ void rfftw(fftw_plan plan, int howmany, fftw_real *in, int istride, int idist, fftw_real *out, int ostride, int odist) { int n = plan->n; if (plan->flags & FFTW_IN_PLACE) { if (howmany == 1) { rexecutor_simple_inplace(n, in, out, plan->root, istride, plan->recurse_kind); } else { rexecutor_many_inplace(n, in, out, plan->root, istride, howmany, idist, plan->recurse_kind); } } else { if (howmany == 1) { rfftw_executor_simple(n, in, out, plan->root, istride, ostride, plan->recurse_kind); } else { #ifdef FFTW_ENABLE_VECTOR_RECURSE int vector_size = plan->vector_size; if (vector_size <= 1) #endif rexecutor_many(n, in, out, plan->root, istride, ostride, howmany, idist, odist, plan->recurse_kind); #ifdef FFTW_ENABLE_VECTOR_RECURSE else { int s; int num_vects = howmany / vector_size; fftw_plan_node *root = plan->root; for (s = 0; s < num_vects; ++s) rexecutor_many_vector(n, in + s * (vector_size * idist), out + s * (vector_size * odist), root, istride, ostride, vector_size, idist, odist); s = howmany % vector_size; if (s > 0) rexecutor_many(n, in + num_vects * (vector_size*idist), out + num_vects * (vector_size*odist), root, istride, ostride, s, idist, odist, FFTW_NORMAL_RECURSE); } #endif } } }
static void rexecutor_many(int n, fftw_real *in, fftw_real *out, fftw_plan_node *p, int istride, int ostride, int howmany, int idist, int odist, fftw_recurse_kind recurse_kind) { int s; switch (p->type) { case FFTW_REAL2HC: { fftw_real2hc_codelet *codelet = p->nodeu.real2hc.codelet; HACK_ALIGN_STACK_ODD; for (s = 0; s < howmany; ++s) codelet(in + s * idist, out + s * odist, out + n * ostride + s * odist, istride, ostride, -ostride); break; } case FFTW_HC2REAL: { fftw_hc2real_codelet *codelet = p->nodeu.hc2real.codelet; HACK_ALIGN_STACK_ODD; for (s = 0; s < howmany; ++s) codelet(in + s * idist, in + n * istride + s * idist, out + s * odist, istride, -istride, ostride); break; } default: for (s = 0; s < howmany; ++s) rfftw_executor_simple(n, in + s * idist, out + s * odist, p, istride, ostride, recurse_kind); } }
/* * in: array of n real numbers (* howmany). * out: array of n/2 + 1 complex numbers (* howmany). * work: array of n real numbers (stride 1) * * We must have out != in if dist < stride. */ void rfftw_real2c_aux(fftw_plan plan, int howmany, fftw_real *in, int istride, int idist, fftw_complex *out, int ostride, int odist, fftw_real *work) { fftw_plan_node *p = plan->root; int j; switch (p->type) { case FFTW_REAL2HC: { fftw_real2hc_codelet *codelet = p->nodeu.real2hc.codelet; int n = plan->n; int n2 = (n & 1) ? 0 : (n + 1) / 2; HACK_ALIGN_STACK_ODD; for (j = 0; j < howmany; ++j, out += odist) { codelet(in + j * idist, &c_re(*out), &c_im(*out), istride, ostride * 2, ostride * 2); c_im(out[0]) = 0.0; c_im(out[n2 * ostride]) = 0.0; } break; } default: { int n = plan->n; fftw_recurse_kind recurse_kind = plan->recurse_kind; for (j = 0; j < howmany; ++j, in += idist, out += odist) { rfftw_executor_simple(n, in, work, p, istride, 1, recurse_kind); rfftw_hc2c(n, work, out, ostride); } break; } } }
static void rexecutor_simple_inplace(int n, fftw_real *in, fftw_real *out, fftw_plan_node *p, int istride, fftw_recurse_kind recurse_kind) { switch (p->type) { case FFTW_REAL2HC: HACK_ALIGN_STACK_ODD; (p->nodeu.real2hc.codelet) (in, in, in + n * istride, istride, istride, -istride); break; case FFTW_HC2REAL: HACK_ALIGN_STACK_ODD; (p->nodeu.hc2real.codelet) (in, in + n * istride, in, istride, -istride, istride); break; default: { fftw_real *tmp; if (out) tmp = out; else tmp = (fftw_real *) fftw_malloc(n * sizeof(fftw_real)); rfftw_executor_simple(n, in, tmp, p, istride, 1, recurse_kind); rfftw_strided_copy(n, tmp, istride, in); if (!out) fftw_free(tmp); } } }