BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Polynomial/prs_resultant.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines