diff --git a/.gitattributes b/.gitattributes index 57cdded8413..c58c565f153 100644 --- a/.gitattributes +++ b/.gitattributes @@ -87,10 +87,10 @@ Algebraic_foundations/include/CGAL/ipower.h -text Algebraic_foundations/package_info/Algebraic_foundations/maintainer -text Algebraic_foundations/test/Algebraic_foundations/ipower.cpp -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/Algebraic_kernel_d.png -text -Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/akrs1.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/examples.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/history.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/intro.tex -text +Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/models.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_ApproximateAbsolute_1.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_ApproximateRelative_1.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_BoundBetween_1.tex -text @@ -106,8 +106,10 @@ Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_ConstructA Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_IsZeroAt_2.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Isolate_2.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_NumberOfSolutions_2.tex -text -Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpq_1.tex -text -Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpz_1.tex -text +Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_d_1.tex -text +Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_d_2.tex -text +Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpq_d_1.tex -text +Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpz_d_1.tex -text Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/intro.tex -text Algebraic_kernel_d/dont_submit -text Algebraic_kernel_d/examples/Algebraic_kernel_d/CMakeLists.txt -text @@ -116,6 +118,43 @@ Algebraic_kernel_d/examples/Algebraic_kernel_d/Construct_algebraic_real_1.cpp -t Algebraic_kernel_d/examples/Algebraic_kernel_d/Isolate_1.cpp -text Algebraic_kernel_d/examples/Algebraic_kernel_d/Sign_at_1.cpp -text Algebraic_kernel_d/examples/Algebraic_kernel_d/Solve_1.cpp -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_quadratic_refinement_rep_bfi.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep_bfi.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel_at_alpha.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_E08_tree.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree_traits.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_analysis_2.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Descartes.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Event_line_builder.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Float_traits.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/LRU_hashed_map.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_embeddable_extension.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_roots.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_controller.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_transformation.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CA_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CPA_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Xy_coordinate_2.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/bound_between_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/construct_binary.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/enums.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/exceptions.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/flags.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/macros.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/refine_zero_against.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/univariate_polynomial_utils.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_1.h -text +Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_2.h -text Algebraic_kernel_d/include/CGAL/RS/algebraic_1_comparisons.h -text Algebraic_kernel_d/include/CGAL/RS/algebraic_1_constructors.h -text Algebraic_kernel_d/include/CGAL/RS/algebraic_1_member.h -text @@ -149,11 +188,27 @@ Algebraic_kernel_d/include/CGAL/RS/sign_1_rs.h -text Algebraic_kernel_d/include/CGAL/RS/ugcd.h -text Algebraic_kernel_d/package_info/Algebraic_kernel_RS/description.txt -text Algebraic_kernel_d/package_info/Algebraic_kernel_RS/maintainer -text -Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_1.cpp -text -Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_1.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_curve_kernel_2.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_CORE.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_GMP.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_LEDA.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_2.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_d_1.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_d_1.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_real_d_1.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Bitstream_descartes.cpp -text Algebraic_kernel_d/test/Algebraic_kernel_d/CMakeLists.txt -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_analysis_2.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_pair_analysis_2.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Descartes.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/Real_embeddable_traits_extension.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_curve_kernel_2.h -text Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h -text -Algebraic_kernel_d/test/Algebraic_kernel_d/io_test.cpp -text +Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_2.h -text +Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_bitstream_descartes.h -text +Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_comparable.h -text +Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_root_isolator.h -text Alpha_shapes_2/demo/Alpha_shapes_2/data/m30f.jpg -text svneol=unset#image/jpeg Alpha_shapes_2/demo/Alpha_shapes_2/help/index.html svneol=native#text/html Alpha_shapes_2/doc_tex/Alpha_shapes_2/alpha-detail.png -text diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/akrs1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/akrs1.tex deleted file mode 100644 index 58dfe03d3b5..00000000000 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/akrs1.tex +++ /dev/null @@ -1,39 +0,0 @@ -% TODO: remove references to Gmpfr and Gmpfi, since they will be part of CGAL. - -\subsection{Models} - -\subsubsection{Algebraic kernels based on \rs} - -The package offers two univariate algebraic kernels that are based on the -library \rs{} \cite{cgal:r-rs}, namely -\ccc{CGAL::Algebraic_kernel_rs_gmpz_1} and -\ccc{CGAL::Algebraic_kernel_rs_gmpq_1}. As the names indicate, the kernels -are based on the library \rs{} \cite{cgal:r-rs} and support univariate -polynomials over \ccc{CGAL::Gmpz} or \ccc{CGAL::Gmpq}, respectively. - -In general we encourage to use \ccc{CGAL::Algebraic_kernel_rs_gmpz_1} -instead of \ccc{CGAL::Algebraic_kernel_rs_gmpq_1}. This is caused by the -fact that the most efficient way to compute operations (such as gcd) on -polynomials with rational coefficients is to use the corresponding -implementation for polynomials with integer coefficients. That is, the -\ccc{CGAL::Algebraic_kernel_rs_gmpq_1} is slightly slower due to overhead -caused by the necessary conversions. However, since this may not always be -a major issue the \ccc{CGAL::Algebraic_kernel_rs_gmpq_1} is provided for -convenience. - -The core of both kernels is the implementation of the interval Descartes -algorithm~\cite{cgal:rz-jcam-04} of the library \rs~\cite{cgal:r-rs}, which -is used to isolate the roots of the polynomial. The \rs~library restricts -its attention to univariate integer polynomials and some substantial gain -of efficiency can be made by using a kernel that does not follow the -generic programming paradigm, by avoiding interfaces between layers. -Specifically, the fact of working with only a number type allows to -optimize some polynomial operations as well as memory handling. The -implementation of these kernels make heavy use of the \mpfr~ -\cite{cgal:mt-mpfr} and \mpfi~\cite{cgal:r-mpfi} libraries, and of their -CGAL interfaces, \ccc{Gmpfr} and \ccc{Gmpfi}. The algebraic numbers (roots -of the polynomials) are represented in the two \rs~kernels by a \ccc{Gmpfi} -interval and a pointer to the polynomial of which they are roots. See -\cite{cgal:lpt-wea-09} for more details on the implementation, tests of -these kernels, comparisons with other algebraic kernels and discussions -about the efficiency. diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/examples.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/examples.tex index d9e3995ff90..f231db768f7 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/examples.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/examples.tex @@ -1,5 +1,5 @@ \clearpage -\subsection{Examples} +\section{Examples} \subsubsection{Construction of Algebraic Real Numbers } The following example illustrates the construction of \ccc{AlgebraicKernel_d_1::Algebraic_real_1} using \ccc{AlgebraicKernel_d_1::Construct_algebraic_real_1}: diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/history.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/history.tex index 15dd75b4e7c..60745ced559 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/history.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/history.tex @@ -1,33 +1,38 @@ + + \section{Design and Implementation History} -This package is clearly split into a univariate and bivariate kernel. -However, with respect to its history the package splits into a -design part and an implementation part. The concepts, which make -up the design part, where written by Eric Berberich, Michael Hemmer, -and Monique Teillaud. The implementation part is currently comprised -of two univariate kernels that interface the library \rs~\cite{cgal:r-rs}. -These models were written by Luis Pe\~{n}aranda and Sylvain Lazard. +This package is clearly split into a univariate and bivariate +kernel. However, with respect to its history the package splits into +a design part and an implementation part. -The design history of the package is fairly old and several ideas -that influenced this package can already be found +The concepts, which make up the design part, +where written by Eric Berberich, Michael Hemmer, and +Monique Teillaud. +The design history of the package is fairly old and several +ideas that influenced this package can already be found in~\cite{cgal:bhkt-risak-07}. Since then, the initial design underwent considerable changes. For instance, it was decided that the algebraic -numbers should be under the control of the algebraic kernel. On the -other hand the initial support for polynomials was extended to a -separate and independent package that is not restricted to a certain -number of variables. Thus, the authors want to thank for all the -useful feedback and ideas that was brought to them throughout the -last years. In particular, they want to thank Menelaos Karavelas -and Elias Tsigaridas for their initial contributions. +numbers should be under the control of the algebraic kernel. On the other +hand the initial support for polynomials was extended to a separate +and independent package that is not restricted to a certain number of +variables. Thus, the authors want to thank for all the useful feedback and +ideas that was brought to them throughout the last years. In particular, +they want to thank Menelaos Karavelas and Elias Tsigaridas for their +initial contributions. -%ACS-TR-123101-01 and -%Interface specification of algebraic kernel -%Eric Berberich, Michael Hemmer, Menelaos Karavelas, Sylvain Pion, Monique Teillaud, Elias Tsigaridas +The two generic models %, \ccc{CGAL::Algebraic_kernel_d_1} and \ccc{CGAL::Algebraic_kernel_d_2}, +where initially developed as part of the \exacus~\cite{beh+-eeeafcs-05} project. +However, the models are now fully integrated into the \cgal~library, +since also the relevant layers of \exacus\ are now part of \cgal. +The main authors for \ccc{CGAL::Algebraic_kernel_d_1} and \ccc{CGAL::Algebraic_kernel_d_2} are +Michael Hemmer and Michael Kerber, respectively. Notwithstanding, the authors also want to emphasize the +contribution of all authors of the \exacus\ project, +particularly the contribution of Arno Eigenwillig, Sebastian Limbach and Pavel Emeliyanenko. + +The two univariate kernels that interface the library \rs~\cite{cgal:r-rs} were +written by Luis Pe\~{n}aranda and Sylvain Lazard. +Both models interface the library \rs~\cite{cgal:r-rs} by Fabrice Rouillier. +The authors want to thank Fabrice Rouillier and Elias Tsigaridas for +strong support and many useful discussions that lead to the integration of \rs. -The implementation history shall be considered as unclosed, since -there are some more models in the pipeline. So far, the package -provides two models of a univariate algebraic kernel. Both models -interface the library \rs~\cite{cgal:r-rs} by Fabrice Rouillier. -The authors want to thank Fabrice Rouillier and Elias Tsigaridas -for strong support and many useful discussions that lead to the -integration of \rs. diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/intro.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/intro.tex index 6db382354bd..fac84a25a1e 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/intro.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/intro.tex @@ -1,18 +1,17 @@ -%\section{General Layout of an Algebraic Kernel} -\section{Introduction} Real solving of polynomials is a fundamental problem with a wide application range. -This package is targeted to provide black-box implementations of state-of-the-art -algorithms to determine, compare and approximate real roots of univariate polynomials +This package is targeted at providing black-box implementations of state-of-the-art +algorithms to determine, compare, and approximate real roots of univariate polynomials and bivariate polynomial systems. Such a black-box is called an {\bf Algebraic Kernel}. -Since this package is aimed at providing more than one implementation, the interface of the algebraic kernels -is expressed in concepts. The main concepts provided by this package are the -\ccc{AlgebraicKernel_d_1} for univariate polynomials and \ccc{AlgebraicKernel_d_2} -for bivariate polynomials systems, the latter being a refinement of the first. +Since this package is aimed at providing more than one implementation, the interface of +the algebraic kernels is expressed in concepts. The main concepts provided by this package are the +\ccc{AlgebraicKernel_d_1} for univariate polynomial systems and \ccc{AlgebraicKernel_d_2} +for bivariate polynomial systems, the latter being a refinement of the first. -So far the package only provides models for the univariate kernel. Nevertheless, -we also provide the concepts for the bivariate kernel, since this settles the interface -for upcoming implementations. + +%So far the package only provides models for the univariate kernel. Nevertheless, +%we also provide the concepts for the bivariate kernel, since this settles the interface +%for upcoming implementations. %The package introduces a concept for a univariate %\ccc{AlgebraicKernel_d_1} and a concept for bivariate \ccc{AlgebraicKernel_d_2}. @@ -24,23 +23,25 @@ for upcoming implementations. %the resulting intersection points. The computation of the sign of a %polynomial at given point is also provide. -\section{Univariate Algebraic Kernel} + +\section{Algebraic Kernel Concepts} +\subsection{Univariate Algebraic Kernel} %\subsection{Layout} \subsubsection{Major types} First of all, the univariate algebraic kernel provides construction, comparison and approximation of real roots of univariate polynomials. Thus, the major public types the \ccc{AlgebraicKernel_d_1} provides are: \\ -\ccc{AlgebraicKernel_d_1::Polynomial_1} - the type representing univariate polynomials;\\ -\ccc{AlgebraicKernel_d_1::Coefficient} - the coefficient type of these polynomials; \\ -\ccc{AlgebraicKernel_d_1::Algebraic_real_1} - the type representing real roots;\\ -\ccc{AlgebraicKernel_d_1::Bound} - the type which is used to approximate these algebraic reals, +\ccc{AlgebraicKernel_d_1::Polynomial_1} -- the type representing univariate polynomials,\\ +\ccc{AlgebraicKernel_d_1::Coefficient} -- the coefficient type of these polynomials, \\ +\ccc{AlgebraicKernel_d_1::Algebraic_real_1} -- the type representing real roots,\\ +\ccc{AlgebraicKernel_d_1::Bound} -- the type which is used to approximate these algebraic reals, in particular, it is used to represent the boundaries of isolating intervals. \\ \subsubsection{Construction of Algebraic Real Numbers } The kernel provides two different function objects to construct an \ccc{AlgebraicKernel_d_1::Algebraic_real_1}. The most general way -is to use \ccc{AlgebraicKernel_d_1::Isolate_1}; the function object +is to use \ccc{AlgebraicKernel_d_1::Isolate_1}; The function object takes a univariate polynomial and writes all real roots into a given output iterator. It is also possible to retrieve the multiplicity of each root. The second option is to construct one particular algebraic @@ -61,16 +62,16 @@ An \ccc{AlgebraicKernel_d_1::Algebraic_real_1} is model of \ccc{RealEmbeddable}, for instance, it is possible to compare two algebraic reals, to determine the sign of an algebraic real or to ask for its double approximation, see also section \ref{sec:RealEmbeddable}. -Moreover, there is \ccc{AlgebraicKernel_d_1::Compare_1} which provides +Moreover, \ccc{AlgebraicKernel_d_1::Compare_1} provides comparison with int, the coefficient type and the bound type. There are several ways to approximate an \ccc{AlgebraicKernel_d_1::Algebraic_real_1}:\\ -\ccc{AlgebraicKernel_d_1::Approximate_absolute_1} - provides an approximation that is -better than the passed absolute error bound. \\ -\ccc{AlgebraicKernel_d_1::Approximate_relative_1} - provides an approximation that is -better than the passed relative error bound. \\ -\ccc{AlgebraicKernel_d_1::Isolate_1} - returns an isolating interval with respect to -a given univariate polynomial. \\ +\ccc{AlgebraicKernel_d_1::Approximate_absolute_1} -- provides an approximation that is +better than the passed absolute error bound,\\ +\ccc{AlgebraicKernel_d_1::Approximate_relative_1} -- provides an approximation that is +better than the passed relative error bound,\\ +\ccc{AlgebraicKernel_d_1::Isolate_1} -- returns an isolating interval with respect to +a given univariate polynomial,\\ A related function object is \ccc{AlgebraicKernel_d_1::Bound_between_1}, which computes a number that isolates two algebraic real numbers. @@ -79,14 +80,14 @@ a number that isolates two algebraic real numbers. \subsubsection{Interplay with Polynomials} It is also possible to retrieve a representing polynomial from an -algebraic real using \ccc{AlgebraicKernel_d_1::Compute_polynomial_1}, that -is, it is guaranteed that the algebraic real is a root of the returned +algebraic real using \ccc{AlgebraicKernel_d_1::Compute_polynomial_1}, +which guarantees that the algebraic real is a root of the returned polynomial. As the name already indicates, this operation may be very costly since the polynomial may not be computed yet. Moreover, it is not guaranteed that the returned polynomial is the minimal polynomial of the number. Together with \ccc{AlgebraicKernel_d_1::Isolate_1}, it is possible to retrieve the traditional representation of an algebraic -real, that is, as a square free polynomial and an isolating interval. +real as a square free polynomial and an isolating interval. Though the \ccc{AlgebraicKernel_d_1} does not provide arithmetic operations on \ccc{AlgebraicKernel_d_1::Algebraic_real_1}, it is @@ -94,7 +95,7 @@ possible to compute the sign of a polynomial at a given algebraic real using \ccc{AlgebraicKernel_d_1::Sign_at_1}. Or alternatively, just compute whether the polynomial is zero at an algebraic real number using \ccc{AlgebraicKernel_d_1::Is_zero_at_1}. Note that this operation -can be significantly less expensive, in particular, if the polynomial +can be significantly less expensive, in particular if the polynomial is not zero at the given algebraic real. %An example can be found in Section~\ref{CGAL::AK1::EG::Sign_at_1}. @@ -107,16 +108,11 @@ in the Polynomial package (see chapter \ref{ChapterPolynomial}). This implies that all essential functionality is provided via \ccc{CGAL::Polynomial_traits_d}. However, the algebraic kernel also provides several function objects to handle polynomials:\\ -\ccc{AlgebraicKernel_d_1::Is_square_free_1} -- determines whether a polynomial is square free \\ -\ccc{AlgebraicKernel_d_1::Make_square_free_1} -- computes the square free part of a polynomial \\ -\ccc{AlgebraicKernel_d_1::Square_free_factorize_1} -- computes a square free factorization of a polynomial \\ -\ccc{AlgebraicKernel_d_1::Is_coprime_1} -- Computes whether a pair of polynomials is square free\\ -\ccc{AlgebraicKernel_d_1::Make_coprime_1} -- decompose two polynomials into the coprime factors and their common factor. +\ccc{AlgebraicKernel_d_1::Is_square_free_1} -- determines whether a polynomial is square free,\\ +\ccc{AlgebraicKernel_d_1::Make_square_free_1} -- computes the square free part of a polynomial,\\ +\ccc{AlgebraicKernel_d_1::Square_free_factorize_1} -- computes a square free factorization of a polynomial,\\ +\ccc{AlgebraicKernel_d_1::Is_coprime_1} -- computes whether a pair of polynomials is square free,\\ +\ccc{AlgebraicKernel_d_1::Make_coprime_1} -- decomposes two polynomials into the coprime factors and their common factor. Though the polynomial package provides similar functionality we suggest to use the function objects provided by the kernel, since the design of the algebraic kernel @@ -127,14 +123,13 @@ allows for instance internal caching by the kernel. %\begin{ccAdvanced} Also note that \ccc{AlgebraicKernel_d_1::Square_free_factorize_1} only computes the square free factorization up to a constant factor. This is a slight modification with respect to its -counter part in \ccc{CGAL::Polynomial_traits_d}. In this way it was possible that the concepts just require +counterpart in \ccc{CGAL::Polynomial_traits_d}. In this way it was possible that the concepts just require the coefficient type to be a model of \ccc{IntegralDomain}, instead of \ccc{Field} or \ccc{UniqueFactorizationDomain}. For more details see also:\\ \ccRefIdfierPage{PolynomialTraits_d::SquareFreeFactorize} \\ \ccRefIdfierPage{PolynomialTraits_d::SquareFreeFactorizeUpToConstantFactor}\\ %\end{ccAdvanced} - \subsubsection{Design Rationale} Most implementations of an \ccc{AlgebraicKernel_d_1} will represent @@ -160,3 +155,58 @@ there is no way to directly ask for the refinement of the current isolating interval since this would impose a state to every object of an \ccc{AlgebraicKernel_d_1::Algebraic_real_1}. + +\subsection{Bivariate Algebraic Kernel} + +The concept \ccc{AlgebraicKernel_d_2} is a refinement of \ccc{AlgebraicKernel_d_1}, +that is, a model of \ccc{AlgebraicKernel_d_2} is also a model of \ccc{AlgebraicKernel_d_1}. +Hence, the \ccc{AlgebraicKernel_d_2} concept is designed such that occurring +names and functionalities are as similar as possible to those in the +\ccc{AlgebraicKernel_d_1} concept. +The following are a direct generalization of their univariate counterparts: + +\ccc{AlgebraicKernel_d_2::Polynomial_2},\\ +\ccc{AlgebraicKernel_d_2::Algebraic_real_2},\\ +\ccc{AlgebraicKernel_d_2::Construct_algebraic_real_2},\\ +\ccc{AlgebraicKernel_d_2::Isolate_2},\\ +\ccc{AlgebraicKernel_d_2::Is_square_free_2},\\ +\ccc{AlgebraicKernel_d_2::Make_square_free_2},\\ +\ccc{AlgebraicKernel_d_2::Square_free_factorize_2},\\ +\ccc{AlgebraicKernel_d_2::Is_coprime_2},\\ +\ccc{AlgebraicKernel_d_2::Make_coprime_2},\\ +\ccc{AlgebraicKernel_d_2::Solve_2},\\ +\ccc{AlgebraicKernel_d_2::Number_of_solutions_2},\\ +\ccc{AlgebraicKernel_d_2::Compare_xy_2},\\ +\ccc{AlgebraicKernel_d_2::Sign_at_2},\\ +\ccc{AlgebraicKernel_d_2::Is_zero_at_2}. + +For instance, \ccc{AlgebraicKernel_d_2::Solve_2} +provides the solution for a bivariate polynomial system. +However, it is also possible to obtain the coordinates of these +solutions with the additional functors: + +\ccc{AlgebraicKernel_d_2::Compute_x_2},\\ +\ccc{AlgebraicKernel_d_2::Compute_y_2}. + +In principal this would be sufficient generalization, +since functions such as isolating, approximating algebraic real numbers +could be implemented using these access functions ant +the corresponding functionalities in the univariate algebraic kernel. +However, one should be aware that an \ccc{AlgebraicKernel_d_2::Algebraic_real_2} +is not necessarily represented as a pair of univariate solutions, that is, +using \ccc{AlgebraicKernel_d_2::Compute_y_2} may entail considerable +computations. Therefore, the concept also requires the following +additional functors that may allow a model to bypass this issue: + +\ccc{AlgebraicKernel_d_2::Compute_polynomial_x_2},\\ +\ccc{AlgebraicKernel_d_2::Compute_polynomial_y_2},\\ +\ccc{AlgebraicKernel_d_2::Isolate_x_2},\\ +\ccc{AlgebraicKernel_d_2::Isolate_y_2},\\ +\ccc{AlgebraicKernel_d_2::Compare_x_2},\\ +\ccc{AlgebraicKernel_d_2::Compare_y_2},\\ +\ccc{AlgebraicKernel_d_2::Approximate_absolute_x_2},\\ +\ccc{AlgebraicKernel_d_2::Approximate_relative_x_2},\\ +\ccc{AlgebraicKernel_d_2::Approximate_absolute_y_2},\\ +\ccc{AlgebraicKernel_d_2::Approximate_relative_y_2},\\ +\ccc{AlgebraicKernel_d_2::Bound_between_x_2},\\ +\ccc{AlgebraicKernel_d_2::Bound_between_y_2}. diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/main.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/main.tex index 10b395ac296..7ef62c81d72 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/main.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/main.tex @@ -1,12 +1,11 @@ \cleardoublepage \ccUserChapter{Algebraic Kernel\label{chapter-algebraic-kernel-d}} -\ccChapterAuthor{Eric Berberich \and Michael Hemmer \and Sylvain Lazard - \and Luis Pe\~{n}aranda \and Monique Teillaud} +\ccChapterAuthor{Eric Berberich \and Michael Hemmer \and Michael Kerber \and Sylvain Lazard \and Luis Pe\~{n}aranda \and Monique Teillaud} \input{Algebraic_kernel_d/PkgDescription.tex} \minitoc \input{Algebraic_kernel_d/intro} -\input{Algebraic_kernel_d/akrs1} +\input{Algebraic_kernel_d/models} \input{Algebraic_kernel_d/examples} \input{Algebraic_kernel_d/history} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/models.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/models.tex new file mode 100644 index 00000000000..3cea3d4e7ce --- /dev/null +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d/models.tex @@ -0,0 +1,111 @@ +% TODO: remove references to Gmpfr and Gmpfi, since they will be part of CGAL. + +\section{Models} + +\subsection{Generic Algebraic Kernels} + +The package provides generic models of the univariate and bivariate algebraic +kernel, namely \ccc{CGAL::Algebraic_kernel_d_1} and \ccc{CGAL::Algebraic_kernel_d_2}, +respectively. Both kernels support a large set of number types as their +template argument, which defines the supported coefficient type. The supported +types are, for instance, \ccc{Gmpz} and \ccc{Gmpq} as well as the corresponding types +of LEDA and CORE. + +The \ccc{CGAL::Algebraic_kernel_d_1} represents an algebraic real root by a square +free polynomial and an isolating interval that uniquely defines the root. +The current method to isolate roots is the Bitstream Descartes +method~\cite{eigenwillig-phd-08}. +The used method to refine the approximation of an algebraic real root is a +slightly modified (filtered) version of the one presented in~\cite{abbott-qir-06}. +The method has quadratic convergence. + +\ccc{CGAL::Algebraic_kernel_d_2} is based on an algorithm computing a +geometric-topological analysis of a single curve~\cite{ekw-fast-07} and of a +pair of curves~\cite{ek-exact-08}. +The main idea behind both analyses is to compute the critical +x-coordinates of curves and curve pairs by projection (resultants), and compute +additional information about the critical fibers using subresultants +and Sturm-Habicht sequences~\cite{grlr-sturm-habicht-98}. +With that information, the fiber at +critical x-coordinates is computed by a variant of the Bitstream +Descartes method. +See also \cite{kerber-phd-09} for a comprehensive description of +these techniques. +Almost all functors in the class that take a \ccc{Polynomial_2} +object as argument trigger such an analysis as a main computation +step. For efficiency, these analyses (of single curves and curve +pairs) are therefore cached internally for efficiency. For instance, +computing the pairwise solutions of 10 \ccc{Polynomial_2} objects +requires 10 curve analyses and 45 curve pair analyses to be computed +internally. + +A point $p$ of type \ccc{Algebraic_real_2} is represented +by its $x$-coordinate $x_0$ (as described in the \ccc{Algebraic_kernel_d_1} +paragraph above), an algebraic curve where $p$ lies on, and an +integer $i$, denoting that $p$ is the $i$th point in the fiber at $x_0$, +counted from the bottom (ignoring a possible vertical line at $x_0$). +Note that this determines the point uniquely, but the $y$-coordinate +is not stored internally in terms of an \ccc{Algebraic_real_1} object. +Querying such a representation by calling \ccc{Compute_y_2} is a +time-consuming step, and should be avoided for efficiency reasons if possible. + + +\subsection{Algebraic Kernels Based on RS} + +The package offers two univariate algebraic kernels that are based on +the library \rs~\cite{cgal:r-rs}, namely \ccc{CGAL::Algebraic_kernel_rs_gmpz_d_1} +and \ccc{CGAL::Algebraic_kernel_rs_gmpq_d_1}. As the names indicate, +the kernels are based on the library \rs~\cite{cgal:r-rs} and support univariate +polynomials over \ccc{CGAL::Gmpz} or \ccc{CGAL::Gmpq}, respectively. + +In general we encourage to use \ccc{CGAL::Algebraic_kernel_rs_gmpz_d_1} +instead of \ccc{CGAL::Algebraic_kernel_rs_gmpq_d_1}. This is caused by +the fact that the most efficient way to compute operations (such as gcd) +on polynomials with rational coefficients is to use the corresponding +implementation for polynomials with integer coefficients. That is, +the \ccc{CGAL::Algebraic_kernel_rs_gmpq_d_1} is slightly slower due to +overhead caused by the necessary conversions. However, since this may +not always be a major issue, the \ccc{CGAL::Algebraic_kernel_rs_gmpq_d_1} +is provided for convenience. + + +The core of both kernels is the implementation of the interval Descartes +algorithm~\cite{cgal:rz-jcam-04} of the library \rs~\cite{cgal:r-rs}, +which is used to isolate the roots of the polynomial. +The \rs~library restricts its attention to univariate integer +polynomials and some substantial gain of efficiency can be made by using a kernel +that does not follow the generic programming paradigm, by avoiding +interfaces between layers. Specifically, working with +only one number type allows to optimize some polynomial operations +as well as memory handling. The implementation of these kernels +make heavy use of the \mpfr~\cite{cgal:mt-mpfr} and \mpfi~\cite{cgal:r-mpfi} +libraries, and of their CGAL interfaces, \ccc{Gmpfr} and \ccc{Gmpfi}. +The algebraic numbers (roots of the polynomials) are represented +in the two \rs~kernels by a \ccc{Gmpfi} interval and a pointer to +the polynomial of which they are roots. See \cite{cgal:lpt-wea-09} +for more details on the implementation, tests of these kernels, +comparisons with other algebraic kernels and discussions about the +efficiency. + + +%-------------------------------------------------- +% \subsubsection{Installation of the kernel} +% +% As said before, this kernel depends on several libraries. First of +% all, it requires CGAL to be compiled with GMP support. Secondly, +% this needs the libraries MPFI and RS. +% +% MPFI can be obtained from \ccc{http://gforge.inria.fr/projects/mpfi/}. +% As for RS, it can be downloaded from +% \ccc{http://www.loria.fr/equipes/vegas/rs}, you should get the +% right package for your architecture and operating system. Once both +% libraries are installed, you may want to set the environment variables +% {\tt MPFI\_INC\_DIR} and {\tt RS\_INC\_DIR} pointing to the include +% directories and {\tt MPFI\_LIB\_DIR} and {\tt RS\_LIB\_DIR} pointing to +% the library directories. +% +% In order to create the \ccc{cmake} script to compile a program using these +% kernels, you should use the example {\tt CMakeLists.txt} from the +% {\tt examples/Algebraic\_kernel\_d} directory. +%-------------------------------------------------- + diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1.tex index ed849407911..e7d9eaaff24 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1.tex @@ -74,8 +74,8 @@ For each of the function objects above, there must exist a member function that \ccMemberFunction{AlgebraicKernel_d_1::Bound_between_1 bound_between_1_object() const;}{} \ccHasModels -\ccc{Algebraic_kernel_rs_gmpz_1}\\ -\ccc{Algebraic_kernel_rs_gmpq_1} +\ccc{Algebraic_kernel_rs_gmpz_d_1}\\ +\ccc{Algebraic_kernel_rs_gmpq_d_1} \ccSeeAlso \ccRefIdfierPage{AlgebraicKernel_d_2}\\ diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Compare_1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Compare_1.tex index 899b77e7cae..4531a1b67e5 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Compare_1.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Compare_1.tex @@ -33,7 +33,7 @@ The following operators and their symmetric counterparts are required: {Compares \ccc{a} and \ccc{b}.} %\ccHasModels -\ccSeeAlso +%\ccSeeAlso diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Solve_1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Solve_1.tex index 65798d83008..9b370138a50 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Solve_1.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Solve_1.tex @@ -38,7 +38,7 @@ Each root, though it might be a multiple root, is reported only once.} OutputIterator operator()( AlgebraicKernel_d_1::Polynomial_1 p, AlgebraicKernel_d_1::Bound l, AlgebraicKernel_d_1::Bound u, OutputIterator res);} -{Computes all real solutions of $p$ in the closed interval $[u,l]$ with multiplicity, and copies them as objects of type +{Computes all real solutions of $p$ in the closed interval $[l,u]$ with multiplicity, and copies them as objects of type \ccc{std::pair} in \ccc{res}.} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Compare_2.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Compare_2.tex index bf0cf75fbfe..9147661fe9c 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Compare_2.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Compare_2.tex @@ -21,17 +21,16 @@ Compares the first coordinates of \ccc{AlgebraicKernel_d_2::Algebraic_real_2}s. The following operators and their symmetric counterparts are required: %\ccThree{result_type}{fo(first_argument_type,++}{} -\ccMethod{result_type - operator()(const first_argument_type & a, - const second_argument_type & b);} +\ccMethod{result_type operator()(const first_argument_type & a, const second_argument_type & b);} {Compares the first coordinates of $a$ and $b$.} - \ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, int x);} {Compares the first coordinate of $a$ with $x$.} \ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Bound x);} {Compares the first coordinate of $a$ with $x$.} \ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Coefficient x);} {Compares the first coordinate of $a$ with $x$.} +\ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Algebraic_real_1 x);} +{Compares the first coordinate of $a$ with $x$.} \ccSeeAlso @@ -62,16 +61,14 @@ The following operators and their symmetric counterparts are required: %\ccThree{result_type}{fo(first_argument_type,++}{} \ccMethod{result_type operator()(const first_argument_type & a, const second_argument_type & b);} -{Compares the second coordinates of $a$ an $b$.} +{Compares the second coordinates of $a$ and $b$.} \ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, int y);} {Compares the second coordinate of $a$ with $y$.} -\ccMethod{result_type operator()( - AlgebraicKernel_d_2::Algebraic_real_2 a, - AlgebraicKernel_d_2::Bound y);} +\ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Bound y);} {Compares the second coordinate of $a$ with $y$.} -\ccMethod{result_type operator()( - AlgebraicKernel_d_2::Algebraic_real_2 a, - AlgebraicKernel_d_2::Coefficient y);} +\ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Coefficient y);} +{Compares the second coordinate of $a$ with $y$.} +\ccMethod{result_type operator()(AlgebraicKernel_d_2::Algebraic_real_2 a, AlgebraicKernel_d_2::Algebraic_real_1 y);} {Compares the second coordinate of $a$ with $y$.} \ccSeeAlso diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Isolate_2.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Isolate_2.tex index 3c8c66fc99c..8a95dce9da4 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Isolate_2.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Isolate_2.tex @@ -32,7 +32,7 @@ operator()( for $a$ with respect to the common solutions of $f$ and $g$. It is not necessary that $a$ is a common solution of $f$ and $g$. \ccPostcond{ $a \in B$. } -\ccPostcond{ $\{ r | f(r)=g(r)=0 \} \cap \overline{B} = \{a\} \vee \emptyset$.} +\ccPostcond{ $\{ r | f(r)=g(r)=0 \} \cap \overline{B} \in \{\{a\},\emptyset\}$.} } %\ccHasModels diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Solve_2.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Solve_2.tex index aa8a19e9b82..7f2f93ec5a3 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Solve_2.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Solve_2.tex @@ -44,7 +44,7 @@ type \ccc{std::pair} +%\label{Algebraic_kernel_d_1} + +\ccInclude{CGAL/Algebraic_kernel_d_1.h} + +\ccDefinition + +The class represents an algebraic real root by a square free polynomial and an +isolating interval that uniquely defines the root. +The template argument \ccc{Coeff} determines the coefficient type of the +kernel, which is also the coefficient type of the supported polynomials. + +Currently, the following coefficient types are supported:\\ +-- \ccc{Gmpz}, \ccc{Gmpq}, (requires configuration with external libraries GMP, MPFR and MPFI)\\ +-- \ccc{CORE::BigInt}, \ccc{CORE::BigRat}, (requires configuration with external library GMP) \\ +-- \ccc{leda_integer}, \ccc{leda_rational}. (requires configuration with external library LEDA)\\ + +\begin{ccAdvanced} +The template argument type can also be set to \ccc{Sqrt_extension}, where \ccc{NT} is +one of the types listed above. \ccc{ROOT} should be one of the integer types. +See also the documentation of \ccc{Sqrt_extension}. +\end{ccAdvanced} + + The current method +to isolate roots is the bitstream Descartes method presented in~\cite{eigenwillig-phd-08}. +The used method to refine the approximation of an algebraic real root is a slightly modified +(filtered) version of the one presented in~\cite{abbott-qir-06}. +The method has quadratic convergence. + +\ccIsModel +\ccc{AlgebraicKernel_d_1}. + + +\ccTypes \ccThree{}{+++++++++++++}{++++++++} + +\ccNestedType{Coefficient}{Same type as the template argument \ccc{Coeff}.} + +\ccNestedType{Polynomial_1}{A model of \ccc{AlgebraicKernel_d_1::Polynomial_1}.} + +\ccNestedType{Algebraic_real_1}{A model of \ccc{AlgebraicKernel_d_1::AlgebraicReal_1}.} + +\ccNestedType{Bound}{The choice of \ccc{Coeff} also determines the provided bound, type. +In case of \ccc{Coeff} is:\\ +-- \ccc{Gmpz} or \ccc{Gmpq} this is \ccc{Gmpq},\\ +-- \ccc{CORE::BigInt} or \ccc{CORE::BigInt} this is \ccc{CORE::BigRat},\\ +-- \ccc{leda_integer} or \ccc{leda_integer} this is \ccc{leda_rational}.} + +\ccNestedType{Multiplicity_type}{The multiplicity type is \ccc{int}.} + + + +\ccSeeAlso +\ccRefConceptPage{AlgebraicKernel_d_1}\\ +\ccRefConceptPage{Polynomial_d}\\ +\ccRefIdfierPage{CGAL::Algebraic_kernel_d_2} + +\end{ccRefClass} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_d_2.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_d_2.tex new file mode 100644 index 00000000000..68566d7e4ad --- /dev/null +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_d_2.tex @@ -0,0 +1,72 @@ +\begin{ccRefClass}{Algebraic_kernel_d_2} +%\label{Algebraic_kernel_d_2} + +\ccInclude{CGAL/Algebraic_kernel_d_2.h} + +\ccDefinition + +This class is based on an algorithm computing a +geometric-topological analysis of a single curve~\cite{ekw-fast-07} and of a +pair of curves~\cite{ek-exact-08}. +The main idea behind both analyses is to compute the critical +x-coordinates of curves and curve pairs by projection (resultants), and compute +additional information about the critical fibers using subresultants +and Sturm-Habicht sequences~\cite{grlr-sturm-habicht-98}. +With that information, the fiber at +critical x-coordinates is computed by a variant of the Bitstream +Descartes method. +See also \cite{kerber-phd-09} for a comprehensive description of +these techniques. + +A point $p$ of type \ccc{Algebraic_real_2} is represented +by its $x$-coordinate $x_0$ (as described in the \ccc{Algebraic_kernel_d_1} +paragraph above), an algebraic curve where $p$ lies on, and an +integer $i$, denoting that $p$ is the $i$th point in the fiber at $x_0$, +counted from the bottom (ignoring a possible vertical line at $x_0$). +This determines the point uniquely, but the $y$-coordinate +is not stored internally in terms of an \ccc{Algebraic_real_1} object. +Querying such a representation by calling \ccc{Compute_y_2} is a +time-consuming step, and should be avoided for efficiency reasons if possible. +Note that this representation is not exposed in the interface. + +The template argument \ccc{Coeff} determines the coefficient type of the +kernel, which is also the innermost coefficient type of the supported polynomials. + +Currently, the following coefficient types are supported:\\ +-- \ccc{Gmpz}, \ccc{Gmpq}, (requires configuration with external libraries GMP, MPFR and MPFI)\\ +-- \ccc{CORE::BigInt}, \ccc{CORE::BigRat}, (requires configuration with external library GMP) \\ +-- \ccc{leda_integer}, \ccc{leda_rational}. (requires configuration with external library LEDA)\\ + +\begin{ccAdvanced} +The template argument type can also be set to \ccc{Sqrt_extension}, where \ccc{NT} +is one of the types listed above. \ccc{ROOT} should be one of the integer types. +See also the documentation of \ccc{Sqrt_extension}. +\end{ccAdvanced} + +\ccIsModel +\ccc{AlgebraicKernel_d_2}. + +\ccTypes \ccThree{}{+++++++++++++}{++++++++} + +\ccNestedType{Coefficient}{Same type as the template argument \ccc{Coeff}. } + +\ccNestedType{Polynomial_2}{A model of \ccc{AlgebraicKernel_d_2::Polynomial_2}}. + +\ccNestedType{Algebraic_real_2}{A model of \ccc{AlgebraicKernel_d_2::AlgebraicReal_2}} + +\ccNestedType{Bound}{The choice of \ccc{Coeff} also determines the provided bound, type. +In case of \ccc{Coeff} is +- \ccc{Gmpz} or \ccc{Gmpq} this is \ccc{Gmpq} \\ +- \ccc{CORE::BigInt} or \ccc{CORE::BigInt} this is \ccc{CORE::BigRat} \\ +- \ccc{leda_integer} or \ccc{leda_integer} this is \ccc{leda_rational} \\ +} + +\ccNestedType{Multiplicity_type}{The multiplicity type is \ccc{int}.} + +\ccSeeAlso +\ccRefConceptPage{AlgebraicKernel_d_1}\\ +\ccRefConceptPage{AlgebraicKernel_d_2}\\ +\ccRefConceptPage{Polynomial_d}\\ +\ccRefIdfierPage{CGAL::Algebraic_kernel_d_2} + +\end{ccRefClass} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpq_1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpq_d_1.tex similarity index 80% rename from Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpq_1.tex rename to Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpq_d_1.tex index e7bbae3f36d..4a20d97ec3b 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpq_1.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpq_d_1.tex @@ -1,15 +1,16 @@ -\begin{ccRefClass}{Algebraic_kernel_rs_gmpq_1} -\label{Algebraic_kernel_rs_gmpq_1} +\begin{ccRefClass}{Algebraic_kernel_rs_gmpq_d_1} +\label{Algebraic_kernel_rs_gmpq_d_1} + +\ccInclude{CGAL/Algebraic_kernel_rs_gmpq_d_1.h} \ccDefinition This univariate algebraic kernel uses the \rs~library to perform rational univariate polynomial root isolation. It is a model of the -\ccc{AlgebraicKernel_d_1} concept. Due to the fact that \rs~can only +\ccc{AlgebraicKernel_d_1} concept. Due to the fact that RS can only isolate integer polynomials, the operations of this kernel have the overhead of converting the polynomials to integer. -\ccInclude{CGAL/Algebraic_kernel_rs_gmpq_1.h} \ccTypes \ccThree{}{+++++++++++++}{++++++++} @@ -31,6 +32,6 @@ isolating interval.} \ccc{AlgebraicKernel_d_1} \ccSeeAlso -\ccc{Algebraic_kernel_rs_gmpz_1} +\ccc{Algebraic_kernel_rs_gmpz_d_1} \end{ccRefClass} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpz_1.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpz_d_1.tex similarity index 84% rename from Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpz_1.tex rename to Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpz_d_1.tex index 55f90abee9d..7ef8d8bceb7 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpz_1.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpz_d_1.tex @@ -1,5 +1,7 @@ -\begin{ccRefClass}{Algebraic_kernel_rs_gmpz_1} -\label{Algebraic_kernel_rs_gmpz_1} +\begin{ccRefClass}{Algebraic_kernel_rs_gmpz_d_1} +\label{Algebraic_kernel_rs_gmpz_d_1} + +\ccInclude{CGAL/Algebraic_kernel_rs_gmpz_d_1.h} \ccDefinition @@ -7,7 +9,6 @@ This univariate algebraic kernel uses the \rs~library to perform integer univariate polynomial root isolation. It is a model of the \ccc{AlgebraicKernel_d_1} concept. -\ccInclude{CGAL/Algebraic_kernel_rs_gmpz_1.h} \ccTypes \ccThree{}{+++++++++++++}{++++++++} @@ -29,6 +30,6 @@ isolating interval.} \ccc{AlgebraicKernel_d_1}. \ccSeeAlso -\ccc{Algebraic_kernel_rs_gmpq_1} +\ccc{Algebraic_kernel_rs_gmpz_d_1} \end{ccRefClass} diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/intro.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/intro.tex index bb46442a030..4f4feceaedd 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/intro.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/intro.tex @@ -72,7 +72,7 @@ %\ccRefConceptPage{CurvePairAnalysis_2::StatusLine_1}\\ %\ccRefConceptPage{AlgebraicKernelWithAnalysis_d_2::CurvePairAnalysis_2}\\ -%Deprecated: +%Deprecated: %\ccRefConceptPage{AlgebraicKernel_d_1::Derive_1}\\ %\ccRefConceptPage{AlgebraicKernel_d_1::Refine_1}\\ %\ccRefConceptPage{AlgebraicKernel_d_1::LowerBound_1}\\ @@ -89,5 +89,10 @@ \subsection{Models} -\ccRefConceptPage{CGAL::Algebraic_kernel_rs_gmpz_1}\\ -\ccRefConceptPage{CGAL::Algebraic_kernel_rs_gmpq_1}\\ +\ccRefIdfierPage{CGAL::Algebraic_kernel_d_1}\\ +\ccRefIdfierPage{CGAL::Algebraic_kernel_d_2}\\ + +\ccRefIdfierPage{CGAL::Algebraic_kernel_rs_gmpz_d_1}\\ +\ccRefIdfierPage{CGAL::Algebraic_kernel_rs_gmpq_d_1}\\ + + diff --git a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/main.tex b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/main.tex index 3b6694526df..83365195f65 100644 --- a/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/main.tex +++ b/Algebraic_kernel_d/doc_tex/Algebraic_kernel_d_ref/main.tex @@ -27,8 +27,9 @@ \input{Algebraic_kernel_d_ref/AlgebraicKernel_d_1_ApproximateAbsolute_1} \input{Algebraic_kernel_d_ref/AlgebraicKernel_d_1_ApproximateRelative_1} -\input{Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpz_1} -\input{Algebraic_kernel_d_ref/AlgebraicKernel_rs_gmpq_1} +\input{Algebraic_kernel_d_ref/Algebraic_kernel_d_1} +\input{Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpz_d_1} +\input{Algebraic_kernel_d_ref/Algebraic_kernel_rs_gmpq_d_1} \input{Algebraic_kernel_d_ref/AlgebraicKernel_d_2} @@ -55,9 +56,11 @@ \input{Algebraic_kernel_d_ref/AlgebraicKernel_d_2_ApproximateRelative_2} \input{Algebraic_kernel_d_ref/AlgebraicKernel_d_2_BoundBetween_2} +\input{Algebraic_kernel_d_ref/Algebraic_kernel_d_2} -%% NOT PART OF THIS SUBMISSION + +%% NOT PART OF THIS SUBMISSION %\input{Algebraic_kernel_d_ref/AlgebraicKernelWithAnalysis_d_2} %\input{Algebraic_kernel_d_ref/CurveAnalysis_2} %\input{Algebraic_kernel_d_ref/CurvePairAnalysis_2} @@ -68,7 +71,7 @@ %\input{Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Derive_2} %\input{Algebraic_kernel_d_ref/AlgebraicKernel_d_1_Refine_1} -%Deprecated +%Deprecated %\input{Algebraic_kernel_d_ref/AlgebraicKernel_d_1_LowerBound_1} %\input{Algebraic_kernel_d_ref/AlgebraicKernel_d_1_UpperBound_1} %\input{Algebraic_kernel_d_ref/AlgebraicKernel_d_2_Refine_2} diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/CMakeLists.txt b/Algebraic_kernel_d/examples/Algebraic_kernel_d/CMakeLists.txt index 8ea08fcb6f6..b75338951a5 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/CMakeLists.txt +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/CMakeLists.txt @@ -1,35 +1,40 @@ -project( AK_examples ) +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Algebraic_kernel_d_test ) CMAKE_MINIMUM_REQUIRED(VERSION 2.4.5) set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) - + if ( COMMAND cmake_policy ) - cmake_policy( SET CMP0003 NEW ) + cmake_policy( SET CMP0003 NEW ) endif() - -find_package( CGAL QUIET ) + +find_package(CGAL QUIET COMPONENTS) if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) include( CGAL_CreateSingleSourceCGALProgram ) - find_package( RS ) - if( RS_FOUND ) - include( ${RS_USE_FILE} ) - include_directories( BEFORE ../../include ) - create_single_source_cgal_program( "Construct_algebraic_real_1.cpp" ) - create_single_source_cgal_program( "Solve_1.cpp" ) - create_single_source_cgal_program( "Compare_1.cpp" ) - create_single_source_cgal_program( "Isolate_1.cpp" ) - create_single_source_cgal_program( "Sign_at_1.cpp" ) - else( RS_FOUND ) - message(STATUS "NOTICE: This program requires RS and will not be compiled.") - endif( RS_FOUND ) + include( CGAL_VersionUtils ) + find_package( MPFI ) + if( MPFI_FOUND ) + include( ${MPFI_USE_FILE} ) + endif( MPFI_FOUND ) -else( CGAL_FOUND ) + include_directories (BEFORE ../../include) - message(STATUS - "NOTICE: This program requires CGAL, and will not be compiled.") + create_single_source_cgal_program( "Compare_1.cpp" ) + create_single_source_cgal_program( "Construct_algebraic_real_1.cpp" ) + create_single_source_cgal_program( "Isolate_1.cpp" ) + create_single_source_cgal_program( "Sign_at_1.cpp" ) + create_single_source_cgal_program( "Solve_1.cpp" ) + +else() + + message(STATUS "This program requires the CGAL library, and will not be compiled.") + +endif() -endif( CGAL_FOUND ) diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Compare_1.cpp b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Compare_1.cpp index abb485081fe..623a8e5d5c9 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Compare_1.cpp +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Compare_1.cpp @@ -2,13 +2,12 @@ // $Id$ #include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include +#ifdef CGAL_USE_MPFI +#include +#include #include -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; +typedef CGAL::Algebraic_kernel_d_1 AK; typedef AK::Coefficient Coefficient; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Algebraic_real_1 Algebraic_real_1; @@ -58,6 +57,7 @@ int main(){ } #else int main(){ - return 0; + std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl; +return 0; } #endif diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Construct_algebraic_real_1.cpp b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Construct_algebraic_real_1.cpp index ac3de9bb310..907c053a6c8 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Construct_algebraic_real_1.cpp +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Construct_algebraic_real_1.cpp @@ -2,13 +2,13 @@ // $Id$ #include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include +#ifdef CGAL_USE_MPFI +#include +#include #include +#include -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; +typedef CGAL::Algebraic_kernel_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Algebraic_real_1 Algebraic_real_1; typedef AK::Coefficient Coefficient; @@ -16,7 +16,7 @@ typedef AK::Bound Bound; typedef AK::Multiplicity_type Multiplicity_type; int main(){ - AK ak; // an object of Algebraic_kernel_d_1_RS_Gmpz + AK ak; // an object of AK::Construct_algebraic_real_1 construct_algreal_1 = ak.construct_algebraic_real_1_object(); std::cout << "Construct from int : " << construct_algreal_1(int(2)) << "\n"; @@ -35,6 +35,7 @@ int main(){ } #else int main(){ - return 0; + std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl; +return 0; } #endif diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Isolate_1.cpp b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Isolate_1.cpp index 49aa1476aaa..e5a5feadec0 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Isolate_1.cpp +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Isolate_1.cpp @@ -2,13 +2,12 @@ // $Id$ #include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include +#ifdef CGAL_USE_MPFI +#include +#include #include -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; +typedef CGAL::Algebraic_kernel_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Algebraic_real_1 Algebraic_real_1; typedef AK::Coefficient Coefficient; @@ -16,7 +15,7 @@ typedef AK::Bound Bound; typedef AK::Multiplicity_type Multiplicity_type; int main(){ - AK ak; // an object of Algebraic_kernel_d_1_RS_Gmpz + AK ak; // an object of AK::Construct_algebraic_real_1 construct_algreal_1 = ak.construct_algebraic_real_1_object(); AK::Isolate_1 isolate_1 = ak.isolate_1_object(); AK::Compute_polynomial_1 compute_polynomial_1 = ak.compute_polynomial_1_object(); @@ -52,6 +51,7 @@ int main(){ } #else int main(){ - return 0; + std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl; +return 0; } #endif diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Sign_at_1.cpp b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Sign_at_1.cpp index f27ece48c77..6ce319925fe 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Sign_at_1.cpp +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Sign_at_1.cpp @@ -2,13 +2,12 @@ // $Id$ #include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include +#ifdef CGAL_USE_MPFI +#include +#include #include -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; +typedef CGAL::Algebraic_kernel_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Algebraic_real_1 Algebraic_real_1; typedef AK::Coefficient Coefficient; @@ -48,8 +47,10 @@ int main(){ return 0; } + #else int main(){ - return 0; + std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl; +return 0; } #endif diff --git a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Solve_1.cpp b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Solve_1.cpp index 0e344e96641..404595956fe 100644 --- a/Algebraic_kernel_d/examples/Algebraic_kernel_d/Solve_1.cpp +++ b/Algebraic_kernel_d/examples/Algebraic_kernel_d/Solve_1.cpp @@ -2,20 +2,19 @@ // $Id$ #include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include +#ifdef CGAL_USE_MPFI +#include +#include #include -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; +typedef CGAL::Algebraic_kernel_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Algebraic_real_1 Algebraic_real_1; typedef AK::Bound Bound; typedef AK::Multiplicity_type Multiplicity_type; int main(){ - AK ak; // an object of Algebraic_kernel_d_1_RS_Gmpz + AK ak; // an object of AK::Solve_1 solve_1 = ak.solve_1_object(); Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monomial x @@ -57,6 +56,7 @@ int main(){ } #else int main(){ - return 0; + std::cout << "This example requires CGAL to be configured with library MPFI." << std::endl; +return 0; } #endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h new file mode 100644 index 00000000000..425f9253b2c --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_curve_kernel_2.h @@ -0,0 +1,2886 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Eric Berberich +// Pavel Emeliyanenko +// Michael Kerber +// +// ============================================================================ + +/*! \file Algebraic_curve_kernel_2.h + * \brief defines class \c Algebraic_curve_kernel_2 + * + * A model for CGAL's AlgebraicKernelWithAnalysis_d_2 concept + */ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_D_2_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_D_2_H + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#if CGAL_ACK_WITH_ROTATIONS +#include +#endif + +#include +#include + +#if CGAL_ACK_USE_EXACUS +#include +#include +#else +#include +#include +#endif + +#include + + +namespace CGAL { + + +/*! + * \b Algebraic_curve_kernel_2 is a model of CGAL's concept \c + * AlgebraicKernelWithAnalysis_d_2 which itself refines \c AlgebraicKernel_d_2. + * As such, it contains functionality + * for solving and manipulating (systems of) bivariate polynomials, + * of arbitrary degree, + * as required by the \c AlgebraicKernel_d_2 concept. + * Additionally, it contains functionality for the topological-geometric + * analysis of a single algebraic curve + * (given as the vanishing set of the polynomial), + * and of a pair of curves (given as a pair of polynomials), as required by the + * \c AlgebraicKernelWithAnalysis_d_2 concept. These two analyses are + * available via the types \c Curve_analysis_2 and Curve_pair_analysis_2. + * + * The given class is also a model of the \c CurveKernel_2 concept that is + * in turn required by the \c CurvedKernelViaAnalysis_2 concept + * (see the documentation of the corresponding package). Therefore, + * some types and methods of the class have both an "algebraic" name + * (demanded by \c CurveKernelWithAnalysis_d_2) and an "non-algebraic name + * (demanded by \c CurveKernel_2). + * + * \b Algebraic_curve_kernel_2 is a template class, and needs a model + * of the \c AlgebraicKernel_d_1 concept as parameter. + * + * Internally, the curve- and curve-pair analysis + * are the computational fundament of the kernel. That means, whenever + * a polynomial is considered within the kernel, the curve analysis + * of the corresponding algebraic curve is performed. + * The same holds for the curve pair analysis, + * when a kernel function deals with two polynomials, + * implicitly or explicitly (e.g. \c Solve_2, \c Sign_at_2). + */ +#if CGAL_ACK_USE_EXACUS +template < class AlgebraicCurvePair_2, class AlgebraicKernel_d_1 > +#else +template < class AlgebraicKernel_d_1 > +#endif +class Algebraic_curve_kernel_2 : public AlgebraicKernel_d_1{ + +// for each predicate functor defines a member function returning an instance +// of this predicate +#define CGAL_Algebraic_Kernel_pred(Y,Z) \ + Y Z() const { return Y((const Algebraic_kernel_d_2*)this); } + +// the same for construction functors +#define CGAL_Algebraic_Kernel_cons(Y,Z) CGAL_Algebraic_Kernel_pred(Y,Z) + +protected: + // temporary types + +public: + //!\name public typedefs + //!@{ + + //! type of 1D algebraic kernel + typedef AlgebraicKernel_d_1 Algebraic_kernel_d_1; + +#if CGAL_ACK_USE_EXACUS + // type of an internal curve pair + typedef AlgebraicCurvePair_2 Internal_curve_pair_2; + + // type of an internal curve + typedef typename AlgebraicCurvePair_2::Algebraic_curve_2 Internal_curve_2; +#endif + + //! type of x-coordinate +#if CGAL_ACK_USE_EXACUS + typedef typename Internal_curve_2::X_coordinate Algebraic_real_1; +#else + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1; +#endif + + //! type of polynomial coefficient + typedef typename Algebraic_kernel_d_1::Coefficient Coefficient; + + // myself +#if CGAL_ACK_USE_EXACUS + typedef Algebraic_curve_kernel_2 + Self; +#else + typedef Algebraic_curve_kernel_2 Self; +#endif + + typedef Self Algebraic_kernel_d_2; + + // Bound type + typedef typename Algebraic_kernel_d_1::Bound Bound; + + typedef typename Algebraic_kernel_d_1::size_type size_type; + typedef typename Algebraic_kernel_d_1::Multiplicity_type Multiplicity_type; + + typedef typename CGAL::Get_arithmetic_kernel::Arithmetic_kernel + Arithmetic_kernel; + + typedef typename Arithmetic_kernel::Bigfloat Bigfloat; + typedef typename Arithmetic_kernel::Bigfloat_interval Bigfloat_interval; + + //! Univariate polynomial type + typedef typename Algebraic_kernel_d_1::Polynomial_1 Polynomial_1; + + //! Bivariate polynomial type + typedef typename CGAL::Polynomial_traits_d + :: template Rebind::Other::Type Polynomial_2; + + //! bivariate polynomial traits + typedef ::CGAL::Polynomial_traits_d< Polynomial_2 > + Polynomial_traits_2; + + /*! + * \brief type of a curve point, a model for the + * \c AlgebraicKernel_d_2::AlgebraicReal_2 concept + */ + typedef internal::Xy_coordinate_2 Algebraic_real_2; + + /*! + * type of the curve analysis, a model for the + * \c AlgebraicKernelWithAnalysis_d_2::CurveAnalysis_2 concept + */ +#if CGAL_ACK_USE_EXACUS + typedef internal::Curve_analysis_2 Curve_analysis_2; +#else + typedef CGAL::Curve_analysis_2 Curve_analysis_2; +#endif + + /*! + * type of the curve pair analysis, a model for the + * \c AlgebraicKernelWithAnalysis_d_2::CurvePairAnalysis_2 concept + */ +#if CGAL_ACK_USE_EXACUS + typedef internal::Curve_pair_analysis_2 Curve_pair_analysis_2; +#else + typedef CGAL::Curve_pair_analysis_2 Curve_pair_analysis_2; +#endif + + //! traits class used for approximations of y-coordinates + + + // berfriending representations to make protected typedefs available + friend class internal::Curve_analysis_2_rep; + friend class internal::Curve_pair_analysis_2_rep; + + //!@} + //! \name rebind operator + //!@{ +#if CGAL_ACK_USE_EXACUS + template + struct rebind { + typedef Algebraic_curve_kernel_2 + Other; + }; +#else + template + struct rebind { + typedef Algebraic_curve_kernel_2 Other; + }; +#endif + + //!@} +protected: + //! \name private functors + //!@{ + +#if 0 + + //! polynomial canonicalizer, needed for the cache + template + struct Poly_canonicalizer : public std::unary_function< Poly, Poly > + { + // use Polynomial_traits_d<>::Canonicalize ? + Poly operator()(Poly p) + { + typedef CGAL::Scalar_factor_traits Sf_traits; + typedef typename Sf_traits::Scalar Scalar; + typename Sf_traits::Scalar_factor scalar_factor; + typename Sf_traits::Scalar_div scalar_div; + Scalar g = scalar_factor(p); + if (g == Scalar(0)) { + CGAL_assertion(p == Poly(Scalar(0))); + return p; + } + CGAL_assertion(g != Scalar(0)); + if(g != Scalar(1)) + scalar_div(p,g); + if(CGAL::leading_coefficient(CGAL::leading_coefficient(p))) < 0) + scalar_div(p,Scalar(-1)); + return p; + } + + }; +#endif + + // NOT a curve pair in our notation, simply a std::pair of Curve_analysis_2 + typedef std::pair Pair_of_curves_2; + + //! orders pair items by ids + struct Pair_id_order { + + template + std::pair operator()(const std::pair& p) const { + + if(p.first.id() > p.second.id()) + return std::make_pair(p.second, p.first); + return p; + } + }; + + class Curve_creator { + + public: + + Curve_creator(Algebraic_kernel_d_2* kernel) : _m_kernel(kernel) {} + Curve_analysis_2 operator()(const Polynomial_2& f) const { + return Curve_analysis_2(_m_kernel,f); + } + + protected: + + Algebraic_kernel_d_2* _m_kernel; + + }; + + template + class Pair_creator { + + public: + + Pair_creator(Algebraic_kernel_d_2* kernel) : _m_kernel(kernel) {} + + template + Result operator()(const std::pair& p) const { + return Result(_m_kernel, p.first, p.second); + } + + protected: + + Algebraic_kernel_d_2* _m_kernel; + + }; + + struct Pair_id_equal_to { + + template + bool operator()(const std::pair& p1, + const std::pair& p2) const { + return (p1.first.id() == p2.first.id() && + p1.second.id() == p2.second.id()); + } + }; + + //! type of curve analysis cache + typedef internal::LRU_hashed_map_with_kernel, + typename Polynomial_traits_2::Canonicalize, + Curve_creator > Curve_cache_2; + + //! type of curve pair analysis cache + typedef internal::LRU_hashed_map_with_kernel > Curve_pair_cache_2; + + typedef std::pair + Pair_of_polynomial_2; + + template struct Gcd { + + T operator() (std::pair pair) { + return typename CGAL::Polynomial_traits_d + ::Gcd_up_to_constant_factor()(pair.first,pair.second); + } + } ; + + + template struct Pair_cannonicalize { + + std::pair operator() (std::pair pair) { + + if(pair.first > pair.second) + return std::make_pair(pair.second,pair.first); + return pair; + } + }; + + typedef CGAL::Pair_lexicographical_less_than + , + std::less > Polynomial_2_compare; + + //! Cache for gcd computations + typedef CGAL::Cache, + Pair_cannonicalize, + Polynomial_2_compare> Gcd_cache_2; + + //!@} + +public: + //!\name cache access functions + //!@{ + + //! access to the gcd_cache + Gcd_cache_2& gcd_cache_2() const { + return *_m_gcd_cache_2; + } + + //! access to the curve cache + Curve_cache_2& curve_cache_2() const + { + return *_m_curve_cache_2; + } + + //! access to the curve pair cache + Curve_pair_cache_2& curve_pair_cache_2() const + { + return *_m_curve_pair_cache_2; + } + + // Composition of two unary functors + template + class Unary_compose + : public std::unary_function { + + public: + + Unary_compose(const InnerFunctor& inner, + const OuterFunctor& outer) + : _inner(inner), _outer(outer) {} + + Unary_compose(const Unary_compose& other) + : _inner(other._inner), _outer(other._outer) {} + + Unary_compose() : _inner(::boost::none),_outer(::boost::none) {} + + typedef typename InnerFunctor::argument_type argument_type; + typedef typename OuterFunctor::result_type result_type; + + + result_type operator() (const argument_type& arg) const { + CGAL_assertion(_inner); + CGAL_assertion(_outer); + return _outer.get()(_inner.get()(arg)); + } + private: + ::boost::optional _inner; + ::boost::optional _outer; + }; + + template + Unary_compose + unary_compose(const InnerFunctor& inner, const OuterFunctor& outer) + const { + return Unary_compose(inner, outer); + } + + + //!@} + //! \name public functors and predicates + //!@{ + + +public: + //! \brief default constructor + Algebraic_curve_kernel_2() + : _m_curve_cache_2(new Curve_cache_2(this)), + _m_curve_pair_cache_2(new Curve_pair_cache_2(this)), + _m_gcd_cache_2(new Gcd_cache_2()) + { + // std::cout << "CONSTRUCTION Algebraic_curve_kernel_2 " << std::endl; + } + +public: + static Algebraic_curve_kernel_2& get_static_instance(){ + // a default constructed ack_2 instance + static Algebraic_curve_kernel_2 ack_2_instance; + return ack_2_instance; + } + + /*! \brief + * constructs \c Curve_analysis_2 from bivariate polynomial, uses caching + * when appropriate + */ + class Construct_curve_2 : + public std::unary_function< Polynomial_2, Curve_analysis_2 > { + + public: + + Construct_curve_2(const Algebraic_kernel_d_2* kernel) : _m_kernel(kernel) {} + +#if CGAL_ACK_WITH_ROTATIONS + + Curve_analysis_2 operator()(const Polynomial_2& f, + Bound angle, + long final_prec) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "angle=" << angle << std::endl; + CGAL_ACK_DEBUG_PRINT << "final_prec=" << final_prec << std::endl; +#endif + std::pair sin_cos + = approximate_sin_and_cos_of_angle(angle,final_prec); + + Bound sine = sin_cos.first, cosine = sin_cos.second; + + + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type + Poly_rat_1; + + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type + Poly_rat_2; + + Poly_rat_2 + sub_x(Poly_rat_1(Bound(0), cosine), Poly_rat_1(sine)), + sub_y(Poly_rat_1(Bound(0), -sine), Poly_rat_1(cosine)), + res; + + std::vector subs; + subs.push_back(sub_x); + subs.push_back(sub_y); + + res = typename CGAL::Polynomial_traits_d + ::Substitute() (f, subs.begin(), subs.end()); + + CGAL::simplify(res); + + // integralize polynomial + typedef CGAL::Fraction_traits FT; + typename FT::Denominator_type dummy; + Polynomial_2 num; + typename FT::Decompose()(res, num, dummy); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "integralized poly: " << num << std::endl; +#endif + + return _m_kernel->curve_cache_2()(num); + } + +#endif //CGAL_ACK_WITH_ROTATIONS + Curve_analysis_2 operator() + (const Polynomial_2& f) const { + return _m_kernel->curve_cache_2()(f); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + + }; + CGAL_Algebraic_Kernel_cons(Construct_curve_2, construct_curve_2_object); + + /*! \brief + * constructs \c Curve_pair_analysis_2 from pair of one curve analyses, + * caching is used when appropriate + */ + class Construct_curve_pair_2 : + public std::binary_function { + + public: + + Construct_curve_pair_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Curve_pair_analysis_2 operator() + (const Curve_analysis_2& ca1, const Curve_analysis_2& ca2) const { + + Curve_pair_analysis_2 cpa_2 = + _m_kernel->curve_pair_cache_2()(std::make_pair(ca1, ca2)); + return cpa_2; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Construct_curve_pair_2, + construct_curve_pair_2_object); + + class Construct_algebraic_real_2 { + + private: + + Curve_analysis_2 _construct_defining_polynomial_from(Bound b) const { + typedef CGAL::Fraction_traits FT; + // We rely on the fact that the Bound is a fraction + BOOST_STATIC_ASSERT((::boost::is_same::value)); + typedef typename FT::Numerator_type Numerator; + typedef typename FT::Denominator_type Denominator; + typedef CGAL::Coercion_traits Num_coercion; + BOOST_STATIC_ASSERT((::boost::is_same + ::value)); + typedef CGAL::Coercion_traits Denom_coercion; + BOOST_STATIC_ASSERT((::boost::is_same + ::value)); + typename Num_coercion::Cast num_cast; + typename Denom_coercion::Cast denom_cast; + typename FT::Decompose decompose; + + Numerator num_uncasted; + Denominator denom_uncasted; + decompose(b,num_uncasted,denom_uncasted); + + Coefficient num = num_cast(num_uncasted); + Coefficient denom = denom_cast(denom_uncasted); + + typedef CGAL::Exponent_vector Exponent; + std::pair coeffs[2] + = {std::make_pair(Exponent(0,0),num), + std::make_pair(Exponent(0,1),-denom)}; + Polynomial_2 pol = typename Polynomial_traits_2 + ::Construct_polynomial()(coeffs,coeffs+2); + return _m_kernel->construct_curve_2_object()(pol); + } + + Curve_analysis_2 _construct_defining_polynomial_from + (typename CGAL::First_if_different::Type c) const { + typedef CGAL::Exponent_vector Exponent; + std::pair coeffs[2] + = {std::make_pair(Exponent(0,0),c),std::make_pair(Exponent(0,1),-1)}; + Polynomial_2 pol = typename Polynomial_traits_2 + ::Construct_polynomial()(coeffs,coeffs+2); + return _m_kernel->construct_curve_2_object()(pol); + } + + + public: + + typedef Algebraic_real_2 result_type; + + Construct_algebraic_real_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + + result_type operator() (int x,int y) const { + return this->operator()(Bound(x),Bound(y)); + } + + result_type operator() (Bound x,Bound y) const { + Algebraic_real_1 x_alg + = _m_kernel->construct_algebraic_real_1_object()(x); + Curve_analysis_2 ca + = this->_construct_defining_polynomial_from(y); + return Algebraic_real_2(x_alg,ca,0); + } + + result_type operator() + (typename CGAL::First_if_different::Type x, + typename CGAL::First_if_different::Type y) const { + Algebraic_real_1 x_alg + = _m_kernel->construct_algebraic_real_1_object()(x); + Curve_analysis_2 ca + = this->_construct_defining_polynomial_from(y); + return Algebraic_real_2(x_alg,ca,0); + } + + result_type operator() (Algebraic_real_1 x, Algebraic_real_1 y) const { + std::vector< Algebraic_real_1> roots; + Polynomial_1 y_pol =_m_kernel->compute_polynomial_1_object()(y); + _m_kernel->solve_1_object()(y_pol,true,std::back_inserter(roots)); + std::pair::iterator, + typename std::vector< Algebraic_real_1>::iterator> + it_pair = std::equal_range(roots.begin(),roots.end(),y); + CGAL_assertion(std::distance(it_pair.first,it_pair.second)==1); + int index = std::distance(roots.begin(),it_pair.first); + + int degree = CGAL::degree(y_pol); + std::vector > coeffs; + for(int i=0;i<=degree;i++) { + Coefficient c = CGAL::get_coefficient(y_pol,i); + coeffs.push_back(std::make_pair(CGAL::Exponent_vector(0,i),c)); + } + Polynomial_2 y_pol_in_xy + = typename Polynomial_traits_2::Construct_polynomial() + (coeffs.begin(),coeffs.end()); + Curve_analysis_2 ca + = _m_kernel->construct_curve_2_object()(y_pol_in_xy); + return Algebraic_real_2(x,ca,index); + } + + result_type operator() (Polynomial_2 f,Polynomial_2 g,size_type i) + const { + CGAL_precondition(_m_kernel->is_square_free_2_object()(f)); + CGAL_precondition(_m_kernel->is_square_free_2_object()(g)); + CGAL_precondition(_m_kernel->is_coprime_2_object()(f,g)); + std::vector > roots; + this->_m_kernel->solve_2_object()(f,g,std::back_inserter(roots)); + CGAL_assertion(roots.size()>static_cast(i)); + return roots[i].first; + } + + result_type operator() (Polynomial_2 f,Polynomial_2 g, + Bound x_l, Bound x_u, + Bound y_l, Bound y_u) const { + CGAL_precondition(x_lis_square_free_2_object()(f)); + CGAL_precondition(_m_kernel->is_square_free_2_object()(g)); + CGAL_precondition(_m_kernel->is_coprime_2_object()(f,g)); + std::vector > roots; + this->_m_kernel->solve_2_object()(f,g,x_l,x_u,y_l,y_u, + std::back_inserter(roots)); + CGAL_precondition(roots.size()==1); + CGAL_precondition(_m_kernel->compare_x_2_object()(roots[0].first,x_l) + == CGAL::LARGER); + CGAL_precondition(_m_kernel->compare_x_2_object()(roots[0].first,x_u) + == CGAL::SMALLER); + CGAL_precondition(_m_kernel->compare_y_2_object()(roots[0].first,y_l) + == CGAL::LARGER); + CGAL_precondition(_m_kernel->compare_y_2_object()(roots[0].first,y_u) + == CGAL::SMALLER); + return roots[0].first; + } + + // These are not part of the concept, but used internally + + result_type operator() (Algebraic_real_1 x,int y) const { + return this->operator()(x,Bound(y)); + } + + result_type operator() (Algebraic_real_1 x,Bound y) const { + Curve_analysis_2 ca + = this->_construct_defining_polynomial_from(y); + return Algebraic_real_2(x,ca,0); + } + + result_type operator() + (Algebraic_real_1 x, + typename CGAL::First_if_different::Type y) const { + Curve_analysis_2 ca + = this->_construct_defining_polynomial_from(y); + return Algebraic_real_2(x,ca,0); + } + + + protected: + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Construct_algebraic_real_2, + construct_algebraic_real_2_object); + + + + class Compute_polynomial_x_2 : + public std::unary_function { + + public: + + Compute_polynomial_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Polynomial_1 operator()(const Algebraic_real_2& xy) const { + return _m_kernel->compute_polynomial_1_object()(xy.x()); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Compute_polynomial_x_2, + compute_polynomial_x_2_object); + + class Compute_polynomial_y_2 : + public std::unary_function { + + public: + + Compute_polynomial_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Polynomial_1 operator()(const Algebraic_real_2& xy) const { + return _m_kernel->compute_polynomial_1_object()(xy.y()); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Compute_polynomial_y_2, + compute_polynomial_y_2_object); + + + class Isolate_x_2 : public std::binary_function > { + + public: + + Isolate_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator()(Algebraic_real_2 a, + Polynomial_1 p) const { + return _m_kernel->isolate_1_object() + (_m_kernel->compute_x_2_object()(a),p); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Isolate_x_2, + isolate_x_2_object); + + class Isolate_y_2 : public std::binary_function > { + + public: + + Isolate_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator()(Algebraic_real_2 a, + Polynomial_1 p) const { + // Note: One can avoid to compute the y-coordinate: + // 1.) Construct a Polynomial_2 out of p (with no x-variable) + // 2.) Check whether a lies on p + // 3.) If no, approx the y-coordinate until it is isolated + // from all roots of p + // 4.) If yes, return the isolating interval of the + // corresponding roots of p + // + // It is not clear, however, whether this is less expensive, + // especially if p has high degree + return _m_kernel->isolate_1_object() + (_m_kernel->compute_y_2_object()(a),p); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Isolate_y_2, + isolate_y_2_object); + + class Isolate_2 { + + public: + + typedef CGAL::cpp0x::array result_type; + + Isolate_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + protected: + + // refines the approximation of a until the box is away from all + // common solutions of f and g + result_type _approx_interval(Algebraic_real_2 a, + Polynomial_2 f, + Polynomial_2 g) const { + CGAL_precondition(!_m_kernel->is_zero_at_2_object()(f,a)); + + typename Algebraic_curve_kernel_2::Approximate_absolute_x_2 + approx_x = _m_kernel->approximate_absolute_x_2_object(); + typename Algebraic_curve_kernel_2::Approximate_absolute_y_2 + approx_y = _m_kernel->approximate_absolute_y_2_object(); + + typedef CGAL::internal::Interval_evaluate_2< Polynomial_2, Bound > + Interval_evaluate_2; + typedef typename Interval_evaluate_2::result_type + Interval_result_type; + Interval_evaluate_2 interval_evaluate_2; + + long prec = 4; + + while(true) { + std::pair x_pair = approx_x(a,prec); + std::pair y_pair = approx_y(a,prec); + result_type curr_box = CGAL::make_array(x_pair.first, + x_pair.second, + y_pair.first, + y_pair.second); + Interval_result_type eval_f = interval_evaluate_2(f,curr_box); + if((CGAL::sign(eval_f.first)==CGAL::sign(eval_f.second)) && + (CGAL::sign(eval_f.first)!=CGAL::ZERO)) { + return curr_box; + } + Interval_result_type eval_g = interval_evaluate_2(g,curr_box); + if((CGAL::sign(eval_g.first)==CGAL::sign(eval_g.second)) && + (CGAL::sign(eval_g.first)!=CGAL::ZERO)) { + return curr_box; + } + prec*=2; + + } + } + + public: + + result_type operator()(Algebraic_real_2 a, + Polynomial_2 f) const { + return this->_approx_interval(a,f,Polynomial_2(Coefficient(0))); + } + + + result_type operator()(Algebraic_real_2 a, + Polynomial_2 f, + Polynomial_2 g) const { + + Curve_analysis_2 ca1 = _m_kernel->construct_curve_2_object()(f); + Curve_analysis_2 ca2 = _m_kernel->construct_curve_2_object()(g); + Curve_pair_analysis_2 cpa_2 + = _m_kernel->construct_curve_pair_2_object()(ca1,ca2); + int idx; bool event; + cpa_2.x_to_index(_m_kernel->compute_x_2_object()(a),idx,event); + if(! event) { // No critical point, no intersection + return this->_approx_interval(a,f,g); + } + std::vector > roots; + _m_kernel->solve_at_x_2_object()(cpa_2,idx,std::back_inserter(roots)); + if(roots.size()==0) { + // easy case: No intersection at a's x-coordinate: + return this->_approx_interval(a,f,g); + } + // Check whether a is really an intersection + if(!_m_kernel->is_zero_at_2_object()(f,a)) { + return this->operator()(a,f); + } + if(!_m_kernel->is_zero_at_2_object()(g,a)) { + return this->operator()(a,g); + } + // At this point, a is a common solution of f and g, it must + // be one of the points in roots + // Isolating x-interval is immediately available from CPA: + Bound xl = cpa_2.bound_value_in_interval(idx), + xu = cpa_2.bound_value_in_interval(idx+1); + // Often, there is just one point, so filter this easy case + if(roots.size()==1) { + // Any y-interval containing roots[0].first is isolating + std::pair y_pair + = _m_kernel->approximate_absolute_y_2_object()(roots[0].first,4); + return CGAL::make_array(xl,xu,y_pair.first,y_pair.second); + } else { + // more work! We should not assume that each + // roots[i].first has f or g as defining polynomial, because + // the representation might have been simplifed + + // Here's the safe way: Take the simpler of the curves + // (but the one without vertical component!) + Curve_analysis_2 ca; + typedef typename Curve_analysis_2::Status_line_1 Status_line_CA_1; + Status_line_CA_1 status_line; + Status_line_CA_1 status_line1 + = ca1.status_line_at_exact_x(_m_kernel->compute_x_2_object()(a)); + Status_line_CA_1 status_line2 + = ca2.status_line_at_exact_x(_m_kernel->compute_x_2_object()(a)); + if(status_line1.covers_line()) { + ca=ca2; + status_line=status_line2; + } else if(status_line2.covers_line()) { + ca=ca1; + status_line=status_line1; + } else if(CGAL::total_degree(f) { + + public: + + Compute_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Algebraic_real_1 operator()(const Algebraic_real_2& xy) const { + return xy.x(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Compute_x_2, compute_x_2_object); + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + typedef Compute_x_2 Get_x_2; + CGAL_Algebraic_Kernel_cons(Get_x_2, get_x_2_object); +#endif + + /*! + * \brief returns the y-coordinate of \c Algebraic_real_2 object + * + * \attention{This method returns the y-coordinate in isolating interval + * representation. Calculating such a representation is usually a time- + * consuming taks, since it is against the "y-per-x"-view that we take + * in our kernel. Therefore, it is recommended, if possible, + * to use the functors + * \c Approximate_absolute_y_2 and \c Approximate_relative_y_2 that + * return approximation of the y-coordinate. + */ + class Compute_y_2 : + public std::unary_function { + + public: + + Compute_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Algebraic_real_1 operator()(const Algebraic_real_2& xy) const { + return xy.y(); + } + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Compute_y_2, compute_y_2_object); + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + typedef Compute_x_2 Get_y_2; + CGAL_Algebraic_Kernel_cons(Get_y_2, get_y_2_object); +#endif + + class Approximate_absolute_x_2 + : public std::binary_function >{ + + public: + + Approximate_absolute_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator() (Algebraic_real_2 xy, + int prec) const { + Compute_x_2 get_x = _m_kernel->compute_x_2_object(); + return _m_kernel->approximate_absolute_1_object() + (get_x(xy),prec); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Approximate_absolute_x_2, + approximate_absolute_x_2_object); + + class Approximate_relative_x_2 + : public std::binary_function >{ + + public: + + Approximate_relative_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator() (Algebraic_real_2 xy, + int prec) const { + Compute_x_2 get_x = _m_kernel->compute_x_2_object(); + return _m_kernel->approximate_relative_1_object() (get_x(xy),prec); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Approximate_relative_x_2, + approximate_relative_x_2_object); + + class Approximate_absolute_y_2 + : public std::binary_function >{ + + public: + + Approximate_absolute_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator() (Algebraic_real_2 xy, + int prec) const { + + Bound l = xy.lower_bound_y(); + Bound u = xy.upper_bound_y(); + Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec)); + while((u-l)*error>Bound(1)) { + xy.refine_y(); + u = xy.upper_bound_y(); + l = xy.lower_bound_y(); + } + return std::make_pair(l,u); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Approximate_absolute_y_2, + approximate_absolute_y_2_object); + + class Approximate_relative_y_2 + : public std::binary_function >{ + + public: + + Approximate_relative_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + std::pair operator() (Algebraic_real_2 xy, + int prec) const { + if(xy.is_y_zero()) { + return std::make_pair(Bound(0),Bound(0)); + } + while(CGAL::sign(xy.lower_bound_y())*CGAL::sign(xy.upper_bound_y()) + !=CGAL::POSITIVE) { + xy.refine_y(); + } + Bound l = xy.lower_bound_y(); + Bound u = xy.upper_bound_y(); + Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec)); + Bound min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l)); + while((prec>0)?((u-l)*error>min_b):((u-l)>error*min_b)){ + xy.refine_y(); + u = xy.upper_bound_y(); + l = xy.lower_bound_y(); + min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l)); + } + return std::make_pair(l,u); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Approximate_relative_y_2, + approximate_relative_y_2_object); + + + /*! + * \brief returns a value of type \c Bound that lies between + * the x-coordinates of the \c Algebraic_real_2s. + * + * \pre{The x-coordinates must not be equal} + */ + class Bound_between_x_2 { + + public: + + Bound_between_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 first_argument_type; + typedef Algebraic_real_2 second_argument_type; + typedef Bound result_type; + + result_type operator()(const Algebraic_real_2& r1, + const Algebraic_real_2& r2) const { + return this->_m_kernel->bound_between_1_object() + (r1.x(), r2.x()); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Bound_between_x_2, + bound_between_x_2_object); + + /*! + * \brief returns a value of type \c Bound that lies between + * the y-coordinates of the \c Algebraic_real_2s. + * + * \pre{The y-coordinates must not be equal} + */ + class Bound_between_y_2 { + + public: + + Bound_between_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 first_argument_type; + typedef Algebraic_real_2 second_argument_type; + typedef Bound result_type; + + typedef typename Algebraic_kernel_d_2::Curve_analysis_2 + ::Status_line_1::Bitstream_descartes Isolator; + + result_type operator()(const Algebraic_real_2& r1, + const Algebraic_real_2& r2) const { + + CGAL_precondition(r1.y() != r2.y()); + + Bound res(0); + + Isolator isol1 = + r1.curve().status_line_at_exact_x(r1.x()).isolator(); + + Isolator isol2 = + r2.curve().status_line_at_exact_x(r2.x()).isolator(); + + Bound low1, low2, high1, high2; + + while (true) { + low1 = isol1.left_bound(r1.arcno()); + high1 = isol1.right_bound(r1.arcno()); + + low2 = isol2.left_bound(r2.arcno()); + high2 = isol2.right_bound(r2.arcno()); + + if (low1 > high2) { + res = ((low1 + high2)/Bound(2)); + break; + } + if (low2 > high1) { + res = ((low2 + high1)/Bound(2)); + break; + } + + // else + isol1.refine_interval(r1.arcno()); + isol2.refine_interval(r2.arcno()); + } + + CGAL::simplify(res); + + CGAL_postcondition_code( + CGAL::Comparison_result exp = CGAL::SMALLER + ); + CGAL_postcondition_code( + if (r1.y() > r2.y()) { + exp = CGAL::LARGER; + } + ); + CGAL_postcondition(r1.y().compare(res) == exp); + CGAL_postcondition(r2.y().compare(res) == -exp); + + return res; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Bound_between_y_2, + bound_between_y_2_object); + + //! \brief comparison of x-coordinates + class Compare_x_2 : + public std::binary_function { + + public: + + Compare_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Comparison_result operator()(const Algebraic_real_2& xy1, + const Algebraic_real_2& xy2) const { + return _m_kernel->compare_1_object()(xy1.x(), xy2.x()); + } + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + Comparison_result operator()(const Algebraic_real_1& xy1, + const Algebraic_real_1& xy2) const { + return _m_kernel->compare_1_object()(xy1, xy2); + } + +#endif + + Comparison_result operator()(const Algebraic_real_2& xy, + int i) const { + return _m_kernel->compare_1_object() + ( _m_kernel->compute_x_2_object()(xy), + _m_kernel->construct_algebraic_real_1_object()(i) ); + } + Comparison_result operator()(int i, const Algebraic_real_2& xy) const { + return _m_kernel->compare_1_object() + ( _m_kernel->construct_algebraic_real_1_object()(i), + _m_kernel->compute_x_2_object()(xy) ); + } + + + Comparison_result operator()(const Algebraic_real_2& xy, + Bound b) const { + return _m_kernel->compare_1_object() + ( _m_kernel->compute_x_2_object()(xy), + _m_kernel->construct_algebraic_real_1_object()(b) ); + } + Comparison_result operator()(Bound b, + const Algebraic_real_2& xy) const { + return _m_kernel->compare_1_object() + ( _m_kernel->construct_algebraic_real_1_object()(b), + _m_kernel->compute_x_2_object()(xy) ); + } + + Comparison_result operator() + (const Algebraic_real_2& xy, + typename CGAL::First_if_different::Type c) + const { + return _m_kernel->compare_1_object() + ( _m_kernel->compute_x_2_object()(xy), + _m_kernel->construct_algebraic_real_1_object()(c) ); + } + Comparison_result operator() + (typename CGAL::First_if_different::Type c, + const Algebraic_real_2& xy) const { + return _m_kernel->compare_1_object() + ( _m_kernel->construct_algebraic_real_1_object()(c), + _m_kernel->compute_x_2_object()(xy) ); + } + + Comparison_result operator()(const Algebraic_real_2& xy, + const Algebraic_real_1 a) const { + return _m_kernel->compare_1_object() + ( _m_kernel->compute_x_2_object()(xy),a ); + } + Comparison_result operator()(const Algebraic_real_1& a, + const Algebraic_real_2& xy) const { + return _m_kernel->compare_1_object() + ( a,_m_kernel->compute_x_2_object()(xy) ); + } + + + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Compare_x_2, compare_x_2_object); + + /*! + * \brief comparison of y-coordinates of two points + * + * \attention{If both points have different x-coordinates, this method + * has to translate both y-coordinates + * into isolating interval representations which is a time-consuming + * operation (compare the documentation of the \c Get_y_2 functor) + * If possible, it is recommended to avoid this functor for efficiency.} + */ + class Compare_y_2 : + public std::binary_function< Algebraic_real_2, Algebraic_real_2, + Comparison_result > { + + public: + + Compare_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Comparison_result operator()(const Algebraic_real_2& xy1, + const Algebraic_real_2& xy2) const { + + // It is easier if the x coordinates are equal! + if(_m_kernel->compare_x_2_object()(xy1, xy2) == + CGAL::EQUAL) + return _m_kernel->compare_xy_2_object()(xy1, xy2, true); + + return _m_kernel->compare_1_object()(xy1.y(), xy2.y()); + } + + Comparison_result operator()(const Algebraic_real_2& xy, + int i) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_i + = _m_kernel->construct_algebraic_real_2_object()(x,i); + return _m_kernel->compare_xy_2_object()(xy, xy_from_i, true); + + } + + Comparison_result operator()(int i,const Algebraic_real_2& xy) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_i + = _m_kernel->construct_algebraic_real_2_object()(x,i); + return _m_kernel->compare_xy_2_object()(xy_from_i, xy, true); + + } + + Comparison_result operator()(const Algebraic_real_2& xy, + Bound b) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_b + = _m_kernel->construct_algebraic_real_2_object()(x,b); + return _m_kernel->compare_xy_2_object()(xy, xy_from_b, true); + + } + + Comparison_result operator()(Bound b, + const Algebraic_real_2& xy) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_b + = _m_kernel->construct_algebraic_real_2_object()(x,b); + return _m_kernel->compare_xy_2_object()(xy_from_b, xy, true); + } + + Comparison_result operator() + (const Algebraic_real_2& xy, + typename CGAL::First_if_different::Type c) + const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_c + = _m_kernel->construct_algebraic_real_2_object()(x,c); + return _m_kernel->compare_xy_2_object()(xy, xy_from_c, true); + } + + Comparison_result operator() + (typename CGAL::First_if_different::Type c, + const Algebraic_real_2& xy) + const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_c + = _m_kernel->construct_algebraic_real_2_object()(x,c); + return _m_kernel->compare_xy_2_object()(xy_from_c, xy, true); + } + + Comparison_result operator()(const Algebraic_real_2& xy, + const Algebraic_real_1& a) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_a + = _m_kernel->construct_algebraic_real_2_object()(x,a); + return _m_kernel->compare_xy_2_object()(xy, xy_from_a, true); + + } + + Comparison_result operator()(const Algebraic_real_1& a, + const Algebraic_real_2& xy) const { + + Algebraic_real_1 x = _m_kernel->compute_x_2_object()(xy); + Algebraic_real_2 xy_from_a + = _m_kernel->construct_algebraic_real_2_object()(x,a); + return _m_kernel->compare_xy_2_object()(xy_from_a, xy, true); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Compare_y_2, compare_y_2_object); + + /*! + * \brief lexicographical comparison of two \c Algebraic_real_2 objects + * + * \param equal_x if set, the points are assumed + * to have equal x-coordinates, thus only the y-coordinates are compared. + */ + class Compare_xy_2 : + public std::binary_function { + + public: + + Compare_xy_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Comparison_result operator()(const Algebraic_real_2& xy1, + const Algebraic_real_2& xy2, bool equal_x = false) const { + + // handle easy cases first + /*if(xy1.is_identical(xy2)) + return CGAL::EQUAL; + + if(equal_x && xy1.curve().is_identical(xy2.curve())) + return CGAL::sign(xy1.arcno() - xy2.arcno()); + + bool swap = (xy1.id() > xy2.id()); + std::pair p(xy1, xy2); + if(swap) { + p.first = xy2; + p.second = xy1; + } + + typename Cmp_xy_map::Find_result r = + _m_kernel->_m_cmp_xy.find(p); + if(r.second) { + //std::cerr << "Xy_coordinate2: precached compare_xy result\n"; + return (swap ? -(r.first->second) : r.first->second); + }*/ + + return xy1.compare_xy(xy2, equal_x); + //_m_kernel->_m_cmp_xy.insert(std::make_pair(p, res)); + //return (swap ? -res : res); + } + + Comparison_result operator() (const Algebraic_real_2& xy, + int x, int y) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(xy,x); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(xy,y) ); + } + + Comparison_result operator() (int x,int y, + const Algebraic_real_2& xy) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(x,xy); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(y,xy) ); + } + + Comparison_result operator() (const Algebraic_real_2& xy, + Bound x, Bound y) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(xy,x); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(xy,y) ); + } + + Comparison_result operator() (Bound x,Bound y, + const Algebraic_real_2& xy) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(x,xy); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(y,xy) ); + } + + Comparison_result operator() + (const Algebraic_real_2& xy, + typename CGAL::First_if_different::Type x, + typename CGAL::First_if_different::Type y) + const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(xy,x); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(xy,y) ); + } + + Comparison_result operator() + (typename CGAL::First_if_different::Type x, + typename CGAL::First_if_different::Type y, + const Algebraic_real_2& xy) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(x,xy); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(y,xy) ); + } + + Comparison_result operator() (const Algebraic_real_2& xy, + const Algebraic_real_1& x, + const Algebraic_real_1& y) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(xy,x); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(xy,y) ); + } + + Comparison_result operator() (const Algebraic_real_1& x, + const Algebraic_real_1& y, + const Algebraic_real_2& xy) const { + Comparison_result comp_x + = _m_kernel->compare_x_2_object()(x,xy); + return (comp_x != CGAL::EQUAL + ? comp_x + : _m_kernel->compare_y_2_object()(y,xy) ); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Compare_xy_2, compare_xy_2_object); + + /*! + * \brief checks whether the curve induced by \c p + * has only finitely many self-intersection points + * + * In algebraic terms, it is checked whether + * the polynomial \c p is square free. + */ + class Has_finite_number_of_self_intersections_2 : + public std::unary_function< Polynomial_2, bool > { + + public: + + Has_finite_number_of_self_intersections_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + bool operator()(const Polynomial_2& p) const { + + typename Polynomial_traits_2::Is_square_free is_square_free; + return is_square_free(p); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Has_finite_number_of_self_intersections_2, + has_finite_number_of_self_intersections_2_object); + + /*! + * \brief checks whether two curves induced bt \c f and \c g + * habe finitely many intersections. + * + * In algebraic terms, it is checked whether + * the two polynomials \c f and \c g are coprime. + */ + class Has_finite_number_of_intersections_2 : + public std::binary_function< Polynomial_2, Polynomial_2, bool > { + + public: + + Has_finite_number_of_intersections_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + bool operator()(const Polynomial_2& f, + const Polynomial_2& g) const { + // if curve ids are the same - non-decomposable + if(f.id() == g.id()) + return true; + typename Polynomial_traits_2::Gcd_up_to_constant_factor gcd_utcf; + typename Polynomial_traits_2::Total_degree total_degree; + return (total_degree(gcd_utcf(f, g)) == 0); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Has_finite_number_of_intersections_2, + has_finite_number_of_intersections_2_object); + + // Square_free_factorize_2 + class Square_free_factorize_2 { + + public: + + Square_free_factorize_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Polynomial_2 first_argument_type; + template< class OutputIterator> + OutputIterator operator()( const Polynomial_2& p, OutputIterator it) + const { + return CGAL::square_free_factorize_up_to_constant_factor(p,it); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons( + Square_free_factorize_2, square_free_factorize_2_object); + + //this is deprecated ! + //! Various curve and curve pair decomposition functions + class Decompose_2 { + + public: + + typedef bool result_type; + + Decompose_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + //! returns the square free part of the curve induced by \c p + Polynomial_2 operator()(const Polynomial_2& p) { + typename Polynomial_traits_2::Make_square_free msf; + return msf(p); + } + + /*! + * \brief computes a square-free factorization of a curve \c c, + * returns the number of pairwise coprime square-free factors + * + * returns square-free pairwise coprime factors in \c fit and + * multiplicities in \c mit. The value type of \c fit is + * \c Curve_analysis_2, the value type of \c mit is \c int + */ + template< class OutputIterator1, class OutputIterator2 > + int operator()(const Curve_analysis_2& ca, + OutputIterator1 fit, OutputIterator2 mit ) const { + + typename Polynomial_traits_2:: + Square_free_factorize_up_to_constant_factor factorize; + std::vector factors; + + int n_factors = factorize(ca.polynomial_2(), + std::back_inserter(factors), mit); + Construct_curve_2 cc_2 = _m_kernel->construct_curve_2_object(); + for(int i = 0; i < static_cast(factors.size()); i++) + *fit++ = cc_2(factors[i]); + + return n_factors; + } + + /*!\brief + * Decomposes two curves \c ca1 and \c ca2 into common part + * and coprime parts + * + * The common part of the curves \c ca1 and \c ca2 is written in + * \c oib, the coprime parts are written to \c oi1 and \c oi2, + * respectively. + * + * \return {true, if the two curves were not coprime (i.e., have a + * non-trivial common part} + * + * The value type of \c oi{1,2,b} is \c Curve_analysis_2 + */ + template < class OutputIterator > + bool operator()(const Curve_analysis_2& ca1, + const Curve_analysis_2& ca2, OutputIterator oi1, + OutputIterator oi2, OutputIterator oib) const { + +#if CGAL_ACK_DONT_CHECK_POLYNOMIALS_FOR_COPRIMALITY + return false; +#else + + Construct_curve_2 cc_2 = _m_kernel->construct_curve_2_object(); +#if CGAL_ACK_USE_EXACUS + typedef std::vector Curves; + + Curves parts_f, parts_g; + + if(Internal_curve_2::decompose(ca1._internal_curve(), + ca2._internal_curve(), + std::back_inserter(parts_f), + std::back_inserter(parts_g))) { + typename Curves::const_iterator cit; + // this is temporary solution while curves are cached on + // AlciX level + CGAL_precondition(parts_f[0].polynomial_2() == + parts_g[0].polynomial_2()); + *oib++ = cc_2(parts_f[0].polynomial_2()); + + if(parts_f.size() > 1) + for(cit = parts_f.begin() + 1; cit != parts_f.end(); cit++) + *oi1++ = cc_2(cit->polynomial_2()); + if(parts_g.size() > 1) + for(cit = parts_g.begin() + 1; cit != parts_g.end(); cit++) + *oi2++ = cc_2(cit->polynomial_2()); + return true; + } + + +#else + + if (ca1.id() == ca2.id()) { + return false; + } + + const Polynomial_2& f = ca1.polynomial_2(); + const Polynomial_2& g = ca2.polynomial_2(); + + if(f == g) { + // both curves are equal, but have different representations! + // std::cout <<"f: " << f <gcd_cache_2(); + typedef typename Curve_analysis_2::size_type size_type; + Polynomial_2 gcd = gcd_cache(std::make_pair(f,g)); + size_type n = CGAL::degree(gcd); + size_type nc = CGAL::degree( + CGAL::univariate_content_up_to_constant_factor(gcd)); + if( n!=0 || nc!=0 ) { + Curve_analysis_2 common_curve = cc_2(gcd); + *oib++ = common_curve; + Polynomial_2 divided_curve + = CGAL::integral_division(f,gcd); + if( CGAL::degree(divided_curve)>=1 || + CGAL::degree( + CGAL::univariate_content_up_to_constant_factor + (divided_curve)) >=1 ) { + Curve_analysis_2 divided_c = cc_2(divided_curve); + *oi1++ = divided_c; + } + divided_curve = CGAL::integral_division(g,gcd); + if(CGAL::degree(divided_curve) >= 1 || + CGAL::degree( + CGAL::univariate_content_up_to_constant_factor + ( divided_curve )) >=1 ) { + Curve_analysis_2 divided_c = cc_2(divided_curve); + *oi2++ = divided_c; + } + return true; + } + +#endif + + // copy original curves to the output iterator: + *oi1++ = ca1; + *oi2++ = ca2; + return false; +#endif + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Decompose_2, decompose_2_object); + + //!@} +public: + //! \name types and functors for \c CurvedKernelViaAnalysis_2 + //!@{ + + //! Algebraic name + typedef Algebraic_real_1 Coordinate_1; + + //! Non-Algebraic name + typedef Algebraic_real_2 Coordinate_2; + + class Is_square_free_2 : public std::unary_function { + + public: + + Is_square_free_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + bool operator()(const Polynomial_2& p) const { + return typename Polynomial_traits_2::Is_square_free() (p); + } + + private: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Is_square_free_2, is_square_free_2_object); + + //! Algebraic name + typedef Has_finite_number_of_intersections_2 Is_coprime_2; + CGAL_Algebraic_Kernel_cons(Is_coprime_2, is_coprime_2_object); + + class Make_square_free_2 : public std::unary_function { + + public: + Make_square_free_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Polynomial_2 operator()(const Polynomial_2& p) const { + return typename Polynomial_traits_2::Make_square_free() (p); + } + + private: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Make_square_free_2, make_square_free_2_object); + + class Make_coprime_2 { + + public: + + typedef bool result_type; + + Make_coprime_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + bool operator()(const Polynomial_2& p1, + const Polynomial_2& p2, + Polynomial_2& g, + Polynomial_2& q1, + Polynomial_2& q2) const { + + Polynomial_2 one(Coefficient(1)); + + if (p1==p2) { + g=p1; q1=one; q2=one; + return false; + } + Gcd_cache_2& gcd_cache = _m_kernel->gcd_cache_2(); + g = gcd_cache(std::make_pair(p1,p2)); + q1=CGAL::integral_division_up_to_constant_factor(p1,g); + q2=CGAL::integral_division_up_to_constant_factor(p2,g); + return CGAL::total_degree(g)==0; + } + + private: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Make_coprime_2, make_coprime_2_object); + + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + + /*! + * \brief computes the x-critical points of of a curve/a polynomial + * + * An x-critical point (x,y) of \c f (or its induced curve) + * satisfies f(x,y) = f_y(x,y) = 0, + * where f_y means the derivative w.r.t. y. + * In pariticular, each singular point is x-critical. + */ + class X_critical_points_2 : + public std::binary_function< Curve_analysis_2, + std::iterator, + std::iterator > { + + public: + + X_critical_points_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + /*! + * \brief writes the x-critical points of \c ca_2 into \c oi + */ + template + OutputIterator operator()(const Curve_analysis_2& ca_2, + OutputIterator oi) const { + + typename Polynomial_traits_2::Differentiate diff; + Construct_curve_2 cc_2 = _m_kernel->construct_curve_2_object(); + Construct_curve_pair_2 ccp_2 + = _m_kernel->construct_curve_pair_2_object(); + // construct curve analysis of a derivative in y + Curve_analysis_2 ca_2x = cc_2(diff(ca_2.polynomial_2(),0)); + Curve_pair_analysis_2 cpa_2 = ccp_2(ca_2, ca_2x); + typename Curve_pair_analysis_2::Status_line_1 cpv_line; + typename Curve_analysis_2::Status_line_1 cv_line; + + int i, j, n_arcs, n_events = + cpa_2.number_of_status_lines_with_event(); + std::pair ipair; + bool vline_constructed = false; + + for(i = 0; i < n_events; i++) { + cpv_line = cpa_2.status_line_at_event(i); + // no 2-curve intersections over this status line + if(!cpv_line.is_intersection()) + continue; + n_arcs = cpv_line.number_of_events(); + for(j = 0; j < n_arcs; j++) { + ipair = cpv_line.curves_at_event(j, ca_2,ca_2x); + if(ipair.first == -1|| ipair.second == -1) + continue; + if(!vline_constructed) { + cv_line = ca_2.status_line_at_exact_x(cpv_line.x()); + vline_constructed = true; + } + // ipair.first is an arcno over status line of the + // curve p + *oi++ = cv_line.algebraic_real_2(ipair.first); + } + vline_constructed = false; + } + return oi; + } + + //! \brief computes the \c i-th x-critical point of \c ca + Algebraic_real_2 operator()(const Curve_analysis_2& ca, int i) const + { + std::vector x_points; + (*this)(ca, std::back_inserter(x_points)); + CGAL_precondition(0 >= i&&i < x_points.size()); + return x_points[i]; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(X_critical_points_2, + x_critical_points_2_object); + + /*! + * \brief computes the y-critical points of of a curve/a polynomial + * + * An y-critical point (x,y) of \c f (or its induced curve) + * satisfies f(x,y) = f_x(x,y) = 0, + * where f_x means the derivative w.r.t. x. + * In pariticular, each singular point is y-critical. + */ + class Y_critical_points_2 : + public std::binary_function< Curve_analysis_2, + std::iterator, + std::iterator > { + + + public: + + Y_critical_points_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + /*! + * \brief writes the y-critical points of \c ca_2 into \c oi + */ + template + OutputIterator operator()(const Curve_analysis_2& ca_2, + OutputIterator oi) const + { + Construct_curve_2 cc_2 = _m_kernel->construct_curve_2_object(); + Construct_curve_pair_2 ccp_2 + = _m_kernel->construct_curve_pair_2_object(); + + typename Curve_analysis_2::Status_line_1 cv_line; + std::pair ipair; + int i, j, k, n_arcs, n_events = + ca_2.number_of_status_lines_with_event(); + + bool cpa_constructed = false, vline_constructed = false; + typename Curve_pair_analysis_2::Status_line_1 + cpv_line; + Curve_pair_analysis_2 cpa_2; + + for(i = 0; i < n_events; i++) { + cv_line = ca_2.status_line_at_event(i); + n_arcs = cv_line.number_of_events(); + for(j = 0; j < n_arcs; j++) { + ipair = cv_line.number_of_incident_branches(j); + // general case: no special tests required + if(!(ipair.first == 1&&ipair.second == 1)) { + *oi++ = cv_line.algebraic_real_2(j); + continue; + } + if(!cpa_constructed) { + typename Polynomial_traits_2::Differentiate diff; + // construct curve analysis of a derivative in y + Curve_analysis_2 ca_2y = + cc_2(diff(ca_2.polynomial_2(),1)); + cpa_2 = ccp_2(ca_2, ca_2y); + cpa_constructed = true; + } + if(!vline_constructed) { + cpv_line = cpa_2.status_line_for_x(cv_line.x()); + vline_constructed = true; + } + if(!cpv_line.is_intersection()) + continue; + // obtain the y-position of j-th event of curve p + k = cpv_line.event_of_curve(j, ca_2); + ipair = cpv_line.curves_at_event(k); + + // pick up only event comprised of both curve and its der + if(ipair.first != -1&&ipair.second != -1) + *oi++ = cv_line.algebraic_real_2(j); + } + vline_constructed = false; + } + return oi; + } + + //! \brief computes the \c i-th x-critical point of \c ca + Algebraic_real_2 operator()(const Curve_analysis_2& ca, int i) const + { + std::vector y_points; + (*this)(ca, std::back_inserter(y_points)); + CGAL_precondition(0 >= i&&i < y_points.size()); + return y_points[i]; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Y_critical_points_2, + y_critical_points_2_object); + +#endif + + protected: + +// TODO typedef Interval_evaluate_2? + public: + + // Overload the Sign_at_1 functor, to enable filter steps in the + // Curve analysis in a coherent way + class Sign_at_1 + : public::std::binary_function { + + + public: + + Sign_at_1(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + + // Version that refines r up to a certain precision. + // If the (non-zero) sign was not computed until this + // precision, CGAL::ZERO is returned. This can be used internally + // as a filter to detect easy cases + Sign operator()(const Polynomial_1& p, + const Algebraic_real_1& r, + int max_prec) const { + typename Algebraic_kernel_d_2::Approximate_absolute_1 approx_x + = _m_kernel->approximate_absolute_1_object(); + + typedef CGAL::internal::Interval_evaluate_1< Polynomial_1, Bound > + Interval_evaluate_1; + typedef typename Interval_evaluate_1::result_type + Interval_result_type; + Interval_evaluate_1 interval_evaluate_1; + + long prec = 1; + + while(prec<=max_prec) { + std::pair x_pair = approx_x(r,prec); + + Interval_result_type iv + = interval_evaluate_1(p, + std::make_pair(x_pair.first, + x_pair.second)); + CGAL::Sign s_lower = CGAL::sign(iv.first); + if(s_lower == sign(iv.second)) { + return s_lower; + } else { + prec*=2; + } + } + return CGAL::ZERO; + + } + + Sign operator()(const Polynomial_1& p, + const Algebraic_real_1& r, + bool known_to_be_non_zero=false) const { + + if(!known_to_be_non_zero && + _m_kernel->is_zero_at_1_object()(p, r)) { + return CGAL::ZERO; + } + CGAL::Sign result = this->operator() + (p,r,(std::numeric_limits::max)()); + CGAL_assertion(result != CGAL::ZERO); + return result; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + + + }; + CGAL_Algebraic_Kernel_pred(Sign_at_1, sign_at_1_object); + + + /*! + * \brief sign computation of a point and a curve + * + * computes the sign of a point \c p, evaluate at the polynomial + * that defines a curve \c c. If the result is 0, the point lies on the + * curve. Returns a value convertible to \c CGAL::Sign + */ + class Sign_at_2 : + public std::binary_function { + + public: + + Sign_at_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Sign operator()(const Polynomial_2& f, + const Algebraic_real_2& r, + bool known_to_be_non_zero=false) const { + + return this->operator()(_m_kernel->construct_curve_2_object()(f),r, + known_to_be_non_zero); + } + + // Version that refines x- and y-coordinate up to a certain + // precision. If the non-zero sign was not computed until this + // precision, CGAL::ZERO is returned. This can used internally + // as a filter to detect easy cases + Sign operator()(const Polynomial_2& f, + const Algebraic_real_2& r, + int max_prec) const { + return this->operator()(_m_kernel->construct_curve_2_object()(f),r, + max_prec); + } + + // Version that refines x- and y-coordinate up to a certain + // precision. If the non-zero sign was not computed until this + // precision, CGAL::ZERO is returned. This can be used internally + // as a filter to detect easy cases + Sign operator()(const Curve_analysis_2& ca_2, + const Algebraic_real_2& r, + int max_prec) const { + if(ca_2.is_identical(r.curve())) { + return CGAL::ZERO; + } + typename Algebraic_kernel_d_2::Approximate_absolute_x_2 approx_x + = _m_kernel->approximate_absolute_x_2_object(); + typename Algebraic_kernel_d_2::Approximate_absolute_y_2 approx_y + = _m_kernel->approximate_absolute_y_2_object(); + + typedef CGAL::internal::Interval_evaluate_2< Polynomial_2, Bound > + Interval_evaluate_2; + typedef typename Interval_evaluate_2::result_type + Interval_result_type; + Interval_evaluate_2 interval_evaluate_2; + + long prec = 4; + + while(prec<=max_prec) { + std::pair x_pair = approx_x(r,prec); + std::pair y_pair = approx_y(r,prec); + + Interval_result_type iv + = interval_evaluate_2(ca_2.polynomial_2(), + CGAL::make_array(x_pair.first, + x_pair.second, + y_pair.first, + y_pair.second)); + CGAL::Sign s_lower = CGAL::sign(iv.first); + if(s_lower == sign(iv.second)) { + return s_lower; + } else { + prec*=2; + } + } + return CGAL::ZERO; + + } + + Sign operator()(const Curve_analysis_2& ca_2, + const Algebraic_real_2& r, + bool known_to_be_non_zero=false) const { + + if(ca_2.is_identical(r.curve())) { + return CGAL::ZERO; + } + if(!known_to_be_non_zero && + _m_kernel->is_zero_at_2_object()(ca_2, r)) { + return CGAL::ZERO; + } + CGAL::Sign result = this->operator() + (ca_2,r,(std::numeric_limits::max)()); + CGAL_assertion(result != CGAL::ZERO); + return result; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + + }; + CGAL_Algebraic_Kernel_pred(Sign_at_2, sign_at_2_object); + + class Is_zero_at_2 + : public std::binary_function { + + public: + + Is_zero_at_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + bool operator() (const Polynomial_2& f, const Algebraic_real_2& r) const { + return this->operator() (_m_kernel->construct_curve_2_object()(f),r); + } + + bool operator() (const Curve_analysis_2& ca_2, + const Algebraic_real_2& r) const { + + + if (CGAL::is_zero(ca_2.polynomial_2())) { + return true; + } + + Construct_curve_2 cc_2 = _m_kernel->construct_curve_2_object(); + Construct_curve_pair_2 ccp_2 + = _m_kernel->construct_curve_pair_2_object(); + + typename Curve_analysis_2::Status_line_1 + cv_line = ca_2.status_line_for_x(r.x()); + // fast check for the presence of status line at r.x() + if(cv_line.covers_line()) + return true; + + // Handle non-coprime polynomial + Polynomial_2 gcd = _m_kernel->gcd_cache_2() + (std::make_pair(ca_2.polynomial_2(), r.curve().polynomial_2())); + + Curve_analysis_2 gcd_curve = cc_2(gcd); + if(CGAL::total_degree(gcd)>0) { + + Construct_curve_pair_2 ccp_2 + = _m_kernel->construct_curve_pair_2_object(); + Curve_analysis_2 r_curve_remainder = + cc_2(CGAL::integral_division_up_to_constant_factor + (r.curve().polynomial_2(), gcd)); + + r.simplify_by(ccp_2(gcd_curve, r_curve_remainder)); + if(r.curve().polynomial_2() == gcd) + return true; + } + + Curve_pair_analysis_2 cpa_2 = ccp_2(ca_2, r.curve()); + typename Curve_pair_analysis_2::Status_line_1 + cpv_line = cpa_2.status_line_for_x(r.x()); + + if(cpv_line.is_event() && cpv_line.is_intersection()) { + // get an y-position of the point r + int idx = cpv_line.event_of_curve(r.arcno(), r.curve()); + std::pair ipair = + cpv_line.curves_at_event(idx); + if(ipair.first != -1 && ipair.second != -1) + return true; + } + return false; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Is_zero_at_2, + is_zero_at_2_object); + + + protected: + + // Internal Functor to get all solutions at a certain x-coordinate + class Solve_at_x_2 { + + public: + + Solve_at_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + + //! Version with Algebraic_real_1 + template + OutputIterator + operator()(const Curve_pair_analysis_2& cpa_2, + Algebraic_real_1 a, + OutputIterator res) const { + int idx; bool event; + cpa_2.x_to_index(a,idx,event); + if(! event) { + return res; // no intersections at a + } else { + return this->operator()(cpa_2,idx,res); + } + } + + //! Version with index (faster) + template + OutputIterator + operator()(const Curve_pair_analysis_2& cpa_2, + size_type index, + OutputIterator res) const + { + Curve_analysis_2 ca1 = cpa_2.curve_analysis(true), + ca2 = cpa_2.curve_analysis(false); + typename Curve_pair_analysis_2::Status_line_1 cpv_line; + // do we need to check which supporting curve is simpler ? + typename Polynomial_traits_2::Total_degree total_degree; + + Polynomial_2 f1 = ca1.polynomial_2(), + f2 = ca2.polynomial_2(); + bool first_curve = (total_degree(f1) < total_degree(f2)); + + CGAL_assertion(index ipair = cpv_line.curves_at_event(j,ca1,ca2); + if(ipair.first != -1 && ipair.second != -1) { + Algebraic_real_2 new_root + = Algebraic_real_2(x, + (first_curve ? ca1 : ca2), + (first_curve ? ipair.first + : ipair.second)); + Multiplicity_type new_mult + = cpv_line.multiplicity_of_intersection(j); + *res++ = std::make_pair(new_root,new_mult); + continue; + } + if(ipair.first!=-1 && ca2_covers_line) { + Algebraic_real_2 new_root + = Algebraic_real_2(x,ca1,ipair.first); + Multiplicity_type new_mult=-1; + *res++ = std::make_pair(new_root,new_mult); + continue; + } + if(ipair.second!=-1 && ca1_covers_line) { + Algebraic_real_2 new_root + = Algebraic_real_2(x,ca2,ipair.second); + Multiplicity_type new_mult=-1; + *res++ = std::make_pair(new_root,new_mult); + continue; + } + } + return res; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Solve_at_x_2, solve_at_x_2_object); + + + public: + + /*! + * \brief computes solutions of systems of two 2 equations and 2 variables + * + * \pre the polynomials must be square-free and coprime + */ + class Solve_2 { + + public: + + Solve_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + template + std::pair + operator() + (const Polynomial_2& f, const Polynomial_2& g, + OutputIteratorRoots roots, OutputIteratorMult mults) const { + std::vector > + roots_vec; + this->operator()(f,g,std::back_inserter(roots_vec)); + typename Algebraic_kernel_d_1::template Pair_first + pair_first; + typename Algebraic_kernel_d_1::template Pair_second + pair_second; + std::copy(::boost::make_transform_iterator + (roots_vec.begin(),pair_first), + ::boost::make_transform_iterator + (roots_vec.end(),pair_first), + roots); + std::copy(::boost::make_transform_iterator + (roots_vec.begin(),pair_second), + ::boost::make_transform_iterator + (roots_vec.end(),pair_second), + mults); + return std::make_pair(roots,mults); + } + +#endif + + /*! + * \brief solves the system (f=0,g=0) + * + * All solutions of the system are written into \c roots + * (whose value type is \c Algebraic_real_2). The multiplicities + * are written into \c mults (whose value type is \c int) + */ + template OutputIterator + operator() + (const Polynomial_2& f, const Polynomial_2& g, + OutputIterator res) const { + return + (*this)(_m_kernel->construct_curve_2_object()(f), + _m_kernel->construct_curve_2_object()(g), + res); + } + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + template + std::pair + operator() + (const Curve_analysis_2& f, const Curve_analysis_2& g, + OutputIteratorRoots roots, OutputIteratorMult mults) const { + std::vector > + roots_vec; + this->operator()(f,g,std::back_inserter(roots_vec)); + typename Algebraic_kernel_d_1::template Pair_first + pair_first; + typename Algebraic_kernel_d_1::template Pair_second + pair_second; + std::copy(::boost::make_transform_iterator + (roots_vec.begin(),pair_first), + ::boost::make_transform_iterator + (roots_vec.end(),pair_first), + roots); + std::copy(::boost::make_transform_iterator + (roots_vec.begin(),pair_second), + ::boost::make_transform_iterator + (roots_vec.end(),pair_second), + mults); + return std::make_pair(roots,mults); + } + +#endif + + + //! Version with curve analyses + template + OutputIterator + operator()(const Curve_analysis_2& ca1, + const Curve_analysis_2& ca2, + OutputIterator res) const + { + // these tests are quite expensive... do we really need them ?? + /* + CGAL_precondition_code ( + typename Self::Has_finite_number_of_self_intersections_2 + not_self_overlapped; + typename Self::Has_finite_number_of_intersections_2 + do_not_overlap; + CGAL_precondition(not_self_overlapped(ca1) && + not_self_overlapped(ca2)); + CGAL_precondition(do_not_overlap(ca1, ca2)); + ); + */ + Construct_curve_pair_2 ccp_2 + = _m_kernel->construct_curve_pair_2_object(); + Curve_pair_analysis_2 cpa_2 = ccp_2(ca1, ca2); + typename Curve_pair_analysis_2::Status_line_1 cpv_line; + // do we need to check which supporting curve is simpler ? + //typename Polynomial_traits_2::Total_degree total_degree; + + //Polynomial_2 f1 = ca1.polynomial_2(), + // f2 = ca2.polynomial_2(); + //bool first_curve = (total_degree(f1) < total_degree(f2)); + + int i, n = cpa_2.number_of_status_lines_with_event(); + for(i = 0; i < n; i++) { + _m_kernel->solve_at_x_2_object()(cpa_2,i,res); + } + return res; + } + + template OutputIterator + operator() + (const Polynomial_2& f, const Polynomial_2& g, + Bound xl, Bound xu, Bound yl, Bound yu, + OutputIterator res) const { + // Note: This could be improved by not computing all solutions + // but only those in [xl,xu] (lazy evaluation) + std::vector > roots; + this->operator() (f,g,std::back_inserter(roots)); + // Find the x-values using binary search: + typename Algebraic_kernel_d_1::template Pair_first + pair_first; + typedef typename + std::vector > + ::iterator Iterator; + Iterator roots_start = std::lower_bound + (::boost::make_transform_iterator + (roots.begin(), + _m_kernel->unary_compose(pair_first, + _m_kernel->compute_x_2_object())), + ::boost::make_transform_iterator + (roots.end(), + _m_kernel->unary_compose(pair_first, + _m_kernel->compute_x_2_object())), + _m_kernel->construct_algebraic_real_1_object()(xl)).base(); + Iterator roots_end = std::upper_bound + (::boost::make_transform_iterator + (roots_start, + _m_kernel->unary_compose(pair_first, + _m_kernel->compute_x_2_object())), + ::boost::make_transform_iterator + (roots.end(), + _m_kernel->unary_compose(pair_first, + _m_kernel->compute_x_2_object())), + _m_kernel->construct_algebraic_real_1_object()(xu)).base(); + // Now check y-coordinate. Binary search is not possible here! + // Note that compare_y is not too expensive here because we + // only compare with rationals + for(Iterator it=roots_start;it!=roots_end;it++) { + if(_m_kernel->compare_y_2_object()(yl,it->first)==CGAL::LARGER) { + continue; + } + if(_m_kernel->compare_y_2_object()(it->first,yu)==CGAL::LARGER) { + continue; + } + *res++ = *it; + } + return res; + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Solve_2, solve_2_object); + + class Number_of_solutions_2 + : public std::binary_function { + + public: + + Number_of_solutions_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + size_type operator() + (const Polynomial_2& f, const Polynomial_2& g) const { + + std::vector > roots; + _m_kernel->solve_2_object()(f,g,std::back_inserter(roots)); + return roots.size(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Number_of_solutions_2, + number_of_solutions_2_object); + + // Functor used to evaluate a Polynomial_2 in a Bound, up to a + // constant factor + class Evaluate_utcf_2 + : public std::binary_function { + + public: + + Evaluate_utcf_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + Polynomial_1 operator() (const Polynomial_2& f, Bound b) const { + typedef CGAL::Fraction_traits FT; + // We rely on the fact that the Bound is a fraction + BOOST_STATIC_ASSERT((::boost::is_same::value)); + typedef typename FT::Numerator_type Numerator; + typedef typename FT::Denominator_type Denominator; + typedef CGAL::Coercion_traits Num_coercion; + BOOST_STATIC_ASSERT((::boost::is_same + ::value)); + typedef CGAL::Coercion_traits Denom_coercion; + BOOST_STATIC_ASSERT((::boost::is_same + ::value)); + typename Num_coercion::Cast num_cast; + typename Denom_coercion::Cast denom_cast; + typename FT::Decompose decompose; + + Numerator num_uncasted; + Denominator denom_uncasted; + decompose(b,num_uncasted,denom_uncasted); + + Coefficient num = num_cast(num_uncasted); + Coefficient denom = denom_cast(denom_uncasted); + return CGAL::evaluate_homogeneous(f,num,denom); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Evaluate_utcf_2, + evaluate_utcf_2_object); + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + /*! + * \brief Construct a curve with the roles of x and y interchanged. + */ + class Swap_x_and_y_2 { + + public: + + Swap_x_and_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Polynomial_2 argument_type; + typedef Curve_analysis_2 result_type; + + Curve_analysis_2 operator() (const Curve_analysis_2& ca) { + return this->operator() (ca.polynomial_2()); + } + + Curve_analysis_2 operator() (const Polynomial_2& f) { + Polynomial_2 f_yx + = typename Polynomial_traits_2::Swap() (f,0,1); + return _m_kernel->construct_curve_2_object() (f_yx); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Swap_x_and_y_2, swap_x_and_y_2_object); + + //! Refines the x-coordinate of an Algebraic_real_2 object + class Refine_x_2 : + public std::unary_function { + + public: + + Refine_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + void operator()(const Algebraic_real_2& r) const { + r.refine_x(); + } + /* TODO: if needed, include + void operator()(Algebraic_real_2& r, int rel_prec) const { + r.refine_x(rel_prec); + } + */ + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Refine_x_2, refine_x_2_object); + + class Refine_y_2 : + public std::unary_function { + + public: + + Refine_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + void operator()(const Algebraic_real_2& r) const { + return r.refine_y(); + } + + /* TODO: if needed, include + void operator()(Algebraic_real_2& r, int rel_prec) const { + return r.refine_y(rel_prec); + } + */ + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_pred(Refine_y_2, refine_y_2_object); + + class Lower_bound_x_2 { + + public: + + Lower_bound_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 argument_type; + typedef Bound result_type; + + result_type operator()(const Algebraic_real_2& r) { + return r.lower_bound_x(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Lower_bound_x_2, lower_bound_x_2_object); + + class Upper_bound_x_2 { + + public: + + Upper_bound_x_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 argument_type; + typedef Bound result_type; + + result_type operator()(const Algebraic_real_2& r) { + return r.upper_bound_x(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Upper_bound_x_2, upper_bound_x_2_object); + + class Lower_bound_y_2 { + + public: + + Lower_bound_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 argument_type; + typedef Bound result_type; + + result_type operator()(const Algebraic_real_2& r) { + return r.lower_bound_y(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Lower_bound_y_2, lower_bound_y_2_object); + + //! an upper bound of the y-coordinate of \c r + class Upper_bound_y_2 { + + public: + + Upper_bound_y_2(const Algebraic_kernel_d_2* kernel) + : _m_kernel(kernel) {} + + typedef Algebraic_real_2 argument_type; + typedef Bound result_type; + + result_type operator()(const Algebraic_real_2& r) { + return r.upper_bound_y(); + } + + protected: + + const Algebraic_kernel_d_2* _m_kernel; + + }; + CGAL_Algebraic_Kernel_cons(Upper_bound_y_2, upper_bound_y_2_object); + + + + typedef Bound Boundary; + typedef Lower_bound_x_2 Lower_boundary_x_2; + typedef Lower_bound_y_2 Lower_boundary_y_2; + typedef Upper_bound_x_2 Upper_boundary_x_2; + typedef Upper_bound_y_2 Upper_boundary_y_2; + typedef Bound_between_x_2 Boundary_between_x_2; + typedef Bound_between_y_2 Boundary_between_y_2; + + CGAL_Algebraic_Kernel_cons(Lower_boundary_x_2,lower_boundary_x_2_object); + CGAL_Algebraic_Kernel_cons(Lower_boundary_y_2,lower_boundary_y_2_object); + CGAL_Algebraic_Kernel_cons(Upper_boundary_x_2,upper_boundary_x_2_object); + CGAL_Algebraic_Kernel_cons(Upper_boundary_y_2,upper_boundary_y_2_object); + CGAL_Algebraic_Kernel_cons(Boundary_between_x_2,boundary_between_x_2_object); + CGAL_Algebraic_Kernel_cons(Boundary_between_y_2,boundary_between_y_2_object); +#endif + + +#undef CGAL_Algebraic_Kernel_pred +#undef CGAL_Algebraic_Kernel_cons + + //!@} + +protected: + +mutable boost::shared_ptr _m_curve_cache_2; +mutable boost::shared_ptr _m_curve_pair_cache_2; +mutable boost::shared_ptr _m_gcd_cache_2; + + +}; // class Algebraic_curve_kernel_2 + +} // namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_D_2_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h new file mode 100644 index 00000000000..4a2317cb1d1 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_d_1.h @@ -0,0 +1,599 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// The comments are all original EXACUS comments and aren't adapted. + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H +#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace CGAL { +namespace internal { +template +class Algebraic_real_d_1; +} + +template < +class Coefficient_, class Rational_, class HandlePolicy, class AlgebraicRealRep_d_1 > +typename Get_arithmetic_kernel::Arithmetic_kernel::Bigfloat_interval +inline convert_to_bfi( + const internal::Algebraic_real_d_1< Coefficient_, Rational_, HandlePolicy, AlgebraicRealRep_d_1 >& x); + +namespace internal { +/*! \ingroup NiX_Algebraic_real + \brief An Algebraic_real_d_1 \a x is represented by a polynomial and an + isolating interval. It is guaranteed that the polynomial is square free. + The isolating interval is an open interval and it is guaranteed that the + polynomial is non-zero at the endpoints of the interval. + + The algebraic real are reference counted by default. + The template parameters are: + - \b Coefficient_: a model of the \c IntegralDomain concept. + - \b Rational_: a model of the \c Field concept. + Must be assignable to \c Field_with_sqrt_. + - \b HandlePolicy: a model of the \c HandlePolicy concept or the + \c Handle_policy_in_place class template that selects a specialized + implementation without reference counting. Has the + default \c Handle_policy_union. + + THIS CLASS IS CONSIDERED AS EXPERIMENTAL ! +*/ +template < class Coefficient_, + class Rational_, + class HandlePolicy = ::CGAL::Handle_policy_no_union, + class AlgebraicRealRep_d_1 = internal::Algebraic_real_rep< Coefficient_, Rational_ > > +class Algebraic_real_d_1 : + public ::CGAL::Handle_with_policy< AlgebraicRealRep_d_1, HandlePolicy > { + + // currently Rational is the only supported Bound type. + BOOST_STATIC_ASSERT( + ( ::boost::is_same ::Arithmetic_kernel::Rational>::value)); + + + +public : + typedef ::CGAL::Handle_with_policy Base; + typedef Algebraic_real_d_1 Self; + + typedef Coefficient_ Coefficient; + typedef Rational_ Bound; + typedef HandlePolicy Handle_policy; + typedef AlgebraicRealRep_d_1 Algebraic_real_rep_d_1; + typedef typename Algebraic_real_rep_d_1::Polynomial_1 Polynomial_1; + + // These public typedefs should be removed in the long run + // typedef typename Algebraic_real_rep_d_1::Polynomial_1 Polynomial; + typedef Rational_ Rational; + +private: + typedef CGAL::Fraction_traits FT_rational; + typedef typename FT_rational::Numerator_type Integer; +public: + + //! copy constructor: copy existing Algebraic_real_d_1 (shares rep) + Algebraic_real_d_1(const Self& p) : Base(static_cast(p)) {} + + //! creates the algebraic real from \a i. + Algebraic_real_d_1(int i = 0 ) : Base(Algebraic_real_rep_d_1(i)) { } + + //! creates the algebraic real from \a x. + explicit Algebraic_real_d_1(const Rational& x) : Base(Algebraic_real_rep_d_1(x)) { } + + /*! \brief creates the algebraic real as the unique root of \a P + * in the open interval ]low,high[. + * \pre P is square free. + * \pre P is not zero at low + * \pre P is not zero at high + */ + Algebraic_real_d_1(const Polynomial_1& P, Rational low, Rational high) + : Base (Algebraic_real_rep_d_1(P,low,high)) {} + + //! returns the polynomial defining \a x + const Polynomial_1& polynomial() const { return this->ptr()->polynomial(); } + + /*! \brief returns the degree of the polynomial defining \a x + * This is not necessarily the algebraic degree of \a x, since + * the polynomial may be reducible. + */ + int degree() const { + return CGAL::degree(this->ptr()->polynomial()); + } + + //! returns the lower endpoint of the isolating interval + Rational low() const { return this->ptr()->low(); } + Rational lower() const { return this->ptr()->low(); } + + //! returns the upper endpoint of the isolating interval + Rational high() const { return this->ptr()->high(); } + Rational upper() const { return this->ptr()->high(); } + + /*! \brief returns the sign of the defining polynomial + * at the lower endpoint of the isolating interval + */ + int sign_at_low() const { return this->ptr()->sign_at_low(); } + + /*! \brief returns whether a rational representation + * (as Rational) is known. + */ + bool is_rational() const { return this->ptr()->is_rational(); } + + //! returns a rational representation of \a x + /*! \pre: type() == NiX::IS_Rational_IONAL */ + Rational rational() const { + CGAL_precondition(is_rational()); + return this->ptr()->rational(); + } + + //! compute a \c double approximation (without guarantees) + double to_double() const { + return (to_interval().first +to_interval().second)/2; + } + + /*! \brief returns a double Interval approximation, + * it is guaranteed that \a x is contained in the Interval. + * + * This is not the isolating interval. + */ + std::pair to_interval() const { + if( this->ptr()->interval_option ) { + return *(this->ptr()->interval_option); + } else { + typedef typename Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Bigfloat_interval BFI; + long old_precision = get_precision( BFI() ); + set_precision( BFI(), 53 ); + std::pair interval = CGAL::to_interval( convert_to_bfi( (*this))); + this->ptr()->interval_option = boost::optional< std::pair >(interval); + set_precision( BFI(), old_precision ); + return *(this->ptr()->interval_option); + } + } + + /*! \brief Refines the isolating interval. */ + void refine() const{ this->ptr()->refine(); } + + /*! \brief Bisects the isolating interval. */ + void bisect() const{ this->ptr()->bisect(); } + + /*! \brief Refines the isolating interval until \a m is outside + * the \c closed interval + */ + template < class NTX > + void strong_refine(const NTX& m) const{ compare(m); } + + /*! \brief compares \a x with respect to \a y + * It returns CGAL::SMALLER if \a x is smaller than y, + * CGAL::EQUAL if they are equal and CGAL::LARGER otherwise. + */ + template < class NTX > + CGAL::Comparison_result + compare(const NTX& y) const { return intern_compare(y,false); } + + + /*! \brief compares \a x with respect to \a y + * \pre \a x != \a y + */ + template < class NTX > + CGAL::Comparison_result + compare_distinct(const NTX& y) const { return intern_compare(y,true); } + + template + static void conjugate(Algebraic_real_iterator begin, + Algebraic_real_iterator end){ + if(begin == end) return; + + CGAL_precondition(begin->ptr()->next==begin->ptr()); + CGAL_precondition(begin->ptr()->prev==begin->ptr()); + + for(Algebraic_real_iterator it = begin; it != end; ++it){ + CGAL_precondition(it->ptr()->next==it->ptr()); + CGAL_precondition(it->ptr()->prev==it->ptr()); + CGAL_precondition(it->polynomial()==begin->polynomial()); + it->ptr()->next =begin->ptr(); + it->ptr()->prev =begin->ptr()->prev; + begin->ptr()->prev->next=it->ptr(); + begin->ptr()->prev =it->ptr(); + } + } + + +private: + CGAL::Comparison_result + intern_compare(const Self& y, bool distinct) const { + if(distinct) + CGAL_precondition(this->ptr()!=y.ptr()); + else if(this->ptr()==y.ptr()) { + return CGAL::EQUAL; + } + CGAL::Comparison_result result = + this->ptr()->compare(*(y.ptr()), distinct); + if (result == CGAL::EQUAL) { + this->unify(y); + } + return result; + } + + CGAL::Comparison_result + intern_compare(const Rational& y, bool distinct) const { + return this->ptr()->compare(y,distinct); + } + + template < class NTX > + CGAL::Comparison_result + intern_compare(const NTX& y, bool distinct) const { + if(y < NTX(low())) return CGAL::LARGER; + if(NTX(high()) < y ) return CGAL::SMALLER; + + if(!distinct){ + typename Real_embeddable_traits::To_interval to_interval; + if( CGAL::Interval_nt( this->to_interval() ).do_overlap( + CGAL::Interval_nt(to_interval(y)) ) ) { + if(polynomial().sign_at(y)==CGAL::ZERO) + return CGAL::EQUAL; + } + } + + while(NTX(low()) <= y && y <= NTX(high())) { + refine(); + } + if(y < NTX(low())) return CGAL::LARGER; + CGAL_assertion(NTX(high()) < y); return CGAL::SMALLER; + } + +public: + //! returns if y is contained in the \c closed isolating interval + template < class NTX > + bool contains(const NTX& y) const { + return ((NTX(low()) <= y) && (y <= NTX(high()))); + } + + //! return if \a x is a root of Q + bool is_root_of(const Polynomial_1& Q) const {return this->ptr()->is_root_of(Q); } + + /*! \brief returns a rational (Rational) between this number and \c y. + * \pre x != y + */ + Rational rational_between (const Self& y) const{ + CGAL::Comparison_result s = compare(y); + CGAL_precondition(s != CGAL::EQUAL); + if(s == CGAL::SMALLER){ + Rational r((high()+y.low())/Rational(2)); + CGAL::simplify(r); + return r; + }else{ + Rational r((y.high()+low())/Rational(2)); + CGAL::simplify(r); + return r; + } + } + +public: + /*! \brief refines the isolating interval to ]lo, + * hi[. + * + * This function can be used to inform an Algebraic_real_d_1 \a x of an + * externally refined isolating interval. Its arguments must be + * the boundaries of an isolating interval that contains \a x in its + * interior. (Use other functions like \c .strong_refine() in case you + * want to communicate an explicit value.) + */ + void refine_to(const Rational& lo, const Rational& hi) const { + // test whether lo < x < hi + // and refines isolating interval until in ]lo,hi[ + CGAL::Comparison_result s; + s = compare_distinct(lo); CGAL_assertion(CGAL::LARGER == s); + s = compare_distinct(hi) ; CGAL_assertion(CGAL::SMALLER == s); + } + + +public: + template + bool operator==( const NTX& y) const {return compare(y)==CGAL::EQUAL;} + template + bool operator!=( const NTX& y) const {return compare(y)!=CGAL::EQUAL;} + template + bool operator< ( const NTX& y) const {return compare(y)==CGAL::SMALLER;} + template + bool operator> ( const NTX& y) const {return compare(y)==CGAL::LARGER;} + template + bool operator<=( const NTX& y) const {return compare(y)!=CGAL::LARGER;} + template + bool operator>=( const NTX& y) const {return compare(y)!=CGAL::SMALLER;} + + //! unary operator + + const Self& operator+() const { return *this; } + + //! unary operator - + Self operator-() const { + Polynomial_1 P(polynomial()); + P.scale_up(Coefficient(-1)); + Rational high_(-low()); + Rational low_ (-high()); + return Self(P,low_,high_); + } + + //! Simplifies the algebraic number + void simplify() const { + this->ptr()->simplify(); + } + +}; // class Algebraic_real_d_1 + +} // namespace internal + + +//---------------------------------------------------------- + +/*! \ingroup NiX_Algebraic_real_d_1 + * \ingroup NiX_NT_traits_spec + * \brief NT_traits class for NiX::Algebraic_real_d_1, which is a model of the + * RealComparable concept. + * + * NiX::Algebraic_real_d_1 does not support any arithmetic operations, thus they + * are not even a model of the IntegralDomainWithoutDiv concept. \see NiX_NT_Concepts + */ +template< class Coefficient, class Rational, class HandlePolicy, class RepClass > +class Real_embeddable_traits< internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > > + : public INTERN_RET::Real_embeddable_traits_base< internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > , CGAL::Tag_true > { + +public: + + typedef internal::Algebraic_real_d_1< Coefficient, Rational, HandlePolicy, RepClass > Type; + + class Compare + : public std::binary_function< Type, Type, CGAL::Comparison_result > { + public: + CGAL::Comparison_result operator()( const Type& a, const Type& b ) const + { return a.compare( b ); } + CGAL::Comparison_result operator()( int a, const Type& b ) const + { return - b.compare( Rational(a) ); } + CGAL::Comparison_result operator()( const Type& a, int b ) const + { return a.compare( Rational(b) ); } + CGAL::Comparison_result operator()( const Rational& a, const Type& b ) const + { return - b.compare( a ); } + CGAL::Comparison_result operator()( const Type& a, const Rational& b ) const + { return a.compare( b ); } + CGAL::Comparison_result operator()( + const typename First_if_different::Type& a, + const Type& b ) const + { + typename Coercion_traits::Cast cast; + return cast(a).compare(b); + } + CGAL::Comparison_result operator()( + const Type& a, + const typename First_if_different::Type& b ) const + { + typename Coercion_traits::Cast cast; + return a.compare(cast(b)); + } + }; + + class Sgn + : public std::unary_function< Type, CGAL::Sign > { + public: + CGAL::Sign operator()( const Type& a ) const { + return a.compare( Rational(0) ); + } + }; + + class To_double + : public std::unary_function< Type, double > { + public: + double operator()(const Type& a) const { + return a.to_double(); + } + }; + + class To_interval + : public std::unary_function< Type, std::pair > { + public: + typename std::pair operator()(const Type& a) const { + return a.to_interval(); + } + }; +}; + + + +/*! \relates NiX::Algebraic_real_d_1 + * \brief outputs \c x to \c os + */ +template +std::ostream& +operator << (std::ostream& os, + const CGAL::internal::Algebraic_real_d_1& x){ + os << "[" << x.polynomial() + << ",[" << oformat(x.low()) + << " , " << oformat(x.high()) << " ]]"; + return os; +} + +/*! \relates NiX::Algebraic_real_d_1 + * \brief read an NiX::Algebraic_real_d_1 from \c is into \c x. + */ +template +std::istream& +operator >> (std::istream& is, + CGAL::internal::Algebraic_real_d_1& x){ + + typedef CGAL::internal::Algebraic_real_d_1 ALGNUM; + + Rational low, high; + typename CGAL::Polynomial_type_generator::Type poly; + + swallow(is, '[');// read the "[" + is >> poly; + swallow(is, ',');// read the "," + swallow(is, '[');// read the "," + is >> iformat(low); + swallow(is, ',');// read the "," + is >> iformat(high); + swallow(is, ']');// read the "]" + swallow(is, ']');// read the "]" + x = ALGNUM(poly, low, high); + return is; +} + +template +typename Get_arithmetic_kernel::Arithmetic_kernel::Bigfloat_interval +inline +convert_to_bfi(const internal::Algebraic_real_d_1< Coefficient_, Rational_, HandlePolicy, AlgebraicRealRep_d_1 >& x){ + typedef typename Get_arithmetic_kernel::Arithmetic_kernel AT; + typedef typename AT::Bigfloat_interval BFI; + typedef internal::Algebraic_real_d_1< Coefficient_, Rational_, HandlePolicy, AlgebraicRealRep_d_1 > ALG; + + if (x.is_rational()) return convert_to_bfi(x.rational()); + + if(CGAL::sign(x) == CGAL::ZERO) return (BFI(0)); + + CGAL_postcondition(CGAL::sign(x.low()) == CGAL::sign(x.high())); + long final_prec = set_precision( BFI(),get_precision( BFI())+4); + + BFI bfi = CGAL::hull(convert_to_bfi(x.low()), convert_to_bfi(x.high())); + + while( !singleton(bfi) && get_significant_bits(bfi) < final_prec ){ + x.refine(); + bfi = CGAL::hull( + convert_to_bfi(x.low()), + convert_to_bfi(x.high())); + } + + set_precision(BFI(),final_prec); + return bfi; +} + + +template +struct Get_arithmetic_kernel >{ + + typedef typename Get_arithmetic_kernel::Arithmetic_kernel + Arithmetic_kernel; + +}; + +template +inline CGAL::internal::Algebraic_real_d_1 +min BOOST_PREVENT_MACRO_SUBSTITUTION( + const CGAL::internal::Algebraic_real_d_1& x, + const CGAL::internal::Algebraic_real_d_1& y){ + return (x<=y)?x:y; +} +template +inline CGAL::internal::Algebraic_real_d_1 +max BOOST_PREVENT_MACRO_SUBSTITUTION( + const CGAL::internal::Algebraic_real_d_1& x, + const CGAL::internal::Algebraic_real_d_1& y){ + return (x>=y)?x:y; +} + +template +struct Coercion_traits >{ + typedef internal::Algebraic_real_d_1 Type; + typedef Tag_true Are_explicit_interoperable; + typedef Tag_false Are_implicit_interoperable; + struct Cast{ + typedef Type result_type; + Type operator()(const Type& x) const { return x; } + Type operator()(const int& x) const { return Type(x); } + }; +}; + +template +struct Coercion_traits,int > + :public Coercion_traits >{}; + + +template +struct Coercion_traits >{ + typedef internal::Algebraic_real_d_1 Type; + typedef Tag_true Are_explicit_interoperable; + typedef Tag_false Are_implicit_interoperable; + struct Cast{ + typedef Type result_type; + Type operator()(const Type& x) const { return x; } + Type operator()(const Rational& x) const { return Type(x); } + }; +}; + +template +struct Coercion_traits, Rational > + :public Coercion_traits >{}; + + +template +struct Coercion_traits< + typename First_if_different::Type, + internal::Algebraic_real_d_1 > +{ + typedef internal::Algebraic_real_d_1 Type; + typedef Tag_true Are_explicit_interoperable; + typedef Tag_false Are_implicit_interoperable; + typedef Coercion_traits CTCR; + struct Cast{ + private: + Type operator()(const Coefficient& a, Tag_true) const { + return Type(typename CTCR::Cast()(a)); + } + Type operator()(const Coefficient& a, Tag_false) const { + typedef typename Type::Polynomial_1 Poly; + typedef CGAL::Polynomial_traits_d PT; + Poly p = typename PT::Shift()(Poly(1),1) - a ; // (x-a) + Rational b(2); + Coefficient aa = CGAL::abs(a); + while( CGAL::compare(b,aa) != LARGER ){b*=2;}; + return Type(p,-b,b); + } + public: + typedef Type result_type; + Type operator()(const Type& a) const { return a; } + Type operator()(const Coefficient& a) const { + static const bool b = boost::is_same::value; + return (*this)(a,Boolean_tag()); + } + }; +}; + +template +struct Coercion_traits< + internal::Algebraic_real_d_1, + typename First_if_different::Type> + :public Coercion_traits >{}; + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_PURE_H + +// EOF diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_quadratic_refinement_rep_bfi.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_quadratic_refinement_rep_bfi.h new file mode 100644 index 00000000000..b0289add0a1 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_quadratic_refinement_rep_bfi.h @@ -0,0 +1,507 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// Michael Kerber +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#ifndef CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_BFI_H +#define CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_BFI_H + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +namespace CGAL { + +namespace internal { + +// definition of the Algebraic_real_rep x: + +//For details about the method, see +/* + * @Unpublished{abbott-quadratic, + * author = {John Abbott}, + * title = {Quadratic Interval Refinement for Real Roots}, + * url = {http://www.dima.unige.it/~abbott/}, + * note = {Poster presented at the 2006 Internat. Sympos. on Symbolic + and Algebraic Computation (ISSAC 2006)} + * } + */ + +template< class Coefficient_, class Field_> +class Algebraic_real_quadratic_refinement_rep_bfi + : public Algebraic_real_rep { + + typedef Coefficient_ Coefficient; + typedef Field_ Field; + + typedef typename + CGAL::Get_arithmetic_kernel::Arithmetic_kernel:: + Bigfloat_interval BFI; + + typedef typename CGAL::Bigfloat_interval_traits::Bound BF; + + // This is a implicit restriction - Field must be some type + // modelling rational numbers to get an integer type + typedef typename CGAL::Fraction_traits::Numerator_type Integer; + + typedef typename + CGAL::Polynomial_type_generator::Type Poly; + + typedef Algebraic_real_rep Base; + typedef Algebraic_real_quadratic_refinement_rep_bfi + Self; + + typedef typename CGAL::Coercion_traits::Type + Eval_result_type; + +private: + + mutable long prec_; + + typedef typename + CGAL::Polynomial_traits_d::template Rebind + ::Other::Type BFI_polynomial; + + mutable boost::optional + < BFI_polynomial > f_bfi_; + + mutable boost::optional low_bfi_, f_low_bfi_, + high_bfi_, f_high_bfi_; + + mutable long N; + + // TODO: replace by call of Coercion_traits::Cast() + BFI_polynomial _convert_polynomial_to_bfi(const Poly& f) const { + std::vector coeffs; + for(int i = 0; i <= CGAL::degree(f); i++) { + coeffs.push_back(CGAL::convert_to_bfi(f[i])); + } + return BFI_polynomial(coeffs.begin(), coeffs.end()); + } + + void _set_prec(long new_prec) const { + + prec_ = new_prec; + CGAL::set_precision(BFI(), prec_); + + f_bfi_ = _convert_polynomial_to_bfi(this->polynomial()); + + low_bfi_ = CGAL::convert_to_bfi(this->low()); + + high_bfi_ = CGAL::convert_to_bfi(this->high()); + f_low_bfi_ = f_bfi_.get().evaluate(low_bfi_.get()); + f_high_bfi_ = f_bfi_.get().evaluate(high_bfi_.get()); + + } + + CGAL::Sign _sign_at(Field m, BFI& m_bfi, BFI& f_m_bfi) const { + + if(! f_bfi_) { + f_bfi_ = _convert_polynomial_to_bfi(this->polynomial()); + } + + m_bfi = CGAL::convert_to_bfi(m); + f_m_bfi = f_bfi_.get().evaluate(m_bfi); + + if(CGAL::zero_in(f_m_bfi)) { + + // Okay, compute exactly + return CGAL::sign(this->polynomial().evaluate(m)); + } + + // If we are here, then the interval is away from zero + + return CGAL::sign(CGAL::upper(f_m_bfi)); + + } + + +private: + // Stores whether the last bisection has taken the upper or lower part + mutable bool last_bisect_lower; + +public: + //! creates the algebraic real from int \a i. + explicit Algebraic_real_quadratic_refinement_rep_bfi(int i = 0) + : Base(i),N(2){ + } + //! creates the algebraic real from Field \a m. + explicit Algebraic_real_quadratic_refinement_rep_bfi(const Field& m) + : Base(m),N(2) { + } + /*! \brief creates the algebraic real as the unique root of \a P + in the open interval ]low,high[. + \pre the polynomial \a P is square free + \pre P(low)!=0 + \pre P(high)<0 + \pre x is the one and only root in the open interval of \a P. + */ + Algebraic_real_quadratic_refinement_rep_bfi(const Poly& P, + Field LOW, + Field HIGH) + : Base(P,LOW,HIGH), + N(2) + { + _set_prec(16); + + } + + //! copy constructor + Algebraic_real_quadratic_refinement_rep_bfi(const Self& y) + : Base(y), prec_(y.prec_), f_bfi_(y.f_bfi_), low_bfi_(y.low_bfi_), + f_low_bfi_(y.f_low_bfi_), high_bfi_(y.high_bfi_), + f_high_bfi_(y.f_high_bfi_), N(y.N) + { + } + + // assignment + Algebraic_real_quadratic_refinement_rep_bfi& operator=(const Self& y) { + Base::operator=(y); + f_low_bfi_=y.f_low_bfi_; + f_high_bfi_=y.f_high_bfi_; + low_bfi_=y.low_bfi_; + high_bfi_=y.high_bfi_; + f_bfi_=y.f_bfi_; + N=y.N; + return *this; + } + +public: + + virtual void bisect() const{ + + if(this->is_rational()) return; + + Field m = (this->low_+this->high_)/Field(2); + + CGAL::simplify(m); + BFI m_bfi, f_m_bfi; + CGAL::Sign s = _sign_at(m,m_bfi,f_m_bfi); + + if (s == ::CGAL::ZERO ) { + this->learn_from(m); + } + else { + if ( s == this->sign_at_low() ) { + this->low_ = m; + low_bfi_ = m_bfi; + f_low_bfi_ = f_m_bfi; + last_bisect_lower=false; + } else { + this->high_ = m; + high_bfi_ = m_bfi; + f_high_bfi_ = f_m_bfi; + last_bisect_lower=true; + } + } + + } + +protected: + virtual void set_implicit_rep(const Poly & P, + const Field& LOW, + const Field& HIGH, + bool dummy_bool=false) const { + + bool poly_changed = (P!=this->polynomial()); + if(poly_changed) { + f_bfi_ = boost::none; + } + if(poly_changed || LOW != this->low()) { + f_low_bfi_ = low_bfi_ = boost::none; + } + if(poly_changed || HIGH != this->high()) { + f_high_bfi_ = high_bfi_ = boost::none; + } + Base::set_implicit_rep(P,LOW,HIGH,dummy_bool); + } + + virtual void set_explicit_rep(const Field& m) const { + f_bfi_ = boost::none; + f_low_bfi_ = low_bfi_ = boost::none; + f_high_bfi_ = high_bfi_ = boost::none; + Base::set_explicit_rep(m); + } + + +public: + virtual void refine_at(const Field& m) const{ + Field old_low_=this->low_, old_high_=this->high_; + Poly old_pol = this->polynomial(); + Base::refine_at(m); + if(this->is_rational()) return; + + if(old_low_!=this->low_) { + f_low_bfi_ = low_bfi_ = boost::none; + } + if(old_high_!=this->high_) { + f_high_bfi_ = high_bfi_ = boost::none; + } + if(old_pol != this->polynomial()) { + f_bfi_ = boost::none; + } + } + + // Abbott's refinement method + virtual void refine() const { + + if(this->is_rational()) { + return; + } + + CGAL_assertion(this->low() != this->high()); + + long old_prec = CGAL::get_precision(BFI()); + + CGAL::set_precision(BFI(),prec_); + + CGAL_assertion(CGAL::sign(this->polynomial().evaluate(this->low())) + ==this->sign_at_low_); + + CGAL_assertion( this->sign_at_low_ != + CGAL::sign(this->polynomial().evaluate(this->high())) ); + + CGAL_assertion(this->low() != this->high()); + + Integer i = find_interval(); + + while(N!=1 && !refine_by_factor(i)) { + N/=2; + i = find_interval(); + } + N*=2; + + CGAL::set_precision(BFI(),old_prec); + + } + +private: + + + std::pair _to_integer_interval(BFI z, long N) const { + + Integer i_low, i_high; + + //typename CGAL::internal::Real_embeddable_extension::Floor floor; + //typename CGAL::internal::Real_embeddable_extension::Ceil ceil; + typename CGAL::internal::Float_traits::Mul_by_pow_of_2 mul_2; + + BF z_low=CGAL::lower(z), z_high = CGAL::upper(z); + + i_low = CGAL::internal::floor(mul_2(CGAL::lower(z),N)); + i_high = CGAL::internal::ceil(mul_2(CGAL::upper(z),N)); + + return std::make_pair(i_low,i_high); + + } + + Integer find_interval() const { + + if(! f_bfi_) { + f_bfi_ = _convert_polynomial_to_bfi(this->polynomial()); + } + + if(! low_bfi_) { + low_bfi_ = CGAL::convert_to_bfi(this->low()); + } + if(! f_low_bfi_) { + f_low_bfi_ = f_bfi_.get().evaluate(low_bfi_.get()); + } + if(! high_bfi_) { + high_bfi_ = CGAL::convert_to_bfi(this->high()); + } + if(! f_high_bfi_) { + f_high_bfi_ = f_bfi_.get().evaluate(high_bfi_.get()); + } + Integer i; + while(true) { + + if(CGAL::zero_in(f_low_bfi_.get() - f_high_bfi_.get())) { + _set_prec(2*prec_); + continue; + } + + BFI denom = f_low_bfi_.get()-f_high_bfi_.get(); + + BFI z = f_low_bfi_.get() / denom; + + std::pair int_pair = _to_integer_interval(z,N); + Integer i_low = int_pair.first; + Integer i_high = int_pair.second; + + if(CGAL::abs(i_high-i_low) <= 2) { + i = CGAL::abs((i_high+i_low))/2; + break; + } + _set_prec(2*prec_); + + } + + CGAL_postcondition(i>=0 && + i <= CGAL::ipower(Integer(2),N)); + + return i; + } + + bool refine_by_factor(Integer i) const { + + if(N==2) { + bool refined = refine_by_factor_4(i); + return refined; + } + bool refined = refine_by_factor_greater_4(i); + return refined; + } + + bool refine_by_factor_4(Integer i) const { + Integer actual_i; + bisect(); + actual_i=last_bisect_lower ? 0 : 2; + bisect(); + if(! last_bisect_lower) { + actual_i = actual_i+1; + } + return this->is_rational() || actual_i==i; + } + + bool refine_by_factor_greater_4(Integer i) const { + Integer intervals = CGAL::ipower(Integer(2),N); + Field step = (this->high_-this->low_)/Field(intervals); + CGAL::simplify(step); + Field m + = this->low_ + step*Field(i); + CGAL::simplify(m); + BFI m_bfi, f_m_bfi; + CGAL::Sign s_m = _sign_at(m,m_bfi,f_m_bfi); + if(s_m==CGAL::ZERO) { + this->learn_from(m); + return true; + } + Field new_left, new_right; + BFI new_left_bfi, new_right_bfi, f_new_left_bfi, f_new_right_bfi; + CGAL::Sign s_new_left, s_new_right; + if(s_m == this->sign_at_low_) { + // Go to the right + new_left=m; + new_left_bfi = m_bfi; + f_new_left_bfi = f_m_bfi; + s_new_left = s_m; + + new_right = m+step; + CGAL::simplify(new_right); + s_new_right = _sign_at(new_right,new_right_bfi,f_new_right_bfi); + if(s_new_right==CGAL::ZERO) { + this->learn_from(new_right); + return true; + } + } else { + // Go to the left + new_right=m; + new_right_bfi = m_bfi; + f_new_right_bfi = f_m_bfi; + s_new_right=s_m; + new_left = m-step; + CGAL::simplify(new_left); + s_new_left = _sign_at(new_left,new_left_bfi,f_new_left_bfi); + if(s_new_left==CGAL::ZERO) { + this->learn_from(new_left); + return true; + } + } + if(s_new_left != s_new_right) { + this->low_=new_left; + this->high_=new_right; + low_bfi_ = new_left_bfi; + high_bfi_ = new_right_bfi; + f_low_bfi_ = f_new_left_bfi; + f_high_bfi_ = f_new_right_bfi; + this->sign_at_low_=s_new_left; + return true; + } + else { + return false; + } + } + +protected: + virtual CGAL::Sign sign_of_polynomial_at( const Field& f ) const { + //return polynomial().sign_at( f ); + + Field m = f; + CGAL::simplify(m); + + if(! f_bfi_) { + f_bfi_ = _convert_polynomial_to_bfi(this->polynomial()); + } + + BFI eval = f_bfi_.get().evaluate(convert_to_bfi(m)); + + CGAL::Sign s = CGAL::sign(CGAL::lower(eval)); + + // correct sign if needed + if( s*CGAL::sign(CGAL::upper(eval) ) != CGAL::POSITIVE ){ + + //std::cout << "APPROX FAILED-------------------------------"<polynomial().sign_at(m); + if ( s != CGAL::ZERO ) { + _set_prec(2*prec_); + } + } + + + CGAL_postcondition(s == this->polynomial_.sign_at(m)); + + if ( s == CGAL::ZERO ) { + this->learn_from(m); + }else{ + if ( s == this->sign_at_low() ) this->low_ = m; + else this->high_ = m; + } + + return s; + } + +public: + virtual void simplify() const { + Poly f_old = this->polynomial(); + Base::simplify(); + if(f_old != this->polynomial()) { + f_bfi_ = boost::none; + } + } +}; +} // namepace internal + +} //namespace CGAL + +#endif //CGAL_ALGEBRAIC_REAL_QUADRATIC_REFINEMENT_REP_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep.h new file mode 100644 index 00000000000..21c8cd7e3e6 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep.h @@ -0,0 +1,526 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H +#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H + +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +// definition of the Algebraic_real_rep x: + +//IS_GENERAL: +// low_ lower bound of x +// high_ upper bound of x +// polynomial_ a square free polynomial +// sign_at_low_ = polynomial_.evaluate(low_) +// x is the only root of polynomial_ in the open interval ]low_,high_[ +// low_ != x != high +// ******************* EXEPTION ******************* +// x is rational: in this case low=high=x + +template< class Coefficient_, class Rational_> +class Algebraic_real_rep{ + +public: + typedef Coefficient_ Coefficient; + typedef Rational_ Bound; + typedef typename CGAL::Polynomial_type_generator::Type Polynomial_1; + +private: + typedef Rational_ Rational; + typedef typename CGAL::Polynomial_type_generator::Type Poly; + typedef CGAL::Sign TRI_BOOL; + + typedef Algebraic_real_rep Self; +public: + typedef boost::optional< std::pair > Interval_option; + + mutable Poly polynomial_; //!< square free polynomial + mutable Rational low_; //!< lower endpoint of interval + mutable Rational high_; //!< upper endpoint of interval + mutable CGAL::Sign sign_at_low_; //!< sign of polynomial a \a low_ + mutable Interval_option interval_option; + mutable bool is_rational_; + + mutable const Self *next; + mutable const Self *prev; +private: + void copy_all_members(const Algebraic_real_rep& y) const { + polynomial_ = y.polynomial_; + low_ = y.low_; + high_ = y.high_; + sign_at_low_ = y.sign_at_low_; + interval_option = y.interval_option; + is_rational_ = y.is_rational_; + } + + +protected: + virtual CGAL::Sign sign_of_polynomial_at( const Rational& f ) const { + return polynomial().sign_at( f ); + } + +protected: + // joins the two lists of related algebraic reals + void introduce(const Algebraic_real_rep& y) const{ + y.prev->next=next; + next->prev=y.prev; + next=&y; + y.prev=this; + } +protected: + + // x leaves the list of related algebraic reals + void erase_from_list() const { + next->prev=prev; + prev->next=next; + next=prev=this; + } +protected: + virtual void set_explicit_rep(const Rational& m) const { + + typename Fraction_traits::Decompose decomp; + typename Fraction_traits::Numerator_type num; + typename Fraction_traits::Denominator_type den; + decomp(m, num, den); + + polynomial_ = Poly(-Coefficient(num),Coefficient(den)); + is_rational_ = true; + low_ = m; + high_ = m; + sign_at_low_= CGAL::ZERO; + interval_option = Interval_option(CGAL::to_interval(m)); + } +protected: + virtual void set_implicit_rep(const Poly & P, + const Rational& LOW, + const Rational& HIGH, + bool use_expensive_sign = false ) const { + + CGAL_precondition(LOW < HIGH); + CGAL_precondition(P.sign_at(LOW) != CGAL::ZERO); + CGAL_precondition(P.sign_at(HIGH) != CGAL::ZERO); + CGAL_precondition(P.sign_at(HIGH) != P.sign_at(LOW)); + CGAL_precondition_msg(typename CGAL::Polynomial_traits_d< Poly >::Is_square_free()(P), "Polynomial not square-free."); + + polynomial_ = P; + low_=LOW; + high_=HIGH; + sign_at_low_=(use_expensive_sign ? P.sign_at(LOW) : sign_of_polynomial_at(LOW) ); + + is_rational_=false; + + // interval_option left out + + // trys to set rational if degree is 1 + typedef typename CGAL::Coercion_traits< Coefficient, Rational >::Type RET; + set_rational(RET()); + } +private: + template < class NTX > + void set_rational(NTX) const { + } + + void set_rational(Rational) const { + if (CGAL::degree(polynomial()) == 1) { + low_ = high_ = -Rational(polynomial()[0])/Rational(polynomial()[1]); + is_rational_ = true; + interval_option = Interval_option(CGAL::to_interval(rational())); + } + } + + +public: + //! creates the algebraic real from int \a i. + explicit Algebraic_real_rep(int i = 0){ + next=prev=this; + set_explicit_rep(i); + } + //! creates the algebraic real from Rational \a m. + explicit Algebraic_real_rep(const Rational& m){ + next=prev=this; + set_explicit_rep(m); + } + /*! \brief creates the algebraic real as the unique root of \a P + in the open interval ]low,high[. + \pre the polynomial \a P is square free + \pre P(low)!=0 + \pre P(high)<0 + \pre x is the one and only root in the open interval of \a P. + */ + Algebraic_real_rep(const Poly& P, Rational LOW, Rational HIGH) { + if (LOW == HIGH) { + CGAL_precondition(P.sign_at(LOW) == CGAL::ZERO); + set_explicit_rep(LOW); + } else { + CGAL_precondition(LOW < HIGH); + CGAL_precondition(P.sign_at(LOW) != CGAL::ZERO); + CGAL_precondition(P.sign_at(HIGH) != CGAL::ZERO); + CGAL_precondition(P.sign_at(HIGH) != P.sign_at(LOW)); + CGAL_precondition_msg(typename CGAL::Polynomial_traits_d::Is_square_free()(P), "Polynomial not square-free."); + set_implicit_rep(P,LOW,HIGH); + } + next=prev=this; + } + + //! copy constructor + Algebraic_real_rep(const Self& y){ + next=prev=this; + copy_all_members(y); + introduce(y); + } + //! destructor + virtual ~Algebraic_real_rep(){ + erase_from_list(); + } + + // assignment + Algebraic_real_rep& operator=(const Self& y) { + if ( this != & y) { + erase_from_list(); + copy_all_members(y); + introduce(y); + } + CGAL_expensive_postcondition(self_test()); + return *this; + } + +public: + const Rational& low() const {return low_;} + const Rational& high() const {return high_;} + const Poly& polynomial() const {return polynomial_;} + + const TRI_BOOL& sign_at_low() const {return sign_at_low_;} + + /*const std::pair< double, double>& interval() const { + if( interval_option ) { + return *interval_option; + } else { + typedef typename Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Bigfloat BF; + //typedef typename LEDA_arithmetic_kernel::Bigfloat BF; + long old_precision = get_precision( BF() ); + set_precision( BF(), 53 ); + interval_option = Interval_option( internal::to_interval( convert_to_bfi( (*this) ) ) ); + set_precision( BF(), old_precision ); + return *interval_option; + } + }*/ + /*const std::pair& interval() const { + if(interval_option){ + return *interval_option; + }else{ + interval_option = Interval_option( + compute_interval_approximation(polynomial(),low(),high())); + return *interval_option; + } + }*/ + bool is_rational() const {return is_rational_;} + const Rational& rational() const { + CGAL_precondition(is_rational()); + CGAL_precondition(low()==high()); + CGAL_precondition(polynomial().sign_at(low())==CGAL::ZERO); + return low_; + } + + /*! \brief convert algebraic real to type double */ + /*double to_double() const { + return (to_interval().first +to_interval().second)/2; + }*/ + + /*! \brief convert algebraic real to type Interval */ + /*std::pair to_interval() const { + + CGAL_precondition(compare(Rational(interval().first)) != CGAL::SMALLER); + CGAL_precondition(compare(Rational(interval().second)) != CGAL::LARGER); + return interval(); + }*/ + +private: + bool self_test() const{ + if(!is_rational()){ + CGAL_precondition(low() + void strong_refine(const NTX& m) const{ + + if(is_rational()) return; + + if( NTX(low()) <= m && m <= NTX(high()) ){ + CGAL_precondition(polynomial().sign_at(m)!=CGAL::ZERO); + refine(); + while( NTX(low()) <= m && m <= NTX(high())) refine(); + } + } +public: + virtual void refine_at(const Rational& m) const{ + if(is_rational()) return; + if( m <= low() || high() <= m ) return; + + // now: low < m < high + CGAL::Sign s = sign_of_polynomial_at(m); + if(s == CGAL::ZERO) learn_from(m); + else (s == sign_at_low())? low_ = m : high_=m; + } + +public: + CGAL::Comparison_result + compare(const Rational& y, bool are_distinct = false) const { + if(is_rational()) return CGAL::compare(rational(),y); + if(y <= low()) { + strong_refine(y); + return CGAL::LARGER; + } + if(high() <= y) { + strong_refine(y); + return CGAL::SMALLER; + } + + // now: low < y < high + if(!are_distinct){ + if(sign_of_polynomial_at(y)==CGAL::ZERO){ + learn_from(y); + return CGAL::EQUAL ; + } + }else{ + CGAL_precondition(polynomial().sign_at(y)!=CGAL::ZERO); + } + strong_refine(y); + CGAL_postcondition(y < low() || high() < y ); + if(y < low()) return CGAL::LARGER; + else return CGAL::SMALLER; + } + + CGAL::Comparison_result + compare (const Algebraic_real_rep& y, bool are_distinct = false) const{ + if( is_rational()) return -y.compare( rational()); + if(y.is_rational()) return compare(y.rational()); + + // type of both x and y IS_GENERAL + if ( high() <= y.low() ) return CGAL::SMALLER; + if ( low() >= y.high()) return CGAL::LARGER; + + // intersection isolating intervals is ]L,R[ + Rational L = (low() > y.low() ) ? low() : y.low() ; + Rational R = (high() < y.high()) ? high() : y.high() ; + + // refine to smaller intervals at intersection interval boundaries + // this can change type() only to IS_RATIONAL + refine_at(L); + refine_at(R); + y.refine_at(L); + y.refine_at(R); + + if ( is_rational()) return -y.compare( rational()); + if (y.is_rational()) return compare(y.rational()); + + // type of both x and y still IS_GENERAL + if ( high() <= y.low() ) return CGAL::SMALLER; + if ( y.high() <= low() ) return CGAL::LARGER; + + // filter 2: probabilistically check coprimality + if (!are_distinct) { + are_distinct = !(may_have_common_factor(polynomial(), + y.polynomial())); + } + if (!are_distinct) { + // OK, filters failed. So we have to do the actual work + // and compute the gcd of the defining polynomials. + + // we have ]low(), high()[ == ]y.low(),y.high()[ == ]L,R[ + // and let both numbers decide for the gcd or its complement + Poly F1,F2,G; + G = gcd_utcf(polynomial(),y.polynomial()); + F1 = integral_division_up_to_constant_factor(polynomial(),G); + CGAL_postcondition(CGAL::degree(F1)== + CGAL::degree(polynomial())-CGAL::degree(G)); + F2 = integral_division_up_to_constant_factor(y.polynomial(),G); + CGAL_postcondition(CGAL::degree(F2)== + CGAL::degree(y.polynomial())-CGAL::degree(G)); + + learn_from(G,F1); + y.learn_from(G,F2); + + // this may simplify them due to degree loss + if (y.is_rational()) return compare(y.rational()); + if ( is_rational()) return -y.compare( rational()); + + // type of x and y is still IS_GENERAL + // check for equality + if (G.sign_at(L)!=G.sign_at(R)){ + introduce(y); + return CGAL::EQUAL; + } + } + + // if we are here, we know the numbers to be distinct + // refine to disjointness + for (;;) { + y.refine(); + refine(); + if (y.is_rational()) return compare(y.rational()); + if ( is_rational()) return -y.compare( rational()); + if ( high() <= y.low()) return CGAL::SMALLER; + if (y.high() <= low()) return CGAL::LARGER; + } + } + +protected: + void learn_from(const Rational& m) const { + if(is_rational()){ + CGAL_precondition(rational()==m); + return; + } + CGAL_precondition(polynomial().sign_at(m)==CGAL::ZERO); + typename Fraction_traits::Decompose decomp; + typename Fraction_traits::Numerator_type num; + typename Fraction_traits::Denominator_type den; + decomp(m, num, den); + Poly G = Poly(-Coefficient(num),Coefficient(den)); + Poly F1= integral_division_up_to_constant_factor(polynomial(),G); + CGAL_postcondition(CGAL::degree(F1)== + CGAL::degree(polynomial())-CGAL::degree(G)); + + learn_from(G,F1); + + if(!is_rational()) set_explicit_rep(m); + } + + // splits the list of related algebraic reals according to the two + // factors of the polynomial + void learn_from(const Poly& pfactor1, + const Poly& pfactor2) const { + if(CGAL::degree(pfactor1)==0) return; + if(CGAL::degree(pfactor2)==0) return; + + CGAL_precondition(may_have_common_factor(polynomial(),pfactor1)); + CGAL_precondition(may_have_common_factor(polynomial(),pfactor2)); + CGAL_precondition(CGAL::degree(pfactor1)+CGAL::degree(pfactor2) + == CGAL::degree(polynomial())); + + + + Self dummy1, dummy2; + Self const *last=prev; + Self const *current=this; + Self const *next; + while(true){ + next=current->next; + + if(pfactor1.sign_at(current->low())!= + pfactor1.sign_at(current->high())){ + current->next=&dummy1; + current->prev=dummy1.prev; + dummy1.prev->next=current; + dummy1.prev=current; + current->set_implicit_rep(pfactor1, + current->low(), + current->high(), true ); + }else{ + current->next=&dummy2; + current->prev=dummy2.prev; + dummy2.prev->next=current; + dummy2.prev=current; + current->set_implicit_rep(pfactor2, + current->low(), + current->high(), true ); + } + + if(current==last) break; + current=next; + } + } + +public: + bool is_root_of(const Poly& Q) const { + if (CGAL::degree(Q) == 0) return Q.is_zero(); + if (is_rational() ) return CGAL::ZERO == Q.sign_at(rational()); + + if ( may_have_common_factor(polynomial(), Q) ) { + Poly G = gcd_utcf(polynomial(),Q); + if(CGAL::degree(G)!=0){ + Poly F1 = integral_division_up_to_constant_factor( + polynomial(),G + ); + CGAL_postcondition(CGAL::degree(F1)== + CGAL::degree(polynomial())-CGAL::degree(G)); + learn_from(G,F1); + return (G.sign_at(low()) != G.sign_at(high())); + } + } + return false; + } +public: + virtual void simplify() const{ + if(is_rational()){ + + }else{ + CGAL::simplify(low_); + CGAL::simplify(high_); + polynomial_ = typename Polynomial_traits_d::Canonicalize()(polynomial_); + } + } +}; +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep_bfi.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep_bfi.h new file mode 100644 index 00000000000..ba24a2f65e7 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Algebraic_real_rep_bfi.h @@ -0,0 +1,426 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +// This is code is expreimental ! + +/*! \file NiX/Algebraic_real_rep_bfi.h + \brief Algebraic_real_rep with refinement via interval rep +*/ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H +#define CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H + +#include +#include +#include +#include +#include +#include +#include + + +namespace CGAL { + +template struct Get_arithmetic_kernel; + +// it would be nice to remove the explicit use of Sqrt_extension +// in this file. However, it is much more efficient to convert the root +// only once. see convert_to_bfi +template class Sqrt_extension; + +namespace internal { + +// definition of the Algebraic_real_rep_bfi x: + +//IS_GENERAL: +// low_ lower bound of x +// high_ upper bound of x +// polynomial_ a square free polynomial +// sign_at_low_ = polynomial_.evaluate(low_) +// x is the only root of polynomial_ in the open interval ]low_,high_[ +// low_ != x != high +// ******************* EXEPTION ******************* +// x is rational: in this case low=high=x + + +template< class Coefficient_, class Field_> +class Algebraic_real_rep_bfi + : public Algebraic_real_rep { + + typedef Algebraic_real_rep Base; + + typedef Coefficient_ Coefficient; + typedef Field_ Field; + + typedef typename CGAL::Get_arithmetic_kernel::Arithmetic_kernel AT; + typedef typename AT::Bigfloat BF; + typedef typename AT::Bigfloat_interval BFI; + typedef typename AT::Field_with_sqrt FWS; + + typedef typename CGAL::Polynomial_type_generator::Type Poly; + typedef typename Poly::const_iterator PIterator; + + typedef Algebraic_real_rep_bfi Self; + + mutable std::vector polynomial_approx; + mutable long current_prec; + +private: + template + inline + void convert_coeffs(const Polynomial_1& poly, OI it) const { + typename CGAL::Polynomial_traits_d::Get_coefficient + coeff; + for(int i = 0; i <= CGAL::degree(poly); i++){ + *it++ = convert_to_bfi(coeff(poly,i)); + } + } + + template + inline + void + convert_coeffs( + const CGAL::Polynomial< CGAL::Sqrt_extension >& poly, + OI it ) const { + + BFI root(0); + for(int i = 0; i <= CGAL::degree(poly); i++){ + if(poly[i].is_extended()){ +// typename Coercion_traits::Cast cast_root; +// root = convert_to_bfi(NiX::sqrt(cast_root(poly[i].root()))); + root = CGAL::sqrt(convert_to_bfi(poly[i].root())); + break; + } + } + + for(int i = 0; i <= CGAL::degree(poly); i++){ + if(poly[i].is_extended()){ + *it++ = + convert_to_bfi(poly[i].a0()) + + convert_to_bfi(poly[i].a1()) * root ; + }else{ + *it++ = convert_to_bfi(poly[i].a0()); + } + } + } + + typedef CGAL::Sign TRI_BOOL; + +public: + const Field& low() const {return this->low_;} + const Field& high() const {return this->high_;} + const Poly& polynomial() const {return this->polynomial_;} + const TRI_BOOL& sign_at_low() const {return this->sign_at_low_;} + + template + void strong_refine(const NTX& m) const{ + if(is_rational()) return; + + if( NTX(low()) <= m && m <= NTX(high()) ){ + CGAL_precondition(polynomial().sign_at(m)!=CGAL::ZERO); + refine(); + while( NTX(low()) <= m && m <= NTX(high())) refine(); + } + } + + bool is_rational() const {return this->is_rational_;} + const Field& rational() const { + CGAL_precondition(is_rational()); + CGAL_precondition(low()==high()); + CGAL_precondition(polynomial().sign_at(low())==CGAL::ZERO); + return this->low_; + } + + CGAL::Comparison_result + compare(const Field& y, bool are_distinct = false) const { + if(is_rational()) return CGAL::compare(rational(),y); + if(y <= low()) { + strong_refine(y); + return CGAL::LARGER; + } + if(high() <= y) { + strong_refine(y); + return CGAL::SMALLER; + } + + // now: low < y < high + if(!are_distinct){ + if(sign_of_polynomial_at(y)==CGAL::ZERO){ + this->learn_from(y); + return CGAL::EQUAL ; + } + }else{ + CGAL_precondition(polynomial().sign_at(y)!=CGAL::ZERO); + } + strong_refine(y); + CGAL_postcondition(y < low() || high() < y ); + if(y < low()) return CGAL::LARGER; + else return CGAL::SMALLER; + } + + CGAL::Comparison_result + compare (const Algebraic_real_rep_bfi& y, bool are_distinct = false) const{ + if( is_rational()) return -y.compare( rational()); + if(y.is_rational()) return compare(y.rational()); + + // type of both x and y IS_GENERAL + if ( high() <= y.low() ) return CGAL::SMALLER; + if ( low() >= y.high()) return CGAL::LARGER; + + // intersection isolating intervals is ]L,R[ + Field L = (low() > y.low() ) ? low() : y.low() ; + Field R = (high() < y.high()) ? high() : y.high() ; + + // refine to smaller intervals at intersection interval boundaries + // this can change type() only to IS_RATIONAL + this->refine_at(L); + this->refine_at(R); + y.refine_at(L); + y.refine_at(R); + + if ( is_rational()) return -y.compare( rational()); + if (y.is_rational()) return compare(y.rational()); + + // type of both x and y still IS_GENERAL + if ( high() <= y.low() ) return CGAL::SMALLER; + if ( y.high() <= low() ) return CGAL::LARGER; + + // filter 1 (optional): determine distinctness by refining intervals +#if NiX_REFINEMENTS_BEFORE_GCD > 0 + if (!are_distinct) { + // we may want to refine a bit and hope for the best + // because computing the gcd is expensive + for (int ntries=0; ntries < NiX_REFINEMENTS_BEFORE_GCD; ntries++) { + y.refine(); + refine(); + if (y.is_rational()) return compare(y.rational()); + if ( is_rational()) return -y.compare( rational()); + if ( high() <= y.low()) return CGAL::SMALLER; + if (y.high() <= low()) return CGAL::LARGER; + } + } +#endif + // filter 2: probabilistically check coprimality + if (!are_distinct) { + are_distinct = !(may_have_common_factor(polynomial(), + y.polynomial())); + } + if (!are_distinct) { + // OK, filters failed. So we have to do the actual work + // and compute the gcd of the defining polynomials. + + // we have ]low(), high()[ == ]y.low(),y.high()[ == ]L,R[ + // and let both numbers decide for the gcd or its complement + Poly F1,F2,G; + G = gcd_utcf(polynomial(),y.polynomial()); + F1 = CGAL::integral_division_up_to_constant_factor(polynomial(),G); + CGAL_postcondition(CGAL::degree(F1)== + CGAL::degree(polynomial())-CGAL::degree(G)); + F2 = CGAL::integral_division_up_to_constant_factor(y.polynomial(),G); + CGAL_postcondition(CGAL::degree(F2)== + CGAL::degree(y.polynomial())-CGAL::degree(G)); + + this->learn_from(G,F1); + y.learn_from(G,F2); + + // this may simplify them due to degree loss + if (y.is_rational()) return compare(y.rational()); + if ( is_rational()) return -y.compare( rational()); + + // type of x and y is still IS_GENERAL + // check for equality + if (G.sign_at(L)!=G.sign_at(R)){ + this->introduce(y); + return CGAL::EQUAL; + } + } + + // if we are here, we know the numbers to be distinct + // refine to disjointness + for (;;) { + y.refine(); + refine(); + if (y.is_rational()) return compare(y.rational()); + if ( is_rational()) return -y.compare( rational()); + if ( high() <= y.low()) return CGAL::SMALLER; + if (y.high() <= low()) return CGAL::LARGER; + } + } + + + //! creates the algebraic real from int \a i. + explicit Algebraic_real_rep_bfi(int i = 0) + :Base(i){} + + //! creates the algebraic real from Field \a m. + explicit Algebraic_real_rep_bfi(const Field& m) + :Base(m), current_prec(53) {} + + /*! \brief creates the algebraic real as the unique root of \a P + in the open interval ]low,high[. + \pre the polynomial \a P is square free + \pre P(low)!=0 + \pre P(high)<0 + \pre x is the one and only root in the open interval of \a P. + */ + Algebraic_real_rep_bfi(const Poly& P, Field LOW, Field HIGH): + Base(P,LOW,HIGH), current_prec(53){}; + + + //! copy constructor + Algebraic_real_rep_bfi(const Self& y) + : Base(y), current_prec(53){} + + // assignment + Algebraic_real_rep_bfi& operator=(const Self& y) { + if ( this != & y) { + this->erase_from_list(); + this->copy_all_members(y); + this->introduce(y); + current_prec = y->current_prec; + } + NiX_expensive_postcond(this->self_test()); + return *this; + } + + + BFI evaluate_polynomial_approx(const BFI& x) const { + // std::cout << "eval approx begin"<< std::endl; + typedef std::vector BFI_VEC; + typedef typename BFI_VEC::reverse_iterator RIT; + + BFI result(0); + for(RIT rit = polynomial_approx.rbegin(); + rit != polynomial_approx.rend(); + rit++){ + result = result * x + (*rit); + } + // std::cout << "eval approx end"<< std::endl; + return result; + } + + void refine_poly_approximation() const { + CGAL_precondition(current_prec > 1); + current_prec *= 2; + // std::cout <<"ALGREAL: refine approx: "<< current_prec<polynomial(), + std::back_inserter(polynomial_approx)); + + Self const *next = static_cast(this->next); + while(this != next){ + // std::cout << this << " " << next << std::endl; + next->polynomial_approx = polynomial_approx; + next->current_prec = current_prec; + next = static_cast(next->next); + } + }; + + void update_poly_approximation() const { + long old_prec = set_precision( BFI(), current_prec ); + + polynomial_approx.clear(); + convert_coeffs( this->polynomial(), std::back_inserter( polynomial_approx ) ); + + set_precision( BFI(), old_prec ); + + // TODO: Problems if the next block gets executed +// Self const *next = static_cast(this->next); +// while(this != next){ +// // std::cout << this << " " << next << std::endl; +// next->polynomial_approx = polynomial_approx; +// next->current_prec = current_prec; +// next = static_cast(next->next); +// } + } + + void refine() const{ + if(this->is_rational()) return; + + // std::cout << "refine begin ------- "<< std::endl; + + Field m = (this->low()+this->high())/Field(2); + + // Currently, sign_of_polynomial_at performs exactly the needed + // refinement. + // TODO: But what if this changes? + sign_of_polynomial_at( m ); + //std::cout << "refine end ----------------- "<polynomial_)+1) { + update_poly_approximation(); + } + + CGAL_postcondition(polynomial_approx.size() > 0); + + BFI eval = evaluate_polynomial_approx(convert_to_bfi(m)); + + CGAL::Sign s = CGAL::sign(CGAL::lower(eval)); + + // correct sign if needed + if( s*CGAL::sign(CGAL::upper(eval) ) != CGAL::POSITIVE ){ + + //std::cout << "APPROX FAILED-------------------------------"<polynomial().sign_at(m); + if ( s != CGAL::ZERO ) { + refine_poly_approximation(); + } + } + + CGAL_postcondition(s == this->polynomial_.sign_at(m)); + + if ( s == CGAL::ZERO ) { + this->learn_from(m); + }else{ + if ( s == this->sign_at_low() ) this->low_ = m; + else this->high_ = m; + } + + set_precision(BFI(),old_prec); + + return s; + } + +}; + +}//namespace internal + +} //namespace CGAL + +#endif //CGAL_ALGEBRAIC_KERNEL_D_ALGEBRAIC_REAL_REP_BFI_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h new file mode 100644 index 00000000000..2474c7429ac --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel.h @@ -0,0 +1,71 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ========================================================================== +#ifndef CGAL_BITSTREAM_COEFFICIENT_KERNEL_H +#define CGAL_BITSTREAM_COEFFICIENT_KERNEL_H 1 + +#include +#include + +namespace CGAL { + +namespace internal { + +template struct Bitstream_coefficient_kernel { + + typedef Coefficient_ Coefficient; + + typedef typename + CGAL::Get_arithmetic_kernel::Arithmetic_kernel + Arithmetic_kernel; + + typedef typename Arithmetic_kernel::Bigfloat_interval Bigfloat_interval; + typedef typename Arithmetic_kernel::Integer Integer; + typedef typename Arithmetic_kernel::Rational Bound; + + + typedef typename CGAL::Algebraic_structure_traits + ::Is_zero Is_zero; + + Is_zero is_zero_object() const { + return Is_zero(); + } + + struct Convert_to_bfi : public std::unary_function + { + + Bigfloat_interval operator() (Coefficient c) const { + return CGAL::convert_to_bfi(c); + } + }; + + Convert_to_bfi convert_to_bfi_object() const { + return Convert_to_bfi(); + } + + +}; // of class Bitstream_coefficient_kernel + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_BITSTREAM_COEFFICIENT_KERNEL_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel_at_alpha.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel_at_alpha.h new file mode 100644 index 00000000000..e0222cc39bb --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_coefficient_kernel_at_alpha.h @@ -0,0 +1,229 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ +#ifndef CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H +#define CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H 1 + +namespace CGAL { + +#include + +#include +#include + +namespace internal { + +template < typename AlgebraicKernel_1 > +class Bitstream_coefficient_kernel_at_alpha; + +template < typename AlgebraicKernel_1 > +class Bitstream_coefficient_kernel_at_alpha_rep { + +public: + + typedef AlgebraicKernel_1 Algebraic_kernel_d_1; + + typedef typename Algebraic_kernel_d_1::Polynomial_1 Polynomial_1; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1; + + Bitstream_coefficient_kernel_at_alpha_rep() {} + + Bitstream_coefficient_kernel_at_alpha_rep(Algebraic_kernel_d_1* kernel, + Algebraic_real_1 alpha) + : _m_kernel(kernel), _m_alpha(alpha) {} + + friend class Bitstream_coefficient_kernel_at_alpha + ; + +private: + Algebraic_kernel_d_1* _m_kernel; + Algebraic_real_1 _m_alpha; + + +}; + +template < typename AlgebraicKernel_1 > +class Bitstream_coefficient_kernel_at_alpha + : public CGAL::Handle_with_policy + < CGAL::internal::Bitstream_coefficient_kernel_at_alpha_rep + + > +{ + +public: + + //! \name typedefs + //! @{ + + typedef AlgebraicKernel_1 Algebraic_kernel_d_1; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1; + + typedef typename Algebraic_kernel_d_1::Polynomial_1 Polynomial_1; + + typedef Polynomial_1 Coefficient; + + typedef typename + CGAL::Get_arithmetic_kernel::Arithmetic_kernel + Arithmetic_kernel; + + typedef typename Arithmetic_kernel::Integer Integer; + + typedef typename Arithmetic_kernel::Rational Bound; + + typedef typename Arithmetic_kernel::Bigfloat_interval Bigfloat_interval; + + typedef CGAL::Handle_with_policy + < CGAL::internal::Bitstream_coefficient_kernel_at_alpha_rep + + > Handle; + + typedef Bitstream_coefficient_kernel_at_alpha Self; + + //! @} + + //! \name Constructors + // !@{ + + Bitstream_coefficient_kernel_at_alpha() {} + + Bitstream_coefficient_kernel_at_alpha(Algebraic_kernel_d_1* kernel, + Algebraic_real_1 alpha) + : Handle(kernel,alpha) {} + + //@} + + //! \name Functors + //! @{ + + struct Is_zero : public std::unary_function { + + Is_zero(Algebraic_kernel_d_1* kernel,Algebraic_real_1 alpha) + : _m_kernel(kernel),_m_alpha(alpha) {} + + bool operator() (Coefficient f) const { + return _m_kernel->is_zero_at_1_object() (f,_m_alpha); + } + + private: + Algebraic_kernel_d_1* _m_kernel; + Algebraic_real_1 _m_alpha; + + }; + + Is_zero is_zero_object() const { + return Is_zero(this->ptr()->_m_kernel,this->ptr()->_m_alpha); + } + + struct Convert_to_bfi + : public std::unary_function { + + Convert_to_bfi(Algebraic_kernel_d_1* kernel, + Algebraic_real_1 alpha) + : _m_kernel(kernel), _m_alpha(alpha) {} + + Bigfloat_interval operator() (Coefficient f) const { + typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type f_bfi; + + typename Algebraic_kernel_d_1::Approximate_relative_1 approx_alpha + =_m_kernel->approximate_relative_1_object(); + + typedef typename Algebraic_kernel_d_1::Bound Bound; + + Bigfloat_interval alpha_bfi, f_alpha_bfi; + + long p = CGAL::get_precision(Bigfloat_interval()); + + long prec = 16; + + long wbit = 0; + + while(true) { + CGAL::set_precision(Bigfloat_interval(),prec); + + f_bfi = this->_convert_polynomial_to_bfi(f); + + std::pair alpha_bounds + = approx_alpha(_m_alpha,prec); + + alpha_bfi = CGAL::hull + (CGAL::convert_to_bfi(alpha_bounds.first), + CGAL::convert_to_bfi(alpha_bounds.second)); + + f_alpha_bfi = f_bfi.evaluate(alpha_bfi); + + if(!CGAL::singleton(f_alpha_bfi)) { + long ceil = CGAL::internal::ceil_log2_abs(f_alpha_bfi); + long signi = CGAL::get_significant_bits(f_alpha_bfi); + wbit = ceil - signi + p; + + } + + if(wbit<-5 || CGAL::singleton(f_alpha_bfi)) { + break; + } else { + prec*=2; + } + } + CGAL::set_precision(Bigfloat_interval(),p); + return f_alpha_bfi; + } + + private: + + typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type + _convert_polynomial_to_bfi(Coefficient f) const { + + typename + CGAL::Polynomial_traits_d::Degree degree; + typename + CGAL::Polynomial_traits_d::Get_coefficient coeff; + std::vector coeffs; + for(int i = 0; i <= degree(f); i++) { + coeffs.push_back(CGAL::convert_to_bfi(coeff(f,i))); + } + return typename CGAL::Polynomial_traits_d + ::template Rebind::Other + ::Construct_polynomial()(coeffs.begin(),coeffs.end()); + } + + Algebraic_kernel_d_1* _m_kernel; + + Algebraic_real_1 _m_alpha; + }; + + Convert_to_bfi convert_to_bfi_object() const { + return Convert_to_bfi(this->ptr()->_m_kernel,this->ptr()->_m_alpha); + } + + // @} + +}; + +} // namespace internal + +} //namespace CGAL + + +#endif // CGAL_BITSTREAM_COEFFICIENT_KERNEL_AT_ALPHA_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes.h new file mode 100644 index 00000000000..92ae3a0fac6 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes.h @@ -0,0 +1,1452 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_GENERIC_DESCARTES +#define CGAL_GENERIC_DESCARTES 1 + + +#include +#include +#include + +// NOTE: If this flag is set, you need EXACUS! +#if CGAL_ACK_BITSTREAM_USES_E08_TREE +#include +#else +#include +#endif + +#include + +namespace CGAL { + +namespace internal { + +//! enum to distinguish between different descartes instances +enum Bitstream_descartes_type { + GENERIC_DESCARTES = 0, + SQUARE_FREE_DESCARTES = 1, //!< uses Square_free_descartes_tag constructor + M_K_DESCARTES = 2, //!< uses M_k_descartes_tag constructor + BACKSHEAR_DESCARTES = 3, //!< uses Backshear_descartes_tag constructor + VERT_LINE_ADAPTER_DESCARTES = 4 // ! < uses Vert_line_adapter_descartes +}; + +// pre-declaration +template +class Bitstream_descartes; + +//! Tag for the square free Bitstream Descartes method +struct Square_free_descartes_tag {}; + +//! Tag for the Bitstream m-k-Descartes method +struct M_k_descartes_tag {}; + +//! Tag for the Backshear Descartes method +struct Backshear_descartes_tag {}; + +//! Tag for the Exchange-Descartes method +struct Vert_line_adapter_descartes_tag {}; + +//! forward declaration +template +class Bitstream_descartes; + + +/* + * \brief Thrown whenever a non-specialised virtual member function is called + */ +class Virtual_method_exception {}; + + +/* + * \brief The base class for all variants of the Bitstream Descartes method. + * + */ +template +class Generic_descartes_rep + : public Policy::template Hierarchy_base::Type { + +public: + + //! The traits class for approximations + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + //! The Handle class + typedef Bitstream_descartes Handle; + + //! The Coeeficient type of the input polynomial + typedef typename Bitstream_descartes_rndl_tree_traits::Coefficient + Coefficient; + + //! The polynomial type + typedef typename Bitstream_descartes_rndl_tree_traits::POLY Polynomial; + + typedef Generic_descartes_rep Self; + + //! The type of the used Bitstream Descartes tree +#if CGAL_ACK_BITSTREAM_USES_E08_TREE + typedef CGAL::internal::Bitstream_descartes_E08_tree + + Bitstream_tree; +#else + typedef CGAL::internal::Bitstream_descartes_rndl_tree + + Bitstream_tree; +#endif + + + //! The used integer type + typedef typename Bitstream_descartes_rndl_tree_traits::Integer Integer; + + //! The type for the iterator of the nodes of the bitstream tree + typedef typename Bitstream_tree::Node_iterator Node_iterator; + + //! The same as constant iterator + typedef typename Bitstream_tree::Node_const_iterator Node_const_iterator; + + //! How the boundaries of the isolating intervals are represented + typedef typename Bitstream_descartes_rndl_tree_traits::Bound Bound; + + //! Default constructor (does nothing) + Generic_descartes_rep(Bitstream_descartes_type type = GENERIC_DESCARTES) : + type_(type) { + }; + + /*! + * Constructor computing an interval containing all real roots of \c f, + * and initialising the Bitstream Descartes tree + */ + Generic_descartes_rep(Bitstream_descartes_type type, + Polynomial f, + Bitstream_descartes_rndl_tree_traits traits) : + type_(type), + f_(f), + traits_(traits), + is_isolated_(false) { + + Integer lower,upper; + long log_div; + this->get_interval(f,lower,upper,log_div,traits); + //AcX_DSTREAM("f: " << f << std::endl); + if (CGAL::degree(f) > 0) { + bitstream_tree +#if CGAL_ACK_BITSTREAM_USES_E08_TREE + = Bitstream_tree(-log_div, + f.begin(), + f.end(), + typename Bitstream_tree::Monomial_basis_tag(), + traits); +#else + = Bitstream_tree(lower,upper,log_div, + f.begin(), + f.end(), + typename Bitstream_tree::Monomial_basis_tag(), + traits); +#endif + + if (bitstream_tree.begin() == bitstream_tree.end()) { + number_of_intervals = 0; + } else { + number_of_intervals = 1; + } + } else { + number_of_intervals=0; + } + } + + /*! + * Constructor that copies the Bitstream tree given from outside + * and initialising the Bitstream Descartes tree + * The tree must "fit" to the polynomial + */ + Generic_descartes_rep(Bitstream_descartes_type type, + Polynomial f, + Bitstream_tree tree, + Bitstream_descartes_rndl_tree_traits traits) : + type_(type), + f_(f), + traits_(traits), + bitstream_tree(tree), + is_isolated_(false) { + + tree.set_traits(traits); + + number_of_intervals = 0; + + for(Node_iterator curr = bitstream_tree.begin(); + curr != bitstream_tree.end(); + curr++) { + number_of_intervals++; + } + } + + //! Destructor (does nothing) + virtual ~Generic_descartes_rep() { + } + + //! Needed for the referencing counting mechanism + virtual CGAL::Reference_counted_hierarchy<>* clone() { + return new Generic_descartes_rep(*this); + } + + /*! + * \brief Computes a better approximation of the \c i th root of the + * polynomial + */ + virtual void refine_interval(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < number_of_intervals); + Node_iterator curr = bitstream_tree.begin(), begin, end, + new_begin, helper; + std::advance(curr,i); + int intervals = 1; + end = curr; + ++end; + begin=curr; + do { + //std::cout << bitstream_tree.lower(begin) << " " << bitstream_tree.upper(begin) << std::endl; + //std::cout << bitstream_tree.min_var(begin) << " " << bitstream_tree.max_var(begin) << std::endl; + int new_intervals = bitstream_tree.subdivide(begin,new_begin,helper); + intervals += new_intervals-1; + begin = new_begin; + curr = helper; + + // Fixes the bug when a interval splits, and the leftmost subintervals + // has no children with sign variation >=1 + if (intervals == 1) { + break; + } + if (new_intervals == 0) { + continue; + } + + while(curr != end) { + intervals += bitstream_tree.subdivide(curr,new_begin,helper)-1; + curr = helper; + } + + } + while (intervals != 1); + //std::cout << "Refined " << left_bound(i) << " " << right_bound(i) << std::endl; + + } + + /*! + * \brief isolates the root of \c f + * + * The mechanism is the following: The \c bitstream_tree member of the + * object is transformed via subdivision until the + * \c termination_condition routine of the object returns true. When this + * happens, the \c process_nodes routine of the object is called. + */ + virtual void isolate() { + + //AcX_DSTREAM("Starting isolation" << std::endl); + + Node_iterator curr = bitstream_tree.begin(),dummy,new_curr; + + if(curr == bitstream_tree.end()) { + is_isolated_ = true; + return; + } + + int newly_created; + + while (!this->termination_condition()) { + + if (curr == bitstream_tree.end()) { + curr = bitstream_tree.begin(); + } + + if (bitstream_tree.max_var(curr) == 1) { + ++curr; + } + else { + //AcX_DSTREAM("Subdivision at " + //<< CGAL::to_double(bitstream_tree.lower(curr)) << " " + //<< CGAL::to_double(bitstream_tree.upper(curr)) << std::flush); + newly_created = bitstream_tree.subdivide(curr,dummy,new_curr); + number_of_intervals += newly_created-1; + curr = new_curr; + //AcX_DSTREAM("done" << std::endl); + } + + } + this->process_nodes(); + is_isolated_ = true; + } + + /*! + * \brief Computes an interval containing all real roots of \c p, + * using the Fujiwara root bound. + * + * So far, the \c log_div variable is always set to zero, this means + * that [lower,upper] is the interval containing all real roots + */ + virtual void get_interval(const Polynomial& p, Integer& lower, + Integer& upper, long& log_div, + Bitstream_descartes_rndl_tree_traits traits) { + + + typename Bitstream_descartes_rndl_tree_traits::Lower_bound_log2_abs + lower_bound_log2_abs = traits.lower_bound_log2_abs_object(); + typename + Bitstream_descartes_rndl_tree_traits::Upper_bound_log2_abs_approximator + upper_bound_log2_abs_approximator + = traits.upper_bound_log2_abs_approximator_object(); + //AcX_DSTREAM("Fujiwara bound.." << p << std::endl); +#if CGAL_ACK_BITSTREAM_USES_E08_TREE + log_div = -CGAL::internal::Fujiwara_root_bound_log + (p.begin(), + p.end(), + lower_bound_log2_abs, + upper_bound_log2_abs_approximator + ); +#else + + log_div = -CGAL::internal + ::Fujiwara_root_bound_log + (p.begin(), + p.end(), + lower_bound_log2_abs, + upper_bound_log2_abs_approximator + ); +#endif + + //AcX_DSTREAM("Fujiwara returns " << log_div << std::endl); + // To be sure + log_div--; + lower=Integer(-1); + upper=Integer(1); + return; + + } + + //! returns the number of detected isolating intervals + virtual int number_of_real_roots() const { + return number_of_intervals; + } + + //! The lower bound of the \c i th root + virtual Bound left_bound(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < number_of_intervals); + Node_const_iterator curr = bitstream_tree.begin(); + std::advance(curr,i); + return bitstream_tree.lower(curr); + } + + //! The upper bound of the \c i th root + virtual Bound right_bound(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < number_of_intervals); + Node_const_iterator curr = bitstream_tree.begin(); + std::advance(curr,i); + return bitstream_tree.upper(curr); + } + + //! Returns the polynomial which is isolated + Polynomial polynomial() const { + return f_; + } + + /*! + * \brief When does the isolation algorithm terminate? + * + * This method must be specialised by derived classes + */ + virtual bool termination_condition() { + throw Virtual_method_exception(); + return false; + } + + /*! + * \brief Gives an opportunity to process the nodes after + * the subdivision steps are finished + * + * This method must be specialised by derived classes, but can + * remain empty in many cases. + */ + virtual void process_nodes() { + throw Virtual_method_exception(); + return; + } + + /*! \brief Returns whether the \c i th root is definitely a simple root + * of the isolated polynomial + * + * Must be specialised by derived class + */ + virtual bool is_certainly_simple_root(int) const { + throw Virtual_method_exception(); + return false; + } + + /*! \brief Returns whether the \c i th root is definitely a multiple root + * of the isolated polynomial + * + * Must be specialised by derived class + */ + virtual bool is_certainly_multiple_root(int) const { + throw Virtual_method_exception(); + return false; + } + + + virtual int multiplicity_of_root(int CGAL_assertion_code(i)) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < number_of_intervals); + return -1; + } + + virtual int get_upper_bound_for_multiplicity(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < number_of_intervals); + Node_const_iterator curr = bitstream_tree.begin(); + std::advance(curr,i); + return bitstream_tree.min_var(curr); + } + + //! Must be specialized by the derived class + virtual int degree_of_gcd() const { + throw Virtual_method_exception(); + return -1; + } + + //! Must be specialized by the derived class + virtual Polynomial square_free_part() const { + throw Virtual_method_exception(); + return Polynomial(); + } + + //! Must be specialized by the derived class + virtual Handle inverse_transform_isolator() const { + throw Virtual_method_exception(); + return Handle(); + } + + bool is_isolated() const { + return is_isolated_; + } + + Bitstream_descartes_rndl_tree_traits traits() const { + return traits_; + } + + Bitstream_tree get_tree() const { + + return bitstream_tree; + + } + + //! type to distinguish used constructor + Bitstream_descartes_type type_; + +protected: + + //! Polynomial which is isolated + Polynomial f_; + + //! The traits class + Bitstream_descartes_rndl_tree_traits traits_; + + //! The tree of the Bitstream Descartes method + mutable Bitstream_tree bitstream_tree; + + //! The number of detected isolating intervals + int number_of_intervals; + + //! Has isolation already taken place + mutable bool is_isolated_; + +}; + +/* + * \brief Representation for square free polynomials + */ +template +class Square_free_descartes_rep + : public Generic_descartes_rep { + + +public: + + //! Traits type + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + //! The generic representation + typedef Generic_descartes_rep Base; + + //! Polynomial type + typedef typename Base::Polynomial Polynomial; + + //! Iterator for the leaves in the bitstream tree + typedef typename Base::Node_iterator Node_iterator; + + //! The type of the tree that controls the Bitstream instance + typedef typename Base::Bitstream_tree Bitstream_tree; + + /*! + * \brief Constructor with the square free polynomial f. + */ + Square_free_descartes_rep( + Polynomial f, + Bitstream_descartes_rndl_tree_traits traits) : + Base(SQUARE_FREE_DESCARTES, f,traits) { + } + + /*! + * \brief Constructor with the square free polynomial f. + */ + Square_free_descartes_rep( + Polynomial f, + Bitstream_tree tree, + Bitstream_descartes_rndl_tree_traits traits) : + Base(SQUARE_FREE_DESCARTES, f, tree, traits) { + } + + //! Needed for reference counting + virtual CGAL::Reference_counted_hierarchy<>* clone() { + return new Square_free_descartes_rep(*this); + } + + /*! + * \brief Terminates when all detected roots are simple + */ + virtual bool termination_condition() { + for(Node_iterator curr=Base::bitstream_tree.begin(); + curr != Base::bitstream_tree.end();curr++) { + if(Base::bitstream_tree.max_var(curr)!=1) { + return false; + } + } + return true; + } + + //! nothing to do here + virtual void process_nodes() { + return; + } + + //! Polynomial is square free, so gcd is 1 + virtual int degree_of_gcd() const { + return 0; + } + + //! Polynomial is square free + virtual Polynomial square_free_part() const { + return this->f_; + } + + //! Always true + virtual bool is_certainly_simple_root(int ) const { + return true; + } + + //! Always false + virtual bool is_certainly_multiple_root(int ) const { + return false; + } + +}; + +/* + * \brief Representation for polynomials with at most one multiple root + */ +template +class M_k_descartes_rep + : public Generic_descartes_rep { + + +public: + + //! Traits class + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + //! Generic representation + typedef Generic_descartes_rep Base; + + //! Polynomial type + typedef typename Base::Polynomial Polynomial; + + //! Iterator for the leaves of the Bitstream Descartes tree + typedef typename Base::Node_iterator Node_iterator; + + //! Constant iterator for the leaves + typedef typename Base::Node_const_iterator Node_const_iterator; + + //! The interval boundaries are represented in this type + typedef typename Bitstream_descartes_rndl_tree_traits::Bound + Bound; + + //! The type of the tree that controls the Bitstream instance + typedef typename Base::Bitstream_tree Bitstream_tree; + + /*! + * \brief Constructor for a polynomial f, not necessarily square + * free + * + * The values m + * and k need to be the exact number of real roots of f + * counted without multiplicity and the degree of the greatest common + * divisor of f with its partial derivative, respectively. + */ + M_k_descartes_rep(Polynomial f,int m, int k, + Bitstream_descartes_rndl_tree_traits traits) : + Base(M_K_DESCARTES, f,traits), + number_of_roots(m), + gcd_degree(k), + index_of_multiple(-1) { + } + + M_k_descartes_rep(Polynomial f,int m, int k, + Bitstream_tree tree, + Bitstream_descartes_rndl_tree_traits traits) : + Base(M_K_DESCARTES, f, tree, traits), + number_of_roots(m), + gcd_degree(k), + index_of_multiple(-1) { + } + + //! Default constructor + M_k_descartes_rep() { + } + + //! Needed for reference counting + virtual CGAL::Reference_counted_hierarchy<>* clone() { + return new M_k_descartes_rep(*this); + } + + /*! + * \brief Termination condition + * + * If m-1 simple and one more leaf is detected, the Bitstream + * Descartes method is stopped. If the minimal sign + * variation drops under k in each leaf, a + * \c Non_generic_position_exception is thrown. + */ + virtual bool termination_condition() { + int counted_simple_roots=0; + int max_max_var = 0; + for(Node_iterator curr=Base::bitstream_tree.begin(); + curr != Base::bitstream_tree.end(); curr++) { + int max_var = Base::bitstream_tree.max_var(curr); + if(max_var > max_max_var) { + max_max_var = max_var; + } + if(max_var == 1) { // && Base::bitstream_tree.max_var(curr)==1) { + ++counted_simple_roots; + } + } + //AcX_DSTREAM("Situation: " << this->number_of_intervals << " intervals " << this->number_of_roots << " are expected" << std::endl); + if (this->number_of_intervals == this->number_of_roots + && counted_simple_roots >= number_of_roots-1) { + return true; + } + if (max_max_var <= gcd_degree) { + throw CGAL::internal::Non_generic_position_exception(); + } + + return false; + + } + + //! The index of the (possibly) multiple root is computed here. + virtual void process_nodes() { + int i = 0; + for (Node_iterator curr=Base::bitstream_tree.begin(); + curr != Base::bitstream_tree.end(); curr++) { + if(Base::bitstream_tree.max_var(curr) > 1 ) { + index_of_multiple = i; + return; + } else { + ++i; + } + } + return; + } + + //! Returns k + virtual int degree_of_gcd() const { + return gcd_degree; + } + + //! True for all roots except for the candidate + virtual bool is_certainly_simple_root(int i) const { + return (i!=index_of_multiple); + } + + //! Always false + virtual bool is_certainly_multiple_root(int) const { + return false; + } + + +protected: + + //! The "m" + int number_of_roots; + + //! The "k" + int gcd_degree; + + //! The candidate's index + int index_of_multiple; + +}; + + +template +class Backshear_descartes_rep + : public Generic_descartes_rep { + + +public: + + typedef EventRefinement Event_refinement; + + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + typedef Generic_descartes_rep Base; + + typedef typename Base::Polynomial Polynomial; + + typedef typename Base::Node_iterator Node_iterator; + + typedef std::list::iterator Marking_iterator; + + typedef std::list::const_iterator Marking_const_iterator; + + typedef typename Base::Node_const_iterator Node_const_iterator; + + typedef typename Base::Bound Bound; + + Backshear_descartes_rep( + Polynomial f, + int number_of_non_event_points, + int number_of_events, + Event_refinement event_refinement, + Bitstream_descartes_rndl_tree_traits traits) : + Base(BACKSHEAR_DESCARTES,f,traits), + number_of_non_event_points(number_of_non_event_points), + number_of_events(number_of_events), + event_refinement(event_refinement) { + } + + Backshear_descartes_rep() { + } + + virtual CGAL::Reference_counted_hierarchy<>* clone() { + return new Backshear_descartes_rep(*this); + } + + virtual void isolate() { + + Node_iterator curr = Base::bitstream_tree.begin(),sub_begin,new_curr; + + if(curr == Base::bitstream_tree.end()) { + this->is_isolated_ = true; + return; + } + markings.clear(); + markings.push_back(this->check_marking(curr)); + + Marking_iterator curr_mark = markings.begin(),mark_helper; + + int newly_created; + + while(! this->termination_condition()) { + //AcX_DSTREAM("Subdivision..." << number_of_intervals << std::endl); + if (curr == Base::bitstream_tree.end()) { + curr = Base::bitstream_tree.begin(); + CGAL_assertion(curr_mark == markings.end()); + curr_mark = markings.begin(); + } + if(Base::bitstream_tree.max_var(curr) == 1) { + ++curr; + ++curr_mark; + //AcX_DSTREAM("nothing happend" << std::endl); + } + else { + newly_created = + Base::bitstream_tree.subdivide(curr,sub_begin,new_curr); + mark_helper = markings.erase(curr_mark); + curr_mark = mark_helper; + for(Node_iterator tmp_curr = sub_begin; + tmp_curr != new_curr; + tmp_curr++) { + markings.insert(curr_mark,check_marking(tmp_curr)); + } + Base::number_of_intervals += newly_created-1; + curr = new_curr; + //AcX_DSTREAM(newly_created << " new intervals, marking size: " << markings.size() << std::endl); + + } + } + this->process_nodes(); + this->is_isolated_ = true; + } + + + + virtual bool termination_condition() { + int marked_intervals = 0; + int unmarked_odd_intervals = 0; + Node_iterator curr = Base::bitstream_tree.begin(); + Marking_iterator curr_mark = markings.begin(); + for(;curr != Base::bitstream_tree.end(); curr++) { + if((*curr_mark) >= 0) { + ++marked_intervals; + } + else { + if (Base::bitstream_tree.min_var(curr) % 2 == 1) { // odd + ++unmarked_odd_intervals; + } + } + ++curr_mark; + } + CGAL_assertion(curr_mark == markings.end()); + return ((marked_intervals == number_of_events) + && (unmarked_odd_intervals == number_of_non_event_points)); + } + + virtual void process_nodes() { + Node_iterator curr=Base::bitstream_tree.begin(),curr_helper; + Marking_iterator curr_mark = markings.begin(); + while(curr!=Base::bitstream_tree.end()) { + if(((*curr_mark) == -1) && + (Base::bitstream_tree.min_var(curr) % 2 == 0)) { + ++curr; + curr_helper = curr; + curr_helper--; + Base::bitstream_tree.erase(curr_helper); + curr_mark = markings.erase(curr_mark); + Base::number_of_intervals--; + } else { + ++curr_mark; + ++curr; + } + } + CGAL_assertion(curr_mark == markings.end()); + + //AcX_DSTREAM(markings.size() << " " << number_of_non_event_points << " " << number_of_events << std::endl); + CGAL_assertion(static_cast(markings.size()) + ==number_of_non_event_points + number_of_events); + return; + } + + virtual bool is_certainly_simple_root(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < Base::number_of_intervals); + Node_const_iterator curr=Base::bitstream_tree.begin(); + std::advance(curr,i); + return (Base::bitstream_tree.max_var(curr) == 1); + } + + virtual bool is_certainly_multiple_root(int i) const { + CGAL_assertion(i >= 0); + CGAL_assertion(i < Base::number_of_intervals); + Marking_const_iterator curr = markings.begin(); + std::advance(curr,i); + return (*curr>=0); + } + + +protected: + + int number_of_non_event_points; + + int number_of_events; + + Event_refinement event_refinement; + + std::list markings; + +protected: + + int check_marking(Node_iterator node) { + Bound lower = Base::bitstream_tree.lower(node), + upper = Base::bitstream_tree.upper(node); + for(int i = 0; i < number_of_events; i++) { + while(true) { + if(CGAL::compare(event_refinement.lower_bound(i),lower) + !=CGAL::NEGATIVE + && + CGAL::compare(event_refinement.upper_bound(i),upper) + !=CGAL::POSITIVE) { + //Event inside the interval + return i; + } + if(CGAL::compare(event_refinement.lower_bound(i),upper) + ==CGAL::POSITIVE + || + CGAL::compare(event_refinement.upper_bound(i),lower) + ==CGAL::NEGATIVE) { + //This event is outside + break; + } + event_refinement.refine(i); + + } + } + return -1; + } + +}; + +/* + * \brief Adaptor for roots of a vert line + * (needed as dummy in surface analysis) + * + */ +template +class Vert_line_adapter_descartes_rep + : public Generic_descartes_rep { + +public: + + //! The traits class for approximations + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + //! type of vert line + typedef VertLine Vert_line; + + //! type of Curve_analysis_2 + typedef typename Vert_line::Curve_analysis_2 Curve_analysis_2; + + //! type of Curve_kernel_2; + typedef typename Curve_analysis_2::Algebraic_kernel_with_analysis_2 + Curve_kernel_2; + + //! The Coeeficient type of the input polynomial + typedef typename Bitstream_descartes_rndl_tree_traits::Coefficient + Coefficient; + + //! The polynomial type + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial; + + typedef Vert_line_adapter_descartes_rep + Self; + + //! The used integer type + typedef typename Bitstream_descartes_rndl_tree_traits::Integer Integer; + + //! How the boundaries of the isolating intervals are represented + typedef typename Bitstream_descartes_rndl_tree_traits::Bound + Bound; + + typedef Generic_descartes_rep + Base; + + //! The type for the inverse isolator + typedef typename Base::Handle Handle; + + /*! + * \brief Constructor + */ + template + Vert_line_adapter_descartes_rep(InputIterator begin, + InputIterator end, + Bitstream_descartes_rndl_tree_traits traits) + : Base(VERT_LINE_ADAPTER_DESCARTES) + { + for (InputIterator it = begin; it != end; it++) { + root_vec.push_back(std::make_pair(*it, 4)); + } + + this->is_isolated_ = true; + this->traits_ = traits; + this->f_ = Polynomial(0); + this->number_of_intervals + = static_cast(root_vec.size()); + // Isolate all real roots until intervals are disjoint: + for (int i = 1; i < this->number_of_real_roots(); i++ ){ + while(left_bound(i) < right_bound(i-1) ) { + if (right_bound(i)-left_bound(i) < + right_bound(i-1) - left_bound(i-1) ) { + refine_interval(i-1); + } else { + refine_interval(i); + } + } + + } + } + + + //! Destructor (does nothing) + virtual ~Vert_line_adapter_descartes_rep() { + } + + //! Needed for the referencing counting mechanism + virtual CGAL::Reference_counted_hierarchy<>* clone() { + return new Vert_line_adapter_descartes_rep(*this); + } + + virtual void refine_interval(int i) const { + root_vec[i] = std::make_pair(root_vec[i].first, root_vec[i].second * 2); + } + + virtual void isolate() const { + } + + + //! The lower bound of the \c i th root + virtual Bound left_bound(int i) const { + typename Curve_kernel_2::Approximate_absolute_y_2 + approx_y = Base::traits_.point().xy().kernel() + ->approximate_absolute_y_2_object(); + return approx_y(root_vec[i].first.first.algebraic_real_2 + (root_vec[i].first.second), + root_vec[i].second).first; + } + + //! The upper bound of the \c i th root + virtual Bound right_bound(int i) const { + typename Curve_kernel_2::Approximate_absolute_y_2 + approx_y = Base::traits_.point().xy().kernel() + ->approximate_absolute_y_2_object(); + return approx_y(root_vec[i].first.first.algebraic_real_2 + (root_vec[i].first.second), + root_vec[i].second).second; + } + + + /*! \brief Returns whether the \c i th root is definitely a simple root + * of the isolated polynomial + * + */ + virtual bool is_certainly_simple_root(int i) const { + return false; + } + + /*! \brief Returns whether the \c i th root is definitely + * a multiple root + * of the isolated polynomial + * + */ + virtual bool is_certainly_multiple_root(int i) const { + return false; + } + +protected: + + //! Roots stored as pair of a AcX::Vert_line and an integer denoting the + //! index. Also, current precision of each root is stored + mutable std::vector,int> > root_vec; + + +}; + +/*! + * \brief Class for the Bitstream Descartes method + * + * Class for the real root isolation of polynomials, using the Bitstream + * Descartes method. The polynomials coefficient type is arbitrary, the + * approximations of the coefficient type are obtained with the + * \c BitstreamDescartesRndlTreeTraits parameter. For the requirements + * of this traits class, see the documentation of + * CGAL::Bitstream_descartes_rndl_tree. + * + * Internally, an instance of CGAL::Bitstream_descartes_rndl_tree is explored + * in a specific way. That exploration strategy depends on the constructor + * that is used to create the object. A tag is passed that defines the + * variant of the Bitstream Descartes method: The Square_free_descartes_tag + * starts the usual Bitstream method for square free integer polynomials. + * With the M_k_descartes tag, it is able to handle one multiple root in + * favourable situations, the Backshear_descartes_tag allows to isolate + * even more complicated polynomials, if the multiple roots with even + * multiplicity can be refined from outside. See the corresponding + * constructors for more information. + * + */ +template +class Bitstream_descartes + : ::CGAL::Handle_with_policy< + CGAL::internal::Generic_descartes_rep > { + +public: + + //! Traits class + typedef BitstreamDescartesRndlTreeTraits + Bitstream_descartes_rndl_tree_traits; + + // The generic representation class + typedef + CGAL::internal::Generic_descartes_rep Rep; + + // The Handle type + typedef ::CGAL::Handle_with_policy Base; + + //! The coefficients of the polynomial + typedef typename Bitstream_descartes_rndl_tree_traits::Coefficient + Coefficient; + + //! The polynomial's type + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial; + + typedef Bitstream_descartes + Self; + + // Type for the Bitstream Descartes tree +#if CGAL_ACK_BITSTREAM_USES_E08_TREE + typedef CGAL::internal::Bitstream_descartes_E08_tree + + Bitstream_tree; +#else + typedef CGAL::internal::Bitstream_descartes_rndl_tree + + Bitstream_tree; +#endif + + //! Type for Integers + typedef typename Bitstream_descartes_rndl_tree_traits::Integer Integer; + + //! Iterator type for the leaves of the Descartes tree + typedef typename Bitstream_tree::Node_iterator + Node_iterator; + + //! Const iterator for the leaves + typedef typename Bitstream_tree::Node_const_iterator + Node_const_iterator; + + //! Type for the interval boundaries of the isolating intervals + typedef typename Bitstream_descartes_rndl_tree_traits::Bound + Bound; + + //! Default constructor + Bitstream_descartes() : Base(new Rep()) {} + + /*! + * \brief Constructor for a polynomial \c f + * + * See the documentation of the constrctor + * with \c Square_free_descartes_tag + */ + Bitstream_descartes(Polynomial f, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate=true) + : Base(new CGAL::internal::Square_free_descartes_rep + (f,traits)) + { + if (isolate) { + this->isolate(); + } + } + + /*! + * \brief Constructor for the square free Descartes method + * + * The polynomial \c f must not have multiple real roots. The + * Bitstream Descartes tree is traversed in a bfs manner until + * all leaves have sign variation zero or one. + */ + Bitstream_descartes(Square_free_descartes_tag , + Polynomial f, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate=true) + : Base(new CGAL::internal::Square_free_descartes_rep + (f,traits)) + { + if (isolate) { + this->isolate(); + } + } + + /*! + * \brief Constructor for the square free Descartes method, + * using a precomputed tree + * + * The polynomial \c f must not have multiple real roots. The + * Bitstream Descartes tree is traversed in a bfs manner until + * all leaves have sign variation zero or one. + * The tree must be adequate for the polynomial. + * Use that constructor only if you know what you're doing! + */ + Bitstream_descartes(Square_free_descartes_tag , + Polynomial f, + Bitstream_tree tree, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate=true) + : Base(new CGAL::internal::Square_free_descartes_rep + (f, tree, traits)) + { + if(isolate) { + this->isolate(); + } + } + + /*! + * \brief Constructor for the m-k-Descartes method + * + * The polynomial \c f must have exactly \c m real roots, counted without + * multiplicity, and the degree of gcd(f,f') must be \c k. In this + * case, the constructor either isolates the real roots of \c f sucessfully + * or a Non_generic_position_exception is thrown. Such an exception + * certainly occurs if \c f has more than one multiple real root. If \c f + * has at most one multiple root over the complex numbers, the roots are + * certainly isolated with success. + */ + Bitstream_descartes(M_k_descartes_tag , + Polynomial f,int m,int k, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate = true) + : Base(new CGAL::internal::M_k_descartes_rep + (f,m,k,traits)) + { + if (isolate) { + this->isolate(); + } + } + + + Bitstream_descartes(M_k_descartes_tag t, + Polynomial f,int m,int k, + Bitstream_tree tree, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate = true) + : Base(new CGAL::internal::M_k_descartes_rep + (f,m,k,tree,traits)) + { + if (isolate) { + this->isolate(); + } + } + + + /*! + * \brief Constructor for the Backshear-Decartes method + * + * The polynomial \c f must have exactly \c number_of_real_roots + * many real roots, counted without multiplicity. Additionally, a set of + * \c number_of_events root can be refined to arbitrary precision with the + * \c event_refinement object. This must support three operations + * for each 0<=i: + *
  • lower_bound(i), upper_bound(i) gives an interval (not + * necessarily isolating) of some root of \c f
  • + *
  • refine(i) refines the corresponding interval
+ * Note that the roots in \c event_refinement need not be sorted. All roots + * which are not covered by \c event_refinement must have odd multiplicity. + */ + template + Bitstream_descartes(Backshear_descartes_tag , + Polynomial f, + int number_of_real_roots, + int number_of_events, + EventRefinement event_refinement, + Bitstream_descartes_rndl_tree_traits traits + = Bitstream_descartes_rndl_tree_traits(), + bool isolate = true) + : Base(new + CGAL::internal::Backshear_descartes_rep + + (f,number_of_real_roots-number_of_events, + number_of_events,event_refinement,traits)) + { + if (isolate) { + this->isolate(); + } + } + + + /*! + * \brief Constructor for the Vert-line-adapter-Descartes method + * + */ + template + Bitstream_descartes(Vert_line_adapter_descartes_tag t, + InputIterator begin, + InputIterator end, + Bitstream_descartes_rndl_tree_traits traits) + : Base(new CGAL::internal::Vert_line_adapter_descartes_rep + + (begin, end, traits) ) + { + // No isolation necessary + } + + //! return the type of the used descartes method + Bitstream_descartes_type type() const { + return this->ptr()->type_; + } + + //! Return the polynomial + Polynomial polynomial() const { + CGAL_assertion(is_isolated()); + return this->ptr()->polynomial(); + } + + //! Returns the traits class + Bitstream_descartes_rndl_tree_traits traits() const { + return this->ptr()->traits(); + } + + //! Number of real roots of the polynomial + int number_of_real_roots() const { + CGAL_assertion(is_isolated()); + return this->ptr()->number_of_real_roots(); + } + + //! Refine the ith isolating interval + void refine_interval(int i) const { + CGAL_assertion(is_isolated()); + this->ptr()->refine_interval(i); + } + + //! The left bound of the ith isolating interval + Bound left_bound(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->left_bound(i); + } + + //! The left bound of the ith isolating interval + void left_bound(int i, + Integer& numerator, + Integer& denominator) const { + typedef CGAL::Fraction_traits Fraction_traits; + typename Fraction_traits::Decompose decompose; + decompose(left_bound(i),numerator,denominator); + } + + //! The right bound of the ith isolating interval + Bound right_bound(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->right_bound(i); + } + + //! The right bound of the ith isolating interval + void right_bound(int i, + Integer& numerator, + Integer& denominator) const { + typedef CGAL::Fraction_traits Fraction_traits; + typename Fraction_traits::Decompose decompose; + decompose(right_bound(i),numerator,denominator); + } + + //! The length of the ith isolating interval + Bound length(int i) const { + CGAL_assertion(is_isolated()); + return (this->ptr()->right_bound(i) - + this->ptr()->left_bound(i)); + } + + bool is_exact_root(int) const { return false; } + + /*! + * \brief Returns true if the ith root is known to be a simple + * root of the curve. + */ + bool is_certainly_simple_root(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->is_certainly_simple_root(i); + } + + /*! + * \brief Returns true if the ith root is known to be a multiple + * root of the curve. + */ + bool is_certainly_multiple_root(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->is_certainly_multiple_root(i); + } + + + /*! + * \brief Returns the multiplicity of the root if know, otherwise -1 + */ + int multiplicity_of_root(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->multiplicity_of_root(i); + } + + /*! + * Returns an upper bound for the multiplicity of the ith root + */ + int get_upper_bound_for_multiplicity(int i) const { + CGAL_assertion(is_isolated()); + return this->ptr()->get_upper_bound_for_multiplicity(i); + } + + /*! + * \brief Returns the isolator of the polynomial f(1/x + q), if known + */ + Self inverse_transform_isolator() const { + return this->ptr()->inverse_transform_isolator(); + } + + +public: + + //! Starts the isolation of the real roots. + void isolate() { + CGAL_assertion(!is_isolated()); + this->ptr()->isolate(); + } + + bool is_isolated() const { + return this->ptr()->is_isolated(); + } + + Bitstream_tree get_tree() const { + return this->ptr()->get_tree(); + } + + //! returns the degree of the gcd of f and its derivative, if known + int degree_of_gcd() const { + return this->ptr()->degree_of_gcd(); + } + + //! returns the square free part of f, if known + Polynomial square_free_part() const { + return this->ptr()->square_free_part(); + } + +}; + +} // namespace internal + +} // namespace CGAL + +#endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_E08_tree.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_E08_tree.h new file mode 100644 index 00000000000..ff9e0b4b8a6 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_E08_tree.h @@ -0,0 +1,1053 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Arno Eigenwillig +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + + +#ifndef CGAL_BITSTREAM_DESCARTES_E08_TREE_H +#define CGAL_BITSTREAM_DESCARTES_E08_TREE_H + +#include +#include +#include +#include +#include + +#include +#include // TODO remove +#include +#include + +#include + +/* + * AUXILIARY CLASSES AND FUNCTIONS + */ + +namespace CGAL { + +namespace internal { + +template +Integer caching_binomial(int n, int k) { + CGAL_precondition(n >= 0); + if (k < 0 || k > n) return Integer(0); + + // Pascal's triangle; augment if necessary + // TODO flat array with manual index computation should be slightly faster + typedef std::vector< Integer > Row; + typedef std::vector< Row > Triangle; + static Triangle pascal; + + int old_size = int(pascal.size()); + if (n >= old_size) { + pascal.resize(n+1); + if (old_size == 0) { + pascal[0].push_back(Integer(1)); + old_size = 1; + } + for (int i = old_size; i <= n; ++i) { + Row& prev = pascal[i-1]; + Row& curr = pascal[i]; + curr.reserve(i+1); + curr.push_back(Integer(1)); + for (int j = 1; j < i; ++j) { + curr.push_back(prev[j-1] + prev[j]); + } + curr.push_back(Integer(1)); + } + } + return pascal[n][k]; +} + + +template +class Power_to_Bernstein_pm1_nofrac_matrix { +public: + typedef Integer_ Integer; + +private: + int dim_; + std::vector m_; + int ij_to_idx(int i, int j) const { return i*dim_ + j; } + void init_m(); + +public: + Power_to_Bernstein_pm1_nofrac_matrix(int degree = -1) + : dim_(degree + 1), m_(dim_ * dim_) + { + CGAL_assertion(degree >= -1); + init_m(); + } + + void set_degree(int degree) { + CGAL_assertion(degree >= -1); + dim_ = degree + 1; + m_.resize(dim_ * dim_); + init_m(); + } + + Integer operator()(int i, int j) const { + CGAL_assertion(0 <= i && i < dim_); + CGAL_assertion(0 <= j && j < dim_); + return m_[ij_to_idx(i,j)]; + } + + int degree() const { return dim_ - 1; } +}; // class Power_to_Bernstein_pm1_nofrac_matrix + +template +void Power_to_Bernstein_pm1_nofrac_matrix::init_m() { + // TODO: this implements the definition, but [E08] describes a faster way + int degree = dim_ - 1; + for (int i = 0; i < dim_; ++i) { + for (int j = 0; j < dim_; ++j) { + Integer sum(0); + int nu_lo = (std::max)(0, i+j-degree); + int nu_hi = (std::min)(i, j); + for (int nu = nu_lo; nu <= nu_hi; ++nu) { + Integer term = caching_binomial(j, nu) + * caching_binomial(degree-j, i-nu); + if ((j - nu) & 1) { sum -= term; } + else { sum += term; } + } + m_[ij_to_idx(i,j)] = + sum + * CGAL::internal::caching_factorial(i) + * CGAL::internal::caching_factorial(degree - i); + } + } +} + +template +class Bitstream_bernstein_from_power { +public: + typedef Traits_ Traits; + typedef typename Traits::Coefficient Coefficient; + typedef typename Traits::Integer Integer; + typedef typename Traits::Approximator Approximator; + typedef typename Traits::Lower_bound_log2_abs Lower_bound_log2_abs; + typedef typename Traits::Ceil_log2_abs_Integer Ceil_log2_abs_Integer; + typedef typename Traits::Ceil_log2_abs_long Ceil_log2_abs_long; + + typedef std::vector Coefficient_vector; + typedef std::vector Integer_vector; + typedef Power_to_Bernstein_pm1_nofrac_matrix Mn; + typedef std::map Mn_cache; + +private: + Coefficient_vector input_power_coeff_; + int degree_; // $ = n $ in [E08] + long log_radius_; // $ = r+1 $ in [E08] + Approximator approximator_; + Lower_bound_log2_abs lower_bound_log2_abs_; + long ceil_log_degfac_, floor_log_degfac_, ceil_log_degp1_; + long lbd_log_lcoeff_; + long log_lcfscale_; // $ = l $ in [E08] + + Integer_vector bernstein_coeff_; // empty if uninitialized + long bernstein_coeff_prec_; // $ = p+1 $ in [E08] + + static Mn_cache mn_cache_; + static const Mn& get_mn(int n) { + Mn& mn = mn_cache_[n]; + if (mn.degree() == -1) mn.set_degree(n); + return mn; + } + +public: + Bitstream_bernstein_from_power() : degree_(-1) { } + + template + Bitstream_bernstein_from_power( + InputIterator first, InputIterator beyond, + long log_radius, + const Traits_& traits = Traits_() + ); + + template + OutputIterator operator()(OutputIterator oi, long prec); + + int degree() const { return degree_; } + + void set_traits(Traits& traits) { + approximator_ = traits.approximator_object(); + lower_bound_log2_abs_ = traits.lower_bound_log2_abs_object(); + } +}; // class Bitstream_bernstein_from_power + +// static member definition +template +std::map > +Bitstream_bernstein_from_power::mn_cache_; + +// non-member functions +template +template +Bitstream_bernstein_from_power::Bitstream_bernstein_from_power( + InputIterator first, InputIterator beyond, + long log_radius, + const Traits_& traits // = Traits_() +) : input_power_coeff_(first, beyond), + degree_(int(input_power_coeff_.size() - 1)), + log_radius_(log_radius), + approximator_(traits.approximator_object()), + lower_bound_log2_abs_(traits.lower_bound_log2_abs_object()) +{ + CGAL_assertion(degree_ >= 0); + lbd_log_lcoeff_ = lower_bound_log2_abs_(input_power_coeff_[degree_]); + if (degree_ == 2) { + ceil_log_degfac_ = floor_log_degfac_ = 1; + ceil_log_degp1_ = 2; + } else { + ceil_log_degfac_ + = Ceil_log2_abs_Integer() + (CGAL::internal:: + caching_factorial(degree_)); + floor_log_degfac_ + = ceil_log_degfac_ - 1; + ceil_log_degp1_ + = Ceil_log2_abs_long()(degree_ + 1); + } + log_lcfscale_ + = lbd_log_lcoeff_ + floor_log_degfac_ + degree_ * (log_radius+1); +} + +template +template +OutputIterator +Bitstream_bernstein_from_power::operator()( + OutputIterator oi, + long prec // $ = p+1$ in [E08] +) { + CGAL_precondition(degree_ >= 0); + + // try to produce output from existing coefficient approximations + if (!bernstein_coeff_.empty()) { + long delta_prec = bernstein_coeff_prec_ - prec; + if (delta_prec == 0) { + for (int i = 0; i <= degree_; ++i) { + *oi = bernstein_coeff_[i]; + ++oi; + } + return oi; + } else if (delta_prec > 0) { + Integer half = Integer(1) << (delta_prec-1); + for (int i = 0; i <= degree_; ++i) { + *oi = (bernstein_coeff_[i] + half) >> delta_prec; + ++oi; + } + return oi; + } + // else delta_prec < 0: fall through to precision increase + } else { + bernstein_coeff_.resize(degree_ + 1); + } + + // compute coefficients at new precision + Integer_vector c(degree_ + 1); + long q = prec + ceil_log_degfac_ + ceil_log_degp1_ + 1; + for (int j = 0; j <= degree_; ++j) { + c[j] = approximator_( + input_power_coeff_[j], + j*log_radius_ - log_lcfscale_ + q + ); + } + const Mn& mn = get_mn(degree_); + long shift = q - prec; + Integer half = Integer(1) << (shift-1); + for (int i = 0; i <= degree_; ++i) { + Integer bi(0); + for (int j = 0; j <= degree_; ++j) bi += mn(i,j) * c[j]; + bernstein_coeff_[i] = (bi + half) >> shift; + } + bernstein_coeff_prec_ = prec; + + // output new approximations + for (int i = 0; i <= degree_; ++i) { + *oi = bernstein_coeff_[i]; + ++oi; + } + return oi; +} + +} // namespace internal + + +/* + * The generic de Casteljau method + */ + +template +class Convex_combinator_approx_Integer_log { +public: + typedef Integer_ Integer; + +private: + Integer alpha_num_, beta_num_, half_; + int log_denom_; + +public: + Convex_combinator_approx_Integer_log( + Integer alpha_num = Integer(1), int log_denom = 1 + ) : alpha_num_(alpha_num), + beta_num_((Integer(1) << log_denom) - alpha_num), + half_((log_denom > 0) ? (Integer(1) << log_denom-1) : 0), + log_denom_(log_denom) + { + CGAL_precondition(log_denom_ >= 0); + } + void into_first(Integer& a, const Integer& b) const { + a *= alpha_num_; a += beta_num_*b; + a += half_; a >>= log_denom_; // round to nearest + } + void into_second(const Integer& a, Integer& b) const { + b *= beta_num_; b += alpha_num_*a; + b += half_; b >>= log_denom_; // round to nearest + } + void into_third(const Integer& a, const Integer& b, Integer& c) const { + c = a; c *= alpha_num_; c += beta_num_*b; // c might alias a but not b + c += half_; c >>= log_denom_; // round to nearest + } +}; + +template +class Convex_combinator_approx_fraction { +public: + typedef NT_ NT; +private: + NT alpha_num_, beta_num_, denom_, half_; +public: + Convex_combinator_approx_fraction(NT alpha_num, NT denom) + : alpha_num_(alpha_num), beta_num_(denom - alpha_num), + denom_(denom), half_(denom >> 1) + { } + void into_first(NT& a, const NT& b) const { + a *= alpha_num_; a += beta_num_*b; + a += half_; a /= denom_; // round to nearest + } + void into_second(const NT& a, NT& b) const { + b *= beta_num_; b += alpha_num_*a; + b += half_; b /= denom_; // round to nearest + } + void into_third(const NT& a, const NT& b, NT& c) const { + c = a; c *= alpha_num_; c += beta_num_*b; // c might alias a but not b + c += half_; c /= denom_; // round to nearest + } +}; // class Convex_combinator_approx_fraction + +namespace internal { + +/* + * THE ACTUAL TREE CLASSES + */ +template +class Bitstream_descartes_E08_tree; + +template + struct Bitstream_descartes_E08_node; + + template + class Bitstream_descartes_E08_tree_rep; +} // namespace internal + +} //namespace CGAL + +/* The template argument supplied as BitstreamDescartesE08TreeTraits + * shall be a class containing the following types in its scope: + * Coefficient: caller-supplied coefficient type + * Bound: type for interval bound output (exact) + * Integer: integer type for actual calculations, needs >>, << + * Approximator: functor to get Integer approx to x*2^p from coeff x + * Lower_bound_log2_abs: functor for lower bound to log|x| for coeff x + * Bound_creator: functor to create bound x*2^p from x and p + * Sign: functor to get sign of Integer x + * Ceil_log2_abs_Integer: functor to get smallest long >= log|x| for Integer + * Ceil_log2_abs_long: functor to get smallest long >= log|x| for long + */ + +/* + * macros for common typedefs + */ + +// bring types from traits into local scope +#define CGAL_SNAP_BITSTREAM_DESCARTES_E08_TREE_TRAITS_TYPEDEFS(TRAITS) \ + typedef typename TRAITS::Coefficient Coefficient; \ + typedef typename TRAITS::Bound Bound; \ + typedef typename TRAITS::Integer Integer; \ + typedef typename TRAITS::Approximator Approximator; \ + typedef typename TRAITS::Lower_bound_log2_abs Lower_bound_log2_abs; \ + typedef typename TRAITS::Bound_creator Bound_creator; \ + typedef typename TRAITS::Sign Sign; \ + typedef typename TRAITS::Ceil_log2_abs_Integer Ceil_log2_abs_Integer; \ + typedef typename TRAITS::Ceil_log2_abs_long Ceil_log2_abs_long \ + +// end #define + +// common typedefs for all Bitstream_descartes_E08_* classes +#define CGAL_BITSTREAM_DESCARTES_E08_TREE_COMMON_TYPEDEFS \ + typedef BitstreamDescartesE08TreeTraits TRAITS; \ + typedef TRAITS Bitstream_descartes_E08_tree_traits; \ + CGAL_SNAP_BITSTREAM_DESCARTES_E08_TREE_TRAITS_TYPEDEFS(TRAITS); \ + typedef CGAL::internal::Bitstream_bernstein_from_power B_from_p; \ + typedef std::vector Integer_vector; \ + typedef CGAL::internal::Abs_le_pow2 \ + Abs_le_pow2; \ + typedef CGAL::internal::Sign_eps_log2 \ + \ + Sign_eps_log2 \ + +// end #define + +// typedefs for Bitstream_descartes_E08_tree{,_rep} +#define CGAL_BITSTREAM_DESCARTES_E08_TREE_TYPEDEFS \ + CGAL_BITSTREAM_DESCARTES_E08_TREE_COMMON_TYPEDEFS; \ + typedef CGAL::internal::Bitstream_descartes_E08_node Node; \ + typedef std::list Node_list \ + +// end #define + + +namespace CGAL { + +namespace internal { + +/* + * class Bitstream_descartes_E08_node + */ + +template +struct Bitstream_descartes_E08_node { +public: + typedef Bitstream_descartes_E08_node Self; + CGAL_BITSTREAM_DESCARTES_E08_TREE_COMMON_TYPEDEFS; + + friend class CGAL::internal::Bitstream_descartes_E08_tree; + friend class CGAL::internal::Bitstream_descartes_E08_tree_rep; + +private: + // "node data" (set individually in subdivision) + Integer lower_num_, upper_num_; // TODO use lower_num_, width_num_ instead + long log_bdry_den_; + Integer_vector coeff_; // wrt [lower_, upper_], approximate + int min_var_, max_var_; + bool coeff_update_delayed_; + // "state data" (copied en bloc by .copy_state_from()) + long subdepth_bound_, subdepth_current_; + long log_eps_; // $q - p$ + long log_C_eps_; // $q - p + 4n$ + + Bitstream_descartes_E08_node(int degree = -1, + Integer lower_num = Integer(0), Integer upper_num = Integer(0), + long log_bdry_den = 0, int min_var = -1, int max_var = -1 + ) : lower_num_(lower_num), upper_num_(upper_num), + log_bdry_den_(log_bdry_den), + coeff_(degree+1), + min_var_(min_var), max_var_(max_var), + coeff_update_delayed_(false), + subdepth_bound_(0), subdepth_current_(0), + log_eps_(0), log_C_eps_(0) + { } + + void copy_state_from(const Self& n) { + subdepth_bound_ = n.subdepth_bound_; + subdepth_current_ = n.subdepth_current_; + log_eps_ = n.log_eps_; + log_C_eps_ = n.log_C_eps_; + } + + // const Self& operator= (const Self&); // assignment is forbidden +}; // struct Bitstream_descartes_E08_node + + +/* + * class Bitstream_descartes_E08_tree_rep + */ + +template +class Bitstream_descartes_E08_tree_rep { +public: + typedef Bitstream_descartes_E08_tree_rep Self; + CGAL_BITSTREAM_DESCARTES_E08_TREE_TYPEDEFS; + + class Monomial_basis_tag { }; + + friend class CGAL::internal::Bitstream_descartes_E08_tree; + +private: + B_from_p b_from_p_; + long log_radius_; + int degree_; + long ceil_log_degree_; + Node_list node_list_; + + long payload_prec_; + int subdiv_tries_, subdiv_fails_; + int bisect_tries_, bisect_fails_; + + // temporary data fields for subdivision + Integer_vector tmp1_coeff_, tmp2_coeff_; + Integer splitpoint_num_; + long log_splitpoint_den_; + +public: + Bitstream_descartes_E08_tree_rep() : degree_(-1) { } + + template + Bitstream_descartes_E08_tree_rep( + long log_radius, + InputIterator first, InputIterator beyond, Monomial_basis_tag, + const TRAITS& traits + ) : b_from_p_(first, beyond, log_radius, traits), + log_radius_(log_radius), + subdiv_tries_(0), subdiv_fails_(0), + bisect_tries_(0), bisect_fails_(0), + splitpoint_num_(0), log_splitpoint_den_(0) + { + degree_ = b_from_p_.degree(); + CGAL_precondition(degree_ >= 0); + ceil_log_degree_ = (degree_ > 0) ? Ceil_log2_abs_long()(degree_) : -1; + node_list_.push_front( + Node(degree_, Integer(-1), Integer(1), -log_radius) + ); + payload_prec_ = 6 * degree_ + 20; + tmp1_coeff_.resize(degree_ + 1); + tmp2_coeff_.resize(degree_ + 1); + } +}; // class Bitstream_descartes_E08_tree_rep + +/* + * class Bitstream_descartes_E08_tree + */ + +/*! \ingroup CGAL_Bitstream_descartes_tree + * \brief Subdivision tree of the BitstreamDescartes method (E08 variant) + */ +template +class Bitstream_descartes_E08_tree + : public + ::CGAL::Handle_with_policy< + internal::Bitstream_descartes_E08_tree_rep< + BitstreamDescartesE08TreeTraits + > + > +{ +public: + typedef Bitstream_descartes_E08_tree Self; + CGAL_BITSTREAM_DESCARTES_E08_TREE_TYPEDEFS; + typedef internal::Bitstream_descartes_E08_tree_rep Rep; + typedef ::CGAL::Handle_with_policy Base; + + //! node iterator. + typedef typename Node_list::iterator Node_iterator; + //! node iterator (for STL compatibility only). + typedef typename Node_list::iterator iterator; + //! const node iterator. + typedef typename Node_list::const_iterator Node_const_iterator; + //! const node iterator (for STL compatibility only). + typedef typename Node_list::const_iterator const_iterator; + + //! tag type to distinguish a certain constructor. + typedef typename Rep::Monomial_basis_tag Monomial_basis_tag; + +public: + //! default constructor (makes degree() == -1) + Bitstream_descartes_E08_tree() : Base(Rep()) { } + + //! copy constructor + Bitstream_descartes_E08_tree(const Self& p) + : Base(static_cast(p)) + { } + + /*! \brief construct from initial interval and coefficients + * + * The initial interval is + * [\c lower_num, \c upper_num] / 2^(\c log_bdry_den ). + * + * The iterator range [\c first, \c beyond ) gives the + * coefficients of 1, x, x2, ... + * The leading coefficient (last in sequence) must be non-zero. + * + * The \c Monomial_basis_tag is required for the benefit of + * future extensions to coefficients w.r.t. other bases. + */ + template + Bitstream_descartes_E08_tree( + long log_radius, + InputIterator first, InputIterator beyond, Monomial_basis_tag tag, + const BitstreamDescartesE08TreeTraits& traits + = BitstreamDescartesE08TreeTraits() + ) : Base(Rep(log_radius, first, beyond, tag, traits)) + { + Node_iterator n = this->ptr()->node_list_.begin(); + if (this->ptr()->degree_ > 0) { + bool init_ok = reinit_from_prec(n); + CGAL_assertion(init_ok); (void)init_ok; + if (n->min_var_ == 0) this->ptr()->node_list_.erase(n); + } else { + this->ptr()->node_list_.erase(n); + } + } + + //! return degree of polynomial + int degree() const { return this->ptr()->degree_; } + + //! iterator to first node + Node_iterator begin() { + return this->ptr()->node_list_.begin(); + } + //! iterator beyond last node + Node_iterator end() { + return this->ptr()->node_list_.end(); + } + //! const iterator to first node + Node_const_iterator begin() const { + return this->ptr()->node_list_.begin(); + } + //! const iterator beyond last node + Node_const_iterator end() const { + return this->ptr()->node_list_.end(); + } + + //! get lower bound of interval at node \c n. + Bound lower(Node_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return Bound_creator()(n->lower_num_, -n->log_bdry_den_); + } + //! get lower bound of interval at node \c n. + Bound lower(Node_const_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return Bound_creator()(n->lower_num_, -n->log_bdry_den_); + } + //! get upper bound of interval at node \c n. + Bound upper(Node_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return Bound_creator()(n->upper_num_, -n->log_bdry_den_); + } + //! get upper bound of interval at node \c n. + Bound upper(Node_const_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return Bound_creator()(n->upper_num_, -n->log_bdry_den_); + } + + //! get boundaries: interval at node \c n is + //! [\c lower_num, \c upper_num] / 2^(\c log_bdry_den ). + void boundaries(Node_iterator n, + Integer& lower_num, Integer& upper_num, long& log_bdry_den + ) { + CGAL_assertion(is_iterator_valid(n)); + lower_num = n->lower_num_; + upper_num = n->upper_num_; + log_bdry_den = n->log_bdry_den_; + } + + //! get minimum number of sign variations in Descartes Test + //! for approximate polynomial at node \c n + int min_var(Node_const_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return n->min_var_; + } + //! get maximum number of sign variations in Descartes Test + //! for approximate polynomial at node \c n + int max_var(Node_const_iterator n) const { + CGAL_assertion(is_iterator_valid(n)); + return n->max_var_; + } + + /*! \brief subdivide interval at node \c n. + * + * The node representing interval \c n is replaced in the list + * of nodes by 0, 1, or 2 nodes that represent those among the + * two subintervals that have \c min_var() greater than 0. + * The number of new nodes is returned as result. + * The subrange of nodes consisting of the new nodes is + * returned in the arguments \c first and \c beyond + * + * Subdividing a node invalidates all iterators to it; + * both for the object where \c subdivide() was called + * and all copies of it (since they share the same + * representation and state). + * + * The parameter \c n is passed by value. Hence you can + * implement depth-first search for isolating intervals like this: + * \code + * Node_iterator dummy, curr = tree.begin(); + * while (curr != tree.end()) { + * if (tree.max_var(curr) == 1) ++curr; + * else tree.subdivide(curr, curr, dummy); + * } + * \endcode + */ + int subdivide( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + /*! \brief erase node \c n. + * + * Erasing a node invalidates all iterators to it; + * both for the object where \c subdivide() was called + * and all copies of it (since they share the same + * representation and state). + */ + void erase(Node_iterator n) { + CGAL_assertion(is_iterator_valid(n)); + this->ptr()->node_list_.erase(n); + } + + /*! \brief Replace traits class + */ + void set_traits(TRAITS& traits) { + this->ptr()->b_from_p_.set_traits(traits); + } + + /*! \brief Returns a copy of this with its own representation + */ + Self make_unique() const { + Self tmp = *this; + tmp.copy_on_write(); + return tmp; + } + +protected: + int subdivide_at_midpoint( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + int subdivide_at( + Node_iterator n, Node_iterator& first, Node_iterator& beyond, + long alpha_num, int log_alpha_den + ); + + bool is_iterator_valid(Node_const_iterator n) const { + Node_const_iterator it = this->ptr()->node_list_.begin(); + Node_const_iterator end = this->ptr()->node_list_.end(); + while (it != end) { + if (it == n) return true; + ++it; + } + return false; + } + +private: + int replace_by_tmp( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + static const long log_subdepth_bound_init_ = 6; + + bool reinit_from_prec(Node_iterator n); + void global_prec_increase(Node_iterator n); + +}; // class Bitstream_descartes_E08_tree + +template +const long +Bitstream_descartes_E08_tree +::log_subdepth_bound_init_; + + + +/* + * Non-inline member functions of class Bitstream_descartes_E08_tree + */ + +template +bool +Bitstream_descartes_E08_tree +::reinit_from_prec(Node_iterator n) { + + n->subdepth_bound_ = 1L << log_subdepth_bound_init_; + n->subdepth_current_ = 0; + n->log_eps_ = this->ptr()->ceil_log_degree_ + + log_subdepth_bound_init_ + + 1; + n->log_C_eps_ = n->log_eps_ + 4*this->degree(); + + this->ptr()->b_from_p_( + this->ptr()->tmp1_coeff_.begin(), + this->ptr()->payload_prec_ + 1 + ); + for (int i = 0; i <= degree(); ++i) { // TODO avoid preceding rshift + this->ptr()->tmp1_coeff_[i] <<= (n->log_eps_ - 1); + } + + Integer alpha_num = + (Integer(1) << (n->log_bdry_den_ + this->ptr()->log_radius_)) + - n->lower_num_; + long log_alpha_den = n->log_bdry_den_ + this->ptr()->log_radius_ + 1; + if (alpha_num != Integer(1) << log_alpha_den) { + de_casteljau_generic( + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp1_coeff_.end(), + this->ptr()->tmp2_coeff_.begin(), this->ptr()->tmp1_coeff_.begin(), + Convex_combinator_approx_Integer_log( + alpha_num, log_alpha_den + ) + ); + ++(n->subdepth_current_); + } + alpha_num = + (Integer(1) << (n->log_bdry_den_ + this->ptr()->log_radius_)) + - n->upper_num_; + if (alpha_num != Integer(0)) { + Integer alpha_den = + (Integer(1) << (n->log_bdry_den_ + this->ptr()->log_radius_)) + - n->lower_num_; + de_casteljau_generic( + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp1_coeff_.end(), + n->coeff_.begin(), this->ptr()->tmp1_coeff_.begin(), + Convex_combinator_approx_fraction(alpha_num, alpha_den) + ); + ++(n->subdepth_current_); + } else { + n->coeff_.swap(this->ptr()->tmp1_coeff_); + } + + if (Abs_le_pow2()(n->coeff_[degree()], n->log_C_eps_) + || Abs_le_pow2()(n->coeff_[0], n->log_C_eps_) + ) { + return false; + } else { + internal::var_eps(n->coeff_.begin(), n->coeff_.end(), + n->min_var_, n->max_var_, Sign_eps_log2(n->log_eps_) + ); + return true; + } +} // Bitstream_descartes_E08_tree::reinit_from_sep() + +template +int +Bitstream_descartes_E08_tree +::subdivide_at_midpoint( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + de_casteljau_generic(n->coeff_.begin(), n->coeff_.end(), + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp2_coeff_.begin(), + CGAL::internal::Convex_combinator_approx_midpoint() + ); + this->ptr()->splitpoint_num_ = n->lower_num_ + n->upper_num_; + this->ptr()->log_splitpoint_den_ = n->log_bdry_den_ + 1; + + if (Abs_le_pow2()(this->ptr()->tmp2_coeff_[0], n->log_C_eps_)) { + return -1; + } else { + return replace_by_tmp(n, first, beyond); + } +} // Bitstream_descartes_E08_tree::subdivide_at() + +template +int +Bitstream_descartes_E08_tree +::subdivide_at( + Node_iterator n, Node_iterator& first, Node_iterator& beyond, + long alpha_num, int log_alpha_den +) { + de_casteljau_generic(n->coeff_.begin(), n->coeff_.end(), + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp2_coeff_.begin(), + CGAL::internal::Convex_combinator_approx_long_log + (alpha_num, log_alpha_den) + ); + this->ptr()->splitpoint_num_ = + alpha_num * n->lower_num_ + + ((1L << log_alpha_den) - alpha_num) * n->upper_num_; + this->ptr()->log_splitpoint_den_ = n->log_bdry_den_ + log_alpha_den; + + if (Abs_le_pow2()(this->ptr()->tmp2_coeff_[0], n->log_C_eps_)) { + return -1; + } else { + return replace_by_tmp(n, first, beyond); + } +} // Bitstream_descartes_E08_tree::subdivide_at() + + +template +int +Bitstream_descartes_E08_tree +::replace_by_tmp( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + + ++(n->subdepth_current_); + + long delta_log_bdry_den = + this->ptr()->log_splitpoint_den_ - n->log_bdry_den_; + CGAL_assertion(delta_log_bdry_den >= 0); + + int l_min_var, l_max_var, r_min_var, r_max_var; + internal::var_eps(this->ptr()->tmp1_coeff_.begin(), + this->ptr()->tmp1_coeff_.end(), + l_min_var, l_max_var, + Sign_eps_log2(n->log_eps_) + ); + internal::var_eps(this->ptr()->tmp2_coeff_.begin(), + this->ptr()->tmp2_coeff_.end(), + r_min_var, r_max_var, Sign_eps_log2(n->log_eps_) + ); + CGAL_assertion(0 <= l_min_var && l_min_var <= l_max_var); + CGAL_assertion(0 <= r_min_var && r_min_var <= r_max_var); + + beyond = first = n; + ++beyond; + + if (l_min_var > 0) { + int children = 1; + if (r_min_var > 0) { + // create new node for right child + Node_iterator r = + this->ptr()->node_list_.insert(beyond, Node(degree(), + this->ptr()->splitpoint_num_, // lower + n->upper_num_ << delta_log_bdry_den, // upper + this->ptr()->log_splitpoint_den_, + r_min_var, r_max_var + )); + r->coeff_.swap(this->ptr()->tmp2_coeff_); + r->copy_state_from(*n); + ++children; + } + // put left child into n + n->lower_num_ <<= delta_log_bdry_den; + n->upper_num_ = this->ptr()->splitpoint_num_; + n->log_bdry_den_ = this->ptr()->log_splitpoint_den_; + n->min_var_ = l_min_var; + n->max_var_ = l_max_var; + n->coeff_.swap(this->ptr()->tmp1_coeff_); + return children; + } else if (r_min_var > 0) { + // put right child into n + n->lower_num_ = this->ptr()->splitpoint_num_; + n->upper_num_ <<= delta_log_bdry_den; + n->log_bdry_den_ = this->ptr()->log_splitpoint_den_; + n->min_var_ = r_min_var; + n->max_var_ = r_max_var; + n->coeff_.swap(this->ptr()->tmp2_coeff_); + return 1; + } else /* l_min_var == 0 && r_min_var == 0 */ { + // delete n + first = beyond; + this->ptr()->node_list_.erase(n); + return 0; + } +} // Bitstream_descartes_E08_tree::replace_by_tmp() + +template +int +Bitstream_descartes_E08_tree +::subdivide( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + long alpha_num; + int log_alpha_den; + long alpha_den_4; + int ret; + + CGAL_assertion(is_iterator_valid(n)); + + // check for delayed update + if (n->coeff_update_delayed_) { + reinit_from_prec(n); + n->coeff_update_delayed_ = false; + } + + // apply Zeno trap + if (n->subdepth_current_ == n->subdepth_bound_) { + for (int i = 0; i <= degree(); ++i) n->coeff_[i] <<= 2; + // n->working_prec_ += 2; + n->log_eps_ += 2; + n->log_C_eps_ += 2; + n->subdepth_bound_ <<= 1; + n->subdepth_current_ = 0; + } + + for (;;) { + if (true) { // used to be recdepth > 0 + // first try heuristic alpha = 1/2 (failures don't count) + ++(this->ptr()->bisect_tries_); + ret = subdivide_at_midpoint(n, first, beyond); + if (ret >= 0) { return ret; } else { ++(this->ptr()->bisect_fails_); } + + // next try heuristic alpha with small denom (failures don't count) + log_alpha_den = 4; + alpha_den_4 = 1L << (log_alpha_den - 2); + alpha_num = CGAL::default_random.get_int( // TODO .get_long + alpha_den_4, 3*alpha_den_4 + 1 + ); + ++(this->ptr()->subdiv_tries_); + ret = subdivide_at(n, first, beyond, alpha_num, log_alpha_den); + if (ret >= 0) { return ret; } else { --(this->ptr()->subdiv_tries_); } + + // now try alpha properly randomized, counting failure rate + log_alpha_den = 4 + this->ptr()->ceil_log_degree_; + alpha_den_4 = 1L << (log_alpha_den - 2); + do { + alpha_num = CGAL::default_random.get_int( // TODO .get_long + alpha_den_4, 3*alpha_den_4 + 1 + ); + ++(this->ptr()->subdiv_tries_); + ret = subdivide_at(n, first, beyond, alpha_num, log_alpha_den); + if (ret >= 0) { + return ret; + } else { + ++(this->ptr()->subdiv_fails_); + } + } while ( +(this->ptr()->subdiv_fails_ < 2 || 2 * this->ptr()->subdiv_fails_ < this->ptr()->subdiv_tries_) +&& (this->ptr()->bisect_fails_ < degree()) + ); + } // if (true) // used to be recdepth > 0 + + // if failure rate too high, decrease guess of prec and restart + global_prec_increase(n); + // TODO what if now n->max_var_ == 1 ?? + } // for (;;) +} // Bitstream_descartes_E08_tree::subdivide() + +template +void +Bitstream_descartes_E08_tree +::global_prec_increase(Node_iterator n) +{ + this->ptr()->payload_prec_ *= 2; + + this->ptr()->subdiv_tries_ = this->ptr()->subdiv_fails_ = 0; + this->ptr()->bisect_tries_ = this->ptr()->bisect_fails_ = 0; + + Node_iterator it = this->ptr()->node_list_.begin(); + Node_iterator end = this->ptr()->node_list_.end(); + while (it != end) { + if (it != n && it->min_var_ == it->max_var_) { + it->coeff_update_delayed_ = true; + } else { + bool reinit_ok = reinit_from_prec(it); + CGAL_assertion(reinit_ok); (void)reinit_ok; + it->coeff_update_delayed_ = false; + } + ++it; + } +} // Bitstream_descartes_E08_tree::global_prec_increase() + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_BITSTREAM_DESCARTES_E08_TREE_H + +// EOF diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree.h new file mode 100644 index 00000000000..4f31eb389b4 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree.h @@ -0,0 +1,1572 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Arno Eigenwillig +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file NiX/Bitstream_descartes_rndl_tree.h + \brief Definition of \c NiX::Bitstream_descartes_rndl_tree. +*/ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_H +#define CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_H + +#include +#include +#include +#include +#include + +#include +#include + +#include +/*#include +#include */ + +/* + * AUXILIARY CLASSES AND FUNCTIONS + */ + +namespace CGAL { + +namespace internal { + +// TODO: Copied from CGAL/enums.h: +enum Three_valued_estimate { + CLEARLY_NEGATIVE = -1, //!< = -1. Sign of a value is clearly + //!< negative. + UNCLEAR_SIGN = 0, //!< = 0. It is unclear whether value + //!< has negative, zero, or positive + //!< sign. + CLEARLY_POSITIVE = 1, //!< = +1. Sign of a value is clearly + //!< positive. + + CLEARLY_LESS = -1, //!< = -1. First value is clearly less + //!< than second value. + UNCLEAR_COMPARISON = 0, //!< = 0. It is unclear whether first value + //!< is less than, equal to, or + //!< greater than second value. + CLEARLY_GREATER = 1, //!< = +1. First value is clearly greater + //!< than second value. + + CLEARLY_CLOCKWISE = -1, //!< = -1. Points in the plane or space are + //!< clearly oriented clockwise. + CLEAR_RIGHT_TURN = -1, //!< = -1. Points in the plane or space + //!< clearly form a right turn. + UNCLEAR_ORIENTATION = 0, //!< = 0. It is not clear whether points in + //!< the plane or space are oriented + //!< clockwise, counterclockwise, or + //!< are in degenerate position. + + UNCLEAR_TURN = 0, //!< = 0. It is not clear whether points in + //!< the plane or space form a left + //!< turn, a right turn, or are in + //!< degenerate position. + CLEAR_LEFT_TURN = 1, //!< = +1. Points in the plane or space + //!< clearly form a left turn. + CLEARLY_COUNTERCLOCKWISE = 1, //!< = +1. Points in the plane or space are + //!< clearly oriented + //!< counterclockwise. + + CLEARLY_ON_NEGATIVE_SIDE = -1, //!< = -1. Point is clearly on the negative + //!< side of an oriented surface. + ON_UNCLEAR_ORIENTED_SIDE = 0, //!< = 0. It is unclear whether point is + //!< outside, on, or inside an + //!< oriented surface. + CLEARLY_ON_POSITIVE_SIDE = 1, //!< = +1. Point is clearly on the positive + //!< side of an oriented surface. + + CLEARLY_ON_UNBOUNDED_SIDE = -1, //!< = -1. Point is clearly in the + //!< exterior of a closed surface. + ON_UNCLEAR_SIDE = 0, //!< = 0. It is unclear whether point is + //!< outside, on, or inside a closed + //!< surface. + CLEARLY_ON_BOUNDED_SIDE = 1 //!< = 1. Point is clearly in the + //!< interior of a closed surface. +}; + +//! reverses the \a sign (from plus to minus and minus to plus ;-) +inline Three_valued_estimate operator- ( Three_valued_estimate sign ) { + return Three_valued_estimate( - int( sign)); +} + + +// END: Copied from CGAL/enums.h + +/* + * Helper functions + */ + +// compute g(x) = 2^p f((ax+b)/c) for c = 2^log_c with absolute error <= 1 +template +OutputIterator +polynomial_affine_transform_approx_log_denom( + RandomAccessIterator first, RandomAccessIterator beyond, + OutputIterator out, + Integer a, Integer b, long log_c, + long p, + Approximator approx, + CeilLog2AbsInteger log, CeilLog2AbsLong logl +) { + // degree of input polynomial + const int n = int((beyond-first)-1); + CGAL_precondition(n >= 0); + + // u[i][j] = \binom{i}{j} a^j b^{i-j} (0 <= i <= n; 0 <= j <= i) + long max_log_u; // = \max_{i,j} \log\abs{u[i][j]} + std::vector< std::vector< Integer > > u(n+1); + u[0].push_back(Integer(1)); + max_log_u = 0; // = log(1) + for (int i = 1; i <= n; ++i) { + u[i].reserve(i+1); + u[i].push_back(b*u[i-1][0]); + if (u[i][0] != 0) max_log_u = (std::max)(max_log_u, log(u[i][0])); + for (int j = 1; j <= i-1; ++j) { + u[i].push_back(a*u[i-1][j-1] + b*u[i-1][j]); + if (u[i][j] != 0) max_log_u = (std::max)(max_log_u, log(u[i][j])); + } + u[i].push_back(a*u[i-1][i-1]); + if (u[i][i] != 0) max_log_u = (std::max)(max_log_u, log(u[i][i])); + } + + long q = logl(n+1) + max_log_u + 1; + Integer half = Integer(1) << q-1; + std::vector< Integer > h(n+1); + RandomAccessIterator it = first; + for (int i = 0; i <= n; ++i, ++it) { + h[i] = approx(*it, -i*log_c + p + q); + } + Integer sum; + for (int j = 0; j <= n; ++j) { + sum = 0; + for (int i = j; i <= n; ++i) { + sum += u[i][j]*h[i]; + } + sum += half; sum >>= q; // round to nearest + *out++ = sum; + } + return out; +} // polynomial_affine_transform_approx_log_denom() + + +template +Integer caching_factorial(int n) { + CGAL_precondition(n >= 0); + + // table of factorials; augment if necessary + static std::vector< Integer > factorial; + factorial.reserve(n+1); + if (factorial.empty()) { + factorial.push_back(Integer(1)); // 0! = 1 + factorial.push_back(Integer(1)); // 1! = 1 + } + for (int i = int(factorial.size()); i <= n; ++i) { + factorial.push_back(i*factorial[i-1]); + } + + return factorial[n]; +} + + +// Bernst coeff of 2^p n! f(x) wrt [lwr_num,upr_num]/2^log_den w/ abs err <= 1 +template +OutputIterator +polynomial_power_to_bernstein_approx( + RandomAccessIterator first, RandomAccessIterator beyond, + OutputIterator out, + Integer lower_num, Integer upper_num, long log_denom, + long p, + Approximator approx, CeilLog2AbsInteger log, CeilLog2AbsLong logl +) { + // degree of input polynomial + const int n = int((beyond-first)-1); + CGAL_precondition(n >= 0); + + long q = log(caching_factorial(n)) + logl(n+1) + 1; + Integer half = Integer(1) << q-1; + std::vector f(n+1); + polynomial_affine_transform_approx_log_denom( + first, beyond, f.begin(), + upper_num - lower_num, lower_num, log_denom, + p+q, + approx, log, logl + ); + Integer sum, lprod; + for (int l = 0; l <= n; ++l) { + sum = 0; + lprod = 1; // = l*(l-1)*(l-2)*...*(l-(k-1)) + for (int k = 0; k <= l; ++k) { + sum += lprod * caching_factorial(n-k) * f[k]; + lprod *= l-k; + } + sum += half; sum >>= q; // round to nearest + *out++ = sum; + } + return out; +} // polynomial_power_to_bernstein_approx() + + +// min/max number of variations in epsilon-sign +template +void var_eps( + InputIterator first, InputIterator beyond, + int& min_var, int& max_var, + const UnaryFunction& sign_eps +) { + min_var = max_var = 0; + InputIterator it = first; + CGAL_precondition(it != beyond); + + internal::Three_valued_estimate last_sign_min, last_sign_max; // always non-zero + last_sign_min = last_sign_max = sign_eps(*it); + CGAL_assertion(last_sign_min != internal::UNCLEAR_SIGN); + + while (++it != beyond) { + internal::Three_valued_estimate cur_sign = sign_eps(*it); + if (cur_sign == internal::UNCLEAR_SIGN) { + last_sign_max = -last_sign_max; + ++max_var; + } else { + if (last_sign_max != cur_sign) ++max_var; + if (last_sign_min != cur_sign) ++min_var; + last_sign_min = last_sign_max = cur_sign; + } + } +} // var_eps() + +/* + * The generic de Casteljau method + */ + +template +class Convex_combinator_generic { +public: + typedef NT_ NT; +private: + NT alpha_, beta_; +public: + Convex_combinator_generic(NT alpha) : alpha_(alpha), beta_(NT(1)-alpha) { } + void into_first (NT& a, const NT& b) const { a *= alpha_; a += beta_*b; } + void into_second(const NT& a, NT& b) const { b *= beta_; b += alpha_*a; } + void into_third (const NT& a, const NT& b, NT& c) const { + c = a; c *= alpha_; c += beta_*b; // c might alias a but not b + } +}; + +template +class Convex_combinator_approx_long_log { +public: + typedef NT_ NT; + +private: + long alpha_num_, beta_num_, half_; + int log_denom_; + +public: + Convex_combinator_approx_long_log( + long alpha_num = 1, int log_denom = 1 + ) : alpha_num_(alpha_num), + beta_num_((1L< 0) ? (1L << (log_denom-1)) : 0), + log_denom_(log_denom) + { + CGAL_precondition(log_denom_ >= 0); + } + void into_first(NT& a, const NT& b) const { + a *= alpha_num_; a += beta_num_*b; + a += half_; a >>= log_denom_; // round to nearest + } + void into_second(const NT& a, NT& b) const { + b *= beta_num_; b += alpha_num_*a; + b += half_; b >>= log_denom_; // round to nearest + } + void into_third(const NT& a, const NT& b, NT& c) const { + c = a; c *= alpha_num_; c += beta_num_*b; // c might alias a but not b + c += half_; c >>= log_denom_; // round to nearest + } +}; + +template +class Convex_combinator_approx_midpoint { +public: + typedef NT_ NT; + +public: + void into_first(NT& a, const NT& b) const { + a += b; + a += 1; a >>= 1; // round to nearest + } + void into_second(const NT& a, NT& b) const { + b += a; + b += 1; b >>= 1; // round to nearest + } + void into_third(const NT& a, const NT& b, NT& c) const { + c = a; c += b; // c might alias a but not b + c += 1; c >>= 1; // round to nearest + } +}; + +template +std::pair +de_casteljau_generic( + ForwardIterator1 first, ForwardIterator1 beyond, + ForwardIterator2 left, ForwardIterator3 right, + const Combinator& combine +) { + // left may not alias any of the other two + CGAL_assertion((void*)(&(*left)) != (void*)(&(*first))); + CGAL_assertion((void*)(&(*left)) != (void*)(&(*right))); + + /* In the sequel, we think of de Casteljau's algorithm as + * filling out a triangular array of numbers: + * + * * * * .. * row 0 + * * * .. * row 1 + * . . . + * . . . + * * + * + * The inputs [first, beyond) form row 0 (at the top). + * Row 1 (below row 0) consists of combinations of any two + * adjacent elements from row 0. + * Inductively, row i+1 consists of combinations of any two + * adjacent elements from row i, until we arrive at a row + * of length 1. + * + * We output through iterator left the values appearing + * on the triangle's left side. + * + * We use the container pointed to by iterator right as + * storage for the rows (one after the other). + * Since each row is one element shorter than the preceding + * one, towards the end of this container the values appearing + * on the triangle's right accumulate. When we terminate, + * the container pointed to by iterator right contains + * the triangle's right side, from bottom to top. + */ + + *left = *first; ++left; // output leftmost element of row 0 + + // to compute row 1, we iterate over pairs (*iit1, *iit2) + // of adjacent elements of row 0 and combine them into *rit1 + ForwardIterator1 iit1 = first, iit2 = first; ++iit2; // source + ForwardIterator3 rit1 = right; // target + for (;;) { + combine.into_third(*iit1, *iit2, *rit1); + ++iit1; ++iit2; + if (iit2 == beyond) break; + ++rit1; + } + ForwardIterator3 right_end = rit1; // point to rightmost element of row 1 + *++rit1 = *iit1; // output rightmost element of row 0 + ForwardIterator3 right_beyond = ++rit1; // past-the-end + *left = *right; ++left; // output leftmost element of row 1 + + // compute rows 2 and later in the same style + // invariant: right_end is the rightmost element of the previous row + ForwardIterator3 rit2; + while (right != right_end) { // prev row was longer than 1 element + rit1 = rit2 = right; ++rit2; + combine.into_first(*rit1, *rit2); + *left = *rit1; ++left; // output leftmost element + while (rit2 != right_end) { + ++rit1; ++rit2; + combine.into_first(*rit1, *rit2); + } + right_end = rit1; + } + + return std::make_pair(left, right_beyond); +} // de_casteljau_generic() + + + +/* + * Helper functors + */ + +template +class Abs_le_pow2 { +public: + typedef CeilLog2Abs Ceil_log2_abs; + typedef bool result_type; + typedef typename Ceil_log2_abs::argument_type first_argument_type; + typedef typename Ceil_log2_abs::result_type second_argument_type; + result_type operator() (first_argument_type x, second_argument_type p) { + return x == 0 || Ceil_log2_abs()(x) <= p; + } +}; + +template +class Sign_eps_log2 { +private: + long log_eps_; + +public: + typedef Integer_ Integer; + typedef AbsLePow2 Abs_le_pow2; + typedef Sign_ Sign; + typedef internal::Three_valued_estimate result_type; + typedef Integer argument_type; + + Sign_eps_log2(long log_eps = 0) : log_eps_(log_eps) { } + long log_eps() const { return log_eps_; } + void set_log_eps(long log_eps) { log_eps_ = log_eps; } + + result_type operator() (argument_type x) const { + if (Abs_le_pow2()(x, log_eps_)) { + return internal::UNCLEAR_SIGN; + } else { + return internal::Three_valued_estimate(Sign()(x)); + } + } +}; // class Sign_eps_log2 + +} // namespace internal + + +namespace internal { + template + class Bitstream_descartes_rndl_tree; + + template + struct Bitstream_descartes_rndl_node; + + template + class Bitstream_descartes_rndl_tree_rep; +} // namespace internal + +/* The template argument supplied as BitstreamDescartesRndlTreeTraits + * shall be a class containing the following types in its scope: + * Coefficient: caller-supplied coefficient type + * Bound: type for interval bound output (exact) + * Integer: integer type for actual calculations, needs >>, << + * Approximator: functor to get Integer approx to x*2^p from coeff x + * Lower_bound_log2_abs: functor for lower bound to log|x| for coeff x + * Bound_creator: functor to create bound x*2^p from x and p + * Sign: functor to get sign of Integer x + * Ceil_log2_abs_Integer: functor to get smallest long >= log|x| for Integer + * Ceil_log2_abs_long: functor to get smallest long >= log|x| for long + */ + +/* + * macros for common typedefs + */ + +// bring types from traits into local scope +#define CGAL_SNAP_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_TYPEDEFS(TRAITS) \ + typedef typename TRAITS::Coefficient Coefficient; \ + typedef typename TRAITS::Bound Bound; \ + typedef typename TRAITS::Integer Integer; \ + typedef typename TRAITS::Approximator Approximator; \ + typedef typename TRAITS::Lower_bound_log2_abs Lower_bound_log2_abs; \ + typedef typename TRAITS::Bound_creator Bound_creator; \ + typedef typename TRAITS::Sign Sign; \ + typedef typename TRAITS::Ceil_log2_abs_Integer Ceil_log2_abs_Integer; \ + typedef typename TRAITS::Ceil_log2_abs_long Ceil_log2_abs_long \ + +// end #define + +// common typedefs for all Bitstream_descartes_rndl_* classes +#define CGAL_BITSTREAM_DESCARTES_RNDL_TREE_COMMON_TYPEDEFS \ + typedef BitstreamDescartesRndlTreeTraits TRAITS; \ + typedef TRAITS Bitstream_descartes_rndl_tree_traits; \ + CGAL_SNAP_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_TYPEDEFS(TRAITS); \ + typedef std::vector Coefficient_vector; \ + typedef std::vector Integer_vector; \ + typedef internal::Abs_le_pow2 Abs_le_pow2; \ + typedef internal::Sign_eps_log2 \ + Sign_eps_log2 \ + +// end #define + +// typedefs for Bitstream_descartes_rndl_tree{,_rep} +#define CGAL_BITSTREAM_DESCARTES_RNDL_TREE_TYPEDEFS \ + CGAL_BITSTREAM_DESCARTES_RNDL_TREE_COMMON_TYPEDEFS; \ + typedef internal::Bitstream_descartes_rndl_node Node; \ + typedef std::list Node_list \ + +// end #define + + +namespace internal { + +/* + * class Bitstream_descartes_rndl_node + */ + +template +struct Bitstream_descartes_rndl_node { +public: + typedef Bitstream_descartes_rndl_node Self; + CGAL_BITSTREAM_DESCARTES_RNDL_TREE_COMMON_TYPEDEFS; + + friend class internal::Bitstream_descartes_rndl_tree; + friend class internal::Bitstream_descartes_rndl_tree_rep; + +private: + // "node data" (set individually in subdivision) + Integer lower_num_, upper_num_; // TODO use lower_num_, width_num_ instead + long log_bdry_den_; + Integer_vector coeff_; // wrt [lower_, upper_], approximate + int min_var_, max_var_; + // "state data" (copied en bloc by .copy_state_from()) + long subdiv_tries_, subdiv_fails_; + long recdepth_; + long log_sep_, delta_log_sep_, log_eps_, log_C_eps_; + + Bitstream_descartes_rndl_node(int degree = -1, + Integer lower_num = Integer(0), Integer upper_num = Integer(0), + long log_bdry_den = 0, int min_var = -1, int max_var = -1 + ) : lower_num_(lower_num), upper_num_(upper_num), + log_bdry_den_(log_bdry_den), + coeff_(degree+1), + min_var_(min_var), max_var_(max_var), + subdiv_tries_(0), subdiv_fails_(0), + recdepth_(-1), + log_sep_(0), delta_log_sep_(0), log_eps_(0), log_C_eps_(0) + { } + + void copy_state_from(const Self& n) { + subdiv_tries_ = n.subdiv_tries_; + subdiv_fails_ = n.subdiv_fails_; + recdepth_ = n.recdepth_; + log_sep_ = n.log_sep_; + delta_log_sep_ = n.delta_log_sep_; + log_eps_ = n.log_eps_; + log_C_eps_ = n.log_C_eps_; + } + + // const Self& operator= (const Self&); // assignment is forbidden +}; // struct Bitstream_descartes_rndl_node + + +/* + * class Bitstream_descartes_rndl_tree_rep + */ + +template +class Bitstream_descartes_rndl_tree_rep { +public: + typedef Bitstream_descartes_rndl_tree_rep Self; + CGAL_BITSTREAM_DESCARTES_RNDL_TREE_TYPEDEFS; + + class Monomial_basis_tag { }; + + friend class internal::Bitstream_descartes_rndl_tree; + +private: + Coefficient_vector input_monomial_coeff_; + int degree_; + long ceil_log_degree_; + long lbd_log_lcoeff_; + Node_list node_list_; + + // temporary data fields for subdivision + Integer_vector tmp1_coeff_, tmp2_coeff_; + Integer splitpoint_num_; + long log_splitpoint_den_; + + // function objects + Approximator approximator_; + Lower_bound_log2_abs lower_bound_log2_abs_; + +public: + Bitstream_descartes_rndl_tree_rep() : degree_(-1) { } + + template + Bitstream_descartes_rndl_tree_rep( + Integer lower_num, Integer upper_num, long log_bdry_den, + InputIterator first, InputIterator beyond, Monomial_basis_tag, + const TRAITS& traits + ) : input_monomial_coeff_(first, beyond), + splitpoint_num_(0), log_splitpoint_den_(0), + approximator_(traits.approximator_object()), + lower_bound_log2_abs_(traits.lower_bound_log2_abs_object()) + { + degree_ = int(input_monomial_coeff_.size() - 1); + CGAL_precondition(degree_ >= 0); + ceil_log_degree_ = (degree_ > 0) ? Ceil_log2_abs_long()(degree_) : -1; + lbd_log_lcoeff_ + = lower_bound_log2_abs_(input_monomial_coeff_[degree_]); + node_list_.push_front( + Node(degree_, lower_num, upper_num, log_bdry_den) + ); + tmp1_coeff_.resize(degree_ + 1); + tmp2_coeff_.resize(degree_ + 1); + } +}; // class Bitstream_descartes_rndl_tree_rep + +/* + * class Bitstream_descartes_rndl_tree + */ + +/*! \ingroup NiX_Bitstream_descartes_tree + \brief Subdivision tree of the BitstreamDescartes method (rndl variant) + + Before you try to understand this class fully, you might want + to have a look at the paper on the BitstreamDescartes method + mentioned \link NiX_Bitstream_descartes here \endlink. + The next paragraph gives a brief summary; + the description of this class follows after it. + + The BitstreamDescartes method + + The BitstreamDescartes method searches the real roots of + a polynomial in some initial interval by subdividing this + interval recursively into open subintervals. + Each subinterval is subjected to the Descartes Test, + which gives an integer that is an upper bound on the + number of real roots in the interval. + For efficiency, the BitstreamDescartes method does not compute + with the coefficients given by the caller, only approximations of them. + Therefore, the result of the Descartes Test may only be known + in the form of lower and upper bounds on the exact test, + called min_var and max_var. + However, the approximation quality of the input coefficients + and the choice of the subdivision points are automatically + controlled in a way that allows the following conclusions: + - If min_var 0 for some interval, this interval + does not contain any real root. + - If max_var is 1 for some interval, this interval + contains exactly one simple real root. + - If all real roots of the input polynomial are simple, + repeated subdivision will eventually produce intervals + that all have min_var equal to max_var equal to 0 or 1. + + Hence we have an algorithm for isolating the real roots + of square-free polynomials. We think of it as constructing + a binary tree: + Each subinterval considered by the algorithm is a node of the tree. + The children of a node are the two subintervals created by subdivision. + The root of the tree is the initial interval. + At each stage of the algorithm, the interesting nodes are + the leaves of the tree. Subdivision of a leaf turns it + into an internal node whose children are leaves. + + Description of class + + This class lets you interactively explore the subdivision + tree of the BitstreamDescartes method (or more precisely, + its variant called "rndL" in the paper). + An object \c T of this class is constructed from an + initial interval and the polynomial. + The polynomial is read from an iterator range, + whose first element is the constant coefficient and whose + last element is the leading coefficient (which has to be + non-zero). + + After construction, \c T represents the list of leaves + in the current subdivision tree. (Initially, there is + only one leaf: the node representing the initial interval.) + You can iterate through this list in the style of an + \c std::list; that is, a \c Node_iterator is a + \c BidirectionalIterator. + At any time, the nodes are sorted in the order of the intervals + they stand for. + + You cannot dereference an iterator into anything meaningful; + however, you can pass it to various member functions + that tell you the relevant data about the interval + represented by the node, e.g., \c lower() and \c upper() + bound and \c min_var() and \c max_var(). + + Most importantly, you can \c subdivide() a node. + Conceptually, this replaces the interval by two subintervals. + However, subintervals with \c min_var() equal to 0 + are immediately discarded; so \c subdivide() may + actually replace one node by zero, one or two new nodes. + In fact, if \c min_var() is 0 already for the initial interval, + a newly constructed object \c T has an empty list of leaves. + (In particular, this happens if the polynomial supplied in + construction is constant.) + + Unlike STL containers, this class is implemented using + \c CGAL::Handle. That means, an object is just a ref-counted + pointer to the actual representation. Thus, copying an + object is cheap. However, all copies of an object alias + each other. If you modify one, this changes the state + of all copies; including invalidation of iterators pointing + to destroyed nodes. + + A \c Node_iterator remains valid until the node it points to + is destroyed by \c subdivide() or \c erase(). Destruction + of one node does not affect validity of iterators pointing + to other nodes. + + Example (root isolation (square-free case)) + + Once you have constructed \c T, implementing the BitstreamDescartes + method by exploring \c T is a matter of a few lines: + \code + Node_iterator it = T.begin(); + Node_iterator chld_first, chld_beyond; + while (it != T.end()) { + if (T.max_var(it) == 1) { + cout << "found [" << T.lower(it) << ", " << T.upper(it) << "]\n"; + ++it; + } else { + T.subdivide(it, chld_first, chld_beyond); + it = chld_first; + } + } + \endcode + + Supplying a traits class + + This class is actually a class template. + To use it, you need to instanciate it with a traits class + that defines the following three types and the various + functors on them listed below. + - \c Coefficient: The type of coefficients supplied + during construction. Must be \c Assignable . + - \c Integer: A type for infinite-precision integer arithmetic + (such as \c leda::integer or \c CORE::BigInt ). + All internal computations are done using this type. + Must be a model of \c Ring and additionally provide + operators \c >> and \c << with the usual semantics. + - \c Bound: \c lower() and \c upper() return + interval boundaries in this type. Must be \c Assignable. + The canonical choice is \c NiX::Exact_float_number. + If you never instanciate \c lower() and \c upper() + (maybe use \c boundaries() instead), you might be lucky + and get away with typedef'ing this to \c void. + + The traits class must also contain the following functors + and member functions for their construction: + - \c Approximator: A \c BinaryFunction with signature + Integer y = Approximator()(Coefficient x, long p) + that computes an \c Integer approximation + to 2p * x satisfying + |y - 2p * x| <= 1. + - \c approximator_object(): A \c const member function + taking no arguments and returning a function object + of class \c Approximator. This function is called once + at construction of \c T to initialize one \c Approximator + that is used for all subsequent coefficient approximations. + It is only applied to arguments \c x that have had one + of the coefficients assigned to them that were supplied + during construction of \c T. Hence it can + keep state and maybe cache some knowledge about coefficients. + - \c Lower_bound_log2_abs: A \c UnaryFunction with signature + long l = Lower_bound_log2_abs()(Coefficient x). + The result \c l must be a lower bound to log2(|x|). + If \c Coefficient posesses \c NiX::NT_traits::Floor_log2_abs, + you can simply use that. + - \c lower_bound_log2_abs_object(): A \c const member function + taking no arguments and returning a function object + of class \c Lower_bound_log2_abs. This function is called once + at construction of \c T to get a \c Lower_bound_log2_abs + on the polynomial's leading coefficient. + - \c Bound_creator: A functor with signature + Bound b = Bound_creator()(Integer x, long p) + to construct \c b with value + x * 2p. + If \c Bound has a matching constructor + (as \c NiX::Exact_float_number does), you can simply + typedef CGAL::Creator_2 + Bound_creator;. + - \c Sign: A functor working identically to + \c NiX::NT_traits::Sign for \c NT equal to \c Integer. + (You can just typedef to that.) + - \c Ceil_log2_abs_Integer: A functor working identically to + \c NiX::NT_traits::Ceil_log2_abs for \c NT equal to \c Integer. + (You can just typedef to that.) + - \c Ceil_log2_abs_long: A functor working identically to + \c NiX::NT_traits::Ceil_log2_abs for \c NT equal to \c long. + (You can just typedef to that.) + + In brief, the core requirement is that you can approximate + \c Coefficient to any arbitrarily small absolute error + 2-p (for integral p) + and deliver that approximation scaled with 2p + as an \c Integer. + For the leading coefficient, you also need to be able to locate + the leading 1-bit in its binary expansion. + The functors dealing with \c Coefficient are accessed + through \c _object() member functions so that the user of + this class can supply them with an internal state, because + \c Coefficient might hide some non-trivial + approximation or evaluation process. + For the functors dealing with \c Integer, this does not + seem necessary. + + Example (traits class) + + You can use the BitstreamDescartes method for polynomials with + integer coefficients. If the coefficients are very long, this + saves time over the exact Descartes method, because they are + only needed in truncated form. A suitable traits class looks + like this: + \code + template + class Bitstream_descartes_rndl_tree_traits_from_Integer_coeff { + public: + typedef Integer_ Coefficient; + typedef Integer_ Integer; + typedef NiX::Exact_float_number Bound; + + class Approximator { + public: + Integer operator() (Coefficient x, long p) { + if (p >= 0) return x << p; else return x >> -p; + } + }; + Approximator approximator_object() const { return Approximator(); } + + typedef typename NiX::NT_traits::Floor_log2_abs Lower_bound_log2_abs; + Lower_bound_log2_abs lower_bound_log2_abs_object() const { return Lower_bound_log2_abs(); } + + typedef CGAL::Creator_2 Bound_creator; + typedef typename NiX::NT_traits::Sign Sign; + typedef typename NiX::NT_traits::Ceil_log2_abs Ceil_log2_abs_Integer; + typedef typename NiX::NT_traits::Ceil_log2_abs Ceil_log2_abs_long; + }; + \endcode + + Technical remarks + + This class implements essentially the "rndL" variant + of the BitstreamDescartes method. The following remarks apply: + + It is an invariant that for all nodes, the first and + last Bernstein coefficient are larger in magnitude than C eps. + Consequently, Lemma 5 of the paper allow us to conclude + right away from \c min_var() being 0 what would happen + after one further subdivision (namely: there are no roots). + We don't have to do this extra subdivision, we know right away. + Unfortunately, the analogous argument for Lemma 6 doesn't work, + because we still would have to verify that the value at the + bisection point is large. + + Subdivision points with value larger than C eps are found + by trying randomly and checking. This randomization means + the same polynomial and same initial interval may give rise + to different intervals each time this class is used. + As indicated in the paper, we favour subdivision ratios + with a small denominator. Hence we first try denominator + 2 (subdivision at midpoint), then denominator 16, and + only then the "proper" denominator prescribed by theory. + Failures are only counted for the "proper" tries. + + Unlike the algorithm in the paper, we do not have one global + estimate for the separation of roots, and we do not restart + globally if that estimate turns out wrong. Instead, each node + maintains an estimate. Upon subdivision, its children + inherit it, including the counts of tried and failed + subdivisions. If fails/tries >= 1/2 and tries >= 2, + the estimate of separation (and all other parameters + coming out of it) are updated only for this one node. + The node's interval does not change; subdivision + resumes from this interval with an improved estimate of + separation. All other nodes are unaffected. + Global restart is not an option for this class, because the user has + already observed the subintervals found up to this point, + so we cannot simply switch to other intervals. + + This implementation relies on the assumption that the + logarithms of certain relevant quantities, in particular + the degree times the logarithm of the estimated separation, + are small enough to be representable in a long int. + Also, the degree of the input polynomial and related quantities + are assumed to fit into an \c int. + */ +template +class Bitstream_descartes_rndl_tree +// TODO: Replaced CGAL::Handle by following CGAL::Handle_with_policy, is this correct? + : public ::CGAL::Handle_with_policy< Bitstream_descartes_rndl_tree_rep< + BitstreamDescartesRndlTreeTraits + >, ::CGAL::Handle_policy_no_union > +{ +public: + typedef Bitstream_descartes_rndl_tree Self; + CGAL_BITSTREAM_DESCARTES_RNDL_TREE_TYPEDEFS; + typedef Bitstream_descartes_rndl_tree_rep Rep; + typedef ::CGAL::Handle_with_policy< Rep, ::CGAL::Handle_policy_no_union > Base; + + //! node iterator. + typedef typename Node_list::iterator Node_iterator; + //! node iterator (for STL compatibility only). + typedef typename Node_list::iterator iterator; + //! const node iterator. + typedef typename Node_list::const_iterator Node_const_iterator; + //! const node iterator (for STL compatibility only). + typedef typename Node_list::const_iterator const_iterator; + + //! tag type to distinguish a certain constructor. + typedef typename Rep::Monomial_basis_tag Monomial_basis_tag; + +public: + //! default constructor (makes degree() == -1) + Bitstream_descartes_rndl_tree() : Base(Rep()) { } + + //! copy constructor + Bitstream_descartes_rndl_tree(const Self& p) + : Base(static_cast(p)) + { } + + //! Internal function called by constructor. Avoids code duplication + void init_tree() { + Node_iterator n = this->ptr()->node_list_.begin(); + if (this->ptr()->degree_ > 0) { + initial_guess_sep(n); + while (!reinit_from_sep(n)) next_guess_sep(n); + if (n->min_var_ == 0) this->ptr()->node_list_.erase(n); + } else { + this->ptr()->node_list_.erase(n); + } + } + + + /*! \brief construct from initial interval and coefficients + * + * The initial interval is + * [\c lower_num, \c upper_num] / 2^(\c log_bdry_den ). + * + * The iterator range [\c first, \c beyond ) gives the + * coefficients of 1, x, x2, ... + * The leading coefficient (last in sequence) must be non-zero. + * + * The \c Monomial_basis_tag is required for the benefit of + * future extensions to coefficients w.r.t. other bases. + */ + template + Bitstream_descartes_rndl_tree( + Integer lower_num, Integer upper_num, long log_bdry_den, + InputIterator first, InputIterator beyond, Monomial_basis_tag tag, + const BitstreamDescartesRndlTreeTraits& traits + = BitstreamDescartesRndlTreeTraits() + ) : Base(Rep(lower_num, upper_num, log_bdry_den, + first, beyond, tag, traits)) + { + CGAL_precondition(lower_num < upper_num); + init_tree(); + + } + + /*! + * This is needed for compatibility with other tree implementations + * The initial interval is + * [-1, 1] / 2^(\c -log_bdry_den ). + * Be aware that log_bdry_den is negated here! + */ + template + Bitstream_descartes_rndl_tree( + long log_bdry_den, + InputIterator first, InputIterator beyond, Monomial_basis_tag tag, + const BitstreamDescartesRndlTreeTraits& traits + = BitstreamDescartesRndlTreeTraits() + ) + : Base(Rep(Integer(-1), Integer(1), -log_bdry_den, + first, beyond, tag, traits)) + { + init_tree(); + } + + //! return degree of polynomial + int degree() const { return this->ptr()->degree_; } + + //! iterator to first node + Node_iterator begin() { + return this->ptr()->node_list_.begin(); + } + //! iterator beyond last node + Node_iterator end() { + return this->ptr()->node_list_.end(); + } + //! const iterator to first node + Node_const_iterator begin() const { + return this->ptr()->node_list_.begin(); + } + //! const iterator beyond last node + Node_const_iterator end() const { + return this->ptr()->node_list_.end(); + } + + //! get lower bound of interval at node \c n. + Bound lower(Node_iterator n) const { + return Bound_creator()(n->lower_num_, -n->log_bdry_den_); + } + //! get lower bound of interval at node \c n. + Bound lower(Node_const_iterator n) const { + return Bound_creator()(n->lower_num_, -n->log_bdry_den_); + } + //! get upper bound of interval at node \c n. + Bound upper(Node_iterator n) const { + return Bound_creator()(n->upper_num_, -n->log_bdry_den_); + } + //! get upper bound of interval at node \c n. + Bound upper(Node_const_iterator n) const { + return Bound_creator()(n->upper_num_, -n->log_bdry_den_); + } + + //! get boundaries: interval at node \c n is + //! [\c lower_num, \c upper_num] / 2^(\c log_bdry_den ). + void boundaries(Node_iterator n, + Integer& lower_num, Integer& upper_num, long& log_bdry_den + ) { + lower_num = n->lower_num_; + upper_num = n->upper_num_; + log_bdry_den = n->log_bdry_den_; + } + + //! get minimum number of sign variations in Descartes Test + //! for approximate polynomial at node \c n + int min_var(Node_const_iterator n) const { return n->min_var_; } + //! get maximum number of sign variations in Descartes Test + //! for approximate polynomial at node \c n + int max_var(Node_const_iterator n) const { return n->max_var_; } + + /*! \brief subdivide interval at node \c n. + * + * The node representing interval \c n is replaced in the list + * of nodes by 0, 1, or 2 nodes that represent those among the + * two subintervals that have \c min_var() greater than 0. + * The number of new nodes is returned as result. + * The subrange of nodes consisting of the new nodes is + * returned in the arguments \c first and \c beyond + * + * Subdividing a node invalidates all iterators to it; + * both for the object where \c subdivide() was called + * and all copies of it (since they share the same + * representation and state). + * + * The parameter \c n is passed by value. Hence you can + * implement depth-first search for isolating intervals like this: + * \code + * Node_iterator dummy, curr = tree.begin(); + * while (curr != tree.end()) { + * if (tree.max_var(curr) == 1) ++curr; + * else tree.subdivide(curr, curr, dummy); + * } + * \endcode + */ + int subdivide( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + /*! \brief erase node \c n. + * + * Erasing a node invalidates all iterators to it; + * both for the object where \c subdivide() was called + * and all copies of it (since they share the same + * representation and state). + */ + void erase(Node_iterator n) { + this->ptr()->node_list_.erase(n); + } + + /*! \brief Replace traits class + */ + void set_traits(TRAITS& traits) { + + this->ptr()->approximator_ + = traits.approximator_object(); + this->ptr()->lower_bound_log2_abs_ + = traits.lower_bound_log2_abs_object(); + + } + + /*! \brief Returns a copy of this with its own representation + */ + Self make_unique() const { + Self tmp = *this; + tmp.copy_on_write(); + return tmp; + } + + +protected: + int subdivide_at_midpoint( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + int subdivide_at( + Node_iterator n, Node_iterator& first, Node_iterator& beyond, + long alpha_num, int log_alpha_den + ); + +private: + int replace_by_tmp( + Node_iterator n, Node_iterator& first, Node_iterator& beyond + ); + + void initial_guess_sep(Node_iterator n) { + Ceil_log2_abs_Integer log; + long log_I = log(n->upper_num_-n->lower_num_) - n->log_bdry_den_; + n->delta_log_sep_ = -5; + n->log_sep_ = log_I + n->delta_log_sep_; + } + + void next_guess_sep(Node_iterator n) { + n->delta_log_sep_ *= 2; + CGAL_warning_msg(-n->delta_log_sep_ < 1L<<24, "delta_log_sep >= 1L<<24"); + n->log_sep_ += n->delta_log_sep_; + } + + bool reinit_from_sep(Node_iterator n); + +}; // class Bitstream_descartes_rndl_tree + + +/* + * Non-inline member functions of class Bitstream_descartes_rndl_tree + */ + +template +bool +Bitstream_descartes_rndl_tree +::reinit_from_sep(Node_iterator n) { + n->subdiv_tries_ = n->subdiv_fails_ = 0; + + Ceil_log2_abs_Integer log; + /* We want to set recdepth to + * floor( (log(|I|/sep) / log(4/3)) + 5/2 ) + * or something slightly larger. + * Using the continued fractions expansion [2,2,2,3], + * we find an upper bound of 41/17 = 82/34 = 2.41176... + * for the exact multiplier 1/log(4/3) = 2.40942... + * which is off by less than 0.1%, namely 0.00234... + * Noting 5/2 = 85/34, we hence set recdepth to + * floor( (log|I| - log(sep))*82 + 85) / 34 ) + */ + n->recdepth_ = ( + (log(n->upper_num_ - n->lower_num_) - n->log_bdry_den_ // log|I| + - n->log_sep_ + )*82 + 85) / 34; + if (n->recdepth_ < 6) n->recdepth_ = 6; // TODO find rationale + + n->log_eps_ = this->ptr()->ceil_log_degree_ + + Ceil_log2_abs_long()(n->recdepth_); + n->log_C_eps_ = n->log_eps_ + 4*degree(); // C = 16^n + long target_log_lcf = (4 - n->log_sep_)*this->ptr()->degree_ + + n->log_eps_ + 2*this->ptr()->ceil_log_degree_ + 10; + long log_lcf_scale = target_log_lcf - this->ptr()->lbd_log_lcoeff_ + - (log(caching_factorial(this->ptr()->degree_)) - 1); + + polynomial_power_to_bernstein_approx( + this->ptr()->input_monomial_coeff_.begin(), + this->ptr()->input_monomial_coeff_.end(), + n->coeff_.begin(), + n->lower_num_, n->upper_num_, n->log_bdry_den_, + log_lcf_scale - (n->log_eps_ - 1), + this->ptr()->approximator_, + Ceil_log2_abs_Integer(), Ceil_log2_abs_long() + ); + for (int i = 0; i <= degree(); ++i) { + n->coeff_[i] <<= (n->log_eps_ - 1); // TODO avoid preceding rshift + } + + if (Abs_le_pow2()(n->coeff_[ degree()], n->log_C_eps_) + || Abs_le_pow2()(n->coeff_[0], n->log_C_eps_) + ) { + return false; + } else { + var_eps(n->coeff_.begin(), n->coeff_.end(), + n->min_var_, n->max_var_, Sign_eps_log2(n->log_eps_) + ); + return true; + } +} // Bitstream_descartes_rndl_tree::reinit_from_sep() + +template +int +Bitstream_descartes_rndl_tree +::subdivide_at_midpoint( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + de_casteljau_generic(n->coeff_.begin(), n->coeff_.end(), + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp2_coeff_.begin(), + Convex_combinator_approx_midpoint() + ); + this->ptr()->splitpoint_num_ = n->lower_num_ + n->upper_num_; + this->ptr()->log_splitpoint_den_ = n->log_bdry_den_ + 1; + + if (Abs_le_pow2()(this->ptr()->tmp2_coeff_[0], n->log_C_eps_)) { + return -1; + } else { + return replace_by_tmp(n, first, beyond); + } +} // Bitstream_descartes_rndl_tree::subdivide_at() + +template +int +Bitstream_descartes_rndl_tree +::subdivide_at( + Node_iterator n, Node_iterator& first, Node_iterator& beyond, + long alpha_num, int log_alpha_den +) { + de_casteljau_generic(n->coeff_.begin(), n->coeff_.end(), + this->ptr()->tmp1_coeff_.begin(), this->ptr()->tmp2_coeff_.begin(), + Convex_combinator_approx_long_log(alpha_num, log_alpha_den) + ); + this->ptr()->splitpoint_num_ = + alpha_num * n->lower_num_ + + ((1L << log_alpha_den) - alpha_num) * n->upper_num_; + this->ptr()->log_splitpoint_den_ = n->log_bdry_den_ + log_alpha_den; + + if (Abs_le_pow2()(this->ptr()->tmp2_coeff_[0], n->log_C_eps_)) { + return -1; + } else { + return replace_by_tmp(n, first, beyond); + } +} // Bitstream_descartes_rndl_tree::subdivide_at() + + +template +int +Bitstream_descartes_rndl_tree +::replace_by_tmp( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + --(n->recdepth_); + + long delta_log_bdry_den = + this->ptr()->log_splitpoint_den_ - n->log_bdry_den_; + CGAL_assertion(delta_log_bdry_den >= 0); + + int l_min_var, l_max_var, r_min_var, r_max_var; + var_eps(this->ptr()->tmp1_coeff_.begin(), + this->ptr()->tmp1_coeff_.end(), + l_min_var, l_max_var, Sign_eps_log2(n->log_eps_) + ); + var_eps(this->ptr()->tmp2_coeff_.begin(), + this->ptr()->tmp2_coeff_.end(), + r_min_var, r_max_var, Sign_eps_log2(n->log_eps_) + ); + CGAL_assertion(l_min_var >= 0 && l_max_var >= 0); + CGAL_assertion(r_min_var >= 0 && r_max_var >= 0); + + beyond = first = n; + ++beyond; + + if (l_min_var > 0) { + int children = 1; + if (r_min_var > 0) { + // create new node for right child + Node_iterator r = + this->ptr()->node_list_.insert(beyond, Node(degree(), + this->ptr()->splitpoint_num_, // lower + n->upper_num_ << delta_log_bdry_den, // upper + this->ptr()->log_splitpoint_den_, + r_min_var, r_max_var + )); + r->coeff_.swap(this->ptr()->tmp2_coeff_); + r->copy_state_from(*n); + ++children; + } + // put left child into n + n->lower_num_ <<= delta_log_bdry_den; + n->upper_num_ = this->ptr()->splitpoint_num_; + n->log_bdry_den_ = this->ptr()->log_splitpoint_den_; + n->min_var_ = l_min_var; + n->max_var_ = l_max_var; + n->coeff_.swap(this->ptr()->tmp1_coeff_); + return children; + } else if (r_min_var > 0) { + // put right child into n + n->lower_num_ = this->ptr()->splitpoint_num_; + n->upper_num_ <<= delta_log_bdry_den; + n->log_bdry_den_ = this->ptr()->log_splitpoint_den_; + n->min_var_ = r_min_var; + n->max_var_ = r_max_var; + n->coeff_.swap(this->ptr()->tmp2_coeff_); + return 1; + } else /* l_min_var == 0 && r_min_var == 0 */ { + // delete n + first = beyond; + this->ptr()->node_list_.erase(n); + return 0; + } +} // Bitstream_descartes_rndl_tree::replace_by_tmp() + +template +int +Bitstream_descartes_rndl_tree +::subdivide( + Node_iterator n, Node_iterator& first, Node_iterator& beyond +) { + long alpha_num; + int log_alpha_den; + long alpha_den_4; + int ret; + + for (;;) { + if (n->recdepth_ > 0) { // TODO decouple recdepth from guess_sep + // first try heuristic alpha = 1/2 (failures don't count) + ++(n->subdiv_tries_); + ret = subdivide_at_midpoint(n, first, beyond); + if (ret >= 0) { return ret; } else { --(n->subdiv_tries_); } + + // next try heuristic alpha with small denom (failures don't count) + log_alpha_den = 4; + alpha_den_4 = 1L << (log_alpha_den - 2); + alpha_num = CGAL::default_random.get_int( // TODO .get_long + alpha_den_4, 3*alpha_den_4 + 1 + ); + ++(n->subdiv_tries_); + ret = subdivide_at(n, first, beyond, alpha_num, log_alpha_den); + if (ret >= 0) { return ret; } else { --(n->subdiv_tries_); } + + // now try alpha properly randomized, counting failure rate + log_alpha_den = 5 + this->ptr()->ceil_log_degree_; + alpha_den_4 = 1L << (log_alpha_den - 2); + do { + alpha_num = CGAL::default_random.get_int( // TODO .get_long + alpha_den_4, 3*alpha_den_4 + 1 + ); + ++(n->subdiv_tries_); + ret = subdivide_at(n, first, beyond, alpha_num, log_alpha_den); + if (ret >= 0) { + return ret; + } else { + ++(n->subdiv_fails_); + } + } while (n->subdiv_fails_ < 2 // Arno says: 2 (not 6) is enough + || 2 * n->subdiv_fails_ < n->subdiv_tries_); + } // if (n->recdepth_ > 0) + + // if failure rate too high or recdepth exceeded, + // decrease guess of sep and restart + next_guess_sep(n); + bool reinit_success = reinit_from_sep(n); + CGAL_assertion(reinit_success); (void)reinit_success; + } // for (;;) +} // Bitstream_descartes_rndl_tree::subdivide() + +} // namespace internal + + +/* + * FUJIWARA ROOT BOUND + */ + +namespace internal { + +struct Fujiwara_root_bound_queue_entry { + typedef Fujiwara_root_bound_queue_entry Self; + + int n_minus_i; + long ub_log2_qi; + bool is_certainly_zero; + bool is_tight; + + bool operator < (Self& rhs) { + if (is_certainly_zero) return !rhs.is_certainly_zero; + if (rhs.is_certainly_zero) return false; + return ub_log2_qi * rhs.n_minus_i < rhs.ub_log2_qi * n_minus_i; + } +}; + +class Fujiwara_root_bound_queue_entry_ptr_less { +public: + typedef bool result_type; + typedef Fujiwara_root_bound_queue_entry* first_argument_type; + typedef Fujiwara_root_bound_queue_entry* second_argument_type; + result_type operator() (first_argument_type a, second_argument_type b) { + return *a < *b; + } +}; + +template +class Upper_bound_log2_abs_approximator_from_ceil_log2_abs { +public: + typedef Upper_bound_log2_abs_approximator_from_ceil_log2_abs Self; + typedef CeilLog2Abs Ceil_log2_abs; + typedef typename Ceil_log2_abs::argument_type NT; + bool initial_upper_bound(NT x, long& ub_log2, bool& is_certainly_zero) { + is_certainly_zero = (x == NT(0)); + if (!is_certainly_zero) ub_log2 = Ceil_log2_abs()(x); + return true; // reported bound is tight + } + bool improve_upper_bound(NT x, long&, bool&) { return true; } +}; + +/*! \ingroup NiX_Bitstream_descartes_tree + \brief Fujiwara root bound (as logarithm wrt base 2) + + All complex roots of a polynomial + A(X) = anXn + ... + a0 + are bounded in magnitude by + F(A) = 2 maxi<n qi1/(n-i) + where qi = |ai/an| + for 0 < i < n + and q0 + = |a0/(2an)|. + This bound goes back to M. Fujiwara + [Tohoku Math. J. 10 (1916) 167-171], + cited here after P. Batra's PhD thesis [TU Hamburg-Harburg, Germany, 1999]. + + This function computes an integer upper bound for + log2(F(A)) from an iterator range [first, beyond) + over values of some type \c Coefficient + where *(first+i) is ai. + This function does not operate on type \c Coefficient + except through the two function objects passed to it: + + LowerBoundLog2Abs lblog2 has to be a function object + with a function call operator taking an argument + *(beyond-1) of type \c Coefficient + and returning a \c long which is a lower bound for + log2(|an|). + This functor is called once and should return a bound as + good as possible. + + UpperBoundLog2AbsApproximator ublog2apx has to be an + object with two member functions + \c initial_upper_bound() and \c improve_upper_bound(). + Both of them take three arguments: + (Coefficient ai, long& ub_log2, bool& is_certainly_zero) + and return bool. \c ai is one of the coefficients. + First, the member function \c initial_upper_bound() is invoked + on \c ai and uninitialized arguments \c ub_log2 and \c is_certainly_zero. + Then, \c improve_upper_bound() is invoked repeatedly on \c ai and + arguments \c ub_log2 and \c is_certainly_zero as set by the + previous call. This sequence of calls has to create a + sequence of estimates of upper bounds for + log2(|ai|). As long as + a later call will return a better approximation, + the function returns \c false. If the current bound is to be + regarded as best possible, the function returns \c true. + If, while improving the bound, it is discovered that + ai is zero, in which case the correct estimate would be + "minus infinity", \c is_certainly_zero is set to \c true; + otherwise it is always \c false. + If \c is_certainly_zero is set to \c true, + the value of \c ub_log2 is ignored. + + Internally, this function works as follows: + It improves upper bounds of log2(|ai|) + for all i < n until it has found one that + is designated as best possible (i.e., has returned \c true) + and that realizes the maximum in the definition + of the Fujiwara bound. Unlike \c LowerBoundLog2Abs, which is + called only once, namely for the leading coefficient, and should + provide the best possible bound at once, + \c UpperBoundLog2AbsApproximator is called repeatedly, + and each call should perform only a limited amount of work + (e.g., one round of interval refinement for its argument) + so that this function can distribute the approximation work + evenly over all coefficients until the maximum is found. + + The leading coefficient *(beyond-1) has to be non-zero. + In the special case that all other coefficients are zero, + the result 0 (standing for 20=1) is returned. + Obviously, this cannot happen for a square-free polynomial + of degree larger than 1. + + Warning: This bound is tight for certain polynomials + (e.g., (X-2)(Xn-1)/(X-1)). + The BitstreamDescartes method, however, needs an initial interval + whose boundaries are far away from the zeroes. Hence you should + add 1 to the result of this function before using it there. + Also bear in mind that this function returns a logarithm of + the bound, whereas certain other functions may expect a + logarithm of a denominator, necessitating a negation. + + For coefficients that are known explicitly (e.g., big integers) + and possess NiX::NT_traits::{Floor,Ceil}_log2_abs functors, + the lower and upper bound function objects for this function + should be constructed from them. This is done automatically + by an overloaded version of this functions that takes only the + first two arguments. + */ +template +long Fujiwara_root_bound_log( + RandomAccessIterator first, RandomAccessIterator beyond, + LowerBoundLog2Abs lblog2, UpperBoundLog2AbsApproximator ublog2apx +) { + int n = beyond - first - 1; // degree + if (n < 1) return 0; + long lblog2_lcoeff = lblog2(*(beyond - 1)); + + Fujiwara_root_bound_queue_entry_ptr_less less; + typedef Fujiwara_root_bound_queue_entry QE; + std::vector entries(n); // entries are never copied + std::vector heap(n); // heap is built from pointers to them + for (int i = 0; i < n; ++i) { + QE& entry = entries[i]; + entry.n_minus_i = n - i; + entry.is_tight = ublog2apx.initial_upper_bound( + *(first + i), entry.ub_log2_qi, entry.is_certainly_zero + ); + CGAL_assertion(entry.is_tight || !entry.is_certainly_zero); + if (!entry.is_certainly_zero) entry.ub_log2_qi -= lblog2_lcoeff; + heap[i] = &(entry); + } + entries[0].ub_log2_qi -= 1; + + std::make_heap(heap.begin(), heap.end(), less); + while (!heap[0]->is_tight) { + std::pop_heap(heap.begin(), heap.end(), less); + QE& popped = **(heap.end() - 1); + int i = n - popped.n_minus_i; + CGAL_assertion(i >= 0 && i < n); + CGAL_assertion(&popped == &(entries[i])); + popped.is_tight = ublog2apx.improve_upper_bound( + *(first + i), + popped.ub_log2_qi, popped.is_certainly_zero + ); + if (!popped.is_certainly_zero) { + popped.ub_log2_qi -= lblog2_lcoeff; + if (i == 0) popped.ub_log2_qi -= 1; + } + std::push_heap(heap.begin(), heap.end(), less); + } + QE& maxi = *(heap[0]); + if (maxi.is_certainly_zero) return 0; + long max_log2_qi_div_n_minus_i = maxi.ub_log2_qi / maxi.n_minus_i; + if (maxi.ub_log2_qi % maxi.n_minus_i > 0) ++max_log2_qi_div_n_minus_i; + return 1 + max_log2_qi_div_n_minus_i; // = log ( 2 * max_i q_i^{1/(n-i)} ) +} + +template +inline +long Fujiwara_root_bound_log( + RandomAccessIterator first, RandomAccessIterator beyond +) { + typedef typename RandomAccessIterator::value_type NT; + typedef typename internal::Real_embeddable_extension::Floor_log2_abs Lbd; + typedef Upper_bound_log2_abs_approximator_from_ceil_log2_abs< + typename internal::Real_embeddable_extension::Ceil_log2_abs + > Ubd; + return Fujiwara_root_bound_log(first, beyond, Lbd(), Ubd()); +} + + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_H + +// EOF diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree_traits.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree_traits.h new file mode 100644 index 00000000000..3bb5dbf4cee --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Bitstream_descartes_rndl_tree_traits.h @@ -0,0 +1,430 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ +#ifndef CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H +#define CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if CGAL_USE_CORE +namespace CORE { class BigInt; } +#endif + +namespace CGAL { + +namespace internal { + +#if CGAL_USE_CORE +// bugfix for CORE by Michael Kerber +// why is there a specialized function for CORE? +inline CORE::BigInt shift_integer_by(CORE::BigInt x, long shift){ + if( shift > 0 ){ + while(shift>63) { + x = (x >> 63); + shift-=63; + } + x = (x >> shift); + }else{ + // add 0 bits + x = (x << -shift); + } + return x; +} +#endif + +template +Shiftable shift_integer_by(Shiftable x, long shift){ + if( shift > 0 ){ + x >>= shift; + }else{ + x <<= -shift; // adds 0 bits + } + return x; +} + +// forward +template +class Bitstream_descartes_rndl_tree_traits; + + +template +class Bitstream_descartes_rndl_tree_traits_rep { + +public: + + typedef BitstreamCoefficientKernel Bitstream_coefficient_kernel; + + Bitstream_descartes_rndl_tree_traits_rep + (Bitstream_coefficient_kernel kernel) + : _m_kernel(kernel) + { + } + + Bitstream_descartes_rndl_tree_traits_rep() {} + +private: + + Bitstream_coefficient_kernel _m_kernel; + + friend class Bitstream_descartes_rndl_tree_traits + ; + +}; // end of class Bitstream_descartes_rndl_tree_traits_rep + +// A version that relies on a Bitstream_coefficient_kernel model +template +class Bitstream_descartes_rndl_tree_traits + : CGAL::Handle_with_policy + > +{ + +public: + //! typedefs + //! @{ + + typedef BitstreamCoefficientKernel Bitstream_coefficient_kernel; + + typedef typename Bitstream_coefficient_kernel::Coefficient Coefficient; + + typedef typename Bitstream_coefficient_kernel::Bigfloat_interval BFI; + typedef typename CGAL::Bigfloat_interval_traits::Bound BF; + + typedef typename + CGAL::Polynomial_type_generator::Type POLY; + typedef Bitstream_descartes_rndl_tree_traits + < Bitstream_coefficient_kernel > Self; + + typedef CGAL::Handle_with_policy + > + Handle; + + typedef typename Bitstream_coefficient_kernel::Integer Integer; + typedef typename Bitstream_coefficient_kernel::Bound Bound; + + //! @} + +public: + + //! \name Constructors + //! @{ + + Bitstream_descartes_rndl_tree_traits(Bitstream_coefficient_kernel kernel) + : Handle(kernel) + {} + + Bitstream_descartes_rndl_tree_traits() {} + + //! @} + + class Approximator { + + private: + + Bitstream_coefficient_kernel _m_kernel; + + public: + Approximator + (const Bitstream_coefficient_kernel& kernel) + : _m_kernel(kernel) {}; + + Approximator() {}; + + Integer operator() (Coefficient f, long p) { + + //std::cout << "Called approximator with f=" << f + // << " and p=" << p << std::endl; + + typename CGAL::internal::Float_traits::Get_exponent get_exp; + typename CGAL::internal::Float_traits::Get_mantissa get_m; + + long old_prec = CGAL::get_precision(BFI()); + long prec = 4; + + BFI f_alpha_bfi; + + while(true) { + + CGAL::set_precision(BFI(),prec); + + f_alpha_bfi = _m_kernel.convert_to_bfi_object()(f); + if(CGAL::singleton(f_alpha_bfi)) { + break; + } + if(CGAL::internal::ceil_log2_abs(CGAL::upper(f_alpha_bfi)- + CGAL::lower(f_alpha_bfi)) <=-p) { + break; + } else { + prec*=2; + } + + } + + BF lower = CGAL::lower(f_alpha_bfi); + + long shift = - (p + get_exp(lower)); + Integer bfi_m(get_m(lower)); + bfi_m = shift_integer_by(bfi_m,shift); + +// if( shift > 0 ){ +// while(shift>63) { // this is a bug fix HACK for CORE::BigInt +// bfi_m = (bfi_m >> 63); +// shift-=63; +// } +// bfi_m = (bfi_m >> shift); +// }else{ +// // add 0 bits +// bfi_m = (bfi_m << -shift); +// } + CGAL::set_precision(BFI(),old_prec); + + //std::cout << "returns " << bfi_m << std::endl; + + return bfi_m; + } + }; + + Approximator approximator_object() const { + return Approximator(this->ptr()->_m_kernel); + } + + + class Lower_bound_log2_abs { + + private: + Bitstream_coefficient_kernel _m_kernel; + + public: + Lower_bound_log2_abs + (const Bitstream_coefficient_kernel& kernel) + : _m_kernel(kernel) {} + + Lower_bound_log2_abs() {}; + + long operator() (Coefficient f) { + //std::cout << "Called lower_bound_log2_abs with " + // << f << std::flush; + + CGAL_assertion(! _m_kernel.is_zero_object()(f)); + + long old_prec = CGAL::get_precision(BFI()); + long prec = 4; + + BFI f_alpha_iv; + + long result; + while(true) { + CGAL::set_precision(BFI(),prec); + f_alpha_iv = _m_kernel.convert_to_bfi_object()(f); + CGAL::Sign lower_sign = CGAL::sign(CGAL::lower(f_alpha_iv)); + if(CGAL::sign(CGAL::upper(f_alpha_iv))==lower_sign) { + BF abs_lower, abs_upper; + if(lower_sign==CGAL::POSITIVE) { + abs_lower=CGAL::lower(f_alpha_iv); + abs_upper=CGAL::upper(f_alpha_iv); + } + else { + abs_lower=CGAL::abs(CGAL::upper(f_alpha_iv)); + abs_upper=CGAL::abs(CGAL::upper(f_alpha_iv)); + } + long lower_bound = CGAL::internal::floor_log2_abs(abs_lower), + upper_bound = CGAL::internal::ceil_log2_abs(abs_upper); + CGAL_assertion(upper_bound>=lower_bound); + if(upper_bound-lower_bound <=2) { + result = lower_bound; + break; + } + } + prec*=2; + + } + + //std::cout << "returning " << result << std::endl; + CGAL::set_precision(BFI(),old_prec); + + return result; + } + + }; + + Lower_bound_log2_abs lower_bound_log2_abs_object() const { + return Lower_bound_log2_abs(this->ptr()->_m_kernel); + } + + + class Upper_bound_log2_abs_approximator { + + private: + Bitstream_coefficient_kernel _m_kernel; + + // Stores id of polynomials which are known to vanish (or not to + // vanish) at alpha + std::vector zeroes,non_zeroes; + + std::vector coeffs_for_alpha; + + // Stores the last known approximation to ensure an improvement + long prec; + + public: + Upper_bound_log2_abs_approximator + (const Bitstream_coefficient_kernel& kernel) + : _m_kernel(kernel), prec(4) + {} + + Upper_bound_log2_abs_approximator() : prec(4) {}; + + bool initial_upper_bound + (Coefficient f, long& ub_log2_abs,bool& is_certainly_zero) { + return improve_upper_bound(f,ub_log2_abs,is_certainly_zero); + } + + bool improve_upper_bound + (const Coefficient f, long& ub_log2_abs,bool& is_certainly_zero) { + //std::cout << "improve upper bound.." + // << f << std::endl; + + long old_prec = CGAL::get_precision(BFI()); + + if(std::find(zeroes.begin(), + zeroes.end(), + f)!=zeroes.end()) { + //std::cout << "ZERO FROM CACHE" << std::endl; + is_certainly_zero=true; + return true; + } + else if(std::find(non_zeroes.begin(), + non_zeroes.end(), + f)!=non_zeroes.end()) { + //std::cout << "NON-ZERO FROM CACHE" << std::endl; + is_certainly_zero=false; + } + else { + bool zero = _m_kernel.is_zero_object()(f); + if(zero) { + //std::cout << "THAT IS ZERO!" << std::endl; + zeroes.push_back(f); + is_certainly_zero=true; + return true; + } + else { + //std::cout << "THAT IS NOT ZERO!" << std::endl; + non_zeroes.push_back(f); + is_certainly_zero=false; + } + } + if(std::find(coeffs_for_alpha.begin(), + coeffs_for_alpha.end(),f)!= + coeffs_for_alpha.end()) { + prec*=2; + coeffs_for_alpha.clear(); + } + coeffs_for_alpha.push_back(f); + + BFI f_alpha_iv = _m_kernel.convert_to_bfi_object()(f); + + BF abs_upper = (std::max)(CGAL::abs(CGAL::lower(f_alpha_iv)), + CGAL::abs(CGAL::upper(f_alpha_iv))); + + if(CGAL::sign(abs_upper)==CGAL::ZERO) { + is_certainly_zero=true; + CGAL::set_precision(BFI(),old_prec); + return true; + } + + ub_log2_abs = CGAL::internal::ceil_log2_abs(abs_upper); + + if(! CGAL::zero_in(f_alpha_iv) ) { + + BF abs_lower = (std::min)(CGAL::abs(CGAL::lower(f_alpha_iv)), + CGAL::abs(CGAL::upper(f_alpha_iv))); + long lb_log2_abs + = CGAL::internal::floor_log2_abs + (CGAL::convert_to_bfi(abs_lower)); + CGAL_assertion(ub_log2_abs >= lb_log2_abs); + CGAL::set_precision(BFI(),old_prec); + return ((ub_log2_abs - lb_log2_abs) <= 2); + } + else { + //std::cout << "Upper: " << ub_log2_abs << std::endl; + CGAL::set_precision(BFI(),old_prec); + return false; + } + } + }; + + Upper_bound_log2_abs_approximator + upper_bound_log2_abs_approximator_object() const { + return Upper_bound_log2_abs_approximator(this->ptr()->_m_kernel); + } + + + // TODO: Look whether this is best possible + class Bound_creator { + + public: + + Bound_creator() {} + + Bound operator() (Integer x,long p) { + Integer num=x, denom,two(2),q,r; + if(p < 0) { + CGAL::div_mod(num,two,q,r); + while(r==Integer(0) && p<0) { + num=q; + p++; + CGAL::div_mod(num,two,q,r); + } + denom = CGAL::ipower(Integer(2),-p); + } + else { + num*=CGAL::ipower(Integer(2),p); + denom=1; + } + Bound b(num,denom); + CGAL::simplify(b); + return b; + } + }; + + typedef typename CGAL::Real_embeddable_traits::Sgn Sign; + typedef typename CGAL::internal::Real_embeddable_extension + ::Ceil_log2_abs Ceil_log2_abs_Integer; + typedef typename CGAL::internal::Real_embeddable_extension + ::Ceil_log2_abs Ceil_log2_abs_long; + +}; // end of class Bitstream_descartes_rndl_tree_traits + + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_BITSTREAM_DESCARTES_RNDL_TREE_TRAITS_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_analysis_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_analysis_2.h new file mode 100644 index 00000000000..093fcf79aed --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_analysis_2.h @@ -0,0 +1,2557 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_CURVE_ANALYSIS_2_ALCIX_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_CURVE_ANALYSIS_2_ALCIX_H + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + + +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX +// put includes here +#endif + + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4290) +#endif + + +namespace CGAL { + +template +class Curve_analysis_2; + +namespace internal { + +template + struct Is_derived_from_Handle_with_policy { + typedef boost::false_type Tag; +}; + +template + struct Is_derived_from_Handle_with_policy { + + typedef typename + boost::is_base_of< CGAL::Handle_with_policy + < typename Comparable::T, + typename Comparable::Handle_policy, + typename Comparable::Allocator >, + Comparable + >::type Tag; +}; + + +template struct Compare_for_vert_line_map_ + { + bool operator() (const Comparable& a, const Comparable& b) { + return a + struct Compare_for_vert_line_map_ { + + bool operator() (const Comparable& a, const Comparable& b) { + return CGAL::Handle_id_less_than< Comparable >()(a,b); + } +}; + +template struct Compare_for_vert_line_map + : public std::binary_function { + + BOOST_MPL_HAS_XXX_TRAIT_DEF(T) + BOOST_MPL_HAS_XXX_TRAIT_DEF(Handle_policy) + BOOST_MPL_HAS_XXX_TRAIT_DEF(Allocator) + + typedef typename CGAL::internal::Is_derived_from_Handle_with_policy + < Comparable, + has_T::value && + has_Handle_policy::value && + has_Allocator::value>::Tag Tag; + + public: + + bool operator() (const Comparable& a, const Comparable& b) { + + return eval(a,b); + } + + private: + + Compare_for_vert_line_map_ eval; + + +}; + + +// \brief Representation class for algebraic curves. +template< typename AlgebraicKernelWithAnalysis_2> +class Curve_analysis_2_rep { + +public: + //! this instance's template parameter + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + //! the class itself + typedef Curve_analysis_2_rep Self; + + //! The handle class + typedef CGAL::Curve_analysis_2 + Handle; + + //protected: +public: + + typedef int size_type; + + CGAL_ACK_SNAP_ALGEBRAIC_CURVE_KERNEL_2_TYPEDEFS(Handle); + + typedef std::map< Bound, Status_line_1 > + Vert_line_at_rational_map; + + typedef + std::map< Algebraic_real_1, + Status_line_1, + internal::Compare_for_vert_line_map > + Vert_line_map; + + //!\name Constructors + //!@{ + + //! Default constructor + Curve_analysis_2_rep() + { + } + + //! Constructor with polynomial + Curve_analysis_2_rep(Algebraic_kernel_with_analysis_2 *kernel, + Polynomial_2 poly, + CGAL::Degeneracy_strategy strategy) : + _m_kernel(kernel), f(poly), degeneracy_strategy(strategy) + { + } + + //!@} + +private: + + typedef internal::LRU_hashed_map< + Bound, + std::vector, + internal::To_double_hasher > Intermediate_cache; + + Intermediate_cache intermediate_cache; + + typedef internal::Event_line_builder + Event_line_builder; + + + // Internal information struct about x-coordinates + struct Event_coordinate_1 { + Algebraic_real_1 val; + size_type mult_of_prim_res_root; + size_type index_of_prim_res_root; + size_type mult_of_content_root; + size_type index_of_content_root; + size_type mult_of_prim_lcoeff_root; + size_type index_of_prim_lcoeff_root; + boost::optional stack; + }; + + // Functor to get the X_coordinate of an Event_coordinate + struct Val_functor { + typedef Event_coordinate_1 argument_type; + typedef Algebraic_real_1 result_type; + result_type operator() (argument_type event) const { + return event.val; + } + }; + + + //! The object holding the information about events, as an optional + mutable boost::optional > + event_coordinates; + + //! The algebraic kernel to use + Algebraic_kernel_with_analysis_2* _m_kernel; + + //! The polynomial defining the curve + boost::optional f; + + //! How degenerate situations are handled + CGAL::Degeneracy_strategy degeneracy_strategy; + + /*! + * \brief The polynomial without its content (the gcd of the coeffs). + * + * The content is the greatest common divisor of the coefficients of \c f + * considered as polynomial y. \c The polynomial f_primitive is + * \c f/cont(f). The corresponding curve is equal to the curve of \c f, + * only without vertical line components. + */ + mutable boost::optional f_primitive; + + //! the polynomial containing all roots of the resultant of the primitive + //! part of f and its y-derivative + mutable boost::optional + resultant_of_primitive_and_derivative_y; + + //! the polynomial containing all roots of the resultant of the primitive + //! part of f and its x-derivative + mutable boost::optional + resultant_of_primitive_and_derivative_x; + + //! The Sturm-Habicht polynomials of f + mutable boost::optional > + sturm_habicht_of_primitive; + + //! The content of f + mutable boost::optional content; + + //! The non-working shear factors, as far as known + mutable std::set bad_shears; + + //! The already known shear factors + mutable std::map sheared_curves; + + //! Has the curve vertical line components + mutable boost::optional has_vertical_component; + + //! The intermediate values + mutable boost::optional > > + intermediate_values; + + //! stores Y_values at rational coordinate + mutable Vert_line_at_rational_map vert_line_at_rational_map; + + //! stores vert_lines + mutable Vert_line_map vert_line_map; + + /**! \brief Information about whether arcs at +/- infty + * are asymptotic to y=beta, + * or go to +/- infty also in y-direction + */ + mutable boost::optional > + horizontal_asymptotes_left, horizontal_asymptotes_right; + + //! friends + friend class ::CGAL::Curve_analysis_2 + ; + +}; // class Curve_analysis_2_rep +} // namespace internal + + +/*! + * \brief Analysis for algebraic curves of arbitrary degree. + * + * This class constitutes a model for the concept + * AlgebraicKernelWithAnalysis_d_2::CurveAnalysis_2. + * For a square-free bivariate polynomial \c f, a topologic-geometrical + * analysis of the algebraic curve defined by the vanishing set of \c f + * is provided. This means, one can ask for the total number, and the position + * of the critical x-coordinates of the curve, and for each x-coordinate, + * geometric information about the curve can be obtained. This data + * is capsuled into an object of type \c Curve_analysis_2::Status_line_1, + * which is in fact a \c Status_line_CA_1 object. + * + * The restriction to square-free curves is a weak one, since the curves + * can be made square-free before passed to the analysis. + * The \c Construct_curve_2 functor of \c Algebraic_curve_kernel_2 is + * doing so, thus it accepts arbitrary bivariate polynomials. + * + * The analysis is implemented in a "lazy" fashion. This means, when + * created, the analysis delays all computations until the information + * is queried for the first time. This means, if only parts of the curves + * are of interest, only a partial analysis is performed. + * We remark that nevertheless, the global \e projection \e step + * (i.e., computing the (sub)resultants) must be done once a \c Status_line_1 + * is queried. Often, this step forms the bottleneck in the whole computation. + * + * For more details of the algorithm, consult the reference: + * A.Eigenwillig, M.Kerber, N.Wolpert: Fast and Exact Geometric Analysis of + * Real Algebraic Plane Curves. Proceedings of the International Symposium + * on Symbolic and Algebraic Computation (ISSAC 2007), pp. 151-158 + */ +template +> +class Curve_analysis_2 : public ::CGAL::Handle_with_policy< Rep_ > { + + //! \name typedefs + //! @{ + +public: + //! this instance' first template parameter + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + //! this instance' second template parameter + typedef Rep_ Rep; + +private: + + //! The internal type for event coordinates + typedef typename Rep::Event_coordinate_1 Event_coordinate_1; + + // Internal class to build lines at events + typedef typename Rep::Event_line_builder Event_line_builder; + + // Base class + typedef ::CGAL::Handle_with_policy Base; + + // This type + typedef CGAL::Curve_analysis_2 Self; + +public: + + //! Indexing type + typedef typename Rep::size_type size_type; + + CGAL_ACK_SNAP_ALGEBRAIC_CURVE_KERNEL_2_TYPEDEFS(Self); + + //! Required by the CurveKernel_2 concept + typedef Algebraic_real_1 Coordinate_1; + + //! Traits type for Polynomial_2 + typedef CGAL::Polynomial_traits_d Polynomial_traits_2; + +private: + + /*! + * \brief Coercion between the coefficient type of the polynomial + * and the bound type of the curve analysis + * + * Interoperability of both types is required + */ + typedef CGAL::Coercion_traits Coercion; + + /*! + * \brief The common supertype that both the coefficient and the bound + * type are convertible to + */ + typedef typename Coercion::Type Coercion_type; + + //! Polynomial over the \c Coercion_type + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type Poly_coer_1; + +public: + + //! Type to represent points on curves + typedef typename Algebraic_kernel_with_analysis_2::Algebraic_real_2 + Algebraic_real_2; + + //! Required by the CurveKernel_2 concept + typedef Algebraic_real_2 Coordinate_2; + + //! type for horizontal asymtote values + typedef CGAL::Object Asymptote_y; + + //! @} + +private: + + //! \name Helping structs + // @{ + + struct Event_functor { + Event_functor(const Self* curve) : curve(curve) {} + const Self* curve; + typedef size_type argument_type; + typedef Status_line_1 result_type; + result_type operator() (argument_type index) const { + return curve->status_line_at_event(index); + } + }; + + struct Intermediate_functor { + Intermediate_functor(const Self* curve) : curve(curve) {} + const Self* curve; + typedef size_type argument_type; + typedef Status_line_1 result_type; + result_type operator() (argument_type index) const { + return curve->status_line_of_interval(index); + } + }; + + struct Stha_functor { + Stha_functor(const Self* curve) : curve(curve) {} + const Self* curve; + typedef size_type argument_type; + typedef Polynomial_1 result_type; + result_type operator() (argument_type index) const { + return curve->principal_sturm_habicht_of_primitive(index); + } + }; + + //! @} + +public: + + //! \name Iterators + //! @{ + + //! Iterator type for status lines at events + typedef boost::transform_iterator > + Event_line_iterator; + + //! Iterator type for status lines of intervals + typedef boost::transform_iterator > + Intermediate_line_iterator; + + //! Iterator type for the principal sturm habicht coefficients of the curve + typedef boost::transform_iterator > + Principal_sturm_habicht_iterator; + + //! @} + +public: + + //!\name Constructors + //!@{ + + //! Default constructor, constructs an empty and invalid curve analysis + Curve_analysis_2() :Base(Rep()) { + } + + /*! + * \brief Constructs the curve analysis for the given polynomial + * + * Analyses the curve that is defined by the vanishing set of the + * polynomial \c f. + * \pre \c f is square free. + * \param strategy The default strategy + * (\c SHEAR_ONLY_AT_IRRATIONAL_STRATEGY) + * is to \c shear the curve + * if a degenerate situation is detected during the analysis, + * except at rational x-coordinates where the curve can be analysed + * more directly. The analysis + * is then performed in the sheared system, and finally translated back + * into the original system. + * Using \c SHEAR_STRATEGY, a shear is triggered also for degeneracies + * at rational x-coordinate. With both strategies, it is guaranteed that + * the analysis works successfully for any square free input curve. + * On the other hand, the EXCEPTION_STRATEGY throws an exception of type + * \c internal::Zero_resultant_exception, + * instead of performing a shear. + * + * \Todo Currently the defualt strategy has been changed to SHEAR_STRATEGY + * because there exist a problem if vertical asymtotes are present at + * the rational x-coordinate. + */ + explicit Curve_analysis_2(Algebraic_kernel_with_analysis_2 *kernel, + const Polynomial_2& f, + CGAL::Degeneracy_strategy strategy + = CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY) + throw(internal::Zero_resultant_exception) + : Base(Rep(kernel,f,strategy)) + { + + } + + //! \brief Copy constructor + Curve_analysis_2(const Self& alg_curve) + : Base(static_cast(alg_curve)) + { + } + + + //!@} + + + //! \name Members + //!@{ + +private: + + /* + * \brief Sets all status lines at events and of intervals + * + * Writes the status lines of events and interval into the object. + * The value type of both \c InputIterator1 and \c InputIterator2 + * is \c Status_line_1. + */ + template + void set_event_lines(InputIterator1 event_begin, + InputIterator1 event_end, + InputIterator2 intermediate_begin, + InputIterator2 CGAL_precondition_code(intermediate_end)) const { + + if(! this->ptr()->event_coordinates) { + + std::vector event_coordinate_vector; + + for(InputIterator1 it = event_begin; it != event_end; it++) { + Event_coordinate_1 curr_event; + curr_event.val = it->x(); + event_coordinate_vector.push_back(curr_event); + } + this->ptr()->event_coordinates = event_coordinate_vector; + + } + + InputIterator1 it1 = event_begin; + for(size_type i = 0; i < number_of_status_lines_with_event() ; i++ ) { + this->ptr()->vert_line_map[event_coordinates()[i].val] = *it1; + event_coordinates()[i].stack = *it1; + + it1++; + } + CGAL_assertion(it1 == event_end); + + if(! this->ptr()->intermediate_values) { + this->ptr()->intermediate_values + = std::vector > + (number_of_status_lines_with_event()+1); + } + + InputIterator2 it2 = intermediate_begin; + for(size_type i = 0; + i < static_cast(intermediate_values().size()); + i++,it2++) { + + CGAL_assertion(it2->x().is_rational()); + Bound q = it2->x().rational(); + + intermediate_values()[i] = q; + this->ptr()->vert_line_map[it2->x()] = *it2; + this->ptr()->vert_line_at_rational_map[q] = *it2; + + } + CGAL_assertion(it2 == intermediate_end); + + } + +public: + + /*! \brief Returns whether the curve has a valid defining polynomial + */ + bool has_defining_polynomial() const { + return this->ptr()->f; + } + +public: + + /*! \brief Sets the defining polynomial. + * + * \pre The object has no defining polynomial yet. + */ + void set_f(Polynomial_2 f) { + CGAL_precondition(! has_defining_polynomial()); + if((! this->ptr()->f) || f!=this->ptr()->f.get()) { + this->copy_on_write(); + this->ptr()->f=f; + } + } + + +public: + + /*! + * \brief Returns whether the curve is y-regular + * + * A curve is called y-regular if the leading coefficient of its defining + * polynomial wrt y is a constant, i.e., contains no x + */ + bool is_y_regular() const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_is_y_regular(); + } +#endif + return CGAL::degree(CGAL::leading_coefficient(polynomial_2())) == 0; + } + +public: + + /*! + * \brief returns whether the curve contains a vertical line as a component + * + * In algebraic terms, this methods computes whether the content + * of its defining polynomial has a real root. + */ + bool has_vertical_component() const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_has_vertical_components(); + } +#endif + if(is_y_regular()) { + this->ptr()->has_vertical_component = false; + } + if(! this->ptr()->has_vertical_component) { + // This is computed as side effect + // when the event coordinates are computed + event_coordinates(); + CGAL_assertion(this->ptr()->has_vertical_component); + } + return this->ptr()->has_vertical_component.get(); + } + +public: + + //! Returns the defining polynomial + Polynomial_2 polynomial_2() const { + CGAL_precondition(this->ptr()->f); + return this->ptr()->f.get(); + } + +public: + + /*! + * \brief Returns the number of event lines of the curve + * + * Algebraically, the number of real roots of the discriminant of + * the curve's defining equation is returned. + */ + size_type number_of_status_lines_with_event() const { + CGAL_precondition(this->ptr()->f); +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_number_of_status_lines_with_event(); + } +#endif + return static_cast(event_coordinates().size()); + } + +public: + + /*! + * \brief Returns whether the given x-coordinate is critical for the curve + * and which event or interval index the x-coordinate belongs to. + * + * \param is_event is set to \c true if the curve has an event + * at this x-coordinate, or in other words, if the discriminant of its + * defining polynomial vanishes at \c x + * \param i is set to the index of the event if \c x is an event. Otherwise + * \c i is set to the index of the interval \c x is contained in. + */ + void x_to_index(Algebraic_real_1 x,size_type& i,bool& is_event) const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_x_to_index(x,i,is_event); + } +#endif + CGAL_precondition(has_defining_polynomial()); + typename Rep::Val_functor xval; + i = std::lower_bound( + ::boost::make_transform_iterator(event_coordinates().begin(), + xval), + ::boost::make_transform_iterator(event_coordinates().end(), + xval), + x + ) - ::boost::make_transform_iterator(event_coordinates().begin(), + xval); + is_event = (i < static_cast(event_coordinates().size()) && + (event_coordinates()[i].val == x) ); + } + +public: + + //! Returns the status line at the i-th event of the curve. + Status_line_1& status_line_at_event(size_type i) const { + + CGAL_precondition(has_defining_polynomial()); +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_status_line_at_event(i); + } +#endif + CGAL_precondition_code( + size_type n = + static_cast(event_coordinates().size()); + ); + CGAL_precondition(i>=0 && iptr()->vert_line_map[event_coordinates()[i].val] + = event_line; + event_coordinates()[i].stack = event_line; + } + CGAL_postcondition(event_coordinates()[i].stack.get().is_event()); + return event_coordinates()[i].stack.get(); + } + +public: + + //! Returns a status line at the rational x-coordinate \c b + Status_line_1& status_line_at_exact_x(Bound b) const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_status_line_at_exact_x(b); + } +#endif + return status_line_at_exact_x(Algebraic_real_1(b)); + } + +private: + + /* + * \brief Returns a status line for an exact value \c alpha that + * is not an event of the curve + * + * This function controls the internal cache that stores already created + * status line at non-events. + */ + Status_line_1& status_line_at_exact_non_event_x(Algebraic_real_1 alpha) + const { + + if(alpha.is_rational()) { + + typename Rep::Vert_line_at_rational_map::iterator it = + this->ptr()->vert_line_at_rational_map.find + (alpha.rational()); + + if (it != this->ptr()->vert_line_at_rational_map.end()) { + CGAL_assertion(!it->second.is_event()); + return it->second; + } + } + + typename Rep::Vert_line_map::iterator it = + this->ptr()->vert_line_map.find(alpha); + + if (it != this->ptr()->vert_line_map.end()) { + CGAL_assertion(!it->second.is_event()); + return it->second; + } + + + // Not stored yet, so create it and store it + Status_line_1 cvl + = create_status_line_at_non_event(alpha); + CGAL_assertion(!cvl.is_event()); + this->ptr()->vert_line_map[alpha] = cvl; + + if(alpha.is_rational()) { + this->ptr()->vert_line_at_rational_map[alpha.rational()] = cvl; + } + return this->ptr()->vert_line_map[alpha]; + } + +public: + + //! Returns a vert line for the x-coordinate alpha + Status_line_1& status_line_at_exact_x(Algebraic_real_1 alpha) const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_status_line_at_exact_x(alpha); + } +#endif + bool is_event_value; + size_type index; + this->x_to_index(alpha,index,is_event_value); + if(is_event_value) { + return status_line_at_event(index); + } + else { + return status_line_at_exact_non_event_x(alpha); + } + } + +private: + + // Creates a status line for the curve's indexth critical point + Status_line_1 create_status_line_at_event(size_type index) const + throw(CGAL::internal::Non_generic_position_exception) { + + Event_coordinate_1& event = event_coordinates()[index]; + + Algebraic_real_1 x = event.val; + + try { + + Event_coordinate_1& event = event_coordinates()[index]; + + Algebraic_real_1 x = event.val; + +#if CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES + if(event.mult_of_prim_lcoeff_root > 0) { + throw CGAL::internal::Non_generic_position_exception(); + } +#else + if(event.mult_of_prim_lcoeff_root > 0) { + if(event.mult_of_prim_lcoeff_root > 1 || + event.mult_of_prim_res_root > 1) { + throw CGAL::internal::Non_generic_position_exception(); + } + } + +#endif + +#if CGAL_ACK_DEBUG_FLAG + double ev_approx = CGAL::to_double(x); + CGAL_ACK_DEBUG_PRINT << (index+1) << "th line: " + << std::setw(6) << std::setprecision(3) + << ev_approx + << ".." + << std::flush; +#endif + size_type left_arcs + = status_line_for_x(x,CGAL::NEGATIVE).number_of_events(); + size_type right_arcs + = status_line_for_x(x,CGAL::POSITIVE).number_of_events(); + + bool root_of_resultant=(event.mult_of_prim_res_root>0); + bool root_of_content=(event.mult_of_content_root>0); + + size_type mult_of_resultant = event.mult_of_prim_res_root; + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Event line for " << index << " " + << root_of_resultant << " " + << root_of_content << " " + << mult_of_resultant << " " + << left_arcs << " " << right_arcs + << std::endl; +#endif +*/ + + Status_line_1 ev_line + = event_line_builder().create_event_line(index, + x, + left_arcs, + right_arcs, + root_of_resultant, + root_of_content, + mult_of_resultant); + + event.stack = ev_line; + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + return ev_line; + } catch(CGAL::internal::Non_generic_position_exception exc) { + switch(this->ptr()->degeneracy_strategy) { + case(CGAL::EXCEPTION_STRATEGY): { + throw CGAL::internal::Non_generic_position_exception(); + break; + } + // Feature does not working atm + case(CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY): { + CGAL_error_msg("Currently not supported"); + /* + if(x.is_rational()) { + return create_non_generic_event_at_rational(x,index); + } + // FALL INTO NEXT CASE + */ + } + case(CGAL::SHEAR_STRATEGY): { + return create_non_generic_event_with_shear(index); + break; + } + default:{ + assert(false); // !!! Never reached + } + } + } + // !!! Never reached + return Status_line_1(); + } + +private: + + /* + * \brief Method to create a status line using shear and backshear + * + * Note that this methods creates all event lines of the object + * at once, and stores them in the object. + */ + Status_line_1 create_non_generic_event_with_shear(size_type index) const { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Use sheared technique..." << std::endl; +#endif + internal::Shear_controller shear_controller; + Integer s(0); + while(true) { + try { + s = shear_controller.get_shear_factor(); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Trying shear factor " + << s << std::endl; +#endif + // TODO: Move shear somewhere else + Self D(kernel(), + CGAL::internal::shear + (primitive_polynomial_2(),Coefficient(s)), + CGAL::EXCEPTION_STRATEGY); + Shear_transformation< Algebraic_kernel_with_analysis_2 > + shear_transformation(kernel()); + shear_transformation.report_sheared_disc_roots + (boost::make_transform_iterator( + event_coordinates().begin(), + typename Rep::Val_functor()), + boost::make_transform_iterator( + event_coordinates().end(), + typename Rep::Val_functor()) + ); + + // Store the sheared curve for later use + this->ptr()->sheared_curves.insert(std::make_pair(s,D)); + shear_transformation(D,-s,(Self&)*this,false); + set_vertical_line_components(); + + break; + } + catch(CGAL::internal::Non_generic_position_exception err) { + + shear_controller.report_failure(s); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Bad shear factor, retrying..." + << std::endl; +#endif + } + } + + return status_line_at_event(index); + } + +private: + + /* + * \brief creates a status line for a rational event x-coordinate + * + * If an event coordinate is rational, a shear can be prevented + * by plugging in the x-coordinate for x and explicitly computing + * the square free part of the defining polynomial at this position. + * + * COMMENTED OUT + + Status_line_1 create_non_generic_event_at_rational(Algebraic_real_1 x, + size_type index) const { + + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Non-generic, rational position x = " + << CGAL::to_double(x) + << std::flush; +#endif + + CGAL_precondition(x.is_rational()); + Bound r = x.rational(); + + Polynomial_1 f_at_x = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() + (primitive_polynomial_2(),0, 1), + r); + + f_at_x_sq_free + = typename CGAL::Polynomial_traits_d + ::Make_square_free() (f_at_x); + + Bitstream_coefficient_kernel coeff_kernel(kernel(),x); + Bitstream_traits traits(coeff_kernel); + + // We need to make an artificial bivariate polynomial + typedef typename + CGAL::Polynomial_traits_d + ::template Rebind::Other::Type + Poly_coer_num_2; + + std::vector coeffs; + for(int i = 0; i <= CGAL::degree(f_at_x_sq_free); i++) { + coeffs.push_back(typename FT::Numerator_type(f_at_x_sq_free[i])); + } + Poly_coer_num_2 f_at_x_ext(coeffs.begin(), coeffs.end()); + + Bitstream_descartes isolator(CGAL::internal::Square_free_descartes_tag(), + f_at_x_ext, + traits); + + // Now adjacencies + std::vector bucket_borders; + + int n = isolator.number_of_real_roots(); + + if(n==0) { + bucket_borders.push_back(0); + } else { + bucket_borders.push_back( + CGAL::internal::bound_left_of + (kernel(),Algebraic_real_1(isolator.left_bound(0)))); + for(int i = 1; i < n; i++) { + while(Algebraic_real_1(isolator.right_bound(i-1))== + Algebraic_real_1(isolator.left_bound(i))) { + isolator.refine_interval(i-1); + isolator.refine_interval(i); + } + bucket_borders.push_back( + kernel()->bound_between_1_object() + (Algebraic_real_1(isolator.right_bound(i-1)), + Algebraic_real_1(isolator.left_bound(i))) + ); + } + + bucket_borders.push_back( + CGAL::internal::bound_right_of + (kernel(), + Algebraic_real_1(isolator.right_bound(n-1)))); + } + + Bound left = bound_value_in_interval(index); + Bound right = bound_value_in_interval(index+1); + + typedef boost::numeric::interval Coercion_interval; + + typename Coercion::Cast cast; + + for(int i = 0; i < static_cast(bucket_borders.size()); i++) { + + Poly_coer_1 curr_pol + = primitive_polynomial_2().evaluate(bucket_borders[i]); + + CGAL::internal::Interval_evaluate_1 + + interval_evaluate_1; + + while(true) { + std::pair curr_interval_pair + = interval_evaluate_1(curr_pol,std::make_pair(left,right)); + Coercion_interval curr_interval(curr_interval_pair.first, + curr_interval_pair.second); + + if(boost::numeric::in_zero(curr_interval)) { + // "refine" + Bound middle = (left+right)/2; + if(middle==r) { + left=(left+middle)/2; + right = (right+middle)/2; + } else if(middle>r) { + right=middle; + } else { + left=middle; + } + } else { + break; + } + } + } + + Status_line_1 left_line + = status_line_at_exact_non_event_x(Algebraic_real_1(left)), + right_line + = status_line_at_exact_non_event_x(Algebraic_real_1(right)); + + int n_left = left_line.number_of_events(); + int n_right = right_line.number_of_events(); + + std::vector left_arcs(bucket_borders.size()+1), + right_arcs(bucket_borders.size()+1); + + for(unsigned int i=0;i(bucket_borders.size())) { + left_arcs[curr_index]++; + break; + } else if(left_line.lower_bound(i)> + bucket_borders[curr_index]) { + curr_index++; + } else if(left_line.upper_bound(i)< + bucket_borders[curr_index]) { + left_arcs[curr_index]++; + break; + } else { + left_line.refine(i); + } + } + } + curr_index=0; + for(int i=0; i < n_right; i++) { + + while(true) { + if(curr_index==static_cast(bucket_borders.size())) { + right_arcs[curr_index]++; + break; + } else if(right_line.lower_bound(i)> + bucket_borders[curr_index]) { + curr_index++; + } else if(right_line.upper_bound(i)< + bucket_borders[curr_index]) { + right_arcs[curr_index]++; + break; + } else { + right_line.refine(i); + } + } + + } + + typename Status_line_1::Arc_container arc_container; + + for(int i = 0; i < n; i++) { + arc_container.push_back(std::make_pair(left_arcs[i+1], + right_arcs[i+1])); + } + + Status_line_1 status_line(x,index,*this,n_left,n_right,arc_container); + + status_line._set_number_of_branches_approaching_infinity + (std::make_pair(left_arcs[0],right_arcs[0]), + std::make_pair(left_arcs[n+1],right_arcs[n+1])); + + status_line.set_isolator(isolator); + + if(event_coordinates()[index].mult_of_content_root > 0) { + status_line._set_v_line(); + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + return status_line; + } + */ + +public: + + /*! + * \brief Returns the status line for the interval + * preceeding the ith event + * + * Returns a status line for a reference x-coordinate of the ith + * interval of the curve. If called multiple times for the same i, + * the same status line is returned. + */ + Status_line_1 status_line_of_interval(size_type i) const + { + CGAL_precondition(i >= 0 && i <= number_of_status_lines_with_event()); + +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_status_line_of_interval(i); + } +#endif + + Bound b = bound_value_in_interval(i); + + Status_line_1 intermediate_line + = status_line_at_exact_non_event_x(Algebraic_real_1(b)); + + CGAL_postcondition(! intermediate_line.is_event()); + + return intermediate_line; + } + + +public: + + /*! + * \brief returns a status line at position \c x + * + * If \c x is not an event of the curve, and lies in the ith + * interval, the result is equal to status_line_of_interval(i). + * Different from status_line_at_exact_x(x) + * the status line \c s returned does not satisft s.x()==x. + * If \c x is an event, and \c perturb is set to \c CGAL::ZERO, + * the status line for the event is returned. Otherwise, the status line + * for the left or right neighboring interval is returned, depending + * on whether \c perturb is set to \c CGAL::NEGATIVE or \c CGAL::POSITIVE. + * If \c x is not an event, \c perturb has no effect. + */ + Status_line_1 status_line_for_x(Algebraic_real_1 x, + CGAL::Sign perturb = CGAL::ZERO) const + { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_status_line_for_x(x,perturb); + } +#endif + + size_type i; + bool is_evt; + x_to_index(x, i, is_evt); + if(is_evt) { + if(perturb == CGAL::ZERO) + return status_line_at_event(i); + if(perturb == CGAL::POSITIVE) + i++; + } + return status_line_of_interval(i); + } + + +private: + + /* + * \brief Creates an intermediate line at position \c ar. + * + * It is required that none of the following situations occurs at position + * ar: singularity, vertical tangent line, vertical asymptote.\n + * Otherwise, the method might run into an infinite loop. + * + * \param index if set to -1, the interval containing \c ar is computed + * within the method, and the index of the status line is set accordingly. + */ + Status_line_1 + create_status_line_at_non_event(Algebraic_real_1 ar, int index = -1) + const { + + if(index==-1) { + bool event; + x_to_index(ar,index,event); + CGAL_assertion(!event); + } + CGAL_assertion(index>=0); + + // TODO .. delay creation of refinement object + // especially when ar is rational + + Bitstream_coefficient_kernel coeff_kernel(kernel(),ar); + Bitstream_traits traits(coeff_kernel); + + Bitstream_descartes + bitstream_descartes(CGAL::internal::Square_free_descartes_tag(), + primitive_polynomial_2(), + traits); + + size_type root_number=bitstream_descartes.number_of_real_roots(); + + Status_line_1 status_line(ar, index, *this, root_number); + status_line.set_isolator(bitstream_descartes); + + CGAL_assertion(! status_line.is_event()); + + return status_line; + } + +private: + + /* + * \brief Returns an Event_line_builder instance + * + * Note: So far, a new instance is created each time the function is called + */ + Event_line_builder event_line_builder() const { + + return Event_line_builder(kernel(), *this, primitive_polynomial_2()); + } + +public: + + /*! + * \brief Number of arcs over the given interval + * + * Shortcut for status_line_of_interval(i).number_of_events() + */ + size_type arcs_over_interval(size_type i) const { + CGAL_precondition(has_defining_polynomial()); +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_arcs_over_interval(i); + } +#endif + CGAL_assertion_code( + size_type n + = static_cast(intermediate_values().size()); + ); + CGAL_precondition(i>=0 && i<=n); + return status_line_of_interval(i).number_of_events(); + } + +public: + + /*! + * \brief Rational number in the ith interval between events + * + * The result of this method is taken as the reference x-coordinate + * for the status lines of intervals. + */ + Bound bound_value_in_interval(size_type i) const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_bound_value_in_interval(i); + } +#endif + CGAL_assertion(i>=0 && + i < static_cast + (intermediate_values().size())); + if(! intermediate_values()[i]) { + // Create it + if(event_coordinates().size()==0) { + CGAL_assertion(i==0); + intermediate_values()[0]=Bound(0); + } else { + if(i==0) { + intermediate_values()[i] + = bound_left_of(kernel(),event_coordinates()[i].val); + } else if(i == static_cast + (event_coordinates().size())) { + intermediate_values()[i] + = bound_right_of + (kernel(),event_coordinates()[i-1].val); + + } else { + intermediate_values()[i] + = kernel()->bound_between_1_object() + (event_coordinates()[i-1].val, + event_coordinates()[i].val); + } + } + } + return intermediate_values()[i].get(); + } + + +public: + + /*! + * Returns the content of the defining polynomial + * + * The content is the gcd of its coefficients (the polynomial is considered + * as polynomial in \c y) + */ + Polynomial_1 content() const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_content(); + } +#endif + if(! this->ptr()->content) { + compute_content_and_primitive_part(); + } + return this->ptr()->content.get(); + } + +public: + + /*! + * Returns the primitive part of the defining polynomial + * + * The primitive part of \c f is the \c f divided by its content. + */ + Polynomial_2 primitive_polynomial_2() const { +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_primitive_polynomial_2(); + } +#endif + if(! this->ptr()->f_primitive) { + compute_content_and_primitive_part(); + } + return this->ptr()->f_primitive.get(); + } + + Algebraic_kernel_with_analysis_2* kernel() const { + return this->ptr()->_m_kernel; + } + +private: + + + // computes and sets the content and the primitive part for the curve + void compute_content_and_primitive_part() const { + + CGAL_assertion(has_defining_polynomial()); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Computing the content..." << std::flush; +#endif + this->ptr()->content + = typename CGAL::Polynomial_traits_d< Polynomial_2 >:: + Univariate_content_up_to_constant_factor()( polynomial_2() ); + if(CGAL::degree(content())==0) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "no vertical lines as components" + << std::endl; +#endif + this->ptr()->f_primitive=polynomial_2(); + } + else { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "non-trivial content found" << std::endl; +#endif + // Content must be square free, because the curve is square free + CGAL_assertion( typename CGAL::Polynomial_traits_d< Polynomial_1 > + ::Is_square_free()(content())); + this->ptr()->f_primitive=polynomial_2() / content(); + + } + + } + +private: + + //! Returns the Sturm-Habicht sequence of the primitive part of f + std::vector& sturm_habicht_of_primitive() const + throw(internal::Zero_resultant_exception) { + if(! this->ptr()->sturm_habicht_of_primitive) { + compute_sturm_habicht_of_primitive(); + } + return this->ptr()->sturm_habicht_of_primitive.get(); + } + +public: + + /*! + * \brief Returns the ith Sturm-Habicht polynomial + * of the primitive part of the defining polynomial + */ + Polynomial_2 sturm_habicht_of_primitive(size_type i) const + throw(internal::Zero_resultant_exception) { + CGAL_assertion(i>=0 && + i < static_cast + (sturm_habicht_of_primitive().size())); + return sturm_habicht_of_primitive()[i]; + } + +public: + + /*! + * \brief Returns the ith principal Sturm-Habicht coefficient + * of the primitive part of the defining polynomial + */ + Polynomial_1 principal_sturm_habicht_of_primitive(size_type i) const + throw(internal::Zero_resultant_exception) { + CGAL_assertion(i>=0 && + i < static_cast + (sturm_habicht_of_primitive().size())); + + CGAL_assertion(CGAL::degree(sturm_habicht_of_primitive()[i])<=i); + if(CGAL::degree(sturm_habicht_of_primitive()[i]) < i) { + return Polynomial_1(0); + } // else: + return sturm_habicht_of_primitive()[i][i]; + } + +public: + + /*! + * \brief Returns the ith coprincipal Sturm-Habicht coefficient + * of the primitive part of the defining polynomial + * + * The coprincipal Sturm-Habicht coefficient is the coefficient + * of y^{i-1} of the ith Sturm-Habicht polynomial + */ + Polynomial_1 coprincipal_sturm_habicht_of_primitive(size_type i) const + throw(internal::Zero_resultant_exception) { + CGAL_assertion(i>=1 && + i < static_cast + (sturm_habicht_of_primitive().size())); + CGAL_assertion(CGAL::degree(sturm_habicht_of_primitive()[i])<=i); + if(CGAL::degree(sturm_habicht_of_primitive()[i]) < i-1) { + return Polynomial_1(0); + } // else: + return sturm_habicht_of_primitive()[i][i-1]; + } + +public: + + /*! + * \brief Returns an iterator to the principal Sturm-Habicht coefficients, + * starting with the 0th one (the resultant) + */ + Principal_sturm_habicht_iterator principal_sturm_habicht_begin() const { + return boost::make_transform_iterator + (boost::counting_iterator(0), + Stha_functor(this)); + } + + //! Returns an iterator to the end of principal Sturm-Habicht coefficients + Principal_sturm_habicht_iterator principal_sturm_habicht_end() const { + return boost::make_transform_iterator + (boost::counting_iterator + (sturm_habicht_of_primitive().size()), + Stha_functor(this)); + } + +private: + + // Internal method to compute the Sturm-Habicht sequence + void compute_sturm_habicht_of_primitive() const + throw(internal::Zero_resultant_exception) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute Sturm-Habicht.." << std::flush; +#endif + std::vector stha; + + // Fix a problem for constant primitive part. + // In this case, the St.-Ha. sequence is never needed + if(CGAL::degree(primitive_polynomial_2()) == 0) { + // Set the resultant + stha.push_back(primitive_polynomial_2()); + } else { + +#if CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS +#warning USES BEZOUT MATRIX FOR SUBRESULTANTS + CGAL::internal::bezout_polynomial_subresultants + (primitive_polynomial_2(), + CGAL::differentiate(primitive_polynomial_2()), + std::back_inserter(stha)); + stha.push_back(primitive_polynomial_2()); + size_type p = CGAL::degree(primitive_polynomial_2()); + CGAL_assertion(static_cast(stha.size()) == p+1); + for(size_type i=0;iptr()->resultant_of_primitive_and_derivative_y) { + this->ptr()->resultant_of_primitive_and_derivative_y = stha[0][0]; + if(this->ptr()->resultant_of_primitive_and_derivative_y. + get().is_zero()) { + throw internal::Zero_resultant_exception + (polynomial_2()); + } + } + + this->ptr()->sturm_habicht_of_primitive = stha; + CGAL_assertion(CGAL::canonicalize + (resultant_of_primitive_and_derivative_y()) == + CGAL::canonicalize + (principal_sturm_habicht_of_primitive(0))); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + } + +private: + + //! Returns the resultant of the primitive part of f and its y-derivative + Polynomial_1 resultant_of_primitive_and_derivative_y() const + throw(internal::Zero_resultant_exception) { + if(! this->ptr()->resultant_of_primitive_and_derivative_y) { + compute_resultant_of_primitive_and_derivative_y(); + } + return this->ptr()->resultant_of_primitive_and_derivative_y.get(); + } + +private: + + //! Returns the resultant of the primitive part of f with its x-derivative + Polynomial_1 resultant_of_primitive_and_derivative_x() const + throw(internal::Zero_resultant_exception) { + if(! this->ptr()->resultant_of_primitive_and_derivative_x) { + compute_resultant_of_primitive_and_derivative_x(); + } + return this->ptr()->resultant_of_primitive_and_derivative_x.get(); + } + +private: + // Computes res_y(f,f_y), where \c f is the defining polynomial + void compute_resultant_of_primitive_and_derivative_y() const + throw(internal::Zero_resultant_exception) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute resultant.." << std::flush; +#endif + + CGAL_assertion(has_defining_polynomial()); + +#if CGAL_ACK_RESULTANT_FIRST_STRATEGY +#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD + bool speed_up = true; +#else + bool speed_up=CGAL::degree(polynomial_2()) >= + CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD; +#endif +#else + bool speed_up=false; +#endif + + if(CGAL::degree(polynomial_2()) == 0) { + this->ptr()->resultant_of_primitive_and_derivative_y + = Polynomial_1(1); + } else { + + if(! speed_up) { + + // Compute resultant using the Sturm-Habicht sequence + this->ptr()->resultant_of_primitive_and_derivative_y + = principal_sturm_habicht_of_primitive(0); + + } else { + typename Polynomial_traits_2::Differentiate diff; + this->ptr()->resultant_of_primitive_and_derivative_y + = CGAL::resultant + (primitive_polynomial_2(), + diff(primitive_polynomial_2(),1)); + } + + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + if(resultant_of_primitive_and_derivative_y().is_zero()) { + throw internal::Zero_resultant_exception + (polynomial_2()); + } + } + + // Computes res_y(f,f_x), where \c f is the defining polynomial + void compute_resultant_of_primitive_and_derivative_x() const + throw(internal::Zero_resultant_exception) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute x-resultant.." << std::flush; +#endif + + CGAL_assertion(has_defining_polynomial()); + + // Transpose the polynomial + Polynomial_2 f_yx = typename Polynomial_traits_2::Swap() + (polynomial_2(),0,1); + + if( CGAL::degree(f_yx) == 0 ) { + // Polynomial only consists of horizontal lines + // primitive resultant is set to 1 + this->ptr()->resultant_of_primitive_and_derivative_x + = Polynomial_1(1); + } else { + + Polynomial_2 f_yx_primitive; + + Polynomial_1 content_yx + = typename CGAL::Polynomial_traits_d< Polynomial_2 >:: + Univariate_content_up_to_constant_factor()( f_yx ); + if(CGAL::degree(content_yx)==0) { + f_yx_primitive=f_yx; + } + else { + CGAL_assertion + (typename CGAL::Polynomial_traits_d< Polynomial_1 >:: + Is_square_free()(content_yx)); + f_yx_primitive=f_yx / content_yx; + + } + + this->ptr()->resultant_of_primitive_and_derivative_x + = CGAL::resultant + (typename Polynomial_traits_2::Swap() (f_yx_primitive,0,1), + typename Polynomial_traits_2::Swap() + (CGAL::differentiate(f_yx_primitive),0,1) ); + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + if(resultant_of_primitive_and_derivative_x().is_zero()) { + throw internal::Zero_resultant_exception + (polynomial_2()); + } + } + + + + +private: + + // Returns the critical event coordinates + std::vector& event_coordinates() const + throw(internal::Zero_resultant_exception) { + if(! this->ptr()->event_coordinates) { + compute_event_coordinates(); + } + return this->ptr()->event_coordinates.get(); + } + +private: + + // Returns the intermediate values for intervals between events + std::vector >& intermediate_values() const + throw(internal::Zero_resultant_exception) { + + if(! this->ptr()->intermediate_values) { + // This is created during event_coordiantes() + event_coordinates(); + CGAL_assertion(this->ptr()->intermediate_values); + } + return this->ptr()->intermediate_values.get(); + } + + +private: + + /* + * \brief Computes the event coordinates of the curve. + * + * This function computes the content of the defining polynomial, + * and the roots of its discriminant. These two sets form the critical + * x-coordinates of the curve. + */ + void compute_event_coordinates() const + throw(internal::Zero_resultant_exception) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "compute events..." << std::flush; +#endif + + Solve_1 solve_1; + + std::vector > content_pairs; + std::vector content_roots; + std::vector content_mults; + solve_1(content(), + std::back_inserter(content_pairs)); + + for(int i=0; i < static_cast(content_pairs.size()); i++ ) { + content_roots.push_back(content_pairs[i].first); + content_mults.push_back(content_pairs[i].second); + } + + // Set the vertical_line_components flag as side effect + this->ptr()->has_vertical_component = (content_roots.size() > 0); + + std::vector > res_pairs; + std::vector res_roots; + std::vector res_mults; + Polynomial_1 R = resultant_of_primitive_and_derivative_y(); + solve_1(R,std::back_inserter(res_pairs)); + + for(int i=0; i < static_cast(res_pairs.size()); i++ ) { + res_roots.push_back(res_pairs[i].first); + res_mults.push_back(res_pairs[i].second); + } + + std::vector > lcoeff_pairs; + std::vector lcoeff_roots; + std::vector lcoeff_mults; + solve_1(CGAL::leading_coefficient(primitive_polynomial_2()), + std::back_inserter(lcoeff_pairs)); + + for(int i=0; i < static_cast(lcoeff_pairs.size()); i++ ) { + lcoeff_roots.push_back(lcoeff_pairs[i].first); + lcoeff_mults.push_back(lcoeff_pairs[i].second); + } + + + //Now, merge the vertical line positions with the resultant roots + typename + CGAL::Real_embeddable_traits::Compare compare; + + std::vector event_values; + std::vector event_values_info; + + CGAL::internal::set_union_with_source + (res_roots.begin(), + res_roots.end(), + content_roots.begin(), + content_roots.end(), + std::back_inserter(event_values), + std::back_inserter(event_values_info), + compare); + + // Now, build the Event_coordinate_1 entries + // for each element of event_values + size_type curr_res_index = 0, curr_content_index = 0, + curr_lcoeff_index = 0; + std::vector event_coordinate_vector; + + for(size_type i = 0; + i < static_cast(event_values.size()); + i++ ) { + + Event_coordinate_1 curr_event; + curr_event.val = event_values[i]; + switch(event_values_info[i]) { + + case(CGAL::internal::ROOT_OF_FIRST_SET): { + curr_event.index_of_prim_res_root = curr_res_index; + CGAL_expensive_assertion(res_roots[curr_res_index] == + event_values[i]); + curr_event.mult_of_prim_res_root + = res_mults[curr_res_index]; + curr_res_index++; + if(curr_lcoeff_index < + static_cast(lcoeff_roots.size()) && + event_values[i]==lcoeff_roots[curr_lcoeff_index]) { + // We have a root of the leading coefficient + // of the primitve polynomial + curr_event.index_of_prim_lcoeff_root = curr_lcoeff_index; + curr_event.mult_of_prim_lcoeff_root + = lcoeff_mults[curr_lcoeff_index]; + curr_lcoeff_index++; + } else { + curr_event.index_of_prim_lcoeff_root = -1; + curr_event.mult_of_prim_lcoeff_root = 0; + } + + curr_event.index_of_content_root = -1; + curr_event.mult_of_content_root = 0; + break; + } + case(CGAL::internal::ROOT_OF_SECOND_SET): { + curr_event.index_of_content_root = curr_content_index; + CGAL_expensive_assertion(content_roots[curr_content_index] == + event_values[i]); + curr_event.mult_of_content_root + = content_mults[curr_content_index]; + curr_content_index++; + curr_event.index_of_prim_res_root = -1; + curr_event.mult_of_prim_res_root = 0; + CGAL_expensive_assertion(event_values[i]!= + lcoeff_roots[curr_lcoeff_index]); + curr_event.index_of_prim_lcoeff_root = -1; + curr_event.mult_of_prim_lcoeff_root = 0; + break; + } + case(CGAL::internal::ROOT_OF_BOTH_SETS): { + curr_event.index_of_prim_res_root = curr_res_index; + CGAL_expensive_assertion(res_roots[curr_res_index] == + event_values[i]); + curr_event.mult_of_prim_res_root + = res_mults[curr_res_index]; + curr_res_index++; + if(curr_lcoeff_index < + static_cast(lcoeff_roots.size()) && + event_values[i]==lcoeff_roots[curr_lcoeff_index]) { + // We have a root of the leading coefficient + // of the primitve polynomial + curr_event.index_of_prim_lcoeff_root = curr_lcoeff_index; + curr_event.mult_of_prim_lcoeff_root + = lcoeff_mults[curr_lcoeff_index]; + curr_lcoeff_index++; + } else { + curr_event.index_of_prim_lcoeff_root = -1; + curr_event.mult_of_prim_lcoeff_root = 0; + } + curr_event.index_of_content_root = curr_content_index; + CGAL_expensive_assertion(content_roots[curr_content_index] == + event_values[i]); + curr_event.mult_of_content_root + = content_mults[curr_content_index]; + curr_content_index++; + break; + } + } // of switch + /* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Constructed event_coordinate: " + << CGAL::to_double(curr_event.val) << " " + << "\nmult_of_prim_res_root : " + << curr_event.mult_of_prim_res_root + << "\nindex_of_prim_res_root : " + << curr_event.index_of_prim_res_root + << "\nmult_of_content_root : " + << curr_event.mult_of_content_root + << "\nindex_of_content_root : " + << curr_event.index_of_content_root + << "\nmult_of_lcoeff_root : " + << curr_event.mult_of_prim_lcoeff_root + << "\nindex_of_lcoeff_root : " + << curr_event.index_of_prim_lcoeff_root + << std::endl; +#endif + */ + event_coordinate_vector.push_back(curr_event); + } + + + CGAL_assertion(curr_lcoeff_index == + static_cast(lcoeff_roots.size())); + CGAL_assertion(curr_res_index == + static_cast(res_roots.size())); + CGAL_assertion(curr_content_index == + static_cast(content_roots.size())); + + this->ptr()->intermediate_values + = std::vector > + (event_coordinate_vector.size()+1); + this->ptr()->event_coordinates = event_coordinate_vector; + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + } + +public: + + /*! + * \brief Returns a \c Curve_analysis_2 object for a sheared curve. + * + * The shear factor is given by the integer \c s. + * This functions only shears the primitive part of the defining equation. + * Internal caching is used to avoid repeated shears. + * + * \todo The sheared curves are not inserted into the curve_cache + * of the Algebraic_curve_kernel_2 yet. + */ + Self& shear_primitive_part(Integer s) const + throw(CGAL::internal::Non_generic_position_exception) + { + CGAL_assertion(s!=0); +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_shear_primitive_part(); + } +#endif + if(this->ptr()->bad_shears.find(s) != + this->ptr()->bad_shears.end()) { + throw CGAL::internal::Non_generic_position_exception(); + } + typedef typename std::map::iterator + Map_iterator; + Map_iterator it = this->ptr()->sheared_curves.find(s); + if(it != this->ptr()->sheared_curves.end()) { + return it->second; + } + try { + Shear_transformation + shear_transformation(kernel()); + Self D=shear_transformation((Self&)*this, s); + std::pair insertion = + this->ptr()->sheared_curves.insert(std::make_pair(s,D)); + CGAL_assertion(insertion.second); + return insertion.first->second; + } + catch(CGAL::internal::Non_generic_position_exception err) { + this->ptr()->bad_shears.insert(s); + throw CGAL::internal::Non_generic_position_exception(); + } + } + +public: + + //! Iterator for sheared curves + typename std::map::const_iterator shear_begin() { + return this->ptr()->sheared_curves.begin(); + } + + //! Iterator for sheared curves + typename std::map::const_iterator shear_end() { + return this->ptr()->sheared_curves.end(); + } + +private: + + // Sets the flag for vertical lines in all status lines that need it + void set_vertical_line_components() const { + for(size_type i = 0; + i < static_cast(event_coordinates().size()); + i++ ) { + + if(event_coordinates()[i].mult_of_content_root > 0) { + status_line_at_event(i)._set_v_line(); + } + } + + } + + +public: + + /*! + * \brief Increases the precision of all status lines + * + * For each status line at an event and each status line that represents + * an interval, all y-coordinates are approximated such that their + * isolating interval has absolute size smaller then \c precision. + */ + void refine_all(Bound precision) { + +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_refine_all(precision); + } +#endif + + for(size_type i=0; + i(event_coordinates().size()); + i++) { + /* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << i << ": " << std::flush; +#endif + */ + Status_line_1& el = status_line_at_event(i); + + for(size_type j=0;j(intermediate_values().size()); + i++) { + Status_line_1 il = status_line_of_interval(i); + for(size_type j=0;j(0), + Event_functor(this)); + } + + //! \brief Iterator for the status lines at events + Event_line_iterator event_end() const { + return boost::make_transform_iterator + (boost::counting_iterator + (number_of_status_lines_with_event()), + Event_functor(this)); + } + +public: + + //! \brief Iterator for the status lines for intervals + Intermediate_line_iterator intermediate_begin() const { + return boost::make_transform_iterator + (boost::counting_iterator(0), + Intermediate_functor(this)); + } + + //! \brief Iterator for the status lines for intervals + Intermediate_line_iterator intermediate_end() const { + return boost::make_transform_iterator + (boost::counting_iterator(intermediate_values().size()), + Intermediate_functor(this)); + } + +public: + + /*! + * \brief Returns the limit an infinite arc converges to + * + * \pre loc==CGAL::ARR_LEFT_BOUNDARY || + * loc==CGAL::ARR_RIGHT_BOUNDARY + * + * This method returns for the arcnoth arc that goes to -infinity + * or +infinity (depending on \c loc) the y-coordinate it converges to. + * Possible values are either a \c Algebraic_real_1 object, or one of the + * values \c CGAL::ARR_TOP_BOUNDARY, \c CGAL::ARR_BOTTOM_BOUNDARY + * that denote that the arc is unbounded in y-direction. + * The result is wrapped into a \c CGAL::Object object. + */ + Asymptote_y asymptotic_value_of_arc(CGAL::Arr_parameter_space loc, + size_type arcno) const { + + CGAL_precondition(loc == CGAL::ARR_LEFT_BOUNDARY || + loc == CGAL::ARR_RIGHT_BOUNDARY); + +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + if(CGAL::degree(polynomial_2(),1)==2) { + return this->conic_asymptotic_value_of_arc(loc,arcno); + } +#endif + + if(loc == CGAL::ARR_LEFT_BOUNDARY) { + + if(! this->ptr()->horizontal_asymptotes_left) { + compute_horizontal_asymptotes(); + } + std::vector& asym_info + = this->ptr()->horizontal_asymptotes_left.get(); + CGAL_precondition(arcno>=0 && + arcno(asym_info.size())); + return asym_info[arcno]; + } // else loc == CGAL::ARR_RIGHT_BOUNDARY + + if(! this->ptr()->horizontal_asymptotes_right) { + compute_horizontal_asymptotes(); + } + std::vector& asym_info + = this->ptr()->horizontal_asymptotes_right.get(); + CGAL_precondition(arcno>=0 && + arcno(asym_info.size())); + return asym_info[arcno]; + + } + + +private: + + // Internal method to compute horizontal asymptotes + void compute_horizontal_asymptotes() const { + + // TODO: Filter out curves with no arc to +/- infty + + Solve_1 solve_1 = kernel()->solve_1_object(); + + Polynomial_1 leading_coefficient_in_x + = CGAL::leading_coefficient(typename Polynomial_traits_2::Swap() + (polynomial_2(),0,1)); + std::vector roots_of_lcoeff; + + solve_1(leading_coefficient_in_x, + std::back_inserter(roots_of_lcoeff), + false); + + + std::vector stripe_bounds; + find_intermediate_values(kernel(), + roots_of_lcoeff.begin(), + roots_of_lcoeff.end(), + std::back_inserter(stripe_bounds)); + Bound leftmost_bound = bound_value_in_interval(0), + rightmost_bound = bound_value_in_interval + (this->number_of_status_lines_with_event()); + for(size_type i=0;i(stripe_bounds.size());i++) { + Bound& beta = stripe_bounds[i]; + Polynomial_1 poly_at_beta + = kernel()->evaluate_utcf_2_object()(this->polynomial_2(),beta); + std::vector x_coordinates_at_beta; + solve_1(poly_at_beta,std::back_inserter(x_coordinates_at_beta), + false); + size_type number_of_roots + = static_cast(x_coordinates_at_beta.size()); + if(number_of_roots>0) { + if(leftmost_bound > x_coordinates_at_beta[0].low()) { + leftmost_bound = x_coordinates_at_beta[0].low(); + } + if(rightmost_bound + < x_coordinates_at_beta[number_of_roots-1].high()) { + rightmost_bound + = x_coordinates_at_beta[number_of_roots-1].high(); + } + } + } + + // Just to be sure... + leftmost_bound = leftmost_bound - 1; + rightmost_bound = rightmost_bound + 1; + + Polynomial_1 curve_at_left_end + = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (this->polynomial_2(),0,1), + leftmost_bound); + std::vector roots_at_left_end; + solve_1(curve_at_left_end,std::back_inserter(roots_at_left_end),false); + size_type number_of_roots_at_left_end + = static_cast(roots_at_left_end.size()); + std::vector asym_left_info; + size_type current_stripe=0,i=0; + while(i(stripe_bounds.size())) { + asym_left_info.push_back( CGAL::make_object + (CGAL::ARR_TOP_BOUNDARY) ); + i++; + continue; + } + if(roots_at_left_end[i].low() > stripe_bounds[current_stripe]) { + current_stripe++; + continue; + } + if(roots_at_left_end[i].high() < stripe_bounds[current_stripe]) { + if(current_stripe==0) { + asym_left_info.push_back(CGAL::make_object + (CGAL::ARR_BOTTOM_BOUNDARY)); + i++; + continue; + } else { + asym_left_info.push_back(CGAL::make_object + (roots_of_lcoeff[current_stripe-1])); + i++; + continue; + } + } + roots_at_left_end[i].refine(); + } + this->ptr()->horizontal_asymptotes_left = asym_left_info; + + Polynomial_1 curve_at_right_end + = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (this->polynomial_2(),0,1), + rightmost_bound); + std::vector roots_at_right_end; + solve_1(curve_at_right_end,std::back_inserter(roots_at_right_end),false); + size_type number_of_roots_at_right_end + = static_cast(roots_at_right_end.size()); + std::vector asym_right_info; + current_stripe=0; + i=0; + while(i(stripe_bounds.size())) { + asym_right_info.push_back(CGAL::make_object + (CGAL::ARR_TOP_BOUNDARY) ); + i++; + continue; + } + if(roots_at_right_end[i].low() > stripe_bounds[current_stripe]) { + current_stripe++; + continue; + } + if(roots_at_right_end[i].high() < stripe_bounds[current_stripe]) { + if(current_stripe==0) { + asym_right_info.push_back(CGAL::make_object + (CGAL::ARR_BOTTOM_BOUNDARY)); + i++; + continue; + } else { + asym_right_info.push_back + (CGAL::make_object(roots_of_lcoeff[current_stripe-1])); + i++; + continue; + } + } + roots_at_right_end[i].refine(); + } + this->ptr()->horizontal_asymptotes_right = asym_right_info; + + } + + //! @} + +public: + + template void get_roots_at_rational + (Bound r, OutputIterator it) const { + + typename Rep::Intermediate_cache::Find_result find_result + = this->ptr()->intermediate_cache.find(r); + + std::vector p_roots; + + if(find_result.second) { + p_roots = find_result.first->second; + } else { + Polynomial_2 swapped = typename Polynomial_traits_2::Swap() + (this->polynomial_2(), 0, 1); + Polynomial_1 p = kernel()->evaluate_utcf_2_object()(swapped,r); + kernel()->solve_1_object()(p,std::back_inserter(p_roots),false); + + this->ptr()->intermediate_cache.insert(std::make_pair(r,p_roots)); + + } + std::copy(p_roots.begin(),p_roots.end(),it); + } + + + // \name Internal functions for Conic optimization + //! @{ + +#if CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX + +private: + + bool conic_is_y_regular() const { + CGAL_error_msg("Implement me"); + return false; + } + + bool conic_has_vertical_component() const { + CGAL_error_msg("Implement me"); + return false; + } + + size_type conic_number_of_status_lines_with_event() const { + CGAL_error_msg("Implement me"); + return 0; + } + + void conic_x_to_index(Algebraic_real_1 x,size_type& i,bool& is_event) const + { + CGAL_error_msg("Implement me"); + } + + Status_line_1& conic_status_line_at_event(size_type i) const { + CGAL_error_msg("Implement me"); + // Just a random status line to make compiler happy + return this->ptr()->vert_line_at_rational_map[Bound(0)]; + } + + Status_line_1& conic_status_line_at_exact_x(Bound b) const { + CGAL_error_msg("Implement me"); + return this->ptr()->vert_line_at_rational_map[Bound(0)]; + } + + Status_line_1& conic_status_line_at_exact_x(Algebraic_real_1 alpha) const { + CGAL_error_msg("Implement me"); + return this->ptr()->vert_line_at_rational_map[Bound(0)]; + } + + Status_line_1 conic_status_line_of_interval(size_type i) const { + CGAL_error_msg("Implement me"); + return this->ptr()->vert_line_at_rational_map[Bound(0)]; + } + + Status_line_1 conic_status_line_for_x + (Algebraic_real_1 x, + CGAL::Sign perturb = CGAL::ZERO) const { + CGAL_error_msg("Implement me"); + return this->ptr()->vert_line_at_rational_map[Bound(0)]; + } + + size_type conic_arcs_over_interval(size_type i) const { + CGAL_error_msg("Implement me"); + return -1; + } + + Bound conic_bound_value_in_interval(size_type i) const { + CGAL_error_msg("Implement me"); + return Bound(0); + } + + Polynomial_1 conic_content() const { + CGAL_error_msg("Implement me"); + return Polynomial_1(); + } + + Polynomial_2 conic_primitive_polynomial_2() const { + CGAL_error_msg("Implement me"); + return Polynomial_2(); + } + + Self& conic_shear_primitive_part(Integer s) const { + CGAL_error_msg("Implement me"); + return Self(); + } + + void conic_refine_all(Bound precision) { + CGAL_error_msg("Implement me"); + } + + Asymptote_y conic_asymptotic_value_of_arc(CGAL::Arr_parameter_space loc, + size_type arcno) const { + CGAL_error_msg("Implement me"); + return Asymptote_y(); + } + +#endif + + + //! @} + + //! \name friends + //! @{ + + // friend function for id-based hashing + friend std::size_t hash_value(const Self& x) { + return static_cast(x.id()); + } + + // another friend + friend class Shear_transformation; + + //! @} + +}; // class Algebraic_curve_2_2 + + +//! \brief Prints the objects. +template +std::ostream& operator<< ( + std::ostream& out, + const Curve_analysis_2< AlgebraicKernelWithAnalysis_2, + Rep_ >& curve) { + + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + typedef Rep_ Rep; + + typedef Curve_analysis_2< Algebraic_kernel_with_analysis_2, Rep > Curve; + + typedef typename Curve::size_type size_type; + typedef typename Curve::Asymptote_y Asymptote_y; + + + switch (::CGAL::get_mode(out)) { + case ::CGAL::IO::PRETTY: { + + out << "--------------- Analysis results ---------------" << std::endl; + out << "Number of constructed event lines: " + << curve.number_of_status_lines_with_event() + << std::endl; + out << "(Horizontal) asymptotes at -infty: " << std::flush; + for (size_type i = 0; i < curve.arcs_over_interval(0); i++) { + + const Asymptote_y& curr_asym_info_obj + = curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,i); + typename Curve::Algebraic_real_1 curr_asym_info; + bool is_finite = CGAL::assign(curr_asym_info,curr_asym_info_obj); + if (!is_finite) { + // Assignment to prevent compiler warning + CGAL::Arr_parameter_space loc = CGAL::ARR_LEFT_BOUNDARY; + CGAL_assertion_code(bool is_valid = ) + CGAL::assign(loc, curr_asym_info_obj); + CGAL_assertion(is_valid); + if (loc == CGAL::ARR_TOP_BOUNDARY) { + out << "+infty " << std::flush; + } else { + CGAL_assertion(loc == CGAL::ARR_BOTTOM_BOUNDARY); + out << "-infty " << std::flush; + } + } else { // is_finite + out << CGAL::to_double(curr_asym_info) + << " " << std::flush; + } + } + + out << std::endl; + + out << "Intermediate line at " + << CGAL::to_double(curve.bound_value_in_interval(0)) + << ": " << curve.arcs_over_interval(0) << " passing arcs" + << std::endl + << std::endl; + for (size_type i = 0; i < curve.number_of_status_lines_with_event(); + i++) { + out << curve.status_line_at_event(i) << std::endl; + out << "Intermediate line at " + << CGAL::to_double(curve.bound_value_in_interval(i+1)) + << ": " << curve.arcs_over_interval(i+1) + << " passing arcs" << std::endl + << std::endl; + } + out << "(Horizontal) asymptotes at +infty: " << std::flush; + size_type no_events = curve.number_of_status_lines_with_event(); + for (size_type i = 0; i < curve.arcs_over_interval(no_events); i++) { + + const Asymptote_y& curr_asym_info_obj + = curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,i); + typename Curve::Algebraic_real_1 curr_asym_info; + bool is_finite = CGAL::assign(curr_asym_info,curr_asym_info_obj); + if(! is_finite) { + // Assignment to prevent compiler warning + CGAL::Arr_parameter_space loc = CGAL::ARR_LEFT_BOUNDARY; + CGAL_assertion_code(bool is_valid = ) + CGAL::assign(loc, curr_asym_info_obj); + CGAL_assertion(is_valid); + if(loc == CGAL::ARR_TOP_BOUNDARY) { + out << "+infty " << std::flush; + } else { + CGAL_assertion(loc == CGAL::ARR_BOTTOM_BOUNDARY); + out << "-infty " << std::flush; + } + } else { // is_finite + out << CGAL::to_double(curr_asym_info) + << " " << std::flush; + } + } + + out << std::endl; + + out << "------------------------------------------------" << std::endl; + break; + } + case ::CGAL::IO::BINARY: + std::cerr << "BINARY format not yet implemented" << std::endl; + break; + default: + // ASCII + out << curve.polynomial_2(); + } + + return out; +} + +//! \brief Reads the objects from stream +template +std::istream& operator>> ( + std::istream& is, + Curve_analysis_2< AlgebraicKernelWithAnalysis_2, Rep_ >& curve) { + + CGAL_precondition(CGAL::is_ascii(is)); + + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + typedef Rep_ Rep; + + typename Curve_analysis_2< Algebraic_kernel_with_analysis_2, Rep >:: + Polynomial_2 f; + + is >> f; + + // TODO is get_static_instance the right way? + curve = Algebraic_kernel_with_analysis_2::get_static_instance(). + construct_curve_2_object()(f); + + return is; +} + + +} //namespace CGAL + + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + + +#endif // ALGEBRAIC_CURVE_2_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h new file mode 100644 index 00000000000..00139c8f9bd --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Curve_pair_analysis_2.h @@ -0,0 +1,2660 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Eric Berberich +// Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_ACK_CURVE_PAIR_ANALYSIS_H +#define CGAL_ACK_CURVE_PAIR_ANALYSIS_H 1 + +#include +#include + +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4290) +#endif + +namespace CGAL { + +namespace internal { + +template +class Distinct_compare { + +public: + + typedef AlgebraicReal_1 Algebraic_real_1; + + typedef ::CGAL::Comparison_result result_type; + typedef Algebraic_real_1 first_argument_type; + typedef Algebraic_real_1 second_argument_type; + + ::CGAL::Comparison_result operator() + (Algebraic_real_1 a,Algebraic_real_1 b) { + return a.compare_distinct(b); + } + +}; + +}// namespace internal + +////////////////////////////////////////////////////////////////////////////// +// Curve_pair_2 + +// Forwards +template < typename AlgebraicKernelWithAnalysis_2 > +class Curve_pair_analysis_2; + +template +std::ostream& operator<< + (std::ostream&,const Curve_pair_analysis_2 + &); + +namespace internal { + +// Internally used enums and structs + +enum Slice_type { + FIRST_CURVE = 0, + SECOND_CURVE = 1, + INTERSECTION = 2, + CANDIDATE = 3 +}; + + +/*! + * An x-event of the curve pair is either a root of a dicriminant of a single + * curve, or a root of the resultant of both curves, or both. + * The \c Event_indices vector stores a triple (fg,ffy,ggy) denoting + * that some event is the fg root of res(f,g,y), + * the ffyth root of disc(f,y) and + * the ggyth root of disc(g,y). + */ +template +struct Event_indices { + + size_type fg; + size_type ffy; + size_type ggy; + Event_indices(size_type fg,size_type ffy, size_type ggy) + : fg(fg), ffy(ffy), ggy(ggy) {} +}; + +// Representation class for curve pairs +template < class AlgebraicKernelWithAnalysis_2 > +struct Curve_pair_analysis_2_rep { + + //! \name public typedefs + //! @{ + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + typedef Curve_pair_analysis_2_rep Self; + + typedef Curve_pair_analysis_2 Handle; + + typedef typename Algebraic_kernel_with_analysis_2::Curve_analysis_2 + Curve_analysis_2; + + typedef typename Curve_analysis_2::size_type size_type; + + typedef typename Curve_analysis_2::Polynomial_2 Polynomial_2; + + typedef typename Curve_analysis_2::Algebraic_real_1 Algebraic_real_1; + + typedef typename Polynomial_2::NT Polynomial_1; + + typedef typename Curve_analysis_2::Bound Bound; + + typedef CGAL::internal::Status_line_CPA_1 Status_line_CPA_1; + + typedef std::pair Slice_element; + + typedef std::vector Slice_info; + + typedef boost::optional Lazy_slice_info; + + typedef boost::optional Lazy_bound; + + typedef CGAL::internal::Event_indices Event_indices; + + struct Intersection_info { + typename Curve_analysis_2::Status_line_1 ev; + size_type index; + size_type mult; + }; + + typedef std::vector > + Intersection_info_container; + + typedef boost::optional + Lazy_intersection_info_container; + + // For lazy evaluation of Status_line_CPA_1s. + typedef boost::optional Lazy_status_line_CPA_1; + + //! @} + + //! \name Constructors + //! @{ + + // DefaultConstructible + Curve_pair_analysis_2_rep() : + c1_(), c2_() { + } + + Curve_pair_analysis_2_rep(Algebraic_kernel_with_analysis_2 *kernel, + Curve_analysis_2 c1, Curve_analysis_2 c2, + CGAL::Degeneracy_strategy strategy) : + _m_kernel(kernel), + c1_(c1), c2_(c2), f(c1.polynomial_2()), g(c2.polynomial_2()), + degeneracy_strategy(strategy) { + } + + //! @} + +private: + + //! \name members + //! @{ + + Algebraic_kernel_with_analysis_2* _m_kernel; + + Curve_analysis_2 c1_; + Curve_analysis_2 c2_; + + Polynomial_2 f; + Polynomial_2 g; + + + mutable boost::optional > subresultants; + + mutable boost::optional > + principal_subresultants; + mutable boost::optional > + coprincipal_subresultants; + + mutable boost::optional resultant; + + mutable boost::optional > resultant_roots; + mutable boost::optional > + event_x_coordinates; + mutable boost::optional > + multiplicities_of_resultant_roots; + + mutable boost::optional > stripe_values; + + mutable std::vector< Lazy_status_line_CPA_1 > event_slices; + + mutable boost::optional > intermediate_values; + + mutable boost::optional< std::vector< Lazy_status_line_CPA_1 > > + intermediate_slices; + + mutable boost::optional > event_indices; + + mutable Lazy_intersection_info_container intersection_info_container; + + typedef typename Curve_analysis_2::Integer Integer; + + CGAL::Degeneracy_strategy degeneracy_strategy; + + mutable CGAL::internal::Shear_controller shear_controller; + + //! @} + + //! \name friends + //! @{ + + friend class Curve_pair_analysis_2; + + //!@} + +}; + +} // namespace internal + +/*! + * A model for AlgebraicKernelWithAnalysis_2::CurvePairAnalysis_2 + * It provides topological-geometric information about the intersection + * points, and the vertical order of arcs of two algebraic plane curves. + * + * The curve pair is passed by two \c Curve_analysis_2 instances. + * It is required that they do not share a component, i.e., the number + * of common points must be finite. Note that overlapping curves are handled + * by \c Algebraic_curve_kernel_2::Construct_curve_pair_2. + * Also for caching reasons, it is recommended to construct curve pairs + * always with this method. + * + * As for the single-curve analysis, the curve pair analysis is implemented + * in a "lazy" fashion. That means, any computation is triggered when + * the result is actually queried by the user. This prevents + * expensive symbolic computations in some cases. + * + * For all algorithmic details of the curve pair analysis, we refer to + * Arno Eigenwillig, Michael Kerber: Exact and Efficient 2D-Arrangements + * of Arbitrary Algebraic Curves. Proceedings of the Nineteenth Annual + * ACM-SIAM Symposium on Discrete Algorithms (SODA 2008), pp. 122-131 + */ +template < typename AlgebraicKernelWithAnalysis_2 > +class Curve_pair_analysis_2 : + public ::CGAL::Handle_with_policy + < CGAL::internal::Curve_pair_analysis_2_rep + < AlgebraicKernelWithAnalysis_2 > > { + + +public: + + //! \name typedefs + //! @{ + + //! The algebraic kernel that uses the curve pair analysis + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + +private: + + //! Representation class + typedef CGAL::internal::Curve_pair_analysis_2_rep + < Algebraic_kernel_with_analysis_2 > Rep; + + //! Base class + typedef ::CGAL::Handle_with_policy< Rep > Base; + +public: + //! The Curve_pair_analysis_2 itself + typedef Curve_pair_analysis_2 Self; + + //! The corresponding Curve_analysis_2 class + typedef typename Rep::Curve_analysis_2 Curve_analysis_2; + + //! Index type + typedef typename Rep::size_type size_type; + + //! Univariate polynomials + typedef typename Rep::Polynomial_1 Polynomial_1; + + //! Bivariate polynomials + typedef typename Rep::Polynomial_2 Polynomial_2; + + //! Type for algebraic numbers (one dimension) + typedef typename Rep::Algebraic_real_1 Algebraic_real_1; + + //! Type for points with algebraic coordinates + typedef typename Algebraic_kernel_with_analysis_2::Algebraic_real_2 + Algebraic_real_2; + + //! Bound type (for rational numbers) + typedef typename Rep::Bound Bound; + +private: + // Optional for boundaries + typedef typename Rep::Lazy_bound Lazy_bound; + + // Object to store information about intersection points + typedef typename Rep::Intersection_info_container + Intersection_info_container; + + // Its lazy version + typedef typename Rep::Lazy_intersection_info_container + Lazy_intersection_info_container; + + // Type for indices of events. + typedef typename Rep::Event_indices Event_indices; + + // Integer type + typedef typename Curve_analysis_2::Integer Integer; + + // Status line of single curve analysis + typedef typename Curve_analysis_2::Status_line_1 Status_line_CA_1; + + // Coefficient type + typedef typename Curve_analysis_2::Coefficient Coefficient; + + // Polynomial traits class + typedef CGAL::Polynomial_traits_d Polynomial_traits_2; + + // Polynomial traits class + typedef CGAL::Polynomial_traits_d Polynomial_traits_1; + +public: + + //! The event slice object type + typedef typename Rep::Status_line_CPA_1 Status_line_CPA_1; + + /*! + * Required by the concept. The name is not used internally + * to distinguish from one curve status_lines syntactically + */ + typedef Status_line_CPA_1 Status_line_1; + +private: + + // Lazy version of status lines + typedef typename Rep::Lazy_status_line_CPA_1 Lazy_status_line_CPA_1; + + // Coercion between Bound and Coefficient type + typedef CGAL::Coercion_traits Coercion; + + // The common supertype + typedef typename Coercion::Type Coercion_type; + + // Polynomials over that supertype + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type Poly_coer_1; + + // Functor to isolate real roots of univariate polynomials + typedef typename Algebraic_kernel_with_analysis_2::Solve_1 Solve_1; + + // Slice info objects + typedef typename Rep::Slice_info Slice_info; + + // Lazy version + typedef typename Rep::Lazy_slice_info Lazy_slice_info; + + //! @} + +private: + + //! \name Internal structs + //! @{ + + struct Curves_at_event_functor { + + typedef size_type argument_type; + typedef CGAL::internal::Slice_type result_type; + + Curves_at_event_functor(const Status_line_CPA_1& status_line) + : status_line(status_line) + {} + + CGAL::internal::Slice_type operator() (size_type i) const { + typedef typename Status_line_CPA_1::size_type + Status_line_size_type; + std::pair pair = + status_line.curves_at_event(i); + CGAL_assertion(pair.first>=0 || pair.second >=0); + if(pair.first==-1) { + return CGAL::internal::SECOND_CURVE; + } + if(pair.second==-1) { + return CGAL::internal::FIRST_CURVE; + } + return CGAL::internal::INTERSECTION; + } + private: + + const Status_line_CPA_1& status_line; + + }; + + typedef boost::transform_iterator > + Status_line_CPA_iterator; + + struct Xval_of_status_line_CA_1 { + typedef Status_line_CA_1 argument_type; + typedef Algebraic_real_1 result_type; + Algebraic_real_1 operator() (const Status_line_CA_1& status_line) + const { + return status_line.x(); + } + }; + + // @} + + //! \name Constructors + //! @{ + +public: + + //! DefaultConstructible + Curve_pair_analysis_2() : + Base(Rep()) { + }; + + //! \brief Copy constructor + Curve_pair_analysis_2(const Self& alg_curve_pair) + : Base(static_cast(alg_curve_pair)) + { + } + + // Assignable + + /*! + * \brief Constructable from two curves + * + * Create a curve pair object for the two curves \c c1 and \c c2, + * given by their curve analysis object. The two curves are checked + * to have no common vertical line component (if they have, an + * exception of type \c CGAL::internal::Non_generic_position_exception + * is thrown), no further computation is performed. + * + * \param strategy If a degenerate situation (e.g., two covertical + * intersection at the same x-coordinate) occurs during the analysis, + * this value controls the strategy to handle it. If set to + * CGAL::EXCEPTION_STRATEGY, an exception of type + * \c CGAL::internal::Non_generic_position_exception is thrown whenever + * such a degeneracy occurs. If set to \c CGAL::SHEAR_STRATEGY, a shear + * transformation is performed, and the sheared curve pair is used + * to handle degenerate situations. Finally, if set to + * CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY, degeneracies at rational + * x-ccordinates are handled directly, and a shear is only applied + * in other situations. The default argument for \c strategy is + * \c CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY. + */ + Curve_pair_analysis_2(Algebraic_kernel_with_analysis_2* kernel, + Curve_analysis_2 c1, + Curve_analysis_2 c2, + CGAL::Degeneracy_strategy strategy + = CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY) + throw(CGAL::internal::Zero_resultant_exception, + CGAL::internal::Non_generic_position_exception) + : Base(Rep(kernel,c1, c2, strategy)) + { + +#if CGAL_ACK_DEBUG_FLAG + CGAL::set_pretty_mode(CGAL_ACK_DEBUG_PRINT); +#endif + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Check content for squarefreeness.." + << std::flush; +#endif + if(CGAL::degree(this->ptr()->c1_.content())>0 && + CGAL::degree(this->ptr()->c2_.content())>0) { + typename Polynomial_traits_1::Gcd_up_to_constant_factor gcd_utcf; + if(CGAL::degree(gcd_utcf + (this->ptr()->c1_.content(), + this->ptr()->c2_.content())) >= 1) { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Common vertical line discovered" + << std::endl; +#endif + throw CGAL::internal::Non_generic_position_exception(); + } else { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + } + } + + } + + //! @} + + +private: + + // Computes the resultant of the defining polynomials wrt \c y + void compute_resultant() const; + + // Computes the subresultant coefficients of the defining polynomials + void compute_subresultants() const; + + /* + * Computes the roots of the resultants (via isolation) and their + * multiplicities + */ + void compute_resultant_roots_with_multiplicities() const; + + /* + * Computes all x-events of the curve pair, + * together with their event indices + */ + void compute_event_x_coordinates_with_event_indices() const; + + /* + * \brief Computes the intermediate x-coordinates and their status lines + * + * In fact, it only fills the data fields with boost::none instances, + * according to the lazy philosophy of the whole class. + */ + void compute_intermediate_values_and_slices() const; + +public: + + Algebraic_kernel_with_analysis_2* kernel() const { + return this->ptr()->_m_kernel; + } + + //! Returns the resultant of the defing polynomials wrt \c y + Polynomial_1 resultant() const { + if(! this->ptr()->resultant) { + compute_resultant(); + } + CGAL_assertion(this->ptr()->resultant); + return this->ptr()->resultant.get(); + } + + std::vector& resultant_roots() const { + if(! this->ptr()->resultant_roots) { + compute_resultant_roots_with_multiplicities(); + } + CGAL_assertion(this->ptr()->resultant_roots); + return this->ptr()->resultant_roots.get(); + } + + Algebraic_real_1& resultant_roots(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast(resultant_roots().size())); + return resultant_roots()[i]; + } + + std::vector& multiplicities_of_resultant_roots() const { + if(! this->ptr()->multiplicities_of_resultant_roots) { + compute_resultant_roots_with_multiplicities(); + } + CGAL_assertion(this->ptr()->multiplicities_of_resultant_roots); + return this->ptr()->multiplicities_of_resultant_roots.get(); + } + + size_type multiplicities_of_resultant_roots(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast + (multiplicities_of_resultant_roots().size())); + return multiplicities_of_resultant_roots()[i]; + } + + std::vector& stripe_values() const { + if(! this->ptr()->stripe_values) { + this->ptr()->stripe_values = std::vector(); + find_intermediate_values + (kernel(), + resultant_roots().begin(), + resultant_roots().end(), + std::back_inserter(this->ptr()->stripe_values.get())); + } + CGAL_assertion(this->ptr()->stripe_values); + return this->ptr()->stripe_values.get(); + } + + std::vector& event_x_coordinates() const { + if(! this->ptr()->event_x_coordinates) { + compute_event_x_coordinates_with_event_indices(); + } + CGAL_assertion(this->ptr()->event_x_coordinates); + return this->ptr()->event_x_coordinates.get(); + } + + std::vector& event_indices() const { + if(! this->ptr()->event_indices) { + compute_event_x_coordinates_with_event_indices(); + } + CGAL_assertion(this->ptr()->event_indices); + return this->ptr()->event_indices.get(); + } + +public: + + /* + * \brief Returns the indices of the ith event value + * + * Returns a Event_indices (fg,ffy,ggy) such that + * the ith event root is the fgth root of the + * resultant of \c f and \c g, the ffyth root of the + * discriminant of \c f, and the ggyth root of the + * discriminant of \c g. + */ + Event_indices event_indices(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast + (event_indices().size())); + return event_indices()[i]; + } + +private: + + std::vector& intermediate_values() const { + if(! this->ptr()->intermediate_values) { + compute_intermediate_values_and_slices(); + } + CGAL_assertion(this->ptr()->intermediate_values); + return this->ptr()->intermediate_values.get(); + } + + std::vector& intermediate_slices() const { + if(! this->ptr()->intermediate_slices) { + compute_intermediate_values_and_slices(); + } + CGAL_assertion(this->ptr()->intermediate_slices); + return this->ptr()->intermediate_slices.get(); + } + + +private: + + std::vector& subresultants() const { + if(! this->ptr()->subresultants) { + compute_subresultants(); + } + CGAL_assertion(this->ptr()->subresultants); + return this->ptr()->subresultants.get(); + } + + Polynomial_2& subresultants(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast(subresultants().size())); + return subresultants()[i]; + } + + std::vector& principal_subresultants() const { + if(! this->ptr()->principal_subresultants) { + compute_subresultants(); + } + CGAL_assertion(this->ptr()->principal_subresultants); + return this->ptr()->principal_subresultants.get(); + } + + Polynomial_1& principal_subresultants(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast + (principal_subresultants().size())); + return principal_subresultants()[i]; + } + + std::vector& coprincipal_subresultants() const { + if(! this->ptr()->coprincipal_subresultants) { + compute_subresultants(); + } + CGAL_assertion(this->ptr()->coprincipal_subresultants); + return this->ptr()->coprincipal_subresultants.get(); + } + + Polynomial_1& coprincipal_subresultants(size_type i) const { + CGAL_assertion(i>=0 && + i < static_cast + (coprincipal_subresultants().size())); + return coprincipal_subresultants()[i]; + } + + + +private: + + /* + * Refines the isolating intervals until they are disjoint + * Returns CGAL::SMALLER, if the y-coordinate defined by (e1,i1) + * is smaller than the y-coordinate (e2,i2), + * and CGAL::GREATER otherwise + * + * If both y-coordinates are equal, this method does not terminate + */ + CGAL::Sign split_compare(Status_line_CA_1& e1, size_type i1, + Status_line_CA_1& e2, size_type i2) const { + while(overlap(e1,i1,e2,i2)) { + if(e1.interval_length(i1)=0; + if(is_resultant_root && + this->ptr()->intersection_info_container) { + return create_event_slice_with_shear(i); + } + try { + Status_line_CPA_1 slice = construct_generic_case(i); + + return slice; + } catch(CGAL::internal::Non_generic_position_exception ex) { + switch(this->ptr()->degeneracy_strategy) { + case(CGAL::EXCEPTION_STRATEGY): { + throw ex; + break; + } + case(CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY): { + if(event_x(i).is_rational()) { + return create_event_slice_at_rational(i); + } + // FALL INTO NEXT CASE + } + case(CGAL::SHEAR_STRATEGY): { + return create_event_slice_with_shear(i); + } + } + + + // NEVER HAPPENS + return Status_line_CPA_1(); + + } + } + +private: + Status_line_CPA_1 create_event_slice_at_rational(size_type i) const { + + Algebraic_real_1& x = event_x(i); + + CGAL_precondition(x.is_rational()); + Bound r = x.rational(); + + typedef typename CGAL::Fraction_traits FT; + + int k = degree_of_local_gcd(event_indices(i).fg,x); + Polynomial_2 sres = subresultants(k); + + Polynomial_1 gcd = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (sres,0,1),r); + std::vector gcd_roots; + kernel()->solve_1_object()(gcd,std::back_inserter(gcd_roots),false); + int m = gcd_roots.size(); + + Slice_info slice_info = construct_slice_info(x); + reduce_number_of_candidates_and_intersections_to + (m, + this->ptr()->c1_.status_line_at_exact_x(x), + this->ptr()->c2_.status_line_at_exact_x(x), + slice_info); + for(typename Slice_info::iterator it=slice_info.begin(); + it!=slice_info.end(); + it++) { + + if(it->first==CGAL::internal::CANDIDATE) { + it->first=CGAL::internal::INTERSECTION; + } + } + + return create_slice_from_slice_info(i,slice_info,true); + } + +private: + + /*! + * TODO doc + */ + Status_line_CPA_1 create_slice_with_multiplicity_zero_or_one(size_type i) + const; + +private: + + // Creates an intermediate slice at a rational value + Status_line_CPA_1 create_intermediate_slice_at(int i) const; + +private: + + // Create a slice with id \c id from the Slice_info object + Status_line_CPA_1 create_slice_from_slice_info(size_type id, + const Slice_info& slice, + bool event_flag) const; + +private: + + // Computes a slice_info object at Algebraic_real_1 \c alpha + Slice_info construct_slice_info(Algebraic_real_1 alpha) const + throw(CGAL::internal::Non_generic_position_exception); + +private: + + Status_line_CPA_1 construct_generic_case(size_type i) const + throw(CGAL::internal::Non_generic_position_exception); + +private: + + bool check_candidate_by_arc_pattern(size_type index, + Status_line_CA_1& e1, + size_type i1, + Status_line_CA_1& e2, + size_type i2) const; +private: + + /* + * TODO update doc + * Checks the point on e1 with index i1, and + * the point on e2 with index i2 really intersect. The \c slice_info + * is updated accordingly: If not intersecting, the corresponding + * points are refined until they can be arranged in the correct order. + * If intersecting, the corresponding Slice_info element is set to + * INTERSECTION. + */ + template + void check_candidate(Status_line_CA_1& e1,size_type i1, + Status_line_CA_1& e2,size_type i2, + size_type k, + Slice_info& slice_info, + InputIterator slice_it, + size_type root_index) const; + +private: + + /* + * Checks intersection with symbolic methods + */ + bool check_candidate_symbolically(Status_line_CA_1& e1,size_type , + Status_line_CA_1& CGAL_precondition_code(e2),size_type , + size_type k) const { + Polynomial_1 p = -coprincipal_subresultants(k-1); + Polynomial_1 q = principal_subresultants(k)*Coefficient(k); + Algebraic_real_1 alpha = e1.x(); + CGAL_assertion(alpha==e2.x()); + if(CGAL::internal::zero_test_bivariate + + (kernel(),alpha,this->ptr()->f,p,q) && + CGAL::internal::zero_test_bivariate + + (kernel(),alpha,this->ptr()->g,p,q)) { + return true; + } + else { + throw CGAL::internal::Non_generic_position_exception(); + } + return false; // never happens + } + +private: + + /* + * Checks whether the isolting intervals for the point on \c e1 with + * index \c index1, and for the point on \c e2 with index \c index2 + * overlap + */ + bool overlap(Status_line_CA_1& e1, + size_type index1, + Status_line_CA_1& e2, + size_type index2) const { + if(e1.lower_bound(index1) > e2.upper_bound(index2)) { + return false; + } + else if(e1.upper_bound(index1) < e2.lower_bound(index2)) { + return false; + } + else { + return true; + } + } + + /* + * For the point \c p on \c e1 with index \c index1, find the + * unique point on \c e2 which might be equal to \c p. If no point + * can be equal, -1 is returned. + */ + size_type find_possible_matching(Status_line_CA_1& e1, + size_type index1, + Status_line_CA_1& e2) const; + + + size_type degree_of_local_gcd(size_type index_of_fg, + Algebraic_real_1 alpha) const { + + if(multiplicities_of_resultant_roots(index_of_fg) == 1) { + return 1; + } else { + size_type k=1; + while(kernel()->is_zero_at_1_object() + (principal_subresultants(k),alpha)) { + k++; + } + return k; + } + } + +public: + + //! Returns curve analysis for the cth curve + Curve_analysis_2 curve_analysis(bool c) const { + return c ? this->ptr()->c2_ : this->ptr()->c1_; + } + + size_type event_of_curve_analysis(size_type i, bool c) const { + Event_indices& ev_ind = event_indices(i); + return c ? ev_ind.ggy : ev_ind.ffy; + } + + size_type event_of_curve_analysis(size_type i, + const Curve_analysis_2& c) const { + CGAL_assertion(c.id()==curve_analysis(false).id() || + c.id()==curve_analysis(true).id()); + Event_indices& ev_ind = event_indices(i); + return (c.id()==curve_analysis(false).id()) ? ev_ind.ffy : ev_ind.ggy; + } + + /*! + * \brief Returns the number of event slices + * + * Precisely, this is the number of points which are either root of + * the resultant of the two curves, or root of discriminant of one + * of the curves + */ + size_type number_of_status_lines_with_event() const { + return static_cast(event_x_coordinates().size()); + } + + //! Returns the x-coordinate of the ith event + Algebraic_real_1& event_x(size_type i) const { + CGAL_assertion(i>=0 && + i(event_x_coordinates().size())); + return event_x_coordinates()[i]; + } + + /*! + * \brief The index of the x-coordinate + * + * For x-value \c x, the index of the suitable slice is computed. For + * event value, the \c event flag is set to true, otherwise to false + * and the slice of the interval to which \c x belongs is returned + */ + void x_to_index(Algebraic_real_1 x, + size_type& idx, bool& event) const { + const std::vector& sl = event_x_coordinates(); + idx = std::lower_bound(sl.begin(), + sl.end(), + x) - sl.begin(); + event = (idx < static_cast(sl.size()) && (sl[idx] == x)); + + } + + + Status_line_CPA_1 status_line_for_x(Algebraic_real_1 x, + CGAL::Sign perturb = CGAL::ZERO) + const { + size_type index; + bool evt; + x_to_index(x,index,evt); + if(evt) { + switch(perturb) { + case(CGAL::ZERO): return status_line_at_event(index); + case(CGAL::NEGATIVE): return status_line_of_interval(index); + case(CGAL::POSITIVE): return status_line_of_interval(index+1); + } + } // else: + return status_line_of_interval(index); + + + } + + + Status_line_CPA_1 status_line_at_exact_x(Algebraic_real_1 x) { + return status_line_for_x(x); + } + + +public: + + //! Returns the Status_line_CPA_1 at the ith event + const Status_line_CPA_1& status_line_at_event(size_type i) const { + if(! this->ptr()->event_slices[i]) { + this->ptr()->event_slices[i] = create_event_slice(i); + } + CGAL_assertion(this->ptr()->event_slices[i]); + return this->ptr()->event_slices[i].get(); + } + + + + //! Returns the Status_line_CPA_1 at the ith interval + const Status_line_CPA_1& status_line_of_interval(size_type i) const { + + if(! intermediate_slices()[i]) { + + intermediate_slices()[i] + = create_intermediate_slice_at(i); + + } + + return intermediate_slices()[i].get(); + } + + //! Returns bound representative value at the ith interval + const Bound bound_value_in_interval(size_type i) const { + + const std::vector& events = event_x_coordinates(); + + if(! intermediate_values()[i]) { + // Create the intermediate x-coordinate first + if(events.size()==0) { + CGAL_assertion(i==0); + intermediate_values()[0]=Bound(0); + } else { + if(i==0) { + intermediate_values()[i] + = bound_left_of(kernel(),events[i]); + } else if(i == static_cast(events.size())) { + intermediate_values()[i] + = bound_right_of(kernel(),events[i-1]); + + } else { + intermediate_values()[i] + = kernel()->bound_between_1_object() + (events[i-1],events[i]); + } + } + } + CGAL_assertion(intermediate_values()[i]); + return intermediate_values()[i].get(); + + } + +private: + + struct Bound_to_coercion_functor { + + typedef Bound argument_type; + typedef Coercion_type result_type; + + result_type operator() (argument_type x) const { + typename CGAL::Coercion_traits::Cast cast; + return cast(x); + } + }; + + struct Coefficient_to_coercion_functor { + + typedef Coefficient argument_type; + typedef Coercion_type result_type; + + result_type operator() (argument_type x) const { + typename CGAL::Coercion_traits::Cast cast; + return cast(x); + } + }; + + + // If a new shear was used, update intersection multiplicities + void merge_new_intersection_info + (const Intersection_info_container& new_info_container) const { + if(! this->ptr()->intersection_info_container) { + // ok, nothing existed, so take the new intersection info + this->ptr()->intersection_info_container + = new_info_container; + return; + } + Intersection_info_container& old_info_container + = *(this->ptr()->intersection_info_container); + size_type n = old_info_container.size(); + CGAL_assertion(n == static_cast + ( new_info_container.size())); + //iterate through the vector and update + // (-1 stands for "multiplicity unknown") + for(size_type i=0;i\ + (new_info_container[i].size())); + for(size_type j=0;jptr()->intersection_info_container) { + Intersection_info_container info_container; + new_shear_for_intersection_info(info_container); + merge_new_intersection_info(info_container); + } + Status_line_CPA_1 slice + = create_event_slice_from_current_intersection_info(i); + + return slice; + } catch(CGAL::internal::Non_generic_position_exception ex) { + // just try the next one + Intersection_info_container info_container; + new_shear_for_intersection_info(info_container); + merge_new_intersection_info(info_container); + } + } + } + + + Status_line_CPA_1 + create_event_slice_from_current_intersection_info (size_type i) + const throw(CGAL::internal::Non_generic_position_exception); + + Bound x_sheared(Bound x, Bound y,Integer sh) const { + return x-sh*y; + } + + void update_intersection_info(Intersection_info_container& + info_container, + Self& sh_pair, + Status_line_CPA_1 slice, + size_type i, + size_type j, + Integer s) const; + + /* + * \brief Reduces the number of possible intersections + * + * At the position given by the event lins \c e1 and \c e2 and the slice + * info object \c slice, the points on the event lines are further refined + * until there are only \c n possible intersection points. The method can + * be interrupted if all possible intersection points are known to have + * a maximal intersection mulipicity smaller \c k, and a + * Non_generic_position_exception is thrown then. + */ + size_type reduce_number_of_candidates_and_intersections_to + (size_type n, + Status_line_CA_1& e1, + Status_line_CA_1& e2, + Slice_info& slice, + size_type k=-1) const; + + // Handle provides + // .id() + // .is_identical + + friend std::ostream& operator<< <> + (std::ostream& out, + const Self& curve_pair); + +}; // end of Curve_pair_analysis_2 + +//! \brief Prints the objects. +template +std::ostream& operator<< + (std::ostream& out, + const Curve_pair_analysis_2& curve_pair) { + typedef Curve_pair_analysis_2 + Curve_pair_analysis_2; + typedef typename Curve_pair_analysis_2::size_type size_type; + typedef typename Curve_pair_analysis_2::Event_indices Event_indices; + typedef typename Curve_pair_analysis_2::Status_line_CPA_1 Slice; + out << "--------------- Analysis results ---------------" << std::endl; + out << "Number of constructed event lines: " + << curve_pair.number_of_status_lines_with_event() + << std::endl; + + out << "Intermediate line: " << std::flush; + Slice slice=curve_pair.status_line_of_interval(0); + + out << slice.number_of_events() << " passing arcs" << std::endl ; + out << "in order: " << std::flush; + for(size_type i=0;i +void Curve_pair_analysis_2::compute_resultant() + const { + +#if CGAL_ACK_RESULTANT_FIRST_STRATEGY +#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD + bool speed_up = true; +#else + bool speed_up = (std::min) + (CGAL::degree(curve_analysis(false).polynomial_2(),1), + CGAL::degree(curve_analysis(true).polynomial_2(),1)) >= + CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD; +#endif +#else + bool speed_up=false; +#endif + if(speed_up) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute the resultant of f and g..." + << std::flush; +#endif + this->ptr()->resultant + = CGAL::resultant(this->ptr()->f,this->ptr()->g); + } else { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute the subres-seq of f and g..." + << std::flush; +#endif + compute_subresultants(); + + this->ptr()->resultant + = this->ptr()->principal_subresultants.get()[0]; + } + + + if(this->ptr()->resultant.get().is_zero()) { + throw CGAL::internal::Zero_resultant_exception + (this->ptr()->f, + this->ptr()->g); + } +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + +} + +//////////////////// compute_resultant_roots_with_multiplicities() + +template +void Curve_pair_analysis_2:: +compute_resultant_roots_with_multiplicities() const { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Isolate the real roots of resultant..." + << std::flush; +#endif + Solve_1 solve_1; + this->ptr()->resultant_roots = std::vector(); + this->ptr()->multiplicities_of_resultant_roots + = std::vector(); + std::vector > res_pairs; + solve_1(resultant(), std::back_inserter(res_pairs)); + + for(int i=0; i < static_cast(res_pairs.size()); i++ ) { + this->ptr()->resultant_roots.get().push_back(res_pairs[i].first); + this->ptr()->multiplicities_of_resultant_roots.get() + .push_back(res_pairs[i].second); + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + +#if CGAL_ACK_DEBUG_FLAG + for(size_type i = 0; + i + (this->ptr()->resultant_roots.get().size()); + i++) { + CGAL_ACK_DEBUG_PRINT + << "Root at " + << CGAL::to_double(this->ptr()->resultant_roots.get()[i]) + << " with multiplicity " + << this->ptr()->multiplicities_of_resultant_roots.get()[i] + << std::endl; + } +#endif + +} + +//////////////////// compute_event_x_coordinates_with_event_indices + +template +void Curve_pair_analysis_2:: +compute_event_x_coordinates_with_event_indices() const { + + Xval_of_status_line_CA_1 xval; + const Curve_analysis_2& c1=this->ptr()->c1_, c2=this->ptr()->c2_; + + std::vector one_curve_events; + + std::vector one_curve_events_type; + + typename CGAL::Real_embeddable_traits::Compare compare; + + CGAL::internal::set_union_with_source + (::boost::make_transform_iterator(c1.event_begin(),xval), + ::boost::make_transform_iterator(c1.event_end(),xval), + ::boost::make_transform_iterator(c2.event_begin(),xval), + ::boost::make_transform_iterator(c2.event_end(),xval), + std::back_inserter(one_curve_events), + std::back_inserter(one_curve_events_type), + compare); + + this->ptr()->event_x_coordinates = std::vector(); + std::vector events_type; + CGAL::internal::set_union_with_source + (one_curve_events.begin(), + one_curve_events.end(), + resultant_roots().begin(), + resultant_roots().end(), + std::back_inserter(this->ptr()->event_x_coordinates.get()), + std::back_inserter(events_type), + compare); + std::vector& events + = this->ptr()->event_x_coordinates.get(); + + typename std::vector::iterator one_curve_it + =one_curve_events_type.begin(); + size_type inter_count=0, f_count=0,g_count=0; + this->ptr()->event_indices = std::vector(); + std::vector& event_indices + = this->ptr()->event_indices.get(); + for(size_type i=0;i(events.size());i++) { +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << CGAL::to_double(events[i]) << std::flush; + #endif +*/ + switch(events_type[i]) { + case(CGAL::internal::ROOT_OF_FIRST_SET): { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << " one curve event" << std::endl; +#endif +*/ + this->ptr()->event_slices.push_back(Lazy_status_line_CPA_1()); + switch(*(one_curve_it++)) { + case(CGAL::internal::ROOT_OF_FIRST_SET): { + event_indices.push_back(Event_indices(-1,f_count,-1)); + f_count++; + break; + } + case(CGAL::internal::ROOT_OF_SECOND_SET): { + event_indices.push_back(Event_indices(-1,-1,g_count)); + g_count++; + break; + } + case(CGAL::internal::ROOT_OF_BOTH_SETS): { + event_indices.push_back(Event_indices(-1,f_count,g_count)); + f_count++; + g_count++; + break; + } + } + break; + } + case(CGAL::internal::ROOT_OF_SECOND_SET): { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << " two curve event" << std::endl; +#endif +*/ + this->ptr()-> + event_slices.push_back(Lazy_status_line_CPA_1()); + + event_indices.push_back + (Event_indices(inter_count,-1,-1)); + inter_count++; + break; + } + case(CGAL::internal::ROOT_OF_BOTH_SETS): { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << " one and two curve event" + << std::endl; +#endif +*/ + this->ptr()->event_slices.push_back(Lazy_status_line_CPA_1()); + + + switch(*(one_curve_it++)) { + case(CGAL::internal::ROOT_OF_FIRST_SET): { + event_indices.push_back + (Event_indices(inter_count,f_count,-1)); + f_count++; + break; + } + case(CGAL::internal::ROOT_OF_SECOND_SET): { + event_indices.push_back + (Event_indices(inter_count,-1,g_count)); + g_count++; + break; + } + case(CGAL::internal::ROOT_OF_BOTH_SETS): { + event_indices.push_back + (Event_indices(inter_count,f_count,g_count)); + f_count++; + g_count++; + break; + } + } + inter_count++; + break; + } + } + } + CGAL_assertion(inter_count + == static_cast + (resultant_roots().size())); + CGAL_assertion(one_curve_it==one_curve_events_type.end()); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + +} + +//////////////////// compute_intermediate_values_and_slices() + +template +void Curve_pair_analysis_2:: +compute_intermediate_values_and_slices() const { + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Prepare intermediate slices.." << std::flush; +#endif + this->ptr()->intermediate_values=std::vector(); + this->ptr()->intermediate_slices=std::vector(); + + for(size_type i=0; + i<=static_cast(event_x_coordinates().size()); + i++) { + this->ptr()->intermediate_values.get().push_back(Lazy_bound()); + this->ptr()->intermediate_slices.get().push_back + (Lazy_status_line_CPA_1()); + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif +} + +//////////////////// compute_subresultants + +template +void Curve_pair_analysis_2:: +compute_subresultants() const { + typedef std::vector Polynomial_container; + this->ptr()->principal_subresultants = Polynomial_container(); + this->ptr()->coprincipal_subresultants = Polynomial_container(); + const Polynomial_2& f = this->ptr()->f, g=this->ptr()->g; + this->ptr()->subresultants = std::vector(); + if(CGAL::degree(f,1)ptr()->subresultants.get())); +#else + typename CGAL::Polynomial_traits_d + ::Polynomial_subresultants() + (g,f,std::back_inserter(this->ptr()->subresultants.get())); +#endif + } else { +#if CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS + CGAL::internal::bezout_polynomial_subresultants + (f,g,std::back_inserter(this->ptr()->subresultants.get())); +#else + typename CGAL::Polynomial_traits_d + ::Polynomial_subresultants() + (f,g,std::back_inserter(this->ptr()->subresultants.get())); +#endif + } + + std::vector& subresultants + = this->ptr()->subresultants.get(); + + size_type n = static_cast(subresultants.size()); + + for(size_type i=0;iptr()->principal_subresultants-> + push_back(Polynomial_1(0)); + } + else { + this->ptr()->principal_subresultants-> + push_back(subresultants[i][i]); + } + } + for(size_type i=1;iptr()->coprincipal_subresultants-> + push_back(Polynomial_1(0)); + } + else { + this->ptr()->coprincipal_subresultants-> + push_back(subresultants[i][i-1]); + } + } + // This must be corrected, if f and g have same degree: + if(CGAL::degree(f,1) == CGAL::degree(g,1)) { + if(n>=1) { + this->ptr()->principal_subresultants.get()[n-1] + = Polynomial_1(CGAL::leading_coefficient(g)); + } + if(n>=2) { + this->ptr()->coprincipal_subresultants.get()[n-2] + = Polynomial_1(g[CGAL::degree(g,1)-1]); + } + } + +} + +//////////////////// create_slice_with_multiplicity_zero_or_one + +template +typename Curve_pair_analysis_2 + ::Status_line_CPA_1 +Curve_pair_analysis_2:: +create_slice_with_multiplicity_zero_or_one(size_type i) const { + + const std::vector& events + = event_x_coordinates(); + Algebraic_real_1 alpha = events[i]; + const Curve_analysis_2& c1=curve_analysis(false), c2=curve_analysis(true); + size_type i1,i2; + bool flag1,flag2; + c1.x_to_index(alpha,i1,flag1); + c2.x_to_index(alpha,i2,flag2); + + bool exactly_at_alpha_1 = flag1, exactly_at_alpha_2 = flag2; + Status_line_CA_1 e1=flag1 ? c1.status_line_at_event(i1) + : c1.status_line_of_interval(i1); + Status_line_CA_1 e2=flag2 ? c2.status_line_at_event(i2) + : c2.status_line_of_interval(i2); + + Status_line_CPA_1 left_slice = this->status_line_of_interval(i), + right_slice = this->status_line_of_interval(i+1); + + Status_line_CPA_iterator left_it + = ::boost::make_transform_iterator + (::boost::counting_iterator(0), + Curves_at_event_functor(left_slice)); + Status_line_CPA_iterator right_it + = ::boost::make_transform_iterator + (::boost::counting_iterator(0), + Curves_at_event_functor(right_slice)); + + Status_line_CPA_iterator left_end + = ::boost::make_transform_iterator + (::boost::counting_iterator + (left_slice.number_of_events()), + Curves_at_event_functor(left_slice)); + Status_line_CPA_iterator right_end + = ::boost::make_transform_iterator + (::boost::counting_iterator + (right_slice.number_of_events()), + Curves_at_event_functor(right_slice)); + + // Take out asymptotes + size_type asym_lm_1 + = e1.number_of_branches_approaching_minus_infinity().first; + size_type asym_rm_1 + = e1.number_of_branches_approaching_minus_infinity().second; + size_type asym_lp_1 + = e1.number_of_branches_approaching_plus_infinity().first; + size_type asym_rp_1 + = e1.number_of_branches_approaching_plus_infinity().second; + size_type asym_lm_2 + = e2.number_of_branches_approaching_minus_infinity().first; + size_type asym_rm_2 + = e2.number_of_branches_approaching_minus_infinity().second; + size_type asym_lp_2 + = e2.number_of_branches_approaching_plus_infinity().first; + size_type asym_rp_2 + = e2.number_of_branches_approaching_plus_infinity().second; + + while(asym_lm_1 != 0 || asym_lm_2 != 0) { + CGAL_assertion(*left_it != CGAL::internal::INTERSECTION); + if(*left_it == CGAL::internal::FIRST_CURVE) { + CGAL_assertion(asym_lm_1!=0); + asym_lm_1--; + } + if(*left_it == CGAL::internal::SECOND_CURVE) { + CGAL_assertion(asym_lm_2!=0); + asym_lm_2--; + } + left_it++; + } + while(asym_rm_1 != 0 || asym_rm_2 != 0) { + if(*right_it == CGAL::internal::FIRST_CURVE) { + CGAL_assertion(asym_rm_1!=0); + asym_rm_1--; + } + if(*right_it == CGAL::internal::SECOND_CURVE) { + CGAL_assertion(asym_rm_2!=0); + asym_rm_2--; + } + right_it++; + } + while(asym_lp_1 != 0 || asym_lp_2 != 0) { + left_end--; + if(*left_end == CGAL::internal::FIRST_CURVE) { + CGAL_assertion(asym_lp_1!=0); + asym_lp_1--; + } + if(*left_end == CGAL::internal::SECOND_CURVE) { + CGAL_assertion(asym_lp_2!=0); + asym_lp_2--; + } + } + while(asym_rp_1 != 0 || asym_rp_2 != 0) { + right_end--; + if(*right_end == CGAL::internal::FIRST_CURVE) { + CGAL_assertion(asym_rp_1!=0); + asym_rp_1--; + } + if(*right_end == CGAL::internal::SECOND_CURVE) { + CGAL_assertion(asym_rp_2!=0); + asym_rp_2--; + } + } + // Now, the iterator ranges [left_it,left_end) + // and [right_it,right_end) give the arcs really + // going into the event line + + Slice_info slice_info; + CGAL::internal::Slice_type curr_lowest_arc; + size_type curr_multiplicity; + + size_type event_index_1=0, event_index_2=0; + + while(event_index_1 != e1.number_of_events() || + event_index_2 != e2.number_of_events()) { + + CGAL_assertion(event_index_1 != e1.number_of_events() || + event_index_2 != e2.number_of_events()); + if(event_index_1==e1.number_of_events()) { + curr_lowest_arc=CGAL::internal::SECOND_CURVE; + } + else if(event_index_2==e2.number_of_events()) { + curr_lowest_arc=CGAL::internal::FIRST_CURVE; + } + else if((e1.number_of_incident_branches(event_index_1).first>0 && + e2.number_of_incident_branches(event_index_2).first>0)) { + // The next arc on the left must come as next: + curr_lowest_arc=*left_it; + } + else if((e1.number_of_incident_branches(event_index_1).second>0 && + e2.number_of_incident_branches(event_index_2).second>0)) { + // The next arc on the right must come as next: + curr_lowest_arc=*right_it; + } + else { + // We cannot decide it from the arcs, so we have to compare + // isolating intervals + if(! exactly_at_alpha_1) { + e1 = c1.status_line_at_exact_x(alpha); + CGAL_assertion(e1.number_of_events()>event_index_1); + } + if(! exactly_at_alpha_2) { + e2 = c2.status_line_at_exact_x(alpha); + CGAL_assertion(e2.number_of_events()>event_index_2); + } + CGAL::Sign e1_smaller + = split_compare(e1,event_index_1,e2,event_index_2); + curr_lowest_arc + = (e1_smaller==CGAL::SMALLER) + ? CGAL::internal::FIRST_CURVE : CGAL::internal::SECOND_CURVE; + } + + curr_multiplicity = -1; + + // Move the iterators + size_type arcs_of_other_curve_left=0, arcs_of_other_curve_right=0; + if(curr_lowest_arc==CGAL::internal::FIRST_CURVE) { + size_type j=0; + while(j0) { + // Intersection! Iterate over the remaining arcs + // on both sides belonging to this intersection + for(size_type j=arcs_of_other_curve_left; + j0) { + // Intersection! Iterate over the remaining arcs + // on both sides belonging to this intersection + for(size_type j=arcs_of_other_curve_left; + j +typename Curve_pair_analysis_2 + ::Status_line_CPA_1 +Curve_pair_analysis_2:: +create_intermediate_slice_at(int i) const { + + Bound r = bound_value_in_interval(i); + + std::vector p1_roots,p2_roots; + + this->ptr()->c1_.get_roots_at_rational(r,std::back_inserter(p1_roots)); + this->ptr()->c2_.get_roots_at_rational(r,std::back_inserter(p2_roots)); + + size_type number_of_roots + = static_cast(p1_roots.size() + p2_roots.size()); + std::vector p12_roots; + p12_roots.reserve(number_of_roots); + std::vector p12_order; + p12_order.reserve(number_of_roots); + + CGAL::internal::Distinct_compare distinct_compare; + set_union_with_source(p1_roots.begin(), + p1_roots.end(), + p2_roots.begin(), + p2_roots.end(), + std::back_inserter(p12_roots), + std::back_inserter(p12_order), + distinct_compare); + + Slice_info slice_info; + + for(typename std::vector::const_iterator + it = p12_order.begin(); + it!=p12_order.end(); + it++) { + switch(*it){ + case(CGAL::internal::ROOT_OF_FIRST_SET): { + slice_info.push_back + (std::make_pair(CGAL::internal::FIRST_CURVE,-1)); + break; + } + case(CGAL::internal::ROOT_OF_SECOND_SET): { + slice_info.push_back + (std::make_pair(CGAL::internal::SECOND_CURVE,-1)); + break; + } + case(CGAL::internal::ROOT_OF_BOTH_SETS): { + CGAL_assertion(false); + break; + } + } + } + + Status_line_CPA_1 new_slice + = create_slice_from_slice_info(i,slice_info,false); + + return new_slice; +} + +//////////////////// create_slice_from_slice_info + +template +typename Curve_pair_analysis_2 + ::Status_line_CPA_1 +Curve_pair_analysis_2:: +create_slice_from_slice_info(size_type id, + const Slice_info& slice, + bool event_flag) const { + typedef typename Status_line_CPA_1::Arc_pair Arc_pair; + typedef typename Status_line_CPA_1::Arc_container Arc_container; + typedef typename Status_line_CPA_1::Int_container Int_container; + Arc_container arc_container; + Int_container int_container; + + for(typename Slice_info::const_iterator it = slice.begin(); + it!=slice.end(); + it++) { + CGAL_assertion(it->first != CGAL::internal::CANDIDATE); + switch(it->first) { + case(CGAL::internal::FIRST_CURVE): { + if(event_flag) { + arc_container.push_back(std::make_pair(0,it->second)); + } else { + int_container.push_back(0); + } + break; + } + case(CGAL::internal::SECOND_CURVE): { + if(event_flag) { + arc_container.push_back(std::make_pair(1,it->second)); + } else { + int_container.push_back(1); + } + break; + } + case(CGAL::internal::INTERSECTION): { + CGAL_assertion(event_flag); + arc_container.push_back(std::make_pair(2,it->second)); + break; + } + case(CGAL::internal::CANDIDATE): { + CGAL_assertion(false); + break; + } + } + } + + return event_flag + ? Status_line_CPA_1(id,arc_container,*this) + : Status_line_CPA_1(id,int_container,*this); +} + +//////////////////// construct_slice_info + +template +typename Curve_pair_analysis_2::Slice_info +Curve_pair_analysis_2:: +construct_slice_info(Algebraic_real_1 alpha) const + throw(CGAL::internal::Non_generic_position_exception) { + +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Consider alpha=" << CGAL::to_double(alpha) + << std::endl; + #endif +*/ + + Status_line_CA_1 e1 = this->ptr()->c1_.status_line_at_exact_x(alpha); + + Status_line_CA_1 e2 = this->ptr()->c2_.status_line_at_exact_x(alpha); + + std::vector > matchings; + for(size_type i=0;i >::const_iterator + match = matchings.begin(); + Slice_info slice_info; + while(i1first && + i2==match->second) { + slice_info.push_back(std::make_pair(CGAL::internal::CANDIDATE,1)); + i1++; + i2++; + match++; + continue; + } + CGAL_assertion(!overlap(e1,i1,e2,i2)); + if(e1.lower_bound(i1) < e2.lower_bound(i2)) { + slice_info.push_back + (std::make_pair(CGAL::internal::FIRST_CURVE,-1)); + i1++; + continue; + } else { + slice_info.push_back + (std::make_pair(CGAL::internal::SECOND_CURVE,-1)); + i2++; + continue; + } + } + CGAL_assertion(match==matchings.end()); + return slice_info; +} + +//////////////////// construct_generic_case + +template +typename Curve_pair_analysis_2 + ::Status_line_CPA_1 +Curve_pair_analysis_2:: +construct_generic_case(size_type i) const + throw(CGAL::internal::Non_generic_position_exception) { + + Algebraic_real_1 alpha = event_x(i); + + Slice_info slice_info; + + size_type index_of_fg = event_indices(i).fg; + size_type index_of_ffy =event_indices(i).ffy; + size_type index_of_ggy =event_indices(i).ggy; + if(index_of_fg>=0) { + if(kernel()->is_zero_at_1_object() + (CGAL::leading_coefficient + (this->ptr()->c1_.polynomial_2()),alpha) + || + kernel()->is_zero_at_1_object() + (CGAL::leading_coefficient + (this->ptr()->c2_.polynomial_2()),alpha)) { + throw CGAL::internal::Non_generic_position_exception(); + } + size_type k = -1; // not yet computed + if(index_of_ffy==-1 && index_of_ggy==-1) { + // this means, we need the multiplicity of the intersections + if(kernel()->is_zero_at_1_object() + (principal_subresultants(1),alpha)) { + // multiplicity cannot be determined, throw exception + throw CGAL::internal::Non_generic_position_exception(); + } else { + k=1; + } + } else { + k = degree_of_local_gcd(index_of_fg,alpha); + } + Status_line_CA_1 e1 + = this->ptr()->c1_.status_line_at_exact_x(alpha); + Status_line_CA_1 e2 + = this->ptr()->c2_.status_line_at_exact_x(alpha); + slice_info = construct_slice_info(alpha); + size_type no_candidates= + reduce_number_of_candidates_and_intersections_to + (1,e1,e2,slice_info,k); + CGAL_assertion(no_candidates==0 || no_candidates==1); + if(no_candidates==1) { + typename Slice_info::iterator slice_it + = slice_info.begin(); + size_type i1=0,i2=0; + while(slice_it->first!=CGAL::internal::CANDIDATE) { + if(slice_it->first==CGAL::internal::FIRST_CURVE) { + i1++; + } + if(slice_it->first==CGAL::internal::SECOND_CURVE) { + i2++; + } + if(slice_it->first==CGAL::internal::INTERSECTION) { + i1++; + i2++; + } + slice_it++; + } + check_candidate(e1,i1,e2,i2,k, + slice_info, + slice_it,i); + } + } else { + Status_line_CA_1 e1 + = this->ptr()->c1_.status_line_at_exact_x(alpha); + Status_line_CA_1 e2 + = this->ptr()->c2_.status_line_at_exact_x(alpha); + slice_info = construct_slice_info(alpha); + reduce_number_of_candidates_and_intersections_to + (0,e1,e2,slice_info,0); + } + return create_slice_from_slice_info(i,slice_info,true); +} + +//////////////////// check_candidate_by_arc_pattern + +template + +bool Curve_pair_analysis_2:: +check_candidate_by_arc_pattern(size_type index, + Status_line_CA_1& e1, + size_type i1, + Status_line_CA_1& e2, + size_type i2) const { + + Status_line_CPA_1 left_slice = status_line_of_interval(index), + right_slice = status_line_of_interval(index+1); + size_type left_index=0,right_index=0; + for(size_type i=0;i=2) { + return true; + } + } + } + } + + Curves_at_event_functor right_functor(right_slice); + + if(right_index < right_slice.number_of_events()) { + curr = right_functor(right_index); + number_of_changes=0; + for(size_type i=1;i=2) { + return true; + } + } + } + } + + return false; +} + +//////////////////// check_candidate + +template +template +void Curve_pair_analysis_2:: +check_candidate(Status_line_CA_1& e1,size_type i1, + Status_line_CA_1& e2,size_type i2, + size_type k, + Slice_info& slice_info, + InputIterator slice_it, + size_type root_index) const { + + Algebraic_real_1 xval = e1.x(); + CGAL_assertion(xval==e2.x()); + bool is_intersection=false; + size_type index_in_fg = event_indices(root_index).fg; + size_type mult_of_resultant + = multiplicities_of_resultant_roots(index_in_fg); + + if(k%2==1 || mult_of_resultant%2==1) { + is_intersection=true; + } else { + if(check_candidate_by_arc_pattern(root_index,e1,i1,e2,i2)) { + is_intersection=true; + } else { + is_intersection=check_candidate_symbolically(e1,i1,e2,i2,k); + } + } + if(is_intersection) { + slice_it=slice_info.erase(slice_it); + size_type mult_of_intersection; + if(k==1) { + mult_of_intersection = mult_of_resultant; + } else { + mult_of_intersection = -1; + } + slice_info.insert(slice_it, + std::make_pair(CGAL::internal::INTERSECTION, + mult_of_intersection)); + } + else { + CGAL::Sign e1_smaller=split_compare(e1,i1,e2,i2); + + slice_it=slice_info.erase(slice_it); + if(e1_smaller==CGAL::SMALLER) { + slice_it = slice_info.insert + (slice_it,std::make_pair(CGAL::internal::FIRST_CURVE,-1)); + slice_it++; + slice_it = slice_info.insert + (slice_it,std::make_pair(CGAL::internal::SECOND_CURVE,-1)); + } else { + slice_it = slice_info.insert + (slice_it,std::make_pair(CGAL::internal::SECOND_CURVE,-1)); + slice_it++; + slice_it = slice_info.insert + (slice_it,std::make_pair(CGAL::internal::FIRST_CURVE,-1)); + } + } +} + +//////////////////// find_possible_matching + +template +typename Curve_pair_analysis_2::size_type +Curve_pair_analysis_2:: +find_possible_matching(Status_line_CA_1& e1, + size_type index1, + Status_line_CA_1& e2) const { + + std::vector possible_overlaps; + for(size_type i=0;i1) { + if(possible_overlaps.size()==2) { + // Prevent that both intervals touch in a bound + while(overlap(e2,possible_overlaps[0], + e2,possible_overlaps[1])) { + e2.refine(possible_overlaps[0]); + e2.refine(possible_overlaps[1]); + } + } + e1.refine(index1); + + typename std::vector::iterator it + = possible_overlaps.begin(); + while(it!=possible_overlaps.end()) { + if(!overlap(e1,index1,e2,*it)) { + it=possible_overlaps.erase(it); + } + else { + it++; + } + } + } + if(possible_overlaps.size()==0) { + return -1; + } + else { + return possible_overlaps[0]; + } +} + + +//////////////////// new_shear_for_intersection_info + +template +void Curve_pair_analysis_2:: +new_shear_for_intersection_info(Intersection_info_container& info_container) + const { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Use shear for intersections.." << std::endl; +#endif + bool good_direction_found=false; + Integer s; + + while(! good_direction_found) { + try { + info_container.clear(); + info_container.resize(resultant_roots().size()); + s = this->ptr()->shear_controller.get_shear_factor(); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Try shear factor " << s << std::endl; + CGAL_ACK_DEBUG_PRINT + << ">>>>>>>>>>> Transform first curve" << std::endl; +#endif + + Curve_analysis_2 sh1 + = this->ptr()->c1_.shear_primitive_part(s); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT + << "<<<<<<<<<<< End of transform first curve" << std::endl; + CGAL_ACK_DEBUG_PRINT << ">>>>>>>>>>> Transform second curve" + << std::endl; +#endif + Curve_analysis_2 sh2 = this->ptr()->c2_.shear_primitive_part(s); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT + << "<<<<<<<<<<< End of transform second curve" + << std::endl; +#endif + Self sh_pair(kernel(),sh1,sh2,CGAL::EXCEPTION_STRATEGY); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Shear back intersection points..." + << std::flush; +#endif + for(size_type i=0; + i + (sh_pair.event_x_coordinates().size()); + i++) { + if(sh_pair.event_indices(i).fg==-1) { + continue; + } + Status_line_CPA_1 slice + = sh_pair.status_line_at_event(i); + Curves_at_event_functor functor(slice); + for(size_type j=0;jupdate_intersection_info(info_container, + sh_pair, + slice, + i,j,s); + } + } + } + good_direction_found=true; + } + catch(CGAL::internal::Non_generic_position_exception ex) { + this->ptr()->shear_controller.report_failure(s); + } + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + return; +} + +//////////////////// create_event_slice_from_current_intersection_info + +template +typename Curve_pair_analysis_2 + ::Status_line_CPA_1 +Curve_pair_analysis_2:: +create_event_slice_from_current_intersection_info (size_type i) + const throw(CGAL::internal::Non_generic_position_exception){ +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Reduce the candidates.." << std::flush; +#endif + Event_indices ev_ind = event_indices(i); + size_type index_of_fg = ev_ind.fg; + Intersection_info_container& intersection_info_container + = *(this->ptr()->intersection_info_container); + Algebraic_real_1 alpha = event_x(i); + CGAL_assertion(index_of_fg < + static_cast + (intersection_info_container.size())); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << i << "th slice has " + << intersection_info_container[index_of_fg].size() + << " intersections" << std::endl; +#endif + Status_line_CA_1 e1=this->ptr()->c1_. + status_line_at_exact_x(resultant_roots(index_of_fg)), + e2=this->ptr()->c2_. + status_line_at_exact_x(resultant_roots(index_of_fg)); + Slice_info slice=construct_slice_info(alpha); + CGAL_assertion_code(size_type no_intersections=) + reduce_number_of_candidates_and_intersections_to + (static_cast + (intersection_info_container[index_of_fg].size()), + e1, + e2, + slice, + -1); + CGAL_assertion(no_intersections==static_cast + (intersection_info_container[index_of_fg].size())); + typename std::vector::iterator + inter_info_it + = intersection_info_container[index_of_fg].begin(); + for(size_type j=0;j(slice.size());j++) { + if(slice[j].first==CGAL::internal::INTERSECTION) { + inter_info_it++; + } + if(slice[j].first==CGAL::internal::CANDIDATE) { + slice[j].first=CGAL::internal::INTERSECTION; + if(ev_ind.ffy==-1 && ev_ind.ggy==-1 && inter_info_it->mult==-1) { + // Multiplicity unknown for case where we need it + throw CGAL::internal::Non_generic_position_exception(); + } + slice[j].second=inter_info_it->mult; + inter_info_it++; + } + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + return create_slice_from_slice_info(i,slice,true); + +} + +//////////////////// update_intersection_info + +template +void Curve_pair_analysis_2:: +update_intersection_info(Intersection_info_container& + info_container, + Self& sh_pair, + Status_line_CPA_1 slice, + size_type i, + size_type j, + Integer s) const { + typedef typename Rep::Intersection_info Intersection_info; + const Algebraic_real_1& xval = sh_pair.event_x(i); + CGAL_assertion(Curves_at_event_functor(slice)(j) + ==CGAL::internal::INTERSECTION); + Status_line_CA_1 ev = sh_pair.ptr()->c1_.status_line_at_exact_x(xval); + // x_coordinate is given by xval + // y_coordinate by ev[index] + Intersection_info intersection_info; + intersection_info.ev=ev; + int index = slice.curves_at_event(j).first; + intersection_info.index=index; + intersection_info.mult=slice.multiplicity_of_intersection(j); + // Find the right position to insert the object + // first the "x-coordiante" + size_type left_index = -1, + right_index = static_cast(stripe_values().size()-1); + Algebraic_real_1 xv = ev.x(); + Bound lx = xv.low(), rx=xv.high(), + x_iv_size = rx-lx; + Bound ly = ev.lower_bound(index), + ry = ev.upper_bound(index);; + while(left_index < right_index) { + if(x_iv_size > ry-ly) { + xv.refine(); + lx = xv.low(); + rx=xv.high(); + x_iv_size=rx-lx; + continue; + } + ev.refine(index); + ly = ev.lower_bound(index); + ry = ev.upper_bound(index); + Bound left=(s<0) ? x_sheared(lx,ry,-s): x_sheared(lx,ly,-s); + Bound right = (s<0) ? x_sheared(rx,ly,-s) : x_sheared(rx,ry,-s); + CGAL_assertion(left Intersection_info_vector; + Intersection_info_vector& info_vec + = info_container[left_index]; + typename Intersection_info_vector::iterator info_it=info_vec.begin(); + while(info_it!=info_vec.end()) { + Status_line_CA_1& comp_ev=info_it->ev; + size_type comp_index = info_it->index; + CGAL::Sign index_smaller + = split_compare(ev,index,comp_ev,comp_index); + if(index_smaller==CGAL::LARGER) { + info_it++; + } else { + break; + } + } + info_vec.insert(info_it,intersection_info); +} + +//////////////////// reduce_number_of_candidates_and_intersections_to + +template +typename Curve_pair_analysis_2::size_type +Curve_pair_analysis_2:: +reduce_number_of_candidates_and_intersections_to(size_type n, + Status_line_CA_1& e1, + Status_line_CA_1& e2, + Slice_info& slice, + size_type k) const { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Reduce: " << n << " " + << CGAL::to_double(e1.x()) << " " << k + << std::endl; +#endif +*/ + size_type number_of_intersections=0; + size_type number_of_candidates=0; + for(size_type i=0;i(slice.size());i++) { + if(slice[i].first==CGAL::internal::CANDIDATE) { + number_of_candidates++; + } + if(slice[i].first==CGAL::internal::INTERSECTION) { + number_of_intersections++; + } + } + CGAL_assertion(number_of_intersections<=n); + + typename Slice_info::iterator slice_it=slice.begin(); + size_type i1=0,i2=0; + size_type max_candidate_mult=0; + while(nfirst) { + case(CGAL::internal::FIRST_CURVE): { + i1++; + break; + } + case(CGAL::internal::SECOND_CURVE): { + i2++; + break; + } + case(CGAL::internal::CANDIDATE): { + if(e1.interval_length(i1)min_m + ? max_candidate_mult : min_m; + } + i1++; + i2++; + break; + } + case(CGAL::internal::INTERSECTION): { + i1++; + i2++; + break; + } + } + slice_it++; + } + return number_of_intersections+number_of_candidates; +} + +} //namespace CGAL + + +#if defined(BOOST_MSVC) +# pragma warning(pop) +#endif + + +#endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Descartes.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Descartes.h new file mode 100644 index 00000000000..efe2e3cfbc3 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Descartes.h @@ -0,0 +1,474 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file NiX/Descartes.h + \brief Defines class NiX::Descartes. + + Isolate real roots of polynomials. + + This file provides a class to isolate real roots of polynomials, + using the algorithm based on the method of Descartes. + + The polynomial has to be a univariat polynomial over any number + type which is contained in the real numbers. + +*/ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H +#define CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H + +#include +#include + +#include +#include + +#define POLYNOMIAL_REBIND( coeff ) \ + typename CGAL::Polynomial_traits_d::template \ + Rebind::Other::Type + + +namespace CGAL { + +namespace internal { + +/*! \ingroup NiX_Algebraic_real + * \brief A model of concept RealRootIsolator. + */ +template +class Descartes { + typedef CGAL::Fraction_traits FT_poly; + typedef Fraction_traits FT_rat; +public: + //! First template parameter + typedef Polynomial_ Polynomial; + //! Second template parameter + typedef Rational_ Rational; + //! Bound type of the isolating intervals + typedef Rational_ Bound; + // Integer or Numerator/Denominator type of bound. + typedef typename CGAL::Fraction_traits::Numerator_type Integer; +private: + typedef typename Polynomial::NT Coeff; + typedef Integer IT; + + Polynomial poly_; + int number_of_real_roots_; + IT* numerator; + IT* denominator_exponent; + bool* is_exact; + IT LEFT,SCALE,DENOM; + bool is_strong_; + int k; + bool interval_given; + +public: + /*! \brief Constructor from univariate square free polynomial. + + The RealRootIsolator provides isolating intervals for the real + roots of the polynomial. + \pre the polynomial is square free + */ + Descartes(const Polynomial& P = Polynomial(Coeff(0)), + bool is_strong = false, + int kk = 2) + : poly_(P) , + is_strong_(is_strong), + k(kk), + interval_given(false) { + + numerator = new IT[CGAL::degree(P)]; + denominator_exponent = new IT[CGAL::degree(P)]; + is_exact = new bool[CGAL::degree(P)]; + number_of_real_roots_ = 0; + if(CGAL::degree(P) == 0) + { + if(P.is_zero()) number_of_real_roots_ = -1; + return; + } + + intern_decompose(poly_,typename FT_poly::Is_fraction()); + } + + // constructor for coefficient types \c Coeff with given interval + // (experimental) + Descartes(const Polynomial& P, + const Rational& left, + const Rational& right, + bool is_strong = false, + int kk = 2) + : poly_(P) , + is_strong_(is_strong), + k(kk), + interval_given(true) { + + numerator = new IT[CGAL::degree(P)]; + denominator_exponent = new IT[CGAL::degree(P)]; + is_exact = new bool[CGAL::degree(P)]; + number_of_real_roots_ = 0; + if(CGAL::degree(P) == 0) + { + if(P.is_zero()) number_of_real_roots_ = -1; + return; + } + typename FT_rat::Decompose decompose; + typedef typename FT_rat::Numerator Numerator; + typedef typename FT_rat::Denominator Denominator; + Numerator numleft, numright; + Denominator denleft, denright; + + decompose(left,numleft,denleft); + decompose(right,numright,denright); + + LEFT = numleft * denright; + SCALE = numright * denleft - LEFT; + DENOM = denleft * denright; + poly_.scale_down(denleft*denright); + + intern_decompose(poly_,typename FT_poly::Is_decomposable()); + } + + //! copy constructor + Descartes(const Descartes& D) + : poly_(D.poly_), + number_of_real_roots_(D.number_of_real_roots_), + LEFT(D.LEFT), + SCALE(D.SCALE), + DENOM(D.DENOM), + is_strong_(D.is_strong_), + k(D.k), + interval_given(D.interval_given) { + + numerator = new IT[CGAL::degree(poly_)]; + denominator_exponent = new IT[CGAL::degree(poly_)]; + is_exact = new bool[CGAL::degree(poly_)]; + for(int i=0; i= 0 && i < number_of_real_roots_); + construct_binary(denominator_exponent[i], denominator_); + numerator_= SCALE * numerator[i] + LEFT * denominator_; + denominator_ = denominator_ * DENOM; + } + + + void right_bound(int i,IT& numerator_, IT& denominator_) const { + CGAL_assertion(i >= 0 && i < number_of_real_roots_); + if(is_exact[i]){ + return left_bound(i,numerator_,denominator_); + } + else{ + construct_binary(denominator_exponent[i],denominator_); + numerator_= SCALE * (numerator[i]+1) + LEFT * denominator_; + denominator_ = denominator_ * DENOM; + } + } +public: + + /*! \brief returns \f${l_i}\f$ the left bound of the isolating interval + for root \f$root_{i}\f$. + + In case is_exact_root(i) is true, \f$l_i = root_{i}\f$,\n + otherwise: \f$l_i < root_{i}\f$. + + If \f$i-1>=0\f$, then \f$l_i > root_{i-1}\f$. \n + If \f$i-1>=0\f$, then \f$l_i >= r_{i-1}\f$, + the right bound of \f$root_{i-1}\f$\n + + \pre 0 <= i < number_of_real_roots() + */ + Rational left_bound(int i) const { + IT numerator_, denominator_; + left_bound(i,numerator_,denominator_); + return Rational(numerator_) / Rational(denominator_); + } + + /*! \brief returns \f${r_i}\f$ the right bound of the isolating interval + for root \f$root_{i}\f$. + + In case is_exact_root(i) is true, \f$r_i = root_{i}\f$,\n + otherwise: \f$r_i > root_{i}\f$. + + If \f$i+1< n \f$, then \f$r_i < root_{i+1}\f$, + where \f$n\f$ is number of real roots.\n + If \f$i+1< n \f$, then \f$r_i <= l_{i+1}\f$, + the left bound of \f$root_{i+1}\f$\n + + + \pre 0 <= i < number_of_real_roots() + */ + Rational right_bound(int i) const { + IT numerator_, denominator_; + right_bound(i,numerator_,denominator_); + return Rational(numerator_) / Rational(denominator_); + } + +private: + void intern_decompose( Polynomial P_, ::CGAL::Tag_true){ + typename FT_poly::Decompose decompose; + typedef typename FT_poly::Numerator_type Numerator_poly; + typedef typename Numerator_poly::NT Coeff; + typename FT_poly::Numerator_type NumP; + typename FT_poly::Denominator_type dummy; + + decompose(P_,NumP,dummy); + init_with(NumP); + } + + void intern_decompose( Polynomial P, ::CGAL::Tag_false){ + init_with(P); + } + + + template + void init_with(const Polynomial__& P){ + typedef typename Polynomial__::NT Coeff; + if(!interval_given) + { + LEFT = -weak_upper_root_bound(P); + SCALE = - LEFT * IT(2); + DENOM = IT(1); + } + Polynomial__ R = ::CGAL::translate(P,Coeff(LEFT)); + Polynomial__ Q = ::CGAL::scale_up(R,Coeff(SCALE)); + zero_one_descartes(Q,0,0); + } + + + //! returns the polynomial $(1 + x)^n P(1/(1 + x))$. + template + /* + typename + CGAL::Polynomial_traits_d + ::template Rebind::Other::Type + */ + POLYNOMIAL_REBIND(Coeff__) + variation_transformation(const POLYNOMIAL_REBIND(Coeff__)& P) { + POLYNOMIAL_REBIND(Coeff__) R = reversal(P); + return translate_by_one(R); + } + + //! Returns an upper bound on the absolute value of all roots of $P$. + /*! The upper bound is a power of two. Only works for univariate + * polynomials. + */ + template + IT weak_upper_root_bound(const POLYNOMIAL_REBIND(Coeff__)& P) { + + typename Real_embeddable_traits::Abs abs; + const int n = CGAL::degree(P); + IT r(1); // return value + Coeff__ x(1); // needed to "evaluate" the polynomial + Coeff__ val; + for (;;) { + val = -abs(P[n]); + for (int i = n-1; i >= 0; i--) { + val = val*x + abs(P[i]); + } + if (val < Coeff__(0)) return r; + r *= IT(2); + x = Coeff__(r); + } + } + + //! tests if the polynomial has no root in the interval. + template + bool not_zero_in_interval(const POLYNOMIAL_REBIND(Coeff__)& P) + { + if(CGAL::degree(P) == 0) return true; + if(internal::sign_variations(variation_transformation(P)) != 0) + return false; + return (P[0] != Coeff__(0) && P.evaluate(Coeff__(1)) != Coeff__(0)); + } + //! Descartes algoritm to determine isolating intervals for the roots + //! lying in the interval (0,1). + // The parameters $(i,D)$ describe the interval $(i/2^D, (i+1)/2^D)$. + // Here $0\leq i < 2^D$. + template + void zero_one_descartes(const POLYNOMIAL_REBIND(Coeff__)& P, + IT i, IT D) { + // Determine the number of sign variations of the transformed + // polynomial $(1+x)^nP(1/(1+x))$. This gives the number of + // roots of $P$ in $(0,1)$. + + POLYNOMIAL_REBIND(Coeff__) R = variation_transformation(P); + int descarte = sign_variations(R); + + // no root + if ( descarte == 0 ) return; + + // exactly one root + // Note the termination criterion $P(0)\neq 0$ and $P(1)\neq 0$. + // This ensures that the given interval is an isolating interval. + if ( descarte == 1 + && P[0] != Coeff__(0) + && P.evaluate(Coeff__(1)) != Coeff__(0) ) { + if(is_strong_) { + strong_zero_one_descartes(P,i,D); + return; + } + else { + numerator[number_of_real_roots_] = i; + denominator_exponent[number_of_real_roots_] = D; + is_exact[number_of_real_roots_] = false; + number_of_real_roots_++; + return; + } + } + + // more than one root + // Refine the interval. + i = 2*i; D = D+1; + + // Transform the polynomial such that the first half of the interval + // is mapped to the unit interval. + POLYNOMIAL_REBIND(Coeff__) Q = scale_down(P,Coeff__(2)); + + // Consider the first half of the interval. + zero_one_descartes(Q,i,D); + + // Test if the polynomial is zero at the midpoint of the interval + POLYNOMIAL_REBIND(Coeff__) S = translate_by_one(Q); + if ( S[0] == Coeff__(0) ) { + numerator[number_of_real_roots_] = i + 1; + denominator_exponent[number_of_real_roots_] = D; + is_exact[number_of_real_roots_] = true; + number_of_real_roots_++; + } + + // Consider the second half of the interval. + zero_one_descartes(S,i+1,D); + } + + + //! Strong Descartes algoritm to determine isolating intervals for the + //! roots lying in the interval (0,1), where the first + //! derivative have no sign change. \pre $P$ has only one root in the + //! interval given by $(i,D)$. + // The parameters $(i,D)$ describe the interval $(i/2^D, (i+1)/2^D)$. + // Here $0\leq i < D$. + template + void strong_zero_one_descartes(const POLYNOMIAL_REBIND(Coeff__)& P, + IT i, IT D) { + + // Test if the polynomial P' has no roots in the + // interval. For further use in Newton, the interval should be not + // too large. + + // test if isolating interval is smaller than epsilon + // [l,r] -> r-l < epsilon + // l = (r-l) * i/2^D + l + // r = (r-l) * (i+1)/2^D + l + // r-l = (r-l) * 1/2^D + // r-l < epsilon = 2^(-k) + // <=> (r-l) * 1/2^D < 2^(-k) + // <=> 2^D > (r-l) / 2^(-k) + // <=> 2^D > (r-l) * 2^k + + POLYNOMIAL_REBIND(Coeff__) PP = CGAL::differentiate(P); + if(not_zero_in_interval(PP)) { // P' + IT tmp; + construct_binary(D-k, tmp); // tmp = 2^{D-k} + if(tmp * DENOM > SCALE ) { + numerator[number_of_real_roots_] = i; + denominator_exponent[number_of_real_roots_] = D; + is_exact[number_of_real_roots_] = false; + number_of_real_roots_++; + return; + } + } + + // either $P'$ fails the test, + // or the interval is too large + // Refine the interval. + i = 2*i; D = D+1; + + // Transform the polynomial such that the first half of the interval + // is mapped to the unit interval. + POLYNOMIAL_REBIND(Coeff__) Q = scale_down(P,Coeff__(2)); + + // Test if the polynomial is zero at the midpoint of the interval + POLYNOMIAL_REBIND(Coeff__) S = translate_by_one(Q); + if ( S[0] == Coeff__(0) ) { + numerator[number_of_real_roots_] = i + 1; + denominator_exponent[number_of_real_roots_] = D; + is_exact[number_of_real_roots_] = true; + number_of_real_roots_++; + return; + } + + // Consider the first half of the interval. + if(sign_variations(variation_transformation(Q)) == 1) { + strong_zero_one_descartes(Q,i,D); + return; + } + + // Consider the second half of the interval. + strong_zero_one_descartes(S,i+1,D); + return; + } +}; + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_DESCARTES_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Event_line_builder.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Event_line_builder.h new file mode 100644 index 00000000000..e35493b87f6 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Event_line_builder.h @@ -0,0 +1,746 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ACK_EVENT_LINE_BUILDER +#define CGAL_ACK_EVENT_LINE_BUILDER 1 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +// Constant for the interval test in \c compute_mk +#define CGAL_ACK_COMPUTE_MK_PRECISION 64 + + +#if defined(BOOST_MSVC) +# pragma warning(push) +# pragma warning(disable:4290) +#endif + +namespace CGAL { + +namespace internal { + +/*! + * \brief Constructs Vert_line-objects for an algebraic curve. + * + * + * The method \ref create_event_line builds such a vert-line + * for critical x-values. See the + * documentation of this routines for further information. + * + */ +template +class Event_line_builder { + +public: + + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + // \brief The curve class. + typedef typename Algebraic_kernel_with_analysis_2::Curve_analysis_2 Curve_analysis_2; + + + // \brief Type of the coefficients of the input polynomial + typedef typename Algebraic_kernel_with_analysis_2::Coefficient Coefficient; + + // \brief The type for rational x-coordinates and for interval boundaries + typedef typename Algebraic_kernel_with_analysis_2::Bound Bound; + + // \brief Univariate polynomials + typedef typename Algebraic_kernel_with_analysis_2::Polynomial_1 + Polynomial_1; + + // \brief Bivariate polynomials + typedef typename Algebraic_kernel_with_analysis_2::Polynomial_2 + Polynomial_2; + + // \brief Rational polynomials + typedef typename + CGAL::Polynomial_traits_d + ::template Rebind::Other::Type Poly_rat_1; + + // \brief Type for x-values + typedef typename Curve_analysis_2::Algebraic_real_1 Algebraic_real_1; + + //! \brief \c Vert_line specification for critical x-values + typedef typename Curve_analysis_2::Status_line_1 Status_line_1; + + // \brief Type for Polynomial traits + typedef CGAL::Polynomial_traits_d Polynomial_traits_2; + + //! Default Constructor + Event_line_builder() {} + + /*! + * \brief Constructs the builder for the \c curve object. + * + * Apart from the curve itself a polynomial is passed which is expected + * to be the primitive part of the curve. + * If the flag \c compute_sturm_habicht is set, the principal and + * coprincipal Sturm-Habicht coefficients of \c polynomial are computed. + * These coefficients provide information about properties of the curve + * at certain x-coordinates. Some methods of this class are only + * possible if they are computed. + * + * See \c NiX_resultant_matrix for + * more details about Sturm-Habicht sequences. + */ + Event_line_builder(Algebraic_kernel_with_analysis_2* kernel, + Curve_analysis_2 curve, + Polynomial_2 polynomial) + throw(internal::Zero_resultant_exception) + : _m_kernel(kernel), curve(curve), polynomial(polynomial) + {} + + + /*! + * \brief Creates an event line at position \c alpha for the specified + * curve. + * + * Additionally, the \c id of the event line to be created has to be + * specfied, and + * the number of arcs that are entering from the left and leaving to the + * right are needed. Furthermore, the flag \c root_of_resultant tells + * whether \c alpha is a root of the resultant of the specified curve, and + * \c root_of_content indicates whether \c alpha is a root of the content, + * which is equivalent to the existence of a vertical line component. + * + * The function tries to apply the Bitstream Descartes method to isolate + * the real roots and create the Vert_line accordingly. For that purpose, + * symbolic precomputations are mostly necessary, using the Sturm-Habicht + * coefficients. It is necessary that they were computed beforehand. + * However, such symbolic computations need not be done if alpha is a + * simple root of the resultant, so if \c mult equals 1. + * + * The method will succeed, if the curve has only one multiple root + * at \c alpha over the complex numbers. It will never succeed, if there is + * more than one real root at \c alpha. In other cases, the outcome is not + * clear. In cases where the functions fails, a + * CGAL::internal::Non_generic_position_exception is thrown, otherwise, a + * fixed AcX::Vert_line object is returned. + */ + Status_line_1 + create_event_line(int id,Algebraic_real_1 alpha,int arcs_left,int arcs_right, + bool root_of_resultant, bool root_of_content,int mult) + throw(CGAL::internal::Non_generic_position_exception) { + + try { + + int k; + + + Bitstream_descartes bit_des + = construct_bitstream_descartes(alpha,k,root_of_resultant,mult, + arcs_left,arcs_right); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "bitstream descartes constructed" + << std::endl; +#endif +*/ + + int n = bit_des.number_of_real_roots(); + + int c = this->get_index_of_multiple_root(bit_des); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "n and c: " << n << " " << c << std::endl; +#endif +*/ + int arcs_to_candidate_left=arcs_left-n+1; + int arcs_to_candidate_right=arcs_right-n+1; + + bool event_flag; + + //if(false) { + if(arcs_to_candidate_left!=1 || arcs_to_candidate_right!= 1) { + event_flag=true; + } + else { + +// Need this flag to decide the event flag correctly, +// we don't care about it for now! +#if !CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY + event_flag=false; +#else + + Polynomial_2& f = polynomial; + + if(c==-1 || k==0) { + event_flag=false; + } else { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Ev check..." << std::flush; +#endif + + typename Polynomial_traits_2::Differentiate diff; + Polynomial_2 fx diff(f,0); + Polynomial_2 fy diff(f,1); + event_flag=event_point_checker(bit_des,f,alpha,k,fx,fy); + + } +#endif + } + + int root_number=bit_des.number_of_real_roots(); + + typename Status_line_1::Arc_container arc_container; + + for(int i=0;iis_zero_at_1_object() + (CGAL::leading_coefficient(polynomial),alpha)) { + int n = CGAL::degree(polynomial,1); + CGAL_assertion(! kernel()->is_zero_at_1_object() + (CGAL::get_coefficient(polynomial,n-1), + alpha)); + CGAL::Sign asym_sign + = kernel()->sign_at_1_object() + (CGAL::get_coefficient(polynomial,n-1),alpha) + * kernel()->sign_at_1_object() + (CGAL::differentiate + (CGAL::get_coefficient(polynomial,n)),alpha); + CGAL_assertion(asym_sign!=CGAL::ZERO); + if(asym_sign==CGAL::SMALLER) { + vl._set_number_of_branches_approaching_infinity + (std::make_pair(1,0),std::make_pair(0,1)); + } else { + vl._set_number_of_branches_approaching_infinity + (std::make_pair(0,1),std::make_pair(1,0)); + } + } +#endif + + + if(root_of_content) { + vl._set_v_line(); + } + return vl; + } + catch(CGAL::internal::Non_generic_position_exception err) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Detected non-generic position for alpha=" + << CGAL::to_double(alpha) << std::endl; +#endif + throw CGAL::internal::Non_generic_position_exception(); + } + + } + +protected: + + Algebraic_kernel_with_analysis_2* kernel() const { + return this->_m_kernel; + } + + /*! + * Typedef for the Interval type + */ + typedef boost::numeric::interval Interval; + + // \brief Refinement type from the curve class. + typedef typename Curve_analysis_2::Bitstream_descartes + Bitstream_descartes; + + typedef typename Curve_analysis_2::Bitstream_coefficient_kernel + Bitstream_coefficient_kernel; + + typedef typename Curve_analysis_2::Bitstream_traits + Bitstream_traits; + + Algebraic_kernel_with_analysis_2* _m_kernel; + + //! The curve whose Status_line_1s are built. + Curve_analysis_2 curve; + + //! The content free part of the curve's polynomial + Polynomial_2 polynomial; + + + /*! + * \brief Exact information about fx=alpha. + * + * Returns a pair (m,k) with the following meaning. Let + * \c seq be a sequence g0,...,gn. + * Then, \c k is the first index for which gi(alpha) + * is not zero. The number m is the result of the function + * C (g0(alpha),...,gn(alpha)), where + * C is defined as in L.Gonzalez-Vega, I.Necula: Efficient + * topology determination of implicitly defined algebraic plane curves. + * Computer Aided Geometric Design 19 (2002) 719-743. + * If \c seq is the sequence of principal Sturm-Habicht coefficients, + * \c m is the number of real roots of fx=alpha, + * counted without multiplicity. + * + * If the first elements in the sequence are known to be zero, + * \c first_elements_zero can be set accordingly. The zero test is then + * ommitted for that leading elements. + */ + template + std::pair compute_mk(Algebraic_real_1 alpha, + InputIterator seq_begin, + InputIterator seq_end, + int first_elements_zero=0) { + + typedef InputIterator Input_iterator; + + + Algebraic_real_1& alpha_ref=alpha; + + int m,k=-1; // Initialize to prevent compiler warning + + bool k_fixed=false; + + int seq_size = std::distance(seq_begin,seq_end); + + typedef int VT; + + typedef std::vector A_vector; + A_vector spec_stha(0); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << seq_size << std::endl; +#endif +*/ + + CGAL_assertion(spec_stha.size()==0); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << seq_size << " elements to consider" + << std::endl; +#endif +*/ + int start_i=first_elements_zero; + for(int i=0;isign_at_1_object()(*seq_it, + alpha_ref, + CGAL_ACK_COMPUTE_MK_PRECISION); + + //CGAL::Sign ia_try=CGAL::ZERO; + + if(ia_try!=CGAL::ZERO) { + if(! k_fixed) { + k=i; + k_fixed=true; +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "m.." << std::flush; +#endif + } + spec_stha.push_back(ia_try); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "successful" << std::endl; +#endif +*/ + continue; + } + /* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "no success" << std::endl; + CGAL_ACK_DEBUG_PRINT << "Is root of..." << std::flush; + CGAL_ACK_DEBUG_PRINT << "s." << std::endl; + CGAL_ACK_DEBUG_PRINT << "pol=" << *seq_it << std::endl; + CGAL_ACK_DEBUG_PRINT << "alpha=" << alpha.polynomial() << std::endl; +#endif + */ + + bool root_of = kernel()->is_zero_at_1_object()(*seq_it,alpha); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done " + << ((root_of) ? "true" : "false") + << std::endl; +#endif +*/ + if(root_of) { + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Is zero" << std::endl; +#endif +*/ + spec_stha.push_back(VT(0)); + } + else { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "is nonzero.." << std::flush; +#endif +*/ + if(! k_fixed) { + k=i; + k_fixed=true; +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "m.." << std::flush; +#endif +*/ + } +/* +#if CGAL_ACK_DEBUG_FLAG + ::CGAL::set_ascii_mode(CGAL_ACK_DEBUG_PRINT); + CGAL_ACK_DEBUG_PRINT << "Stha: " << (*seq_it) << std::endl; +#endif +*/ + VT beta + =kernel()->sign_at_1_object() (*seq_it,alpha_ref); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Value: " << beta << std::endl; +#endif +*/ + spec_stha.push_back(beta); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << " " << spec_stha.size() << std::endl; +#endif +*/ + } + } +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "--------" << std::endl; + CGAL_ACK_DEBUG_PRINT << " " << spec_stha.size() << std::endl; + for(int j=0;j<(int)spec_stha.size();j++) { + CGAL_ACK_DEBUG_PRINT << j << ": " << spec_stha[j] << std::endl; + } + CGAL_ACK_DEBUG_PRINT << "--------" << std::endl; +#endif +*/ + + typename A_vector::iterator it=spec_stha.begin() + k; +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "k=" << k << ", Compute m..." << std::flush; +#endif +*/ + m = CGAL::number_of_real_roots(it,spec_stha.end()); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif +*/ +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "k=" << k << " m=" << m << ".."<< std::flush; +#endif + + return std::make_pair(m,k); + + } + + Poly_rat_1 mod(Poly_rat_1 a,Poly_rat_1 b) const { + Poly_rat_1 ret=CGAL::mod(a,b); + return ret; + } + + /*! + * \brief Constructs a Bitstream Descartes object for + * fx=alpha + * + * Tries to isolate the roots of fx=alpha with the + * Bitstream m-k-Descartes method. As additional information, the value + * \c k is returned which is the greatest common divisor of \c f with its + * derivative. The flag \c root_of_resultant denotes whether alpha is + * a root of the resultant of \c f with its derivative. + * Also, the multiplicity of \c alpha as root of the resultant is given + * It his multiplcity is 1, one can avoid the computations with the + * Sturm-Habicht coefficient by looking at \c arcs_left and \c arcs_right. + * + * This method requires the Sturm-Habicht coefficients of \c f to be + * computed beforehand. + * On failure, the error CGAL::internal::Non_generic_position_exception + * is thrown. + */ + Bitstream_descartes construct_bitstream_descartes(const Algebraic_real_1& + alpha, + int& k, + bool root_of_resultant, + int mult, + int arcs_left, + int arcs_right) + throw(CGAL::internal::Non_generic_position_exception) { + + + Bitstream_traits traits(Bitstream_coefficient_kernel(kernel(),alpha)); + + if(root_of_resultant) { +#if !CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES + if(kernel()->is_zero_at_1_object() + (CGAL::leading_coefficient(polynomial),alpha)) { + Polynomial_2 trunc_pol = + CGAL::internal::poly_non_vanish_leading_term + (kernel(),polynomial,alpha); + + CGAL_assertion(CGAL::degree(trunc_pol,1)+1 == + CGAL::degree(polynomial,1)); + CGAL::internal::Square_free_descartes_tag t; + + Bitstream_descartes bit_des(t,trunc_pol,traits); + + return bit_des; + } +#endif + + int m; + CGAL_assertion(mult>0); + if(mult==1) { + m=(arcs_left+arcs_right) / 2; + k=1; + } + else { + std::pair mk + = compute_mk(alpha, + curve.principal_sturm_habicht_begin(), + curve.principal_sturm_habicht_end(), + 1); + + m = mk.first; + k = mk.second; + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Bit Des..." << std::flush; +#endif + + CGAL::internal::M_k_descartes_tag t; + + Bitstream_descartes bit_des(t,polynomial,m,k,traits); + + return bit_des; + } + else { + CGAL::internal::Square_free_descartes_tag t; + Bitstream_descartes bit_des(t,polynomial,traits); + + return bit_des; + } + + } + + + /*! + * \brief Checks whether a point is a singularity or not. + * + * This routine is applied in situations where a potential event point + * has one incident arc to the left and to the right. To distinguish + * singularities from other points, this method checks whether the two + * linearly independent partial derivatives \c der_1 and \c der_2 vansh + * at the point \c (alpha,beta). Here, \c beta is implicitly defined as + * \f[\beta=\frac{-costha[k-1]}{k\cdot stha[k]}\f] + * and it is verified first that \c beta is indeed the y-value that + * corresponds to the multiple root in the bit_des-instance. + * If it is not, a Non_generic_position_exception is thrown. + * + * If no exception is thrown, the function returns true if and only if + * there is a singularity at (alpha,beta). + */ + bool event_point_checker(Bitstream_descartes& bit_des, + const Polynomial_2& polynomial, + const Algebraic_real_1& alpha, + int k, + const Polynomial_2& der_1, + const Polynomial_2& der_2) + throw(CGAL::internal::Non_generic_position_exception) { + + //Guess the right expression for y +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << costha.size() << " " + << stha.size() << std::endl; + CGAL_ACK_DEBUG_PRINT << k << std::endl; + CGAL_ACK_DEBUG_PRINT << "Costha: " << costha[k-1] + << " Stha: " << stha[k] << std::endl; +#endif +*/ + + Polynomial_1 p = -curve.coprincipal_sturm_habicht_of_primitive(k); + Polynomial_1 q + = Coefficient(k)*curve.principal_sturm_habicht_of_primitive(k); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << k << " " << CGAL::to_double(alpha) + << std::endl); + CGAL_ACK_DEBUG_PRINT << p << " " << q << std::endl + << polynomial << std::endl; + Bound a_d = alpha.low(); + CGAL_ACK_DEBUG_PRINT << CGAL::to_double(p.evaluate(a_d)/ + q.evaluate(a_d)) + << std::endl; +#endif +*/ + // Check whether it lies in the candidates interval + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "iv-test..." << std::flush; +#endif + + typedef typename CGAL::Get_arithmetic_kernel + ::Arithmetic_kernel::Bigfloat_interval BFI; + + CGAL::internal::Bitstream_coefficient_kernel_at_alpha + + alpha_kernel(kernel(),alpha); + + int c = this->get_index_of_multiple_root(bit_des); + + long old_prec = CGAL::get_precision(BFI()); + + //std::cout << "p=" << p << std::endl; + //std::cout << "q=" << q << std::endl; + + long prec=16; + + while(true) { + CGAL::set_precision(BFI(),prec); + //std::cout << "Increased to " << prec << std::endl; + BFI isol_iv + = CGAL::hull(CGAL::convert_to_bfi(bit_des.left_bound(c)), + CGAL::convert_to_bfi(bit_des.right_bound(c))); + BFI q_iv = alpha_kernel.convert_to_bfi_object()(q); + if(! CGAL::in_zero(q_iv)) { + BFI p_iv = alpha_kernel.convert_to_bfi_object()(p); + BFI approx_iv = p_iv/q_iv; + //std::cout << "p_iv=[" << CGAL::lower(p_iv) << "," << CGAL::upper(p_iv) << "]" << std::endl; + //std::cout << "q_iv=[" << CGAL::lower(q_iv) << "," << CGAL::upper(q_iv) << "]" << std::endl; + //std::cout << "isol_iv=[" << CGAL::lower(isol_iv) << "," << CGAL::upper(isol_iv) << "]" << std::endl; + //std::cout << "approx_iv=[" << CGAL::lower(approx_iv) << "," << CGAL::upper(approx_iv) << "]" << std::endl; + if(CGAL::subset(approx_iv,isol_iv)) { + break; + } + if(! CGAL::overlap(approx_iv,isol_iv)) { + throw CGAL::internal::Non_generic_position_exception(); + } + } + prec*=2; + } + + CGAL::set_precision(BFI(),old_prec); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "on f..." << std::flush; +#endif + if(! CGAL::internal::zero_test_bivariate + + (kernel(),alpha,polynomial,p,q)) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Detected non-generic position for alpha=" + << CGAL::to_double(alpha) << std::endl; +#endif + throw CGAL::internal::Non_generic_position_exception(); + } + // Check whether the two partial derivatives vanish +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "on fx..." << std::flush; +#endif + bool is_singularity + = CGAL::internal::zero_test_bivariate + + (kernel(),alpha,der_1,p,q); + if(is_singularity) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "on fy..." << std::flush; +#endif + return CGAL::internal::zero_test_bivariate + + (kernel(),alpha,der_2,p,q); + } else { + return false; + } + } + +protected: + + int get_index_of_multiple_root(const Bitstream_descartes& bit_des) const { + int n = bit_des.number_of_real_roots(); + for(int i=0;i +// +// ============================================================================ + +// TODO: Some comments are original EXACUS comments and aren't adapted. So +// they may be wrong now. + +// TODO: should exponent type be long or Integer ? + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H +#define CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H + +#include + +#if CGAL_USE_LEDA +#include +#endif + +#if CGAL_USE_CORE +#include +#endif + +#if CGAL_USE_MPFR +#include +#endif + +#include + + +namespace CGAL { + +namespace internal { + +// Don't define default, results in more convinient compiler messages +template< class Type > class Float_traits; +// { +// public: +// typedef Null_functor Get_mantissa; +// typedef Null_functor Get_exponent; +// typedef Null_functor Mul_by_pow_of_2; +// }; + +#ifdef CGAL_USE_LEDA + +// Specialization for leda_bigfloat +template<> +class Float_traits< leda_bigfloat > { +public: + struct Get_mantissa + : public std::unary_function< leda_bigfloat, leda_integer > { + leda_integer operator()( const leda_bigfloat& x ) const { + //std::cout << x.get_significant() << std::endl; + return x.get_significant(); + } + }; + + struct Get_exponent + : public std::unary_function< leda_bigfloat, long > { + long operator()( const leda_bigfloat& x ) const { + return x.get_exponent().to_long(); + } + }; + + struct Mul_by_pow_of_2 + : public std::binary_function< leda_bigfloat, long, leda_bigfloat> { + leda_bigfloat operator()( const leda_bigfloat& a, long e ) const { + return leda_bigfloat(a.get_significant(), a.get_exponent()+e); + } + }; +}; + +#endif + +#ifdef CGAL_USE_CORE + +// Specialization for CORE::BigFloat +template<> +class Float_traits< CORE::BigFloat > { +public: + + struct Get_mantissa + : public std::unary_function< CORE::BigFloat, CORE::BigInt > { + CORE::BigInt operator()( const CORE::BigFloat& x ) const { + return x.m(); + } + }; + + struct Get_exponent + : public std::unary_function< CORE::BigFloat, long > { + long operator()( const CORE::BigFloat& x ) const { + return 14*x.exp(); // The basis is 8092 + } + }; + + struct Mul_by_pow_of_2 + : public std::binary_function + < CORE::BigFloat, long , CORE::BigFloat> { + CORE::BigFloat operator()( const CORE::BigFloat& a, long e ) const { + return a*CORE::BigFloat::exp2(e); + } + }; + +}; +#endif + + +#if CGAL_USE_MPFR +template<> class Float_traits< Gmpfr > { + + struct Get_mantissa_exponent + : public std::unary_function< Gmpfr, std::pair > { + + std::pair operator()( const Gmpfr& x ) const { + return x.to_integer_exp(); + } + }; +public: + struct Get_mantissa + : public std::unary_function< Gmpfr, Gmpz > { + Gmpz operator()( const Gmpfr& x ) const { + return Get_mantissa_exponent()(x).first; + } + }; + + struct Get_exponent + : public std::unary_function< Gmpfr, long > { + long operator()( const Gmpfr& x ) const { + return Get_mantissa_exponent()(x).second; + } + }; + +struct Mul_by_pow_of_2 + : public std::binary_function< Gmpfr, Gmpz, Gmpfr> { + Gmpfr operator()( const Gmpfr& a, long e ) const { + Gmpfr result(0,a.get_precision()); // just to get the prec of a + if (e >= 0 ){ + mpfr_mul_2si (result.fr(), a.fr(), e, mpfr_get_default_rounding_mode()); + //std::cout << "INPUT : "<< a <<"+" << e << std::endl; + //std::cout << "result: "<< result << std::endl; + //std::cout << "TRUTH : "<< a * CGAL::ipower(Gmpfr(2),e) << std::endl; + CGAL_postcondition(a * CGAL::ipower(Gmpfr(2),e) == result); + } + else{ + mpfr_div_2si (result.fr(), a.fr(), -e, mpfr_get_default_rounding_mode()); + CGAL_postcondition(a / CGAL::ipower(Gmpfr(2),-e) != result); + } + return result; + } +}; +}; +#endif +} //namespace internal + + + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_FLOAT_TRAITS_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_1.h new file mode 100644 index 00000000000..f34190c7aa9 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_1.h @@ -0,0 +1,99 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_INTERVAL_EVALUATE_1 +#define CGAL_INTERVAL_EVALUATE_1 1 + +#include + +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +template +struct Interval_evaluate_1 : public std::binary_function +, + std::pair::Coefficient_type,Bound>::Type, + typename CGAL::Coercion_traits::Coefficient_type,Bound>::Type> > { + + typedef CGAL::Polynomial_traits_d< Polynomial_1 > PT_1; + + typedef typename PT_1::Innermost_coefficient_type Innermost_coefficient_type; + + typedef CGAL::Coercion_traits< Innermost_coefficient_type, Bound > CT; + + typedef typename CT::Type Coercion_type; + + typedef std::pair< Coercion_type, Coercion_type > result_type; + + result_type operator()(const Polynomial_1& p, + const std::pair< Bound, Bound >& b) const { + return this->operator()(p, CGAL::make_array(b.first, b.second)); + } + + result_type operator()(const Polynomial_1& p, + const CGAL::cpp0x::array< Bound, 2 >& b) const { + + typename CT::Cast cast; + + typedef ::boost::numeric::interval< Coercion_type > Coercion_interval; + + typedef typename PT_1::Coefficient_const_iterator + Coefficient_const_iterator; + + Coercion_interval ix(cast(b[0]), cast(b[1])); + + typedef typename PT_1::Coefficient_const_iterator_range + Coefficient_const_iterator_range; + + Coefficient_const_iterator_range range = + typename PT_1::Construct_coefficient_const_iterator_range()(p); + + Coefficient_const_iterator it = CGAL::predecessor(range.second); + + Coercion_interval res(cast(*it)); + + Coefficient_const_iterator p_begin = range.first; + while(it != p_begin) { + it--; + res = res * ix + Coercion_interval(cast(*it)); + } + return std::make_pair(res.lower(),res.upper()); + } + +}; + +} // namespace internal + +} // namespace CGAL + +#endif // CGAL_INTERVAL_EVALUATE_1 diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_2.h new file mode 100644 index 00000000000..c14f395e8d5 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Interval_evaluate_2.h @@ -0,0 +1,111 @@ +// Copyright (c) 2006-2010 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_INTERVAL_EVALUATE_2 +#define CGAL_INTERVAL_EVALUATE_2 1 + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +template +struct Interval_evaluate_2 : public std::binary_function +, + std::pair::Innermost_coefficient_type,Bound>::Type, + typename CGAL::Coercion_traits::Innermost_coefficient_type,Bound>::Type> > { + +public: + + typedef CGAL::Polynomial_traits_d< Polynomial_2 > PT_2; + + typedef typename PT_2::Innermost_coefficient_type Innermost_coefficient_type; + + typedef CGAL::Coercion_traits< Innermost_coefficient_type, Bound > CT; + + typedef typename CT::Type Coercion_type; + + typedef std::pair< Coercion_type, Coercion_type > result_type; + + result_type operator()(const Polynomial_2& p, + const CGAL::cpp0x::array< Bound, 4 >& b) const { + + typename CT::Cast cast; + + typedef ::boost::numeric::interval< Coercion_type > Coercion_interval; + + typedef typename PT_2::Coefficient_const_iterator + Coefficient_const_iterator; + + typedef typename PT_2::Coefficient_const_iterator_range + Coefficient_const_iterator_range; + + typedef typename PT_2::Coefficient_type Polynomial_1; + + CGAL::internal::Interval_evaluate_1< Polynomial_1,Bound > + interval_evaluate_1; + + typedef typename CGAL::internal::Interval_evaluate_1< Polynomial_1,Bound >:: + result_type Interval_result_type; + + std::pair< Bound, Bound > x_pair = std::make_pair(b[0],b[1]); + + Coercion_interval iy(cast(b[2]),cast(b[3])); + + // CGAL::Polynomial does not provide Coercion_traits for number + // types => therefore evaluate manually + Coefficient_const_iterator_range range = + typename PT_2::Construct_coefficient_const_iterator_range()(p); + + Coefficient_const_iterator it = CGAL::predecessor(range.second); + + Interval_result_type initial_pair = interval_evaluate_1(*it,x_pair); + Coercion_interval res(initial_pair.first,initial_pair.second); + + Coefficient_const_iterator p_begin = range.first; + + while((it) != p_begin) { + it--; + Interval_result_type curr_iv = interval_evaluate_1(*it,x_pair); + res = res * iy + Coercion_interval(curr_iv.first,curr_iv.second); + } + return std::make_pair(res.lower(),res.upper()); + } + +}; + +} // namespace internal + + +} // namespace CGAL + +#endif // CGAL_INTERVAL_EVALUATE_2 diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/LRU_hashed_map.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/LRU_hashed_map.h new file mode 100644 index 00000000000..dee7905d316 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/LRU_hashed_map.h @@ -0,0 +1,426 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Pavel Emeliyanenko +// +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H + +#include + +#include + +#include +#include +#include +#include +#include +#include + +using boost::multi_index::multi_index_container; +using boost::multi_index::get; +using boost::multi_index::project; + +namespace CGAL { + +namespace internal { + + +//! \brief this class defines hashed map container with LRU capabilities, +//! +//! stores pair of \c KeyType_ and \c ValueType_. Before adding to +//! the map the input is normialized using \c Canonicalizer_ +//! \c Pred_ is binary predicate acting as an equivalence relation on +//! values of \c KeyType_, \c Creator_ is a mapping from \c KeyType_ to +//! \c ValueType_, \c Hash_ is function object which returns hash values +//! for the keys +template < + class KeyType_, class ValueType_, + class Hash_ = boost::hash, + class Pred_ = std::equal_to, + class Canonicalizer_ = CGAL::Identity, + class Creator_ = CGAL::Creator_1 > +class LRU_hashed_map +{ +public: + //!\name public typedefs + //!@{ + + //! this instance's first argument + typedef KeyType_ Key_type; + //! this instance's second argument + typedef ValueType_ Value_type; + //! hash function + typedef Hash_ Hash; + //! equality predicate + typedef Pred_ Pred; + //! input data canonicalizer + typedef Canonicalizer_ Canonicalizer; + //! mapping \c KeyType_ -> \c ValueType_ + typedef Creator_ Creator; + + //! hashed map data type + typedef std::pair Data_type; + + // try boost::identity ? + typedef boost::multi_index::multi_index_container< + Data_type, + boost::multi_index::indexed_by< + boost::multi_index::sequenced<>, + boost::multi_index::hashed_unique< + BOOST_MULTI_INDEX_MEMBER(Data_type, Key_type, first), + Hash, Pred > > > Hashed_map; + + + + //!@} +protected: + //!\name private members + //!@{ + + + //! hashed map instance + mutable Hashed_map _m_hashed_map; + + //! maximal size allowed + unsigned _m_max_size; + + //!@} +public: + //!\name iterator types + //!@{ + + //! hashed index iterator + typedef typename + boost::multi_index::nth_index_iterator::type + Hashed_iterator; + + //! sequenced index iterator + typedef typename + boost::multi_index::nth_index_iterator::type + Sequenced_iterator; + + //! sequenced index const iterator + typedef typename + boost::multi_index::nth_index_const_iterator::type + Sequenced_const_iterator; + + //! result type of \c find operation: a pair of iterator pointing to + //! \c Data_type and a boolean indicating whether an element with + //! specified key was found + typedef std::pair Find_result; + + //!@} +public: + //!\name constructors and access functions + //!@{ + + //! \brief default constructor + LRU_hashed_map(unsigned max_size = + (std::numeric_limits< unsigned >::max)()) : + _m_hashed_map(),_m_max_size(max_size) + { } + + virtual ~LRU_hashed_map() + { } + + /*! \brief implements cache-like behaviour of the map + * + * If the object is not in the map, it is constructed using \c Creator + * and added to the map + */ + Value_type operator()(const Key_type& key_) const + { + Canonicalizer canonicalize; + Key_type key = canonicalize(key_); + + Find_result p = find(key); + if(!p.second) { + Creator create; + Value_type val = create(key); + insert(Data_type(key, val)); + return val; + } + return (p.first)->second; + } + + //! \brief looks for an entry with a specified key in the map + //! + //! returns a pair of iterator pointing to \c Data_type and a boolean + //! indicating whether an element with specified key was found + Find_result find(const Key_type& key) const + { + typename boost::multi_index::nth_index::type& + idx = _m_hashed_map.template get<1>(); + Hashed_iterator it = idx.find(key); + if(it == idx.end()) { + return Find_result(it, false); + } + + // otherwise put the accessed element on the top + // Comment out because of compiler problems with 3.4 + /* + _m_hashed_map.relocate(_m_hashed_map.begin(), + _m_hashed_map.project<0>(it)); + */ + return Find_result(it, true); + } + + //! \brief inserts an entry to the map + //! + //! on successful insertion, \c p.first points to the element + //! inserted; otherwise \c p.first points to an element that caused + //! the insertion to be banned. If the map's size exceeds \c max_size + //! the least recently used entry is dropped + std::pair insert(const Data_type& data) const + { + if(_m_hashed_map.size() > _m_max_size) + _m_hashed_map.pop_back(); + return _m_hashed_map.push_front(data); + } + + //! clears the map contents + void clear() { _m_hashed_map.clear(); } + + //! returns whether the map is empty. + bool is_empty() const { return _m_hashed_map.empty(); } + + //! returns the number of items in the map + unsigned size() { return _m_hashed_map.size(); } + + //! returns the largest possible size of the map (-1 if not set) + unsigned max_size() const { return _m_max_size; } + + //! \brief returns an iterator pointing to the beginning of the map + //! + //! all iterators run over sequenced indices + Sequenced_iterator begin() { return _m_hashed_map.begin(); } + + //! returns an iterator pointing to the end of the map + Sequenced_iterator end() { return _m_hashed_map.end(); } + + //! returns a const_iterator pointing to the beginning of the map + Sequenced_const_iterator begin() const + { return _m_hashed_map.begin(); } + + //! Returns a const_iterator pointing to the end of the map + Sequenced_const_iterator end() const + { return _m_hashed_map.end(); } + + //!@} +}; // class LRU_hashed_map_with_kernel + + +//! \brief this class defines hashed map container with LRU capabilities, +//! +//! stores pair of \c KeyType_ and \c ValueType_. Before adding to +//! the map the input is normialized using \c Canonicalizer_ +//! \c Pred_ is binary predicate acting as an equivalence relation on +//! values of \c KeyType_, \c Creator_ is a mapping from \c KeyType_ to +//! \c ValueType_, \c Hash_ is function object which returns hash values +//! for the keys +template < + class AlgebraicKernelWithAnalysis_2, + class KeyType_, class ValueType_, + class Hash_ = boost::hash, + class Pred_ = std::equal_to, + class Canonicalizer_ = CGAL::Identity, + class Creator_ = CGAL::Creator_1 > +class LRU_hashed_map_with_kernel + : public LRU_hashed_map +{ + +public: + + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + typedef LRU_hashed_map Base; + + //! this instance's first argument + typedef typename Base::Key_type Key_type; + //! this instance's second argument + typedef typename Base::Value_type Value_type; + //! hash function + typedef typename Base::Hash Hash; + //! equality predicate + typedef typename Base::Pred Pred; + //! input data canonicalizer + typedef typename Base::Canonicalizer Canonicalizer; + //! mapping \c KeyType_ -> \c ValueType_ + typedef typename Base::Creator Creator; + + //! hashed map data type + typedef typename Base::Data_type Data_type; + + typedef typename Base::Hashed_map Hashed_map; + + +protected: + //!\name private members + //!@{ + + + Algebraic_kernel_with_analysis_2* _m_kernel; + + +public: + + //!\name iterator types + //!@{ + + //! hashed index iterator + typedef typename Base::Hashed_iterator Hashed_iterator; + + //! sequenced index iterator + typedef typename Base::Sequenced_iterator Sequenced_iterator; + + //! sequenced index const iterator + typedef typename Base::Sequenced_const_iterator Sequenced_const_iterator; + + //! result type of \c find operation: a pair of iterator pointing to + //! \c Data_type and a boolean indicating whether an element with + //! specified key was found + typedef typename Base::Find_result Find_result; + + + //!\name constructors and access functions + //!@{ + + //! \brief default constructor + LRU_hashed_map_with_kernel(Algebraic_kernel_with_analysis_2* kernel, + unsigned max_size = -1u) : + Base(max_size), + _m_kernel(kernel) + { } + + ~LRU_hashed_map_with_kernel() + { } + + /*! \brief implements cache-like behaviour of the map + * + * If the object is not in the map, it is constructed using \c Creator + * and added to the map + */ + Value_type operator()(const Key_type& key_) const + { + Canonicalizer canonicalize; + Key_type key = canonicalize(key_); + + Find_result p = this->find(key); + if(!p.second) { + Creator create(_m_kernel); + Value_type val = create(key); + this->insert(Data_type(key, val)); + return val; + } + return (p.first)->second; + } + +}; // class LRU_hashed_map_with_kernel + +/*! \brief + * returns representation id as a hash value + */ +struct Id_hasher +{ + template + size_t operator()(const T& x) const { + return static_cast(x.id()); + } +}; + +struct To_double_hasher +{ + template + size_t operator()(const T& x) const { + return static_cast(CGAL::to_double(x)); + } +}; + + + +struct Id_equal_to +{ + template + bool operator()(const T& x1, const T& x2) const { + return (x1.id() == x2.id()); + } +}; + +struct Poly_hasher { + + template + std::size_t operator()(const Poly_2& p) const { + + if(p.is_zero()) + return 0xDeadBeef; + + typedef typename Poly_2::NT Poly_1; + typedef typename Poly_1::NT NT; + + const Poly_1& v = p[0]; + typename Poly_1::const_iterator cit; + NT res(0); + int i=0; + // take at most 3 trailing coeffs + for (cit = v.begin(), i = 0; i < 3 && cit != v.end(); cit++, i++) { + res += *cit; + } + if(res == NT(0)) + return 0xDeadBeef; + // randomization of the result + return static_cast(CGAL::to_double(res)); + } +}; + +struct Pair_id_hasher { + typedef size_t result_type; + + template + size_t operator()(const std::pair& p) const { + + std::size_t seed = p.first.id() + 0x9e3779b9; + seed ^= p.second.id() + 0x9e3779b9 + (seed << 6) + (seed >> 2); + return seed; + } +}; + +struct Pair_hasher { + + typedef size_t result_type; + + template + size_t operator()(const std::pair& p) const + { + std::size_t seed = 0; + boost::hash_combine(seed, p.first); + boost::hash_combine(seed, p.second); + return seed; + } +}; + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_HASHED_MAP_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_embeddable_extension.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_embeddable_extension.h new file mode 100644 index 00000000000..db107f5f02c --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_embeddable_extension.h @@ -0,0 +1,516 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: Some comments are original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H +#define CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H + +#include +#include + +#ifdef CGAL_USE_LEDA + +#include +#include +#include +#include +#endif + +#ifdef CGAL_USE_CORE +#include +#endif + +#ifdef CGAL_USE_GMP +#include +#include +#endif + +#ifdef CGAL_USE_MPFR +#include +#endif + +#ifdef CGAL_USE_MPFI +#include +#endif + + +namespace CGAL { + +namespace internal { + +// TODO: Implement array in source code file +// extern const signed char floor_log2_4bit[16]; // see src/floor_log2_4bit.C + +// Don't define default, results in more convinient compiler messages +template< class Type > class Real_embeddable_extension; +// { +// public: +// typedef Null_functor Ceil_log2_abs; +// typedef Null_functor Floor_log2_abs; +// typedef Null_functor Floor; +// typedef Null_functor Ceil; +// }; + + + +// Functor adapting functions +template< class NT > +long floor_log2_abs( const NT& x ) { + return typename Real_embeddable_extension< NT >::Floor_log2_abs()( x ); +} + +template< class NT > +long ceil_log2_abs( const NT& x ) { + return typename Real_embeddable_extension< NT >::Ceil_log2_abs()( x ); +} + +template< class NT > +typename Real_embeddable_extension::Floor::result_type +floor (const NT& x) { + return typename Real_embeddable_extension::Floor() (x); +} + +template< class NT > +typename Real_embeddable_extension::Ceil::result_type +ceil (const NT& x) { + return typename Real_embeddable_extension::Ceil() (x); +} + +// Specialization for long +template<> +class Real_embeddable_extension< long > { +public: + struct Ceil_log2_abs + : public std::unary_function< long, long > { + long operator()( long x ) { + if (x < 0) x = -x; + CGAL_precondition(x > 0); + if (x == 1) return 0; + return Floor_log2_abs()(x-1) + 1; + } + }; + + struct Floor_log2_abs + : public std::unary_function< long, long > { + private: + signed char floor_log2_4bit[16]; + public: + Floor_log2_abs() { + floor_log2_4bit[ 0] = -42; + floor_log2_4bit[ 1] = 0; + floor_log2_4bit[ 2] = 1; + floor_log2_4bit[ 3] = 1; + floor_log2_4bit[ 4] = 2; + floor_log2_4bit[ 5] = 2; + floor_log2_4bit[ 6] = 2; + floor_log2_4bit[ 7] = 2; + floor_log2_4bit[ 8] = 3; + floor_log2_4bit[ 9] = 3; + floor_log2_4bit[10] = 3; + floor_log2_4bit[11] = 3; + floor_log2_4bit[12] = 3; + floor_log2_4bit[13] = 3; + floor_log2_4bit[14] = 3; + floor_log2_4bit[15] = 3; + } + + long operator()( long x ) { + if (x < 0) x = -x; + CGAL_precondition(x > 0); + result_type l = 0; + while (x > 0xFFFF) { l += 16; x >>= 16; } + if (x > 0xFF) { l += 8; x >>= 8; } + if (x > 0xF) { l += 4; x >>= 4; } + CGAL_assertion(x > 0 && x < 16); + return l + int(floor_log2_4bit[x]); + } + }; + + struct Floor + : public std::unary_function< long, long > { + long operator() (long x) { return x;} + }; + struct Ceil + : public std::unary_function< long, long > { + long operator() (long x) { return x;} + }; +}; + + +#ifdef CGAL_USE_LEDA +// Specialization for leda_integer + +template<> +class Real_embeddable_extension< leda_integer > { +public: + typedef leda_integer Type; + + struct Ceil_log2_abs + : public std::unary_function< leda_integer, long > { + long operator()( const leda_integer& x ) const { + CGAL_precondition(x != leda_integer(0)); + ::leda::digit_sz ldgzeros = ::leda::digLeadingZeros(x.highword()); + result_type l = + x.used_words() * ::leda::DIGIT_LENGTH - 1 - ldgzeros; + // look if additional 1-bits force to round up + ::leda::digit h = 1; + h <<= ::leda::DIGIT_LENGTH - 1 - ldgzeros; + int i = x.used_words() - 1; + CGAL_assertion(x.contents(i) >= h); + if (x.contents(i) > h) return l+1; + while (--i >= 0) { + if (x.contents(i) != 0) return l+1; + } + return l; + } + }; + + struct Floor_log2_abs + : public std::unary_function< leda_integer, long > { + long operator()( const leda_integer& x ) const { + CGAL_precondition(x != leda_integer(0)); + ::leda::digit_sz ldgzeros + = ::leda::digLeadingZeros(x.highword()); + result_type l = + x.used_words() * ::leda::DIGIT_LENGTH - 1 - ldgzeros; + return l; + } + }; + + struct Floor + : public std::unary_function< leda_integer, leda_integer > { + leda_integer operator() (const leda_integer& x) const { return x;} + }; + struct Ceil + : public std::unary_function< leda_integer, leda_integer > { + leda_integer operator() (const leda_integer& x) const { return x;} + }; +}; + +template<> +class Real_embeddable_extension< leda_bigfloat > { +public: + + typedef leda_bigfloat Type; + + struct Floor_log2_abs + : public std::unary_function< leda_bigfloat, long > { + long operator()( const leda_bigfloat& x ) const { + CGAL_precondition(CGAL::sign(x) != CGAL::ZERO); + ::leda::integer abs_sign = abs(x.get_significant()); + return (x.get_exponent() + ::leda::log(abs_sign)).to_long(); + + } + }; + + struct Ceil_log2_abs + : public std::unary_function< leda_bigfloat, long > { + long operator()( const leda_bigfloat& x ) const { + CGAL_precondition(CGAL::sign(x) != CGAL::ZERO); + return ::leda::ilog2(x).to_long(); + } + }; + + struct Floor + : public std::unary_function< leda_bigfloat, leda_integer > { + leda_integer operator() ( const leda_bigfloat& x ) const { + return leda::to_integer( x, leda::TO_N_INF ); + } + }; + + struct Ceil + : public std::unary_function< leda_bigfloat, leda_integer > { + leda_integer operator() ( const leda_bigfloat& x ) const { + return leda::to_integer( x, leda::TO_P_INF ); + } + }; + +}; + +template<> +class Real_embeddable_extension< leda_bigfloat_interval > { +public: + typedef leda_bigfloat_interval Type; + + struct Floor_log2_abs + : public std::unary_function< leda_bigfloat_interval, long > { + + result_type operator() (const argument_type& x) const { + CGAL_precondition(! ::boost::numeric::in_zero(x)); + return internal::floor_log2_abs(::boost::numeric::abs(x).lower()); + } + }; + + struct Ceil_log2_abs + : public std::unary_function< leda_bigfloat_interval, long > { + long operator()( const leda_bigfloat_interval& x ) const { + CGAL_precondition(!(::boost::numeric::in_zero(x) && + ::boost::numeric::singleton(x))); + return internal::ceil_log2_abs(::boost::numeric::abs(x).upper()); + } + }; + + struct Floor + : public std::unary_function< leda_bigfloat_interval, leda_integer > { + leda_integer operator() ( const leda_bigfloat_interval& x ) + const { + return internal::floor( x.lower() ); + } + }; + + struct Ceil + : public std::unary_function< leda_bigfloat_interval, leda_integer > { + leda_integer operator() ( const leda_bigfloat_interval& x ) + const { + return internal::ceil( x.upper() ); + } + }; +}; + +#endif + +#ifdef CGAL_USE_CORE + +// Specialization for CORE::BigInt +template<> +class Real_embeddable_extension< CORE::BigInt > { +public: + typedef CORE::BigInt Type; + struct Floor_log2_abs + : public std::unary_function< CORE::BigInt, long > { + long operator()( const CORE::BigInt& x ) const { + return CORE::floorLg(x); + } + }; + + struct Ceil_log2_abs + : public std::unary_function< CORE::BigInt, long > { + long operator()( const CORE::BigInt& x ) const { + return CORE::ceilLg(x); + } + }; + + struct Floor + : public std::unary_function< CORE::BigInt, CORE::BigInt > { + CORE::BigInt operator() (const CORE::BigInt& x) const { + return x; + } + }; + struct Ceil + : public std::unary_function< CORE::BigInt, CORE::BigInt > { + CORE::BigInt operator() (const CORE::BigInt& x) const { + return x; + } + }; +}; + +// Specialization for CORE::BigFloat +template<> +class Real_embeddable_extension< CORE::BigFloat > { +public: + typedef CORE::BigFloat Type; + struct Floor_log2_abs + : public std::unary_function< CORE::BigFloat, long > { + long operator()( CORE::BigFloat x ) const { + CGAL_precondition(!CGAL::zero_in(x)); + x = CGAL::abs(x); + return CORE::floorLg(x.m()-x.err())+x.exp()*14; + } + }; + + struct Ceil_log2_abs + : public std::unary_function< CORE::BigFloat, long > { + long operator()( CORE::BigFloat x ) const { + // (already commented out in EXACUS)... + // NiX_precond(!(NiX::in_zero(x) && NiX::singleton(x))); + x = CGAL::abs(x); + return CORE::ceilLg(x.m()+x.err())+x.exp()*14; + } + }; + + struct Floor + : public std::unary_function< CORE::BigFloat, CORE::BigInt > { + CORE::BigInt operator() ( const CORE::BigFloat& x ) const { + CORE::BigInt xi = x.BigIntValue(); + if(x.sign() < 0 && x.cmp(xi)!=0) { + xi--; + } + return xi; + } + }; + + struct Ceil + : public std::unary_function< CORE::BigFloat, CORE::BigInt > { + CORE::BigInt operator() ( const CORE::BigFloat& x ) const { + CORE::BigInt xi = x.BigIntValue(); + if(x.sign() >0 && x.cmp(xi)!=0) { + xi++; + } + return xi; + } + }; + +}; + +#endif // CORE + +#if CGAL_USE_GMP + +// Specialization for Gmpz +template<> +class Real_embeddable_extension< Gmpz > { +public: + typedef Gmpz Type; + + struct Floor_log2_abs + : public std::unary_function< Gmpz, long > { + long operator()( const Gmpz& x ) const { + CGAL_precondition(!CGAL::is_zero(x)); + return mpz_sizeinbase(x.mpz(),2)-1; + } + }; + + struct Ceil_log2_abs + : public std::unary_function< Gmpz, long > { + long operator()( const Gmpz& x ) const { + long pos = mpz_scan1(x.mpz(),0); + long size = mpz_sizeinbase(x.mpz(),2); + if (pos == size-1) + return size-1; + else + return size; + } + }; + + struct Floor + : public std::unary_function< Gmpz, Gmpz > { + Gmpz operator() (const Gmpz& x) const { + return x; + } + }; + struct Ceil + : public std::unary_function< Gmpz, Gmpz > { + Gmpz operator() (const Gmpz& x) const { + return x; + } + }; +}; + +#endif + +#ifdef CGAL_USE_MPFR +template<> +class Real_embeddable_extension< Gmpfr > { +public: + typedef Gmpfr Type; + + struct Floor_log2_abs + : public std::unary_function< Gmpfr, long > { + long operator()( const Gmpfr& x ) const { + Float_traits::Get_mantissa get_mantissa; + Float_traits::Get_exponent get_exponent; + CGAL_precondition(!CGAL::is_zero(x)); + Real_embeddable_extension::Floor_log2_abs floor_log2_abs; + return floor_log2_abs(get_mantissa(x))+get_exponent(x); + } + }; + + struct Ceil_log2_abs + : public std::unary_function< Gmpfr, long > { + long operator()( const Gmpfr& x ) const { + Float_traits::Get_mantissa get_mantissa; + Float_traits::Get_exponent get_exponent; + CGAL_precondition(!CGAL::is_zero(x)); + Real_embeddable_extension::Ceil_log2_abs ceil_log2_abs; + return ceil_log2_abs(get_mantissa(x))+get_exponent(x); + } + }; + + struct Floor + : public std::unary_function< Gmpfr, Gmpz > { + Gmpz operator() ( const Gmpfr& x ) const { + Gmpz result; + mpfr_get_z (result.mpz(),x.fr(),GMP_RNDD); + return result; + } + }; + + struct Ceil + : public std::unary_function< Gmpfr, Gmpz > { + Gmpz operator() ( const Gmpfr& x ) const { + Gmpz result; + mpfr_get_z (result.mpz(),x.fr(),GMP_RNDU); + return result; + } + }; + +}; +#endif + +#ifdef CGAL_USE_MPFI +template<> +class Real_embeddable_extension< Gmpfi > { +public: + typedef Gmpfi Type; + + struct Floor_log2_abs + : public std::unary_function< Gmpfi, long > { + result_type operator() (const argument_type& x) const { + CGAL_precondition(!x.is_zero()); + return internal::floor_log2_abs(x.abs().inf()); + } + }; + + struct Ceil_log2_abs + : public std::unary_function< Gmpfi, long > { + long operator()( const Gmpfi& x ) const { + CGAL_precondition(!x.inf().is_zero() || !x.sup().is_zero()); + return internal::ceil_log2_abs(x.abs().sup()); + } + }; + + struct Floor + : public std::unary_function< Gmpfi, Gmpz > { + Gmpz operator() ( const Gmpfi& x ) + const { + return internal::floor( x.inf() ); + } + }; + + struct Ceil + : public std::unary_function< Gmpfi, Gmpz > { + Gmpz operator() ( const Gmpfi& x ) + const { + return internal::ceil( x.sup() ); + } + }; +}; + +#endif + +} //namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_KERNEL_D_REAL_EMBEDDABLE_EXTENSION_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_roots.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_roots.h new file mode 100644 index 00000000000..884c1b00b10 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Real_roots.h @@ -0,0 +1,299 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// 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 +#include + +#include +#include +#include + + +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 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_precondition_code(mul_end), + AlgebraicRealOutputIterator oi_root, + IntOutputIterator oi_mult){ + + Self real_roots; + typedef std::pair PAIR; + + // find zeroes of each factor and sort them in ascending order + std::priority_queue< PAIR,std::vector,std::greater > pqueue; + std::vector 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(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 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 +int operator()(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 +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 sqffac; + std::list 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 +int operator()(const Real_root_isolator& isolator, + AlgebraicRealOutputIterator it){ + + Polynomial poly = isolator.polynomial(); + //cout << "P: "< 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: "< conjugated_roots; + std::back_insert_iterator > 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 #k 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, as are its factors; + * the roots are of type \c AlgebraicReal ; and the multiplicities are + * of type \c int . + * + */ +template +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 sqffac; + std::list 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 diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_controller.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_controller.h new file mode 100644 index 00000000000..5f0db719fec --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_controller.h @@ -0,0 +1,113 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ACK_SHEAR_CONTROLLER +#define CGAL_ACK_SHEAR_CONTROLLER 1 + +#include + +#include + +namespace CGAL { + + namespace internal { + + /*! + * \brief A class that controls the used shear factors + * + * The objects returns positive integers that are used as shear factors. + * It choses integers from the range \c 1..max at random , + * where \c c is a positive integer + * initially set in the constructor (8 by default). No integer is given + * twice by \c get_shear_factor(), at least if the failed ones are reported + * with the \c report_failure() method. + * If more than half of the integers in the range were bad, the range is + * enlarged to \c 1..2*max. + */ + template + class Shear_controller { + + public: + + //! Constructor, getting the maximal absolute value of the shear factor + Shear_controller() + : m_max(InitialMax) + , pos_next_factor(0) { + CGAL_assertion(m_max>=1); +#if CGAL_ACK_STATIC_SEED + #warning Warning, uses static seed! + srand(CGAL_ACK_STATIC_SEED); +#else + srand(time(NULL)); +#endif + } + + //! Reports that the shear factor \c factor was bad. + void report_failure(Int factor) { + this->bad_shears.insert(factor); + long failures=static_cast(this->bad_shears.size())+1; + if(2*failures>this->m_max) { + this->m_max*=2; + } + + } + + //! Gets a shear factor + Int get_shear_factor() { + if(pos_next_factor==static_cast(value_order().size())) { + value_order().push_back(get_new_shear_factor()); + } + return value_order()[pos_next_factor++]; + } + + private: + + //! Gets a new shear factor + Int get_new_shear_factor() { + CGAL_assertion(int(this->bad_shears.size())& value_order() { + static std::vector value_order_; + return value_order_; + } + + int pos_next_factor; + + // Unsuccesfull shear factors + std::set bad_shears; + + }; + + } // namespace internal +} //namespace CGAL + +#endif // CGAL_ACK_SHEAR_CONTROLLER diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_transformation.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_transformation.h new file mode 100644 index 00000000000..26071dc36f4 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Shear_transformation.h @@ -0,0 +1,1185 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ACK_SHEAR_TRANSFORMATION +#define CGAL_ACK_SHEAR_TRANSFORMATION 1 + +#include + +#include + +#include +#include +#include +#include +#include + +namespace CGAL { + +/*! + * The class is a functor, getting an algebraic curve and some + * shear factor, and returning the sheared curve. + */ +template class Shear_transformation { + +public: + + typedef AlgebraicKernelWithAnalysis_2 Algebraic_kernel_with_analysis_2; + + typedef typename Algebraic_kernel_with_analysis_2::Curve_analysis_2 + Curve_analysis_2; + + typedef typename AlgebraicKernelWithAnalysis_2::Polynomial_traits_2 + Polynomial_traits_2; + + CGAL_ACK_SNAP_ALGEBRAIC_CURVE_KERNEL_2_TYPEDEFS(Curve_analysis_2); + + typedef std::pair Point; + + typedef std::vector< Algebraic_real_1 > Root_container; + + typedef typename Root_container::iterator Root_iterator; + + typedef typename Curve_analysis_2::Event_line_iterator + Status_line_1_iterator; + +private: + + struct Y_structure_element; + + typedef std::list Y_structure; + + // TODO replace by something that we already have + enum Coor_type { MINUS_INFTY,FINITE,PLUS_INFTY}; + +public: + + Shear_transformation(Algebraic_kernel_with_analysis_2* kernel) + : _m_kernel(kernel), + x_extreme_index_counter(0), + disc_roots_computed(false), + sh_disc_roots_computed(false) + {} + + template + void report_sheared_disc_roots(InputIterator begin, + InputIterator end) { + std::copy(begin,end,std::back_inserter(sh_disc_roots)); + sh_disc_roots_computed=true; + } + + Curve_analysis_2 operator() (const Curve_analysis_2& C, Integer s, + bool use_primitive_curve=true) { + Curve_analysis_2 D; + this->operator() (C,s,D,use_primitive_curve); + return D; + } + + void operator() (const Curve_analysis_2& C, Integer s, Curve_analysis_2& D, + bool use_primitive_curve=true) { + this->C=C; + this->s=s; + this->use_primitive_curve = use_primitive_curve; +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Curve_analysis_2: " + << C.polynomial_2() << std::endl; + CGAL_ACK_DEBUG_PRINT << "num events: " + << C.number_of_status_lines_with_event() + << std::endl; + CGAL_ACK_DEBUG_PRINT << "s: " << s << std::endl; +#endif +*/ + x_structure.clear(); + /* + sh_disc_roots.clear(); + x_structure_info.clear(); + + ev_res_roots_mults.clear(); + sh_ev_indices.clear(); + stripe_values.clear(); + pre_vert_lines.clear(); + sh_intermediate_lines.clear(); + */ +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute the polynomials.." << std::flush; +#endif + + if(this->use_primitive_curve) { + pol = C.primitive_polynomial_2(); + } else { + pol=C.polynomial_2(); + } + sh_pol=CGAL::internal::shear(pol,Coefficient(s)); + if(CGAL::degree(typename Polynomial_traits_2 + ::Univariate_content_up_to_constant_factor()( sh_pol ))>0) { + throw CGAL::internal::Non_generic_position_exception(); + } + if(! D.has_defining_polynomial()) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "set f.." << std::flush; +#endif + D.set_f(sh_pol); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done.." << std::flush; +#endif + } + + der_sh_pol = typename Polynomial_traits_2::Differentiate() (sh_pol,1); + sh_der_sh_pol = CGAL::internal::shear(der_sh_pol,Coefficient(-s)); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + Solve_1 solve_1; + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Store the discriminant roots.." + << std::flush; +#endif + + Root_container disc_roots; + for(Status_line_1_iterator it=C.event_begin(); + it!=C.event_end(); + it++) { + disc_roots.push_back(it->x()); + } +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + if(! sh_disc_roots_computed) { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute the sheared discriminant.." + << std::flush; +#endif + + if(typename Polynomial_traits_2::Degree() (sh_pol) > 0) { + + + Polynomial_1 sh_disc + = CGAL::resultant(sh_pol,der_sh_pol); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "root isolation.." << std::flush; +#endif + solve_1(sh_disc,std::back_inserter(sh_disc_roots),false); + + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + sh_disc_roots_computed=true; + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Compute the event resultant.." << std::flush; +#endif + Root_container ev_res_roots; + if(typename Polynomial_traits_2::Degree() (sh_pol) > 0) { + Polynomial_1 ev_res = CGAL::resultant(pol,sh_der_sh_pol); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "root isolation.." << std::flush; +#endif + solve_1(ev_res,std::back_inserter(ev_res_roots),false); + + } + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done, " << ev_res_roots.size() + << " roots found" << std::endl; +#endif + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Merge both root sets..." << std::flush; +#endif + typename CGAL::Real_embeddable_traits::Compare + x_compare; + + CGAL::internal::set_union_with_source + (disc_roots.begin(), + disc_roots.end(), + ev_res_roots.begin(), + ev_res_roots.end(), + std::back_inserter(x_structure), + std::back_inserter(x_structure_info), + x_compare); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; + CGAL_ACK_DEBUG_PRINT << "Take the stripe values..." << std::flush; +#endif + + CGAL::internal::find_intermediate_values + (kernel(), + sh_disc_roots.begin(), + sh_disc_roots.end(), + std::back_inserter(stripe_values)); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; + CGAL_ACK_DEBUG_PRINT << "Search sheared event points..." << std::flush; +#endif + find_sheared_event_points(); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; + CGAL_ACK_DEBUG_PRINT << "Find start- and endpoints for sweep.." + << std::flush; +#endif + find_far_points(D); + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; + CGAL_ACK_DEBUG_PRINT << "Start sweep..." << std::flush; +#endif + + sweep(); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; + CGAL_ACK_DEBUG_PRINT << "vert lines info:" << std::endl; + + for(int i=0;i(pre_vert_lines.size());i++) { + + CGAL_ACK_DEBUG_PRINT << "At: " + << CGAL::to_double(sh_disc_roots[i]) << ", " + << pre_vert_lines[i].number_of_non_event_roots + << " non-event-roots, and " + << pre_vert_lines[i].event_points.size() + << std::endl; + } + CGAL_ACK_DEBUG_PRINT << "Vert_lines.." << std::flush; +#endif + + CGAL_assertion(sh_disc_roots.size()==pre_vert_lines.size()); + std::vector sh_ev_lines; + for(int i=0;i(pre_vert_lines.size());i++) { + sh_ev_lines.push_back(create_event_line(D,i)); + } + D.set_event_lines(sh_ev_lines.begin(),sh_ev_lines.end(), + sh_intermediate_lines.begin(), + sh_intermediate_lines.end()); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + + } + +private: + + // X-coordinate of the shear of p + Bound x_sheared(Point p,Integer sh) { + return p.first-s*p.second; + } + Bound x_sheared(Bound x,Bound y,Integer sh) { + return x-sh*y; + } + + int compute_stripe(Status_line_1& ev, int index) { + int left_index = -1, + right_index = static_cast(stripe_values.size()-1); + Algebraic_real_1 xv = ev.x(); + Bound lx = xv.low(), rx=xv.high(), + x_iv_size = rx-lx; + Bound ly = ev.lower_bound(index), + ry = ev.upper_bound(index);; + while(left_index < right_index) { + if(x_iv_size > ry-ly) { + xv.refine(); + lx = xv.low(); + rx=xv.high(); + x_iv_size=rx-lx; + continue; + } + ev.refine(index); + ly = ev.lower_bound(index); + ry = ev.upper_bound(index); + Bound right(0), left(0); + left = (s>0) ? x_sheared(lx,ry,s) : x_sheared(lx,ly,s); + right = (s>0) ? x_sheared(rx,ly,s) : x_sheared(rx,ry,s); + CGAL_assertion(left(stripe_values.size()); + Bound upper_bound,lower_bound; + Bound left_bound = stripe_values[0], + right_bound=stripe_values[n-1]; + lower_bound = upper_bound = Bound(0); + for(int i=0;i0) { + if(descartes.left_bound(0) upper_bound) { + upper_bound = descartes.right_bound(m-1); + } + } + // Create intermediate line for later use + Algebraic_real_1 xval(curr_bound); + Status_line_1 inter_line(xval,i,D,m); + inter_line.set_isolator(descartes); + sh_intermediate_lines.push_back(inter_line); + } + far_left=(s<0) ? x_sheared(left_bound,upper_bound,-s) + : x_sheared(left_bound,lower_bound,-s)-1; + far_right=(s<0) ? x_sheared(right_bound,lower_bound,-s) + : x_sheared(right_bound,upper_bound,-s)+1; + if(C.number_of_status_lines_with_event()>0) { + if(far_left>C.status_line_at_event(0).x().low()) { + far_left = C.status_line_at_event(0).x().low(); + } + if(far_right + void find_sheared_event_points_at_x(const Status_line_1& ev, + Status_line_1& left, + Status_line_1& right, + OutputIterator out) { + + int ev_id = 0, left_id=0, right_id=0; + int ev_n = ev.number_of_events(), + left_n = left.number_of_events(), + right_n = right.number_of_events(); + (void)left_n; + (void)right_n; + // Simple if a vertical line exists + if(ev.covers_line() && ! use_primitive_curve) { + for(int i=0;ievaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (pol, 0, 1), + left_x); + Polynomial_1 left_sh_der_sh_pol = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (sh_der_sh_pol, 0, 1), + left_x); + + // right side + + + CGAL_assertion(right.x().is_rational()); + Bound right_x = right.x().rational(); + + Polynomial_1 right_pol = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (pol, 0, 1), + right_x); + Polynomial_1 right_sh_der_sh_pol = kernel()->evaluate_utcf_2_object() + (typename Polynomial_traits_2::Swap() (sh_der_sh_pol, 0, 1), + right_x); + + int asym_left_minus,asym_left_plus,asym_right_minus,asym_right_plus; + + typedef typename Status_line_1::Arc_pair Arc_pair; + + Arc_pair apair1 = ev.number_of_branches_approaching_minus_infinity(); + Arc_pair apair2 = ev.number_of_branches_approaching_plus_infinity(); + + asym_left_minus = apair1.first; + asym_right_minus = apair1.second; + + asym_left_plus = apair2.first; + asym_right_plus = apair2.second; + + left_id += asym_left_minus; + right_id += asym_right_minus; + while(ev_id != ev_n) { + + typename Status_line_1::Arc_pair arc_pair = + ev.number_of_incident_branches(ev_id); + + int arcs_left = arc_pair.first; + int arcs_right = arc_pair.second; + if(arcs_left+arcs_right!=2) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Sheared event point found at " + << ev.x().to_double() << ", index " + << ev_id << std::endl; +#endif +*/ + out++=ev_id; + left_id+=arcs_left; + right_id+=arcs_right; + ev_id++; + } + else { + if(arcs_left==1 && arcs_right==1) { + + Algebraic_real_1 left_y(left_pol, + left.lower_bound(left_id), + left.upper_bound(left_id)); + + CGAL::Sign left_sign + = kernel()->sign_at_1_object() + (left_sh_der_sh_pol,left_y,true); + + Algebraic_real_1 right_y(right_pol, + right.lower_bound(right_id), + right.upper_bound(right_id)); + + CGAL::Sign right_sign + = kernel()->sign_at_1_object() + (right_sh_der_sh_pol,right_y,true); + + if(left_sign!=right_sign) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Sheared ev point found at " + << ev.x().to_double() + << ", index " << ev_id + << std::endl; +#endif +*/ + out++=ev_id; + } + ev_id++; + left_id++; + right_id++; + } + else if(arcs_left==2 && arcs_right==0) { + Algebraic_real_1 left_y_1(left_pol, + left.lower_bound(left_id), + left.upper_bound(left_id)); + + CGAL::Sign left_sign_1 + = kernel()->sign_at_1_object() + (left_sh_der_sh_pol,left_y_1,true); + + left_id++; + Algebraic_real_1 left_y_2(left_pol, + left.lower_bound(left_id), + left.upper_bound(left_id)); + CGAL::Sign left_sign_2 + = kernel()->sign_at_1_object() + (left_sh_der_sh_pol,left_y_2,true); + if(left_sign_1!=left_sign_2) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Sheared ev point found at " + << ev.x().to_double() + << ", index " << ev_id + << std::endl; +#endif +*/ + out++=ev_id; + } + ev_id++; + left_id++; + } + else if(arcs_left==0 && arcs_right==2) { + Algebraic_real_1 right_y_1(right_pol, + right.lower_bound(right_id), + right.upper_bound(right_id)); + + CGAL::Sign right_sign_1 + = kernel()->sign_at_1_object() + (right_sh_der_sh_pol,right_y_1,true); + right_id++; + Algebraic_real_1 right_y_2(right_pol, + right.lower_bound(right_id), + right.upper_bound(right_id)); + CGAL::Sign right_sign_2 + = kernel()->sign_at_1_object() + (right_sh_der_sh_pol,right_y_2,true); + if(right_sign_1!=right_sign_2) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Sheared ev point found at " + << ev.x().to_double() + << ", index " << ev_id + << std::endl; +#endif +*/ + out++=ev_id; + } + ev_id++; + right_id++; + } + } + } + left_id += asym_left_plus; + right_id += asym_right_plus; + CGAL_assertion(ev_id==ev_n); + CGAL_assertion(left_id==left_n); + CGAL_assertion(right_id==right_n); + } + + void find_sheared_event_points() { + + sh_ev_indices.resize(x_structure.size()); + std::vector intermediate_values; + find_intermediate_values(kernel(), + x_structure.begin(), + x_structure.end(), + std::back_inserter(intermediate_values)); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "interline.." << std::flush; +#endif +*/ + std::vector intermediate_lines(intermediate_values.size()); + + int i=0; + for(typename std::vector::iterator it + = intermediate_values.begin(); + it!=intermediate_values.end();it++) { + intermediate_lines[i]=C.status_line_at_exact_x(*it); + i++; + } + int event_count=0; +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "at some x.." << std::flush; +#endif +*/ + for(int i=0;i(x_structure.size());i++) { + CGAL::internal::Three_valued info = x_structure_info[i]; +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << i << "th of " << x_structure.size() + << std::endl; + CGAL_ACK_DEBUG_PRINT << "To_double approx" << std::endl; + CGAL_ACK_DEBUG_PRINT << "x_struct: " + << CGAL::to_double(x_structure[i]) + << std::endl; + CGAL_ACK_DEBUG_PRINT << "Info: " << info << std::endl; +#endif +*/ + if(info==CGAL::internal::ROOT_OF_SECOND_SET || + info==CGAL::internal::ROOT_OF_BOTH_SETS) { + const Status_line_1& event_line_at_x = + (info==CGAL::internal::ROOT_OF_BOTH_SETS) + ? C.status_line_at_event(event_count) : C.status_line_at_exact_x(x_structure[i]); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "now really at x.." << std::flush; +#endif +*/ + find_sheared_event_points_at_x(event_line_at_x, + intermediate_lines[i], + intermediate_lines[i+1], + std::back_inserter + (sh_ev_indices[i])); + +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif +*/ + } + if(info==CGAL::internal::ROOT_OF_FIRST_SET || + info==CGAL::internal::ROOT_OF_BOTH_SETS) { + event_count++; + } + } + + CGAL_assertion(event_count==C.number_of_status_lines_with_event()); + } + + struct Sh_ev_point_info { + + Sh_ev_point_info(Status_line_1 ev,int index) + : ev(ev),index(index), + incident_left(0), + incident_right(0) + {} + + Status_line_1 ev; + int index; + int incident_left; + int incident_right; + }; + + struct Sh_ev_line_info { + int asym_left_plus,asym_left_minus,asym_right_plus,asym_right_minus; + int number_of_non_event_roots; + std::vector event_points; + + Bound lower_bound(int i) { + Sh_ev_point_info p= event_points[i]; + return p.ev.lower_bound(p.index); + } + Bound upper_bound(int i) { + Sh_ev_point_info p= event_points[i]; + return p.ev.upper_bound(p.index); + } + void refine(int i) { + Sh_ev_point_info p= event_points[i]; + p.ev.refine(p.index); + } + + int num_arcs_left() { + int sum=0; + sum+=asym_left_plus+asym_left_minus; + sum+=number_of_non_event_roots; + for(int k=0;k(event_points.size());k++) { + sum+=event_points[k].incident_left; + } + return sum; + } + + int num_arcs_right() { + int sum=0; + sum+=asym_right_plus+asym_right_minus; + sum+=number_of_non_event_roots ; + for(int k=0;k(event_points.size());k++) { + sum+=event_points[k].incident_right; + } + return sum; + } + + }; + + struct Y_structure_element { + bool one_event_known; + Coor_type x_type; + int x_index; + Coor_type y_type; + int y_index; + }; + + Y_structure_element create_unbounded_element(Status_line_1& ev, int i) { + int n = static_cast(stripe_values.size()); + int stripe = compute_stripe(ev,i); + Y_structure_element y_el; + y_el.one_event_known=true; + if(stripe==-1) { + y_el.x_type=MINUS_INFTY; + } else if(stripe==n-1) { + y_el.x_type=PLUS_INFTY; + } else { + y_el.x_type=FINITE; + y_el.x_index=stripe; + while((ev.upper_bound(i)>y_in_box) && + (ev.lower_bound(i)(stripe_values.size()); + (void)n; + int stripe = compute_stripe(ev,i); + CGAL_assertion(stripe>=0 && stripe<=n); + Y_structure_element y_el; + y_el.one_event_known=true; + y_el.x_type=FINITE; + y_el.x_index=stripe; + Sh_ev_point_info ev_info(ev,i); + pre_vert_lines[stripe].event_points.push_back(ev_info); + y_el.y_type=FINITE; + y_el.y_index=static_cast + (pre_vert_lines[stripe].event_points.size()-1); + return y_el; + } + + void start_sweep() { + y_structure.clear(); + for(int i=0;i(sh_disc_roots.size());i++) { + Sh_ev_line_info info; + info.number_of_non_event_roots=0; + info.asym_left_plus=info.asym_left_minus= + info.asym_right_plus=info.asym_right_minus=0; + pre_vert_lines.push_back(info); + } +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "X-coordinate (far left) " + << CGAL::to_double(far_left) << std::endl; +#endif +*/ + Status_line_1 far_left_line + = C.status_line_at_exact_x(Algebraic_real_1(far_left)); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "No. arcs " + << far_left_line.number_of_events() << std::endl; +#endif +*/ + for(int i=0;i(y_structure.size())); + + typename Y_structure::iterator y_it=y_structure.begin(); + for(int i=0;i::iterator sh_ev_it = sh_ev_indices[index].begin(); + Status_line_1 ev=C.status_line_at_exact_x(x_structure[index]); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "EV: " << std::endl << ev << std::endl; +#endif +*/ + int ev_id=0, ev_n=ev.number_of_events(); + typename Y_structure::iterator y_it=y_structure.begin(); +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Y-structure has " << y_structure.size() + << " elements" << std::endl; +#endif +*/ + // needed for vertical components + std::vector events_at_x; + bool vert=ev.covers_line() && ! this->use_primitive_curve; + Y_structure_element below,above; + Y_structure_element minus_x_inf,plus_x_inf; + minus_x_inf.one_event_known = plus_x_inf.one_event_known=true; + minus_x_inf.x_type=MINUS_INFTY; + plus_x_inf.x_type = PLUS_INFTY; + below = (s>0) ? plus_x_inf : minus_x_inf; + above = (s>0) ? minus_x_inf: plus_x_inf; + events_at_x.push_back(below); + int minus_left,minus_right,plus_left,plus_right; + + typedef typename Status_line_1::Arc_pair Arc_pair; + + Arc_pair apair1 = ev.number_of_branches_approaching_minus_infinity(); + Arc_pair apair2 = ev.number_of_branches_approaching_plus_infinity(); + + minus_left = apair1.first; + minus_right = apair1.second; + + plus_left = apair2.first; + plus_right = apair2.second; + + for(int i=0;i(events_at_x.size());i++) { + handle_edge(events_at_x[i-1],events_at_x[i]); + } + } + } + + void y_struct_info(Y_structure_element e1, + std::ostream& out) { + if(!e1.one_event_known) { + out << "dummy node with id " << e1.x_index << std::endl; + } else { + if(e1.x_type==MINUS_INFTY) { + out << "Point at -infty" << std::endl; + } else if(e1.x_type==PLUS_INFTY) { + out << "point at +infty" << std::endl; + } else { + out << "point at index" << e1.x_index; + if(e1.y_type==MINUS_INFTY) { + out << " y-coor: -infty" << std::endl; + } else if(e1.y_type==PLUS_INFTY) { + out << " y-coor: +infty" << std::endl; + } else { + out << " y-id: " << e1.y_index << std::endl; + } + + } + } + } + + void handle_edge(Y_structure_element& e1, + Y_structure_element& e2) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Y-STRUCT: " << std::endl; + for(typename Y_structure::iterator it=y_structure.begin(); + it!=y_structure.end();it++) { + y_struct_info(*it,CGAL_ACK_DEBUG_PRINT); + } + CGAL_ACK_DEBUG_PRINT << "Y-STRUCT done" << std::endl; + + CGAL_ACK_DEBUG_PRINT << "handle edge..." << std::flush; + CGAL_ACK_DEBUG_PRINT << "info for e1: "; + y_struct_info(e1,CGAL_ACK_DEBUG_PRINT); + CGAL_ACK_DEBUG_PRINT << "info for e2: "; + y_struct_info(e2,CGAL_ACK_DEBUG_PRINT); +#endif +*/ + if(! e1.one_event_known) { + int id = e1.x_index; + typename Y_structure::iterator it=y_structure.begin(); + while(it!=y_structure.end()) { + if((! it->one_event_known) && it->x_index==id) { + //it=y_structure.erase(it); + //it=y_structure.insert(it,e2); + *it=e2; + } + it++; + } + } else if(! e2.one_event_known) { + int id = e2.x_index; + typename Y_structure::iterator it=y_structure.begin(); + while(it!=y_structure.end()) { + if((! it->one_event_known) && it->x_index==id) { + //it=y_structure.erase(it); + //it=y_structure.insert(it,e1); + *it=e1; + } + it++; + } + } else { + CGAL_assertion(e1.x_type!=e2.x_type || + e1.x_type==FINITE || + e2.x_type==FINITE); + if(e2.x_type==MINUS_INFTY || e1.x_type==PLUS_INFTY) { + handle_edge(e2,e1); + return; + } else if(e1.x_type==FINITE && e2.x_type==FINITE) { + CGAL_assertion(e1.x_index!=e2.x_index); + if(e1.x_index>e2.x_index) { + handle_edge(e2,e1); + return; + } + } + int left_stripe = (e1.x_type==MINUS_INFTY) ? -1 : e1.x_index; + int right_stripe = (e2.x_type==PLUS_INFTY) + ? static_cast(stripe_values.size()-1) : e2.x_index; + for(int i=left_stripe+1;i(x_structure.size());i++) { +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Coordinate.." + << CGAL::to_double(x_structure[i]) + << ", index " << i << std::endl; + CGAL_ACK_DEBUG_PRINT << << "Y-struct before x" << std::endl; + for(typename Y_structure::iterator it=y_structure.begin(); + it!=y_structure.end(); + it++) { + y_struct_info(*it,CGAL_ACK_DEBUG_PRINT); + } + + CGAL_ACK_DEBUG_PRINT << "End of y-struct" << std::endl; +#endif +*/ + sweep_at_x_coordinate(i); + } +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Terminate.." << std::flush; +#endif + end_sweep(); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done" << std::endl; +#endif + } + + Status_line_1 create_event_line(Curve_analysis_2& D,int i) { + Algebraic_real_1 xval = sh_disc_roots[i]; + Bitstream_traits traits(Bitstream_coefficient_kernel(kernel(),xval)); + int number_of_events + = static_cast(pre_vert_lines[i].event_points.size()); + int number_of_roots + = pre_vert_lines[i].number_of_non_event_roots+number_of_events; + Polynomial_2 sh_pol_with_correct_degree + = CGAL::internal::poly_non_vanish_leading_term(kernel(),sh_pol,xval); + Bitstream_descartes descartes(CGAL::internal::Backshear_descartes_tag(), + sh_pol_with_correct_degree, + number_of_roots, + number_of_events, + pre_vert_lines[i], + traits); + typename Status_line_1::Arc_container arc_container; + for(int j=0;j(pre_vert_lines[i].event_points.size()); + int k=0; + while(k=descartes.left_bound(j))) { + break; + } + else { + k++; + } + } + CGAL_assertion(k x_structure_info; + + std::vector > sh_ev_indices; + + std::vector stripe_values; + + Bound far_left, far_right, y_in_box; + + Y_structure y_structure; + + std::vector pre_vert_lines; + + int x_extreme_index_counter; + + std::vector sh_intermediate_lines; + + bool use_primitive_curve; + + bool disc_roots_computed,sh_disc_roots_computed; + +}; + +} //namespace CGAL + +#endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CA_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CA_1.h new file mode 100644 index 00000000000..a0672101ef6 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CA_1.h @@ -0,0 +1,619 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Pavel Emeliyanenko +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H + +#include +#include + +#include +#include +#include + +namespace CGAL { + +namespace internal { + +template < class CurveAnalysis_2, class Rep_ > +class Status_line_CA_1; + +template +std::ostream& operator<< (std::ostream&, + const Status_line_CA_1&); + +#if !CGAL_ACK_USE_EXACUS +template < typename AlgebraicCurveKernel_2 > +class Event_line_builder; + +template < typename AlgebraicCurveKernel_2 > +class Shear_transformation; +#endif + + +template < class AlgebraicCurveKernel_2 > +class Status_line_CA_1_rep { + +public: + + // this template argument + typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2; + + typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 + Curve_analysis_2; + + // myself + typedef Status_line_CA_1_rep Self; + + // type of x-coordinate + typedef typename Curve_analysis_2::Algebraic_real_1 + Algebraic_real_1; + + // type of a curve point + typedef typename Curve_analysis_2::Algebraic_real_2 + Algebraic_real_2; + + // type of bivariate Polynomial + typedef typename Curve_analysis_2::Polynomial_2 + Polynomial_2; + + // an instance of a size type + typedef typename Curve_analysis_2::size_type size_type; + + // encodes number of arcs to the left and to the right + typedef std::pair Arc_pair; + + // container of arcs + typedef std::vector Arc_container; + + // Isolator type + typedef typename Curve_analysis_2::Bitstream_descartes Bitstream_descartes; + + // constructors + + // default constructor () + Status_line_CA_1_rep() + { } + + // constructs status line over interval + Status_line_CA_1_rep( + Algebraic_real_1 x, size_type i, + const Curve_analysis_2& ca, size_type n_arcs) : + _m_kernel(ca.kernel()), + _m_x(x), _m_index(i), _m_ca(ca),/*_m_num_arcs(n_arcs, n_arcs),*/ + _m_total_arcs(n_arcs), _m_vertical_line(false), _m_event(false), + _m_num_arcs_minus_inf(0, 0), _m_num_arcs_plus_inf(0, 0), + _m_xy_coords(n_arcs) { + } + + // constructs status line at events + Status_line_CA_1_rep( + Algebraic_real_1 x, size_type i, + const Curve_analysis_2& ca, + size_type , size_type ) : + _m_kernel(ca.kernel()), + _m_x(x), _m_index(i), _m_ca(ca), + /*_m_num_arcs(n_arcs_left, n_arcs_right),*/ _m_total_arcs(0), + _m_vertical_line(false), _m_event(true), + _m_num_arcs_minus_inf(0, 0), _m_num_arcs_plus_inf(0, 0) { + }; + + //! kernel instance + // TODO remove kernel? + const Algebraic_curve_kernel_2 *_m_kernel; + + //! x-coordinate of event info + mutable Algebraic_real_1 _m_x; + + //! this status line id (# of event or # of interval depending on whether + //! or not this status line encodes an event) + size_type _m_index; + + //! underlying curve analysis + Curve_analysis_2 _m_ca; + + //! number of incident arcs to the left and to the right + //Arc_pair _m_num_arcs; + + //! sequence of arcs crossing this status line (valid only event lines) + mutable boost::optional _m_arcs; + + //! number of arcs intersecting this status line + mutable int _m_total_arcs; + + //! curve has vertical line at this x-coordinate + mutable bool _m_vertical_line; + + //! decsribes an event + mutable bool _m_event; + + //! number of arcs running down the pole + Arc_pair _m_num_arcs_minus_inf; + + //! number of arcs running up the pole + Arc_pair _m_num_arcs_plus_inf; + + /*// matchings valid? + mutable bool matching_valid_; + + // match side arcs to event arcs + mutable std::vector< int > matching_[2]; + + // total number of arcs + int numarcs_at_; + + // arc number of lowest event + int lowest_event_; + + // stores multiplicities + std::vector< int > multiplicities_;*/ + + // stores algebraic real over the vertical line + mutable std::vector >_m_xy_coords; + + // stores the isolator instance + mutable boost::optional isolator; + + // befriending the handle + friend class Status_line_CA_1; + //friend class Curve_analysis_2; + //friend class Event_line_builder; + //friend class Shear_transformation; + +}; + +//! \brief The class provides information about the intersections of a curve +//! with a vertical line at a given finite x-coordinate. +//! +//! Note that a curve can have a vertical line component at this coordinate +//! and non-vertical components may intersect the vertical line respectively. +//! With the help of this class' methods one is able to compute the local +//! topology of the curve at the given vertical line. Note that vertical lines +//! at x = +/-oo are not allowed, since different events (curve ends going to +//! infinity with different non-horizontal asymptotes) would have equal +//! y-coordinate (+/-oo), which confuses more than it helps. Note in addition +//! that curve ends approaching the vertical asymptote introduce an event +//! (depending on whether approaching +oo or -oo - but the event with +//! coordinates (x,?oo), resp. (x,+oo), occur only once, if they occur, and +//! they imply not to be associated with a instance of \c Algebraic_real_2. +template > +class Status_line_CA_1 + : public ::CGAL::Handle_with_policy< Rep_ > { +public: + //!@{ + //!\name typedefs + + //! this instance's first template parameter + //! model of AlgebraicKernel_d_2 + typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2; + + typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 Curve_analysis_2; + + //! this instance's second template parameter + typedef Rep_ Rep; + + //! this instance itself + typedef Status_line_CA_1 Self; + + //! type of x-coordinate + typedef typename Curve_analysis_2::Algebraic_real_1 Algebraic_real_1; + + //! type of a curve point + typedef typename Curve_analysis_2::Algebraic_real_2 Algebraic_real_2; + + //! an instance of a size type + typedef typename Curve_analysis_2::size_type size_type; + + //! encodes number of arcs to the left and to the right + typedef std::pair Arc_pair; + + //! container of arcs + typedef std::vector Arc_container; + + //! Local isolator type + typedef typename Rep::Bitstream_descartes Bitstream_descartes; + + //! the handle superclass + typedef ::CGAL::Handle_with_policy< Rep > Base; + + //!@} +public: + //!\name constructors + //!@{ + + /*!\brief + * Default constructor + */ + Status_line_CA_1() : + Base(Rep()) { + } + + /*!\brief + * copy constructor + */ + Status_line_CA_1(const Self& p) : + Base(static_cast(p)) { + } + + /*!\brief + * constructs a status line over the \c i-th interval with x-coordinate + * \c x + * + * \c n_arcs defines # of curve arcs over the interval + * + * \pre specified x-coordinate belongs to \c i-th interval + */ + Status_line_CA_1( + Algebraic_real_1 x, size_type i, const Curve_analysis_2& ca, + size_type n_arcs) : + Base(Rep(x, i, ca, n_arcs)) { + + CGAL_precondition(n_arcs >= 0); + CGAL_precondition_code( + bool is_event; + size_type idx; + ca.x_to_index(x, idx, is_event); + CGAL_precondition(!is_event && idx == i); + ); + } + + + /*!\brief + * constructs a status line at the event with x-coorinate \c x + * + * \c arcs container defines # of incident arcs to the left and to the + * right of each intersection point of the curve \c ca with this status + * line, sorted by y-s in ascending order. + * \c n_arcs_left and \c n_arcs_right specify total number of incident + * arcs to the left and to the right respectively. + * \c has_v_line specifies whether the curve has a vertical line as a + * component at this x-coordinate + * + * \pre there is a curve event at specified x-coordinate + */ + Status_line_CA_1(Algebraic_real_1 x, + size_type i, const Curve_analysis_2& ca, + size_type n_arcs_left, size_type n_arcs_right, + Arc_container arcs, bool has_v_line = false) : + Base(Rep(x, i, ca, n_arcs_left, n_arcs_right)) { + + CGAL_precondition(n_arcs_left >= 0 && n_arcs_right >= 0); + CGAL_precondition_code( + bool is_event; + size_type idx; + ca.x_to_index(x, idx, is_event); + CGAL_precondition(idx == i); + ); + _set_arcs(arcs); + if(has_v_line) + _set_v_line(); + } + + /*!\brief + * constructs a status line at the event with x-coorinate \c x + * + * arcs and vertical line flag can be set later + */ + Status_line_CA_1(Algebraic_real_1 x, + size_type i, const Curve_analysis_2& ca, + size_type n_arcs_left, size_type n_arcs_right) : + Base(Rep(x, i, ca, n_arcs_left, n_arcs_right)) { + + CGAL_precondition(n_arcs_left >= 0 && n_arcs_right >= 0); + CGAL_precondition_code( + bool is_event; + size_type idx; + ca.x_to_index(x, idx, is_event); + CGAL_precondition(idx == i); + ); + } + + /*!\brief + * constructs from a given represenation + */ + Status_line_CA_1(Rep rep) : + Base(rep) { + } + + //!@} +public: + //!\name access functions + //!@{ + + /*! \brief + * returns the x-coordinate of the status line (always a finite value) + */ + Algebraic_real_1 x() const { + return this->ptr()->_m_x; + } + + /*! \brief + * returns this status line CurveAnalysis_2 object + */ + Curve_analysis_2 curve_analysis_2() const { + return this->ptr()->_m_ca; + } + + /*! \brief + * returns this status line index (event or interval index) + */ + size_type index() const { + return this->ptr()->_m_index; + } + + /*! \brief + * returns \c true in case the given curve contains the status line + * as a component + */ + bool covers_line() const { + return this->ptr()->_m_vertical_line; + } + + /*!\brief + * returns \c true if the curve f has intersection with f_y at x + */ + bool has_f_fy_intersection() const { + return (is_event() && !covers_line()); + } + + /*! \brief + * returns \c true if one of \c covers_line of \c has_f_fy_intersection + * evaluates to \c true + */ + bool is_event() const { + return this->ptr()->_m_event; + } + + /*! \brief + * returns \c true if the ith point is an event point + */ + bool is_event(size_type i) const { + // TODO: Make it possible to detect singularities as well + Arc_pair branches = number_of_incident_branches(i); + return branches.first!=1 || branches.second!=1; + } + + + /*! \brief + * returns number of distinct and finite intersections of a curve with a + * (intended) vertical line ignoring a real vertical line component of the + * curve at the given x-coordinate. + */ + size_type number_of_events() const { + return this->ptr()->_m_total_arcs; + } + + /*!\brief + * returns \c Algebraic_real_2 for j-th event over this vert line + * + * \pre 0 <= j < num_of_events() + */ + Algebraic_real_2 algebraic_real_2(size_type j) const + { + CGAL_precondition(0 <= j&&j < number_of_events()); + if(!this->ptr()->_m_xy_coords[j]) + this->ptr()->_m_xy_coords[j] = Algebraic_real_2(x(), + this->ptr()->_m_ca, j); + return *(this->ptr()->_m_xy_coords[j]); + } + + /*!\brief + * alias for \c get_algebraic_real_2() + */ + Algebraic_real_2 xy_coordinate_2(size_type j) const { + return algebraic_real_2(j); + } + + /*!\brief + * returns the number of branches of the curve connected to j-th + * event immediately to the left, to the right, respectively, as a pair of + * unsigned int ignoring vertical curve components at the given + * x-coordinate. + * + * \pre 0 <= j < num_of_events() + */ + Arc_pair number_of_incident_branches(int j) const { + + CGAL_precondition(0 <= j&&j < number_of_events()); + if(!is_event()) + return Arc_pair(1, 1); + + return (*(this->ptr()->_m_arcs))[j]; + } + + /*! \brief + * returns the number of vertical asymptotes at x of the curve + * approaching y=-oo from left and right. A vertical line being component + * of the curve is ignored. + */ + const Arc_pair& number_of_branches_approaching_minus_infinity() const { + return this->ptr()->_m_num_arcs_minus_inf; + } + + /*! \brief + * returns the number of vertical asymptotes at x of the curve + * approaching y=+oo from left and right. A vertical line being component + * of the curve is ignored. + */ + const Arc_pair& number_of_branches_approaching_plus_infinity() const { + return this->ptr()->_m_num_arcs_plus_inf; + } +protected: + Algebraic_curve_kernel_2* kernel() const { + return this->ptr()->_m_kernel; + } + + + //!@} +public: + //!@{ + + /*!\brief + * sets # of arcs running from left and right to -inf and +inf at vertical + * asymptote + */ + void _set_number_of_branches_approaching_infinity( + const Arc_pair& minus_inf, const Arc_pair& plus_inf) { + + CGAL_precondition(minus_inf.first >= 0 && minus_inf.second >= 0); + CGAL_precondition(plus_inf.first >= 0 && plus_inf.second >= 0); + + this->ptr()->_m_num_arcs_minus_inf = minus_inf; + this->ptr()->_m_num_arcs_plus_inf = plus_inf; + + if(!this->ptr()->_m_event) + this->ptr()->_m_event = (minus_inf.first + minus_inf.second + + plus_inf.first + plus_inf.second > 0); + } + + void _set_arcs(const Arc_container& arcs) const { + CGAL_precondition(is_event()); + this->ptr()->_m_arcs = arcs; + this->ptr()->_m_total_arcs = static_cast(arcs.size()); + this->ptr()->_m_xy_coords.resize(arcs.size()); + } + + void _set_v_line() const { + CGAL_precondition(is_event()); + this->ptr()->_m_vertical_line = true; + } + + //!@} + //!\name IO + //!@{ + + void write(std::ostream& os) const { + + os << "status_line [CA@" << this->ptr()->_m_ca.id() << std::flush; +#if CGAL_ACK_USE_EXACUS + os << "; x = " << x() << "; #events: " << number_of_events() << "; " + << std::flush; +#else + os << "; x = " << CGAL::to_double(x()) << "; #events: " + << number_of_events() << "; " << std::flush; +#endif + + + if(is_event()) { + os << "incident branches: {" << std::flush; + typename Arc_container::const_iterator ait = + (*this->ptr()->_m_arcs).begin(); + for(int i = 0; i < number_of_events(); i++) { + + Arc_pair arc_pair = number_of_incident_branches(i); + + if(i!=0) { + os << ", " << std::flush; + } + Algebraic_real_2 xy = algebraic_real_2(i); + typedef typename Bitstream_descartes::Bound Bound; + Bound th = CGAL::ipower(Bound(1,2),53); + std::pair d_pair + = xy.to_double(); + os << "y=" << d_pair.second << ", " << std::flush; + os << "(" << arc_pair.first << ", " << arc_pair.second << ")" + << std::flush; + } + os << "}"; + Arc_pair p = number_of_branches_approaching_minus_infinity(); + if(p.first + p.second > 0) + os << "; approaching -oo: (" << p.first << "; " << + p.second << ")" << std::flush; + p = number_of_branches_approaching_plus_infinity(); + if(p.first + p.second > 0) + os << "; approaching +oo: (" << p.first << "; " << + p.second << ")" << std::flush; + if(covers_line()) + os << "; covers line" << std::flush; + } else + os << "interval line" << std::flush; + + os << "]" << std::flush; + } + + //!@} + + //! Sets the isolator instance + void set_isolator (const Bitstream_descartes& isolator) const { + this->ptr()->isolator = isolator; + } + + //! Returns the isolator instance + Bitstream_descartes& isolator() const { + CGAL_assertion(this->ptr()->isolator); + return this->ptr()->isolator.get(); + } + + //! Returns whether an isolator has been given for that status line + bool has_isolator() const { + return this->ptr()->isolator; + } + + typename Bitstream_descartes::Bound lower_bound(int index) const { + return isolator().left_bound(index); + } + + typename Bitstream_descartes::Bound upper_bound(int index) const { + return isolator().right_bound(index); + } + + typename Bitstream_descartes::Bound interval_length(int index) const { + return isolator().right_bound(index)- + isolator().left_bound(index); + } + + int get_upper_bound_for_multiplicity(int index) const { + return isolator().get_upper_bound_for_multiplicity(index); + } + + void refine(int index) const { + return isolator().refine_interval(index); + } + + void refine_to(int index, typename Bitstream_descartes::Bound b) { + while(upper_bound(index) - lower_bound(index) > b) { + refine(index); + } + } + + + //! these are our friends + //friend class Curve_analysis_2; + +}; // class Status_line_CA_1 + +template +std::ostream& operator<< ( + std::ostream& os, + const internal::Status_line_CA_1& line) { + + line.write(os); + return os; +} + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CA_1_H + diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CPA_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CPA_1.h new file mode 100644 index 00000000000..0bad3aa4309 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Status_line_CPA_1.h @@ -0,0 +1,493 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Pavel Emeliyanenko +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H + +#include +#include +#include + +namespace CGAL { + +namespace internal { + +template < class CurvePairAnalysis_2, class Rep_ > +class Status_line_CPA_1; + +template +std::ostream& operator<< (std::ostream&, + const Status_line_CPA_1&); + +template < class CurvePairAnalysis_2 > +class Status_line_CPA_1_rep { + + // this template argument + typedef CurvePairAnalysis_2 Curve_pair_analysis_2; + + // myself + typedef Status_line_CPA_1_rep Self; + + // type of x-coordinate + typedef typename Curve_pair_analysis_2::Algebraic_real_1 + Algebraic_real_1; + + // type of a curve point + typedef typename Curve_pair_analysis_2::Algebraic_real_2 + Algebraic_real_2; + + // an instance of a size type + typedef typename Curve_pair_analysis_2::size_type size_type; + + // encodes number of arcs to the left and to the right + typedef std::pair Arc_pair; + + // container of arcs + typedef std::vector Arc_container; + + // container of integers ? + typedef std::vector Int_container; + + // constructors +public: + // default constructor () + Status_line_CPA_1_rep() + { } + + // constructs an empty status line object + Status_line_CPA_1_rep(size_type i, Curve_pair_analysis_2 cpa) : + _m_index(i), _m_cpa(cpa), _m_event(false), _m_intersection(false) { + } + + // stores this status line interval or event index of a curve pair + size_type _m_index; + + // represents x-coordinate of event of rational value over interval + // computed only by demand + mutable boost::optional _m_x; + + // for each event point stores a pair of arcnos of the 1st and 2nd curve + // or -1 if respective curve is not involved + mutable Arc_container _m_arcs; + + // inverse mapping from arcnos of the 1st and 2nd curve to respective + // y-position + mutable Int_container _m_arcno_to_pos[2]; + + // stores multiplicities of intersection points (-1 if there is no 2-curve + // intersection) + mutable Int_container _m_mults; + + // underlying curve pair analysis + Curve_pair_analysis_2 _m_cpa; + + // is there an event + mutable bool _m_event; + + // is there is an intersection of both curves + mutable bool _m_intersection; + + // befriending the handle + friend class Status_line_CPA_1; +}; + +//! \brief The class provides information about the intersections of a pair of +//! curves with a (intended) vertical line (ignoring vertical lines of the +//! curves themselves). +//! +//! Each intersection of a curve with the vertical line defined by some given x +//! induces an event. An event can be asked for its coordinates +//! (\c Algebraic_real_2) and the involved curve(s). Note that the involvement +//! also holds for curve ends approaching the vertical asymptote. +//! Curve_pair_vertical_line_1 at x = +/-oo are not allowed. +template > +class Status_line_CPA_1 : + public ::CGAL::Handle_with_policy< Rep_ > +{ +public: + //!@{ + //!\name typedefs + + //! this instance's first template parameter + typedef CurvePairAnalysis_2 Curve_pair_analysis_2; + + //! this instance's second template parameter + typedef Rep_ Rep; + + //! this instance itself + typedef Status_line_CPA_1 Self; + + //! type of x-coordinate + typedef typename Curve_pair_analysis_2::Algebraic_real_1 Algebraic_real_1; + + //! type of a curve point + typedef typename Curve_pair_analysis_2::Algebraic_real_2 Algebraic_real_2; + + //! an instance of a size type + typedef typename Curve_pair_analysis_2::size_type size_type; + + //! encodes number of arcs to the left and to the right + typedef std::pair Arc_pair; + + //! container of arcs + typedef std::vector Arc_container; + + //! container of integers ? + typedef std::vector Int_container; + + //! the handle superclass + typedef ::CGAL::Handle_with_policy< Rep > Base; + + //!@} +public: + //!\name constructors + //!@{ + + /*!\brief + * Default constructor + */ + Status_line_CPA_1() : + Base(Rep()) { + } + + /*!\brief + * copy constructor + */ + Status_line_CPA_1(const Self& p) : + Base(static_cast(p)) { + } + + /*!\brief + * constructs undefined status line + */ + Status_line_CPA_1(size_type i, Curve_pair_analysis_2 cpa) : + Base(Rep(i, cpa)) { + } + + /*!\brief + * constructs a status line at the \c i -th event of a curve pair + * + * each element of \c arcs is a pair with the first item specifying the + * type of event (0 - event of the 1st curve, 1 - of the second curve, + * 2 - of both curves), and the second item - multiplicity of intersection + * or -1 if not available + */ + Status_line_CPA_1(size_type i, const Arc_container& arcs, + Curve_pair_analysis_2 cpa) : + Base(Rep(i, cpa)) { + _set_event_arcs(arcs); + } + + /*!\brief + * constructs a status line over the \c i -th interval of a curve pair + * + * each element of \c arcs specifies to which curve a respective arc + * belongs to (0 - arc of the 1st curve, 1 - arc of the 2nd curve) + * \c is_swapped defines that the curves in targeting curve pair analysis + * were swapped during precaching + */ + Status_line_CPA_1(size_type i, const Int_container& arcs, + Curve_pair_analysis_2 cpa) : + Base(Rep(i, cpa)) { + _set_interval_arcs(arcs); + } + +protected: + /*!\brief + * constructs from a given represenation + */ + Status_line_CPA_1(Rep rep) : + Base(rep) { + } + + //!@} +public: + //!\name access functions + //!@{ + + /*! \brief + * returns the x-coordinate of the vertical line (always a finite value). + */ + Algebraic_real_1 x() const { + // unless x-coordiate was explicitly set with _set_x: compute its value + if(!this->ptr()->_m_x) { + this->ptr()->_m_x = (is_event() ? +#if CGAL_ACK_USE_EXACUS + this->ptr()->_m_cpa._internal_curve_pair().event_x(index()) : + Algebraic_real_1(this->ptr()->_m_cpa._internal_curve_pair(). + bound_value_in_interval(index()))); +#else + this->ptr()->_m_cpa.event_x(index()) : + Algebraic_real_1(this->ptr()->_m_cpa. + bound_value_in_interval(index()))); +#endif + } + return *(this->ptr()->_m_x); + } + + //! returns this vertical line's index (event or interval index) + size_type index() const { + CGAL_precondition(this->ptr()->_m_index>=0); + return this->ptr()->_m_index; + } + + /*! \brief + * returns number of distinct and finite intersections of a pair + * of curves with a (intended) vertical line ignoring a real vertical + * line component of the curve at the given x-coordinate. + */ + size_type number_of_events() const { + return this->ptr()->_m_arcs.size(); + } + + + /*! \brief + * returns the y-position of the k-th event of + * the curve in the sequence of events. + * + * Note that each event is formed by the 1st, 2nd, or both curves + * + * \pre 0 <= k < "number of arcs defined for curve c at x()" + */ + size_type event_of_curve(size_type k, + const typename Curve_pair_analysis_2 + ::Curve_analysis_2& c) const { + CGAL_assertion(c.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| + c.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); + bool b = (c.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); + return event_of_curve(k,b); + } + + + + + /*! \brief + * returns the y-position of the k-th event of the c-th (0 or 1) + * curve in the sequence of events. + * + * Note that each event is formed by the 1st, 2nd, or both curves + * + * \pre 0 <= k < "number of arcs defined for curve[c] at x()" + */ + size_type event_of_curve(size_type k, bool c) const { + + CGAL_precondition_msg(0 <= k && + k < static_cast(this->ptr()->_m_arcno_to_pos[c].size()), + "Invalid arc number of the c-th curve specified"); + return this->ptr()->_m_arcno_to_pos[c][k]; + } + + /*! \brief + * returns the multiplicity of intersection defined at event with + * position \c j. May return -1 in case multiplicity is unknown. + * + * \pre There is an intersection of both curves at j-th event + * \pre 0 <= j < number_of_events() + */ + size_type multiplicity_of_intersection(size_type j) const + { + CGAL_precondition(0 <= j && j < number_of_events()); + CGAL_precondition(is_intersection()); + CGAL_precondition(this->ptr()->_m_arcs[j].first != -1 && + this->ptr()->_m_arcs[j].second != -1); + + return this->ptr()->_m_mults[j]; + } + + /*! \brief + * returns a pair of \c int indicating whether event \c j is formed + * by which arc numbers of the first and the second curve, or -1, if the + * corresponding curve is not involved. + * + * \pre 0 <= j < number_of_events() + */ + Arc_pair curves_at_event(size_type j) const + { + CGAL_precondition(0 <= j && j < number_of_events()); + const Arc_pair& arc = this->ptr()->_m_arcs[j]; + return arc; + } + + /*! + * returns an index indicating whether event \c j is formed + * by which arc numbers of the curve \c ca, or -1, if the + * corresponding curve is not involved. + */ + Arc_pair curves_at_event(size_type j, + const typename Curve_pair_analysis_2 + ::Curve_analysis_2& c1, + const typename Curve_pair_analysis_2 + ::Curve_analysis_2& CGAL_precondition_code(c2)) const + { + + CGAL_precondition(0 <= j && j < number_of_events()); + CGAL_assertion(c1.id()!=c2.id()); + CGAL_assertion + (c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| + c1.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); + CGAL_assertion + (c2.id()==this->ptr()->_m_cpa.curve_analysis(false).id()|| + c2.id()==this->ptr()->_m_cpa.curve_analysis(true).id()); + bool b = (c1.id()==this->ptr()->_m_cpa.curve_analysis(false).id()); + const Arc_pair& arc_pair = curves_at_event(j); + return b ? arc_pair : std::make_pair(arc_pair.second, arc_pair.first); + } + + /*! \brief + * returns true if a curve has an event or in case there is an + * intersection of both curves. + */ + bool is_event() const { + return this->ptr()->_m_event; + } + + /*! \brief + * returns true if there is an intersection of both curves. + */ + bool is_intersection() const { + return this->ptr()->_m_intersection; + } + + //!@} +public: + //!@{ + + /*!\brief + * sets x-coordinate of a status line + */ + void _set_x(Algebraic_real_1 x) const { + this->ptr()->_m_x = x; + } + + /*!\brief + * sets arcs at event (use at your own risk!) + */ + void _set_event_arcs(const Arc_container& arcs) const { + + size_type k = 0, arcf = 0, arcg = 0; + this->ptr()->_m_arcs.resize(arcs.size()); + this->ptr()->_m_mults.resize(arcs.size()); + this->ptr()->_m_event = true; + + for(typename Arc_container::const_iterator ait = arcs.begin(); + ait != arcs.end(); ait++, k++) { + + if(ait->first == 0) { // 1st curve + this->ptr()->_m_arcs[k].first = arcf++; + this->ptr()->_m_arcs[k].second = -1; + this->ptr()->_m_arcno_to_pos[0].push_back(k); + + } else if(ait->first == 1) { // 2nd curve + this->ptr()->_m_arcs[k].first = -1; + this->ptr()->_m_arcs[k].second = arcg++; + this->ptr()->_m_arcno_to_pos[1].push_back(k); + + } else if(ait->first == 2) { // intersection + this->ptr()->_m_arcs[k].first = arcf++; + this->ptr()->_m_arcs[k].second = arcg++; + this->ptr()->_m_arcno_to_pos[0].push_back(k); + this->ptr()->_m_arcno_to_pos[1].push_back(k); + this->ptr()->_m_intersection = true; + + } else + CGAL_error_msg("Bogus curve index.."); + this->ptr()->_m_mults[k] = ait->second; + } + } + + /*!\brief + * sets arcs over interval (use at your own risk!) + */ + void _set_interval_arcs(const Int_container& arcs) const { + + this->ptr()->_m_arcs.resize(arcs.size()); + this->ptr()->_m_event = false; + this->ptr()->_m_intersection = false; + + size_type k = 0, arcf = 0, arcg = 0; + for(typename Int_container::const_iterator ait = arcs.begin(); + ait != arcs.end(); ait++, k++) { + if(*ait == 0) { // 1st curve + this->ptr()->_m_arcs[k].first = arcf++; + this->ptr()->_m_arcs[k].second = -1; + this->ptr()->_m_arcno_to_pos[0].push_back(k); + + } else if(*ait == 1) { // 2nd curve + this->ptr()->_m_arcs[k].first = -1; + this->ptr()->_m_arcs[k].second = arcg++; + this->ptr()->_m_arcno_to_pos[1].push_back(k); + + } else + CGAL_error_msg("Bogus curve index.."); + } + } + + //!@} +public: + //!\name IO + //!@{ + + void write(std::ostream& os) const { + + os << "status_line [CPA@" << this->ptr()->_m_cpa.id(); + + os << "; x = " << (index()==-1 ? 999.999 : CGAL::to_double(x())) << "; #events: " << number_of_events() << "; "; + + typename Arc_container::const_iterator ait = + this->ptr()->_m_arcs.begin(); + if(is_event()) + os << "arcs at event: {"; + else + os << "arcs of interval: {"; + + for(; ait != this->ptr()->_m_arcs.end(); ait++) { + if(ait != this->ptr()->_m_arcs.begin()) + os << ", "; + os << "(" << ait->first << "; " << ait->second << ")"; + } + os << "}, arcno2pos: ("; + + CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[0].begin(), + this->ptr()->_m_arcno_to_pos[0].end(), ","); + os << "), ("; + CGAL::output_range(os, this->ptr()->_m_arcno_to_pos[1].begin(), + this->ptr()->_m_arcno_to_pos[1].end(), ","); + os << ")]"; + } + + //!@} +}; // class Status_line_CPA_1 + +template +std::ostream& operator<< (std::ostream& os, + const internal::Status_line_CPA_1& sline) { + + sline.write(os); + return os; +} + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_STATUS_LINE_CPA_1_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Xy_coordinate_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Xy_coordinate_2.h new file mode 100644 index 00000000000..15b135e2e3f --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/Xy_coordinate_2.h @@ -0,0 +1,781 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Eric Berberich +// Pavel Emeliyanenko +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H +#define CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H + +#include +#include +#include + +#include + +#include + +namespace CGAL { + +namespace internal { + +template < class AlgebraicCurveKernel_2, class Rep_, + class HandlePolicy_ , + class Allocator_> + //::boost::fast_pool_allocator > +class Xy_coordinate_2; + + +template < class AlgebraicCurveKernel_2 > +class Xy_coordinate_2_rep { + +public: + // this first template argument + typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2; + + // myself + typedef Xy_coordinate_2_rep Self; + + typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 + Curve_analysis_2; + + typedef typename Algebraic_curve_kernel_2::Algebraic_real_1 + Algebraic_real_1; + + typedef CGAL::Bbox_2 Bbox_2; + + typedef CGAL::Handle_with_policy + Xy_coordinate_2_inst; + + // constructors +public: + // default constructor () + Xy_coordinate_2_rep() : _m_arcno(-1) { + } + + // standard constructor + Xy_coordinate_2_rep(const Algebraic_real_1& x, + const Curve_analysis_2& curve, int arcno) + : _m_kernel(curve.kernel()),_m_x(x), _m_curve(curve), _m_arcno(arcno) { + } + + // data + + const Algebraic_curve_kernel_2* _m_kernel; + + // x-coordinate + Algebraic_real_1 _m_x; + + // supporting curve + mutable Curve_analysis_2 _m_curve; + + // arc number on curve + mutable int _m_arcno; + + // y-coordinate + mutable boost::optional< Algebraic_real_1 > _m_y; + + //! A bounding box for the given point + mutable boost::optional< std::pair > _m_bbox_2_pair; + +}; + +//! \brief class \c Xy_coordinate_2 represents a single root of a system of +//! two polynomial equations in two variables that are models +//! \c AlgebraicCurveKernel_2::Polynomial_2 +//! +//! \c Xy_coordinate_2 coordinate is represented by an \c Algebraic_real_1, +//! a supporting curve and an arcno and is valid only for finite solutions, +//! i.e., it cannot represent points at infinity +template , + class HandlePolicy_= CGAL::Handle_policy_union, + class Allocator_ = CGAL_ALLOCATOR(Rep_) > +class Xy_coordinate_2 : + public ::CGAL::Handle_with_policy +{ +public: + //! \name public typedefs + //!@{ + + //! this instance's first template parameter + typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2; + + //! this instance's second template parameter + typedef Rep_ Rep; + + //! this instance's third template parameter + typedef HandlePolicy_ Handle_policy; + + //! this instance's fourth template parameter + typedef Allocator_ Allocator; + + //! this instance itself + typedef Xy_coordinate_2 Self; + + //! an instance of AlgebraicKernel_1 + typedef typename Algebraic_curve_kernel_2::Algebraic_kernel_d_1 + Algebraic_kernel_d_1; + + typedef typename Algebraic_curve_kernel_2::Polynomial_1 Polynomial_1; + typedef CGAL::Polynomial_traits_d Polynomial_traits_1; + + typedef typename Algebraic_curve_kernel_2::Polynomial_2 Polynomial_2; + typedef CGAL::Polynomial_traits_d Polynomial_traits_2; + + //! type of (explicit) x- and y-coordinates + typedef typename Algebraic_curve_kernel_2::Algebraic_real_1 + Algebraic_real_1; + + //! Coefficient type + typedef typename Algebraic_curve_kernel_2::Coefficient Coefficient; + + //! type of curve pair analysis + typedef typename Algebraic_curve_kernel_2::Curve_pair_analysis_2 + Curve_pair_analysis_2; + + //! type of curve analysis + typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 + Curve_analysis_2; + + //! the handle superclass + typedef ::CGAL::Handle_with_policy Base; + + //! type for approximation boundaries + typedef typename Algebraic_curve_kernel_2::Bound Bound; + + //! type for bound intervals + typedef boost::numeric::interval Bound_interval; + + //! Type for the bounding box + typedef typename Rep::Bbox_2 Bbox_2; + + //!@} +private: + //! \name private methods + //!@{ + + /*!\brief + * Simplifies the representation of two points whose supporting curves + * share a common part. + */ + bool _simplify(const Xy_coordinate_2& p, const Xy_coordinate_2& q) const + { + std::vector parts_of_f, parts_of_g, common; + + if(kernel()->decompose_2_object()(p.curve(), q.curve(), + std::back_inserter(parts_of_f), std::back_inserter(parts_of_g), + std::back_inserter(common))) { + + CGAL_assertion((parts_of_f.size() == 1 || + parts_of_g.size() == 1) && common.size() == 1); + if(parts_of_f.size() == 1) { + p.simplify_by(kernel()->construct_curve_pair_2_object()( + parts_of_f[0], common[0])); + } + + if(parts_of_g.size() == 1) { + q.simplify_by(kernel()->construct_curve_pair_2_object()( + parts_of_g[0], common[0])); + } + return true; + } + return false; + } + + //!@} +public: + //!\name Constructors + //!@{ + + /*!\brief + * default constructor + * + * A default-constructed point supports no operation other than + * having \c CGAL::degree(curve()) return \c -1. + */ + Xy_coordinate_2() : + Base(Rep()) { + } + + /*!\brief + * copy constructor + */ + Xy_coordinate_2(const Self& p) : + Base(static_cast(p)) { + } + + /*!\brief + * Point at \c x, on \c curve with \c arcno. Finite points on vertical arcs + * are also constructed in this way + */ + Xy_coordinate_2(const Algebraic_real_1& x, const Curve_analysis_2& curve, + int arcno) : + Base(Rep(x, curve, arcno)) { + + CGAL_precondition(arcno >= 0); + CGAL_precondition_code( + typename Curve_analysis_2::Status_line_1 v = + curve.status_line_for_x(x); + ); + CGAL_precondition(arcno >= 0 && arcno < v.number_of_events()); + } + + /*!\brief + * constructs a point from a given represenation + */ + Xy_coordinate_2(Rep rep) : + Base(rep) { + } + + //!@} +public: + //!\name Access functions + //!@{ + + /*!\brief + * x-coordinate of the point + */ + const Algebraic_real_1& x() const { + return this->ptr()->_m_x; + } + + /*! + * \brief y-coordinate of this point + * + * Note: In general, this method results in a extremly large polynomial + * for the y-coordinate. It is recommended to use it carefully, + * and using get_approximation_y() instead whenever approximations suffice. + */ + Algebraic_real_1 y() const { + + typedef std::vector< Algebraic_real_1 > Roots; + typedef typename Curve_analysis_2::Status_line_1 Key; + typedef Roots Data; + typedef std::map< Key, Data, CGAL::Handle_id_less_than< Key > > + Y_root_map; + + static Y_root_map y_root_map; + + if (!this->ptr()->_m_y) { + + Polynomial_2 f = curve().primitive_polynomial_2(); + // This will be the defining polynomial of y + Polynomial_1 y_pol; + + // Filter: If we know that the point is critical, we can use + // the resultant of f and f_y with respect to x as polynomial + bool point_is_certainly_critical = false; + typename Curve_analysis_2::Status_line_1 line = + curve().status_line_at_exact_x(x()); + + typename Y_root_map::iterator yit = + y_root_map.find(line); + + // TODO: Cache resultant computation + // exacus-related code shouldn't be used here + //curve().x_to_index(x(),i,is_event); + if (line.is_event()) { + //typename Internal_curve_2::Event1_info ev_info = + // curve().event_info(i); + typename Curve_analysis_2::Status_line_1::Arc_pair ipair = + line.number_of_incident_branches(arcno()); + + if (ipair.first != 1 || ipair.second != 1) { + point_is_certainly_critical = true; + y_pol = CGAL::make_square_free( + CGAL::resultant + (typename Polynomial_traits_2::Swap() (f,0,1), + typename Polynomial_traits_2::Swap() + (CGAL::differentiate(f),0,1)) + ); + // BUGFIX: y_pol might be zero: + if(y_pol.is_zero()) { + // force re-computation with bigger resultant + point_is_certainly_critical=false; + } + + } + } + + if (!point_is_certainly_critical) { + + Polynomial_2 r(x().polynomial()); + y_pol = CGAL::make_square_free( + CGAL::resultant + (typename Polynomial_traits_2::Swap() (f,0,1), + typename Polynomial_traits_2::Swap() (r,0,1)) + ); + + } + typename Algebraic_kernel_d_1::Solve_1 real_roots; + + Roots y_roots; + real_roots(y_pol, std::back_inserter(y_roots), false ); + + long prec = 16; + + typename Algebraic_curve_kernel_2::Approximate_absolute_y_2 + approx_y=kernel()->approximate_absolute_y_2_object(); + + std::pair y_pair = approx_y(*this,prec); + + Bound_interval y_iv(y_pair.first,y_pair.second); + + typedef typename std::vector::const_iterator + Iterator; + + std::list< Iterator > candidates; + + for (Iterator it = y_roots.begin(); it != y_roots.end(); it++) { + Bound_interval it_interval(it->low(), it->high()); + if (boost::numeric::overlap(it_interval, y_iv)) { + candidates.push_back(it); + } + } + CGAL_assertion(!candidates.empty()); + + while (candidates.size() > 1) { + prec*=2; + y_pair = approx_y(*this,prec); + + y_iv = Bound_interval(y_pair.first,y_pair.second); + + for (typename std::list< Iterator >::iterator dit, cit = + candidates.begin(); cit != candidates.end(); ) { + bool remove = false; + Bound_interval + cit_interval((*cit)->low(), (*cit)->high()); + if (!boost::numeric::overlap(cit_interval, y_iv)) { + dit = cit; + remove = true; + } + cit++; + if (remove) { + candidates.erase(dit); + } + } + } + CGAL_assertion(static_cast< int >(candidates.size()) == 1); + this->ptr()->_m_y = + Algebraic_real_1( + (*candidates.begin())->polynomial(), + (*candidates.begin())->low(), + (*candidates.begin())->high() + ); + } + CGAL_postcondition(this->ptr()->_m_y); + return *this->ptr()->_m_y; + } + + /*!\brief + * supporting curve of the point + */ + Curve_analysis_2 curve() const { + return this->ptr()->_m_curve; + } + + /*!\brief + * arc number of point + * + */ + int arcno() const { + return this->ptr()->_m_arcno; + } + + //!@} +public: + //!\name comparison predicates + //!@{ + + /*!\brief + * compares x-coordinates of \c *this with \c q + * + * do we need this method or one should use Algebraic_curve_kernel_2 + * directly ? + */ + CGAL::Comparison_result compare_x(const Self& q) const { + + if(this->is_identical(q)) { + return CGAL::EQUAL; + } + return kernel()->compare_1_object()(this->x(), q.x()); + } + + /*!\brief + * compares \c *this with \c q lexicographically + */ + CGAL::Comparison_result compare_xy(const Self& q, + bool equal_x = false) const { + + if(this->is_identical(q)) + return CGAL::EQUAL; + + CGAL::Comparison_result res = (equal_x ? CGAL::EQUAL : compare_x(q)); + if(res == CGAL::EQUAL) { + res = _compare_y_at_x(q); + } + return res; + } + + //! equality + bool operator == (const Self& q) const {return q.compare_xy(*this)== 0;} + + //! inequality + bool operator != (const Self& q) const {return q.compare_xy(*this)!= 0;} + + //! less than in (x,y) lexicographic order + bool operator < (const Self& q) const {return q.compare_xy(*this)> 0;} + + //! less-equal in (x,y) lexicographic order + bool operator <= (const Self& q) const {return q.compare_xy(*this)>= 0;} + + //! greater than in (x,y) lexicographic order + bool operator > (const Self& q) const {return q.compare_xy(*this)< 0;} + + //! greater-equal in (x,y) lexicographic order + bool operator >= (const Self& q) const {return q.compare_xy(*this)<= 0;} + + //!@} + + //!@{ + //! \name + + const Algebraic_curve_kernel_2* kernel() const { + return this->ptr()->_m_kernel; + } + +private: + + /*!\brief + * compares y-coordinates for covertical points \c *this and \c q + * + * \pre x() == q.x() + */ + CGAL::Comparison_result _compare_y_at_x(const Self& q) const + { + CGAL_precondition(this->compare_x(q) == CGAL::EQUAL); + + Curve_analysis_2 f = curve(), g = q.curve(); + if(f.is_identical(g)) + return CGAL::sign(arcno() - q.arcno()); + if(Self::_simplify(*this, q)) + // restart since supporting curves might be equal now + return _compare_y_at_x(q); + + Curve_pair_analysis_2 cpa_2 = + kernel()->construct_curve_pair_2_object()(f, g); + + + typename Curve_pair_analysis_2::Status_line_1 vline = + cpa_2.status_line_for_x(x()); + return CGAL::sign(vline.event_of_curve(arcno(), f) - + vline.event_of_curve(q.arcno(), g)); + } + + //!@} +public: + //!\name Reconstructing functions + //!@{ + + /*!\brief + * Simplifies the representation of a point. + * + * Given a decomposition of the point's supporting \c curve() into + * a pair of two curves \c pair, this function searches this point + * in the curve pair and resets the curve and the arcno to this + * found arc. It can happen, that both curves of the pair fit this + * condition (intersection of the two curves at this point), then it + * chooses the simpler one (less total degree). + * + * \pre pair must be a decomposition of curve() + */ + void simplify_by(const Curve_pair_analysis_2& cpa_2) const { + + CGAL_precondition_code( + Polynomial_2 mult = + cpa_2.curve_analysis(0).polynomial_2() * + cpa_2.curve_analysis(1).polynomial_2(); + ); + // common parts + CGAL_precondition(CGAL::resultant(mult, + curve().polynomial_2()).is_zero()); + // full parts + CGAL_precondition(CGAL::degree(mult) == + CGAL::degree(curve().polynomial_2())); + CGAL_precondition(CGAL::total_degree(mult) == + CGAL::total_degree(curve().polynomial_2())); + + typename Curve_pair_analysis_2::Status_line_1 cpv_line = + cpa_2.status_line_for_x(x()); + // # of arcs must match + CGAL_precondition_code( + typename Curve_analysis_2::Status_line_1 cv_line = + curve().status_line_for_x(x()); + ); + CGAL_precondition(cpv_line.number_of_events() == + cv_line.number_of_events()); + + int cid = 0; + std::pair p = cpv_line.curves_at_event(arcno()); + if(p.first != -1 && p.second != -1) { + // both curves involved: choose simpler one + // Remark: In this case, a vertical line in the curves can be + // ignored, since it has not been considered when constructing + // the point from the composed curved (also including this vertical + // line). Therefore, the old arc number is also valid in the curve + // pair. + Polynomial_2 ff = cpa_2.curve_analysis(0).polynomial_2(), + gg = cpa_2.curve_analysis(1).polynomial_2(); + if(total_degree(ff) > total_degree(gg)) + cid = 1; + } else + cid = (p.first != -1 ? 0 : 1); + // overwrite data + this->ptr()->_m_curve = cpa_2.curve_analysis(cid); + this->ptr()->_m_arcno = (cid == 0 ? p.first : p.second); + } + + //! befriending output iterator + // friend std::ostream& operator << <>(std::ostream& os, const Self& pt); + + //!@} +public: + + //! Returns whether the x-coordinate equals zero + bool is_x_zero() const { + return CGAL::is_zero(this->ptr()->_m_x); + } + + //! Returns whether the y-coordinate equals zero + bool is_y_zero() const { + CGAL::Sign lower_sign = CGAL::sign(this->lower_bound_y()), + upper_sign = CGAL::sign(this->upper_bound_y()); + if( lower_sign == CGAL::ZERO ||upper_sign == CGAL::ZERO) { + if(lower_sign==upper_sign) { //both zero + return true; + } else { // one zero, one not...isol interval is OPEN + return false; + } + } else if( lower_sign==upper_sign) { // zero not in isol interval + return false; + } else { // zero in interval, need to check + Polynomial_1 constant_pol = + CGAL::get_coefficient(curve().primitive_polynomial_2(),0); + bool zero_is_root_of_local_pol + = kernel()->is_zero_at_1_object()(constant_pol,this->ptr()->_m_x); + // Since we know that y_iv is an _isolating_ interval, + // we can immediately return + return zero_is_root_of_local_pol; + } + } + + // returns a double approximation of the point + std::pair to_double() const { + + typedef typename CGAL::Get_arithmetic_kernel::Arithmetic_kernel + AT; + typedef typename AT::Bigfloat_interval BFI; + + long old_prec = get_precision(BFI()); + + set_precision (BFI(), 53); + + // rely on double conversion of the x-type + double double_x = CGAL::to_double(this->ptr()->_m_x); + double double_y; + + + if (this->lower_bound_y()==this->upper_bound_y()) { + double_y = CGAL::to_double(convert_to_bfi(this->lower_bound_y())); + } else if(is_y_zero()) { + double_y = 0.; + } else { + while(CGAL::sign(this->lower_bound_y()) != + CGAL::sign(this->upper_bound_y()) ) { + this->refine_y(); + } + long final_prec = set_precision(BFI(),get_precision(BFI())+4); + + BFI bfi = CGAL::hull(convert_to_bfi(this->lower_bound_y()), + convert_to_bfi(this->upper_bound_y())); + + while( !singleton(bfi) && + get_significant_bits(bfi) < final_prec ){ + this->refine_y(); + bfi = CGAL::hull( + convert_to_bfi(this->lower_bound_y()), + convert_to_bfi(this->upper_bound_y())); + } + double_y + = CGAL::to_double((CGAL::lower(bfi)+ CGAL::upper(bfi)) / 2); + } + set_precision(BFI(),old_prec); + return std::make_pair(double_x, double_y); + } + + public: + + + void refine_y() const { + this->curve().status_line_at_exact_x(this->x()).refine(this->arcno()); + } + + Bound lower_bound_y() const { + return this->curve().status_line_at_exact_x(this->x()). + lower_bound(this->arcno()); + } + + Bound upper_bound_y() const { + return this->curve().status_line_at_exact_x(this->x()). + upper_bound(this->arcno()); + } + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + + void refine_x() const { + this->x().refine(); + } + + Bound lower_bound_x() const { + return this->x().low(); + } + + Bound upper_bound_x() const { + return this->x().high(); + } + +#endif + + + // friend function to provide a fast hashing + friend std::size_t hash_value(const Self& x) { + return static_cast(x.id()); + } + + //!@} + +}; // class Xy_coordinate_2 + +template < class AlgebraicCurveKernel_2, class Rep> +std::ostream& operator<< (std::ostream& os, + const Xy_coordinate_2& pt) +{ + switch (::CGAL::get_mode(os)) { + case ::CGAL::IO::PRETTY: { + os << "[x-coord: " << CGAL::to_double(pt.x()) << "; curve: " << + pt.curve().polynomial_2() << + "; arcno: " << pt.arcno() << "]\n"; + break; + } + case ::CGAL::IO::BINARY: + std::cerr << "BINARY format not yet implemented" << std::endl; + break; + default: + // ASCII + os << "Algebraic_real_xca_2("; + os << pt.x(); + os << ","; + os << pt.curve(); + os << ","; + os << pt.arcno(); + os << ")"; + } + return os; +} + +template < class AlgebraicCurveKernel_2, class Rep_ > +std::istream& operator >> ( + std::istream& is, + Xy_coordinate_2< AlgebraicCurveKernel_2, Rep_>& pt) { + + CGAL_precondition(CGAL::is_ascii(is)); + + // this instance's first template argument + typedef AlgebraicCurveKernel_2 Algebraic_curve_kernel_2; + + // this instance's second template argument + typedef Rep_ Rep; + + // myself + typedef Xy_coordinate_2< Algebraic_curve_kernel_2, Rep > Xy_coordinate_2; + + typedef typename Algebraic_curve_kernel_2::Algebraic_real_1 + Algebraic_real_1; + + typedef typename Algebraic_curve_kernel_2::Curve_analysis_2 + Curve_analysis_2; + + // x-coordinate + Algebraic_real_1 x; + + // supporting curve + Curve_analysis_2 curve; + + // arc number on curve + int arcno; + + // read "Algebraic_real_xca_2(" + swallow(is, 'A'); + swallow(is, 'l'); + swallow(is, 'g'); + swallow(is, 'e'); + swallow(is, 'b'); + swallow(is, 'r'); + swallow(is, 'a'); + swallow(is, 'i'); + swallow(is, 'c'); + swallow(is, '_'); + swallow(is, 'r'); + swallow(is, 'e'); + swallow(is, 'a'); + swallow(is, 'l'); + swallow(is, '_'); + swallow(is, 'x'); + swallow(is, 'c'); + swallow(is, 'a'); + swallow(is, '_'); + swallow(is, '2'); + swallow(is, '('); + + + // read values + is >> x; + swallow(is, ','); + + is >> curve; + swallow(is, ','); + + is >> arcno; + + // read the ") + swallow(is, ')'); + + pt = Xy_coordinate_2(x, curve, arcno); + + return is; +} + +} // namespace internal + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_XY_COORDINATE_2_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.h new file mode 100644 index 00000000000..207c1ffaa15 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.h @@ -0,0 +1,434 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS +#define CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS 1 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +/* + * \brief Function for merging two sets + * + * This function is similar to the \c std::union_set operation. + * Additionally, it provides a sequence of CGAL::internal::Three_valued + * providing information to which input set the corresponding root + * in the merged sequence belonged + * + * The BinaryFunction must have the Result type CGAL::Comparison_result. + */ +template +std::pair +set_union_with_source(InputIterator1 first_begin, + InputIterator1 first_end, + InputIterator2 second_begin, + InputIterator2 second_end, + OutputIterator1 merged_values, + OutputIterator2 merged_values_info, + BinaryFunction compare) { + + InputIterator1 first_it=first_begin; + InputIterator2 second_it=second_begin; + + while((first_it != first_end) || (second_it!=second_end)) { + if(first_it == first_end) { + *merged_values=*second_it++; + ++merged_values; + *merged_values_info++ = CGAL::internal::ROOT_OF_SECOND_SET; + continue; + } + if(second_it == second_end) { + *merged_values++=*first_it++; + *merged_values_info++ = CGAL::internal::ROOT_OF_FIRST_SET; + continue; + } + + CGAL::Comparison_result c = compare(*first_it,*second_it); + + if(c==CGAL::EQUAL) { + *merged_values++=*first_it++; + ++second_it; + *merged_values_info++ = CGAL::internal::ROOT_OF_BOTH_SETS; + continue; + } + if(c==CGAL::SMALLER) { + *merged_values++=*first_it++; + *merged_values_info++ = CGAL::internal::ROOT_OF_FIRST_SET; + continue; + } + if(c==CGAL::LARGER) { + *merged_values++=*second_it++; + *merged_values_info++ = CGAL::internal::ROOT_OF_SECOND_SET; + continue; + } + } + return std::make_pair(merged_values,merged_values_info); +} + +/* + * \brief Removes the leading term of the polynomial \c f as long as it + * vanishes at \c alpha + * + */ +template +Poly_2 poly_non_vanish_leading_term(Algebraic_kernel_d_1* kernel, + const Poly_2& pol, + Algebraic_real alpha) { + Poly_2 f(pol); + while(true) { + if(kernel->is_zero_at_1_object() + (CGAL::leading_coefficient(f),alpha)) { + typename Poly_2::const_iterator poly_end = f.end(); + if(f.begin()==poly_end) { + break; + } + poly_end--; + f=Poly_2(f.begin(),poly_end); + } + else { + break; + } + } + return f; +} + +/*! + * \brief finds a Rational value left of an Algebraic real alpha + */ +template typename AlgebraicKernel_1::Bound + bound_left_of(const AlgebraicKernel_1* kernel, + typename AlgebraicKernel_1::Algebraic_real_1 ar) { + + typedef AlgebraicKernel_1 Algebraic_kernel_d_1; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real_1; + typedef typename Algebraic_kernel_d_1::Bound Bound; + + switch( CGAL::sign( ar ) ) { + case(CGAL::ZERO): { + return Bound(-1); + break; + } + case(CGAL::POSITIVE): { + return Bound(0); + break; + } + case(CGAL::NEGATIVE): { + Algebraic_real_1 small_value + = kernel->construct_algebraic_real_1_object() + (Bound(2)*kernel->approximate_absolute_1_object()(ar,1).first); + + return kernel->bound_between_1_object()(small_value,ar); + // = small_value.rational_between(ar); + //= ar.low()-1; + } + } + // never reached + return Bound(0); +} + +/*! + * \brief finds a Rational value rightt of an Algebraic real alpha + */ +template typename AlgebraicKernel_1::Bound + bound_right_of(const AlgebraicKernel_1* kernel, + typename AlgebraicKernel_1::Algebraic_real_1 ar) { + + return -bound_left_of(kernel,-ar); + +} + + +/*! + * \brief Produces intermediate rational values for a list of + * algebraic reals. + * + * For a list of Algebraic real values with \c n elements, a list with + * n+1 elements of rational values is given such that the + * ith element is + * between the ith and the (i+1)th element of the input list + * + * The input list must be in increasing order + */ +template + OutputIterator find_intermediate_values(const AlgebraicKernel_1* kernel, + InputIterator start, + InputIterator end, + OutputIterator output) { + typedef typename AlgebraicKernel_1::Algebraic_real_1 Alg_real; + BOOST_STATIC_ASSERT + ((::boost::is_same + ::value_type >::value)); + + typedef typename AlgebraicKernel_1::Bound Bound; + if(start==end) { + // Empty vector, create one element + *output++=Bound(0); + return output; + } + *output++=bound_left_of(kernel,*start); + + InputIterator it_1(start),it_2(start); + ++it_2; + while(it_2 != end) { + CGAL_assertion(it_1->compare(*it_2)==CGAL::SMALLER); + Bound beta + = kernel->bound_between_1_object()(*it_1,*it_2); + *output++=beta; + ++it_1; + ++it_2; + } + *output++=bound_right_of(kernel,*it_1); + + return output; +} + + + +// Used internally for zero_test_bivariate + +namespace for_zero_test_bivariate { + +template + void cast_back_utcf(const Poly_coer_1& p,Polynomial_1& q) { + // We can assume that both template arguments are polynomial types + typedef typename CGAL::Polynomial_traits_d::Coefficient_type + Coercion_type; + typedef typename CGAL::Polynomial_traits_d::Coefficient_type + Coefficient; + typedef CGAL::Fraction_traits FT; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + typedef typename FT::Numerator_type Numerator; + typedef typename FT::Denominator_type Denominator; + typedef CGAL::Coercion_traits Num_coercion; + BOOST_STATIC_ASSERT((::boost::is_same + ::value)); + Numerator p_num; + Denominator p_denom; + typename FT::Decompose()(p,p_num,p_denom); + q = typename Num_coercion::Cast()(p_num); +} + +template void cast_back_utcf(const A& p, A& q) { + q = p; +} + +} // of namespace for_zero_test_bivariate + +/* + * \brief Symbolic zero test. + * + * Checks whether h(x,y(x))=0, where y(x) is a rational + * expression in terms of \c x, i.e. y=p/q with p,q + * univariate polynomials + */ +template + bool zero_test_bivariate + (const AlgebraicCurveKernel_2* kernel, + const typename AlgebraicCurveKernel_2::Algebraic_real_1& alpha, + const typename AlgebraicCurveKernel_2::Polynomial_2& h, + const typename AlgebraicCurveKernel_2::Polynomial_1& p, + const typename AlgebraicCurveKernel_2::Polynomial_1& q) { + + bool result; + typedef typename AlgebraicCurveKernel_2::Polynomial_1 Polynomial_1; +#if !CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT + + typedef typename AlgebraicCurveKernel_2::Algebraic_real_1 Algebraic_real_1; + typedef typename AlgebraicCurveKernel_2::Bound Bound; + typedef typename AlgebraicCurveKernel_2::Coefficient Coefficient; + typedef typename AlgebraicCurveKernel_2::Polynomial_2 Polynomial_2; + + typedef CGAL::Coercion_traits Coercion; + typedef typename Coercion::Type Coercion_type; + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type Poly_coer_1; + typedef typename CGAL::Polynomial_traits_d + ::template Rebind::Other::Type Poly_coer_2; + + typename Coercion::Cast cast; + + bool general = ! alpha.is_rational(); + + Poly_coer_1 p_rat = typename CGAL::Polynomial_traits_d + ::Construct_polynomial() + (boost::make_transform_iterator + (p.begin(),cast), + boost::make_transform_iterator + (p.end(),cast)); + Poly_coer_1 q_rat = typename CGAL::Polynomial_traits_d + ::Construct_polynomial() + (boost::make_transform_iterator + (q.begin(),cast), + boost::make_transform_iterator + (q.end(),cast)); + + if(general) { + + + Poly_coer_1 modulus = typename CGAL::Polynomial_traits_d + ::Construct_polynomial() + (boost::make_transform_iterator + (alpha.polynomial().begin(),cast), + boost::make_transform_iterator + (alpha.polynomial().end(),cast)); + +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "Mod: " << modulus << std::endl; + #endif +*/ + p_rat=CGAL::mod(p_rat,modulus); + q_rat=CGAL::mod(q_rat,modulus); + + int n = CGAL::degree(h,1); + // Create the powers of p and q mod modulus +/* +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "precomp powers.." << std::flush; +#endif +*/ + std::vector p_powers(n+1),q_powers(n+1); + p_powers[0]=Poly_coer_1(Bound(1)); + q_powers[0]=Poly_coer_1(Bound(1)); + Poly_coer_1 intermediate; + for(int i=1;i<=n;i++) { +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << i << ": mult.." << std::flush; + #endif +*/ + intermediate=p_powers[i-1]*p_rat; +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "mod.." << std::flush; + #endif +*/ + p_powers[i]=CGAL::mod(intermediate,modulus); +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "simpl.." << std::flush; + #endif +*/ + p_powers[i].simplify_coefficients(); +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "mult.." << std::flush; + #endif +*/ + intermediate=q_powers[i-1]*q_rat; +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "mod.." << std::flush; + #endif +*/ + q_powers[i]=CGAL::mod(intermediate,modulus); +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "simpl.." << std::flush; + #endif +*/ + q_powers[i].simplify_coefficients(); + } +/* + #if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "done\ncomp rat pol.." << std::flush; + #endif +*/ + + Poly_coer_1 curr_coeff,curr_fac; + Poly_coer_1 h_0_rat(Coercion_type(0)); + for(int i=0;i<=n;i++) { + Poly_coer_1 tmp_pol = typename CGAL::Polynomial_traits_d + ::Construct_polynomial() + (boost::make_transform_iterator + (h[i].begin(),cast), + boost::make_transform_iterator + (h[i].end(),cast)); + curr_fac=CGAL::mod + (tmp_pol*p_powers[i]*q_powers[n-i], modulus); + h_0_rat+=curr_fac; + } + + Polynomial_1 h_0_utcf; + for_zero_test_bivariate::cast_back_utcf(h_0_rat,h_0_utcf); + + return kernel->is_zero_at_1_object() (h_0_utcf,alpha); + } + else { + Coercion_type b = cast(alpha.rational()), + p_b=CGAL::evaluate(p_rat,b),q_b=CGAL::evaluate(q_rat,b); + int n = CGAL::degree(h,1); + Coercion_type eval(0); + for(int i=0;i<=n;i++) { + Poly_coer_1 h_i_rat = typename CGAL::Polynomial_traits_d + ::Construct_polynomial() + (boost::make_transform_iterator + (CGAL::get_coefficient(h,i).begin(),cast), + boost::make_transform_iterator + (CGAL::get_coefficient(h,i).end(),cast)); + eval+=CGAL::evaluate(h_i_rat,b) + *CGAL::ipower(p_b,i)*CGAL::ipower(q_b,n-i); + } + result=(CGAL::sign(eval)==CGAL::ZERO); + } +#else +#warning Uses no reduction modulo resultant! + Polynomial_1 h_0=CGAL::evaluate_homogeneous(h,p,q); + result= kernel->is_zero_at_1_object() (h_0,alpha); +#endif + + return result; + +} + + + +} // namespace internal + + +} //namespace CGAL + +#endif // CGAL_ALGEBRAIC_CURVE_KERNEL_2_TOOLS diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/bound_between_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/bound_between_1.h new file mode 100644 index 00000000000..8402ad6e388 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/bound_between_1.h @@ -0,0 +1,267 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_BOUND_BETWEEN_1_H +#define CGAL_BOUND_BETWEEN_1_H 1 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace CGAL { + +namespace internal { + +/*! \brief Tries to find a SIMPLE rational q with aq
+ * is a power of two, and is not too big. There is no guarantee to find + * the rational value between a and b of minimal + * bit size. + */ +template +typename Algebraic_real::Rational +simple_bound_between(const Algebraic_real& a, + const Algebraic_real&b) { + + //srb.start(); + typedef typename Algebraic_real::Rational Rational; + typename CGAL::Fraction_traits::Compose compose; + typedef typename + CGAL::Get_arithmetic_kernel::Arithmetic_kernel AK; + typedef typename AK::Bigfloat_interval Bigfloat_interval; + typedef typename CGAL::Bigfloat_interval_traits + ::Bound Bigfloat; + typedef typename AK::Integer Integer; + + long old_prec = CGAL::get_precision(Bigfloat_interval()); + + CGAL_assertion(a!=b); + if(a>b) { + return simple_bound_between(b,a); + } + + //std::cout << "Intermediate1: " << CGAL::to_double(a) << " " << CGAL::to_double(b) << std::endl; + /* + * First, refine a and b until their isolating intervals are disjoint + * Therefore, the bigger interval is refined in each substep + */ + //srb_a.start(); + if(a.high() >= b.low()) { + Rational size_a=a.high()-a.low(), + size_b=b.high() - b.low(); + while(a.high() >= b.low()) { + if(size_a < size_b) { + b.refine(); + size_b=b.high() - b.low(); + } else { + a.refine(); + size_a=a.high()-a.low(); + } + } + } + //srb_a.stop(); + + //srb_b.start(); + Bigfloat x=CGAL::upper(CGAL::convert_to_bfi(a.high())); + Bigfloat y=CGAL::lower(CGAL::convert_to_bfi(b.low())); + + if(x>=y) { + Rational size_a=a.high() - a.low(), + size_b=b.high() - b.low(), + size_max = size_a>size_b ? size_a : size_b, + size_int = b.low()-a.high(); + while(x>=y) { + //std::cout << "x and y: " << x << " and " << y << std::endl; + //std::cout << "sizes: " << CGAL::to_double(size_int) << " " << CGAL::to_double(size_max) << std::endl; + if(size_int>size_max) { + CGAL::set_precision(Bigfloat_interval(), + 2*CGAL::get_precision(Bigfloat_interval())); + x=CGAL::upper(CGAL::convert_to_bfi(a.high())); + y=CGAL::lower(CGAL::convert_to_bfi(b.low())); + } else { + if(size_a < size_b) { + b.refine(); + size_b=b.high() - b.low(); + y=CGAL::lower(CGAL::convert_to_bfi(b.low())); + } else { + a.refine(); + size_a=a.high()-a.low(); + x=CGAL::upper(CGAL::convert_to_bfi(a.high())); + } + size_max = size_a>size_b ? size_a : size_b; + size_int = b.low()-a.high(); + } + } + } + CGAL_assertion(x::Get_mantissa mantissa; + typename CGAL::internal::Float_traits::Get_exponent exponent; + + // std::cout << CGAL::to_double(x) << " < " << CGAL::to_double(y) << std::endl; + + Integer x_m = mantissa(x), y_m=mantissa(y); + long x_e = exponent(x), y_e = exponent(y); + //std::cout << "Floats1: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl; + + + if (((x_m > 0) && (y_m < 0)) || ((x_m < 0) && (y_m > 0))) { + //srb.stop(); + return Rational(0); + } + bool negative=false; + if(x_m<=0 && y_m <=0) { + x_m=-x_m; + y_m=-y_m; + std::swap(x_m,y_m); + std::swap(x_e,y_e); + negative=true; + } + // Now, we have that (x_m,x_e) represents a number smaller than (y_m,y_e) + //srb_c.start(); + //std::cout << "Floats2: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl; + + // As long as the mantissa is even, simplify + while(x_m != 0 && (x_m & 1)==0 ) { + x_m=x_m >> 1; + x_e++; + } + while(y_m != 0 && (y_m & 1)==0 ) { + y_m=y_m >> 1; + y_e++; + } + //srb_c.stop(); + //std::cout << "Floats3: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl; + + // Bring both numbers to a common exponent + //srb_d.start(); + long min_e = x_e < y_e ? x_e : y_e; + while(x_e > min_e) { + x_m=x_m << 1; + x_e--; + } + while(y_e > min_e) { + y_m=y_m << 1; + y_e--; + } + //srb_d.stop(); + CGAL_assertion(y_e==x_e && x_e==min_e); + CGAL_assertion(x_m < y_m); + //std::cout << "Floats4: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl; + + // Avoid mantissas to have difference one + if(y_m-x_m==Integer(1)) { + x_m=x_m << 1; + y_m=y_m << 1; + x_e--; + y_e--; + min_e--; + } + //std::cout << "Floats5: " << x_m << " " << x_e << " and " << y_m << " " << y_e << std::endl; + Integer final_mantissa(0); + //srb_e.start(); + long x_log = x_m==Integer(0) ? -1 : CGAL::internal::floor_log2_abs(x_m), + y_log = y_m==Integer(0) ? -1 : CGAL::internal::floor_log2_abs(y_m), + old_log = y_log; + //std::cout << x_log << " < " << y_log << std::endl; + while(x_log==y_log) { + //std::cout << "here" << std::endl; + while(old_log > y_log) { + final_mantissa = final_mantissa << 1; + old_log--; + } + CGAL_assertion((x_m & ((Integer(1) << x_log) - 1)) == x_m - CGAL::ipower(Integer(2),x_log)); + x_m = x_m & ((Integer(1) << x_log) - 1); // x_m - CGAL::ipower(Integer(2),x_log); + y_m = y_m & ((Integer(1) << y_log) - 1); // y_m - CGAL::ipower(Integer(2),y_log); + + final_mantissa++; + old_log=y_log; + x_log = x_m==0 ? -1 : CGAL::internal::floor_log2_abs(x_m); + y_log = y_m==0 ? -1 : CGAL::internal::floor_log2_abs(y_m); + } + //srb_e.stop(); + // Now, x_log != y_log, in fact, y_log is greater + CGAL_assertion(x_log y_log) { + final_mantissa = final_mantissa << 1; + old_log--; + } + if((y_m & ((Integer(1) << y_log) - 1 ))==0) { // y_m - CGAL::ipower(Integer(2),y_log)==0) { + // Now, the constructed value would be equal to + while(y_log!=0 && x_log==y_log-1) { + final_mantissa = final_mantissa << 1; + final_mantissa++; + y_log--; + x_m = x_m==0 ? 0 : x_m & ((Integer(1) << x_log) - 1); //x_m - CGAL::ipower(Integer(2),x_log); + x_log = x_m==0 ? -1 : CGAL::internal::floor_log2_abs(x_m); + } + final_mantissa = final_mantissa << 1; + final_mantissa++; + y_log--; + } else { + final_mantissa++; + } + //srb_f.stop(); + min_e += y_log; + Rational rat_between; + //std::cout << "Min_e: " << min_e << std::endl; + if(min_e > 0) { + rat_between = compose(final_mantissa << min_e, + Integer(1)); + } else { + rat_between = compose(final_mantissa, Integer(1) << -min_e); + } + if(negative) { + rat_between = -rat_between; + } + //std::cout << "Result: " << a.high() << " " << rat_between << " " << b.low() << std::endl; + CGAL_assertion(a.high() < rat_between); + CGAL_assertion(b.low() > rat_between); + CGAL::set_precision(Bigfloat_interval(),old_prec); + //srb.stop(); + return rat_between; +} + + +} // namespace internal + + +} //namespace CGAL + +#endif // CGAL_BOUND_BETWEEN_1_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/construct_binary.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/construct_binary.h new file mode 100644 index 00000000000..cd4f542e406 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/construct_binary.h @@ -0,0 +1,141 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H +#define CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H + +#include +#include + +#ifdef CGAL_USE_LEDA +#include +#include +#endif +#ifdef CGAL_USE_CORE +#include +#include +#endif + +#include + +namespace CGAL { + +namespace internal { + +// Generic construct_binary function, using ipower +template< class Integer > +inline void construct_binary( const Integer& e, Integer& x ) { + CGAL_precondition( e >= 0 ); + Integer exponent(e); + x = Integer(1); + + const Integer max_ipower = (exponent > Integer((std::numeric_limits::max)())) ? + CGAL::ipower( Integer(2), (std::numeric_limits::max)() ) : + Integer(0); + + while( exponent > Integer((std::numeric_limits::max)()) ) { + x *= max_ipower; + exponent -= Integer((std::numeric_limits::max)()); + } + + x *= CGAL::ipower( Integer(2), (int)CGAL::to_double(exponent) ); +} + +template< class Integer, class Rational > +inline void construct_binary( const Integer& m, const Integer& e, Rational& x ) { + Integer den(1), num; + if(e>0) { + construct_binary( e, num ); + num *= m; + } + else { + num = m; + construct_binary( -e, den ); + } + x = Rational(num, den); +} + +// Specialization for LEDA + +#ifdef CGAL_USE_LEDA + + // Constructs 2^e from an integer e. Needed in Descartes + inline void construct_binary(const ::leda::integer& e, ::leda::integer& x) { + typedef ::leda::integer Integer; + x = Integer(1) << e.to_long(); + } + + // Constructs m*2^e from two integers m,e. Needed in Descartes + inline void construct_binary(const ::leda::integer& m, const ::leda::integer& e, + ::leda::rational& x) { + + typedef ::leda::integer Integer; + typedef ::leda::rational Rational; + + Integer den(1); + Integer num(m); + if(e>0) { + num <<= e.to_long(); + } + else { + den <<= (-e).to_long(); + } + x = Rational(num, den); + } + +#endif // CGAL_USE_LEDA + +// Specialization for CORE + +#ifdef CGAL_USE_CORE + + // Constructs 2^e from an integer e. Needed in Descartes + inline void construct_binary(const ::CORE::BigInt& e, ::CORE::BigInt& x) { + typedef ::CORE::BigInt Integer; + x = Integer(1) << ::CORE::ulongValue(e); + } + + // Constructs m*2^e from two integers m,e. Needed in Descardes + inline void construct_binary(const ::CORE::BigInt& m, const ::CORE::BigInt& e, + ::CORE::BigRat& x) { + typedef ::CORE::BigInt Integer; + typedef ::CORE::BigRat Rational; + + Integer den(1); + Integer num(m); + if(e>0) { + num <<= ::CORE::ulongValue(e); + } + else { + den <<= ::CORE::ulongValue(-e); + } + x = Rational(num, den); + } + +#endif // CGAL_USE_CORE + +} // namespace internal + +} //namespace CGAL + + +#endif // CGAL_ALGEBRAIC_KERNEL_D_CONSTRUCT_BINARY_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/enums.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/enums.h new file mode 100644 index 00000000000..fc9353eb5e4 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/enums.h @@ -0,0 +1,57 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_ACK_ENUMS_H +#define CGAL_ACK_ENUMS_H 1 + +namespace CGAL { + +namespace internal { + + enum Three_valued { + + ROOT_OF_FIRST_SET = 1, + ROOT_OF_BOTH_SETS = 0, + ROOT_OF_SECOND_SET=-1 + + }; + +} // namespace internal + +/*! + * \brief Represents different strategies how to handle + * degenerate cases during the analysis + * + * Currently, there are two possible strategies implemented. See the + * constructor of \c Curve_analysis_2 for more details. + */ +enum Degeneracy_strategy { + + SHEAR_STRATEGY = 0, + EXCEPTION_STRATEGY = 1, + SHEAR_ONLY_AT_IRRATIONAL_STRATEGY = 2 +}; + +} //namespace CGAL + +#endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/exceptions.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/exceptions.h new file mode 100644 index 00000000000..49f971f2510 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/exceptions.h @@ -0,0 +1,77 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + + +#ifndef CGAL_ALGEBRAIC_KERNEL_EXCEPTIONS_H +#define CGAL_ALGEBRAIC_KERNEL_EXCEPTIONS_H + + +namespace CGAL { + + namespace internal { + + /*! + * \brief Exception class for not sufficiently generic positions. + * + * Must be thrown whenever a curve cannot be analysed because its position + * is not "good enough". + */ + class Non_generic_position_exception { + + public: + + //! Default constructible + Non_generic_position_exception() {} + + }; + + /*! + * \brief Exception class for not sufficiently generic positions. + * + * Must be thrown whenever a curve cannot be analysed because its position + * is not "good enough". + */ + template + class Zero_resultant_exception { + + Polynomial curve1,curve2; + bool one_curve_failure; + + public: + + Zero_resultant_exception(Polynomial c) + : curve1(c), curve2(c),one_curve_failure(true) + {} + + Zero_resultant_exception(Polynomial c1,Polynomial c2) + : curve1(c1),curve2(c2),one_curve_failure(false) + {} + + }; + + } // namespace internal + +} //namespace CGAL + + +#endif diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/flags.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/flags.h new file mode 100644 index 00000000000..4a0e588d888 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/flags.h @@ -0,0 +1,216 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + + +#ifndef CGAL_ACK_FLAGS_H +#define CGAL_ACK_FLAGS_H 1 + +// TODO: use new interface and remove this flag +#ifndef CGAL_AK_ENABLE_DEPRECATED_INTERFACE +#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 0 +#endif + +// Is debug-information printed? +#ifndef CGAL_ACK_DEBUG_FLAG +#define CGAL_ACK_DEBUG_FLAG 0 +#endif + +// If CGAL_ACK_DEBUG_FLAG is set, which output stream is used for debug? +#ifndef CGAL_ACK_DEBUG_PRINT +#define CGAL_ACK_DEBUG_PRINT std::cout +#endif + +// If enabled, needs includes from experimental package +#ifndef CGAL_ACK_WITH_FILTERED_KERNEL +#define CGAL_ACK_WITH_FILTERED_KERNEL 0 +#endif + +// If enabled, needs includes from experimental package +#ifndef CGAL_ACK_WITH_ROTATIONS +#define CGAL_ACK_WITH_ROTATIONS 0 +#endif + +/** + * The threshold that is used in the Filtered_algebraic_curve_kernel_2 + */ +#ifndef CGAL_ACK_THRESHOLD_FOR_FILTERED_KERNEL +#define CGAL_ACK_THRESHOLD_FOR_FILTERED_KERNEL 0.01 +#endif + +/** + * For random choices in the algorithm, this seed is used + * If set to zero, a random seed is used + */ +#ifndef CGAL_ACK_STATIC_SEED +#define CGAL_ACK_STATIC_SEED 0 +#endif + +/** + * Allows to use the Bitstream tree described in Eigenwillig's thesis + */ +#ifndef CGAL_ACK_BITSTREAM_USES_E08_TREE +#define CGAL_ACK_BITSTREAM_USES_E08_TREE 1 +#endif + + +/** + * If set, the program uses the AlciX-code + * for the curve- and curve-pair-analysis. + * This flag is only for debugging purposes. + */ +#ifndef CGAL_ACK_USE_EXACUS +#define CGAL_ACK_USE_EXACUS 0 +#endif + +/** + * If set, the curve and curve pair analysis are using specialized code + * to analyse conic curves, i.e. curves of degree 2 + */ +#ifndef CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX +#define CGAL_ACK_USE_SPECIAL_TREATMENT_FOR_CONIX 0 +#endif + +/** + * The curve analysis does not distinguish between "(1,1)-singularities" + * (i.e., vertical cusps, isolated points on arcs), and usual regular points. + * The candidate point on each status line can be checked for being singular + * using this flag. This gives additional information but increases + * compuation time + * + * WARNING: Currently, the status line does not store the additional + * information whether a point is singluar or not. + * Therefore, there is currently no reasons to set this flag. It is still + * contained for possible further extension of the status line. + */ +#ifndef CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY +#define CGAL_ACK_CHECK_CANDIDATE_FOR_SINGULARITY 0 +#endif + +/** + * If set to 1, curve pairs are not checked for coprimality. Only do this + * if you know what you are doing! + */ +#ifndef CGAL_ACK_DONT_CHECK_POLYNOMIALS_FOR_COPRIMALITY +#define CGAL_ACK_DONT_CHECK_POLYNOMIALS_FOR_COPRIMALITY 0 +#endif + +/** + * The "resultant first" strategy means: instead of computing the full + * subresultant sequence (or Sturm-Habicht sequence), the algorithm + * only computed the resultant in a first step. This suffices already for + * many curves (i.e., regular ones). The full subresultant is computed + * if it is needed for the first time. + * + * This strategy only makes sense if computing resultants is faster than + * computing subresultants, otherwise, it wastes computation time. + * Since resultant computation is done by interpolation, + * it is faster than the pseudo-remainder based subresultant computation. + */ +#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY +#define CGAL_ACK_RESULTANT_FIRST_STRATEGY 1 +#endif + +/** + * If CGAL_ACK_RESULTANT_FIRST_STRATEGY is set, this flag determines + * for which curves the "resultant first" strategy is used. Depending + * on the resultant algorithm, the strategy might only be advantageous + * for higher degree curves + * + * If CGAL_ACK_RESULTANT_FIRST_STRATEGY is not set, this flag has no effect + */ +#ifndef CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD +#define CGAL_ACK_RESULTANT_FIRST_STRATEGY_DEGREE_THRESHOLD 0 +#endif + +/** + * Subresultants can be computed by a polynomial remainder sequence (default), + * or by evaluating minors of the bezout matrix by setting this flag. + * Tests have shown that the polynomial remainder sequence is more efficient + * so it is not recommended to set this flag. + */ +#ifndef CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS +#define CGAL_ACK_USE_BEZOUT_MATRIX_FOR_SUBRESULTANTS 0 +#endif + +/** + * Allows to switch off the specialized method for Status_line_CPA_1 + * if multiplicity is zero or one. + * Since this methods improves the performance, + * it is not recommended to set this flag unless for testing + */ +#ifndef ACK_CGAL_NO_ARC_FLIP +#define ACK_CGAL_NO_ARC_FLIP 0 +#endif + +/** + * This flags defines the default strategy to handle degenerate curves + * There are three choices currently available: + * SHEAR_STRATEGY performs a shear whenever a degenerate situation occurs. + * SHEAR_ONLY_AT_IRRATIONAL_STRATEGY handles rational coordinates with + * a more direct method, but performs a shear for irrational x-coordinates + * that have a degeneracy. Finally, EXCEPTION_STRATEGY throws an exception + * whenever a degeneracy occurs. + */ +#ifndef CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY +//#define CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY CGAL::SHEAR_ONLY_AT_IRRATIONAL_STRATEGY +#define CGAL_ACK_DEFAULT_DEGENERACY_STRATEGY CGAL::SHEAR_STRATEGY +#endif + +/** + * The algorithm can also handle non-y-regular curves without shearing, + * in case that the resultant multiplicity at vertical asymptotes is one. + * This special treatement can be switched off by setting this flag. + * It is not recommended to do this because of efficiency + */ +#ifndef CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES +#define CGAL_ACK_SHEAR_ALL_NOT_Y_REGULAR_CURVES 0 +#endif + +/** + * At some points in the algorithm, it is checked whether a polynomial + * H(x):=h(p(x),q(x)) vanishes for an algebraic number x_0 with polynomial r. + * For that check, the computation of H is done modulo r for efficiency. + * This can be switched off by this flag, though it is recommended not to + * do so. + */ +#ifndef CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT +#define CGAL_ACK_USE_NO_REDUCTION_MODULO_RESULTANT 0 +#endif + +#ifndef CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN +#define CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN 0 +#endif + +/** + * These flags are experimental, concerning interval arithmetic methods + * Don't change them! + */ +#ifndef CGAL_ACK_USE_DERIVATIVE_OPTION +#define CGAL_ACK_USE_DERIVATIVE_OPTION 0 +#endif +#ifndef CGAL_ACK_USE_BISECTION_OPTION +#define CGAL_ACK_USE_BISECTION_OPTION 0 +#endif + + +#endif // CGAL_ACK_FLAGS_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/macros.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/macros.h new file mode 100644 index 00000000000..da70e068397 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/macros.h @@ -0,0 +1,82 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Eric Berberich +// Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ACK_MACROS_H +#define CGAL_ACK_MACROS_H 1 + +/*!\file include/CGAL/Algebraic_kernel_d/macros.d + * \brief Macro definitions wrt algebraic kernels + */ + +#include + +#include +#include +#include + +namespace CGAL { + +#define CGAL_ACK_SNAP_ALGEBRAIC_CURVE_KERNEL_2_TYPEDEFS(Curve_analysis_2) \ + typedef typename Algebraic_kernel_with_analysis_2::Coefficient Coefficient; \ + typedef typename Algebraic_kernel_with_analysis_2::Bound Bound; \ + typedef typename CGAL::Get_arithmetic_kernel \ + ::Arithmetic_kernel Arithmetic_kernel; \ + typedef typename Arithmetic_kernel::Integer Integer; \ + typedef typename Algebraic_kernel_with_analysis_2::Algebraic_real_1 Algebraic_real_1; \ + typedef typename Algebraic_kernel_with_analysis_2::Polynomial_1 Polynomial_1; \ + typedef typename Algebraic_kernel_with_analysis_2::Polynomial_2 Polynomial_2; \ + typedef typename Algebraic_kernel_with_analysis_2::Solve_1 Solve_1; \ + typedef CGAL::internal::Bitstream_coefficient_kernel_at_alpha \ + < Algebraic_kernel_with_analysis_2 > Bitstream_coefficient_kernel; \ + typedef CGAL::internal::Bitstream_descartes_rndl_tree_traits \ + < Bitstream_coefficient_kernel > Bitstream_traits; \ + typedef CGAL::internal::Bitstream_descartes \ + Bitstream_descartes; \ + typedef CGAL::internal::Status_line_CA_1< Algebraic_kernel_with_analysis_2 > \ + Status_line_1 \ + + + +#define CGAL_SNAP_AK_3_TYPEDEFS(Arithmetic_kernel) \ + CGAL_SNAP_ARITHMETIC_KERNEL_TYPEDEFS(Arithmetic_kernel); \ + typedef CGAL::Polynomial< Integer > Poly_int1; \ + typedef CGAL::Polynomial< Poly_int1 > Poly_int2; \ + typedef CGAL::Polynomial< Poly_int2 > Poly_int3; \ + typedef CGAL::Polynomial< Rational > Poly_rat1; \ + typedef CGAL::Polynomial< Poly_rat1 > Poly_rat2; \ + typedef CGAL::Polynomial< Poly_rat2 > Poly_rat3; \ + typedef CGAL::Sqrt_extension< Rational, Integer > Extn; \ + typedef CGAL::Sqrt_extension< Extn, Extn > Nested_extn; \ + typedef CGAL::Polynomial< Extn > Poly_extn1; \ + typedef CGAL::Polynomial< Poly_extn1 > Poly_extn2; \ + typedef CGAL::Polynomial< Poly_extn2 > Poly_extn3; \ + typedef CGAL::Polynomial< Nested_extn > Poly_nested_extn1; \ + typedef CGAL::Polynomial< Poly_nested_extn1 > Poly_nested_extn2; \ + typedef CGAL::Polynomial< Poly_nested_extn2 > Poly_nested_extn3 \ +// end #define CGAL_SNAP_AK_3_TYPEDEFS(AT) + + +} //namespace CGAL + +#endif //CGAL_ACK_MACROS_H +// EOF diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/refine_zero_against.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/refine_zero_against.h new file mode 100644 index 00000000000..a9820f8cd91 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/refine_zero_against.h @@ -0,0 +1,214 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#ifndef CGAL_REFINE_ZERO_AGAINST_H +#define CGAL_REFINE_ZERO_AGAINST_H + +#include + +#include + +namespace CGAL { + +namespace internal { +/* computes an upper bound on the number of roots ]low,high[ using Descartes' + * Sign Rule +*/ +template +int descartes(Polynomial& p, const Field& low,const Field& high){ +// decompose interval length and upper bound + CGAL_precondition(low::Numerator_type Numerator; + typedef typename Fraction_traits::Denominator_type Denominator; + + typename Fraction_traits::Decompose decomp; + //typename Algebraic_structure_traits::Simplify simplify; + + //simplify(low); + //simplify(high); + + Numerator num_high, num_low_sub_high; + Denominator den_high, den_low_sub_high; + + decomp(high, num_high, den_high); + decomp(low - high, num_low_sub_high, den_low_sub_high); + + Coefficient tmp(num_high); + // apply Descartes' rule to count zeros of q in ]low,high[ + Polynomial transf = // q(high + (low-high)/(1+x)) + CGAL::translate_by_one( + CGAL::reversal( + CGAL::scale_homogeneous( + CGAL::translate_homogeneous(p + ,Coefficient(num_high) + ,Coefficient(den_high)) + ,Coefficient(num_low_sub_high) + ,Coefficient(den_low_sub_high) + ) + ) + ); + return sign_variations(transf); +} + +/*! \ingroup \NiX_univariate_polynomial_utils + * \brief refine isolating interval for \c p w.r.t \c q + * + * This function refines the interval ]low, high[ + * such that it does not contain any zero of \c q different from the + * unique zero of \c p in ]low, high[. It is returned + * whether \c q has a zero in ]low, high[ equal to + * that of \c p . Note that zeroes of \c q at the boundaries are + * ignored. + * + * This function is implemented using bisection and Descartes' Rule. + * If the interval boundaries have denominators 2k, then + * this property will still hold after refinement. Although this + * function works similar to \c NiX::Algebraic_real<>.compare() , + * it is different insofar that it always maintains an open interval + * and never simplifies. + * + * \pre Both polynomials must be square-free. \c p must not vanish at the + * interval boundaries \c low and \c high . + * + * \todo Provide a means to let an \c NiX::Algebraic_real benefit + * from the interval refinement if it is the origin of the respective + * input data. + */ +template +bool refine_zero_against(Field& low, Field& high, Polynomial p, Polynomial q) { + typedef typename Polynomial::NT COEFF; + typename Algebraic_structure_traits::Simplify simplify; + + CGAL_precondition(low < high); + CGAL_precondition(CGAL::degree(p) > 0); + CGAL_precondition((CGAL::degree(q) >= 0) && !q.is_zero()); + + if (CGAL::degree(q) == 0) return false; + + CGAL::Sign sign_p_low = p.sign_at(low); + CGAL::Sign sign_p_high = p.sign_at(high); + CGAL_precondition(sign_p_low != CGAL::ZERO); + CGAL_precondition(sign_p_high != CGAL::ZERO); + CGAL_precondition(sign_p_high != sign_p_low); + + Polynomial gcd_pq; // computed below if necessary + + for (;;) { + int sv = internal::descartes(q,low,high); + CGAL_assertion(sv >= 0); + + if (sv == 0) { + // q has no zero in ]low,high[ + return false; + } else if (sv == 1) { + if (CGAL::degree(gcd_pq) < 0) { + if (may_have_common_factor(p, q)) { + gcd_pq = gcd_utcf(p, q); + } else { + gcd_pq = Polynomial(1); + } + } + std::cout << CGAL::to_double(low) << " " + << CGAL::to_double(high) << " " + << CGAL::degree(gcd_pq) << " " + << gcd_pq + << std::endl; + if (CGAL::degree(gcd_pq) > 0 // constant poly cannot change sign + && gcd_pq.sign_at(low) != gcd_pq.sign_at(high)) { + // q has exactly one zero in ]low,high[ + // and it's equal to that of p + return true; + } + } + // q may have a zero in ]low,high[ not equal to that of p + Field mid = (low+high)/Field(2); + CGAL::Sign s = p.sign_at(mid); + if (s == CGAL::ZERO) { + mid = (low+mid)/Field(2); + simplify(mid); + s = p.sign_at(mid); + } + CGAL_postcondition(s != CGAL::ZERO); + + if (s == sign_p_low) { + low = mid; + sign_p_low = s; + } else { + CGAL_postcondition(s == sign_p_high); + high = mid; + sign_p_high = s; + } + } +} + + +// Uses refine_zero_against first and refines the interval further, if any +// of the interval boarders has sign zero. +template < class Polynomial, class Field > +static bool strong_refine_zero_against(Field& low, Field& high, + Polynomial p, Polynomial q){ + std::cout << "comp has_common_root" << std::endl; + + bool has_common_root = refine_zero_against(low,high,p,q); + + std::cout << "done, " << has_common_root << std::endl; + + CGAL::Sign sign_p_low = p.sign_at(low); + CGAL::Sign sign_p_high = p.sign_at(high); + + Field mid; + CGAL::Sign s; + + while ((q.sign_at(low)==CGAL::ZERO)||(q.sign_at(high)==CGAL::ZERO)) { + mid = (low+high)/Field(2); + simplify(mid); + s = p.sign_at(mid); + if (s == CGAL::ZERO) { + mid = (low+mid)/Field(2); + simplify(mid); + s = p.sign_at(mid); + } + CGAL_postcondition(s != CGAL::ZERO); + + if (s == sign_p_low) { + low = mid; + sign_p_low = s; //bogus? + } + else { + CGAL_assertion(s == sign_p_high); + high = mid; + sign_p_high = s; //bogus? + } + } + + return has_common_root; +} + +} //namespace internal + +} //namespace CGAL + +#endif //CGAL_REFINE_ZERO_AGAINST_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h new file mode 100644 index 00000000000..80ba473e175 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/shear.h @@ -0,0 +1,70 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + + +#ifndef CGAL_ACK_SHEAR_H +#define CGAL_ACK_SHEAR_H 1 + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { + +/*! \ingroup NiX_bivariate_polynomial_hacks + * \brief Computes the polynomial f(x+sy,y) + */ +template +CGAL::Polynomial > +shear(const CGAL::Polynomial >& f,NT s) { + typedef CGAL::Polynomial Poly_1; + typedef CGAL::Polynomial Poly_2; + + Poly_1 x(NT(0),NT(1)); + Poly_1 zero(NT(0)); + Poly_1 one(NT(1)); + Poly_2 for_x(x,Poly_1(NT(s))); + Poly_2 for_y(zero,one); + + std::vector coeffs; + coeffs.push_back(for_x); + coeffs.push_back(for_y); + + return typename CGAL::Polynomial_traits_d::Substitute() + (f,coeffs.begin(), coeffs.end()); + +} + +} // namespace internal + +} //namespace CGAL + +#endif // NiX_BIVARIATE_POLYNOMIAL_HACKS_H +// EOF diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/univariate_polynomial_utils.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/univariate_polynomial_utils.h new file mode 100644 index 00000000000..788be0e5445 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d/univariate_polynomial_utils.h @@ -0,0 +1,107 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#ifndef CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H +#define CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H + +#include + +namespace CGAL { + +namespace internal { + //! return an upper bound on the absolute value of all real roots of \c P. + /*! The upper bound is a power of two. Only works for univariate polynomials. + * \pre \c NT must be \c RealComparable. + * \relates CGAL::Polynomial + */ + template + NT weak_upper_root_bound(const Polynomial& P) { + // code comes from Kurt Mehlhorn + // see [Mignotte, 1992], p.144 for a proof + CGAL_precondition(Polynomial_traits_d::d == 0); + typename Real_embeddable_traits::Abs abs; + const int n = CGAL::degree(P); + NT x(1); + NT val; + for (;;) { + val = -abs(P[n]); + for (int i = n-1; i >= 0; i--) { + val = val*x + abs(P[i]); + } + if (val < NT(0)) return x; + x *= NT(2); + } + } + + //! return the number of sign variations in the coefficient sequence of \c P. + /*! This is the number of sign changes (+ to - or - to +) in the + * coefficient sequence of the polynomial, ignoring zeroes. + * Only meaningful for univariate polynomials. + * \pre \c NT must be \c RealComparable. + * \relates CGAL::Polynomial + */ + template + int sign_variations(const Polynomial& P) { + const int n = CGAL::degree(P); + int variations = 0; + int old_sign = CGAL::sign(P[n]); // never zero unless P is zero + for (int i = n-1; i >= 0; i--) { + int s = sign(P[i]); + if (s == 0) continue; + if (old_sign != s) { + old_sign = s; + variations++; + } + } + return variations; + } + + /*! \ingroup CGAL_polynomial_utils + * \brief checks whether a univariate polynomial is square-free + */ + + /*template < class NT > + bool is_square_free(const Polynomial& p) { + if( may_have_multiple_factor(p) ) { + Polynomial d = p; d.diff(); + return CGAL::degree(gcd_utcf(p, d)) == 0; + } else { + return true; + } + } + + template< class NT > + bool is_square_free( const Polynomail< Polynomial< NT > >& ) { + + + return true; + } */ + +} // namespace internal + +} //namespace CGAL + + +#endif // CGAL_POLYNOMIAL_UNIVARIATE_POLYNOMIAL_UTILS_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_1.h new file mode 100644 index 00000000000..b36fbb489d5 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_1.h @@ -0,0 +1,668 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// Sebastian Limbach +// Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_1_H +#define CGAL_ALGEBRAIC_KERNEL_D_1_H + +#ifndef CGAL_AK_ENABLE_DEPRECATED_INTERFACE +#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 0 +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { + +namespace internal { +template< class AlgebraicReal1, class Isolator_ > +class Algebraic_kernel_d_1_base { + +public: + typedef AlgebraicReal1 Algebraic_real_1; + typedef Isolator_ Isolator; + + typedef typename Algebraic_real_1::Coefficient Coefficient; + typedef typename Algebraic_real_1::Bound Bound; + typedef typename Algebraic_real_1::Polynomial_1 Polynomial_1; + + // TODO: Other choice? + typedef int size_type; + typedef int Multiplicity_type; + +private: + typedef CGAL::Polynomial_traits_d< Polynomial_1 > PT_1; + + +protected: + + // Some functors used for STL calls + template + struct Pair_first : public std::unary_function,A> { + A operator() (std::pair pair) const { return pair.first; } + }; + + template + struct Pair_second : public std::unary_function,B> { + B operator() (std::pair pair) const { return pair.second; } + }; + +public: + class Algebraic_real_traits { + public: + typedef Algebraic_real_1 Type; + + struct Bound_between + : public std::binary_function< Type, Type, Bound > { + Bound operator()( const Type& t1, + const Type& t2 ) const { +#if CGAL_AK_DONT_USE_SIMPLE_BOUND_BETWEEN +#warning uses deprecated bound_between_1 functor + return t1.rational_between( t2 ); +#else + return internal::simple_bound_between(t1,t2); +#endif + } + }; + + struct Lower_bound + : public std::unary_function< Type, Bound > { + Bound operator()( const Type& t ) const { + return t.low(); + } + }; + + struct Upper_bound + : public std::unary_function< Type, Bound > { + Bound operator()( const Type& t ) const { + return t.high(); + } + }; + + struct Refine + : public std::unary_function< Type, void > { + void operator()( const Type& t ) const { + t.refine(); + } + + void operator()( Type& t, int rel_prec ) const { + // If t is zero, we can refine the interval to + // infinite precission + if( CGAL::is_zero( t ) ) { + t = Type(0); + } else { + // Refine until both boundaries have the same sign + while( CGAL::sign( t.high() ) != + CGAL::sign( t.low() ) ) + t.refine(); + + CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO && + CGAL::sign( t.low() ) != CGAL::ZERO ); + + // Calculate the needed precision + Bound prec = Bound(1) / + CGAL::ipower( Bound(2), rel_prec ); + + // Refine until precision is reached + while( CGAL::abs( t.high() - t.low() ) / + (CGAL::max)( CGAL::abs( t.high() ), + CGAL::abs( t.low() ) ) > prec ) { + t.refine(); + + CGAL_assertion( CGAL::sign( t.high() ) != CGAL::ZERO && + CGAL::sign( t.low() ) != CGAL::ZERO ); + + } + } + } + }; + + struct Approximate_absolute_1: + public std::binary_function >{ + std::pair + operator()(const Algebraic_real_1& x, int prec) const { + Lower_bound lower; + Upper_bound upper; + Refine refine; + Bound l = lower(x); + Bound u = upper(x); + Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec)); + while((prec>0)?((u-l)*error>Bound(1)):((u-l)>error)){ + refine(x); + u = upper(x); + l = lower(x); + } + return std::make_pair(l,u); + } + }; + + struct Approximate_relative_1: + public std::binary_function >{ + std::pair + operator()(const Algebraic_real_1& x, int prec) const { + + if(CGAL::is_zero(x)) return std::make_pair(Bound(0),Bound(0)); + + Lower_bound lower; + Upper_bound upper; + Refine refine; + Bound l = lower(x); + Bound u = upper(x); + Bound error = CGAL::ipower(Bound(2),CGAL::abs(prec)); + Bound min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l)); + while((prec>0)?((u-l)*error>min_b):((u-l)>error*min_b)){ + refine(x); + u = upper(x); + l = lower(x); + min_b = (CGAL::min)(CGAL::abs(u),CGAL::abs(l)); + } + return std::make_pair(l,u); + } + }; + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + typedef Lower_bound Lower_boundary; + typedef Upper_bound Upper_boundary; + typedef Bound_between Boundary_between; +#endif + + + }; // class Algebraic_real_traits + + // Functors of Algebraic_kernel_d_1 + struct Solve_1 { + public: + template + OutputIterator + operator()(const Polynomial_1& p, OutputIterator oi) const { +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE +#else + CGAL_precondition(!CGAL::is_zero(p)); +#endif + internal::Real_roots< Algebraic_real_1, Isolator > real_roots; + std::list< int > mults; + std::list< Algebraic_real_1 > roots; + real_roots( p, std::back_inserter(roots), std::back_inserter( mults ) ); + CGAL_assertion(roots.size()==mults.size()); + std::list::iterator mit =mults.begin(); + typename std::list< Algebraic_real_1 >::iterator rit = roots.begin(); + while(rit != roots.end()) { + //*oi++ = std::make_pair(*rit, (unsigned int)(*mit)); + *oi++ = std::make_pair(*rit, *mit); + rit++; + mit++; + } + return oi; + } + +#if 1 || CGAL_AK_ENABLE_DEPRECATED_INTERFACE + template< class OutputIterator > + OutputIterator operator()( + const Polynomial_1& p, + OutputIterator oi , + bool known_to_be_square_free) const { + return this->operator()(p,known_to_be_square_free,oi); + } +#endif + + template< class OutputIterator > + OutputIterator operator()( + const Polynomial_1& p, + bool known_to_be_square_free, + OutputIterator oi) const { + + internal::Real_roots< Algebraic_real_1, Isolator > real_roots; +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE +#else + CGAL_precondition(!CGAL::is_zero(p)); +#endif + std::list roots; + if( known_to_be_square_free ){ + real_roots(p,std::back_inserter(roots)); + }else{ + std::list dummy; + real_roots(p,std::back_inserter(roots),std::back_inserter(dummy)); + } + return std::copy(roots.begin(),roots.end(),oi); + } + +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + template< class OutputIteratorRoots , class OutputIteratorMults > + std::pair + operator()( + const Polynomial_1& p, + OutputIteratorRoots roi, + OutputIteratorMults moi) const { + + internal::Real_roots< Algebraic_real_1, Isolator > real_roots; + real_roots(p,roi,moi); + return std::make_pair(roi,moi); + } +#endif + + protected: + + /* + // TODO: Can we avoid to use this? + struct Greater_compare : + public std::binary_function { + + bool operator() (const Algebraic_real_1& a, const Algebraic_real_1& b) + const { + return a>b; + } + + }; + */ + + public: + + template< class OutputIterator > + OutputIterator operator()(const Polynomial_1& p, Bound l, Bound u, + OutputIterator res) const { + + std::vector > roots; + this->operator() (p,std::back_inserter(roots)); + Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l); + Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u); + typedef typename + std::vector >::iterator + Iterator; + Pair_first pair_first; + Iterator it_start=std::lower_bound + (::boost::make_transform_iterator(roots.begin(),pair_first), + ::boost::make_transform_iterator(roots.end(),pair_first), + alg_l).base(); + Iterator it_end=std::upper_bound + (::boost::make_transform_iterator(it_start,pair_first), + ::boost::make_transform_iterator(roots.end(),pair_first), + alg_u).base(); + std::copy(it_start,it_end,res); + return res; + } + + template< class OutputIterator > + OutputIterator operator()(const Polynomial_1& p, + bool known_to_be_square_free, + Bound l, Bound u, + OutputIterator res) const { + + std::vector roots; + this->operator() (p,known_to_be_square_free,std::back_inserter(roots)); + Algebraic_real_1 alg_l=Construct_algebraic_real_1()(l); + Algebraic_real_1 alg_u=Construct_algebraic_real_1()(u); + typedef typename + std::vector::iterator + Iterator; + Iterator it_start=std::lower_bound(roots.begin(),roots.end(),alg_l); + Iterator it_end=std::upper_bound(it_start,roots.end(),alg_u); + std::copy(it_start,it_end,res); + return res; + } + + }; + + class Number_of_solutions_1 + : public std::unary_function { + + public: + + size_type operator() + (const Polynomial_1& p) const { + + std::vector > roots; + Solve_1()(p,std::back_inserter(roots)); + return roots.size(); + } + + }; + + + struct Sign_at_1 + : public std::binary_function< Polynomial_1, Algebraic_real_1, CGAL::Sign > { + CGAL::Sign operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const { + if(CGAL::is_zero(p)) return ZERO; + if(CGAL::degree(p)==0) return p.sign_at(0); + if( ar.low() == ar.high() ) return p.sign_at( ar.low() ); + + Polynomial_1 g = gcd_utcf(p,ar.polynomial()); + if (g.sign_at(ar.low()) != g.sign_at(ar.high())) return ZERO; + + while(internal::descartes(p,ar.low(),ar.high()) > 0) ar.refine(); + while( p.sign_at(ar.low()) == ZERO ) ar.refine(); + while( p.sign_at(ar.high()) == ZERO ) ar.refine(); + + CGAL::Sign result = p.sign_at(ar.low()); + CGAL_assertion(result == p.sign_at(ar.high())); + return result; + } + }; + struct Is_zero_at_1 + : public std::binary_function< Polynomial_1, Algebraic_real_1, bool > { + bool operator()( const Polynomial_1& p, const Algebraic_real_1& ar ) const { + if(CGAL::is_zero(p)) return true; + if( ar.low() == ar.high() ) return p.sign_at( ar.low() ) == ZERO; + Polynomial_1 g = gcd_utcf(p,ar.polynomial()); + return g.sign_at(ar.low()) != g.sign_at(ar.high()); + } + }; + + struct Is_square_free_1 + : public std::unary_function< Polynomial_1, bool > { + bool operator()( const Polynomial_1& p ) const { + typename CGAL::Polynomial_traits_d< Polynomial_1 >::Is_square_free isf; + return isf(p); + } + }; + + struct Is_coprime_1 + : public std::binary_function< Polynomial_1, Polynomial_1, bool > { + bool operator()( const Polynomial_1& p1, const Polynomial_1& p2 ) const { + typename CGAL::Polynomial_traits_d< Polynomial_1 >::Total_degree total_degree; + + // TODO: Is GCD already filtered? + return( total_degree( gcd_utcf( p1, p2 ) ) == 0 ); + } + }; + + struct Make_square_free_1 + : public std::unary_function< Polynomial_1, Polynomial_1 > { + Polynomial_1 operator()( const Polynomial_1& p ) const { + return typename CGAL::Polynomial_traits_d< Polynomial_1 >::Make_square_free()( p ); + } + }; + + struct Make_coprime_1 { + typedef bool result_type; + typedef Polynomial_1 first_argument_type; + typedef Polynomial_1 second_argument_type; + typedef Polynomial_1 third_argument_type; + typedef Polynomial_1 fourth_argument_type; + typedef Polynomial_1 fifth_argument_type; + + bool operator()( const Polynomial_1& p1, + const Polynomial_1& p2, + Polynomial_1& g, // ggT utcf + Polynomial_1& q1, // Rest utcf + Polynomial_1& q2 ) const { + g = typename CGAL::Polynomial_traits_d< Polynomial_1 >::Gcd_up_to_constant_factor()( p1, p2 ); + q1 = p1 / g; + q2 = p2 / g; + return CGAL::is_one(g); + } + }; + + + struct Square_free_factorize_1 { + template< class OutputIterator> + OutputIterator operator()( const Polynomial_1& p, OutputIterator it) const { + typename PT_1::Square_free_factorize_up_to_constant_factor sqff; + return sqff(p,it); + } + }; + + struct Compute_polynomial_1 : public std::unary_function { + Polynomial_1 operator()(const Algebraic_real_1& x) const { + return x.polynomial(); + } + }; + + struct Construct_algebraic_real_1 { + + public: + + typedef Algebraic_real_1 result_type; + + result_type operator() (int a) const { + return Algebraic_real_1(a); + } + + result_type operator() (Bound a) const { + return Algebraic_real_1(a); + } + + result_type operator() + (typename CGAL::First_if_different::Type a) const { + Coefficient coeffs[2] = {a,Coefficient(-1)}; + Polynomial_1 p = typename PT_1::Construct_polynomial() + (coeffs,coeffs+2); + std::vector roots; + Solve_1()(p,true,std::back_inserter(roots)); + CGAL_assertion(roots.size() == size_type(1)); + return roots[0]; + } + + + result_type operator() (Polynomial_1 p,size_type i) + const { + std::vector roots; + Solve_1()(p,true,std::back_inserter(roots)); + CGAL_assertion( size_type(roots.size()) > i); + return roots[i]; + } + + result_type operator() (Polynomial_1 p, + Bound l, Bound u) const { + CGAL_precondition(l{ + + typedef CGAL::Comparison_result result_type; + + result_type operator() (Algebraic_real_1 a,Algebraic_real_1 b) const { + return typename Real_embeddable_traits + ::Compare() (a,b); + } + + result_type operator() (Algebraic_real_1 a,int b) const { + return this->operator()(a,Construct_algebraic_real_1()(b)); + } + + result_type operator() (Algebraic_real_1 a,Bound b) const { + return this->operator()(a,Construct_algebraic_real_1()(b)); + } + + + result_type operator() + (Algebraic_real_1 a, + typename CGAL::First_if_different::Type b) const { + return this->operator()(a,Construct_algebraic_real_1()(b)); + } + + result_type operator() (int a, Algebraic_real_1 b) const { + return this->operator()(Construct_algebraic_real_1()(a),b); + } + + result_type operator() (Bound a,Algebraic_real_1 b) const { + return this->operator()(Construct_algebraic_real_1()(a),b); + } + + + result_type operator() + (typename CGAL::First_if_different::Type a, + Algebraic_real_1 b) const { + return this->operator()(Construct_algebraic_real_1()(a),b); + } + + }; + + public: + + struct Isolate_1 : public std::binary_function + < Algebraic_real_1,Polynomial_1,std::pair > { + + public: + + std::pair operator() (const Algebraic_real_1 a, + const Polynomial_1 p) const { + std::vector roots; + // First isolate p... + Solve_1()(p,false,std::back_inserter(roots)); + typedef typename std::vector::iterator Iterator; + // Binary search on the root to find a place where a could be inserted + std::pair it_pair + = equal_range(roots.begin(),roots.end(),a); + CGAL_assertion(std::distance(it_pair.first,it_pair.second)==0 || + std::distance(it_pair.first,it_pair.second)==1); + // If we can insert a in two places, it must have been in roots already + bool a_in_roots = std::distance(it_pair.first,it_pair.second)==1; + if(a_in_roots) { + // TODO: can we rely on the property that the isolating intervals + // of the roots in p are isolating from each other. What + // if p was factorized during isolation? Is that still + // guaranteed? To be sure, we do it this way: + if(it_pair.first!=roots.begin()) { + it_pair.first->strong_refine(*(it_pair.first-1)); + } + if(it_pair.second!=roots.end()) { + it_pair.first->strong_refine(*(it_pair.second)); + } + return std::make_pair(it_pair.first->low(),it_pair.first->high()); + } else { + // Refine a until disjoint from neighbors + // This is probably not even necessary since the isolating + // interval of a isolates against all roots of p thanks to the + // comparisons. But to be sure... + if(it_pair.first!=roots.begin()) { + a.strong_refine(*(it_pair.first-1)); + } + if(it_pair.first!=roots.end()) { + a.strong_refine(*(it_pair.first)); + } + return std::make_pair(a.low(),a.high()); + } + } + + }; + + typedef typename Algebraic_real_traits::Bound_between Bound_between_1; + typedef typename Algebraic_real_traits::Approximate_absolute_1 Approximate_absolute_1; + typedef typename Algebraic_real_traits::Approximate_relative_1 Approximate_relative_1; + + + + +#define CGAL_ALGEBRAIC_KERNEL_1_PRED(Y,Z) Y Z() const { return Y(); } +#define CGAL_ALGEBRAIC_KERNEL_1_PRED_WITH_KERNEL \ + Y Z() const { return Y((const Algebraic_kernel_d_1*)this); } + + + CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_square_free_1, + is_square_free_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_square_free_1, + make_square_free_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Square_free_factorize_1, + square_free_factorize_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_coprime_1, + is_coprime_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Make_coprime_1, + make_coprime_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Solve_1, + solve_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Number_of_solutions_1, + number_of_solutions_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Construct_algebraic_real_1, + construct_algebraic_real_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Sign_at_1, + sign_at_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Is_zero_at_1, + is_zero_at_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Compare_1,compare_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Bound_between_1, + bound_between_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_absolute_1, + approximate_absolute_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Approximate_relative_1, + approximate_relative_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Compute_polynomial_1, + compute_polynomial_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Isolate_1, + isolate_1_object); + + // Deprecated +#if CGAL_AK_ENABLE_DEPRECATED_INTERFACE + typedef Bound Boundary; + typedef typename Algebraic_real_traits::Refine Refine_1; + typedef typename Algebraic_real_traits::Lower_bound Lower_bound_1; + typedef typename Algebraic_real_traits::Upper_bound Upper_bound_1; + typedef typename Algebraic_real_traits::Lower_bound Lower_boundary_1; + typedef typename Algebraic_real_traits::Upper_bound Upper_boundary_1; + typedef Bound_between_1 Boundary_between_1; + + CGAL_ALGEBRAIC_KERNEL_1_PRED(Refine_1, refine_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_bound_1, lower_bound_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_bound_1, upper_bound_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Lower_boundary_1, lower_boundary_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Upper_boundary_1, upper_boundary_1_object); + CGAL_ALGEBRAIC_KERNEL_1_PRED(Boundary_between_1, boundary_between_1_object); +#endif + +#undef CGAL_ALGEBRAIC_KERNEL_1_PRED + +}; +} // namespace internal + + +template< class Coefficient, + class Bound = typename CGAL::Get_arithmetic_kernel< Coefficient >::Arithmetic_kernel::Rational, + class RepClass = internal::Algebraic_real_rep< Coefficient, Bound >, + class Isolator = internal::Descartes< typename CGAL::Polynomial_type_generator::Type, Bound > > +class Algebraic_kernel_d_1 + : public internal::Algebraic_kernel_d_1_base< + + // Template argument #1 (AlgebraicReal1) + internal::Algebraic_real_d_1< + Coefficient, + Bound, + ::CGAL::Handle_policy_no_union, + RepClass >, + + // Template argument #2 (Isolator_) + Isolator > + +{}; + + +} //namespace CGAL + + + +#endif // CGAL_ALGEBRAIC_KERNEL_D_1_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_2.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_2.h new file mode 100644 index 00000000000..eaa3afcfef3 --- /dev/null +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_d_2.h @@ -0,0 +1,42 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#ifndef CGAL_ALGEBRAIC_KERNEL_D_2_H +#define CGAL_ALGEBRAIC_KERNEL_D_2_H + +#include + +#include +#include + +namespace CGAL { + +template class Algebraic_kernel_d_2 + : public CGAL::Algebraic_curve_kernel_2 + < CGAL::Algebraic_kernel_d_1 > +{}; + +} //namespace CGAL + + + +#endif // CGAL_ALGEBRAIC_KERNEL_D_1_H diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_d_1.h similarity index 99% rename from Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_1.h rename to Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_d_1.h index 137f7f36319..d5a88a31fee 100644 --- a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_1.h +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpq_d_1.h @@ -24,7 +24,7 @@ namespace CGAL{ -typedef Algebraic_kernel_rs_1 Algebraic_kernel_rs_gmpq_1; +typedef Algebraic_kernel_rs_1 Algebraic_kernel_rs_gmpq_d_1; } diff --git a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_1.h b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_d_1.h similarity index 99% rename from Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_1.h rename to Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_d_1.h index 31f0c2cf4e2..514b8565aa1 100644 --- a/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_1.h +++ b/Algebraic_kernel_d/include/CGAL/Algebraic_kernel_rs_gmpz_d_1.h @@ -24,7 +24,7 @@ namespace CGAL{ -typedef Algebraic_kernel_rs_1 Algebraic_kernel_rs_gmpz_1; +typedef Algebraic_kernel_rs_1 Algebraic_kernel_rs_gmpz_d_1; } diff --git a/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_comparisons.h b/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_comparisons.h index 82a9ac8c037..911d6a7559f 100644 --- a/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_comparisons.h +++ b/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_comparisons.h @@ -19,6 +19,7 @@ #ifndef CGAL_RS_ALGEBRAIC_1_COMPARISONS_H #define CGAL_RS_ALGEBRAIC_1_COMPARISONS_H +#include #include #include @@ -37,12 +38,12 @@ bool operator==(const Algebraic_1 &n1,const Algebraic_1 &n2){ } inline -Algebraic_1 min(const Algebraic_1 &a,const Algebraic_1 &b){ +Algebraic_1 min BOOST_PREVENT_MACRO_SUBSTITUTION (const Algebraic_1 &a,const Algebraic_1 &b){ return (ab?a:b); } diff --git a/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_real_embeddable.h b/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_real_embeddable.h index b9dacb44228..2f09aefa50e 100644 --- a/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_real_embeddable.h +++ b/Algebraic_kernel_d/include/CGAL/RS/algebraic_1_real_embeddable.h @@ -14,7 +14,7 @@ // $URL$ // $Id$ // -// Author(s) : Michael Hemmer +// Author(s) : Michael Hemmer // // ============================================================================ diff --git a/Algebraic_kernel_d/package_info/Algebraic_kernel_RS/maintainer b/Algebraic_kernel_d/package_info/Algebraic_kernel_RS/maintainer index b3b1e9ccdc4..6853b2b9d18 100644 --- a/Algebraic_kernel_d/package_info/Algebraic_kernel_RS/maintainer +++ b/Algebraic_kernel_d/package_info/Algebraic_kernel_RS/maintainer @@ -1 +1 @@ -Luis PeÃąaranda +Luis Peņaranda diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_curve_kernel_2.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_curve_kernel_2.cpp new file mode 100644 index 00000000000..8b0301a451d --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_curve_kernel_2.cpp @@ -0,0 +1,128 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Pavel Emeliyanenko +// +// ============================================================================ + +// code coverage test for Algebraic_curve_kernel_2 + +#define CGAL_ACK_DEBUG_FLAG 0 + +#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 1 + +#include +#include + +#include + +#if CGAL_ACK_USE_EXACUS +#include +#include +#endif + +#include +#include +#include +#include + +#if CGAL_ACK_WITH_FILTERED_KERNEL +#include +#endif + +#include + +#include + +template< class ArithmeticTraits > +void test_algebraic_curve_kernel_2() { + + typedef ArithmeticTraits AT; + typedef typename AT::Integer Coefficient; + typedef typename AT::Rational Rational; + + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi + < Coefficient, Rational > Rep_class; + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits< + CGAL::internal::Bitstream_coefficient_kernel > > + Isolator; + + typedef CGAL::Algebraic_kernel_d_1 + Algebraic_kernel_d_1; + +#if CGAL_ACK_USE_EXACUS + typedef AcX::Algebraic_curve_2 Algebraic_curve_2; + typedef AcX::Algebraic_curve_pair_2 + Algebraic_curve_pair_2; + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#else + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#endif + + //std::cout << "Non-filtered kernel..." << std::endl; + CGAL::internal::test_algebraic_curve_kernel_2(); + +#if CGAL_ACK_WITH_FILTERED_KERNEL + //std::cout << "Filtered kernel..." << std::endl; +#if CGAL_ACK_USE_EXACUS + + typedef CGAL::Filtered_algebraic_curve_kernel_2 + Filtered_kernel_2; +#else + typedef CGAL::Filtered_algebraic_curve_kernel_2 + Filtered_kernel_2; +#endif + + CGAL::internal::test_algebraic_curve_kernel_2(); + +#endif +} + +int main() { + + +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING LEDA" << std::endl; +#endif + test_algebraic_curve_kernel_2(); +#else + std::cerr << "LEDA tests skipped" << std::endl; +#endif + + +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING CORE" << std::endl; +#endif + + test_algebraic_curve_kernel_2(); +#else + std::cerr << "CORE tests skipped" << std::endl; +#endif + + +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING GMP" << std::endl; +#endif + test_algebraic_curve_kernel_2(); +#else + std::cerr << "GMP tests skipped" << std::endl; +#endif + + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_CORE.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_CORE.cpp new file mode 100644 index 00000000000..77fc0ddd44e --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_CORE.cpp @@ -0,0 +1,101 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Sebastian Limbach +// Michael Hemmer +// +// ============================================================================ + +// Test of Algebraic_kernel + +#define CGAL_TEST_ALL_AK_VARIANTS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +template< class Coefficient_, class Bound_, class RepClass > +void test_algebraic_kernel_coeff_bound_rep() { + typedef Coefficient_ Coefficient; + typedef Bound_ Bound; + typedef RepClass Rep_class; + + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial_1; + typedef CGAL::internal::Algebraic_real_d_1 + < Coefficient, Bound, CGAL::Handle_policy_no_union, Rep_class > Algebraic_real_1; + + typedef CGAL::internal::Descartes< Polynomial_1, Bound > Descartes; + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > BDescartes; +// typedef CGAL::internal::Bitstream_descartes< Polynomial_1, Bound > BDescartes; + + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , Descartes> + Kernel_Descartes; + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , BDescartes> + Kernel_BDescartes; + + CGAL::test_algebraic_kernel_1(Kernel_Descartes()); +#if CGAL_TEST_ALL_AK_VARIANTS + CGAL::test_algebraic_kernel_1(Kernel_BDescartes()); +#endif +} + + +template< class Coeff, class Bound > +void test_algebraic_kernel_coeff_bound() { + test_algebraic_kernel_coeff_bound_rep > (); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound_rep > (); + test_algebraic_kernel_coeff_bound_rep > (); +#endif +} + + +template< class ArithmeticKernel > +void test_algebraic_kernel() { + typedef ArithmeticKernel AK; + typedef typename AK::Integer Integer; + typedef typename AK::Rational Rational; + + test_algebraic_kernel_coeff_bound(); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); +#endif +} + +int main() { +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING CORE " << std::endl; + test_algebraic_kernel< CGAL::CORE_arithmetic_kernel >(); +#else + std::cout << " NOTHING TESTED " << std::endl; +#endif + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_GMP.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_GMP.cpp new file mode 100644 index 00000000000..83c46361234 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_GMP.cpp @@ -0,0 +1,102 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Sebastian Limbach +// Michael Hemmer +// +// ============================================================================ + +// Test of Algebraic_kernel + +#define CGAL_TEST_ALL_AK_VARIANTS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +template< class Coefficient_, class Bound_, class RepClass > +void test_algebraic_kernel_coeff_bound_rep() { + typedef Coefficient_ Coefficient; + typedef Bound_ Bound; + typedef RepClass Rep_class; + + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial_1; + typedef CGAL::internal::Algebraic_real_d_1 + < Coefficient, Bound, CGAL::Handle_policy_no_union, Rep_class > Algebraic_real_1; + + typedef CGAL::internal::Descartes< Polynomial_1, Bound > Descartes; + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > BDescartes; +// typedef CGAL::internal::Bitstream_descartes< Polynomial_1, Bound > BDescartes; + + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , Descartes> + Kernel_Descartes; + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , BDescartes> + Kernel_BDescartes; + + CGAL::test_algebraic_kernel_1(Kernel_Descartes()); +#if CGAL_TEST_ALL_AK_VARIANTS + CGAL::test_algebraic_kernel_1(Kernel_BDescartes()); +#endif +} + + +template< class Coeff, class Bound > +void test_algebraic_kernel_coeff_bound() { + test_algebraic_kernel_coeff_bound_rep > (); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound_rep > (); + test_algebraic_kernel_coeff_bound_rep > (); +#endif +} + + +template< class ArithmeticKernel > +void test_algebraic_kernel() { + typedef ArithmeticKernel AK; + typedef typename AK::Integer Integer; + typedef typename AK::Rational Rational; + + test_algebraic_kernel_coeff_bound(); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); +#endif +} + +int main() { +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING GMP " << std::endl; + test_algebraic_kernel< CGAL::GMP_arithmetic_kernel >(); +#else + std::cout << " NOTHING TESTED " << std::endl; +#endif + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_LEDA.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_LEDA.cpp new file mode 100644 index 00000000000..575bb2ad298 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_1_LEDA.cpp @@ -0,0 +1,102 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Sebastian Limbach +// Michael Hemmer +// +// ============================================================================ + +// Test of Algebraic_kernel + +#define CGAL_TEST_ALL_AK_VARIANTS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +template< class Coefficient_, class Bound_, class RepClass > +void test_algebraic_kernel_coeff_bound_rep() { + typedef Coefficient_ Coefficient; + typedef Bound_ Bound; + typedef RepClass Rep_class; + + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial_1; + typedef CGAL::internal::Algebraic_real_d_1 + < Coefficient, Bound, CGAL::Handle_policy_no_union, Rep_class > Algebraic_real_1; + + typedef CGAL::internal::Descartes< Polynomial_1, Bound > Descartes; + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > BDescartes; +// typedef CGAL::internal::Bitstream_descartes< Polynomial_1, Bound > BDescartes; + + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , Descartes> + Kernel_Descartes; + typedef CGAL::Algebraic_kernel_d_1< Coefficient, Bound, Rep_class , BDescartes> + Kernel_BDescartes; + + CGAL::test_algebraic_kernel_1(Kernel_Descartes()); +#if CGAL_TEST_ALL_AK_VARIANTS + CGAL::test_algebraic_kernel_1(Kernel_BDescartes()); +#endif +} + + +template< class Coeff, class Bound > +void test_algebraic_kernel_coeff_bound() { + test_algebraic_kernel_coeff_bound_rep > (); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound_rep > (); + test_algebraic_kernel_coeff_bound_rep > (); +#endif +} + + +template< class ArithmeticKernel > +void test_algebraic_kernel() { + typedef ArithmeticKernel AK; + typedef typename AK::Integer Integer; + typedef typename AK::Rational Rational; + + test_algebraic_kernel_coeff_bound(); +#if CGAL_TEST_ALL_AK_VARIANTS + test_algebraic_kernel_coeff_bound(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); + test_algebraic_kernel_coeff_bound + , Rational>(); +#endif +} + +int main() { +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING LEDA " << std::endl; + test_algebraic_kernel< CGAL::LEDA_arithmetic_kernel >(); +#else + std::cout << " NOTHING TESTED " << std::endl; +#endif + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_2.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_2.cpp new file mode 100644 index 00000000000..f075abe0212 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_d_2.cpp @@ -0,0 +1,105 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +// code coverage test for Algebraic_curve_kernel_2 + +// #define CGAL_ACK_DEBUG_FLAG 1 + +//#define CGAL_AK_ENABLE_DEPRECATED_INTERFACE 1 + +#include +#include + +#include + +#include + +#include + +#include + + +template< typename Coefficient > +void test_algebraic_kernel() { + typedef CGAL::Algebraic_kernel_d_2 Algebraic_kernel_d_2; + Algebraic_kernel_d_2 ak_2; + CGAL::test_algebraic_kernel_2(ak_2); +} + +int main() { + + +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING LEDA" << std::endl; +#endif + { + + typedef CGAL::LEDA_arithmetic_kernel AK; + test_algebraic_kernel(); + /* + test_algebraic_kernel(); + test_algebraic_kernel >(); + + test_algebraic_kernel + >(); + */ + } +#else + std::cerr << "LEDA tests skipped" << std::endl; +#endif + + +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING CORE" << std::endl; +#endif + { + typedef CGAL::CORE_arithmetic_kernel AK; + test_algebraic_kernel(); + /* + test_algebraic_kernel(); + test_algebraic_kernel >(); + + test_algebraic_kernel + >(); + */ + } +#else + std::cerr << "CORE tests skipped" << std::endl; +#endif + + +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "TESTING GMP" << std::endl; +#endif + { + typedef CGAL::GMP_arithmetic_kernel AK; + test_algebraic_kernel(); + /* + test_algebraic_kernel(); + test_algebraic_kernel >(); + + test_algebraic_kernel + >(); + */ + } +#else + std::cerr << "GMP tests skipped" << std::endl; +#endif + + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_1.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_d_1.cpp similarity index 97% rename from Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_1.cpp rename to Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_d_1.cpp index ec22d66f3cb..5c8bb11f631 100644 --- a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_1.cpp +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpq_d_1.cpp @@ -20,12 +20,12 @@ #if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) -#include +#include #include "include/CGAL/_test_algebraic_kernel_1.h" int main(){ - typedef CGAL::Algebraic_kernel_rs_gmpq_1 AK; + typedef CGAL::Algebraic_kernel_rs_gmpq_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Coefficient Coefficient; typedef AK::Bound Bound; diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_1.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_d_1.cpp similarity index 95% rename from Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_1.cpp rename to Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_d_1.cpp index 73152dc7629..2de5e8e5d68 100644 --- a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_1.cpp +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_kernel_rs_gmpz_d_1.cpp @@ -20,19 +20,19 @@ #if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) -#include +#include #include "include/CGAL/_test_algebraic_kernel_1.h" int main(){ - typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; + typedef CGAL::Algebraic_kernel_rs_gmpz_d_1 AK; typedef AK::Polynomial_1 Polynomial_1; typedef AK::Coefficient Coefficient; typedef AK::Bound Bound; typedef AK::Algebraic_real_1 Algebraic_real_1; typedef AK::Multiplicity_type Multiplicity_type; - AK ak; // an object of Algebraic_kernel_rs_gmpz_1 + AK ak; // an object of Algebraic_kernel_rs_gmpz_d_1 CGAL::test_algebraic_kernel_1(ak); AK::Solve_1 solve_1 = ak.solve_1_object(); diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_real_d_1.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_real_d_1.cpp new file mode 100644 index 00000000000..81d28a9f107 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Algebraic_real_d_1.cpp @@ -0,0 +1,372 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file NiX/Algebraic_real_d_1.C + This is the test file for the class NiX::Algebraic_real_d_1. +*/ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* +Coefficient_ Coefficient type of Polynomial +REAL a FieldWithSqrt +RATIONAL a numbertype representing the rational numbers +Z a numbertype representing Z (needed for Descartes) +*/ +template +void algebraic_number_test() +{ + typedef Coefficient_ Coefficient; + typedef Rational_ Rational; + + typedef CGAL::internal::Algebraic_real_d_1 Algebraic_real_d_1; + typedef typename CGAL::Polynomial_type_generator::Type Poly; + CGAL::test_real_embeddable(); + // general test of comparable functionality + + // TODO generates a precondition error in Algebraic_real_rep + //NiX::test_real_comparable(); + + // test of constructors + Poly P_00(Coefficient(0)); // zero polynomial + Poly P_01(Coefficient(1)); // constant polynomial + Poly P_1(Coefficient(-1),Coefficient(1)); //(x-1) + Poly P_2(Coefficient(-2),Coefficient(1)); //(x-2) + Poly P_3(Coefficient(-3),Coefficient(1)); //(x-3) + Poly P_4(Coefficient(-4),Coefficient(1)); //(x-4) + Poly P_12=P_1*P_2; //(x-1)(x-2) + Poly P_123=P_1*P_2*P_3; //(x-1)(x-2)(x-3) + Poly P_s2(Coefficient(-2),Coefficient(0),Coefficient(1)); //(x^2-2) + Poly P_s3(Coefficient(-3),Coefficient(0),Coefficient(1)); //(x^2-3) + Poly P_s5(-Coefficient(5),Coefficient(0),Coefficient(1)); + Poly P_s10(-Coefficient(10),Coefficient(0),Coefficient(1)); + Poly P_s30(-Coefficient(30),Coefficient(0),Coefficient(1)); + Poly P_s2510= P_s2*P_s5*P_s10; + Poly P_s530= P_s5 * P_s30; + + Algebraic_real_d_1 tmp; + Algebraic_real_d_1 tmp1,tmp2; + + Rational m; + // general constructors; + // default + // tmp = IS_Rational_ = 0 + tmp = Algebraic_real_d_1(); + assert(tmp.is_rational()); + assert(tmp.rational()==0); + // from int + tmp = Algebraic_real_d_1(1); + assert(tmp.is_rational()); + assert(tmp.rational()==1); + + tmp = Algebraic_real_d_1(5); + assert(tmp.is_rational()); + assert(tmp.rational()==5); + + // from Field + tmp = Algebraic_real_d_1(Rational(0)); + assert(tmp.is_rational()); + assert(tmp.rational()==0); + + tmp = Algebraic_real_d_1(Rational(1)); + assert(tmp.is_rational()); + assert(tmp.rational()==1); + + tmp = Algebraic_real_d_1(Rational(5)/ Rational(2)); + assert(tmp.is_rational()); + assert(tmp.rational()== Rational(5)/ Rational(2)); + + // general constructor + // tmp = 1 +#if 0 + tmp = Algebraic_real_d_1(P_1,-2,+2); + // TODO different behavior with leda and core + assert(!tmp.is_rational()); + assert(tmp==Rational(1)); + assert(tmp.is_rational()); + assert(tmp.rational()==1); +#endif + + // special constructors + // from int + tmp = Algebraic_real_d_1(2); + assert(tmp.is_rational()); + assert(tmp.rational()==Rational(2)); + //from Rational + tmp = Algebraic_real_d_1(Rational(2)); + assert(tmp.is_rational()); + assert(tmp.rational()==Rational(2)); + + // member functions + // tmp IS_GENERAL == 2; + + tmp = Algebraic_real_d_1(P_123,Rational(3)/2,Rational(5)/2); + assert(!tmp.is_rational()); + assert(tmp.polynomial()==P_123); + assert(tmp.low()==Rational(3)/2); + assert(tmp.high()==Rational(5)/2); + assert(tmp.sign_at_low()==P_123.sign_at(Rational(3)/2)); + + // refine + tmp = Algebraic_real_d_1(P_123,Rational(3)/2,Rational(5)/2); + tmp.refine(); + assert(tmp.is_rational()); + assert(tmp.rational()==Rational(2)); + // tmp IS_GENERAL = sqrt 2 + tmp = Algebraic_real_d_1(P_s2*P_3,Rational(1),Rational(2)); + tmp.refine(); + assert(tmp.low() >= Rational(1)); + assert(tmp.high() <= Rational(3)/2); + + // strong_refine + // tmp IS_GENERAL == 2; + + tmp = Algebraic_real_d_1(P_123,Rational(3)/2,Rational(5)/2); + m = Rational(2); + tmp.strong_refine(m); + assert(tmp.is_rational()); + assert(tmp.rational()==Rational(2)); + // tmp IS_GENERAL = sqrt 2 + tmp = Algebraic_real_d_1(P_s2*P_3,Rational(1),Rational(2)); + m = Rational(3)/2; + tmp.strong_refine(m); + assert(tmp.low()!=m); + assert(tmp.high()!=m); + + // refine_to(a,b) + // tmp IS_GENERAL = sqrt 2 + tmp = Algebraic_real_d_1(P_s2*P_4,Rational(0),Rational(3)); + assert(!tmp.is_rational()); + tmp.refine_to(Rational(1), Rational(2)); + assert(tmp.low() >= Rational(1)); + assert(tmp.high() <= Rational(2)); + + // tmp IS_REAL = sqrt 2 + tmp = Algebraic_real_d_1(P_s2,Rational(0),Rational(3)); + assert(!tmp.is_rational()); + tmp.refine_to(Rational(1), Rational(2)); + assert(tmp.low() >= Rational(1)); + assert(tmp.high() <= Rational(2)); + + // compare(rat) + // tmp IS_GENERAL = sqrt 2 + tmp = Algebraic_real_d_1(P_s2*P_3,Rational(1),Rational(2)); + m = Rational(1); + assert(tmp.compare(m)==1); + m = Rational(2); + assert(tmp.compare(m)==-1); + // tmp IS_GENERAL = 3 + tmp = Algebraic_real_d_1(P_s2*P_3,Rational(2),Rational(4)); + m = Rational(3); + assert(tmp.compare(m)==0); + assert(tmp.is_rational()); + assert(tmp.rational()==Rational(3)); + assert(CGAL::degree(tmp.polynomial()) == 1); + assert(tmp.polynomial().evaluate(Coefficient(3)) == Coefficient(0)); + + // compare_distinct() + + tmp1 = Algebraic_real_d_1(P_s530, Rational(2), Rational(3)); // sqrt(5) = 2.236... + tmp2 = Algebraic_real_d_1(P_s530, Rational(5), Rational(6)); // sqrt(30) = 5.477... + assert(tmp1.compare_distinct(tmp2) == CGAL::SMALLER); + assert(tmp2.compare_distinct(tmp1) == CGAL::LARGER); + + //member functions + // is_root_of + tmp1 = Algebraic_real_d_1(P_s2510,Rational(1)/2,Rational(3)/2); + assert(tmp1.is_root_of(P_s530*P_s2)); + tmp1 = Algebraic_real_d_1(P_s2510,Rational(1)/2,Rational(3)/2); + assert(!tmp1.is_root_of(P_s530)); + + //rational_between + { + Rational r; + tmp1 = Algebraic_real_d_1(P_s2,Rational(1),Rational(2)); //sqrt2 + tmp2 = Algebraic_real_d_1(P_s3,Rational(1),Rational(3)); //sqrt3 + r = tmp1.rational_between(tmp2); + assert(tmp1.compare(r)==CGAL::SMALLER); + assert(tmp2.compare(r)==CGAL::LARGER); + + r = tmp2.rational_between(tmp1); + assert(tmp1.compare(r)==CGAL::SMALLER); + assert(tmp2.compare(r)==CGAL::LARGER); + } + + // to_double() + tmp = Algebraic_real_d_1(P_1*P_3*P_4, Rational(0), Rational(2)); + assert(fabs(tmp.to_double() - 1.0) < 1e-10); + tmp = Algebraic_real_d_1(P_1*P_3, Rational(0), Rational(2)); + assert(fabs(tmp.to_double() - 1.0) < 1e-10); + tmp = Algebraic_real_d_1(P_1, Rational(0), Rational(2)); + assert(fabs(tmp.to_double() - 1.0) < 1e-10); + + //IO tested in _test_algebraic_kernel_1.h + + // test for Handle with union + { + typedef + CGAL::internal::Algebraic_real_d_1 + Int; + Int i(5); + Int j(5); + Int k(6); + assert( ! i.identical( j)); + assert( ! i.identical( k)); + assert( ! j.identical( k)); + assert( i == j); + assert( ! (i == k)); + assert( i.identical( j)); + assert( ! i.identical( k)); + assert( ! j.identical( k)); + // code coverage + assert( i == j); + } + // test for Handle without union + { + typedef + CGAL::internal::Algebraic_real_d_1 + Int; + Int i(5); + Int j(5); + Int k(6); + assert( ! i.identical( j)); + assert( ! i.identical( k)); + assert( ! j.identical( k)); + assert( i == j); + assert( ! (i == k)); + assert( ! i.identical( j)); + assert( ! i.identical( k)); + assert( ! j.identical( k)); + } + + +// to_interval +// { +// Algebraic_real_d_1 TMP; +// assert(CGAL::in(25.0,CGAL::to_interval(Algebraic_real_d_1(25)))); +// assert(CGAL::in(sqrt(2),CGAL::to_interval(Algebraic_real_d_1(P_s2,1,2)))); +// assert(CGAL::in(sqrt(2),CGAL::to_interval(Algebraic_real_d_1(P_s2510,1,2)))); +// assert(CGAL::in(-sqrt(2),CGAL::to_interval(Algebraic_real_d_1(P_s2510,-2,-1)))); +// assert(CGAL::in(sqrt(5),CGAL::to_interval(Algebraic_real_d_1(P_s2510,2,3)))); +// assert(CGAL::in(-sqrt(5),CGAL::to_interval(Algebraic_real_d_1(P_s2510,-3,-2)))); +// assert(CGAL::in(sqrt(10),CGAL::to_interval(Algebraic_real_d_1(P_s2510,3,4)))); +// assert(CGAL::in(-sqrt(10),CGAL::to_interval(Algebraic_real_d_1(P_s2510,-4,-3)))); +// } + + //simplify + { + // just a synatx check + Algebraic_real_d_1(P_s2510,1,2).simplify(); + } +} + +template +void algebraic_number_test_at(){ + typedef typename AT::Integer Integer; + typedef typename AT::Rational Rational; + typedef typename CGAL::Sqrt_extension Ext_int_int; + typedef typename CGAL::Sqrt_extension Ext_rat_int; + typedef typename CGAL::Sqrt_extension Ext_rat_rat; + + + typedef CGAL::internal::Algebraic_real_rep< Integer, Rational> Rep_int; + typedef CGAL::internal::Algebraic_real_rep< Rational, Rational > Rep_rat; + typedef CGAL::internal::Algebraic_real_rep< Ext_int_int, Rational > Rep_ext_int_int; + typedef CGAL::internal::Algebraic_real_rep< Ext_rat_int, Rational > Rep_ext_rat_int; + typedef CGAL::internal::Algebraic_real_rep< Ext_rat_rat, Rational > Rep_ext_rat_rat; + + + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + + + typedef CGAL::internal::Algebraic_real_rep_bfi< Integer, Rational> Rep_bfi_int; + typedef CGAL::internal::Algebraic_real_rep_bfi< Rational, Rational > Rep_bfi_rat; + typedef CGAL::internal::Algebraic_real_rep_bfi< Ext_int_int, Rational > Rep_bfi_ext_int_int; + typedef CGAL::internal::Algebraic_real_rep_bfi< Ext_rat_int, Rational > Rep_bfi_ext_rat_int; + typedef CGAL::internal::Algebraic_real_rep_bfi< Ext_rat_rat, Rational > Rep_bfi_ext_rat_rat; + + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + + +// Algebraic_real_quadratic_refinement_rep_bfi + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi< Integer, Rational> Rep_qr_bfi_int; + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi< Rational, Rational > Rep_qr_bfi_rat; + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi< Ext_int_int, Rational > Rep_qr_bfi_ext_int_int; + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi< Ext_rat_int, Rational > Rep_qr_bfi_ext_rat_int; + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi< Ext_rat_rat, Rational > Rep_qr_bfi_ext_rat_rat; + + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + algebraic_number_test(); + +} + +int main() +{ +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + typedef CGAL::LEDA_arithmetic_kernel LEDA_AK; + algebraic_number_test_at(); + std::cerr << " LEDA test .. " << std::flush; + std::cerr << " done " << std::endl; +#else + std::cerr << " LEDA test skipped " << std::endl; +#endif // CGAL_HAS_LEDA_ARITHMETIC_KERNEL + +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + std::cerr << " CORE test .. " << std::flush; + typedef CGAL::CORE_arithmetic_kernel CORE_AK; + algebraic_number_test_at(); + std::cerr << " done " << std::endl; +#else + std::cerr << " CORE test skipped " << std::endl; +#endif // CGAL_HAS_CORE_ARITHMETIC_KERNEL + +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + std::cerr << " GMP test .. " << std::flush; + typedef CGAL::GMP_arithmetic_kernel GMP_AK; + algebraic_number_test_at(); + std::cerr << " done " << std::endl; +#else + std::cerr << " GMP test skipped " << std::endl; +#endif // CGAL_HAS_GMP_ARITHMETIC_KERNEL + +} +//EOF diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Bitstream_descartes.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Bitstream_descartes.cpp new file mode 100644 index 00000000000..64b62dca7ab --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Bitstream_descartes.cpp @@ -0,0 +1,106 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file NiX/Bitstream_descartes.C + This is the test file for the class NiX::Bitstream_descartes. + +*/ + +#include +#include + +// include these traits here by 'hand', since not in release 3.3 +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include // used in this file + +template +void test_descartes(){ + typedef typename AT::Integer Integer; + typedef typename AT::Rational Rational; + + { + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > Isolator; + + // general test of concept RealRootIsolator + CGAL::internal::test_real_root_isolator(); + }{ + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > Isolator; + // general test of concept RealRootIsolator + CGAL::internal::test_real_root_isolator(); + }{ + typedef CGAL::Sqrt_extension EXT; + typedef typename + CGAL::Polynomial_type_generator::Type Polynomial; + typedef CGAL::internal::Bitstream_descartes< + CGAL::internal::Bitstream_descartes_rndl_tree_traits + > > Isolator; + // general test of concept RealRootIsolator + CGAL::internal::test_real_root_isolator(); + + std::istringstream is("P[8(0,EXT[1263296571491275162619395552058539312049753537208652637440,42968358109221573436642744060744334362576495937343892480,859])(1,EXT[2207556620237983039471566299950573667219187771717363990528,76852322515373647784745416857429135583058957867416403456,859])(2,EXT[1309275777321138279335848837056750819020098551750287419392,39195296448043974486512553808164864989806318662622537728,859])(3,EXT[86302507833822837152267458208050616275030717971310571520,10003400461933730535898849196215973480541410956350136320,859])(4,EXT[491437197926570070047913809040994179733862944058588160,-823318654055010400576035967724449228967294601081409536,859])(5,EXT[65617171248843379260568930361980285279772972904474353664,-2321236429038088490878641998530459657094667195101177856,859])(6,EXT[-31388640426864731218854617935763549592108582309411053568,1147925677098540153039869220704807888848997763457081344,859])(7,EXT[-9044080753104082029116583549917596926203452476780478464,319259245952387286523925425244746929470795371494383616,859])(8,EXT[7527302869236151900084946597004902733830052515530309632,-256375273905623226297550301204997314964265060295540736,859])]"); + + Polynomial P; + is >> P ; + Isolator isolator(P); + assert(isolator.number_of_real_roots() == 2 ); + + typedef CGAL::internal::Algebraic_real_d_1 Alg_real; + Alg_real r0(P,isolator.left_bound(0),isolator.right_bound(0)); + Alg_real r1(P,isolator.left_bound(1),isolator.right_bound(1)); + assert(r0 < r1); + assert(r0 > isolator.left_bound(0)); + assert(r0 < isolator.right_bound(0)); + assert(r1 > isolator.left_bound(1)); + assert(r1 < isolator.right_bound(1)); + + } + CGAL::internal::test_bitstream_descartes(); + +} + +int main(){ +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + test_descartes(); +#endif + +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + test_descartes(); +#endif + +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + test_descartes(); +#endif + return EXIT_SUCCESS; +} +// EOF diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/CMakeLists.txt b/Algebraic_kernel_d/test/Algebraic_kernel_d/CMakeLists.txt index 6a300b8029c..0268555e07a 100644 --- a/Algebraic_kernel_d/test/Algebraic_kernel_d/CMakeLists.txt +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/CMakeLists.txt @@ -1,4 +1,8 @@ -project( AK_test ) +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + + +project( Algebraic_kernel_d_test ) CMAKE_MINIMUM_REQUIRED(VERSION 2.4.5) @@ -8,26 +12,57 @@ if ( COMMAND cmake_policy ) cmake_policy( SET CMP0003 NEW ) endif() -find_package( CGAL QUIET ) +find_package(CGAL QUIET COMPONENTS Core ) if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) include( CGAL_CreateSingleSourceCGALProgram ) + include( CGAL_VersionUtils ) + find_package( MPFI ) + + if( MPFI_FOUND ) + include( ${MPFI_USE_FILE} ) + endif( MPFI_FOUND ) + find_package( RS ) + if( RS_FOUND ) include( ${RS_USE_FILE} ) - include_directories (BEFORE ../../include) - create_single_source_cgal_program( "Algebraic_kernel_rs_gmpq_1.cpp" ) - create_single_source_cgal_program( "Algebraic_kernel_rs_gmpz_1.cpp" ) - create_single_source_cgal_program( "io_test.cpp" ) - else( RS_FOUND ) - message(STATUS "NOTICE: This program requires RS and will not be compiled.") endif( RS_FOUND ) -else( CGAL_FOUND ) + include_directories (BEFORE ../../include) + include_directories (BEFORE include) - message(STATUS - "NOTICE: This program requires CGAL and GMP, and will not be compiled.") + include_directories(BEFORE $ENV{CGAL_TRUNK}/Number_types/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Algebraic_foundations/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Arithmetic_kernel/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Modular_arithmetic/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Polynomial/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Interval_support/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Arrangement_on_surface_2/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Envelope_3/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Mesh_3/include/) + include_directories(BEFORE $ENV{CGAL_TRUNK}/Intersections_3/include/) + + create_single_source_cgal_program( "Algebraic_curve_kernel_2.cpp" ) + create_single_source_cgal_program( "algebraic_curve_kernel_2_tools.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_d_1_LEDA.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_d_1_CORE.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_d_1_GMP.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_d_2.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_rs_gmpq_d_1.cpp" ) + create_single_source_cgal_program( "Algebraic_kernel_rs_gmpz_d_1.cpp" ) + create_single_source_cgal_program( "Algebraic_real_d_1.cpp" ) + create_single_source_cgal_program( "Bitstream_descartes.cpp" ) + create_single_source_cgal_program( "Curve_analysis_2.cpp" ) + create_single_source_cgal_program( "Curve_pair_analysis_2.cpp" ) + create_single_source_cgal_program( "Descartes.cpp" ) + create_single_source_cgal_program( "Real_embeddable_traits_extension.cpp" ) + +else() + + message(STATUS "This program requires the CGAL library, and will not be compiled.") + +endif() -endif( CGAL_FOUND ) diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_analysis_2.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_analysis_2.cpp new file mode 100644 index 00000000000..dbf9248f1a6 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_analysis_2.cpp @@ -0,0 +1,553 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#include + +// Switches on/off tests for Sqrt-extension types +#if CGAL_ACK_WITH_ROTATIONS +#ifndef DO_SQRT_EXTENSION_TESTS +#define DO_SQRT_EXTENSION_TESTS 1 +#endif +#endif + +#if CGAL_ACK_USE_EXACUS +#include +#include +#endif + +#include + +#include + +#include +#include +#include +#include +#include + +#include + +template Poly_ from_string(const char* s) { + std::stringstream ss(s); + Poly_ f; + ss >> f; + return f; +} + +template +int number_of_objects(typename AlgebraicKernel_2::Curve_analysis_2 c) { + + typedef typename AlgebraicKernel_2::Curve_analysis_2::Status_line_1 + Status_line_1; + + int vertical_arcs=0, non_vertical_arcs=0, isolated_vertices=0; + + int n = c.number_of_status_lines_with_event(); + + for( int i = 0; i < n; i++ ) { + const Status_line_1& status_line = c.status_line_at_event(i); + if(status_line.covers_line()) { + // vertical + vertical_arcs += 1 + status_line.number_of_events(); + } + for( int j = 0; j < status_line.number_of_events(); j++ ) { + if(status_line.number_of_incident_branches(j).first == 0 && + status_line.number_of_incident_branches(j).second == 0) { + isolated_vertices++; + } + } + } + for( int i = 0 ; i <= n; i++ ) { + non_vertical_arcs += c.status_line_of_interval(i).number_of_events(); + } + + return vertical_arcs + non_vertical_arcs + isolated_vertices; +} + + + +template void test_routine() { + + + typedef typename Arithmetic_kernel::Rational Rational; + typedef typename Arithmetic_kernel::Integer Integer; + + typedef Integer Coefficient; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_int1; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_int2; + + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi + < Coefficient, Rational > Rep_class; + typedef CGAL::internal::Bitstream_descartes + < CGAL::internal::Bitstream_descartes_rndl_tree_traits + < CGAL::internal::Bitstream_coefficient_kernel + > + > + Isolator; + + typedef CGAL::Algebraic_kernel_d_1 + Algebraic_kernel_d_1; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real; + + + +#if CGAL_ACK_USE_EXACUS + typedef AcX::Algebraic_curve_2 Algebraic_curve_2; + typedef AcX::Algebraic_curve_pair_2 + Algebraic_curve_pair_2; + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#else + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#endif + + Algebraic_kernel_d_2 kernel; + + typename Algebraic_kernel_d_2::Construct_curve_2 construct_curve_2 + = kernel.construct_curve_2_object(); + + typedef typename Algebraic_kernel_d_2::Curve_analysis_2 Curve_analysis_2; + + typedef typename Curve_analysis_2::Status_line_1 Status_line_1; + + Poly_int2 f; + + Curve_analysis_2 curve; + + Status_line_1 event; + + Rational eps(1,1000); + + { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[1(0,P[1(0,2)(1,2)])(1,P[0(0,-3)])]" + << std::endl; +#endif + f=from_string("P[1(0,P[1(0,2)(1,2)])(1,P[0(0,-3)])]"); + curve=construct_curve_2(f); + assert(curve.number_of_status_lines_with_event()==0); + assert(number_of_objects(curve)==1); + //assert(!curve.may_be_singular()); + + CGAL::Arr_parameter_space loc; + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc, + curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,0))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + } + { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[3(0,P[2(0,-2)(2,2)])(1,P[1(1,-1)])(3,P[1(1,-6)])]" << std::endl; +#endif + f=from_string("P[3(0,P[2(0,-2)(2,2)])(1,P[1(1,-1)])(3,P[1(1,-6)])]"); + ::CGAL::set_pretty_mode(std::cout); + curve=construct_curve_2(f); + assert(curve.number_of_status_lines_with_event()==1); + assert(number_of_objects(curve)==2); + event=curve.status_line_at_event(0); + assert(event.number_of_events()==0); + + assert(event.number_of_branches_approaching_minus_infinity().first==0); + assert(event.number_of_branches_approaching_minus_infinity().second + ==1); + assert(event.number_of_branches_approaching_plus_infinity().first==1); + assert(event.number_of_branches_approaching_plus_infinity().second==0); + CGAL::Arr_parameter_space loc; + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc, + curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,0))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + } + { +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[10(1,P[9(4,18)(9,18)])(2,P[9(4,-9)(9,-9)])(3,P[7(2,-12)(7,-12)])(4,P[7(2,6)(3,-18)(7,6)])(5,P[5(3,9)(5,36)])(6,P[5(1,12)(5,-18)])(7,P[3(1,-6)(3,-42)])(8,P[3(3,21)])(9,P[1(1,12)])(10,P[1(1,-6)])]" << std::endl; +#endif + f=from_string("P[10(1,P[9(4,18)(9,18)])(2,P[9(4,-9)(9,-9)])(3,P[7(2,-12)(7,-12)])(4,P[7(2,6)(3,-18)(7,6)])(5,P[5(3,9)(5,36)])(6,P[5(1,12)(5,-18)])(7,P[3(1,-6)(3,-42)])(8,P[3(3,21)])(9,P[1(1,12)])(10,P[1(1,-6)])]"); + curve=construct_curve_2(f); + assert(curve.number_of_status_lines_with_event()==10); + // assert(curve.may_be_singular()); + + event=curve.status_line_at_exact_x(Algebraic_real(1)); + assert(event.number_of_events()==6); + event.refine_to(0,eps); + assert(event.lower_bound(0) > Rational(-169,100)); + assert(event.upper_bound(0) < Rational(-168,100)); + assert(! event.is_event(0)); + event.refine_to(3,eps); + assert(event.lower_bound(3) > Rational(122,100)); + assert(event.upper_bound(3) < Rational(123,100)); + assert(! event.is_event(0)); + + event=curve.status_line_at_exact_x(Algebraic_real(0)); + assert(event.covers_line()); + assert(event.number_of_events()==3); + event.refine_to(0,eps); + assert(event.lower_bound(0) > Rational(-101,100)); + assert(event.upper_bound(0) < Rational(-99,100)); + assert(! event.is_event(0)); + event.refine_to(1,eps); + assert(event.lower_bound(1) > Rational(-1,100)); + assert(event.upper_bound(1) < Rational(1,100)); + assert(event.is_event(1)); + assert(event.number_of_incident_branches(1).first==4); + assert(event.number_of_incident_branches(1).second==4); + event.refine_to(2,eps); + assert(event.lower_bound(2) > Rational(199,100)); + assert(event.upper_bound(2) < Rational(201,100)); + assert(! event.is_event(0)); + + event=curve.status_line_at_exact_x(Algebraic_real(Poly_int1(-3,0,1),0,2)); + assert(event.number_of_events()==6); + event.refine_to(1,eps); + assert(event.lower_bound(1) > Rational(-213,100)); + assert(event.upper_bound(1) < Rational(-212,100)); + assert(! event.is_event(0)); + event.refine_to(3,eps); + assert(event.lower_bound(3) > Rational(199,100)); + assert(event.upper_bound(3) < Rational(201,100)); + assert(! event.is_event(0)); + + CGAL::Arr_parameter_space loc; + Algebraic_real y_coor; + + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,1))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (y_coor, + curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,2))); + assert( y_coor == Rational(0)); + + assert(CGAL::assign + (y_coor, + curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,3))); + assert( y_coor == Rational(2)); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,4))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,5))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,1))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (y_coor, + curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,2))); + assert( y_coor == Rational(0)); + + assert(CGAL::assign + (y_coor, + curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,3))); + assert( y_coor == Rational(2)); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,4))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + assert(CGAL::assign + (loc,curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,5))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + + } + { + curve=Curve_analysis_2(); +#if !CGAL_ACK_USE_EXACUS + assert(! curve.has_defining_polynomial()); +#endif + } + { + Poly_int2 f1 + = from_string("P[1(0,P[1(0,2)(1,2)])(1,P[0(0,-3)])]"); + Poly_int2 f2 + = from_string("P[1(0,P[1(0,3)(1,2)])(1,P[0(0,-3)])]"); + Curve_analysis_2 curve1=construct_curve_2(f1), + curve2=construct_curve_2(f2); + assert(!curve1.is_identical(curve2)); + assert(curve1.polynomial_2()!=curve2.polynomial_2()); + std::swap(curve1,curve2); + assert(curve1.polynomial_2()!=curve2.polynomial_2()); + } + { + Poly_int2 f1 + = from_string("P[1(0,P[1(0,2)(1,2)])(1,P[0(0,-3)])]"); + Curve_analysis_2 curve1 = construct_curve_2(f1); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[1(0,P[1(0,2)(1,2)])(1,P[0(0,-3)])]" + << std::endl; +#endif + Curve_analysis_2 curve2(curve1); + assert(curve1.is_identical(curve2)); + Poly_int2 new_f=from_string("P[1(0,P[1(0,3)(1,2)])(1,P[0(0,-3)])]"); + } + { + Poly_int2 f =from_string("P[2(0,P[2(1,3)(2,6)])(1,P[2(0,-3)(1,-11)(2,1)])(2,P[1(0,5)(1,-1)])]"); + Curve_analysis_2 curve = construct_curve_2(f); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[2(0,P[2(1,3)(2,6)])(1,P[2(0,-3)(1,-11)(2,1)])(2,P[1(0,5)(1,-1)])]" << std::endl; +#endif +#if !CGAL_ACK_USE_EXACUS + assert(curve.polynomial_2()==curve.primitive_polynomial_2()); + assert(number_of_objects(curve)==4); + Curve_analysis_2 sh_curve=curve.shear_primitive_part(2); + assert(number_of_objects(sh_curve)==7); + assert(sh_curve.status_line_at_exact_x(Algebraic_real(-10)).number_of_events()==3); + // Now, this should be cached + sh_curve=curve.shear_primitive_part(2); + assert(number_of_objects(sh_curve)==7); + assert(sh_curve.status_line_at_exact_x(Algebraic_real(-10)).number_of_events()==3); +#endif + } + + { // More tests...just analyse some curves and compute their segments + Poly_int2 f = from_string("P[8(0,P[8(0,24)(1,-8)(2,-162)(3,204)(4,106)(5,-340)(6,240)(7,-72)(8,8)])(1,P[6(0,-60)(1,8)(2,304)(3,-400)(4,148)(5,8)(6,-8)])(2,P[6(0,18)(1,80)(2,-165)(3,-132)(4,367)(5,-212)(6,38)])(3,P[4(0,-30)(1,-136)(2,264)(3,-72)(4,-26)])(4,P[4(0,-15)(1,36)(2,89)(3,-144)(4,49)])(5,P[2(0,30)(1,-24)(2,-6)])(6,P[2(0,-6)(1,-28)(2,22)])(8,P[0(0,3)])]"); + Curve_analysis_2 curve= construct_curve_2(f); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[8(0,P[8(0,24)(1,-8)(2,-162)(3,204)(4,106)(5,-340)(6,240)(7,-72)(8,8)])(1,P[6(0,-60)(1,8)(2,304)(3,-400)(4,148)(5,8)(6,-8)])(2,P[6(0,18)(1,80)(2,-165)(3,-132)(4,367)(5,-212)(6,38)])(3,P[4(0,-30)(1,-136)(2,264)(3,-72)(4,-26)])(4,P[4(0,-15)(1,36)(2,89)(3,-144)(4,49)])(5,P[2(0,30)(1,-24)(2,-6)])(6,P[2(0,-6)(1,-28)(2,22)])(8,P[0(0,3)])]" << std::endl; +#endif + assert(number_of_objects(curve)==54); + f = from_string("P[5(0,P[8(0,40)(1,-40)(2,-20)(3,20)(5,-8)(6,8)(7,4)(8,-4)])(1,P[8(0,-100)(1,100)(2,50)(3,-50)(5,20)(6,-20)(7,-10)(8,10)])(2,P[8(0,60)(1,-60)(2,-30)(3,30)(5,-12)(6,12)(7,6)(8,-6)])(3,P[8(0,-20)(1,20)(2,10)(3,-10)(5,4)(6,-4)(7,-2)(8,2)])(4,P[8(0,50)(1,-50)(2,-25)(3,25)(5,-10)(6,10)(7,5)(8,-5)])(5,P[8(0,-30)(1,30)(2,15)(3,-15)(5,6)(6,-6)(7,-3)(8,3)])]"); + curve=construct_curve_2(f); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[5(0,P[8(0,40)(1,-40)(2,-20)(3,20)(5,-8)(6,8)(7,4)(8,-4)])(1,P[8(0,-100)(1,100)(2,50)(3,-50)(5,20)(6,-20)(7,-10)(8,10)])(2,P[8(0,60)(1,-60)(2,-30)(3,30)(5,-12)(6,12)(7,6)(8,-6)])(3,P[8(0,-20)(1,20)(2,10)(3,-10)(5,4)(6,-4)(7,-2)(8,2)])(4,P[8(0,50)(1,-50)(2,-25)(3,25)(5,-10)(6,10)(7,5)(8,-5)])(5,P[8(0,-30)(1,30)(2,15)(3,-15)(5,6)(6,-6)(7,-3)(8,3)])]" << std::endl; +#endif + assert(number_of_objects(curve)==31); + f=from_string("P[8(0,P[10(5,80)(6,104)(7,44)(8,10)(9,4)(10,1)])(1,P[8(4,-80)(5,-36)(6,54)(7,32)(8,3)])(2,P[8(2,-80)(3,-104)(4,-72)(5,-66)(6,-8)(7,5)(8,1)])(3,P[7(1,80)(2,36)(3,-94)(4,-60)(5,-19)(6,-5)(7,-1)])(4,P[5(1,28)(2,56)(3,-10)(4,-30)(5,-6)])(5,P[5(0,40)(1,28)(2,16)(3,7)(4,-3)(5,-1)])(6,P[3(0,14)(1,24)(2,5)(3,1)])(7,P[2(0,-2)(1,4)(2,1)])(8,P[0(0,-1)])]"); + curve=construct_curve_2(f); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[8(0,P[10(5,80)(6,104)(7,44)(8,10)(9,4)(10,1)])(1,P[8(4,-80)(5,-36)(6,54)(7,32)(8,3)])(2,P[8(2,-80)(3,-104)(4,-72)(5,-66)(6,-8)(7,5)(8,1)])(3,P[7(1,80)(2,36)(3,-94)(4,-60)(5,-19)(6,-5)(7,-1)])(4,P[5(1,28)(2,56)(3,-10)(4,-30)(5,-6)])(5,P[5(0,40)(1,28)(2,16)(3,7)(4,-3)(5,-1)])(6,P[3(0,14)(1,24)(2,5)(3,1)])(7,P[2(0,-2)(1,4)(2,1)])(8,P[0(0,-1)])]" << std::endl; +#endif + assert(number_of_objects(curve)==27); + f=from_string("P[4(0,P[1(0,-10)(1,6)])(1,P[2(0,4)(1,8)(2,-6)])(2,P[2(0,-5)(1,-6)(2,5)])(3,P[3(0,2)(1,6)(2,1)(3,-3)])(4,P[3(1,-2)(2,-1)(3,1)])]"); + curve=construct_curve_2(f); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[4(0,P[1(0,-10)(1,6)])(1,P[2(0,4)(1,8)(2,-6)])(2,P[2(0,-5)(1,-6)(2,5)])(3,P[3(0,2)(1,6)(2,1)(3,-3)])(4,P[3(1,-2)(2,-1)(3,1)])]" << std::endl; +#endif + assert(number_of_objects(curve)==18); + f=from_string("P[7(0,P[7(3,-12)(4,-12)(5,7)(6,4)(7,-1)])(1,P[6(1,12)(2,24)(3,-31)(4,-11)(5,9)(6,1)])(2,P[5(0,-12)(1,24)(2,43)(3,-22)(4,-9)(5,5)])(3,P[5(0,-36)(1,14)(2,22)(4,-5)(5,1)])(4,P[4(0,-14)(1,-5)(2,-4)(3,5)(4,-1)])(5,P[3(0,9)(1,-6)(2,-5)(3,1)])(6,P[2(0,6)(1,-1)(2,-1)])(7,P[0(0,1)])]"); + curve=construct_curve_2(f); + } +#if CGAL_ACK_WITH_ROTATIONS +#if DO_SQRT_EXTENSION_TESTS + + // Tests for Sqrt_extension + { + typedef CGAL::Sqrt_extension Sqrt_extension; + + typedef Sqrt_extension Coefficient; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_sqrt1; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_sqrt2; + + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi + < Coefficient, Rational > Rep_class; + typedef CGAL::internal::Bitstream_descartes + < CGAL::internal::Bitstream_descartes_rndl_tree_traits + < CGAL::internal::Bitstream_coefficient_kernel + > + > + Isolator; + + typedef CGAL::Algebraic_kernel_d_1 + Algebraic_kernel_d_1_with_sqrt; + + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2_with_sqrt; + + Algebraic_kernel_d_2_with_sqrt kernel; + + typename Algebraic_kernel_d_2_with_sqrt::Construct_curve_2 + sqrt_construct_curve_2 + = kernel.construct_curve_2_object(); + + typedef typename Algebraic_kernel_d_2_with_sqrt::Curve_analysis_2 + Sqrt_curve_analysis_2; + + typedef typename Sqrt_curve_analysis_2::Algebraic_real_1 + Sqrt_algebraic_real; + + typedef typename Sqrt_curve_analysis_2::Status_line_1 + Sqrt_status_line_1; + + + + Sqrt_status_line_1 event; + + + + Poly_sqrt2 sqrt_f=from_string("P[10(1,P[9(4,EXT[0,54,5])(9,EXT[0,54,5])])(2,P[9(4,EXT[0,-27,5])(9,EXT[0,-27,5])])(3,P[7(2,EXT[0,-36,5])(7,EXT[0,-36,5])])(4,P[7(2,EXT[0,18,5])(3,EXT[0,-54,5])(7,EXT[0,18,5])])(5,P[5(3,EXT[0,27,5])(5,EXT[0,108,5])])(6,P[5(1,EXT[0,36,5])(5,EXT[0,-54,5])])(7,P[3(1,EXT[0,-18,5])(3,EXT[0,-126,5])])(8,P[3(3,EXT[0,63,5])])(9,P[1(1,EXT[0,36,5])])(10,P[1(1,EXT[0,-18,5])])]"); +#if CGAL_ACK_DEBUG_FLAG + CGAL_ACK_DEBUG_PRINT << "P[10(1,P[9(4,EXT[0,54,5])(9,EXT[0,54,5])])(2,P[9(4,EXT[0,-27,5])(9,EXT[0,-27,5])])(3,P[7(2,EXT[0,-36,5])(7,EXT[0,-36,5])])(4,P[7(2,EXT[0,18,5])(3,EXT[0,-54,5])(7,EXT[0,18,5])])(5,P[5(3,EXT[0,27,5])(5,EXT[0,108,5])])(6,P[5(1,EXT[0,36,5])(5,EXT[0,-54,5])])(7,P[3(1,EXT[0,-18,5])(3,EXT[0,-126,5])])(8,P[3(3,EXT[0,63,5])])(9,P[1(1,EXT[0,36,5])])(10,P[1(1,EXT[0,-18,5])])]" << std::endl; +#endif + Sqrt_curve_analysis_2 sqrt_curve= sqrt_construct_curve_2(sqrt_f); + assert(sqrt_curve.number_of_status_lines_with_event()==10); + // assert(sqrt_curve.may_be_singular()); + + event=sqrt_curve.status_line_at_exact_x(Sqrt_algebraic_real(1)); + assert(event.number_of_events()==6); + event.refine_to(0,eps); + assert(event.lower_bound(0) > Rational(-169,100)); + assert(event.upper_bound(0) < Rational(-168,100)); + assert(! event.is_event(0)); + event.refine_to(3,eps); + assert(event.lower_bound(3) > Rational(122,100)); + assert(event.upper_bound(3) < Rational(123,100)); + assert(! event.is_event(0)); + + event=sqrt_curve.status_line_at_exact_x(Sqrt_algebraic_real(0)); + assert(event.covers_line()); + assert(event.number_of_events()==3); + event.refine_to(0,eps); + assert(event.lower_bound(0) > Rational(-101,100)); + assert(event.upper_bound(0) < Rational(-99,100)); + assert(! event.is_event(0)); + event.refine_to(1,eps); + assert(event.lower_bound(1) > Rational(-1,100)); + assert(event.upper_bound(1) < Rational(1,100)); + assert(event.is_event(1)); + assert(event.number_of_incident_branches(1).first==4); + assert(event.number_of_incident_branches(1).second==4); + event.refine_to(2,eps); + assert(event.lower_bound(2) > Rational(199,100)); + assert(event.upper_bound(2) < Rational(201,100)); + assert(! event.is_event(0)); + + event=sqrt_curve.status_line_at_exact_x(Sqrt_algebraic_real(Poly_sqrt1(-3,0,1),0,2)); + assert(event.number_of_events()==6); + event.refine_to(1,eps); + assert(event.lower_bound(1) > Rational(-213,100)); + assert(event.upper_bound(1) < Rational(-212,100)); + assert(! event.is_event(0)); + event.refine_to(3,eps); + assert(event.lower_bound(3) > Rational(199,100)); + assert(event.upper_bound(3) < Rational(201,100)); + assert(! event.is_event(0)); + + + CGAL::Arr_parameter_space loc; + Sqrt_algebraic_real y_coor; + + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,1))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (y_coor, + sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,2))); + assert( y_coor == Rational(0)); + + assert(CGAL::assign + (y_coor, + sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,3))); + assert( y_coor == Rational(2)); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,4))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_LEFT_BOUNDARY,5))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,0))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,1))); + assert( loc == CGAL::ARR_BOTTOM_BOUNDARY); + + assert(CGAL::assign + (y_coor, + sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,2))); + assert( y_coor == Rational(0)); + + assert(CGAL::assign + (y_coor, + sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,3))); + assert( y_coor == Rational(2)); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,4))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + assert(CGAL::assign + (loc,sqrt_curve.asymptotic_value_of_arc(CGAL::ARR_RIGHT_BOUNDARY,5))); + assert( loc == CGAL::ARR_TOP_BOUNDARY); + + } +#endif +#endif + +} + + +int main() { + +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + test_routine(); +#else + std::cerr << "LEDA tests skipped" << std::endl; +#endif +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + test_routine(); +#else + std::cerr << "CORE tests skipped" << std::endl; +#endif +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + test_routine(); +#else + std::cerr << "GMP tests skipped" << std::endl; +#endif + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_pair_analysis_2.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_pair_analysis_2.cpp new file mode 100644 index 00000000000..16c1cfcf4cc --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Curve_pair_analysis_2.cpp @@ -0,0 +1,1148 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#include + +// Switches on/off tests for Sqrt-extension types +#if CGAL_ACK_WITH_ROTATIONS +#ifndef DO_SQRT_EXTENSION_TESTS +#define DO_SQRT_EXTENSION_TESTS 1 +#endif +#endif + +#include + +#include + +#if CGAL_ACK_USE_EXACUS +#include +#include +#endif + +#include + +#include +#include +#include +#include +#include + +#include + +template Poly_ from_string(const char* s) { + std::stringstream ss(s); + Poly_ f; + ss >> f; + return f; +} + +template +void test_routine() { + + + typedef typename Arithmetic_kernel::Rational Rational; + typedef typename Arithmetic_kernel::Integer Integer; + + typedef Integer Coefficient; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_1; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_2; + + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi + < Coefficient, Rational > Rep_class; + typedef CGAL::internal::Bitstream_descartes + < CGAL::internal::Bitstream_descartes_rndl_tree_traits + < CGAL::internal::Bitstream_coefficient_kernel + > + > + Isolator; + + typedef CGAL::Algebraic_kernel_d_1 + Algebraic_kernel_d_1; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real; + +#if CGAL_ACK_USE_EXACUS + typedef AcX::Algebraic_curve_2 Algebraic_curve_2; + typedef AcX::Algebraic_curve_pair_2 + Algebraic_curve_pair_2; + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#else + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; +#endif + + Algebraic_kernel_d_2 kernel; + + typedef typename Algebraic_kernel_d_2::Curve_analysis_2 Curve_analysis_2; + + typedef typename Algebraic_kernel_d_2::Curve_pair_analysis_2 + Curve_pair_analysis_2; + + typename Algebraic_kernel_d_2::Construct_curve_2 + construct_curve_2 + = kernel.construct_curve_2_object(); + + typename Algebraic_kernel_d_2::Construct_curve_pair_2 + construct_curve_pair_2 + = kernel.construct_curve_pair_2_object(); + + + { + Poly_2 f=from_string("P[4(0,P[4(3,-1)(4,2)])(2,P[1(1,1)])(4,P[0(0,1)])]"); + Poly_2 g=from_string("P[4(0,P[4(4,1)])(1,P[2(2,1)])(3,P[0(0,-1)])(4,P[0(0,2)])]"); + Curve_analysis_2 c1=construct_curve_2(f); + Curve_analysis_2 c2=construct_curve_2(g); + Curve_pair_analysis_2 curve_pair=construct_curve_pair_2(c1,c2); + assert(curve_pair.number_of_status_lines_with_event()==10); + typedef typename Curve_pair_analysis_2::Status_line_1 Status_line_1; +#if CGAL_ACK_USE_EXACUS + typedef SoX::Index_triple Triple; +#else + typedef CGAL::internal::Event_indices Triple; +#endif + int i; + { + i=0; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==0); + } + { + i=0; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==0); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==0); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==1); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==0); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==2); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==2); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==3); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==0); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==0); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==6); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==3); + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==8); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==3); + assert(slice.curves_at_event(5).second==-1); + assert(slice.curves_at_event(6).first==-1); + assert(slice.curves_at_event(6).second==2); + assert(slice.curves_at_event(7).first==-1); + assert(slice.curves_at_event(7).second==3); + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==0); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==7); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==3); + assert(slice.curves_at_event(5).second==2); + assert(slice.curves_at_event(6).first==-1); + assert(slice.curves_at_event(6).second==3); + + assert(slice.multiplicity_of_intersection(5)==1); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==8); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==2); + assert(slice.curves_at_event(6).first==3); + assert(slice.curves_at_event(6).second==-1); + assert(slice.curves_at_event(7).first==-1); + assert(slice.curves_at_event(7).second==3); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==1); + assert(triple.ffy==1); + assert(triple.ggy==2); + //assert(slice.event_of_curve(i,0)==1); + //assert(slice.event_of_curve(i,1)==2); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==6); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==3); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==3); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==5); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==2); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + assert(slice.multiplicity_of_intersection(0)==1); + } + { + i=7; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=7; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==4); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==4); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + } + { + i=8; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=8; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==2); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==2); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==1); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + } + { + i=9; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==0); + } + { + i=9; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==3); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==3); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==0); + } + { + i=10; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==0); + } + + } + { + Poly_2 f=from_string("P[4(0,P[1(0,1)(1,1)])(4,P[0(0,-1)])]"); + Poly_2 g=from_string("P[2(0,P[2(0,-5)(2,6)])(2,P[0(0,4)])]"); + Curve_analysis_2 ca1=construct_curve_2(f), + ca2=construct_curve_2(g); + + Curve_pair_analysis_2 curve_pair=construct_curve_pair_2(ca1,ca2); + assert(curve_pair.number_of_status_lines_with_event()==7); + typedef typename Curve_pair_analysis_2::Status_line_1 Status_line_1; +#if CGAL_ACK_USE_EXACUS + typedef SoX::Index_triple Triple; +#else + typedef CGAL::internal::Event_indices Triple; +#endif + int i; + { + i=0; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==0); + } + { + i=0; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==0); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==0); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==1); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==0); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==0); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==0); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==1); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==1); + assert(slice.multiplicity_of_intersection(0)==1); + assert(slice.multiplicity_of_intersection(1)==1); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==2); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==1); + assert(slice.multiplicity_of_intersection(0)==1); + assert(slice.multiplicity_of_intersection(1)==1); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==3); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=7; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + } + { + Poly_2 f=from_string("P[4(0,P[4(3,-1)(4,2)])(2,P[1(1,1)])(4,P[0(0,1)])]"); + Poly_2 g=from_string("P[4(0,P[4(0,12)(1,-380)(2,4200)(3,-18000)(4,20000)])(2,P[1(0,-4000)(1,40000)])(4,P[0(0,160000)])]"); + Curve_analysis_2 ca1=construct_curve_2(f), + ca2=construct_curve_2(g); + Curve_pair_analysis_2 curve_pair=construct_curve_pair_2(ca1,ca2); + //assert(curve_pair.number_of_status_lines_with_event()==11); + + + } +#if CGAL_ACK_WITH_ROTATIONS +#if DO_SQRT_EXTENSION_TESTS + // Sqrt extension: + { + typedef CGAL::Sqrt_extension Sqrt_extension; + + typedef Sqrt_extension Coefficient; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_sqrt1; + typedef typename + CGAL::Polynomial_type_generator::Type Poly_sqrt2; + + + typedef CGAL::internal::Algebraic_real_quadratic_refinement_rep_bfi + < Coefficient, Rational > Rep_class; + typedef CGAL::internal::Bitstream_descartes + < CGAL::internal::Bitstream_descartes_rndl_tree_traits + < CGAL::internal::Bitstream_coefficient_kernel + > + > + Isolator; + + typedef CGAL::Algebraic_kernel_d_1< Coefficient,Rational, + Rep_class, Isolator > + Algebraic_kernel_d_1_with_sqrt; + + Poly_sqrt2 f,g; + f=from_string("P[4(0,P[4(3,EXT[0,-2,7])(4,EXT[0,4,7])])(2,P[1(1,EXT[0,2,7])])(4,P[0(0,EXT[0,2,7])])]"); + g=from_string("P[4(0,P[4(4,EXT[0,2,7])])(1,P[2(2,EXT[0,2,7])])(3,P[0(0,EXT[0,-2,7])])(4,P[0(0,EXT[0,4,7])])]"); + + typedef CGAL::Algebraic_curve_kernel_2 + Algebraic_kernel_d_2; + + typedef typename Algebraic_kernel_d_2::Curve_analysis_2 Curve_analysis_2; + typedef typename Algebraic_kernel_d_2::Curve_pair_analysis_2 + Curve_pair_analysis_2; + + Algebraic_kernel_d_2 kernel; + + typename Algebraic_kernel_d_2::Construct_curve_2 + construct_curve_2 + = kernel.construct_curve_2_object(); + + typename Algebraic_kernel_d_2::Construct_curve_pair_2 + construct_curve_pair_2 + = kernel.construct_curve_pair_2_object(); + + + Curve_analysis_2 c1=construct_curve_2(f), + c2=construct_curve_2(g); + + Curve_pair_analysis_2 curve_pair=construct_curve_pair_2(c1,c2); + assert(curve_pair.number_of_status_lines_with_event()==10); + typedef typename Curve_pair_analysis_2::Status_line_1 Status_line_1; + typedef CGAL::internal::Event_indices Triple; + int i; + + { + i=0; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==0); + } + { + i=0; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==0); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==0); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==1); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + } + { + i=1; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==0); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==2); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==2); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==3); + } + { + i=2; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==0); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==0); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==6); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==3); + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==8); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==3); + assert(slice.curves_at_event(5).second==-1); + assert(slice.curves_at_event(6).first==-1); + assert(slice.curves_at_event(6).second==2); + assert(slice.curves_at_event(7).first==-1); + assert(slice.curves_at_event(7).second==3); + } + { + i=3; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==0); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==7); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==3); + assert(slice.curves_at_event(5).second==2); + assert(slice.curves_at_event(6).first==-1); + assert(slice.curves_at_event(6).second==3); + + assert(slice.multiplicity_of_intersection(5)==1); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==8); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==0); + assert(slice.curves_at_event(3).first==-1); + assert(slice.curves_at_event(3).second==1); + assert(slice.curves_at_event(4).first==2); + assert(slice.curves_at_event(4).second==-1); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==2); + assert(slice.curves_at_event(6).first==3); + assert(slice.curves_at_event(6).second==-1); + assert(slice.curves_at_event(7).first==-1); + assert(slice.curves_at_event(7).second==3); + } + { + i=4; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==1); + assert(triple.ffy==1); + assert(triple.ggy==2); + //assert(slice.event_of_curve(i,0)==1); + //assert(slice.event_of_curve(i,1)==2); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==6); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + assert(slice.curves_at_event(5).first==-1); + assert(slice.curves_at_event(5).second==3); + } + { + i=5; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==3); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==5); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + assert(slice.curves_at_event(4).first==-1); + assert(slice.curves_at_event(4).second==2); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==-1); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==0); + assert(slice.curves_at_event(1).second==-1); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=6; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==2); + assert(triple.ffy==-1); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==0); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==1); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + assert(slice.multiplicity_of_intersection(0)==1); + } + { + i=7; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==4); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==-1); + assert(slice.curves_at_event(2).second==1); + assert(slice.curves_at_event(3).first==1); + assert(slice.curves_at_event(3).second==-1); + } + { + i=7; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==-1); + assert(triple.ggy==4); + //assert(slice.event_of_curve(i,0)==-1); + //assert(slice.event_of_curve(i,1)==4); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==3); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==-1); + assert(slice.curves_at_event(1).second==0); + assert(slice.curves_at_event(2).first==1); + assert(slice.curves_at_event(2).second==-1); + } + { + i=8; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==2); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + assert(slice.curves_at_event(1).first==1); + assert(slice.curves_at_event(1).second==-1); + } + { + i=8; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==2); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==2); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==1); + assert(slice.curves_at_event(0).first==0); + assert(slice.curves_at_event(0).second==-1); + } + { + i=9; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==0); + } + { + i=9; + const Status_line_1& slice=curve_pair.status_line_at_event(i); + Triple triple = curve_pair.event_indices(i); + assert(triple.fg==-1); + assert(triple.ffy==3); + assert(triple.ggy==-1); + //assert(slice.event_of_curve(i,0)==3); + //assert(slice.event_of_curve(i,1)==-1); + assert(slice.index()==i); + assert(slice.is_event()); + assert(! slice.is_intersection()); + assert(slice.number_of_events()==0); + } + { + i=10; + const Status_line_1& slice=curve_pair.status_line_of_interval(i); + assert(! slice.is_event()); + assert(slice.number_of_events()==0); + } + + } +#endif +#endif +} + + +int main() { +#ifdef NDEBUG + std::cout << "Assertions switched off!" << std::endl; + return 0; +#endif +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + test_routine(); +#else + std::cout << "LEDA tests skipped!" << std::endl; +#endif +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + test_routine(); +#else + std::cout << "CORE tests skipped!" << std::endl; +#endif +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + test_routine(); +#else + std::cout << "GMP tests skipped!" << std::endl; +#endif + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Descartes.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Descartes.cpp new file mode 100644 index 00000000000..3f9435b38cc --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Descartes.cpp @@ -0,0 +1,70 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file NiX/Descartes.C + This is the test file for the class NiX::Descartes. +*/ + + +#include + +// include these traits here by 'hand', since not in release 3.3 +#include +#include + +#include +#include + +#include +#include + +template +void test_descartes(){ + typedef typename AT::Integer Integer; + typedef typename AT::Rational Rational; + { + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial; + typedef ::CGAL::internal::Descartes Isolator; + + // general test of concept RealRootIsolator + CGAL::internal::test_real_root_isolator(); + }{ + typedef typename CGAL::Polynomial_type_generator::Type + Polynomial; + typedef ::CGAL::internal::Descartes Isolator; + // general test of concept RealRootIsolator + CGAL::internal::test_real_root_isolator(); + } +} + +int main(){ +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING LEDA " << std::endl; + test_descartes< CGAL::LEDA_arithmetic_kernel >(); +#endif +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING CORE " << std::endl; + test_descartes< CGAL::CORE_arithmetic_kernel >(); +#endif +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + std::cout << " TEST AK1 USING GMP " << std::endl; + test_descartes< CGAL::GMP_arithmetic_kernel >(); +#endif + + return EXIT_SUCCESS; +} +// EOF diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/Real_embeddable_traits_extension.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/Real_embeddable_traits_extension.cpp new file mode 100644 index 00000000000..47a457966cd --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/Real_embeddable_traits_extension.cpp @@ -0,0 +1,152 @@ +// Copyright (c) 2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id:$ +// +// Author(s) : Michael Hemmer +// +// ============================================================================ +// +// \brief test for Real_embeddable_traits_extension + + + +#include +#include + +#include +#include +#include + +//#include // used in this file + + +void test_real_embeddable_extension(CGAL::Null_tag){ return ; } + +template +void test_real_embeddable_extension(const NT_&){ + typedef typename CGAL::Get_arithmetic_kernel::Arithmetic_kernel AK; + typedef typename AK::Integer Integer; + + typedef CGAL::internal::Real_embeddable_extension RETE; + + typedef typename RETE::Type NT; + + typedef typename RETE::Floor Floor; + typedef typename RETE::Ceil Ceil; + typedef typename RETE::Floor_log2_abs Floor_log2_abs; + typedef typename RETE::Ceil_log2_abs Ceil_log2_abs; + + { + const Floor floor = Floor(); + typedef typename Floor::argument_type Argument_type; + typedef typename Floor::result_type Result_type; + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + assert(Integer(42) == floor(NT(42))); + assert(Integer(-42) == floor(NT(-42))); + } + + { + const Floor_log2_abs floor_log2_abs = Floor_log2_abs(); + typedef typename Floor_log2_abs::argument_type Argument_type; + typedef typename Floor_log2_abs::result_type Result_type; + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + + assert(long(0) == floor_log2_abs(NT(1))); + assert(long(0) == floor_log2_abs(NT(-1))); + + assert(long(1) == floor_log2_abs(NT(2))); + + assert(long(1) == floor_log2_abs(NT(3))); + assert(long(2) == floor_log2_abs(NT(4))); + assert(long(2) == floor_log2_abs(NT(5))); + + assert(long(2) == floor_log2_abs(NT(7))); + assert(long(3) == floor_log2_abs(NT(8))); + assert(long(3) == floor_log2_abs(NT(9))); + + assert(long(2) == floor_log2_abs(NT(-7))); + assert(long(3) == floor_log2_abs(NT(-8))); + assert(long(3) == floor_log2_abs(NT(-9))); + } + + { + const Ceil ceil = Ceil(); + typedef typename Ceil::argument_type Argument_type; + typedef typename Ceil::result_type Result_type; + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + assert(Integer(42) == ceil(NT(42))); + assert(Integer(-42) == ceil(NT(-42))); + } + + { + const Ceil_log2_abs ceil_log2_abs = Ceil_log2_abs(); + typedef typename Ceil_log2_abs::argument_type Argument_type; + typedef typename Ceil_log2_abs::result_type Result_type; + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + BOOST_STATIC_ASSERT(( ::boost::is_same::value)); + + assert(long(0) == ceil_log2_abs(NT(1))); + assert(long(0) == ceil_log2_abs(NT(-1))); + + assert(long(1) == ceil_log2_abs(NT(2))); + + assert(long(2) == ceil_log2_abs(NT(3))); + assert(long(2) == ceil_log2_abs(NT(4))); + assert(long(3) == ceil_log2_abs(NT(5))); + + assert(long(3) == ceil_log2_abs(NT(7))); + assert(long(3) == ceil_log2_abs(NT(8))); + assert(long(4) == ceil_log2_abs(NT(9))); + + assert(long(3) == ceil_log2_abs(NT(-7))); + assert(long(3) == ceil_log2_abs(NT(-8))); + assert(long(4) == ceil_log2_abs(NT(-9))); + } + +} + + + +template +void test_real_embeddable_extension_ak(){ + typedef typename AK::Integer Integer; + typedef typename AK::Rational Rational; + typedef typename AK::Bigfloat Bigfloat; + typedef typename AK::Bigfloat Bigfloat_interval; + + test_real_embeddable_extension(Integer()); + //test_real_embeddable_extension(Rational()); TODO + test_real_embeddable_extension(Bigfloat()); + test_real_embeddable_extension(Bigfloat_interval()); +} + + +int main() { +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + test_real_embeddable_extension_ak< CGAL::GMP_arithmetic_kernel >(); +#endif +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + test_real_embeddable_extension_ak< CGAL::LEDA_arithmetic_kernel >(); +#endif +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + test_real_embeddable_extension_ak< CGAL::CORE_arithmetic_kernel >(); +#endif + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.cpp new file mode 100644 index 00000000000..028fe784268 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/algebraic_curve_kernel_2_tools.cpp @@ -0,0 +1,186 @@ +// TODO: Add licence +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL:$ +// $Id: $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#include + +#include + +#include + +#include +#include + +#include + +template +void test_routine() { + typedef ArithmeticKernel Arithmetic_kernel; + typedef typename Arithmetic_kernel::Integer Integer; + typedef typename Arithmetic_kernel::Rational Rational; + + typedef typename CGAL::Polynomial_type_generator::Type Poly_int1; + + typedef CGAL::Algebraic_kernel_d_1 Algebraic_kernel_d_1; + + Algebraic_kernel_d_1 ak_1; + + typedef typename Algebraic_kernel_d_1::Solve_1 Real_roots; + + typedef typename Algebraic_kernel_d_1::Algebraic_real_1 Algebraic_real; + + + { + Poly_int1 p(1,-3,1,0,-1,0,0,1); + Real_roots rr; + std::vector v1; + + rr(p,std::back_inserter(v1),true); + + int n = std::distance(v1.begin(),v1.end()); + + assert(n==3); + + std::vector inter; + CGAL::internal::find_intermediate_values + (&ak_1,v1.begin(),v1.end(),std::back_inserter(inter)); + int m = (int)inter.size(); + assert(m==n+1); + + for(int i=0;i v2; + + rr2(p,std::back_inserter(v2),false); + + int n = std::distance(v2.begin(), v2.end()); + + assert(n==4); + + std::vector inter; + CGAL::internal::find_intermediate_values + (&ak_1,v2.begin(),v2.end(),std::back_inserter(inter)); + int m = (int)inter.size(); + assert(m==n+1); + + for(int i=0;i v1; + + rr1(p,std::back_inserter(v1),false); + + int n = std::distance(v1.begin(), v1.end()); + + assert(n==0); + + std::vector inter; + CGAL::internal::find_intermediate_values + (&ak_1,v1.begin(),v1.end(),std::back_inserter(inter)); + int m = (int)inter.size(); + assert(m==n+1); + + for(int i=0;i v2; + + rr2(p,std::back_inserter(v2),false); + + int n = std::distance(v2.begin(), v2.end()); + + assert(n==1); + + std::vector inter; + CGAL::internal::find_intermediate_values + (&ak_1,v2.begin(),v2.end(),std::back_inserter(inter)); + int m = (int)inter.size(); + assert(m==n+1); + + for(int i=0;i> f; + + ::CGAL::set_pretty_mode(std::cout); + //std::cout << f << " " << a << std::endl; + + assert(CGAL::internal::is_root_of(a,f)); + + } + */ + return; +} + +int main() { + +#ifdef CGAL_HAS_LEDA_ARITHMETIC_KERNEL + std::cerr << "test LEDA " << std::endl; + test_routine (); + std::cerr << "done " << std::endl; +#else + std::cerr << "test LEDA skipped" << std::endl; +#endif +#ifdef CGAL_HAS_CORE_ARITHMETIC_KERNEL + std::cerr << "test CORE " << std::endl; + test_routine (); + std::cerr << "done " << std::endl; +#else + std::cerr << "test CORE skipped" << std::endl; +#endif +#ifdef CGAL_HAS_GMP_ARITHMETIC_KERNEL + std::cerr << "test GMP " << std::endl; + test_routine (); + std::cerr << "done " << std::endl; +#else + std::cerr << "test GMP skipped" << std::endl; +#endif + + + + return 0; +} diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_curve_kernel_2.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_curve_kernel_2.h new file mode 100644 index 00000000000..68deb364363 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_curve_kernel_2.h @@ -0,0 +1,393 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Pavel Emeliyanenko +// Michael Kerber +// +// ============================================================================ + +#include +#include + +//#include + +#ifndef CGAL_TEST_ALGEBRAIC_CURVE_KERNEL_2_H +#define CGAL_TEST_ALGEBRAIC_CURVE_KERNEL_2_H + +namespace CGAL { + +namespace internal { + +static const char *ACK_2_ascii_polys[] = { + + "P[12(0,P[12(0,-403)(1,445)(2,-244)(3,-261)(4,182)(5,-284)(6,321)(7,-150)(8,-312)(9,-395)(10,451)(11,166)(12,-268)])(1,P[11(0,-149)(1,-194)(2,190)(3,397)(4,-423)(5,507)(6,-321)(7,215)(8,-459)(9,-112)(10,35)(11,-296)])(2,P[10(0,326)(1,296)(2,-461)(3,-175)(4,-123)(5,432)(6,195)(7,447)(8,-135)(9,-87)(10,8)])(3,P[9(0,299)(1,10)(2,-494)(3,192)(4,269)(5,-177)(6,-418)(7,461)(8,352)(9,23)])(4,P[8(0,193)(1,-357)(2,-187)(3,-140)(4,-126)(5,195)(6,-178)(7,-156)(8,-118)])(5,P[7(0,-11)(1,-205)(2,-357)(3,-157)(4,-321)(5,295)(6,-120)(7,-72)])(6,P[6(0,322)(1,443)(2,-26)(3,-29)(4,196)(5,-188)(6,132)])(7,P[5(0,372)(1,-15)(2,-184)(3,-4)(4,453)(5,-134)])(8,P[4(0,26)(1,131)(2,-170)(3,256)(4,282)])(9,P[3(0,198)(1,-424)(2,134)(3,350)])(10,P[2(0,-49)(1,-445)(2,343)])(11,P[1(0,86)(1,417)])(12,P[0(0,-295)])]", // 0 + + "P[6(0,P[6(0,132371318621897968)(1,62063386199148599600)(2,-151639931559080760922)(3,93583844480566235832)(4,-83154766543076124512)(5,-35432091262507130904)(6,227271934222282896800)])(1,P[5(0,-71827641993430936816)(1,368348281512476672028)(2,-286334917753887437776)(3,204520624662741644980)(4,-153426196026247710960)(5,-806483254283204758968)])(2,P[4(0,-207823824331267897258)(1,407437416975079236352)(2,-109980596108783730996)(3,560473260289176309328)(4,707425975812414448406)])(3,P[3(0,-229793885496425988888)(1,-16258161769731113484)(2,-225314637374518033384)(3,390228626765477166248)])(4,P[2(0,30511269636646463220)(1,-323492766503557473768)(2,-917252466360862051372)])(5,P[1(0,159815596286749757976)(1,567591812420861278704)])(6,P[0(0,-148967343686356735666)])]", // 1 + + "P[2(0,P[2(0,35204645504740)(1,18690431343280)(2,-33659097374560)])(1,P[1(0,-5878113292740)(1,25167512604160)])(2,P[0(0,41597705375085)])]", // 2 + + "P[6(0,P[6(0,-4041376884475638882353)(1,7050387367979191249572)(2,13657295334099123447165)(3,25540501499116672333266)(4,35818873525049083535243)(5,5246125427237612693902)(6,14604340604186011880149)])(1,P[5(0,6901581474556480012157)(1,-7529175981573515299061)(2,-11055581988553126878879)(3,12006542139536462689689)(4,14452481220936855448204)(5,13877670792372320318222)])(2,P[4(0,-11020699216485230516718)(1,-17311543433158205744767)(2,-31286655398777064659338)(3,-31056714506153479404652)(4,4356717231425141453473)])(3,P[3(0,3592444310543685259781)(1,6258214164280712933460)(2,-21871202396326925470570)(3,-7534603152074886821296)])(4,P[2(0,9063109123142130614750)(1,7920859532025064873268)(2,-6296939225750115900496)])(5,P[1(0,5169051546475000208976)(1,893576149924111317664)])(6,P[0(0,973644041162690858383)])]", // 3 + + "P[3(0,P[3(0,1)(1,3)(2,3)(3,1)])(1,P[2(0,-3)(1,-6)(2,-3)])(2,P[1(0,3)(1,3)])(3,P[0(0,-1)])]", // (x-y+1)^3 // 4 + + "P[1(0,P[1(1,1)])(1,P[0(0,-1)])]", // (x-y) // 5 + + "P[2(0,P[2(2,1)])(2,P[0(0,-1)])]", // x^2-y^2 // 6 + + "P[1(0,P[2(2,1)])(1,P[0(0,1)])]", // x^2+y // 7 + + "P[2(0,P[2(0,1)(2,2)])(2,P[0(0,-1)])]", // 2x^2-y^2+1 // 8 + + "P[7(1,P[7(1,-500)(3,300)(5,-60)(7,4)])(3,P[5(1,300)(3,-147)(5,12)])(5,P[3(1,-60)(3,12)])(7,P[1(1,4)])]", // (4*x)*y^7 + (12*x^3 + (-60)*x)*y^5 + (12*x^5 + (-147)*x^3 + 300*x)*y^3 + (4*x^7 + (-60)*x^5 + 300*x^3 + (-500)*x)*y // 9 + + "P[2(0,P[2(0,148)(1,20)(2,1)])(1,P[0(0,16)])(2,P[0(0,1)])]", // y^2 + 16*y + (x^2 + 20*x + 148) //10 + + "P[0(0,P[1(0,10)(1,1)])]", // x+10 // 11 +}; + + + +static const int ACK_2_n_polys = 12; + +template< class AlgebraicCurveKernel_2 > +void test_algebraic_curve_kernel_2() { + + typedef AlgebraicCurveKernel_2 AK_2; + + /* BOOST_STATIC_ASSERT( (::boost::is_same< + Algebraic_real_1, typename AK::Algebraic_real_1 >::value) ); + + BOOST_STATIC_ASSERT((::boost::is_same< + Isolator, + typename AK::Isolator >::value) ); + + BOOST_STATIC_ASSERT((::boost::is_same< + Coefficient, + typename AK::Coefficient >::value)); + + BOOST_STATIC_ASSERT((::boost::is_same< + Polynomial_1, + typename AK::Polynomial_1 >::value));*/ + + typedef typename AK_2::Polynomial_2 Poly_2; + typedef typename AK_2::Curve_analysis_2 Curve_analysis_2; + typedef typename Curve_analysis_2::Status_line_1 + Status_line_1; + + typedef typename AK_2::Algebraic_real_1 Algebraic_real_1; + typedef typename AK_2::Algebraic_real_2 Algebraic_real_2; + + typedef typename AK_2::Coordinate_1 Coordinate_1; + typedef typename AK_2::Coordinate_2 Coordinate_2; + + Poly_2 polys[ACK_2_n_polys]; + + ::CGAL::set_mode(std::cerr, ::CGAL::IO::PRETTY); + + //std::cerr << "constructing curves..\n"; + for(int i = 0; i < ACK_2_n_polys; i++) { + std::istringstream in(ACK_2_ascii_polys[i]); + in >> polys[i]; + } + + + + + + ///////// testing curve construction ////////// + + + AK_2 kernel_2; + Curve_analysis_2 c0 = kernel_2.construct_curve_2_object()(polys[0]), + // make it decomposable + c1 = kernel_2.construct_curve_2_object()(polys[1]*polys[2]), + c2 = kernel_2.construct_curve_2_object()(polys[2]), + c3 = kernel_2.construct_curve_2_object()(polys[3]), + c5 = kernel_2.construct_curve_2_object()(polys[5]), + c6 = kernel_2.construct_curve_2_object()(polys[6]); + //std::cerr << "done..\n"; + + Status_line_1 line1, line2; + Algebraic_real_2 xy1, xy2, xy3, xy4; + + ///////////// testing sign_at_2 for non-coprime case ///////////// + + { + Curve_analysis_2 c7_c6 = + kernel_2.construct_curve_2_object()(polys[7]*polys[6]); + assert(c7_c6.number_of_status_lines_with_event() > 0); + Status_line_1 line = c7_c6.status_line_at_event(0); + assert(line.number_of_events() > 0); + Algebraic_real_2 xy = line.algebraic_real_2(0); + + //std::cerr << "done..1.5\n"; + assert(kernel_2.sign_at_2_object()(c7_c6, xy) == CGAL::ZERO); + } + { + Curve_analysis_2 c7_c6 = + kernel_2.construct_curve_2_object()(polys[7]*polys[6]), + c8_c6 = kernel_2.construct_curve_2_object()(polys[8]*polys[6]); + + assert(c7_c6.number_of_status_lines_with_event() > 0); + Status_line_1 line = c7_c6.status_line_at_event(0); + assert(line.number_of_events() > 0); + Algebraic_real_2 xy = line.algebraic_real_2(0); + + //std::cerr << "done..1.6\n"; + assert(kernel_2.sign_at_2_object()(c8_c6, xy) == CGAL::ZERO); + } + + //std::cerr << "done..2\n"; + + + ///////// test buggy y() ////////////// + + { + Curve_analysis_2 c9 = kernel_2.construct_curve_2_object()(polys[9]); + + typename Algebraic_real_1::Polynomial_1 f(25,0,-11,0,1); + + typedef typename Algebraic_real_1::Rational Rational; + + Rational left(-3), right(-2); + + Algebraic_real_1 x(f,left,right); + + Algebraic_real_2 xy(x,c9,0); + + xy.y(); + } + + ///////// testing comparison predicates ////////// + + line1 = c0.status_line_of_interval(0); + xy1 = line1.algebraic_real_2(1); + line2 = c1.status_line_at_event(1); + xy2 = line2.algebraic_real_2(2); + xy3 = line2.algebraic_real_2(1); + + assert(kernel_2.compare_x_2_object()(xy1, xy2) == CGAL::SMALLER); + assert(kernel_2.compare_x_2_object()(xy2, xy3) == CGAL::EQUAL); + + assert(kernel_2.compare_xy_2_object()(xy1, xy2) == + CGAL::SMALLER); + assert(kernel_2.compare_xy_2_object()(xy2, xy3) == + CGAL::LARGER); + + xy1 = c2.status_line_at_event(0).algebraic_real_2(0); + line2 = c3.status_line_at_event(0); + xy2 = line2.algebraic_real_2(2); + xy3 = line2.algebraic_real_2(3); + xy4 = line2.algebraic_real_2(4); + + //std::cerr << "y_comp 1" << std::flush; + assert(kernel_2.compare_y_2_object()(xy1, xy2) == CGAL::LARGER); + //std::cerr << " 2" << std::flush; + assert(kernel_2.compare_y_2_object()(xy1, xy3) == CGAL::SMALLER); + //std::cerr << " 3" << std::flush; + assert(kernel_2.compare_y_2_object()(xy1, xy4) == CGAL::SMALLER); + //std::cerr << " 4" << std::flush; + assert(kernel_2.compare_y_2_object()(xy2, xy3) == CGAL::SMALLER); + //std::cerr << " done" << std::endl; + + /////// testing squarefreeness and coprimality ///////// + + /*assert( + kernel_2.has_finite_number_of_self_intersections_2_object() + (polys[0])); + assert( + !kernel_2.has_finite_number_of_self_intersections_2_object() + (polys[4])); // non-squarefree*/ + + assert( + kernel_2.has_finite_number_of_intersections_2_object() + (c2.polynomial_2(), c3.polynomial_2())); // coprime + + assert( + !kernel_2.has_finite_number_of_intersections_2_object() + (c1.polynomial_2(), c2.polynomial_2())); // non-coprime + + assert( + !kernel_2.has_finite_number_of_intersections_2_object() + (c5.polynomial_2(), c6.polynomial_2())); // non-coprime + + //////// testing decompose /////////// + + assert((kernel_2.decompose_2_object()(polys[4])) != + polys[4]); // non-squarefree + + assert((kernel_2.decompose_2_object()(polys[3])) == + polys[3]); + + typedef std::vector Curves_2; + typedef std::vector Int_vector; + Curves_2 parts; + Int_vector mults; + typename Curves_2::const_iterator cit; + typename Int_vector::const_iterator iit; + + //std::cerr << "n_factors: " << kernel_2.decompose_2_object()(c1, + // std::back_inserter(parts), std::back_inserter(mults)); + + for(cit = parts.begin(), iit = mults.begin(); cit != parts.end(); + cit++, iit++) { + //std::cerr << "part: " << cit->f() << "; mult: " << *iit << "\n"; + } + + parts.clear(); + mults.clear(); + + + //std::cerr << "n_factors :" << + // kernel_2.decompose_2_object()(c3, std::back_inserter(parts), + // std::back_inserter(mults)); + for(cit = parts.begin(), iit = mults.begin(); cit != parts.end(); + cit++, iit++) { + //std::cerr << "part: " << cit->f() << "; mult: " << *iit << "\n"; + } + + Curves_2 fgs, fs, gs; + + assert(kernel_2.decompose_2_object()(c5, c6, + std::back_inserter(fs), std::back_inserter(gs), + std::back_inserter(fgs))); // must have a common part + + assert(fgs.size() == 1); + assert(fs.size() == 0); + assert(gs.size() == 1); + + /*std::cerr << "common: " << fgs.size() << "; " << + fs.size() << "; " << gs.size() << "\n";*/ + + fgs.clear(); + fs.clear(); + gs.clear(); + assert(!kernel_2.decompose_2_object()(c2, c3, + std::back_inserter(fs), std::back_inserter(gs), + std::back_inserter(fgs))); // must be coprime + + assert(fgs.size() == 0); + assert(fs.size() == 1); + assert(gs.size() == 1); + + /*std::cerr << "coprime: " << fgs.size() << "; " << + fs.size() << "; " << gs.size() << "\n";*/ + + //////// testing x/y-critical points //////// + + typedef std::vector Xy_coords; + + Xy_coords points; + typename Xy_coords::const_iterator xyit; + kernel_2.x_critical_points_2_object()(c0, std::back_inserter(points)); + + assert(points.size() == 10); + //std::cerr << "testing x-critical points: " << points.size() << "\n"; + + points.clear(); + kernel_2.y_critical_points_2_object()(c0, std::back_inserter(points)); + + assert(points.size() == 10); + + ///////// testing sign_2 ////////////// + + Status_line_1 line; + Algebraic_real_2 xy; + + int n_lines = c0.number_of_status_lines_with_event(), ii, jj, + n_events; + for(ii = 0; ii < n_lines; ii++) { + + line = c0.status_line_at_event(ii); + n_events = line.number_of_events(); + //std::cout << ii << "pts at event: \n"; + for(jj = 0; jj < n_events; jj++) { + xy = line.algebraic_real_2(jj); + //std::cout << "sign 2: " << + // kernel_2.sign_at_2_object()(c1, xy) << "\n\n"; + } + + //std::cout << ii << "pts over interval: \n"; + line = c0.status_line_of_interval(ii); + n_events = line.number_of_events(); + for(jj = 0; jj < n_events; jj++) { + xy = line.algebraic_real_2(jj); + //std::cout << " sign 2: " << + // kernel_2.sign_at_2_object()(c1, xy) << "\n\n"; + } + } + + + ///////////// testing solve_2 ///////////// + + points.clear(); + mults.clear(); + kernel_2.solve_2_object()(c2, c3, std::back_inserter(points), + std::back_inserter(mults)); + + for(xyit = points.begin(), iit = mults.begin(); xyit != points.end(); + xyit++, iit++) { + //std::cerr << "pt: " << *xyit << "; mult: " << *iit << "\n"; + } + + points.clear(); + mults.clear(); + Curve_analysis_2 c10 = kernel_2.construct_curve_2_object()(polys[10]), + c11 = kernel_2.construct_curve_2_object()(polys[11]); + kernel_2.solve_2_object()(c10, c11, std::back_inserter(points), + std::back_inserter(mults)); + assert(points.size()==2); + points.clear(); + mults.clear(); + kernel_2.solve_2_object()(c11, c10, std::back_inserter(points), + std::back_inserter(mults)); + assert(points.size()==2); + + + + ///////////// testing Swap_x_and_y ///////////// + { + Curve_analysis_2 c7_c6 = + kernel_2.construct_curve_2_object()(polys[7]*polys[6]); + + Curve_analysis_2 swapped = kernel_2.swap_x_and_y_2_object()(c7_c6); + (void) swapped; + + } + ///////////// Overloaded sign_at_1 functor + { + typedef typename AK_2::Polynomial_1 Polynomial_1; + Polynomial_1 p(5,-4,3,-2,-1,1); + AK_2 kernel_2; + Algebraic_real_1 ar(p,-3,3); + assert(kernel_2.sign_at_1_object()(p,ar,1000)==CGAL::ZERO); + Polynomial_1 q(1,0,0,-1,1,0,0,1); + Algebraic_real_1 ar2(q,-2,0); + assert(kernel_2.sign_at_1_object()(p,ar2)==CGAL::POSITIVE); + Polynomial_1 r(500001,-400000,300000,-200000,-100000,100000); + Algebraic_real_1 ar3(r,-5,5); + assert(kernel_2.sign_at_1_object()(p,ar3)==CGAL::NEGATIVE); + } + +} + +} //namespace internal + +} //namespace CGAL + +#endif // CGAL_TEST_ALGEBRAIC_CURVE_KERNEL_2_H diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h index 5ff1a0cd2f1..c12f6f76e01 100644 --- a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h @@ -1,14 +1,22 @@ -// TODO: Add licence +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // -// $URL$ -// $Id$ -// +// $URL: svn+ssh://mkerber@scm.gforge.inria.fr/svn/cgal/trunk/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_1.h $ +// $Id: _test_algebraic_kernel_1.h 55082 2010-03-31 12:52:26Z penarand $ // // Author(s) : Sebastian Limbach -// Michael Hemmer +// Michael Hemmer // // ============================================================================ @@ -78,16 +86,20 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ //test_explicit_interoperable_from_to(); //test_explicit_interoperable_from_to(); -#define CGAL_GET_FTOR(Name,name) \ - typedef typename AlgebraicKernel_d_1::Name Name; \ +#define CGAL_GET_FTOR(Name,name) \ + typedef typename AlgebraicKernel_d_1::Name Name; \ const Name name = ak_1.name##_object(); + + CGAL_GET_FTOR(Construct_algebraic_real_1,construct_algebraic_real_1); + CGAL_GET_FTOR(Compute_polynomial_1,compute_polynomial_1); CGAL_GET_FTOR(Is_square_free_1,is_square_free_1); CGAL_GET_FTOR(Make_square_free_1,make_square_free_1); CGAL_GET_FTOR(Square_free_factorize_1,square_free_factorize_1); CGAL_GET_FTOR(Is_coprime_1,is_coprime_1); CGAL_GET_FTOR(Make_coprime_1,make_coprime_1); CGAL_GET_FTOR(Solve_1,solve_1); + CGAL_GET_FTOR(Number_of_solutions_1,number_of_solutions_1); CGAL_GET_FTOR(Sign_at_1,sign_at_1); CGAL_GET_FTOR(Is_zero_at_1,is_zero_at_1); CGAL_GET_FTOR(Compare_1,compare_1); @@ -113,12 +125,15 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ } + // TODO: missing check for Construct_algebraic_real_1 + CGAL_CHECK_UFUNCTION(Compute_polynomial_1,Algebraic_real_1,Polynomial_1); CGAL_CHECK_UFUNCTION(Is_square_free_1,Polynomial_1,bool); CGAL_CHECK_UFUNCTION(Make_square_free_1,Polynomial_1,Polynomial_1); // TODO: missing check for Square_free_factorize_1 CGAL_CHECK_BFUNCTION(Is_coprime_1,Polynomial_1,Polynomial_1,bool); // TODO: missing check for Make_coprime_1 // TODO: missing check for Solve_1 + CGAL_CHECK_UFUNCTION(Number_of_solutions_1,Polynomial_1,int); CGAL_CHECK_BFUNCTION(Sign_at_1,Polynomial_1,Algebraic_real_1,Sign); CGAL_CHECK_BFUNCTION(Is_zero_at_1,Polynomial_1,Algebraic_real_1,bool); CGAL_CHECK_BFUNCTION(Compare_1,Algebraic_real_1,Algebraic_real_1,Sign); @@ -130,13 +145,12 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ Polynomial_1 x = typename PT::Shift()(Polynomial_1(1),1); { - assert( is_square_free_1(ipower((x-1),1))); - assert(!is_square_free_1(ipower((x-1),2))); + assert( is_square_free_1(ipower((x-1),1))); + assert(!is_square_free_1(ipower((x-1),2))); } { - assert( make_square_free_1(ipower(5*(x-1),2))==ipower((x-1),1)); + assert( make_square_free_1(ipower(5*(x-1),2))==ipower((x-1),1)); } - { std::list< std::pair > factors; square_free_factorize_1((x-1)*(x-2)*(x-2),std::back_inserter(factors)); @@ -189,6 +203,19 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ solve_1((x-1)*(x-2)*(x-2),biit); // use iterator again assert(roots.size()==4); } + { + // Compute_polynomial + typedef std::vector > ROOTS; + ROOTS roots; + Polynomial_1 p1 = (x-1)*(x-2)*(x-2); + std::back_insert_iterator biit = + solve_1(p1,std::back_inserter(roots)); + Algebraic_real_1 ar = roots[1].first; + Polynomial_1 p2 = compute_polynomial_1(ar); + assert(!is_coprime_1(p1,p2)); + assert(is_zero_at_1(p2,ar)); + + } { // solve_1 for OI::value_type == std::pair typedef std::list ROOTS; @@ -208,6 +235,10 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ solve_1((x-1)*(x-2),true,biit); // use iterator again assert(roots.size()==4); } + { + // number_of_solutions + assert(3 == number_of_solutions_1((x-1)*(x-2)*(x-3))); + } { assert(sign_at_1(x*0,Algebraic_real_1(0)) == ZERO); @@ -315,6 +346,36 @@ void test_algebraic_kernel_1(const AlgebraicKernel_d_1& ak_1){ <= (CGAL::max)(abs(bi.first),abs(bi.second)) ); } } + + { + +#define CGAL_TEST_ALGEBRAIC_REAL_IO(_f) \ + alg1=_f; \ + ss<>CGAL::iformat(alg2); \ + assert(alg1==alg2) + + + const typename Algebraic_kernel_d_1::Construct_algebraic_real_1 construct_algreal_1 = + ak_1.construct_algebraic_real_1_object(); + + Algebraic_real_1 alg1,alg2; + std::stringstream ss; + CGAL::set_ascii_mode(ss); + + // test construction from int, Coefficient and Bound + CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(int(2))); + CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(Coefficient(2))); + CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(Bound(2))); + + // construction by index + Polynomial_1 x = CGAL::shift(Polynomial_1(1),1); // the monom x + CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(x*x-2,1)); + + // construction by isolating interval + CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(x*x-2,Bound(0),Bound(2))); +#undef CGAL_TEST_ALGEBRAIC_REAL_IO + } } } // namespace CGAL diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_2.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_2.h new file mode 100644 index 00000000000..6cf8d6ad735 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_algebraic_kernel_2.h @@ -0,0 +1,502 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// +// ============================================================================ + +#include +#include +#include + +//#include + +#include +#include + +#ifndef CGAL_TEST_ALGEBRAIC_KERNEL_2_H +#define CGAL_TEST_ALGEBRAIC_KERNEL_2_H + +// For convenience +#define pow(a,b) CGAL::ipower(a,b) + +namespace CGAL { + +template< class AlgebraicKernel_2 > +void test_algebraic_kernel_2(const AlgebraicKernel_2& ak_2) { + + typedef AlgebraicKernel_2 AK_2; + + // AK_2 is also AK_1, thus test it: + CGAL::test_algebraic_kernel_1(ak_2); + + typedef typename AK_2::Coefficient Coefficient; + typedef typename AK_2::Bound Bound; + typedef std::pair BInterval; + typedef CGAL::cpp0x::array BArray; + typedef typename AK_2::Polynomial_1 Polynomial_1; + typedef typename AK_2::Polynomial_2 Polynomial_2; + typedef typename AK_2::Algebraic_real_1 Algebraic_real_1; + typedef typename AK_2::Algebraic_real_2 Algebraic_real_2; + typedef typename AK_2::size_type size_type; + typedef typename AK_2::Multiplicity_type Multiplicity_type; + + typedef CGAL::Polynomial_traits_d Polynomial_traits_1; + typedef CGAL::Polynomial_traits_d Polynomial_traits_2; + + + #define CGAL_GET_FTOR(Name,name) \ + typedef typename AK_2::Name Name; \ + const Name name = ak_2.name##_object(); + + CGAL_GET_FTOR(Construct_algebraic_real_1,construct_algebraic_real_1); + CGAL_GET_FTOR(Compare_1,compare_1); + CGAL_GET_FTOR(Is_zero_at_1,is_zero_at_1); + CGAL_GET_FTOR(Solve_1,solve_1); + + CGAL_GET_FTOR(Construct_algebraic_real_2,construct_algebraic_real_2); + CGAL_GET_FTOR(Is_square_free_2,is_square_free_2); + CGAL_GET_FTOR(Make_square_free_2,make_square_free_2); + CGAL_GET_FTOR(Square_free_factorize_2,square_free_factorize_2); + CGAL_GET_FTOR(Is_coprime_2,is_coprime_2); + CGAL_GET_FTOR(Make_coprime_2,make_coprime_2); + CGAL_GET_FTOR(Solve_2,solve_2); + CGAL_GET_FTOR(Number_of_solutions_2,number_of_solutions_2); + CGAL_GET_FTOR(Sign_at_2,sign_at_2); + CGAL_GET_FTOR(Is_zero_at_2,is_zero_at_2); + CGAL_GET_FTOR(Compute_x_2,compute_x_2); + CGAL_GET_FTOR(Compute_y_2,compute_y_2); + CGAL_GET_FTOR(Compute_polynomial_x_2,compute_polynomial_x_2); + CGAL_GET_FTOR(Compute_polynomial_y_2,compute_polynomial_y_2); + CGAL_GET_FTOR(Isolate_x_2,isolate_x_2); + CGAL_GET_FTOR(Isolate_y_2,isolate_y_2); + CGAL_GET_FTOR(Isolate_2,isolate_2); + CGAL_GET_FTOR(Compare_x_2,compare_x_2); + CGAL_GET_FTOR(Compare_y_2,compare_y_2); + CGAL_GET_FTOR(Compare_xy_2,compare_xy_2); + CGAL_GET_FTOR(Bound_between_x_2,bound_between_x_2); + CGAL_GET_FTOR(Bound_between_y_2,bound_between_y_2); + CGAL_GET_FTOR(Approximate_absolute_x_2,approximate_absolute_x_2); + CGAL_GET_FTOR(Approximate_absolute_y_2,approximate_absolute_y_2); + CGAL_GET_FTOR(Approximate_relative_x_2,approximate_relative_x_2); + CGAL_GET_FTOR(Approximate_relative_y_2,approximate_relative_y_2); +#undef CGAL_GET_FTOR + + #define CGAL_CHECK_UFUNCTION(Name,AT,RT) \ + { \ + typedef typename Name::argument_type AT_; \ + typedef typename Name::result_type RT_; \ + {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ + {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ + } + #define CGAL_CHECK_BFUNCTION(Name,AT1,AT2,RT) \ + { \ + typedef typename Name::first_argument_type AT1_; \ + typedef typename Name::second_argument_type AT2_; \ + typedef typename Name::result_type RT_; \ + {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ + {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ + {BOOST_STATIC_ASSERT(( ::boost::is_same::value));} \ + } + + + BOOST_STATIC_ASSERT(( ::boost::is_same + + ::value)); + CGAL_CHECK_UFUNCTION(Is_square_free_2,Polynomial_2,bool); + CGAL_CHECK_UFUNCTION(Make_square_free_2,Polynomial_2,Polynomial_2); + // TODO: missing check for Square_free_factorize_2 + CGAL_CHECK_BFUNCTION(Is_coprime_2,Polynomial_2,Polynomial_2,bool); + BOOST_STATIC_ASSERT(( ::boost::is_same + ::value)); + CGAL_CHECK_BFUNCTION(Number_of_solutions_2,Polynomial_2,Polynomial_2, + size_type); + CGAL_CHECK_UFUNCTION(Compute_x_2,Algebraic_real_2,Algebraic_real_1); + CGAL_CHECK_UFUNCTION(Compute_y_2,Algebraic_real_2,Algebraic_real_1); + CGAL_CHECK_UFUNCTION(Compute_polynomial_x_2,Algebraic_real_2,Polynomial_1); + CGAL_CHECK_UFUNCTION(Compute_polynomial_y_2,Algebraic_real_2,Polynomial_1); + CGAL_CHECK_BFUNCTION(Isolate_x_2,Algebraic_real_2,Polynomial_1,BInterval); + CGAL_CHECK_BFUNCTION(Isolate_y_2,Algebraic_real_2,Polynomial_1,BInterval); + BOOST_STATIC_ASSERT(( ::boost::is_same + < BArray,typename Isolate_2::result_type>::value)); + CGAL_CHECK_BFUNCTION(Sign_at_2,Polynomial_2,Algebraic_real_2,Sign); + CGAL_CHECK_BFUNCTION(Is_zero_at_2,Polynomial_2,Algebraic_real_2,bool); + CGAL_CHECK_BFUNCTION(Compare_x_2,Algebraic_real_2,Algebraic_real_2,Sign); + CGAL_CHECK_BFUNCTION(Compare_y_2,Algebraic_real_2,Algebraic_real_2,Sign); + CGAL_CHECK_BFUNCTION(Compare_xy_2,Algebraic_real_2,Algebraic_real_2,Sign); + CGAL_CHECK_BFUNCTION(Bound_between_x_2,Algebraic_real_2, + Algebraic_real_2,Bound); + CGAL_CHECK_BFUNCTION(Bound_between_y_2,Algebraic_real_2, + Algebraic_real_2,Bound); + CGAL_CHECK_BFUNCTION(Approximate_absolute_x_2,Algebraic_real_2, + int,BInterval); + CGAL_CHECK_BFUNCTION(Approximate_absolute_y_2,Algebraic_real_2, + int,BInterval); + CGAL_CHECK_BFUNCTION(Approximate_relative_x_2,Algebraic_real_2, + int,BInterval); + CGAL_CHECK_BFUNCTION(Approximate_relative_y_2,Algebraic_real_2, + int,BInterval); +#undef CGAL_CHECK_BFUNCTION +#undef CGAL_CHECK_UFUNCTION + + typename Polynomial_traits_1::Construct_polynomial construct_polynomial_1; + std::pair coeffs_t[1] + = {std::make_pair(CGAL::Exponent_vector(1),Coefficient(1))}; + Polynomial_1 t=construct_polynomial_1(coeffs_t,coeffs_t+1); + + typename Polynomial_traits_2::Construct_polynomial construct_polynomial_2; + std::pair coeffs_x[1] + = {std::make_pair(CGAL::Exponent_vector(1,0),Coefficient(1))}; + Polynomial_2 x=construct_polynomial_2(coeffs_x,coeffs_x+1); + std::pair coeffs_y[1] + = {std::make_pair(CGAL::Exponent_vector(0,1),Coefficient(1))}; + Polynomial_2 y=construct_polynomial_2(coeffs_y,coeffs_y+1); + Polynomial_2 one=construct_polynomial_2(Coefficient(1)); + + { + // Construct_algebraic_real_2 + Algebraic_real_2 ar1 = construct_algebraic_real_2(1,1); + Algebraic_real_2 ar2 = construct_algebraic_real_2(Bound(1),Bound(1)); + Algebraic_real_2 ar3 + = construct_algebraic_real_2(Coefficient(2),Coefficient(-2)); + Algebraic_real_2 ar4 + = construct_algebraic_real_2(construct_algebraic_real_1(Coefficient(2)), + construct_algebraic_real_1(Bound(-5))); + // 3y+2x+2 + Polynomial_2 pol1_2 = y*3+x*2+2; + // x^2+xy + Polynomial_2 pol2_2 = pow(x,2)+x*y; + Algebraic_real_2 ar5 + = construct_algebraic_real_2(pol1_2,pol2_2,0); // (0,-2/3) + + Algebraic_real_2 ar6 + = construct_algebraic_real_2(pol1_2,pol2_2,1); // (2,-2) + + Algebraic_real_2 ar7 + = construct_algebraic_real_2(pol1_2,pol2_2, + Bound(-3),Bound(3),Bound(-1),Bound(100)); + + // Comparisons + CGAL_assertion(compare_xy_2(ar1,ar2)==CGAL::EQUAL); + CGAL_assertion(compare_xy_2(ar1,ar3)==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(ar2,ar3)==CGAL::SMALLER); + CGAL_assertion(compare_y_2(ar1,ar3)==CGAL::LARGER); + CGAL_assertion(compare_x_2(ar3,ar4)==CGAL::EQUAL); + CGAL_assertion(compare_y_2(ar3,ar4)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(ar3,ar4)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(ar3,ar6)==CGAL::EQUAL); + CGAL_assertion(compare_x_2(ar1,ar5)==CGAL::LARGER); + CGAL_assertion(compare_x_2(ar5,0)==CGAL::EQUAL); + CGAL_assertion(compare_x_2(ar5,Bound(0))==CGAL::EQUAL); + CGAL_assertion(compare_x_2(ar5,Coefficient(0))==CGAL::EQUAL); + CGAL_assertion(compare_x_2(ar5,construct_algebraic_real_1(0))==CGAL::EQUAL); + CGAL_assertion(compare_x_2(0,ar5)==CGAL::EQUAL); + CGAL_assertion(compare_x_2(Bound(0),ar5)==CGAL::EQUAL); + CGAL_assertion(compare_x_2(Coefficient(0),ar5)==CGAL::EQUAL); + CGAL_assertion(compare_x_2(construct_algebraic_real_1(0),ar5)==CGAL::EQUAL); + CGAL_assertion(compare_y_2(ar5,0)==CGAL::SMALLER); + CGAL_assertion(compare_y_2(ar5,Bound(0))==CGAL::SMALLER); + CGAL_assertion(compare_y_2(ar5,Coefficient(0))==CGAL::SMALLER); + CGAL_assertion(compare_y_2(ar5,construct_algebraic_real_1(0)) + ==CGAL::SMALLER); + CGAL_assertion(compare_y_2(0,ar5)==CGAL::LARGER); + CGAL_assertion(compare_y_2(Bound(0),ar5)==CGAL::LARGER); + CGAL_assertion(compare_y_2(Coefficient(0),ar5)==CGAL::LARGER); + CGAL_assertion(compare_y_2(construct_algebraic_real_1(0),ar5)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(ar5,0,0)==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(ar5,Bound(0),Bound(0))==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(ar5,Coefficient(0),Coefficient(0)) + ==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(ar5,construct_algebraic_real_1(0), + construct_algebraic_real_1(0))==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(0,0,ar5)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(Bound(0),Bound(0),ar5)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(Coefficient(0),Coefficient(0),ar5) + ==CGAL::LARGER); + CGAL_assertion(compare_xy_2(construct_algebraic_real_1(0), + construct_algebraic_real_1(0), + ar5)==CGAL::LARGER); + CGAL_assertion(compare_y_2(0,ar5)==CGAL::LARGER); + CGAL_assertion(compare_y_2(-1,ar5)==CGAL::SMALLER); + CGAL_assertion(compare_xy_2(ar5,-1,1000)==CGAL::LARGER); + CGAL_assertion(compare_xy_2(ar5,ar7)==CGAL::EQUAL); + + // Compute_x/y_2 + Algebraic_real_1 ar1_x = compute_x_2(ar1); + CGAL_assertion(compare_1(1,ar1_x)==CGAL::EQUAL); + CGAL_assertion(compare_1(ar1_x,1)==CGAL::EQUAL); + Algebraic_real_1 ar6_y = compute_y_2(ar6); + CGAL_assertion(compare_1(Bound(-2),ar6_y)==CGAL::EQUAL); + CGAL_assertion(compare_1(ar6_y,Bound(-2))==CGAL::EQUAL); + + // SignAt_2, IsZeroAt_2 + CGAL_assertion(sign_at_2(pol1_2,ar4)==CGAL::NEGATIVE); + CGAL_assertion(! is_zero_at_2(pol1_2,ar4)); + CGAL_assertion(sign_at_2(pol2_2,ar7)==CGAL::ZERO); + CGAL_assertion(is_zero_at_2(pol2_2,ar7)); + CGAL_assertion(sign_at_2(pol2_2,ar1)==CGAL::POSITIVE); + CGAL_assertion(! is_zero_at_2(pol1_2,ar4)); + + // ComputePolynomial + Polynomial_1 pol1_x = compute_polynomial_x_2(ar1); + CGAL_assertion(is_zero_at_1(pol1_x,compute_x_2(ar1))); + Polynomial_1 pol1_y = compute_polynomial_y_2(ar1); + CGAL_assertion(is_zero_at_1(pol1_y,compute_y_2(ar1))); + + // Is_square_free, Make_square_free + CGAL_assertion(is_square_free_2(pol1_2)); + CGAL_assertion(! is_square_free_2(pol1_2*pol1_2)); + Polynomial_2 pol1_2_prime = make_square_free_2(pol1_2*pol1_2); + CGAL_assertion(CGAL::canonicalize(pol1_2) + ==CGAL::canonicalize(pol1_2_prime)); + // Is_coprime, Make_coprime + CGAL_assertion(is_coprime_2(pol1_2,pol2_2)); + CGAL_assertion(is_coprime_2(pol1_2*Coefficient(3),pol2_2*Coefficient(3))); + CGAL_assertion(! is_coprime_2(pol1_2,pol1_2*pol2_2)); + Polynomial_2 g,q1,q2; + bool check = make_coprime_2(pol1_2,pol1_2*pol2_2,g,q1,q2); + CGAL_assertion(! check); + CGAL_assertion(CGAL::canonicalize(q1) + ==CGAL::canonicalize(one)); + CGAL_assertion(CGAL::canonicalize(q2)==CGAL::canonicalize(pol2_2)); + CGAL_assertion(CGAL::canonicalize(g)==CGAL::canonicalize(pol1_2)); + check = make_coprime_2(pol2_2,pol1_2,g,q1,q2); + CGAL_assertion(check); + CGAL_assertion(CGAL::canonicalize(q1)==CGAL::canonicalize(pol2_2)); + CGAL_assertion(CGAL::canonicalize(q2)==CGAL::canonicalize(pol1_2)); + CGAL_assertion(CGAL::total_degree(g)==0); + // Test coprime also for factors in x only + Polynomial_2 pol3_2 = pow(x,2)-3; + CGAL_assertion(! is_coprime_2(pol3_2*pol1_2, pol3_2*pol3_2*pol2_2)); + check = make_coprime_2(pol3_2*pol1_2, pol3_2*pol3_2*pol2_2,g,q1,q2); + CGAL_assertion(! check); + CGAL_assertion(CGAL::canonicalize(g)==CGAL::canonicalize(pol3_2)); + CGAL_assertion(CGAL::canonicalize(q1)==CGAL::canonicalize(pol1_2)); + CGAL_assertion(CGAL::canonicalize(q2)==CGAL::canonicalize(pol3_2*pol2_2)); + // Square_free_factorize_2 + std::vector > sqfr_factors; + Polynomial_2 sqfr_fac_test_pol + = pol1_2*CGAL::ipower(pol2_2,3)*CGAL::ipower(pol3_2,7); + square_free_factorize_2(sqfr_fac_test_pol, + std::back_inserter(sqfr_factors)); + Polynomial_2 sqfr_fac_checksum=one; + for(unsigned int i=0;i > roots,roots2; + solve_2(pol1,pol2,std::back_inserter(roots)); + CGAL_assertion(roots.size()==4); + for(size_type i = 0; i < 4; i++) { + CGAL_assertion(roots[i].second==1); + } + solve_2(pol1,pol2,Bound(-7),Bound(-1),Bound(-123),Bound(1), + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==1); + solve_2(pol1,pol2,Bound(-7),Bound(17),Bound(1),Bound(2), + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==2); // sum of the roots so far + solve_2(pol1,pol2,Bound(-1),Bound(8),Bound(-9),Bound(20), + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==4); // sum of the roots so far + std::sort(roots.begin(),roots.end()); + std::sort(roots2.begin(),roots2.end()); + CGAL_assertion(std::equal(roots.begin(),roots.end(),roots2.begin())); + + CGAL_assertion(number_of_solutions_2(pol1,pol2*pol3)==7); + roots2.clear(); + solve_2(pol1,pol2*pol3,Bound(-2),Bound(0),Bound(0),Bound(1), + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==5); + + // Isolate_2 + Polynomial_2 circle = pow(x,2)+pow(y,2)-1; + Algebraic_real_2 ar1 = construct_algebraic_real_2(10*x+1,10*y-1,0); + BArray box = isolate_2(ar1,circle); + CGAL_assertion(box[0]>-1); + CGAL_assertion(box[1]<1); + CGAL_assertion(box[2]>-1); + CGAL_assertion(box[3]<1); + CGAL_assertion(sign_at_2(circle,construct_algebraic_real_2(box[0],box[2])) + == CGAL::NEGATIVE); + CGAL_assertion(sign_at_2(circle,construct_algebraic_real_2(box[1],box[2])) + == CGAL::NEGATIVE); + CGAL_assertion(sign_at_2(circle,construct_algebraic_real_2(box[0],box[3])) + == CGAL::NEGATIVE); + CGAL_assertion(sign_at_2(circle,construct_algebraic_real_2(box[1],box[3])) + == CGAL::NEGATIVE); + isolate_2(ar1,one); + box = isolate_2(ar1,pol1,pol2*pol3); + roots2.clear(); + solve_2(pol1,pol2*pol3,box[0],box[1],box[2],box[3], + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==0); + roots.clear(); + roots2.clear(); + solve_2(pol1,pol2*pol3,std::back_inserter(roots)); + CGAL_assertion(roots.size()==7); + for(size_type i = 0; i < 7; i++) { + box=isolate_2(roots[i].first,pol1,pol2*pol3); + solve_2(pol1,pol2*pol3,box[0],box[1],box[2],box[3], + std::back_inserter(roots2)); + CGAL_assertion(roots2.size()==static_cast(i+1)); + } + std::sort(roots.begin(),roots.end()); + std::sort(roots2.begin(),roots2.end()); + CGAL_assertion(std::equal(roots.begin(),roots.end(),roots2.begin())); + + // Isolate_x_2, and Isolate_y_2 + Polynomial_1 q = pow(t,8) - 7*pow(t,6)+3*pow(t,3)-2*pow(t,2)+1; + CGAL_assertion(!is_zero_at_1(q,compute_x_2(ar1))); + BInterval bounds = isolate_x_2(ar1,q); + CGAL_assertion(bounds.first<=bounds.second); + std::vector roots_1,roots2_1,roots3_1; + solve_1(q,false,bounds.first,bounds.second,std::back_inserter(roots_1)); + std::vector > root_pairs_1; + solve_1(q,bounds.first,bounds.second,std::back_inserter(root_pairs_1)); + CGAL_assertion(roots_1.size()==0); + solve_1(q,false,std::back_inserter(roots_1)); + CGAL_assertion(roots_1.size()==4); + for(size_type i=0;i<4;i++) { + Algebraic_real_2 c_ar + = construct_algebraic_real_2(roots_1[i],roots_1[3-i]); + bounds=isolate_x_2(c_ar,q); + solve_1(q,false,bounds.first,bounds.second,std::back_inserter(roots2_1)); + bounds=isolate_y_2(c_ar,q); + solve_1(q,false,bounds.first,bounds.second,std::back_inserter(roots3_1)); + } + CGAL_assertion(roots2_1.size()==roots3_1.size()); + CGAL_assertion(roots_1.size()==roots3_1.size()); + CGAL_assertion(std::equal(roots_1.begin(),roots_1.end(),roots2_1.begin())); + CGAL_assertion(std::equal(roots_1.begin(),roots_1.end(), + roots3_1.rbegin())); + + // Approximate_absolute_2, Approximate_relative_2 + Polynomial_2 pol4 = pow(x,5)+pow(y,2)-y+y*x-1; + Polynomial_2 pol5 = pow(y,2)-pow(x,3); + // absolute + Algebraic_real_2 ar2 + = construct_algebraic_real_2(pol4,pol5, + Bound(0),Bound(2),Bound(0),Bound(3)); + for(int i=1;i<1024;i*=2) { + Bound dist = CGAL::ipower(Bound(2),i); + bounds = approximate_absolute_x_2(ar2,i); + CGAL_assertion(bounds.first<=bounds.second); + CGAL_assertion(compare_x_2(bounds.first,ar2)!=CGAL::LARGER); + CGAL_assertion(compare_x_2(bounds.second,ar2)!=CGAL::SMALLER); + // NOTE: The following check is not sufficient for ensuring + // the postcondition, but if it fails, the postcondition + // cannot be satisfied + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(2)); + // For the default implementation, we can test this - this + // is sufficient for ensuring the postcondition, but other + // kernels might not satisfy this property + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(1)); + bounds = approximate_absolute_y_2(ar2,i); + CGAL_assertion(bounds.first<=bounds.second); + CGAL_assertion(compare_y_2(bounds.first,ar2)!=CGAL::LARGER); + CGAL_assertion(compare_y_2(bounds.second,ar2)!=CGAL::SMALLER); + // NOTE: The following check is not sufficient for ensuring + // the postcondition, but if it fails, the postcondition + // cannot be satisfied + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(2)); + // For the default implementation, we can test this - this + // is sufficient for ensuring the postcondition, but other + // kernels might not satisfy this property + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(1)); + } + + // relative + ar2 = construct_algebraic_real_2(pol4,pol5, + Bound(0),Bound(2),Bound(-3),Bound(0)); + for(int i=1;i<1024;i*=2) { + Bound dist = CGAL::ipower(Bound(2),i); + bounds = approximate_relative_x_2(ar2,i); + Bound min=(CGAL::min)(CGAL::abs(bounds.first),CGAL::abs(bounds.second)); + Bound max=(CGAL::max)(CGAL::abs(bounds.first),CGAL::abs(bounds.second)); + CGAL_assertion(bounds.first<=bounds.second); + CGAL_assertion(CGAL::sign(bounds.first)==CGAL::sign(bounds.second)); + CGAL_assertion(compare_x_2(bounds.first,ar2)!=CGAL::LARGER); + CGAL_assertion(compare_x_2(bounds.second,ar2)!=CGAL::SMALLER); + // NOTE: The following check is not sufficient for ensuring + // the postcondition, but if it fails, the postcondition + // cannot be satisfied + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(2)*max); + // For the default implementation, we can test this - this + // is sufficient for ensuring the postcondition, but other + // kernels might not satisfy this property + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(1)*min); + bounds = approximate_relative_y_2(ar2,i); + CGAL_assertion(bounds.first<=bounds.second); + CGAL_assertion(compare_y_2(bounds.first,ar2)!=CGAL::LARGER); + CGAL_assertion(compare_y_2(bounds.second,ar2)!=CGAL::SMALLER); + // NOTE: The following check is not sufficient for ensuring + // the postcondition, but if it fails, the postcondition + // cannot be satisfied + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(2)*max); + // For the default implementation, we can test this - this + // is sufficient for ensuring the postcondition, but other + // kernels might not satisfy this property + CGAL_assertion(dist*(bounds.second-bounds.first)<=Bound(1)*min); + } + + } + + + + +} + +} //namespace CGAL + +#endif diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_bitstream_descartes.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_bitstream_descartes.h new file mode 100644 index 00000000000..628a85b88c3 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_bitstream_descartes.h @@ -0,0 +1,446 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Kerber +// Eric Berberich +// +// ============================================================================ + +// #include + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include + +#include + +#include + +namespace CGAL { + +namespace internal { + +// A simple model of the EventRefinement concept: +// Uses a vector of Algebraic reals +template +class Event_refinement { + + typedef AlgReal Alg_real; + + typedef typename AlgReal::Rational Rational; + +private: + std::vector events; + +public: + Event_refinement() {} + void add(Alg_real a) {events.push_back(a);} + Rational lower_bound(int i){return events[i].low();} + Rational upper_bound(int i){return events[i].high();} + void refine(int i) {events[i].refine();} +}; + +template +void test_bitstream_descartes() { + + typedef ArithmeticKernel Arithmetic_kernel; + typedef typename Arithmetic_kernel::Integer Integer; + typedef typename Arithmetic_kernel::Rational Rational; + + typedef typename CGAL::Polynomial_type_generator::Type Poly_int1; + typedef typename CGAL::Polynomial_type_generator::Type Poly_int2; + typedef CGAL::internal::Algebraic_real_d_1 + Algebraic_real; + + typedef CGAL::internal::Bitstream_descartes_rndl_tree_traits + > Traits; + + typedef CGAL::internal::Bitstream_descartes Bitstream_descartes; + + Traits traits; + + + + { // Test for the classical Descartes method + std::stringstream ss("P[15(0,59738427711)(1,300038251861)(2,-471253844514)(3,538575935875)(4,22286946912)(5,548111721525)(6,-379185895352)(7,296681325489)(8,-464256140044)(9,410194800463)(10,232977578849)(11,-376080509486)(12,521721411895)(13,-100316773723)(14,-171187873598)(15,-189253202432)]"); + Poly_int1 f; + ss >> f; + + // In Maple: f := 59738427711-189253202432*x^15-171187873598*x^14-100316773723*x^13+521721411895*x^12-376080509486*x^11+232977578849*x^10+410194800463*x^9-464256140044*x^8+296681325489*x^7-379185895352*x^6+548111721525*x^5+22286946912*x^4+538575935875*x^3-471253844514*x^2+300038251861*x + + // We expect 3 roots, at -1.176, -.154 and 1.168 + + CGAL::internal::Square_free_descartes_tag t; + + Bitstream_descartes descartes(t, f); + + assert(descartes.degree_of_gcd() == 0); + assert(descartes.square_free_part() == f); + + int n = descartes.number_of_real_roots(); + + assert(n==3); + + for(int i = 0; i Rational(1,10000)) + { + descartes.refine_interval(i); + } + } + assert(Rational(-118,100)descartes.right_bound(0)); + assert(Rational(-155,1000)descartes.right_bound(1)); + assert(Rational(116,100)descartes.right_bound(2)); + } + + { // Test for the square free case, created with tree from outside + + typedef typename Bitstream_descartes::Bitstream_tree Bitstream_tree; + + std::stringstream ss("P[13(1,1)(4,1)(6,95)(8,77)(11,-51)(13,31)]"); + + Poly_int1 f; + + ss >> f; +#if CGAL_ACK_BITSTREAM_USES_E08_TREE + Bitstream_tree tree(1,f.begin(),f.end(), + typename Bitstream_tree::Monomial_basis_tag()); +#else + Bitstream_tree tree(-2,2,0,f.begin(),f.end(), + typename Bitstream_tree::Monomial_basis_tag()); +#endif + + // We expect 3 roots, at -1.597, -.388 and 0 + + CGAL::internal::Square_free_descartes_tag t; + + Bitstream_descartes descartes(t, f, tree); + + assert(descartes.degree_of_gcd() == 0); + assert(descartes.square_free_part() == f); + + int n = descartes.number_of_real_roots(); + + assert(n==3); + + for(int i = 0; i Rational(1,10000)) + { + descartes.refine_interval(i); + } + } + assert(Rational(-160,100)descartes.right_bound(0)); + assert(Rational(-389,1000)descartes.right_bound(1)); + assert(Rational(-1,100)descartes.right_bound(2)); + } + + + + { // Test for the m-k-Descartes method + + // Polnomial with one multiple root: + + std::stringstream ss("P[11(0,-51960)(1,158454)(2,3015726)(3,-22833405)(4,64277882)(5,-86502719)(6,58622397)(7,-260172)(8,-77833332)(9,85923423)(10,-37885401)(11,1874259)]"); + // This is a polynomial with a 4-fold root at 1/3, and 3 more roots at + // approximate positions -1.036, -0.104, 17.764 + + // In Maple:g := -51960-86502719*x^5+158454*x-22833405*x^3+3015726*x^2+64277882*x^4+1874259*x^11-77833332*x^8+85923423*x^9-37885401*x^10+58622397*x^6-260172*x^7 + + Poly_int1 f; + ss >> f; + + CGAL::internal::M_k_descartes_tag t; + + // We expect 4 real roots (m), and the gcd of g and g' is 3 (k) + Bitstream_descartes descartes(t, f, 4, 3); + + assert(descartes.degree_of_gcd() == 3); + try { + Poly_int1 sq_f = descartes.square_free_part(); + assert(false); + } catch (CGAL::internal::Virtual_method_exception ex) { + // Expected + } + + int n = descartes.number_of_real_roots(); + + assert(n==4); + + for(int i = 0; iRational(1,10000)) + { + descartes.refine_interval(i); + } + } + assert(Rational(-104,100)descartes.right_bound(0)); + assert(Rational(-106,1000)descartes.right_bound(1)); + assert(Rational(33,100)descartes.right_bound(2)); + assert(Rational(1776,100)descartes.right_bound(3)); + + } + + { // Another test for the m-k-method + + // Test for the m-k-Descartes method + + // Polnomial with one multiple root: + + // In Maple:f := y^3 - y^2 -2*y + Poly_int1 f(0,-2,-1,1); + + CGAL::internal::M_k_descartes_tag t; + + // We expect 3 real roots (m), and the degree of gcd of g and g' is 0 (k) + Bitstream_descartes descartes(t, f, 3, 0); + + assert(descartes.degree_of_gcd() == 0); + try { + Poly_int1 sq_f = descartes.square_free_part(); + assert(false); + } catch (CGAL::internal::Virtual_method_exception ex) { + // Expected + } + + int n = descartes.number_of_real_roots(); + + assert(n==3); + + for(int i = 0; iRational(1,10000)) + { + descartes.refine_interval(i); + } + } + assert(Rational(-101,100)descartes.right_bound(0)); + assert(Rational(-1,1000)descartes.right_bound(1)); + assert(Rational(199,100)descartes.right_bound(2)); + + } + + { // Test for the backshear method + typedef Event_refinement Ev_refinement; + Ev_refinement event_refinement; + // A polynomial with 3 real roots + Poly_int1 f(19,21,-28,-22); + event_refinement.add(Algebraic_real(f,Rational(-2),Rational(-1))); + event_refinement.add(Algebraic_real(f,Rational(-8,10),Rational(-5,10))); + event_refinement.add(Algebraic_real(f,Rational(0),Rational(1))); + + std::stringstream ss("P[14(0,75449)(1,359917)(2,299972)(3,-1003302)(4,-1857360)(5,42392)(6,2091751)(7,1825115)(8,840268)(9,-840578)(10,-2327140)(11,-1130116)(12,705936)(13,746328)(14,170368)]"); + Poly_int1 g; + ss >> g; + // g = f^3*h, where h is a polynomial with 3 simple roots + // g := 75449+42392*x^5+359917*x-1003302*x^3+299972*x^2-1857360*x^4-1130116*x^11+840268*x^8-840578*x^9-2327140*x^10+705936*x^12+2091751*x^6+1825115*x^7+746328*x^13+170368*x^14 + + CGAL::internal::Backshear_descartes_tag t; + + // We expect 3 event roots, and 3 non-event roots + Bitstream_descartes descartes(t, g, 6, 3, event_refinement); + + try { + int k = descartes.degree_of_gcd(); + (void)k; + assert(false); + } catch (CGAL::internal::Virtual_method_exception ex) { + // Expected + } + try { + Poly_int1 sq_f = descartes.square_free_part(); + assert(false); + } catch (CGAL::internal::Virtual_method_exception ex) { + // Expected + } + + int n = descartes.number_of_real_roots(); + + assert(n==6); + + for(int i =0; iRational(1,10000)) + { + descartes.refine_interval(i); + } + } + + // The non-event roots are expected at -0.953, -0.685, 1.009. The events at + // -1.527, -0.635, 0.890 (approximate) + + assert(! descartes.is_certainly_simple_root(0)); + assert(descartes.is_certainly_multiple_root(0)); + assert(Rational(-1528,1000)descartes.right_bound(0)); + + assert(! descartes.is_certainly_multiple_root(1)); + assert(Rational(-954,1000)descartes.right_bound(1)); + + assert(! descartes.is_certainly_multiple_root(2)); + assert(Rational(-686,1000)descartes.right_bound(2)); + + assert(! descartes.is_certainly_simple_root(3)); + assert(descartes.is_certainly_multiple_root(3)); + assert(Rational(-636,1000)descartes.right_bound(3)); + + assert(! descartes.is_certainly_simple_root(4)); + assert(descartes.is_certainly_multiple_root(4)); + assert(Rational(889,1000)descartes.right_bound(4)); + + assert(! descartes.is_certainly_multiple_root(5)); + assert(Rational(1009,1000)descartes.right_bound(5)); + + } + { // Another test for the square free method with tree from outside + + // More complicated polynomials needed - change the traits class + + typedef CGAL::Algebraic_kernel_d_1 AK_1; + + typedef CGAL::internal::Bitstream_coefficient_kernel_at_alpha + Bitstream_coefficient_kernel; + + typedef CGAL::internal::Bitstream_descartes_rndl_tree_traits + Traits_2; + + typedef CGAL::internal::Bitstream_descartes Bitstream_descartes; + + typedef typename Bitstream_descartes::Bitstream_tree Bitstream_tree; + + std::stringstream ss("P[4(0,P[4(0,-87)(1,47)(2,43)(3,-88)(4,5)])(1,P[3(0,-90)(1,92)(2,-48)(3,13)])(2,P[2(0,-91)(1,53)(2,-10)])(3,P[1(0,-28)(1,-82)])(4,P[0(0,71)])]"); + + // In MAPLE: f:=-87+47*x-90*y+43*x^2+92*x*y-91*y^2-88*x^3-48*x^2*y+53*x*y^2-28*y^3+5*x^4+13*x^3*y-10*x^2*y^2-82*x*y^3+71*y^4; + + AK_1 ak_1; + + Poly_int2 f; + + ss >> f; + + Poly_int1 r = CGAL::internal::resultant(f,CGAL::differentiate(f)); + + Algebraic_real alpha(r,-2,-1); + + Bitstream_coefficient_kernel bitstream_coefficient_kernel(&ak_1,alpha); + + Traits_2 traits(bitstream_coefficient_kernel); + + CGAL::internal::M_k_descartes_tag mk; + + Bitstream_descartes m_k_descartes(mk,f,1,1,traits); + + assert(m_k_descartes.number_of_real_roots()==1); + + // The root is an "opening" x-extreme point + + // Refine the y-coordinate (just to make it harder...) + while(m_k_descartes.right_bound(0) - m_k_descartes.left_bound(0) + > Rational(1,100000)) { + m_k_descartes.refine_interval(0); + } + + // Get copy of the tree + Bitstream_tree tree = m_k_descartes.get_tree().make_unique(); + + + // Now, find a value inside the isolating interval of alpha, on the right + // of alpha + Rational right_bound = alpha.high(); + + while(alpha.high()==right_bound) { + alpha.refine(); + } + + Rational on_right = (alpha.high() + right_bound) / 2; + + Algebraic_real beta(on_right); + + Bitstream_coefficient_kernel new_bitstream_coefficient_kernel(&ak_1,beta); + + Traits_2 new_traits(new_bitstream_coefficient_kernel); + + CGAL::internal::Square_free_descartes_tag sq_free; + + Bitstream_descartes sq_free_descartes(sq_free, f, tree, new_traits); + + assert(sq_free_descartes.number_of_real_roots() == 2); + + for( int i = 0 ; i m_k_descartes.left_bound(0)); + assert(sq_free_descartes.right_bound(i) < m_k_descartes.right_bound(0)); + + } + + } +} + +} // namespace internal + +} //namespace CGAL diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_comparable.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_comparable.h new file mode 100644 index 00000000000..ca1a15b7310 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_comparable.h @@ -0,0 +1,231 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +/*! \file include/NiX/test_real_comparable.h + \brief provides test functions for the \c RealComparable concept of + number types. +*/ + +#ifndef CGAL_TEST_REAL_COMPARABLE_H +#define CGAL_TEST_REAL_COMPARABLE_H + +#include +#include +#include +/*#include +#include +#include */ +#include +#include +#include + + +namespace CGAL { + +namespace internal { + + template + class Test_to_double { + public: + void operator() (ToDouble to_double) { + typedef typename ToDouble::argument_type Argument_type; + typedef typename ToDouble::result_type Result_type; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same::value)); + assert(42.0 == to_double(NT(42))); + } + }; + + template + class Test_to_double { + public: + void operator() (::CGAL::Null_functor) { + CGAL_error_msg("To_double functor not implemented"); + } + }; + + template + class Test_to_Interval { + public: + void operator() (ToInterval to_Interval) { + typedef typename ToInterval::argument_type Argument_type; + typedef typename ToInterval::result_type Result_type; + BOOST_STATIC_ASSERT((::boost::is_same::value)); + BOOST_STATIC_ASSERT((::boost::is_same< typename Argument_type::Interval, Result_type>::value)); + + // TODO: NiX::in not available!? + //assert(NiX::in(42.0,to_Interval(NT(42)))); + assert(to_Interval(NT(42)).lower() > 41.99); + assert(to_Interval(NT(42)).upper() < 42.01); + + /* + NT notdouble = ipower(2,60); + notdouble = notdouble + NT(1); + Interval test = to_Interval(notdouble); + double lower = ipower(2.0,60); + double upper = ipower(2.0,53); + upper++; + upper *= ipower(2.0,7); + std::cout << lower << "," << upper << std::endl; + std::cout << test.lower() << "," << test.upper() << std::endl; + assert( (in(lower,test) == true) && (in(upper,test) == true) ); + */ + } + }; + + template + class Test_to_Interval { + public: + void operator() (::CGAL::Null_functor) { + CGAL_error_msg("To_Interval not implemented"); + // ok, nothing to test + } + }; + + +//! tests if \c NT is a model for the \c RealComparable concept +//! and terminates the program with an error message if not. +template +void test_real_comparable() { + typedef CGAL::Real_embeddable_traits Traits; + typedef typename Traits::Is_real_embeddable Is_real_comparable; + using ::CGAL::Tag_true; + BOOST_STATIC_ASSERT((::boost::is_same< Is_real_comparable, Tag_true>::value)); + typename Traits::Compare compare; + typename Traits::Sign sign; + typename Traits::Abs abs; + + NT a(-2); + NT b(1); + NT c(0); + assert( a < b); + assert( b > a); + assert( a <= b); + assert( b >= a); + assert( a <= a); + assert( a >= a); + assert( compare(a,b) == CGAL::SMALLER); + assert( compare(b,a) == CGAL::LARGER); + assert( compare(a,a) == CGAL::EQUAL); + assert( sign(a) == CGAL::NEGATIVE); + assert( sign(b) == CGAL::POSITIVE); + assert( sign(c) == CGAL::ZERO); + assert( sign(a) < sign(b)); + assert( sign(b) > sign(a)); + assert( sign(a) <= sign(b)); + assert( sign(b) >= sign(a)); + assert( sign(a) <= sign(a)); + assert( sign(a) >= sign(a)); + assert( sign(c) < sign(b)); + assert( sign(b) > sign(c)); + assert( sign(c) <= sign(b)); + assert( sign(b) >= sign(c)); + assert( sign(c) <= sign(c)); + assert( sign(c) >= sign(c)); + assert( sign(a) < sign(c)); + assert( sign(c) > sign(a)); + assert( sign(a) <= sign(c)); + assert( sign(c) >= sign(a)); + assert( abs(a) == NT(2)); + assert( abs(b) == NT(1)); + assert( abs(c) == NT(0)); + + // To_double -------------------------------------------------------------- + typename Traits::To_double to_double; + (void)to_double; + typename internal::Test_to_double ttd; + ttd(to_double); + + // To_Interval ------------------------------------------------------------ + typename Traits::To_Interval to_Interval; + (void)to_Interval; + typename internal::Test_to_Interval tti; + tti(to_Interval); + + // additional functions + assert(CGAL::sign(NT(-5))==CGAL::NEGATIVE); + assert(CGAL::abs(NT(-5))==NT(5)); + // TODO: NiX::in not available!? + //assert(NiX::in(5.0,NiX::to_Interval(NT(5)))); + assert(CGAL::compare(NT(-5),NT(6))==CGAL::SMALLER); + +} + +//! tests if \c NT says it is not a model for the \c RealComparable +//! concept and terminates the program with an error message if it +//! actually is. +template +void test_not_real_comparable() { + typedef CGAL::Real_embeddable_traits Traits; + typedef typename Traits::Is_real_embeddable Is_real_comparable; + using ::CGAL::Tag_false; + BOOST_STATIC_ASSERT((::boost::is_same< Is_real_comparable, Tag_false>::value)); +} + + +template +void test_rounded_log2_abs(NT zero, ::CGAL::Null_functor, CeilLog2Abs) { + typedef ::CGAL::Null_functor Nulltype; + BOOST_STATIC_ASSERT((::boost::is_same< CeilLog2Abs, Nulltype>::value)); +} + +template +void test_rounded_log2_abs(NT zero, FloorLog2Abs fl_log, CeilLog2Abs cl_log) { + typedef ::CGAL::Null_functor Null_functor; + BOOST_STATIC_ASSERT((!::boost::is_same< CeilLog2Abs, Null_functor>::value)); + + assert( fl_log(NT( 7)) == 2 ); + assert( cl_log(NT( 7)) == 3 ); + assert( fl_log(NT( 8)) == 3 ); + assert( cl_log(NT( 8)) == 3 ); + assert( fl_log(NT(-9)) == 3 ); + assert( cl_log(NT(-9)) == 4 ); + + // TODO: floor_log2_abs etc. not available yet!? + /*assert( NiX::floor_log2_abs(NT( 64)) == 6 ); + assert( NiX::ceil_log2_abs( NT( 64)) == 6 ); + assert( NiX::floor_log2_abs(NT(-126)) == 6 ); + assert( NiX::ceil_log2_abs( NT(-126)) == 7 );*/ +} + + +//! tests that \c Floor_log2_abs and \c Ceil_log2_abs are +//! \c both ::CGAL::Null_functor or both working properly +//! (This is independent of the \c RealComparable concept) +template +void test_rounded_log2_abs() { + + // TODO: floor_log2_abs etc. not available yet!? + /*typedef typename NiX::NT_traits::Floor_log2_abs F; + typedef typename NiX::NT_traits::Ceil_log2_abs C; + test_rounded_log2_abs(NT(0), F(), C());*/ +} + +} // namespace internal + + +} //namespace CGAL + +#endif // CGAL_TEST_REAL_COMPARABLE_H diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_root_isolator.h b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_root_isolator.h new file mode 100644 index 00000000000..e2a147ca5a9 --- /dev/null +++ b/Algebraic_kernel_d/test/Algebraic_kernel_d/include/CGAL/_test_real_root_isolator.h @@ -0,0 +1,250 @@ +// Copyright (c) 2006-2009 Max-Planck-Institute Saarbruecken (Germany). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL: svn+ssh://hemmer@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial.h $ +// $Id: Polynomial.h 47254 2008-12-06 21:18:27Z afabri $ +// +// +// Author(s) : Michael Hemmer +// +// ============================================================================ + +// TODO: The comments are all original EXACUS comments and aren't adapted. So +// they may be wrong now. + +#include +#include +#include + +#include +/*#include +#include */ + +#ifndef CGAL_TEST_REAL_ROOT_ISOLATOR_H +#define CGAL_TEST_REAL_ROOT_ISOLATOR_H + +namespace CGAL { + +namespace internal { + +template +int check_intervals_real_root_isolator( + const typename RealRootIsolator::Polynomial& P) { + + typedef RealRootIsolator Isolator; + typedef typename Isolator::Bound Bound; + + Isolator Isol(P); + int n = Isol.number_of_real_roots(); + for(int i=0; i(P); + assert( n == number_of_roots); + }{ + //std::cout << "Kameny 3\n"; + // from http://www-sop.inria.fr/saga/POL/BASE/1.unipol + + NT c = CGAL::ipower(NT(10),12); + Polynomial P(NT(-3),NT(0),c); + P = P*P; // (c^2x^2-3)^2 + Polynomial Q (NT(0),NT(1)); + Q = Q*Q; // x^2 + Q = Q*Q; // x^4 + Q = Q*Q; // x^8 + Q = Q*Polynomial(NT(0),c);//c^2x^9 + P = P+Q; + + assert(3 == internal::check_intervals_real_root_isolator(P)); + }{ + //std::cout << "Kameny 4\n"; + // from http://www-sop.inria.fr/saga/POL/BASE/1.unipol + + NT z(0); + NT a = CGAL::ipower(NT(10),24); // a = 10^{24} + + Polynomial P(z,NT(4),CGAL::ipower(a,2),z,z,2*a,z,z,NT(1)); + // x^8+2*10^{24}*x^5+10^{48}*x^2+4*x + P = P * Polynomial(z,z,z,z,z,z,NT(1)); + // x^{14}+2*10^{24}*x^{11}+10^{48}*x^8+4*x^7 + P = P + Polynomial(NT(4),z,z,z,-4*a); + // x^{14}+2*10^{24}*x^{11}+10^{48}*x^8+4*x^7-4*10^{24}*X^4+4 + + Isolator isol(P); + assert( 4 == internal::check_intervals_real_root_isolator(P)); + }{ + //std::cout << "Polynomial with large and small clustered roots\n"; + // from http://www-sop.inria.fr/saga/POL/BASE/1.unipol + // there seems to be some error or misunderstanding + + NT z(0); + NT a = CGAL::ipower(NT(10),20); // a = 10^{20} + + Polynomial P(z,z,z,z,z,z,z,z,NT(1)); //x^8 + P = P*Polynomial(z,z,z,z,NT(1)); // x^{12} + Polynomial R(NT(-1),a); // ax-1 + R = R*R; + R = R*R; // (ax-1)^4 + P = P-R; // x^{12} - (ax-1)^4 + + assert( 4 == internal::check_intervals_real_root_isolator(P)); + } + +} + +} //namespace internal + +} //namespace CGAL + +#endif // CGAL_TEST_REAL_ROOT_ISOLATOR_H diff --git a/Algebraic_kernel_d/test/Algebraic_kernel_d/io_test.cpp b/Algebraic_kernel_d/test/Algebraic_kernel_d/io_test.cpp deleted file mode 100644 index 02244480106..00000000000 --- a/Algebraic_kernel_d/test/Algebraic_kernel_d/io_test.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2009,2010 Inria Lorraine (France). All rights reserved. -// -// This file is part of CGAL (www.cgal.org); you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; version 2.1 of the License. -// See the file LICENSE.LGPL distributed with CGAL. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// -// Author: Luis Peņaranda - -#include - -#if defined(CGAL_USE_GMP) && defined(CGAL_USE_MPFI) && defined(CGAL_USE_RS) - -#include - -typedef CGAL::Algebraic_kernel_rs_gmpz_1 AK; -typedef AK::Polynomial_1 Polynomial_1; -typedef AK::Algebraic_real_1 Algebraic_real_1; -typedef AK::Coefficient Coefficient; -typedef AK::Bound Bound; - -#define CGAL_TEST_ALGEBRAIC_REAL_IO(_f) \ - CGAL::set_ascii_mode(ss); \ - CGAL_TEST_ALGEBRAIC_REAL_IO_MODE(_f) \ - CGAL::set_pretty_mode(ss); \ - CGAL_TEST_ALGEBRAIC_REAL_IO_MODE(_f) - -#define CGAL_TEST_ALGEBRAIC_REAL_IO_MODE(_f) \ - alg1=_f; \ - ss<>CGAL::iformat(alg2); \ - assert(alg1==alg2); - -int main(){ - AK ak; // an object of Algebraic_kernel_d_1_RS_Gmpz - AK::Construct_algebraic_real_1 construct_algreal_1 = - ak.construct_algebraic_real_1_object(); - - Algebraic_real_1 alg1,alg2; - std::stringstream ss; - - // test construction from int, Coefficient and Bound - CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(int(2))) - CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(Coefficient(2))) - CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(Bound(2))) - - // construction by index - Polynomial_1 x = CGAL::shift(AK::Polynomial_1(1),1); // the monom x - CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(x*x-2,1)) - - // construction by isolating interval - CGAL_TEST_ALGEBRAIC_REAL_IO(construct_algreal_1(x*x-2,Bound(0),Bound(2))) - - return 0; -} -#else -int main(){ - return 0; -} -#endif