#include "FCN.h"

SV* mnfunname;
PDL_Indx ene;

#define PDL_FCN_SETUP(pvar, pdata) \
  pdl* pvar = PDL->pdlnew(); \
  if (!pvar) PDL->pdl_barf("Failed to create pdl"); \
  SV *pvar ## sv = sv_newmortal(); \
  PDL->SetSV_PDL(pvar ## sv, pvar); \
  pvar->datatype = PDL_D; \
  PDL->barf_if_error(PDL->setdims(pvar,pdims,ndims)); \
  pvar->data = (void *) pdata; \
  pvar->state |= PDL_ALLOCATED | PDL_DONTTOUCHDATA;

void FCN(PDL_LongLong* npar,double* grad,double* fval,double* xval,int* iflag,double* futil){
  dSP;
  ENTER;
  SAVETMPS;

  PDL_Indx ndims = 1, i;
  PDL_Indx pdims[] = { ene };

  PDL_FCN_SETUP(pgrad, grad)
  PDL_FCN_SETUP(pxval, xval)

  PUSHMARK(SP);
  XPUSHs(sv_2mortal(newSViv(*npar)));
  XPUSHs(pgradsv);
  XPUSHs(sv_2mortal(newSVnv(*fval)));
  XPUSHs(pxvalsv);
  XPUSHs(sv_2mortal(newSViv(*iflag)));
  PUTBACK;
  int count=call_sv(mnfunname,G_ARRAY); /* name of function on the Perl side */
  if (count!=2)
    croak("error calling perl function\n");
  SPAGAIN;
  SP -= count ;
  I32 ax = (SP - PL_stack_base) + 1 ;

  *fval = SvNV(ST(0));

  double* x = (double *) PDL->SvPDLV(ST(1))->data;
  for(i=0;i<ene;i++)
    grad[i] = x[i];

  pxval->data = NULL;
  pgrad->data = NULL;

  PUTBACK;
  FREETMPS;
  LEAVE;
}