|
realroot_doc 0.1.1
|
#include <univariate_bounds.hpp>
A (n) time algorithm for computing a lower bound. It is based upon an upper bound by Akritas et al. that returns a value some what better than Kioustelidis' bound, but is not better than the bound by Hong. The idea is to pair the positive and negative coefficients in a certain manner. Assume the constant coefficient is not zero and there is at least one sign variation in the coefficients.
Definition at line 425 of file univariate_bounds.hpp.
| static RT lower_bound | ( | const Poly & | f | ) | [inline, static] |
Definition at line 429 of file univariate_bounds.hpp.
References mmx::abs(), mmx::bit_size(), mmx::degree(), and mmx::sign().
Referenced by solver_cffirst< Real, POL >::all_roots(), and solver_cffirst< Real, POL >::first_root().
{
using univariate::degree;
// std::cout <<"Poly is " << f << std::endl;
typedef std::pair<RT, int> Coeff_deg;
Coeff_deg T1, T2;
unsigned deg=degree(f);
int s=sign(f[0]);//, len;
long B=0;// The logarithm of the bound to be returned
bool boundSet=false;// The bound is not set initially
long temp,q;
int posCounter=0, negCounter=0, nPosCounter=0;
// The coefficients from posCounter to negCounter-1 have the same sign
// as f[0]; the coefficients from negCounter to nPosCounter-1 have the
// opposite sign of f[0].
std::queue< Coeff_deg > Neg;// Queue that stores the negative (between
// negCounter and nPosCounter) coefficients.
std::stack< Coeff_deg > Pos; // Stack that stores the positive (between
// posCounter and negCounter) coefficients.
int l1, l2;// size of the above two queues
while(posCounter != int(deg+1)){
// Find the first change in sign larger than posCounter and assign negCounter
// to this value. If no such sign variation occurs then
// set negCounter to -1.
negCounter = -1;// By default there is no such coefficient
//Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));// Push the first "positive" coefficient
Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));// Push the first "positive" coefficient
for(unsigned i=posCounter + 1;i <= deg; i++){
if(sign(f[i]) * s < 0){
negCounter=i; break;
}
if(sign(f[i]) *s > 0){// Store the list of "positive" coefficients
//Pos.push(Coeff_deg(RT(f[i]), i));// Note the actual degree is deg-i, but
// later we subtract degrees so we store only i
Pos.push(Coeff_deg(RT(f[i]), i));
}
}
if(negCounter == -1){
// std::cout <<"Returning the lower bound " << B << std::endl;
if ( B < 0 )
return pow2<RT>( abs(B) );
else
return 0;
}
// Now find the next coefficient that has the same sign as f[0].
nPosCounter = deg+1;// By default this is deg+1
Neg.push(Coeff_deg(RT(f[negCounter]), negCounter));
for(unsigned i=negCounter + 1;i <= deg; i++){
if(sign(f[i]) * s > 0){
nPosCounter=i; break;
}
if(sign(f[i]) *s < 0)// Store the list of "negative" coefficients
Neg.push(Coeff_deg(RT(f[i]), i));
}
// std::cout <<" Assigning to the queues done" << std::endl;
// Start computing the bound
// If the number of "positive" terms from posCounter to negCounter -1 are
// greater or equal to the number of "negative" terms from negCounter to
// nPosCounter -1 then we have the straightforward matching of "negative"
// coefficients with the "positive" ones.
l1 = Neg.size(); l2 = Pos.size();
if(l2 >= l1){
// std::cout <<"Pos length " << l2 << " greater than Neg length "
// << l1 << std::endl;
// or equally negCounter - posCounter >= nPosCounter - negCounter
for(int i=0; i < l1; i++){
T1= Neg.front(); Neg.pop();
//T2= Pos.front(); Pos.pop();
T2=Pos.top();Pos.pop();
// std::cout <<"Neg coeff " << T1.first << " Pos coeff " << T2.first
// << " Deg difference " << T1.second - T2.second
// << std::endl;
temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
q = temp/(T1.second - T2.second);
// std::cout << "Difference between logs " << temp
// << " temporary bound value " << B << std::endl;
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
}else{//Else split the coefficient f[posCounter] to compensate for
// the paucity of "positive" terms and then do the matching.
// std::cout <<" Pos length "<< l2 << " smaller than Neg length "
// << l1 << std::endl;
//T2=Pos.front(); Pos.pop();
T2= Pos.top();Pos.pop();
for(int i=0; i <= l1-l2; i++){
T1= Neg.front(); Neg.pop();
temp = bit_size( T1.first ) - bit_size( T2.first ) + bit_size(RT(l1-l2+1)) - 1;
q = temp/(T1.second-T2.second);
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
// std::cout <<" Splitting the leading coefficient done" << std::endl;
l1 = Neg.size();// Now the size of Neg and Pos should be the same
for(int i=0; i < l1; i++){
T1= Neg.front(); Neg.pop();
//T2= Pos.front(); Pos.pop();
Pos.pop();
temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
q = temp/(T1.second - T2.second);
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
}// end else
// std::cout <<" Matching the coefficients done" << std::endl;
posCounter = nPosCounter; Neg.empty(); Pos.empty();
}//end while
// std::cout <<"Returning the lower bound " << B << std::endl;
if ( B < 0 ) return pow2<RT>( abs(B) );
return 0;
}
| static long lower_power_2 | ( | const Poly & | f | ) | [inline, static] |
Definition at line 555 of file univariate_bounds.hpp.
References mmx::abs(), mmx::bit_size(), mmx::degree(), and mmx::sign().
{
using univariate::degree;
// std::cout <<"Poly is " << f << std::endl;
typedef std::pair<RT, int> Coeff_deg;
Coeff_deg T1, T2;
unsigned deg=degree(f);
int s=sign(f[0]);//, len;
long B=0;// The logarithm of the bound to be returned
bool boundSet=false;// The bound is not set initially
long temp,q;
int posCounter=0, negCounter=0, nPosCounter=0;
// The coefficients from posCounter to negCounter-1 have the same sign
// as f[0]; the coefficients from negCounter to nPosCounter-1 have the
// opposite sign of f[0].
std::queue< Coeff_deg > Neg;// Queue that stores the negative (between
// negCounter and nPosCounter) coefficients.
std::stack< Coeff_deg > Pos; // Stack that stores the positive (between
// posCounter and negCounter) coefficients.
int l1, l2;// size of the above two queues
while(posCounter != int(deg+1)){
// Find the first change in sign larger than posCounter and assign negCounter
// to this value. If no such sign variation occurs then
// set negCounter to -1.
negCounter = -1;// By default there is no such coefficient
//Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));// Push the first "positive" coefficient
Pos.push(Coeff_deg(RT(f[posCounter]), posCounter));// Push the first "positive" coefficient
for(unsigned i=posCounter + 1;i <= deg; i++){
if(sign(f[i]) * s < 0){
negCounter=i; break;
}
if(sign(f[i]) *s > 0){// Store the list of "positive" coefficients
//Pos.push(Coeff_deg(RT(f[i]), i));// Note the actual degree is deg-i, but
// later we subtract degrees so we store only i
Pos.push(Coeff_deg(RT(f[i]), i));
}
}
if(negCounter == -1){
// std::cout <<"Returning the lower bound " << B << std::endl;
if ( B < 0 ) return abs( B);
else return -1;
}
// Now find the next coefficient that has the same sign as f[0].
nPosCounter = deg+1;// By default this is deg+1
Neg.push(Coeff_deg(RT(f[negCounter]), negCounter));
for(unsigned i=negCounter + 1;i <= deg; i++){
if(sign(f[i]) * s > 0){
nPosCounter=i; break;
}
if(sign(f[i]) *s < 0)// Store the list of "negative" coefficients
Neg.push(Coeff_deg(RT(f[i]), i));
}
// std::cout <<" Assigning to the queues done" << std::endl;
// Start computing the bound
// If the number of "positive" terms from posCounter to negCounter -1 are
// greater or equal to the number of "negative" terms from negCounter to
// nPosCounter -1 then we have the straightforward matching of "negative"
// coefficients with the "positive" ones.
l1 = Neg.size(); l2 = Pos.size();
if(l2 >= l1){
// std::cout <<"Pos length " << l2 << " greater than Neg length "
// << l1 << std::endl;
// or equally negCounter - posCounter >= nPosCounter - negCounter
for(int i=0; i < l1; i++){
T1= Neg.front(); Neg.pop();
//T2= Pos.front(); Pos.pop();
T2=Pos.top();Pos.pop();
// std::cout <<"Neg coeff " << T1.first << " Pos coeff " << T2.first
// << " Deg difference " << T1.second - T2.second
// << std::endl;
temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
q = temp/(T1.second - T2.second);
// std::cout << "Difference between logs " << temp
// << " temporary bound value " << B << std::endl;
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
}else{//Else split the coefficient f[posCounter] to compensate for
// the paucity of "positive" terms and then do the matching.
// std::cout <<" Pos length "<< l2 << " smaller than Neg length "
// << l1 << std::endl;
//T2=Pos.front(); Pos.pop();
T2= Pos.top();Pos.pop();
for(int i=0; i <= l1-l2; i++){
T1= Neg.front(); Neg.pop();
temp = bit_size( T1.first ) - bit_size( T2.first ) + bit_size(RT(l1-l2+1)) - 1;
q = temp/(T1.second-T2.second);
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
// std::cout <<" Splitting the leading coefficient done" << std::endl;
l1 = Neg.size();// Now the size of Neg and Pos should be the same
for(int i=0; i < l1; i++){
T1= Neg.front(); Neg.pop();
//T2= Pos.front(); Pos.pop();
Pos.pop();
temp = bit_size( T1.first ) - bit_size( T2.first ) - 1;
q = temp/(T1.second - T2.second);
if(!boundSet || B < q + 2){// Choose the maximum
boundSet = true;
B = q+2;
}
}
}// end else
// std::cout <<" Matching the coefficients done" << std::endl;
posCounter = nPosCounter; Neg.empty(); Pos.empty();
}//end while
// std::cout <<"Returning the lower bound " << B << std::endl;
if ( B < 0 ) return abs( B);
else return -1;
}