/**
 * \license This project is released under the BSD 2-clause license
 *
 * Copyright (C) 2014 Xevolver Project. All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in
 *   the documentation and/or other materials provided with the
 *   distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/* 計算ラッパ群 倍精度FORTRAN用*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef FFTW_ASL_INCLUDED
#include "fftw_asl.h"
#endif

#ifndef UTIL_INCLUDED
#include "util.h"
#endif

/* 倍精度Fortran */
void sfftw_execute_(struct sfftw_plan **plan)
{
  struct sfftw_plan *plan_p = *plan;
  /* asl_wk:作業配列、asl_ifax:基数分け情報、asl_trigs:三角関数テーブル */
  /* 配列の大きさはASLの3次元複素フーリエ変換に対応。詳細はマニュアル参照 */
  Complex8 asl_wk[plan_p->asl_n1 * plan_p->asl_n2 * plan_p->asl_n3];
  Int32 asl_ifax[60];
  float asl_trigs[2 * (plan_p->asl_n1 + plan_p->asl_n2 + plan_p->asl_n3)];
  Int32    asl_err;                            /* エラーインディケータ */
  Int32    asl_isw;    /* 変換の方向 0:初期化のみ、1:順変換、-1:逆変換 */

  /* プランが生成されていれば asl_flags は絶対に -1 (何も行わない) */
  if (plan_p->asl_flags != NOEFFECT)
  {
    fprintf(stderr, "Illegal PLAN\n");
    exit(1);
  }

  /* ASLとFFTWの変換の方向を対応させる */
  asl_isw = __FFTWR_fftw_to_asl_flag(plan_p->asl_fbflag);

  switch (plan_p->asl_plan_type)
  {
  case SFFTW_PLAN_DFT_1D :
    /* 複素1次元 */
    /* ASLは入出力配列の区別がないので、事前にコピーしてから計算 */
    if (plan_p->asl_outdt != plan_p->asl_indt )
    {
      memmove(plan_p->asl_outdt, plan_p->asl_indt, plan_p->asl_n1*sizeof(Complex8));
    }
    cfc1fb_(&plan_p->asl_n1, plan_p->asl_outdt, &plan_p->asl_n1, &asl_isw,
             asl_ifax, asl_trigs,asl_wk, &asl_err);
    break ;

  case SFFTW_PLAN_DFT_2D :
    /* 複素2次元 */
    /* ASLは入出力配列の区別がないので、事前にコピーしてから計算 */
    if (plan_p->asl_outdt != plan_p->asl_indt )
    {
      memmove(plan_p->asl_outdt, plan_p->asl_indt, plan_p->asl_n1*
                                                   plan_p->asl_n2*sizeof(Complex8));
    }
    cfc2fb_(&plan_p->asl_n1, &plan_p->asl_n2, plan_p->asl_outdt, &plan_p->asl_n1,
             &plan_p->asl_n2, &asl_isw, asl_ifax, asl_trigs, asl_wk,&asl_err);
    break ;

  case SFFTW_PLAN_DFT_3D :
    /* 複素3次元 */
    /* ASLは入出力配列の区別がないので、事前にコピーしてから計算 */
    if (plan_p->asl_outdt != plan_p->asl_indt )
    {
      memmove(plan_p->asl_outdt, plan_p->asl_indt, plan_p->asl_n1*
                                                   plan_p->asl_n2*
                                                   plan_p->asl_n3*sizeof(Complex8));
    }
    cfc3fb_(&plan_p->asl_n1, &plan_p->asl_n2, &plan_p->asl_n3, plan_p->asl_outdt,
             &plan_p->asl_n1, &plan_p->asl_n2, &plan_p->asl_n3, &asl_isw, asl_ifax,
             asl_trigs, asl_wk,&asl_err);
    break ;

  default :
    fprintf(stderr, "Illegal PLAN\n");
    exit(1);
  }

  __FFTWR_check_asl_error(asl_err);

  return ;
}
