#include <math.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "dace/config.h"
#include "dace/dacebase.h"
#include "dace/daceaux.h"
void daceCreateVariable(DACEDA *ina, const unsigned int i, const double ckon)
{
monomial *ipoa; unsigned int ilma, illa;
unsigned int ic1, ic2, base;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
daceSetLength(ina, 0);
if(i > DACECom.nvmax)
{
daceSetError(__func__, DACE_ERROR, 24);
return;
}
if(fabs(ckon) <= DACECom_t.eps)
{
return;
}
if(ilma < 1)
{
daceSetError(__func__, DACE_ERROR, 21);
return;
}
ic1 = 0;
ic2 = 0;
if(i != 0)
{
base = DACECom.nomax+1;
if(i > DACECom.nv1)
{
ic2 = npown(base, i-1-DACECom.nv1);
}
else
{
ic1 = npown(base, i-1);
}
}
daceSetLength(ina, 1);
ipoa->cc = ckon;
ipoa->ii = DACECom.ia1[ic1]+DACECom.ia2[ic2];
}
void daceCreateMonomial(DACEDA *ina, const unsigned int jj[], const double ckon)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
if(ilma < 1)
{
daceSetError(__func__, DACE_ERROR, 21);
daceSetLength(ina, 0);
return;
}
if(fabs(ckon) <= DACECom_t.eps)
{
daceSetLength(ina, 0);
}
else
{
ipoa->ii = daceEncode(jj);
ipoa->cc = ckon;
daceSetLength(ina, 1);
}
}
void daceCreateFilled(DACEDA *ina, const double ckon)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
unsigned int i = 0;
for(monomial *ia = ipoa; ia < ipoa+ilma && i < DACECom.nmmax; ia++, i++)
{
ia->ii = i;
ia->cc = ckon;
}
daceSetLength(ina, i);
}
void daceCreateConstant(DACEDA *ina, const double ckon)
{
daceCreateVariable(ina, 0, ckon);
}
void daceCreateRandom(DACEDA *ina, const double cm)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
monomial *ia = ipoa, *iamax = ipoa+ilma;
if(cm < 0.0)
{
for(unsigned int i = 0; i < DACECom.nmmax && ia < iamax; i++)
{
if((DACECom.ieo[i] <= DACECom_t.nocut) && (daceRandom() < -cm))
{
ia->cc = 2.0*daceRandom()-1.0;
ia->ii = i;
ia++;
}
}
}
else
{
for(unsigned int i = 0; i < DACECom.nmmax && ia < iamax; i++)
{
if((DACECom.ieo[i] <= DACECom_t.nocut) && (daceRandom() < cm))
{
const double w = pow(DACECom.epsmac, (DACECom.ieo[i]/((double)DACECom_t.nocut)));
ia->cc = w*(2.0*daceRandom()-1.0);
ia->ii = i;
ia++;
}
}
}
daceSetLength(ina, ia-ipoa);
}
double daceGetConstant(const DACEDA *ina)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
if(illa > 0 && ipoa->ii == 0)
{
return ipoa->cc;
}
else
{
return 0.0;
}
}
void daceGetLinear(const DACEDA *ina, double c[])
{
#if DACE_MEMORY_MODEL == DACE_MEMORY_STATIC
unsigned int jj[DACE_STATIC_NVMAX] = {0};
#else
unsigned int *jj = (unsigned int*) dacecalloc(DACECom.nvmax, sizeof(unsigned int));
#endif
for(unsigned int i = 0; i < DACECom.nvmax; i++)
{
jj[i] = 1;
c[i] = daceGetCoefficient(ina, jj);
jj[i] = 0;
}
#if DACE_MEMORY_MODEL != DACE_MEMORY_STATIC
dacefree(jj);
#endif
}
double daceGetCoefficient(const DACEDA *ina, const unsigned int jj[])
{
return daceGetCoefficient0(ina, daceEncode(jj));
}
double daceGetCoefficient0(const DACEDA *ina, const unsigned int ic)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
if(illa == 0) return 0.0;
monomial *iu = ipoa;
monomial *iz = ipoa+(illa-1);
if(ic == iu->ii)
{
return iu->cc;
}
else if(ic == iz->ii)
{
return iz->cc;
}
else if(ic < iu->ii || ic > iz->ii)
{
return 0.0;
}
while(iz-iu > 1)
{
monomial *i = iu+((iz-iu)/2);
if(i->ii < ic)
{
iu = i;
}
else if(i->ii > ic)
{
iz = i;
}
else
{
return i->cc;
}
}
return 0.0;
}
void daceSetCoefficient(DACEDA *ina, const unsigned int jj[], const double cjj)
{
daceSetCoefficient0(ina, daceEncode(jj), cjj);
}
void daceSetCoefficient0(DACEDA *ina, const unsigned int ic, const double cjj)
{
monomial *ipoa; unsigned int ilma, illa;
monomial *i;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
bool insert = true;
if(illa == 0)
{
i = ipoa;
}
else
{
monomial *iu = ipoa;
monomial *iz = ipoa+(illa-1);
if(ic == iu->ii)
{
i = iu;
insert = false;
}
else if(ic < iu->ii)
{
i = iu;
}
else if(ic == iz->ii)
{
i = iz;
insert = false;
}
else if(ic > iz->ii)
{
i = iz+1;
}
else
{
while(iz-iu > 1)
{
i = iu+((iz-iu)/2);
if(i->ii < ic)
{
iu = i;
}
else if(i->ii > ic)
{
iz = i;
}
else
{
insert = false;
iz = i;
break;
}
}
i = iz;
}
}
if(insert)
{
if(fabs(cjj) <= DACECom_t.eps) return;
if(illa+1 > ilma)
{
daceSetError(__func__, DACE_ERROR, 21);
return;
}
for(monomial *ii = ipoa+illa; ii > i; ii--)
*ii = *(ii-1);
i->cc = cjj;
i->ii = ic;
daceSetLength(ina, illa+1);
}
else
{
if(!(fabs(cjj) <= DACECom_t.eps))
{
i->cc = cjj;
}
else
{
for(monomial *ii = i; ii < ipoa+(illa-1); ii++)
*ii = *(ii+1);
daceSetLength(ina, illa-1);
}
}
}
void daceGetCoefficientAt(const DACEDA *ina, const unsigned int npos, unsigned int jj[], double *cjj)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
if(npos > 0 && npos <= illa)
{
*cjj = ipoa[npos-1].cc;
daceDecode(ipoa[npos-1].ii, jj);
}
else
{
*cjj = 0.0;
for(unsigned int j = 0; j < DACECom.nvmax; j++) jj[j] = 0;
}
}
unsigned int daceGetLength(const DACEDA *ina)
{
monomial *ipoa; unsigned int ilma, illa;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
return illa;
}
void daceCopy(const DACEDA *ina, DACEDA *inb)
{
monomial *ipoa; unsigned int ilma, illa;
monomial *ipob; unsigned int ilmb, illb;
if(daceIsSameObject(ina, inb)) return;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
daceVariableInformation(inb, &ipob, &ilmb, &illb);
if(illa > ilmb)
{
daceSetError(__func__, DACE_ERROR, 21);
illa = ilmb;
}
memmove(ipob, ipoa, illa*sizeof(monomial));
daceSetLength(inb, illa);
}
void daceCopyFiltering(const DACEDA *ina, DACEDA *inb)
{
monomial *ipoa; unsigned int ilma, illa;
monomial *ipob; unsigned int ilmb, illb;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
daceVariableInformation(inb, &ipob, &ilmb, &illb);
monomial *ib = ipob;
if(illa <= ilmb)
{
for(monomial *ia = ipoa; ia < ipoa+illa; ia++)
{
if(fabs(ia->cc) <= DACECom_t.eps || DACECom.ieo[ia->ii] > DACECom_t.nocut)
continue;
*ib = *ia;
ib++;
}
}
else
{
for(monomial *ia = ipoa; ia < ipoa+illa; ia++)
{
if(fabs(ia->cc) <= DACECom_t.eps || DACECom.ieo[ia->ii] > DACECom_t.nocut)
continue;
if(ib >= ipob+ilmb)
{
daceSetError(__func__, DACE_ERROR, 21);
break;
}
*ib = *ia;
ib++;
}
}
daceSetLength(inb, ib-ipob);
}
void daceTrim(const DACEDA *ina, const unsigned int imin, const unsigned int imax, DACEDA *inc)
{
monomial *ipoa; unsigned int ilma, illa;
monomial *ipoc; unsigned int ilmc, illc;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
daceVariableInformation(inc, &ipoc, &ilmc, &illc);
monomial *const icmax = ipoc+ilmc;
monomial *ic = ipoc;
for(monomial *i = ipoa; i < ipoa+illa; i++)
{
const unsigned int io = DACECom.ieo[i->ii];
if((io > imax)||(io < imin))
{
continue;
}
if(ic >= icmax)
{
daceSetError(__func__, DACE_ERROR, 21);
break;
}
*ic = *i;
ic++;
}
daceSetLength(inc, ic-ipoc);
}
void daceFilter(const DACEDA *ina, DACEDA *inb, const DACEDA *inc)
{
monomial *ipoa; unsigned int ilma, illa;
monomial *ipob; unsigned int ilmb, illb;
monomial *ipoc; unsigned int ilmc, illc;
daceVariableInformation(ina, &ipoa, &ilma, &illa);
daceVariableInformation(inb, &ipob, &ilmb, &illb);
daceVariableInformation(inc, &ipoc, &ilmc, &illc);
monomial *ib = ipob;
monomial *ic = ipoc;
if(illa <= ilmb)
{
for(monomial *ia = ipoa; ia < ipoa+illa; ia++)
{
while(ic < ipoc+illc && ia->ii > ic->ii)
ic++;
if(ic >= ipoc+illc) break;
if(ia->ii < ic->ii || fabs(ia->cc) <= DACECom_t.eps || DACECom.ieo[ia->ii] > DACECom_t.nocut)
continue;
*ib = *ia;
ib++;
}
}
else
{
for(monomial *ia = ipoa; ia < ipoa+illa; ia++)
{
while(ic < ipoc+illc && ia->ii > ic->ii)
ic++;
if(ic >= ipoc+illc) break;
if(ia->ii < ic->ii || fabs(ia->cc) <= DACECom_t.eps || DACECom.ieo[ia->ii] > DACECom_t.nocut)
continue;
if(ib >= ipob+ilmb)
{
daceSetError(__func__, DACE_ERROR, 21);
break;
}
*ib = *ia;
ib++;
}
}
daceSetLength(inb, ib-ipob);
}