/*
* Copyright (c) 2010-2013 Michael Pippig
*
* This file is part of PFFT.
*
* PFFT is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PFFT is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PFFT. If not, see .
*
*/
#include "pfft.h"
#include "ipfft.h"
static void get_outrafo_param(
int step, int rnk_pm,
const INT *n, const INT *ni, const INT *no,
const INT *local_ni, const INT *local_no,
const X(r2r_kind) *kind_in, const unsigned *trafo_flags,
INT *Nb, INT *N, INT *Ni, INT *No,
X(r2r_kind) *kind, unsigned *trafo_flag);
static outrafo_plan outrafo_mkplan(void);
/* combine multidimensional serial trafo (c2c, r2c, c2r, r2r)
* with over- and/or under sampling */
/* input array:
* nb x ni0 x ni1 x ... x nir x howmany
* oversample to array of size:
* nb x n0 x n1 x ... x nr x howmany
* plan trafo of last dimensions:
* nb x N0 x N1 x ... x Nr x howmany
* truncate to array of size:
* nb x no0 x no1 x ... x nor x howmany
*/
void PX(get_outrafo_param)(
int step, int rnk_pm,
const INT *n, const INT *ni, const INT *no,
const INT *local_ni, const INT *local_no,
const X(r2r_kind) *kinds, unsigned transp_flag, const unsigned *trafo_flags,
INT *Nb, INT *N, INT *Ni, INT *No,
X(r2r_kind) *kind, unsigned *trafo_flag
)
{
/* TRANSPOSED_IN is planned in backward direction.
* Therefore switch input and output parameters. */
if(transp_flag & PFFT_TRANSPOSED_IN)
get_outrafo_param(
step, rnk_pm, n, ni, no, local_no, local_ni, kinds, trafo_flags,
Nb, N, Ni, No, kind, trafo_flag);
else
get_outrafo_param(
step, rnk_pm, n, ni, no, local_ni, local_no, kinds, trafo_flags,
Nb, N, Ni, No, kind, trafo_flag);
}
static void get_outrafo_param(
int step, int rnk_pm,
const INT *n, const INT *ni, const INT *no,
const INT *local_ni, const INT *local_no,
const X(r2r_kind) *kinds, const unsigned *trafo_flags,
INT *Nb, INT *N, INT *Ni, INT *No,
X(r2r_kind) *kind, unsigned *trafo_flag
)
{
*Nb = 1;
for(int t=0; tembed = PX(plan_ousam_dd)(nb, rnk, ni, n, howmany,
in, in, trafo_flag, si_flag, PFFTI_OUSAM_EMBED | ousam_flag);
/* plan serial trafo */
ths->trafo = PX(plan_sertrafo)(
nb, rnk, n, howmany, in, out, sign, kinds,
trafo_flag, transp_flag, io_flag, opt_flag, fftw_flags);
/* plan trunc */
ousam_flag = (transp_flag & PFFT_TRANSPOSED_OUT) ?
PFFTI_OUSAM_TRANSPOSED : 0;
ths->trunc = PX(plan_ousam_dd)(nb, rnk, n, no, howmany,
out, out, trafo_flag, si_flag, PFFTI_OUSAM_TRUNC | ousam_flag);
/* give back NULL if all contained palns are NULL */
if( (ths->trafo == NULL) && (ths->embed == NULL) && (ths->trunc == NULL) ){
PX(outrafo_rmplan)(ths);
return NULL;
}
return ths;
}
void PX(execute_outrafo)(
outrafo_plan ths,
R *planned_in, R *planned_out,
R *executed_in, R *executed_out
)
{
if(ths == NULL)
return;
PX(execute_ousam_dd)(ths->embed, planned_in, planned_out, executed_in, executed_out);
PX(execute_sertrafo)(ths->trafo, planned_in, planned_out, executed_in, executed_out);
PX(execute_ousam_dd)(ths->trunc, planned_in, planned_out, executed_in, executed_out);
}
static outrafo_plan outrafo_mkplan(void)
{
outrafo_plan ths = (outrafo_plan) malloc(sizeof(outrafo_plan_s));
ths->embed = NULL;
ths->trafo = NULL;
ths->trunc = NULL;
return ths;
}
void PX(outrafo_rmplan)(
outrafo_plan ths
)
{
/* plan was already destroyed or never initialized */
if(ths==NULL)
return;
/* destroy trafo and ousam plans */
PX(ousam_dd_rmplan)(ths->embed);
PX(sertrafo_rmplan)(ths->trafo);
PX(ousam_dd_rmplan)(ths->trunc);
/* finally free mem of the plan itself */
free(ths);
}