moved to Arrangement_2 sub directory

This commit is contained in:
Efi Fogel 2002-11-29 12:17:33 +00:00
parent 6a136e5254
commit d147ebb274
2 changed files with 0 additions and 3053 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,965 +0,0 @@
// ======================================================================
//
// Copyright (c) 2001 The CGAL Consortium
//
// This software and related documentation is part of an INTERNAL release
// of the Computational Geometry Algorithms Library (CGAL). It is not
// intended for general use.
//
// ----------------------------------------------------------------------
//
// release : $CGAL_Revision: CGAL-2.4-I-5 $
// release_date : $CGAL_Date: 2001/08/31 $
//
// file : include/CGAL/Conic_arc_2_eq.h
// package : Arrangement (2.19)
// maintainer : Eyal Flato <flato@math.tau.ac.il>
// author(s) : Ron Wein <wein@post.tau.ac.il>
// coordinator : Tel-Aviv University (Dan Halperin <halperin@math.tau.ac.il>)
//
// ======================================================================
#ifndef CGAL_CONIC_ARC_2_EQ_H
#define CGAL_CONIC_ARC_2_EQ_H
//#include <CGAL/number_type_tags.h>
//#include <CGAL/double.h>
//#include <CGAL/double.h>
#include <CGAL/basic.h>
#include <CGAL/leda_bigfloat.h>
CGAL_BEGIN_NAMESPACE
/*
typedef double APNT;
#define APNT_EPS 0.00000001
#define COMP_EPS 0.000001
#define TO_APNT(x) CGAL::to_double(x)
#define APNT_ABS(x) fabs(x)
*/
typedef leda_bigfloat APNT;
#define APNT_BITLEN 512
#define ZERO_BITLEN -25
#define APNT_ZERO(x) (x == 0 || ilog2(x) < ZERO_BITLEN)
#define APNT_CZERO(x) (x == 0 || ilog2(x) < ZERO_BITLEN/2)
#define TO_APNT(x) to_bigfloat(x)
#define APNT_ABS(x) CGAL_NTS abs(x)
// ----------------------------------------------------------------------------
// Compare two approximate values.
//
template <class APNT>
Comparison_result eps_compare (const APNT& val1, const APNT& val2)
{
APNT denom = APNT_ABS(val1 - val2);
APNT numer = APNT_ABS(val1) + APNT_ABS(val2);
if (APNT_CZERO(val1) && APNT_CZERO(val2))
// if (numer < APNT_EPS)
{
// The two number are very close to zero:
if (APNT_ZERO(val1 - val2))
//if (denom < numer)
return (EQUAL);
else
return ((val1 < val2) ? SMALLER : LARGER);
}
else
{
// | x - y |
// x = y <==> ----------- < COMP_EPS
// |x| + |y|
if (APNT_ZERO(denom / numer))
//if (denom / numer < COMP_EPS)
return (EQUAL);
else
return ((val1 < val2) ? SMALLER : LARGER);
}
}
/*****************************************************************************/
// Some functions for quick-solving equations when working with doubles.
//--------------------------------------------------------------------
// Solve the cubic equation: a*x^3 + b*x^2 + c*x + d = 0 (a != 0),
// with double precision floats and using Tartaglia's method.
// The equation is assumed not to have multiple roots.
// The function returns the number of real solutions.
// The roots area must be at least of size 3.
//
template <class NT>
int _Tartaglia_cubic_eq (const NT& a,
const NT& b,
const NT& c,
const NT& d,
NT *roots)
{
// Some constants.
static const NT _Zero = 0;
static const NT _One = 1;
static const NT _Two = 2;
static const NT _Three = 3;
static const NT _Nine = 9;
static const NT _Twenty_seven = 27;
static const NT _Fifty_four = 54;
static const NT _One_third = _One / _Three;
// Normalize the equation to obtain: x^3 + a2*x^2 + a1*x^1 + a0 = 0.
const NT a2 = b / a;
const NT a1 = c / a;
const NT a0 = d / a;
// Caclculate the "cubic discriminant" D.
const NT Q = (_Three*a1 - a2*a2) /
_Nine;
const NT R = (_Nine*a1*a2 - _Twenty_seven*a0 - _Two*a2*a2*a2) /
_Fifty_four;
const NT D = Q*Q*Q + R*R;
NT S, T;
if (D > _Zero)
{
// One real-valued root (the other two are complex conjugates):
NT temp = R + CGAL::sqrt(D);
if (temp > _Zero)
S = ::pow(temp, _One_third);
else
S = - ::pow(-temp, _One_third);
temp = R - CGAL::sqrt(D);
if (temp > _Zero)
T = ::pow(temp, _One_third);
else
T = - ::pow(-temp, _One_third);
roots[0] = S + T - a2/_Three;
return (1);
}
else
{
// We have three real-valued roots:
const NT phi = ::atan2 (CGAL::sqrt(-D), R) / _Three;
const NT sin_phi = ::sin(phi);
const NT cos_phi = ::cos(phi);
roots[0] = _Two*CGAL::sqrt(-Q)*cos_phi - a2/_Three;
roots[1] = -CGAL::sqrt(-Q)*cos_phi -
CGAL::sqrt(-_Three*Q)*sin_phi - a2/_Three;
roots[2] = -CGAL::sqrt(-Q)*cos_phi +
CGAL::sqrt(-_Three*Q)*sin_phi - a2/_Three;
return (3);
}
}
//--------------------------------------------------------------------
// Calculate the square root of a complex number.
//
template <class NT>
void _complex_sqrt (const NT& real, const NT& imag,
NT& sqrt_re, NT& sqrt_im)
{
static const NT _Zero = 0;
static const NT _Two = 2;
// Check the special case where imag=0:
if (imag == _Zero)
{
if (real >= _Zero)
{
sqrt_re = CGAL::sqrt(real);
sqrt_im = _Zero;
}
else
{
sqrt_re = _Zero;
sqrt_im = CGAL::sqrt(-real);
}
return;
}
// We seek x,y such that: (x^2 - y^2 = 0) and (2xy = imag).
// So, we get the equation: x^4 - real*x^2 - (imag/2)^2 = 0.
// This equation has one positive root (and one irrelevant negative root).
const NT sqrt_disc = CGAL::sqrt(real*real + imag*imag);
const NT x_2 = (real + sqrt_disc) / _Two;
// Calculate on of the roots (the other root is -sqrt_re - i*sqrt_im).
sqrt_re = CGAL::sqrt(x_2);
sqrt_im = imag / (_Two*sqrt_re);
return;
}
//--------------------------------------------------------------------
// Solve the quartic equation: a*x^4 + b*x^3 + c*x^2 + d*x + e = 0 (a != 0),
// with double precision floats and using Ferrari's method.
// The equation is assumed not to have multiple roots.
// The function returns the number of real solutions.
// The roots area must be at least of size 4.
//
template <class NT>
int _Ferrari_quartic_eq (const NT& a,
const NT& b,
const NT& c,
const NT& d,
const NT& e,
NT *roots)
{
// Some constants.
static const NT _Zero = 0;
static const NT _One = 1;
static const NT _Two = 2;
static const NT _Three = 3;
static const NT _Four = 4;
static const NT _Eight = 8;
static const NT _One_quarter = _One/_Four;
static const NT _One_half = _One/_Two;
static const NT _Three_quarters = _Three/_Four;
// Normalize the equation to obtain: x^4 + a3*x^3 + a2*x^2 + a1*x^1 + a0 = 0.
const NT a3 = b / a;
const NT a2 = c / a;
const NT a1 = d / a;
const NT a0 = e / a;
// Find a real root of the resolvent cubic equation:
// y^3 - a2*y^2 + (a1*a3 - 4*a0)*y + (2*a2*a0 - a1^2 - a0*a3^2) = 0.
NT cubic_roots[3];
NT y1;
_Tartaglia_cubic_eq (_One,
-a2,
a1*a3 - _Four*a0,
_Four*a2*a0 - a1*a1 - a3*a3*a0,
cubic_roots);
y1 = cubic_roots[0];
// Calculate R^2 and act accordingly.
const NT R_square = _One_quarter*a3*a3 - a2 + y1;
int n_roots = 0;
if (R_square == _Zero)
{
// R is _Zero: In this case, D and E must be real-valued.
const NT disc_square = y1*y1 - _Four*a0;
if (disc_square < _Zero)
{
// No real roots at all.
return (0);
}
const NT disc = CGAL::sqrt(disc_square);
const NT D_square = _Three_quarters*a3*a3 + _Two*(disc - a2);
const NT E_square = _Three_quarters*a3*a3 - _Two*(disc + a2);
if (D_square > _Zero)
{
// Add two real-valued roots.
const NT D = CGAL::sqrt(D_square);
roots[n_roots] = -_One_quarter*a3 + _One_half*D;
n_roots++;
roots[n_roots] = -_One_quarter*a3 - _One_half*D;
n_roots++;
}
if (E_square > _Zero)
{
// Add two real-valued roots.
const NT E = CGAL::sqrt(E_square);
roots[n_roots] = -_One_quarter*a3 + _One_half*E;
n_roots++;
roots[n_roots] = -_One_quarter*a3 - _One_half*E;
n_roots++;
}
}
else if (R_square > _Zero)
{
// R is real-valued: In this case, D and E must also be real-valued.
const NT R = CGAL::sqrt(R_square);
const NT D_square = _Three_quarters*a3*a3 - R_square - _Two*a2 +
(_Four*a3*a2 - _Eight*a1 - a3*a3*a3) / (_Four*R);
const NT E_square = _Three_quarters*a3*a3 - R_square - _Two*a2 -
(_Four*a3*a2 - _Eight*a1 - a3*a3*a3) / (_Four*R);
if (D_square > _Zero)
{
// Add two real-valued roots.
const NT D = CGAL::sqrt(D_square);
roots[n_roots] = -_One_quarter*a3 + _One_half*(R + D);
n_roots++;
roots[n_roots] = -_One_quarter*a3 + _One_half*(R - D);
n_roots++;
}
if (E_square > _Zero)
{
// Add two real-valued roots.
const NT E = CGAL::sqrt(E_square);
roots[n_roots] = -_One_quarter*a3 + _One_half*(E - R);
n_roots++;
roots[n_roots] = -_One_quarter*a3 - _One_half*(E + R);
n_roots++;
}
}
else
{
// R is imaginary: Calclualte D and E as complex numbers.
const NT R_im = CGAL::sqrt(-R_square);
const NT R_inv_im = -_One / R_im; // The inverse of R.
const NT D_square_re = _Three_quarters*a3*a3 - R_square - _Two*a2;
const NT D_square_im =
(a3*a2 - _Two*a1 - _One_quarter*a3*a3*a3) * R_inv_im;
NT D_re, D_im;
const NT E_square_re = D_square_re;
const NT E_square_im = -D_square_im;
NT E_re, E_im;
_complex_sqrt (D_square_re, D_square_im,
D_re, D_im);
_complex_sqrt (E_square_re, E_square_im,
E_re, E_im);
// Use only the combinations that yield real-valued numbers.
if (R_im == -D_im)
{
roots[n_roots] = -_One_quarter*a3 + _One_half*D_re;
n_roots++;
}
if (R_im == D_im)
{
roots[n_roots] = -_One_quarter*a3 - _One_half*D_re;
n_roots++;
}
if (R_im == E_im)
{
roots[n_roots] = -_One_quarter*a3 + _One_half*E_re;
n_roots++;
}
if (R_im == -E_im)
{
roots[n_roots] = -_One_quarter*a3 - _One_half*D_re;
n_roots++;
}
}
return (n_roots);
}
/*****************************************************************************/
// ----------------------------------------------------------------------------
// Solve the quadratic equation: a*x^2 + b*x + c = 0.
// The function returns the number of distinct solutions.
// The roots area must be at least of size 2.
//
template <class NT>
int solve_quadratic_eq (const NT& a, const NT& b, const NT& c,
NT* roots)
{
static const NT _zero = 0;
static const NT _two = 2;
static const NT _four = 4;
if (a == _zero)
{
if (b != _zero)
{
roots[0] = -c/b;
return (1);
}
else
return (0);
}
const NT disc = b*b - _four*a*c;
if (disc < _zero)
{
return (0);
}
else if (disc == _zero)
{
roots[0] = roots[1] = -b/(_two*a);
return (1);
}
else
{
const NT sqrt_disc = CGAL::sqrt(disc);
roots[0] = (sqrt_disc - b)/(_two*a);
roots[1] = -(sqrt_disc + b)/(_two*a);
return (2);
}
}
template <class NT>
int _solve_quadratic_eq (const NT& a, const NT& b, const NT& c,
NT* roots)
{
static const NT _zero = 0;
static const NT _two = 2;
static const NT _four = 4;
if (a == _zero)
{
if (b != _zero)
{
roots[0] = -c/b;
return (1);
}
else
return (0);
}
const NT disc = b*b - _four*a*c;
if (disc < _zero)
{
return (0);
}
else if (disc == _zero)
{
roots[0] = roots[1] = -b/(_two*a);
return (1);
}
else
{
const NT sqrt_disc = sqrt_d(disc, APNT_BITLEN, 2);
roots[0] = (sqrt_disc - b)/(_two*a);
roots[1] = -(sqrt_disc + b)/(_two*a);
return (2);
}
}
// ----------------------------------------------------------------------------
// Solve the cubic equation: _a*x^3 + _b*x^2 + _c*x + _d = 0.
// Notice this is an auxiliary function (used only by solve_quartic_eq()).
// The function returns the number of distinct solutions.
// The roots area must be at least of size 3.
//
template <class NT>
static int _solve_cubic_eq (const NT& _a, const NT& _b,
const NT& _c, const NT& _d,
NT* roots, int& n_approx)
{
n_approx = 0;
// In case we have an equation of a lower degree:
static const NT _zero = 0;
if (_a == _zero)
{
// We have to solve _b*x^2 + _c*x + _d = 0.
return (solve_quadratic_eq<NT> (_b, _c, _d,
roots));
}
// Normalize the equation, so that the leading coefficient is 1 and we have:
// x^3 + b*x^2 + c*x + d = 0
//
const NT b = _b/_a;
const NT c = _c/_a;
const NT d = _d/_a;
// Check whether the equation has multiple roots.
// If we write:
// p(x) = x^3 + b*x^2 + c*x + d = 0
//
// Then:
// p'(x) = 3*x^2 + 2*b*x + c
//
// We know that there are multiple roots iff GCD(p(x), p'(x)) != 0.
// In order to check the GCD, let us denote:
// p(x) mod p'(x) = A*x + B
//
// Then:
static const NT _two = 2;
static const NT _three = 3;
static const NT _nine = 9;
const NT A = _two*(c - b*b/_three)/_three;
const NT B = d - b*c/_nine;
if (A == _zero)
{
// In case A,B == 0, then p'(x) divides p(x).
// This means the equation has one solution with multiplicity of 3.
// We can obtainf this root using the fact that -b is the sum of p(x)'s
// roots.
if (B == _zero)
{
roots[0] = -b / _three;
return (1);
}
}
else
{
// Check whether A*x + B divides p'(x).
const NT x0 = -B/A;
if (c + x0*(_two*b + _three*x0) == _zero)
{
// Since GCD(p(x), p'(x)) = (x - x0), then x0 is a root of p(x) with
// multiplicity 2. The other root is obtained from b.
roots[0] = x0;
roots[1] = -(b + 2*x0);
return (2);
}
}
// If we reached here, we can be sure that there are no multiple roots.
// We continue by trying to find a quadratic factor (x^2 - r*x - q) that
// divides p(x).
const APNT b_app = TO_APNT(b);
const APNT c_app = TO_APNT(c);
const APNT d_app = TO_APNT(d);
APNT q = 1;
APNT r = 2;
APNT A0, B0;
APNT A1, B1;
APNT mat[2][2];
APNT det;
APNT r_tag, q_tag;
bool another_iter = true;
int iter = 0;
while (another_iter && iter < APNT_BITLEN)
{
iter++;
// Let us denote:
// p(x) = p1(x) * (x^2 - r*x - q) + (A0*x + B0)
// p1(x) = 0 * (x^2 - r*x - q) + (A1*x + B1)
//
// Where:
// p1(x) = x + psi
//
// Then we can obtain:
A0 = c_app + q + r*(b_app + r);
B0 = d_app + q*(b_app + r);
A1 = 1;
B1 = b_app + r;
// Now exchange r,q with the updated approximations r',q' given by:
//
// +- -+ +- -+ +- -+ -1 +- -+
// | r' | = | r | - | A1*r+B1 A1 | | A0 |
// | q' | | q | | A1*q B1 | | B0 |
// +- -+ +- -+ +- -+ +- -+
//
mat[0][0] = A1*r + B1;
mat[0][1] = A1;
mat[1][0] = A1*q;
mat[1][1] = B1;
det = mat[0][0]*mat[1][1] - mat[1][0]*mat[0][1];
if (APNT_ZERO(det))
// if (APNT_ABS(det) < APNT_EPS)
break;
r_tag = r - (mat[1][1]*A0 - mat[0][1]*B0) / det;
q_tag = q - (-mat[1][0]*A0 + mat[0][0]*B0) / det;
if (eps_compare<APNT> (r, r_tag) == EQUAL &&
eps_compare<APNT> (q, q_tag) == EQUAL)
{
another_iter = false;
}
r = r_tag;
q = q_tag;
}
// Now we have the approximation:
// p(x) = (x^2 + psi) * (x^2 - r*x - q)
//
// Try to solve the two quadratic factor:
APNT app_roots[2];
n_approx = _solve_quadratic_eq<APNT> (APNT(1), -r, -q,
app_roots + n_approx);
// Copy the approximations.
for (int i = 0; i < n_approx; i++)
roots[i] = NT(app_roots[i]);
// Add the extra root.
roots[n_approx] = -(b_app + r);
n_approx++;
return (n_approx);
}
/*
template <class APNT>
APNT refine_solution (const APNT& a, const APNT& b, const APNT& c,
const APNT& d, const APNT& e,
const APNT& _x)
{
APNT x = _x;
APNT val, deriv;
for (int i = 0; i < 10; i++)
{
val = (((a*x + b)*x + c)*x + d)*x + e;
if (APNT_ZERO(val))
return (x);
deriv = ((4*a*x + 3*b)*x + 2*c)*x + d;
x -= val/deriv;
}
return (x);
}
*/
// ----------------------------------------------------------------------------
// Solve a quartic equation: _a*x^4 + _b*x^3 + _c*x^2 + _d*x + _e = 0.
// The function returns the number of distinct solutions.
// The roots area must be at least of size 4.
//
template <class NT>
int solve_quartic_eq (const NT& _a, const NT& _b, const NT& _c,
const NT& _d, const NT& _e,
NT* roots, int& n_approx)
{
// Right now we have no approximate solutions.
n_approx = 0;
// First check whether we have roots that are 0.
static const NT _zero = 0;
if (_e == _zero)
{
if (_d == _zero)
{
if (_c == _zero)
{
if (_b == _zero)
{
// Unless the equation is trivial, we have the root 0,
// with multiplicity of 4.
if (_a == _zero)
return (0);
roots[0] = _zero;
return (1);
}
else
{
// Add the solution 0 (with multiplicity 3), and add the solution
// to _a*x + _b = 0.
if (_a == _zero)
return (0);
roots[0] = _zero;
roots[1] = -(_b/_a);
return (2);
}
}
else
{
// Add the solution 0 (with multiplicity 2),
// and solve _a*x^2 + _b*x + _c*x = 0.
roots[0] = _zero;
return (1 + solve_quadratic_eq<NT> (_a, _b, _c,
roots + 1));
}
}
else
{
// Add the solution 0, and solve _a*x^3 + _b*x^2 + _c*x + _d = 0.
roots[0] = _zero;
return (1 + _solve_cubic_eq<NT> (_a, _b, _c, _d,
roots + 1, n_approx));
}
}
// In case we have an equation of a lower degree:
if (_a == _zero)
{
if (_b == _zero)
{
// We have to solve _c*x^2 + _d*x + _e = 0.
return (solve_quadratic_eq<NT> (_c, _d, _e,
roots));
}
else
{
// We have to solve _b*x^3 + _c*x^2 + _d*x + _e = 0.
return (_solve_cubic_eq<NT> (_b, _c, _d, _e,
roots, n_approx));
}
}
// In case we have an equation of the form:
// _a*x^4 + _c*x^2 + _e = 0
//
// Then by substituting y = x^2, we obtain a quadratic equation:
// _a*y^2 + _c*y + _e = 0
//
if (_b == _zero && _d == _zero)
{
// Solve the equation for y = x^2.
NT sq_roots[2];
int n_sq;
int n = 0;
n_sq = solve_quadratic_eq<NT> (_a, _c, _e,
sq_roots);
// Convert to roots of the original equation: only positive roots for y
// are relevant of course.
for (int j = 0; j < n_sq; j++)
{
if (sq_roots[j] > _zero)
{
roots[n] = CGAL::sqrt(sq_roots[j]);
roots[n+1] = -roots[n];
n += 2;
}
}
return (n);
}
// Normalize the equation, so that the leading coefficient is 1 and we have:
// x^4 + b*x^3 + c*x^2 + d*x + e = 0
//
const NT b = _b/_a;
const NT c = _c/_a;
const NT d = _d/_a;
const NT e = _e/_a;
// Check whether the equation has multiple roots.
// If we write:
// p(x) = x^4 + b*x^3 + c*x^2 + d*x + e = 0
//
// Then:
// p'(x) = 4*x^3 + 3*b*x^2 + 2*c*x + d
//
// We know that there are multiple roots iff GCD(p(x), p'(x)) != 0.
// In order to check the GCD, let us denote:
// p(x) mod p'(x) = alpha*x^2 + beta*x + gamma
//
// Then:
static const NT _two = 2;
static const NT _three = 3;
static const NT _four = 4;
static const NT _eight = 8;
static const NT _sixteen = 16;
const NT alpha = c/_two - _three*b*b/_sixteen;
const NT beta = _three*d/_four - b*c/_eight;
const NT gamma = e - b*d/_sixteen;
if (alpha == _zero)
{
if (beta == _zero)
{
if (gamma == _zero)
{
// p'(x) divides p(x). This can happen only if there is a single
// root with multiplicity 4.
// Since b = -(sum of p(x)'s roots) then this root is -b/4.
roots[0] = -b/_four;
return (1);
}
}
else
{
// In case alpha is 0, check whether (beta*x + gamma) divides p'(x) -
// this happens iff -gamma/beta is a root of p'(x).
if (beta == _zero)
return (0);
const NT x0 = -gamma/beta;
if (d + x0*(_two*c + x0*(_three*b + x0*_four)) == _zero)
{
// We have two ditinct solutions: x0 with multiplicity of 3, and
// p'(x)/(x - x0)^2 with multiplicity of 1.
// Since b = -(sum of p(x)'s roots), the other root is -(b + 3*x0).
roots[0] = x0;
roots[1] = -(b + 3*x0);
return (2);
}
}
}
else
{
// If alpha is not 0, let us denote:
// p'(x) mod (alpha*x^2 + beta*x + gamma) = A*x + B
//
// And so:
const NT A = _two*c - (_four*gamma + _three*b*beta)/alpha +
_four*beta*beta/(alpha*alpha);
const NT B = d - _three*b*gamma/alpha + _four*beta*gamma/(alpha*alpha);
// In case A,B == 0, then GCD(p(x), p'(x)) = (alpha*x^2 + beta*x + gamma).
// This means the equation has two distinct solution, each one of them
// has a multiplicity of 2.
if (A == _zero)
{
if (B == _zero)
{
// There are two cases:
// - If (alpha*x^2 + beta*x + gamma) has two distinct roots, that
// these roots are roots of p(x), each with multiplicity 2.
// - If there is one root x0, than this root is a root of p(x) with
// multiplicity 3. The other root can be obtained using the fact
// that b = -(sum of p(x)'s roots).
int m = solve_quadratic_eq<NT> (alpha, beta, gamma,
roots);
if (m == 1)
{
// Add the second root.
roots[1] = -(b + 3*roots[0]);
m++;
}
return (m);
}
}
else
{
// Check whether (A*x + B) divides (alpha*x^2 + beta*x + gamma).
// This happend iff -B/A is a root of (alpha*x^2 + beta*x + gamma).
const NT x0 = -B / A;
if (gamma + x0*(beta + x0*alpha) == _zero)
{
// We have one solution with multiplicity of 2.
roots[0] = x0;
// The other two solutions are obtained from solving:
// p(x) / (x - x0)^2 = x^2 + (b + 2*x0)*x + (c + 2*b*x0 + 3*x0^2)
return (1 +
solve_quadratic_eq<NT> (NT(1), b + 2*x0, c + x0*(2*b + 3*x0),
roots + 1));
}
}
}
// If we reached here, we can be sure that there are no multiple roots.
// We continue by trying to find a quadratic factor (x^2 - r*x - q) that
// divides p(x).
const APNT b_app = TO_APNT(b);
const APNT c_app = TO_APNT(c);
const APNT d_app = TO_APNT(d);
const APNT e_app = TO_APNT(e);
APNT q = 1;
APNT r = 2;
APNT phi, psi;
APNT A0, B0;
APNT A1, B1;
APNT mat[2][2];
APNT det;
APNT r_tag, q_tag;
bool another_iter = true;
int iter = 0;
double droots[4];
int n_droots = _Ferrari_quartic_eq<double> (1,
CGAL::to_double(b),
CGAL::to_double(c),
CGAL::to_double(d),
CGAL::to_double(e),
droots);
if (n_droots == 0)
return (0);
r = APNT(droots[0] + droots[1]);
q = -APNT(droots[0] * droots[1]);
while (another_iter && iter < APNT_BITLEN)
{
iter++;
// Let us denote:
// p(x) = p1(x) * (x^2 - r*x - q) + (A0*x + B0)
// p1(x) = p2(x) * (x^2 - r*x - q) + (A1*x + B1)
//
// Where:
// p1(x) = x^2 + phi*x + psi
//
// Then we can obtain:
A0 = d_app + b_app*q + r*(2*q + c_app + r*(b_app + r));
B0 = e_app + q*(c_app + r*(b_app + r) + q);
A1 = b_app + 2*r;
B1 = c_app + 2*q + r*(b_app + r);
// Now exchange r,q with the updated approximations r',q' given by:
//
// +- -+ +- -+ +- -+ -1 +- -+
// | r' | = | r | - | A1*r+B1 A1 | | A0 |
// | q' | | q | | A1*q B1 | | B0 |
// +- -+ +- -+ +- -+ +- -+
//
mat[0][0] = A1*r + B1;
mat[0][1] = A1;
mat[1][0] = A1*q;
mat[1][1] = B1;
det = mat[0][0]*mat[1][1] - mat[1][0]*mat[0][1];
if (APNT_ZERO(det))
//if (APNT_ABS(det) < APNT_EPS)
break;
r_tag = r - (mat[1][1]*A0 - mat[0][1]*B0) / det;
q_tag = q - (-mat[1][0]*A0 + mat[0][0]*B0) / det;
if (eps_compare<APNT> (r, r_tag) == EQUAL &&
eps_compare<APNT> (q, q_tag) == EQUAL)
{
another_iter = false;
}
r = r_tag;
q = q_tag;
}
// Now we have the approximation:
// p(x) = (x^2 + phi*x^2 + psi) * (x^2 - r*x - q)
//
// Try to solve the two quadratic factors:
APNT app_roots[4];
phi = b_app + r;
psi = c_app + q + r*(b_app + r);
n_approx = _solve_quadratic_eq<APNT> (APNT(1), phi, psi,
app_roots);
n_approx += _solve_quadratic_eq<APNT> (APNT(1), -r, -q,
app_roots + n_approx);
// Copy the approximations.
for (int i = 0; i < n_approx; i++)
roots[i] = NT(app_roots[i]);
//roots[i] = NT(refine_solution(TO_APNT(_a), TO_APNT(_b), TO_APNT(_c),
// TO_APNT(_d), TO_APNT(_e),
// app_roots[i]));
return (n_approx);
}
CGAL_END_NAMESPACE
#endif