1
// Copyright (c) 2006-2013 INRIA Nancy-Grand Est (France). All rights reserved.
3
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
4
// modify it under the terms of the GNU Lesser General Public License as
5
// published by the Free Software Foundation; either version 3 of the License,
6
// or (at your option) any later version.
8
// See the file LICENSE.LGPL distributed with CGAL.
10
// Licensees holding a valid commercial license may use this file in
11
// accordance with the commercial license agreement provided with the software.
13
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
14
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19
// Author: Luis Peñaranda <luis.penaranda@gmx.com>
21
#ifndef CGAL_RS_FUNCTORS_Z_1_H
22
#define CGAL_RS_FUNCTORS_Z_1_H
25
#include <CGAL/Gmpfi.h>
30
template <class Polynomial_,
37
struct Construct_algebraic_real_z_1{
38
typedef Polynomial_ Polynomial;
39
typedef ZPolynomial_ ZPolynomial;
40
typedef PolConverter_ PolConverter;
41
typedef Algebraic_ Algebraic;
43
typedef Coefficient_ Coefficient;
44
typedef Isolator_ Isolator;
45
typedef Algebraic result_type;
48
Algebraic operator()(const T &a)const{
52
Algebraic operator()(const Polynomial &p,size_t i)const{
53
ZPolynomial zp=PolConverter()(p);
61
Algebraic operator()(const Polynomial &p,
64
return Algebraic(p,PolConverter()(p),l,r);
67
}; // struct Construct_algebraic_real_z_1
69
template <class Polynomial_,class Algebraic_>
70
struct Compute_polynomial_z_1:
71
public std::unary_function<Algebraic_,Polynomial_>{
72
typedef Polynomial_ Polynomial;
73
typedef Algebraic_ Algebraic;
74
Polynomial operator()(const Algebraic &x)const{
77
}; // struct Compute_polynomial_z_1
79
template <class Polynomial_,class Ptraits_>
80
struct Is_coprime_z_1:
81
public std::binary_function<Polynomial_,Polynomial_,bool>{
82
typedef Polynomial_ Polynomial;
83
typedef Ptraits_ Ptraits;
84
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
85
typedef typename Ptraits::Degree Degree;
86
inline bool operator()(const Polynomial &p1,const Polynomial &p2)const{
87
return Degree()(Gcd()(p1,p2))==0;
89
}; // struct Is_coprime_z_1
91
template <class Polynomial_,class Ptraits_>
92
struct Make_coprime_z_1{
93
typedef Polynomial_ Polynomial;
94
typedef Ptraits_ Ptraits;
95
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
96
typedef typename Ptraits::Degree Degree;
97
typedef typename Ptraits::Integral_division_up_to_constant_factor
99
bool operator()(const Polynomial &p1,
100
const Polynomial &p2,
103
Polynomial &q2)const{
107
return Degree()(Gcd()(p1,p2))==0;
109
}; // struct Make_coprime_z_1
111
template <class Polynomial_,
121
typedef Polynomial_ Polynomial_1;
122
typedef ZPolynomial_ ZPolynomial_1;
123
typedef PolConverter_ PolConverter;
124
typedef Bound_ Bound;
125
typedef Algebraic_ Algebraic;
126
typedef Isolator_ Isolator;
127
typedef Signat_ ZSignat;
128
typedef Ptraits_ Ptraits;
129
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
130
typedef typename Ptraits::Square_free_factorize_up_to_constant_factor
132
typedef typename Ptraits::Degree Degree;
133
typedef typename Ptraits::Make_square_free Sfpart;
134
typedef ZPtraits_ ZPtraits;
135
typedef typename ZPtraits::Gcd_up_to_constant_factor ZGcd;
136
typedef typename ZPtraits::Square_free_factorize_up_to_constant_factor
138
typedef typename ZPtraits::Degree ZDegree;
139
typedef typename ZPtraits::Make_square_free ZSfpart;
141
template <class OutputIterator>
142
OutputIterator operator()(const Polynomial_1 &p,
143
OutputIterator res)const{
144
typedef std::pair<Polynomial_1,int> polmult;
145
typedef std::vector<polmult> sqvec;
146
typedef std::pair<ZPolynomial_1,int> zpolmult;
147
typedef std::vector<zpolmult> zsqvec;
149
ZPolynomial_1 zp=PolConverter()(p);
150
Polynomial_1 sfp=Sfpart()(p);
151
ZPolynomial_1 zsfp=PolConverter()(sfp);
153
ZSqfr()(zp,std::back_inserter(zsfv));
155
int *m=(int*)calloc(isol.number_of_real_roots(),sizeof(int));
156
for(typename zsqvec::iterator i=zsfv.begin();i!=zsfv.end();++i){
157
int k=ZDegree()(i->first);
158
ZSignat signof(i->first);
159
for(int j=0;k&&j<isol.number_of_real_roots();++j){
162
signof(isol.left_bound(j));
164
signof(isol.right_bound(j));
166
((sg_l==CGAL::ZERO)&&
167
(sg_r==CGAL::ZERO))){
174
for(int l=0;l<isol.number_of_real_roots();++l)
175
*res++=std::make_pair(Algebraic(sfp,
178
isol.right_bound(l)),
184
template <class OutputIterator>
185
OutputIterator operator()(const Polynomial_1 &p,
186
bool known_to_be_square_free,
187
OutputIterator res)const{
188
ZPolynomial_1 zp=PolConverter()(p);
190
for(int l=0;l<isol.number_of_real_roots();++l)
194
isol.right_bound(l));
198
template <class OutputIterator>
199
OutputIterator operator()(const Polynomial_1 &p,
202
OutputIterator res)const{
203
typedef std::vector<Algebraic> RV;
204
typedef std::pair<Polynomial_1,int> PM;
205
typedef std::vector<PM> PMV;
206
typedef typename PMV::iterator PMVI;
207
CGAL_precondition_msg(l<=u,
208
"left bound must be <= right bound");
209
RV roots; // all roots of the polynomial
210
this->operator()(p,false,std::back_inserter(roots));
211
size_t nb_roots=roots.size();
212
// indices of the first and last roots to be reported:
213
size_t index_l=0,index_u;
214
while(index_l<nb_roots&&roots[index_l]<l)
216
CGAL_assertion(index_l<=nb_roots);
217
if(index_l==nb_roots)
220
while(index_u<nb_roots&&roots[index_u]<u)
222
CGAL_assertion(index_u<=nb_roots);
225
// now, we have to return roots in [index_l,index_u)
227
Sqfr()(p,std::back_inserter(sfv)); // square-free fact. of p
228
// array to store the multiplicities
229
int *m=(int*)calloc(nb_roots,sizeof(int));
230
// we iterate over all the pairs <root,mult> and match the
231
// roots in the interval [index_l,index_u)
232
for(PMVI i=sfv.begin();i!=sfv.end();++i){
233
ZPolynomial_1 zifirst=PolConverter()(i->first);
234
int k=ZDegree()(zifirst);
235
ZSignat signof(zifirst);
236
for(size_t j=index_l;k&&j<index_u;++j){
239
signof(roots[j].get_left());
241
signof(roots[j].get_right());
243
((sg_l==CGAL::ZERO)&&
244
(sg_r==CGAL::ZERO))){
251
for(size_t l=index_l;l<index_u;++l)
252
*res++=std::make_pair(roots[l],m[l]);
257
template <class OutputIterator>
258
OutputIterator operator()(const Polynomial_1 &p,
259
bool known_to_be_square_free,
262
OutputIterator res)const{
263
typedef std::vector<Algebraic> RV;
264
typedef typename RV::iterator RVI;
265
CGAL_precondition_msg(l<=u,
266
"left bound must be <= right bound");
269
known_to_be_square_free,
270
std::back_inserter(roots));
271
for(RVI it=roots.begin();it!=roots.end();it++)
277
}; // struct Solve_z_1
279
template <class Polynomial_,
289
public std::binary_function<Polynomial_,Algebraic_,CGAL::Sign>{
290
// This implementation will work with any polynomial type whose
291
// coefficient type is explicit interoperable with Gmpfi.
292
// TODO: Make this function generic.
294
typedef Polynomial_ Polynomial_1;
295
typedef ZPolynomial_ ZPolynomial_1;
296
typedef PolConverter_ PolConverter;
297
typedef Bound_ Bound;
298
typedef Algebraic_ Algebraic;
299
typedef Refiner_ Refiner;
300
typedef Signat_ ZSignat;
301
typedef Ptraits_ Ptraits;
302
typedef ZPtraits_ ZPtraits;
305
CGAL::Uncertain<CGAL::Sign> eval_interv(const Polynomial_1 &p,
307
const Bound &r)const{
308
typedef typename Ptraits::Substitute Subst;
309
std::vector<CGAL::Gmpfi> substitutions;
310
substitutions.push_back(CGAL::Gmpfi(l,r));
311
CGAL::Gmpfi eval=Subst()(p,
312
substitutions.begin(),
313
substitutions.end());
317
// This function assumes that the sign of the evaluation is not zero,
318
// it just refines x until having the correct sign.
319
CGAL::Sign refine_and_return(const Polynomial_1 &p,Algebraic x)const{
320
CGAL::Gmpfr xl(x.get_left());
321
CGAL::Gmpfr xr(x.get_right());
322
CGAL::Uncertain<CGAL::Sign> s;
324
Refiner()(x.get_zpol(),
327
2*CGAL::max(xl.get_precision(),
328
xr.get_precision()));
329
s=eval_interv(p,xl,xr);
330
if(!s.is_same(Uncertain<CGAL::Sign>::indeterminate())){
339
CGAL::Sign operator()(const Polynomial_1 &p,Algebraic x)const{
340
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
341
typedef typename Ptraits::Make_square_free Sfpart;
342
typedef typename Ptraits::Degree Degree;
343
typedef typename Ptraits::Differentiate Deriv;
344
CGAL::Uncertain<CGAL::Sign> unknown=
345
Uncertain<CGAL::Sign>::indeterminate();
346
CGAL::Uncertain<CGAL::Sign> s=eval_interv(p,
349
if(!s.is_same(unknown))
351
// We are not sure about the sign. We calculate the gcd in
352
// order to know if both polynomials have common roots.
353
Polynomial_1 sfpp=Sfpart()(p);
354
Polynomial_1 gcd=Gcd()(sfpp,Sfpart()(x.get_pol()));
356
return refine_and_return(p,x);
358
// At this point, gcd is not 1; we proceed as follows:
359
// -we refine x until having p monotonic in x's interval (to be
360
// sure that p has at most one root on that interval),
361
// -if the gcd has a root on this interval, both roots are
362
// equal (we return 0), otherwise, we refine until having a
365
// How to assure that p is monotonic in an interval: when its
366
// derivative is never zero in that interval.
367
Polynomial_1 dsfpp=Deriv()(sfpp);
368
CGAL::Gmpfr xl(x.get_left());
369
CGAL::Gmpfr xr(x.get_right());
370
while(eval_interv(dsfpp,xl,xr).is_same(unknown)){
371
Refiner()(x.get_zpol(),
374
2*CGAL::max(xl.get_precision(),
375
xr.get_precision()));
380
// How to know that the gcd has a root: evaluate endpoints.
381
CGAL::Sign sleft,sright;
382
ZSignat sign_at_gcd(PolConverter()(gcd));
383
if((sleft=sign_at_gcd(x.get_left()))==CGAL::ZERO||
384
(sright=sign_at_gcd(x.get_right()))==CGAL::ZERO||
387
return refine_and_return(p,x);
389
}; // struct Sign_at_z_1
391
template <class Polynomial_,
400
class Is_zero_at_z_1:
401
public std::binary_function<Polynomial_,Algebraic_,bool>{
402
// This implementation will work with any polynomial type whose
403
// coefficient type is explicit interoperable with Gmpfi.
404
// TODO: Make this function generic.
406
typedef Polynomial_ Polynomial_1;
407
typedef ZPolynomial_ ZPolynomial_1;
408
typedef PolConverter_ PolConverter;
409
typedef Bound_ Bound;
410
typedef Algebraic_ Algebraic;
411
typedef Refiner_ Refiner;
412
typedef Signat_ ZSignat;
413
typedef Ptraits_ Ptraits;
414
typedef ZPtraits_ ZPtraits;
417
CGAL::Uncertain<CGAL::Sign> eval_interv(const Polynomial_1 &p,
419
const Bound &r)const{
420
typedef typename Ptraits::Substitute Subst;
421
std::vector<CGAL::Gmpfi> substitutions;
422
substitutions.push_back(CGAL::Gmpfi(l,r));
423
CGAL::Gmpfi eval=Subst()(p,
424
substitutions.begin(),
425
substitutions.end());
430
bool operator()(const Polynomial_1 &p,Algebraic x)const{
431
typedef typename Ptraits::Gcd_up_to_constant_factor Gcd;
432
typedef typename Ptraits::Make_square_free Sfpart;
433
typedef typename Ptraits::Degree Degree;
434
typedef typename Ptraits::Differentiate Deriv;
435
CGAL::Uncertain<CGAL::Sign> unknown=
436
Uncertain<CGAL::Sign>::indeterminate();
437
CGAL::Uncertain<CGAL::Sign> s=eval_interv(p,
440
if(!s.is_same(unknown))
441
return (s==CGAL::ZERO);
442
// We are not sure about the sign. We calculate the gcd in
443
// order to know if both polynomials have common roots.
444
Polynomial_1 sfpp=Sfpart()(p);
445
Polynomial_1 gcd=Gcd()(sfpp,Sfpart()(x.get_pol()));
449
// At this point, gcd is not 1; we proceed as follows:
450
// -we refine x until having p monotonic in x's interval (to be
451
// sure that p has at most one root on that interval),
452
// -if the gcd has a root on this interval, both roots are
453
// equal (we return 0), otherwise, we refine until having a
456
// How to assure that p is monotonic in an interval: when its
457
// derivative is never zero in that interval.
458
Polynomial_1 dsfpp=Deriv()(sfpp);
459
CGAL::Gmpfr xl(x.get_left());
460
CGAL::Gmpfr xr(x.get_right());
461
while(eval_interv(dsfpp,xl,xr).is_same(unknown)){
462
Refiner()(x.get_zpol(),
465
2*CGAL::max(xl.get_precision(),
466
xr.get_precision()));
471
// How to know that the gcd has a root: evaluate endpoints.
472
CGAL::Sign sleft,sright;
473
ZSignat sign_at_gcd(PolConverter()(gcd));
474
return((sleft=sign_at_gcd(x.get_left()))==CGAL::ZERO||
475
(sright=sign_at_gcd(x.get_right()))==CGAL::ZERO||
478
}; // class Is_zero_at_z_1
480
// TODO: it says in the manual that this should return a size_type, but test
481
// programs assume that this is equal to int
482
template <class Polynomial_,
486
struct Number_of_solutions_z_1:
487
public std::unary_function<Polynomial_,int>{
488
typedef Polynomial_ Polynomial_1;
489
typedef ZPolynomial_ ZPolynomial_1;
490
typedef PolConverter_ PolConverter;
491
typedef Isolator_ Isolator;
492
size_t operator()(const Polynomial_1 &p)const{
493
// TODO: make sure that p is square free (precondition)
494
Isolator isol(PolConverter()(p));
495
return isol.number_of_real_roots();
497
}; // struct Number_of_solutions_z_1
499
// This functor not only compares two algebraic numbers. In case they are
500
// different, it refines them until they do not overlap.
501
template <class Algebraic_,
505
public std::binary_function<Algebraic_,Algebraic_,CGAL::Comparison_result>{
506
typedef Algebraic_ Algebraic;
507
typedef Bound_ Bound;
508
typedef Comparator_ Comparator;
510
CGAL::Comparison_result operator()(Algebraic a,Algebraic b)const{
511
Bound al=a.get_left();
512
Bound ar=a.get_right();
513
Bound bl=b.get_left();
514
Bound br=b.get_right();
515
CGAL::Comparison_result c=Comparator()(a.get_zpol(),al,ar,
524
CGAL::Comparison_result operator()(Algebraic a,const Bound &b)const{
525
Bound al=a.get_left();
526
Bound ar=a.get_right();
528
CGAL::Comparison_result c=Comparator()(a.get_zpol(),al,ar,
529
balg.get_zpol(),b,b);
536
CGAL::Comparison_result operator()(Algebraic a,const T &b)const{
537
Bound al=a.get_left();
538
Bound ar=a.get_right();
540
CGAL::Comparison_result c=Comparator()(a.get_zpol(),
551
}; // class Compare_z_1
553
template <class Algebraic_,
556
struct Bound_between_z_1:
557
public std::binary_function<Algebraic_,Algebraic_,Bound_>{
558
typedef Algebraic_ Algebraic;
559
typedef Bound_ Bound;
560
typedef Comparator_ Comparator;
562
Bound operator()(Algebraic a,Algebraic b)const{
563
typedef Compare_z_1<Algebraic,Bound,Comparator> Compare;
564
typename Bound::Precision_type prec;
565
switch(Compare()(a,b)){
567
CGAL_assertion(b.get_right()<a.get_left());
568
prec=CGAL::max(b.get_right().get_precision(),
569
a.get_left().get_precision());
570
return Bound::add(b.get_right(),
575
CGAL_assertion(a.get_right()<b.get_left());
576
prec=CGAL::max(a.get_right().get_precision(),
577
b.get_left().get_precision());
578
return Bound::add(a.get_right(),
584
"bound between two equal numbers");
587
}; // struct Bound_between_z_1
589
template <class Polynomial_,
600
public std::binary_function<Algebraic_,Polynomial_,std::pair<Bound_,Bound_> >{
601
typedef Polynomial_ Polynomial_1;
602
typedef ZPolynomial_ ZPolynomial_1;
603
typedef PolConverter_ PolConverter;
604
typedef Bound_ Bound;
605
typedef Algebraic_ Algebraic;
606
typedef Isolator_ Isolator;
607
typedef Comparator_ Comparator;
608
typedef Signat_ Signat;
609
typedef Ptraits_ Ptraits;
610
typedef ZPtraits_ ZPtraits;
612
std::pair<Bound,Bound>
613
operator()(const Algebraic &a,const Polynomial_1 &p)const{
614
std::vector<Algebraic> roots;
615
std::back_insert_iterator<std::vector<Algebraic> > rit(roots);
616
typedef Solve_z_1<Polynomial_1,
625
typedef Compare_z_1<Algebraic,Bound,Comparator> Compare;
626
Solve()(p,false,rit);
627
for(typename std::vector<Algebraic>::size_type i=0;
630
// we use the comparison functor, that makes both
631
// intervals disjoint iff the algebraic numbers they
632
// represent are not equal
633
Compare()(a,roots[i]);
635
return std::make_pair(a.left(),a.right());
639
template <class Polynomial_,
643
struct Approximate_absolute_z_1:
644
public std::binary_function<Algebraic_,int,std::pair<Bound_,Bound_> >{
645
typedef Polynomial_ Polynomial_1;
646
typedef Bound_ Bound;
647
typedef Algebraic_ Algebraic;
648
typedef Refiner_ Refiner;
650
// This implementation assumes that Bound is Gmpfr.
651
// TODO: make generic.
652
std::pair<Bound,Bound> operator()(const Algebraic &x,const int &a)const{
653
Bound xl(x.get_left()),xr(x.get_right());
654
// refsteps=log2(xl-xr)
657
mpfr_sub(temp,xr.fr(),xl.fr(),GMP_RNDU);
658
mpfr_log2(temp,temp,GMP_RNDU);
659
long refsteps=mpfr_get_si(temp,GMP_RNDU);
661
Refiner()(x.get_zpol(),xl,xr,CGAL::abs(refsteps+a));
665
(xr-xl)*CGAL::ipower(Bound(2),a)<=Bound(1):
666
(xr-xl)<=CGAL::ipower(Bound(2),-a));
667
return std::make_pair(xl,xr);
669
}; // struct Approximate_absolute_z_1
671
template <class Polynomial_,
675
struct Approximate_relative_z_1:
676
public std::binary_function<Algebraic_,int,std::pair<Bound_,Bound_> >{
677
typedef Polynomial_ Polynomial_1;
678
typedef Bound_ Bound;
679
typedef Algebraic_ Algebraic;
680
typedef Refiner_ Refiner;
682
std::pair<Bound,Bound> operator()(const Algebraic &x,const int &a)const{
684
return std::make_pair(Bound(0),Bound(0));
685
Bound error=CGAL::ipower(Bound(2),CGAL::abs(a));
686
Bound xl(x.get_left()),xr(x.get_right());
687
Bound max_b=(CGAL::max)(CGAL::abs(xr),CGAL::abs(xl));
688
while(a>0?(xr-xl)*error>max_b:(xr-xl)>error*max_b){
689
Refiner()(x.get_zpol(),
694
CGAL::max(xl.get_precision(),
695
xr.get_precision())));
696
max_b=(CGAL::max)(CGAL::abs(xr),CGAL::abs(xl));
702
(xr-xl)*CGAL::ipower(Bound(2),a)<=max_b:
703
(xr-xl)<=CGAL::ipower(Bound(2),-a)*max_b);
704
return std::make_pair(xl,xr);
706
}; // struct Approximate_relative_z_1
708
} // namespace RS_AK1
711
#endif // CGAL_RS_FUNCTORS_Z_1_H