1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
|
// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL: https://github.com/CGAL/cgal/blob/v6.1.1/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_roots.h $
// $Id: include/CGAL/Algebraic_kernel_d/Real_roots.h 08b27d3db14 $
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
//
// ============================================================================
// TODO: The comments are all original EXACUS comments and aren't adapted. So
// they may be wrong now.
/*! \file NiX/Real_roots.h
\brief This file defines the class NiX::Real_roots.
*/
#ifndef CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_H
#define CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_H
#include <CGAL/basic.h>
#include <CGAL/Polynomial.h>
#include <list>
#include <vector>
#include <queue>
namespace CGAL {
namespace internal {
/*! \ingroup NiX_Real_roots
* \brief This class provides operators for a comfortable construction of
* AlgebraicReal from Polynomials using a specific RealRootIsolator.
*
* A valid template argument for AlgebraicReal is NiX::Algebraic_real.
*/
template < class AlgebraicReal ,
class RealRootIsolator >
class Real_roots{
public:
//! The Real_roots type it self.
typedef Real_roots<AlgebraicReal,RealRootIsolator> Self;
//! First template argument.
typedef AlgebraicReal Algebraic_real;
//! Second template argument.
typedef RealRootIsolator Real_root_isolator;
//! The Polnomial type used by Algebraic_real and the Real_root_isolator.
typedef typename Algebraic_real::Polynomial_1 Polynomial;
private:
typedef typename AlgebraicReal::Coefficient Coefficient;
typedef typename AlgebraicReal::Rational Rational;
private:
template < class PolynomialIterator,
class IntIterator,
class AlgebraicRealOutputIterator,
class IntOutputIterator>
int gen_agebraic_reals_with_mults( PolynomialIterator fac,
PolynomialIterator fac_end,
IntIterator mul,
IntIterator CGAL_assertion_code(mul_end),
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult){
Self real_roots;
typedef std::pair<Algebraic_real, int> PAIR;
// find zeroes of each factor and sort them in ascending order
std::priority_queue< PAIR,std::vector<PAIR>,std::greater<PAIR> > pqueue;
std::vector<Algebraic_real> tmp;
while(fac != fac_end){
CGAL_assertion(mul != mul_end);
tmp.clear();
real_roots(*fac, std::back_inserter(tmp));
for (int j = 0; j < static_cast<int>(tmp.size()); j++) {
pqueue.push(PAIR(tmp[j], *mul));
}
fac++;
mul++;
}
// output factors and multiplicities
int n = 0;
while (!pqueue.empty()) {
*oi_root++ = pqueue.top().first;
*oi_mult++ = pqueue.top().second;
n++;
pqueue.pop();
}
return n;
}
private:
template < class PolynomialConstIterator,
class IntConstIterator,
class PolynomialOutputIterator>
void write_factors_by_multiplicity(PolynomialConstIterator fac,
PolynomialConstIterator fac_end,
IntConstIterator mul,
IntConstIterator CGAL_assertion_code(mul_end),
PolynomialOutputIterator oi_poly){
// output table such that table[m] contains square-free factor of
// multiplicity m (or else constant poly 1)
int m = 0;
while (fac != fac_end) {
CGAL_assertion(mul != mul_end);
while (m < *mul) {
*oi_poly++ = Polynomial(Coefficient(1)); m++;
}
*oi_poly++ = *fac; m++;
++fac; ++mul;
}
}
public:
/*! \brief computes all roots of the square free polynomial P in
* ascending order and returns the number of real roots.
*/
template <class AlgebraicRealOutputIterator>
int operator()(const Polynomial& poly ,
AlgebraicRealOutputIterator it){
CGAL_precondition_msg( typename CGAL::Polynomial_traits_d< Polynomial >::Is_square_free()(poly), "P not square free.");
return (*this)(Real_root_isolator(poly),it);
}
public:
/*! \brief computes all roots of the polynomial P in ascending order
* and their multiplicity and returns the number of real roots.
*
* This operator returns the number \e n of distinct real roots of \c poly.
* Each root is represented as an object of an instance AlgebraicReal.
* The operator writes these \e n real zeroes in ascending order to \c
* oi_root.
* It writes the multiplicities of the zeroes in the same order to
* \c oi_mult .
*/
template <class AlgebraicRealOutputIterator,
class IntOutputIterator>
int operator()(const Polynomial& poly,
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult){
CGAL_precondition(CGAL::degree(poly) >= 0);
// fast exit
if (CGAL::degree(poly) == 0)
return (poly.is_zero())?-1:0;
std::list<Polynomial> sqffac;
std::list<int> facmul;
filtered_square_free_factorize_utcf(poly,
std::back_inserter(sqffac),
std::back_inserter(facmul));
int number_of_real_roots=
gen_agebraic_reals_with_mults(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_root,
oi_mult);
return number_of_real_roots;
}
public:
/*! \brief computes all roots defined by the Real_root_isolator object in
* ascending order
*/
template <class AlgebraicRealOutputIterator>
int operator()(const Real_root_isolator& isolator,
AlgebraicRealOutputIterator it){
Polynomial poly = isolator.polynomial();
//cout << "P: "<<poly<<endl;
// take out exact known roots out of Poly
for(int j = 0 ; j < isolator.number_of_real_roots(); j++){
if(isolator.is_exact_root(j)){
Rational root(isolator.left_bound(j));
CGAL::simplify(root);
typedef CGAL::Fraction_traits<Rational> FT;
typename FT::Numerator_type num;
typename FT::Denominator_type denom;
typename FT::Decompose decomp;
decomp(root,num,denom);
Polynomial linear_factor(Coefficient(-num),
Coefficient(denom));
poly=CGAL::integral_division(poly,linear_factor);
}
}
//cout << "P_without_exact: "<<poly<<endl;
std::vector<AlgebraicReal> conjugated_roots;
std::back_insert_iterator<std::vector<AlgebraicReal> > con_it
= std::back_inserter(conjugated_roots);
// construct AlgebraicReal
for(int j = 0 ; j < isolator.number_of_real_roots(); j++){
if(isolator.is_exact_root(j)){
// exact roots (Rational
Rational root=isolator.left_bound(j);
CGAL::simplify(root);
*it++=AlgebraicReal(root);
}else{
// other roots
Rational left = isolator.left_bound(j);
Rational right= isolator.right_bound(j);
CGAL::simplify(left);
CGAL::simplify(right);
AlgebraicReal tmp(poly,left,right);
*it++=tmp;
*con_it++=tmp;
}
}
AlgebraicReal::conjugate(conjugated_roots.begin(),
conjugated_roots.end());
return isolator.number_of_real_roots();
}
/*! \brief factor \c p by multiplicities, return both factors and their roots
*
* This operator is for those users who have an
* Polynomial \c poly which is not necessarily square-free, and who
* want to get both its square-free factorization and its real roots with
* their respective multiplicities.
*
* This operator returns the number \e n of distinct real roots of \c poly .
* Each root is represented as an object of an instance AlgebraicReal.
* The operator writes these \e n real zeroes in ascending order to \c
* oi_root.
* It writes the multiplicities of the roots in the same order to
* \c oi_mult .
* Finally, it writes the square-free factors of \c p
* to \c oi_poly such that the factor #<I>k</I> written is the factor
* with exponent \e k in the square-free factorization of \c p , or
* the constant polynomial 1 if a factor of multiplicity \e k does
* not occur. Yes, this means that the first factor written, which is
* factor #0, will always be 1.
*
* The data types involved are determined the \c AlgebraicReal
* template argument. In particular, \c p must be of type
* \c NiX::Polynomial<AlgebraicReal::Coefficient>, as are its factors;
* the roots are of type \c AlgebraicReal ; and the multiplicities are
* of type \c int .
*
*/
template <class AlgebraicRealOutputIterator,
class IntOutputIterator,
class PolynomialOutputIterator>
int operator()( const Polynomial& poly,
AlgebraicRealOutputIterator oi_root,
IntOutputIterator oi_mult,
PolynomialOutputIterator oi_poly) {
CGAL_precondition(CGAL::degree(poly) >= 0);
// fast exit
if (CGAL::degree(poly) == 0)
return (poly.is_zero())?-1:0;
std::list<Polynomial> sqffac;
std::list<int> facmul;
filtered_square_free_factorize_utcf(poly,
std::back_inserter(sqffac),
std::back_inserter(facmul));
write_factors_by_multiplicity(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_poly);
int numer_of_real_roots =
gen_agebraic_reals_with_mults(sqffac.begin(),sqffac.end(),
facmul.begin(),facmul.end(),
oi_root,
oi_mult);
return numer_of_real_roots;
}
};
} // namespace internal
} //namespace CGAL
#endif // CGAL_ALGEBRAIC_KERNEL_D_REAL_ROOTS_ROOTS_H
|