// Copyright (c) 2000,2001 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Kernel_23/include/CGAL/Kernel/Conic_misc.h $ // $Id: Conic_misc.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Bernd Gaertner, Sven Schoenherr #ifndef CGAL_CONIC_MISC_H #define CGAL_CONIC_MISC_H #include #include #include #include namespace CGAL { template < class R> class Conic_2; enum Conic_type { HYPERBOLA = -1, PARABOLA, ELLIPSE }; typedef CGAL::Bounded_side Convex_side; const Convex_side ON_CONVEX_SIDE = CGAL::ON_BOUNDED_SIDE; const Convex_side ON_NONCONVEX_SIDE = CGAL::ON_UNBOUNDED_SIDE; template < class NT > NT best_value (NT *values, int nr_values, NT a2, NT a1, NT a0, NT b3, NT b2, NT b1, NT b0) { bool det_positive = false; NT d, q, max_det = 0, det, best = -1; for (int i=0; i max_det)) { max_det = det; best = x; det_positive = true; } } CGAL_kernel_precondition (det_positive); return best; } template < class NT > int solve_cubic (NT c3, NT c2, NT c1, NT c0, NT& r1, NT& r2, NT& r3) { if (c3 == 0.0) { // quadratic equation if (c2 == 0) { // linear equation CGAL_kernel_precondition (c1 != 0); r1 = -c0/c1; return 1; } NT D = c1*c1-4*c2*c0; if (D < 0.0) // only complex roots return 0; if (D == 0.0) { // one real root r1 = -c1/(2.0*c2); return 1; } // two real roots r1 = (-c1 + CGAL_NTS sqrt(D))/(2.0*c2); r2 = (-c1 - CGAL_NTS sqrt(D))/(2.0*c2); return 2; } // cubic equation // define the gamma_i NT g2 = c2/c3, g1 = c1/c3, g0 = c0/c3; // define a, b NT a = g1 - g2*g2/3.0, b = 2.0*g2*g2*g2/27.0 - g1*g2/3.0 + g0; if (a == 0) { // one real root r1 = boost::math::cbrt(-b) - g2 / 3.0; // r1 = std::exp(std::log(-b) / 3.0) - g2 / 3.0; return 1; } // define D NT D = a*a*a/27.0 + b*b/4.0; if (D >= 0.0) { // real case NT u = boost::math::cbrt(-b / 2.0 + CGAL_NTS sqrt(D)), // NT u = std::exp(std::log(-b/2.0 + CGAL_NTS sqrt(D)) / 3.0), alpha = 1.0 - a/(3.0*u*u); if (D == 0) { // two distinct real roots r1 = u*alpha - g2/3.0; r2 = -0.5*alpha*u - g2/3.0; return 2; } // one real root r1 = u*alpha - g2/3.0; return 1; } // complex case NT r_prime = CGAL_NTS sqrt(-a/3), phi_prime = acos (-b/(2.0*r_prime*r_prime*r_prime))/3.0, u_R = r_prime * cos (phi_prime), u_I = r_prime * sin (phi_prime); // three distinct real roots r1 = 2.0*u_R - g2/3.0; r2 = -u_R + u_I*std::sqrt(3.0) - g2/3.0; r3 = -u_R - u_I*std::sqrt(3.0) - g2/3.0; return 3; } } //namespace CGAL #endif // CGAL_CONIC_MISC_H // ===== EOF ==================================================================