Add functions to treat the factors of the polynomial separatedly.

This commit is contained in:
Miguel Marco 2021-06-30 11:52:46 +02:00
parent 8dffa82a98
commit dbdc52aeb3
Signed by: mmarco
GPG Key ID: DD0114EDB7410592
6 changed files with 779 additions and 12 deletions

View File

@ -277,8 +277,32 @@ make install
as before.
## To do:
## Multiple components:
- include an option for passing the factors of the polynomial, for the cases
where the original polynomial is reducible. This might speed up the computations
In the case where the polynomial is reducible, its roots can be tracked for each
factor separatedly. In that case, each root is tracked for its corresponding factor,
making sure that there is no root of the other factors in the corresponding bounding
box.
The functions to do so are `homotopyPath_comps` and `homotopyPath_mp_comps`.
Their interface is similar to the ones of `homotopyPath` and `homotopyPath_mp`, but
including the other factors. That is:
- `int degree` : the degree of the factor whose root is being tracked
- `double *_coef` : a malloc'ed array with the coefficients of that factor
- `double _y0R` : the real part of the starting root
- `double _y0I` : the imaginary part of the starting root
- `int nothercomps` : the number of the other factors of the polynomial
- `int *degreescomps` : an array with the degrees of the other factors
- `double *_coefscomps` : an array with the coefficients of the other factors, all concatenated in just one array.
The multiple precission version works similarly, but changing the doubles by mpfr numbers, and having an extra parameter with the used precission:
- `int degree` : the degree of the factor whose root is being tracked
- `mpfr_t *_coef` : a malloc'ed array with the coefficients of that factor
- `mpfr_t _y0R` : the real part of the starting root
- `mpfr_t _y0I` : the imaginary part of the starting root
- `int prec` : the used precission
- `int nothercomps` : the number of the other factors of the polynomial
- `int *degreescomps` : an array with the degrees of the other factors
- `mpfr_t *_coefscomps` : an array with the coefficients of the other factors, all concatenated in just one array.

View File

@ -13,4 +13,8 @@
double * homotopyPath (int degree, double *_coef, double _y0R, double _y0I);
mpfr_t * homotopyPath_mp (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec);
double * homotopyPath_comps (int degree, double *_coef, double _y0R, double _y0I,
int nothercomps, int *degreescomps, double *_coefscomps);
mpfr_t * homotopyPath_mp_comps (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec, int nothercomps, int *degreescomps, mpfr_t *_coefscomps);
#endif

View File

@ -5,6 +5,7 @@
#include <fenv.h>
#include <mp_complex.hpp>
#include <polynomial.hpp>
#include <stdio.h>
// ACTIVATE ROUND MODE CONTROL
@ -17,6 +18,9 @@ typedef std::complex<double> Complex;
double * homotopyPath (int degree, double *_coef, double _y0R, double _y0I);
mpfr_t * homotopyPath_mp (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec);
double * homotopyPath_comps (int degree, double *_coef, double _y0R, double _y0I, int nothercomps, int *degreescomps, double *_coefscomps);
mpfr_t * homotopyPath_mp_comps (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec, int nothercomps, int *degreescomps, mpfr_t *_coefscomps);
template <class T> // T -> Complex, IComplex, MPComplex or MPIComplex
void correctRoot (const Polynomial<T>, const T &x0, T &y0) {}
@ -72,4 +76,35 @@ int validate (const Polynomial<T> &If, const T &Ix0, const T &Iy0, const T &IY0)
return 1;
}
template <class T>
int validate (const Polynomial<T> &If, const T &Ix0, const T &Iy0, const T &IY0, int nothercomps, const Polynomial<T> othercomps[]) {
T IY1;
if (!newtonTest<T> (If, Ix0, Iy0, IY0)) return 0;
// COMPUTES AN ENCLOSURE THREE TIMES BIGGER FOR N2
// CREATE A 3-TIMES BIGGER ENCLOSURE (ROUNDING TO BIGGER)
IY1 = IY0 + IY0;
IY1 = IY1 - IY0;
if (!newtonTest<T> (If, Ix0, Iy0, IY1)) return 0;
T evalcomp;
for (int i=0; i<nothercomps; ++i) {
evalcomp = othercomps[i](Ix0, IY1);
if ( evalcomp.containsZero() ) {
return 0;
}
}
return 1;
}
#endif

View File

@ -4,6 +4,7 @@
#include <sirocco.hpp>
#include <list.hpp>
using namespace std;
// unsigned int *_Polynomial::combinatorial;
@ -69,6 +70,284 @@ void correctRoot<MPComplex> (const Polynomial<MPComplex> f, const MPComplex &x0,
return;
}
double * homotopyPath_comps (int degree, double *_coef, double _y0R, double _y0I, int nothercomps, int *degreescomps, double *_coefscomps) {
int tdegree = degree;
for (int i=0; i< nothercomps; ++i) {
tdegree = max(tdegree, degreescomps[i]);
}
_Polynomial::startCombinatorialNumbers (tdegree);
// /************************************************/
// /* VARIABLE DECLARATION AND DATA INITIALIZATION */
// /************************************************/
Complex aux; // Complex aux variable.
double stepsize = 0.0001; // step size
double eps; // radius of the box
int nCoef = ((degree+1)*(degree+2)) / 2; // number of monomials
Complex coef[nCoef]; // coefficient list for floating point representation of
// the polynomial.
IComplex Icoef[nCoef]; // coefficient list for Interval representation of
// the polynomial.
std::vector<Cell<double> > outputList;
// INITIALIZE COEFICIENT DATA FROM ARGUMENT INTO APPROPIATE DATA STRUCTURES
for (int i=0; i<nCoef; ++i) {
Icoef[i] = IComplex (_coef[4*i] ,_coef[4*i+1] ,_coef[4*i+2] ,_coef[4*i+3]);
coef[i] = Complex ((_coef[4*i] + _coef[4*i+1])/2.0 ,
(_coef[4*i+2] + _coef[4*i+3])/2.0);
}
Polynomial<Complex> f (degree, coef); // complex polynomials (with fp arithmetic)
// to be used in Newton method correction
Polynomial<IComplex> If (degree, Icoef); // complex polynomials (with Interval arithmetic)
Polynomial<IComplex> Ig (degree); // to be used in validated homotopy
Polynomial<IComplex> Ih (degree);
Polynomial<IComplex> othercomponents[nothercomps];
Polynomial<IComplex> Igs[nothercomps];
Polynomial<IComplex> Ihs[nothercomps];
int acumcoefscomps = 0;
for (int i=0; i< nothercomps; ++i) {
int cdegree = degreescomps[i];
int nCoefcomp = ((cdegree+1)*(cdegree+2)) / 2;
IComplex Icoefcomp[nCoefcomp];
for (int j=0; j<nCoefcomp; ++j) {
Icoefcomp[j] = IComplex (_coefscomps[4*acumcoefscomps] ,_coefscomps[4*acumcoefscomps+1] ,_coefscomps[4*acumcoefscomps+2] ,_coefscomps[acumcoefscomps*4+3]);
acumcoefscomps++;
}
Polynomial<IComplex> Ifcomp (cdegree, Icoefcomp);
othercomponents[i] = Ifcomp;
Polynomial<IComplex > Igcomp (cdegree);
Polynomial<IComplex > Ihcomp (cdegree);
Igs[i] = Igcomp;
Ihs[i] = Ihcomp;
}
// INITIALIZE FLOATING POINT COMPLEX APPROXIMATION OF THE ROOT
Complex x0 (0.0); // x0 of the root (x0.imag = 0)
Complex y0 (_y0R, _y0I); // approximated y0 of the root
IComplex Ix0; // Interval representation for x0
IComplex Iy0; // Interval representation for y0
IComplex IY0; // Interval enclosure for y0 for Newton Method
IComplex Iy1, IY1; // Interval representation of zeros for rotated polynomial
IComplex Ix1;
Complex a; // y'(x0) as Complex
IComplex Ia; // y'(x0) as IComplex
#ifdef PROFILING
int nsteps = 0; // number of steps performed
int nrejectedEps = 0; // number of rejected validations of boxes
int nrejectedSteps = 0; // number of rejected validations of tubes
#endif
outputList.push_back (Cell<double> (0.0, y0.real (), y0.imag ()));
/*******************/
/* CORRECT ROOT */
/*******************/
correctRoot<Complex> (f, x0, y0);
/*******************/
/** MAIN LOOP */
/*******************/
while (x0.real () < 1.0) {
#ifdef PROFILING
nsteps++; // used for profiling only
#endif
/***********************************************************/
/*** BOX SIZE ESTIMATION. F RESTRICTED TO X0 IS INJECTIVE. */
/***********************************************************/
aux = f.diffYY (x0, y0);
if (abs (aux) < 1.0e-10) {
eps = 0.5;
} else {
eps = (abs (f.diffY(x0,y0) / aux)) / 8.0;
}
eps /= 2.0;
// cout << "estima eps = " << eps << endl;
/**************************/
/*** VALIDATE y0 AS POINT.*/
/**************************/
Ix0 = x0;
Iy0 = y0;
IY0 = y0 + IComplex (-eps, eps, -eps, eps);
while (!validate<IComplex> (If, Ix0, Iy0, IY0, nothercomps, othercomponents)) {
#ifdef PROFILING
nrejectedEps++; // used for profiling
#endif
if (eps < 1.0e-13) {
printf ("Singularity detected. Abort Sirocco\n");
/*******************/
/* CLEAN VARIABLES */
/*******************/
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
eps *= 0.5;
IY0 = Iy0;
IY0 = y0 + IComplex (-eps, eps, -eps, eps);
}
// cout << "acepta eps = " << eps << endl;
// COMPUTE a = -fx(x0,y0) / fy(x0.y0)
// both fp and Interval
a = getA<Complex> (f, x0, y0);
Ia = a;
/************************/
/* ESTIMATE STEP SIZE ***/
/************************/
// we have: aux = fyy
// store all in aux2
aux = a*a*aux + 2.0*a*f.diffXY(x0,y0) + f.diffXX (x0, y0);
// DETECT INFLEXION POINT
if (abs(aux) < 1.0e-10)
stepsize=1.0;
else
stepsize = sqrt(abs((eps * f.diffY (x0, y0) )/ aux));
if (stepsize + x0.real () > 1.0) stepsize = 1.000001 - x0.real ();
/*******************/
/** VALIDATE STEP */
/*******************/
Ix1 = Interval(0,stepsize);
// PERFORM TRANSLATION AND ROTATION OF THE POLYNOMIAL
Ig = If.IlinearVarChange2 (Ix0);
Ih = Ig.IlinearVarChange (Ia);
for (int jj = 0; jj<nothercomps; ++jj) {
Igs[jj] = othercomponents[jj].IlinearVarChange2(Ix0);
Ihs[jj] = Igs[jj].IlinearVarChange (Ia);
}
while (!validate<IComplex> (Ih, Ix1, Iy0, IY0, nothercomps, Ihs)) {
#ifdef PROFILING
nrejectedSteps++; // used for profiling
#endif
stepsize *= 0.5;
eps*=0.95;
IY0 = y0 + IComplex (-eps, eps, -eps, eps);
Ix1 = Interval (0, stepsize);
if (stepsize < 1.0e-13) {
/*******************/
/* CLEAN VARIABLES */
/*******************/
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
}
#ifdef DEVELOPER
std::cout << "x0 = " << x0.real () << " step = " << stepsize << std::endl;
#endif
// /**************************/
// /** VALIDATE FINAL STEP */
// /**************************/
if (x0.real () + stepsize > 1.0) {
stepsize = 1.0 - x0.real ();
Ix1.r.b = stepsize;
#ifdef DEVELOPER
std::cout << "final step = " << stepsize << std::endl;
#endif
while (!validate<IComplex> (Ih, Ix1, Iy0, IY0, nothercomps, Ihs));
}
// /********************/
// /* UPDATE VARIABLES */
// /********************/
x0 = Complex (Ix0.r.a + stepsize, 0.0);
y0 = Complex (y0.real () + Ia.r.a * stepsize,
y0.imag () + Ia.i.a * stepsize);
// /*******************/
// /* CORRECT ROOT */
// /*******************/
correctRoot<Complex> (f, x0, y0);
/**********************************************/
/* CHECK WE HAVE NOT JUMPED TO ANOTHER ROOT */
/**********************************************/
if (!(IY0+Ia*stepsize).contains (y0)) {
printf ("error! Jumped to other thread!\n");
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
outputList.push_back (Cell<double> (x0.real (), y0.real (), y0.imag ()));
}
// /***********************************************/
/* PREPARE OUTPUT AS A BINARY ARRAY OF DOUBLES */
/***********************************************/
double *rop = new double [((3 * outputList.size () + 1))];
rop[0] = outputList.size ();
for (int i=0; i<outputList.size (); i++) {
rop[3*i+1] = outputList[i].x[0];
rop[3*i+2] = outputList[i].x[1];
rop[3*i+3] = outputList[i].x[2];
}
_Polynomial::releaseCombinatorialNumbers ();
return rop;
}
double * homotopyPath (int degree, double *_coef, double _y0R, double _y0I) {
_Polynomial::startCombinatorialNumbers (degree);
@ -556,3 +835,290 @@ mpfr_set_default_prec(oldprec);
_Polynomial::releaseCombinatorialNumbers ();
return rop;
}
mpfr_t * homotopyPath_mp_comps (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec, int nothercomps, int *degreescomps, mpfr_t *_coefscomps) {
mpfr_prec_t oldprec = mpfr_get_default_prec();
mpfr_set_default_prec(prec);
int tdegree = degree;
for (int i=0; i< nothercomps; ++i) {
tdegree = max(tdegree, degreescomps[i]);
}
_Polynomial::startCombinatorialNumbers (tdegree);
// // /************************************************/
// // /* VARIABLE DECLARATION AND DATA INITIALIZATION */
// // /************************************************/
MPComplex aux; // Complex aux variable.
mpfr_t stepsize , eps, calc, tol;
mpfr_inits (stepsize, eps, calc, tol, NULL); // step size and radius of the box
mpfr_set_d (stepsize, 0.0001, MPFR_RNDN);
mpfr_set_d (tol, mpfr_get_default_prec(), MPFR_RNDN);
mpfr_sub_si (tol, tol, 10, MPFR_RNDN);
mpfr_neg (tol, tol, MPFR_RNDN);
mpfr_exp2 (tol, tol, MPFR_RNDN);
int nCoef = ((degree+1)*(degree+2)) / 2; // number of monomials
MPComplex coef[nCoef]; // coefficient list for floating point representation of
// the polynomial.
MPIComplex Icoef[nCoef]; // coefficient list for Interval representation of
// the polynomial.
std::vector<Cell<mpfr_t> > outputList;
// INITIALIZE COEFICIENT DATA FROM ARGUMENT INTO APPROPRIATE DATA STRUCTURES
for (int i=0; i<nCoef; ++i) {
Icoef[i] = MPIComplex (_coef[4*i] ,_coef[4*i+1] ,_coef[4*i+2] ,_coef[4*i+3]);
coef[i] = 0.5*(MPComplex (_coef[4*i] , _coef[4*i+2]) +
MPComplex (_coef[4*i+1] , _coef[4*i+3]));
}
Polynomial<MPComplex> f (degree, coef); // complex polynomials (with fp arithmetic)
// to be used in Newton method correction
Polynomial<MPIComplex> If (degree, Icoef); // complex polynomials (with Interval arithmetic)
Polynomial<MPIComplex> Ig (degree); // to be used in validated homotopy
Polynomial<MPIComplex> Ih (degree);
Polynomial<MPIComplex> othercomponents[nothercomps];
Polynomial<MPIComplex> Igs[nothercomps];
Polynomial<MPIComplex> Ihs[nothercomps];
int acumcoefscomps = 0;
for (int i=0; i< nothercomps; ++i) {
int cdegree = degreescomps[i];
int nCoefcomp = ((cdegree+1)*(cdegree+2)) / 2;
MPIComplex MPIcoefcomp[nCoefcomp];
for (int j=0; j<nCoefcomp; ++j) {
MPIcoefcomp[j] = MPIComplex (_coefscomps[4*acumcoefscomps] ,_coefscomps[4*acumcoefscomps+1] ,_coefscomps[4*acumcoefscomps+2] ,_coefscomps[acumcoefscomps*4+3]);
acumcoefscomps++;
}
Polynomial<MPIComplex> Ifcomp (cdegree, MPIcoefcomp);
othercomponents[i] = Ifcomp;
Polynomial<MPIComplex > Igcomp (cdegree);
Polynomial<MPIComplex > Ihcomp (cdegree);
Igs[i] = Igcomp;
Ihs[i] = Ihcomp;
}
// // INITIALIZE FLOATING POINT COMPLEX APPROXIMATION OF THE ROOT
MPComplex x0 (0.0); // x0 of the root (x0.imag = 0)
MPComplex y0 (_y0R, _y0I); // approximated y0 of the root
MPIComplex Ix0; // Interval representation for x0
MPIComplex Iy0; // Interval representation for y0
MPIComplex IY0; // Interval enclosure for y0 for Newton Method
MPIComplex Iy1, IY1; // Interval representation of zeros for rotated polynomial
MPIComplex Ix1;
MPComplex a; // y'(x0) as Complex
MPIComplex Ia; // y'(x0) as MPIComplex
#ifdef PROFILING
int nsteps = 0; // number of steps performed
int nrejectedEps = 0; // number of rejected validations of boxes
int nrejectedSteps = 0; // number of rejected validations of tubes
#endif
outputList.push_back (Cell<mpfr_t> (x0.r, y0.r, y0.i));
// /*******************/
// /* CORRECT ROOT */
// /*******************/
correctRoot<MPComplex> (f, x0, y0);
// /*******************/
// /** MAIN LOOP */
// /*******************/
while (mpfr_cmp_si(x0.r, 1.0) < 0) {
#ifdef PROFILING
nsteps++; // used for profiling only
#endif
/***********************************************************/
/*** BOX SIZE ESTIMATION. F RESTRICTED TO X0 IS INJECTIVE. */
/***********************************************************/
aux = f.diffYY (x0, y0);
abs (calc, aux);
if (mpfr_cmp_d (calc, 1.0e-10) < 0) {
mpfr_set_d (eps, 0.5, MPFR_RNDN);
} else {
abs (eps, (f.diffY(x0,y0) / aux));
mpfr_div_si (eps, eps, 8, MPFR_RNDN);
}
/**************************/
/*** VALIDATE y0 AS POINT.*/
/**************************/
Ix0 = x0;
Iy0 = y0;
IY0 = MPIComplex(y0) + eps*MPIComplex (-1.0, 1.0, -1.0, 1.0);
while (!validate<MPIComplex> (If, Ix0, Iy0, IY0, nothercomps, othercomponents)) {
#ifdef PROFILING
nrejectedEps++; // used for profiling
#endif
if (mpfr_cmp (eps ,tol) < 0) {
printf ("Singularity detected. Abort Sirocco\n");
/*******************/
/* CLEAN VARIABLES */
/*******************/
mpfr_clears (stepsize, eps, calc, tol, NULL);
mpfr_set_default_prec(oldprec);
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
mpfr_div_si (eps, eps, 2, MPFR_RNDN);
IY0 = Iy0;
IY0 = MPIComplex(y0) + eps*MPIComplex (-1.0, 1.0, -1.0, 1.0);
}
// COMPUTE a = -fx(x0,y0) / fy(x0.y0)
// both fp and Interval
a = getA<MPComplex> (f, x0, y0);
Ia = a;
/************************/
/* ESTIMATE STEP SIZE ***/
/************************/
// we have: aux = fyy
// store all in aux2
aux = a*a*aux + 2.0*a*f.diffXY(x0,y0) + f.diffXX (x0, y0);
// DETECT INFLEXION POINT
abs (calc, aux);
if (mpfr_cmp_d(calc, 1.0e-10) < 0) {
mpfr_set_si (stepsize, 1, MPFR_RNDN);
} else {
abs (calc, (eps * f.diffY (x0, y0) )/ aux);
mpfr_sqrt (stepsize, calc, MPFR_RNDN);
}
// if (stepsize + x0.real () > 1.0) stepsize = 1.000001 - x0.real ();
mpfr_add (calc, x0.r, stepsize, MPFR_RNDU);
if (mpfr_cmp_si (calc, 1) > 0) {
mpfr_si_sub (stepsize, 1, x0.r, MPFR_RNDU);
}
/*******************/
/** VALIDATE STEP */
/*******************/
mpfr_set_si (calc, 0, MPFR_RNDN);
Ix1 = MPInterval(calc,stepsize);
// PERFORM TRANSLATION AND ROTATION OF THE POLYNOMIAL
Ig = If.IlinearVarChange2 (Ix0);
Ih = Ig.IlinearVarChange (Ia);
for (int jj = 0; jj<nothercomps; ++jj) {
Igs[jj] = othercomponents[jj].IlinearVarChange2(Ix0);
Ihs[jj] = Igs[jj].IlinearVarChange (Ia);
}
while (!validate<MPIComplex> (Ih, Ix1, Iy0, IY0, nothercomps, Ihs)) {
#ifdef PROFILING
nrejectedSteps++; // used for profiling
#endif
mpfr_div_si (stepsize, stepsize, 2, MPFR_RNDN);
mpfr_mul_d (eps, eps, 0.95, MPFR_RNDN);
IY0 = MPIComplex(y0) + eps*MPIComplex (-1.0, 1.0, -1.0, 1.0);
Ix1 = MPInterval (calc, stepsize);
if (mpfr_cmp_d (stepsize, 1.0e-13) < 0) {
/*******************/
/* CLEAN VARIABLES */
/*******************/
mpfr_clears (stepsize, eps, calc, tol, NULL);
mpfr_set_default_prec(oldprec);
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
}
#ifdef DEVELOPER
std::cout << "x0 = " << x0.r << " step = " << stepsize << std::endl;
#endif
// // /********************/
// // /* UPDATE VARIABLES */
// // /********************/
x0 = MPComplex (Ix0.r.a) + MPComplex (stepsize);
y0 = y0 + stepsize*a;
// /*******************/
// /* CORRECT ROOT */
// /*******************/
correctRoot<MPComplex> (f, x0, y0);
/**********************************************/
/* CHECK WE HAVE NOT JUMPED TO ANOTHER ROOT */
/**********************************************/
if (!(MPIComplex(y0).subset (IY0+Ia*stepsize))) {
mpfr_clears (stepsize, eps, calc, tol, NULL);
printf ("error! Jumped to other thread!\n");
mpfr_set_default_prec(oldprec);
_Polynomial::releaseCombinatorialNumbers ();
return NULL;
}
outputList.push_back (Cell<mpfr_t> (x0.r, y0.r, y0.i));
}
// /***********************************************/
/* PREPARE OUTPUT AS A BINARY ARRAY OF DOUBLES */
/***********************************************/
mpfr_t *rop = new mpfr_t [((3 * outputList.size () + 1))];
mpfr_init(rop[0]);
mpfr_set_si(rop[0], outputList.size(), MPFR_RNDN);
for (int i=0; i<outputList.size (); i++) {
mpfr_init(rop[3*i+1]);
mpfr_init(rop[3*i+2]);
mpfr_init(rop[3*i+3]);
mpfr_set(rop[3*i+1], outputList[i].x[0], MPFR_RNDN);
mpfr_set(rop[3*i+2], outputList[i].x[1], MPFR_RNDN);
mpfr_set(rop[3*i+3], outputList[i].x[2], MPFR_RNDN);
}
mpfr_clears (stepsize, eps, calc, tol, NULL);
mpfr_set_default_prec(oldprec);
_Polynomial::releaseCombinatorialNumbers ();
return rop;
}

View File

@ -3,26 +3,29 @@
#clang C++
#clib sirocco
include 'cysignals/signals.pxi'
#include 'cysignals/signals.pxi'
from cysignals.signals cimport sig_on, sig_off
from cysignals.memory cimport check_allocarray, sig_free as free
from sage.libs.mpfr cimport *
from sage.rings.real_mpfr cimport RealNumber
from sage.rings.real_mpfr import RealField
cdef extern from "stdlib.h":
void free(void* ptr)
cdef extern from "sirocco.h":
mpfr_t* homotopyPath_mp (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec)
mpfr_t* homotopyPath_mp_comps (int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec, int nothercomps, int *degreescomps, mpfr_t *_coefscomps)
double * homotopyPath (int degree, double *_coef, double _y0R, double _y0I)
double * homotopyPath_comps (int degree, double *_coef, double _y0R, double _y0I, int nothercomps, int *degreescomps, double *_coefscomps)
def contpath_mp(deg, values, RealNumber y0r, RealNumber y0i, int prec):
cdef int cdeg = deg
cdef mpfr_t* cvalues = <mpfr_t*> sage_malloc(sizeof(mpfr_t)*len(values))
cdef mpfr_t* cvalues = <mpfr_t*> check_allocarray(len(values), sizeof(mpfr_t))
cdef mpfr_t* rop
cdef int j
for i in range(len(values)):
@ -66,16 +69,82 @@ def contpath_mp(deg, values, RealNumber y0r, RealNumber y0i, int prec):
def contpath_mp_comps(deg, values, RealNumber y0r, RealNumber y0i, int prec, otherdegrees, othercoefs):
cdef int cdeg = deg
cdef mpfr_t* cvalues = <mpfr_t*> check_allocarray(len(values),sizeof(mpfr_t))
cdef mpfr_t* cothercoefs = <mpfr_t*> check_allocarray(len(othercoefs),sizeof(mpfr_t))
cdef mpfr_t* rop
cdef int j
for i in range(len(values)):
j = <int>i
sig_on()
mpfr_init2(cvalues[j], prec)
mpfr_set(cvalues[j], (<RealNumber>values[j]).value, MPFR_RNDN)
sig_off()
for i in range(len(othercoefs)):
j = <int>i
sig_on()
mpfr_init2(cothercoefs[j], prec)
mpfr_set(cothercoefs[j], (<RealNumber>othercoefs[j]).value, MPFR_RNDN)
sig_off()
cdef int* c_otherdegrees = <int*> check_allocarray(len(otherdegrees),sizeof(int))
for i in range(len(otherdegrees)):
c_otherdegrees[i] = int(otherdegrees[i])
cdef mpfr_t y0R
cdef mpfr_t y0I
sig_on()
mpfr_init2(y0R, prec)
mpfr_set(y0R, (<RealNumber>y0r).value, MPFR_RNDN)
mpfr_init2(y0I, prec)
mpfr_set(y0I, (<RealNumber>y0i).value, MPFR_RNDN)
rop = homotopyPath_mp_comps(cdeg, cvalues, y0R, y0I, prec, int(len(otherdegrees)), c_otherdegrees, cothercoefs)
sig_off()
for i in range(len(values)):
j = <int>i
sig_on()
mpfr_clear(cvalues[j])
sig_off()
for i in range(len(othercoefs)):
j = <int>i
sig_on()
mpfr_clear(cothercoefs[j])
sig_off()
free(cvalues)
free(cothercoefs)
free(c_otherdegrees)
if rop == NULL:
raise ValueError("libsirocco could not guarantee one step")
cdef int n = mpfr_get_si(rop[0], MPFR_RNDN)
#cdef RealNumber res = RealField(53)()
cdef double res
l = []
for i in range(1, 3*n+1):
RN = RealField(prec)()
sig_on()
res = mpfr_set((<RealNumber>RN).value, rop[i], MPFR_RNDN)
mpfr_clear(rop[i])
sig_off()
l.append(RN)
free(rop)
return [(l[3*i], l[3*i+1], l[3*i+2]) for i in range(len(l)/3)]
def contpath(deg,values,y0r,y0i):
cdef double* rop
cdef double* c_values = <double*> sage_malloc(sizeof(double)*len(values))
cdef double* c_values = <double*> check_allocarray(len(values),sizeof(double))
cdef int clen = <int> len(values)
for i,v in enumerate(values):
c_values[i] = values[i]
cdef double y0R = y0r
cdef double y0I = y0i
sig_on()
@ -90,3 +159,37 @@ def contpath(deg,values,y0r,y0i):
free(rop)
free(c_values)
return l
def contpath_comps(deg, values, y0r, y0i, otherdegrees, othercomps):
cdef double* rop
cdef double* c_values = <double*> check_allocarray(len(values),sizeof(double))
for i,v in enumerate(values):
c_values[i] = values[i]
cdef double* c_othercomps = <double*> check_allocarray(len(othercomps),sizeof(double))
for i,v in enumerate(othercomps):
c_othercomps[i] = othercomps[i]
cdef int* c_otherdegrees = <int *> check_allocarray(len(otherdegrees),sizeof(int))
for i,v in enumerate(otherdegrees):
c_otherdegrees[i] = int(otherdegrees[i])
cdef double y0R = y0r
cdef double y0I = y0i
sig_on()
rop = homotopyPath_comps (int(deg), c_values, y0R, y0I, int(len(otherdegrees)), c_otherdegrees, c_othercomps)
sig_off()
if rop == NULL:
raise ValueError("libsirocco could not guarantee one step")
n=int(rop[0])
l=[0 for i in range(n)]
for i in range(n):
l[i]=(rop[3*i+1],rop[3*i+2],rop[3*i+3])
free(rop)
free(c_values)
free(c_othercomps)
free(c_otherdegrees)
return l

View File

@ -16,6 +16,23 @@ int main(int argc, char const *argv[]) {
};
double testCoefsotcomp[] = {
-2.100000000000, -2.10000000000000, 0.000000000000000, 0.000000000000000,
0.0000000000000, 0.00000000000000, 0.000000000000000, -0.000000000000000,
0.000000000000, 0.000000000000, 0.0000000000000, 0.0000000000000,
1.000000000000000, 1.000000000000000, 0.000000000000000, -0.000000000000000,
0.00000000000000, 0.000000000000000, 0.000000000000000, 0.0000000000000000,
1.0000000000000, 1.000000000000000, 0.000000000000000, 0.0000000000000000
};
int compdegs[]={2};
double y0R = 1.414;
double y0I = 0.0;
double *rop = homotopyPath (2, testCoefs, y0R, y0I);
@ -25,28 +42,46 @@ int main(int argc, char const *argv[]) {
delete [] rop;
double *rop2 = homotopyPath_comps (2, testCoefs, y0R, y0I,1, compdegs, testCoefsotcomp);
delete [] rop2;
mpfr_t mp_testCoefs[24];
for (int i=0; i<24; ++i) {
mpfr_init_set_d (mp_testCoefs[i], testCoefs[i],
(i%2)? MPFR_RNDU : MPFR_RNDD);
}
mpfr_t mp_othercompsCoefs[24];
for (int i=0; i<24; ++i) {
mpfr_init_set_d (mp_othercompsCoefs[i], testCoefsotcomp[i],
(i%2)? MPFR_RNDU : MPFR_RNDD);
}
mpfr_t mp_y0R, mp_y0I;
mpfr_init_set_d (mp_y0R, y0R, MPFR_RNDN);
mpfr_init_set_d (mp_y0I, y0I, MPFR_RNDN);
mpfr_t *mp_rop = homotopyPath_mp (2, mp_testCoefs, mp_y0R, mp_y0I, 106);
mpfr_t *mp_rop2 = homotopyPath_mp_comps (2, mp_testCoefs, mp_y0R, mp_y0I,102,1,compdegs, mp_othercompsCoefs);
int size = mpfr_get_si (mp_rop[0], MPFR_RNDN);
for (int i=0; i<3*size+1; ++i)
mpfr_clear(mp_rop[i]);
delete [] mp_rop;
delete [] mp_rop2;
for (int i=0; i<24; ++i) {
mpfr_clear (mp_testCoefs[i]);
}
for (int i=0; i<24; ++i) {
mpfr_clear (mp_othercompsCoefs[i]);
}
mpfr_clear (mp_y0R);
mpfr_clear (mp_y0I);