BWAPI
|
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany). 00002 // All rights reserved. 00003 // 00004 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License as 00006 // published by the Free Software Foundation; version 2.1 of the License. 00007 // See the file LICENSE.LGPL distributed with CGAL. 00008 // 00009 // Licensees holding a valid commercial license may use this file in 00010 // accordance with the commercial license agreement provided with the software. 00011 // 00012 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00013 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00014 00015 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Polynomial/include/CGAL/Polynomial/prs_resultant.h $ 00016 // $Id: prs_resultant.h 47254 2008-12-06 21:18:27Z afabri $ 00017 // 00018 // 00019 // Author(s) : Arno Eigenwillig <arno@mpi-inf.mpg.de> 00020 // 00021 // ============================================================================ 00022 00023 // TODO: The comments are all original EXACUS comments and aren't adapted. So 00024 // they may be wrong now. 00025 00031 #include <CGAL/basic.h> 00032 #include <CGAL/Polynomial.h> 00033 00034 #include <CGAL/ipower.h> 00035 #include <CGAL/Polynomial/hgdelta_update.h> 00036 00037 #ifndef CGAL_POLYNOMIAL_PRS_RESULTANT_H 00038 #define CGAL_POLYNOMIAL_PRS_RESULTANT_H 00039 00040 CGAL_BEGIN_NAMESPACE 00041 00042 template <class NT> inline 00043 NT prs_resultant_integral_domain(Polynomial<NT> A, Polynomial<NT> B) { 00044 // implemented using the subresultant algorithm for resultant computation 00045 // see [Cohen, 1993], algorithm 3.3.7 00046 00047 if (A.is_zero() || B.is_zero()) return NT(0); 00048 00049 int signflip; 00050 if (A.degree() < B.degree()) { 00051 Polynomial<NT> T = A; A = B; B = T; 00052 signflip = (A.degree() & B.degree() & 1); 00053 } else { 00054 signflip = 0; 00055 } 00056 00057 typedef CGAL::Scalar_factor_traits<Polynomial<NT> > SFT; 00058 typedef typename SFT::Scalar Scalar; 00059 typename SFT::Scalar_factor scalar_factor; 00060 typename CGAL::Coercion_traits<Scalar, NT>::Cast cast_scalar_nt; 00061 00062 Scalar a = scalar_factor(A), b = scalar_factor(B); 00063 NT g(1), h(1); 00064 NT t = cast_scalar_nt (CGAL::ipower(a, B.degree()) * CGAL::ipower(b, A.degree())); 00065 00066 Polynomial<NT> Q, R; NT d; 00067 int delta; 00068 00069 A /= cast_scalar_nt(a); B /= cast_scalar_nt(b); 00070 do { 00071 signflip ^= (A.degree() & B.degree() & 1); 00072 Polynomial<NT>::pseudo_division(A, B, Q, R, d); 00073 delta = A.degree() - B.degree(); 00074 typedef typename CGAL::Algebraic_structure_traits<NT>::Is_exact 00075 Is_exact; 00076 CGAL_expensive_assertion(CGAL::check_tag(Is_exact()) == false 00077 || d == CGAL::ipower(B.lcoeff(), delta + 1) ); 00078 A = B; 00079 B = R / (g * CGAL::ipower(h, delta)); 00080 g = A.lcoeff(); 00081 // h = h^(1-delta) * g^delta 00082 CGALi::hgdelta_update(h, g, delta); 00083 } while (B.degree() > 0); 00084 // h = h^(1-deg(A)) * lcoeff(B)^deg(A) 00085 delta = A.degree(); 00086 g = B.lcoeff(); 00087 CGALi::hgdelta_update(h, g, delta); 00088 h = signflip ? -(t*h) : t*h; 00089 typename Algebraic_structure_traits<NT>::Simplify simplify; 00090 simplify(h); 00091 return h; 00092 } 00093 00094 00095 00096 template <class NT> inline 00097 NT prs_resultant_ufd(Polynomial<NT> A, Polynomial<NT> B) { 00098 // implemented using the subresultant algorithm for resultant computation 00099 // see [Cohen, 1993], algorithm 3.3.7 00100 00101 if (A.is_zero() || B.is_zero()) return NT(0); 00102 00103 int signflip; 00104 if (A.degree() < B.degree()) { 00105 Polynomial<NT> T = A; A = B; B = T; 00106 signflip = (A.degree() & B.degree() & 1); 00107 } else { 00108 signflip = 0; 00109 } 00110 00111 NT a = A.content(), b = B.content(); 00112 NT g(1), h(1), t = CGAL::ipower(a, B.degree()) * CGAL::ipower(b, A.degree()); 00113 Polynomial<NT> Q, R; NT d; 00114 int delta; 00115 00116 A /= a; B /= b; 00117 do { 00118 signflip ^= (A.degree() & B.degree() & 1); 00119 Polynomial<NT>::pseudo_division(A, B, Q, R, d); 00120 delta = A.degree() - B.degree(); 00121 typedef typename CGAL::Algebraic_structure_traits<NT>::Is_exact 00122 Is_exact; 00123 CGAL_expensive_assertion(CGAL::check_tag(Is_exact()) == false 00124 || d == CGAL::ipower(B.lcoeff(), delta + 1) ); 00125 A = B; 00126 B = R / (g * CGAL::ipower(h, delta)); 00127 g = A.lcoeff(); 00128 // h = h^(1-delta) * g^delta 00129 CGALi::hgdelta_update(h, g, delta); 00130 } while (B.degree() > 0); 00131 // h = h^(1-deg(A)) * lcoeff(B)^deg(A) 00132 delta = A.degree(); 00133 g = B.lcoeff(); 00134 CGALi::hgdelta_update(h, g, delta); 00135 h = signflip ? -(t*h) : t*h; 00136 typename Algebraic_structure_traits<NT>::Simplify simplify; 00137 simplify(h); 00138 return h; 00139 } 00140 00141 template <class NT> inline 00142 NT prs_resultant_field(Polynomial<NT> A, Polynomial<NT> B) { 00143 // implemented using the Euclidean algorithm for resultant computation 00144 // compare [Cox et al, 1997], p.157 00145 00146 if (A.is_zero() || B.is_zero()) return NT(0); 00147 00148 int signflip; 00149 if (A.degree() < B.degree()) { 00150 Polynomial<NT> T = A; A = B; B = T; 00151 signflip = (A.degree() & B.degree() & 1); 00152 } else { 00153 signflip = 0; 00154 } 00155 00156 NT res(1); 00157 Polynomial<NT> Q, R; 00158 while (B.degree() > 0) { 00159 signflip ^= (A.degree() & B.degree() & 1); 00160 Polynomial<NT>::euclidean_division(A, B, Q, R); 00161 res *= CGAL::ipower(B.lcoeff(), A.degree() - R.degree()); 00162 A = B; 00163 B = R; 00164 } 00165 res = CGAL::ipower(B.lcoeff(), A.degree()) * (signflip ? -res : res); 00166 typename Algebraic_structure_traits<NT>::Simplify simplify; 00167 simplify(res); 00168 return res; 00169 } 00170 00171 // definition follows below 00172 template <class NT> inline 00173 NT prs_resultant_decompose(Polynomial<NT> A, Polynomial<NT> B); 00174 00175 namespace INTERN_PRS_RESULTANT { 00176 template <class NT> inline 00177 NT prs_resultant_(Polynomial<NT> A, Polynomial<NT> B, ::CGAL::Tag_false) { 00178 return prs_resultant_field(A, B); 00179 } 00180 00181 template <class NT> inline 00182 NT prs_resultant_(Polynomial<NT> A, Polynomial<NT> B, ::CGAL::Tag_true) { 00183 return prs_resultant_decompose(A, B); 00184 } 00185 00186 template <class NT> inline 00187 NT prs_resultant_(Polynomial<NT> A, Polynomial<NT> B, Field_tag) { 00188 typedef typename Fraction_traits<NT>::Is_fraction Is_decomposable; 00189 return prs_resultant_(A, B, Is_decomposable()); 00190 } 00191 00192 template <class NT> inline 00193 NT prs_resultant_(Polynomial<NT> A, Polynomial<NT> B, Unique_factorization_domain_tag) { 00194 return prs_resultant_ufd(A, B); 00195 } 00196 } // namespace CGALi 00197 00198 template <class NT> inline 00199 NT prs_resultant_decompose(Polynomial<NT> A, Polynomial<NT> B){ 00200 typedef Polynomial<NT> POLY; 00201 typedef typename Fraction_traits<POLY>::Numerator_type INTPOLY; 00202 typedef typename Fraction_traits<POLY>::Denominator_type DENOM; 00203 typename Fraction_traits<POLY>::Decompose decompose; 00204 typedef typename INTPOLY::NT RES; 00205 00206 DENOM a, b; 00207 A.simplify_coefficients(); 00208 B.simplify_coefficients(); 00209 INTPOLY A0; decompose(A,A0,a); 00210 INTPOLY B0; decompose(B,B0,b); 00211 DENOM c = CGAL::ipower(a, B.degree()) * CGAL::ipower(b, A.degree()); 00212 typedef typename Algebraic_structure_traits<RES>::Algebraic_category Algebraic_category; 00213 RES res0 = INTERN_PRS_RESULTANT::prs_resultant_(A0, B0, Algebraic_category()); 00214 typename Fraction_traits<NT>::Compose comp_frac; 00215 NT res = comp_frac(res0, c); 00216 typename Algebraic_structure_traits<NT>::Simplify simplify; 00217 simplify(res); 00218 return res; 00219 } 00220 00221 00250 template <class NT> inline 00251 NT prs_resultant(Polynomial<NT> A, Polynomial<NT> B) { 00252 typedef typename Algebraic_structure_traits<NT>::Algebraic_category 00253 Algebraic_category; 00254 return INTERN_PRS_RESULTANT::prs_resultant_(A, B, Algebraic_category()); 00255 } 00256 00257 CGAL_END_NAMESPACE 00258 00259 #endif // CGAL_POLYNOMIAL_PRS_RESULTANT_H 00260 00261 // EOF