BWAPI
|
00001 // Copyright (c) 2008 Max-Planck-Institute Saarbruecken (Germany) 00002 // 00003 // This file is part of CGAL (www.cgal.org); you can redistribute it and/or 00004 // modify it under the terms of the GNU Lesser General Public License as 00005 // published by the Free Software Foundation; version 2.1 of the License. 00006 // See the file LICENSE.LGPL distributed with CGAL. 00007 // 00008 // Licensees holding a valid commercial license may use this file in 00009 // accordance with the commercial license agreement provided with the software. 00010 // 00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00013 // 00014 // $URL: svn+ssh://afabri@scm.gforge.inria.fr/svn/cgal/trunk/Polynomial/include/CGAL/Polynomial/polynomial_functions.h $ 00015 // $Id: polynomial_functions.h 46402 2008-10-21 16:20:05Z eric $ 00016 // 00017 // 00018 // Author(s) : Michael Hemmer 00019 // 00020 // ============================================================================ 00021 00022 // TODO: The comments are all original EXACUS comments and aren't adapted. So 00023 // they may be wrong now. 00024 00025 #ifndef CGAL_POLYNOMIAL_BEZOUT_MATRIX_H 00026 #define CGAL_POLYNOMIAL_BEZOUT_MATRIX_H 00027 00028 #include <algorithm> 00029 00030 #include <CGAL/basic.h> 00031 #include <CGAL/Polynomial_traits_d.h> 00032 #include <CGAL/Polynomial/determinant.h> 00033 00034 #include <vector> 00035 //#include <CGAL/Linear_algebraHd.h> 00036 00037 00038 //#include <CGAL/Linear_algebra.h> 00039 //#include <CGAL/number_type_utils.h> 00040 00041 CGAL_BEGIN_NAMESPACE 00042 00043 namespace CGALi { 00044 00074 template <typename Polynomial_traits_d> 00075 typename CGALi::Simple_matrix< typename Polynomial_traits_d::Coefficient_type > 00076 hybrid_bezout_matrix(typename Polynomial_traits_d::Polynomial_d f, 00077 typename Polynomial_traits_d::Polynomial_d g, 00078 int sub = 0) 00079 { 00080 00081 typedef typename Polynomial_traits_d::Polynomial_d Polynomial; 00082 typedef typename Polynomial_traits_d::Coefficient_type NT; 00083 typename Polynomial_traits_d::Degree degree; 00084 typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero; 00085 typename Polynomial_traits_d::Get_coefficient coeff; 00086 00087 typedef typename CGALi::Simple_matrix<NT> Matrix; 00088 00089 int n = degree(f); 00090 int m = degree(g); 00091 CGAL_precondition((n >= 0) && !is_zero(f)); 00092 CGAL_precondition((m >= 0) && !is_zero(g)); 00093 CGAL_precondition(n > sub || sub == 0); 00094 CGAL_precondition(m > sub || sub == 0); 00095 00096 int i, j, k, l; 00097 NT s; 00098 00099 if (m > n) { 00100 std::swap(f, g); 00101 std::swap(m, n); 00102 } 00103 00104 Matrix B(n-sub); 00105 00106 for (i = 1+sub; i <= m; i++) { 00107 for (j = 1; j <= n-sub; j++) { 00108 s = NT(0); 00109 for (k = 0; k <= i-1; k++) { 00110 l = n+i-j-k; 00111 if ((l <= n) and (l >= n-(m-i))) { 00112 s += coeff(f,l) * coeff(g,k); 00113 } 00114 } 00115 for (k = 0; k <= n-(m-i+1); k++) { 00116 l = n+i-j-k; 00117 if ((l <= m) and (l >= i)) { 00118 s -= coeff(f,k) * coeff(g,l); 00119 } 00120 } 00121 B[i-sub-1][j-1] = s; 00122 } 00123 } 00124 for (i = std::max(m+1, 1+sub); i <= n; i++) { 00125 for (j = i-m; j <= std::min(i, n-sub); j++) { 00126 B[i-sub-1][j-1] = coeff(g,i-j); 00127 } 00128 } 00129 00130 return B; // g++ 3.1+ has NRVO, so this should not be too expensive 00131 } 00132 00144 template <typename Polynomial_traits_d> 00145 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type> 00146 symmetric_bezout_matrix 00147 (typename Polynomial_traits_d::Polynomial_d f, 00148 typename Polynomial_traits_d::Polynomial_d g, 00149 int sub = 0) 00150 { 00151 00152 00153 00154 // Note: The algorithm is taken from: 00155 // Chionh, Zhang, Goldman: Fast Computation of the Bezout and Dixon Resultant 00156 // Matrices. J.Symbolic Computation 33, 13-29 (2002) 00157 00158 typedef typename Polynomial_traits_d::Polynomial_d Polynomial; 00159 typedef typename Polynomial_traits_d::Coefficient_type NT; 00160 typename Polynomial_traits_d::Degree degree; 00161 typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero; 00162 typename Polynomial_traits_d::Get_coefficient coeff; 00163 00164 typedef typename CGALi::Simple_matrix<NT> Matrix; 00165 00166 int n = degree(f); 00167 int m = degree(g); 00168 CGAL_precondition((n >= 0) && !is_zero(f)); 00169 CGAL_precondition((m >= 0) && !is_zero(g)); 00170 00171 int i,j,stop; 00172 00173 NT sum1,sum2; 00174 00175 if (m > n) { 00176 std::swap(f, g); 00177 std::swap(m, n); 00178 } 00179 00180 CGAL_precondition((sub>=0) && sub < n); 00181 00182 int d = n - sub; 00183 00184 Matrix B(d); 00185 00186 // 1st step: Initialisation 00187 for(i=0;i<d;i++) { 00188 for(j=i;j<d;j++) { 00189 sum1 = ((j+sub)+1>m) ? NT(0) : -coeff(f,i+sub)*coeff(g,(j+sub)+1); 00190 sum2 = ((i+sub)>m) ? NT(0) : coeff(g,i+sub)*coeff(f,(j+sub)+1); 00191 B[i][j]=sum1+sum2; 00192 } 00193 } 00194 00195 // 2nd Step: Recursion adding 00196 00197 // First, set up the first line correctly 00198 for(i=0;i<d-1;i++) { 00199 stop = (sub<d-1-i) ? sub : d-i-1; 00200 for(j=1;j<=stop;j++) { 00201 sum1 = ((i+sub+j)+1>m) ? NT(0) 00202 : -coeff(f,sub-j)*coeff(g,(i+sub+j)+1); 00203 sum2 = ((sub-j)>m) ? NT(0) 00204 : coeff(g,sub-j)*coeff(f,(i+sub+j)+1); 00205 00206 B[0][i]+=sum1+sum2; 00207 } 00208 } 00209 // Now, compute the rest 00210 for(i=1;i<d-1;i++) { 00211 for(j=i;j<d-1;j++) { 00212 B[i][j]+=B[i-1][j+1]; 00213 } 00214 } 00215 00216 00217 //3rd Step: Exploit symmetry 00218 for(i=1;i<d;i++) { 00219 for(j=0;j<i;j++) { 00220 B[i][j]=B[j][i]; 00221 } 00222 } 00223 00224 return B; 00225 } 00226 00227 00228 00244 template <class Polynomial_traits_d> 00245 typename Polynomial_traits_d::Coefficient_type hybrid_bezout_subresultant( 00246 typename Polynomial_traits_d::Polynomial_d f, 00247 typename Polynomial_traits_d::Polynomial_d g, 00248 int sub = 0 00249 ) { 00250 00251 typedef typename Polynomial_traits_d::Polynomial_d Polynomial; 00252 typedef typename Polynomial_traits_d::Coefficient_type NT; 00253 typename Polynomial_traits_d::Degree degree; 00254 typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero; 00255 00256 typedef CGALi::Simple_matrix<NT> Matrix; 00257 00258 CGAL_precondition((degree(f) >= 0)); 00259 CGAL_precondition((degree(g) >= 0)); 00260 00261 if (is_zero(f) || is_zero(g)) return NT(0); 00262 00263 Matrix S = hybrid_bezout_matrix<Polynomial_traits_d>(f, g, sub); 00264 CGAL_assertion(S.row_dimension() == S.column_dimension()); 00265 if (S.row_dimension() == 0) { 00266 return NT(1); 00267 } else { 00268 return CGALi::determinant(S); 00269 } 00270 } 00271 00272 // Transforms the minors of the symmetric bezout matrix into the subresultant. 00273 // Needs the appropriate power of the leading coedfficient of f and the 00274 // degrees of f and g 00275 template<class InputIterator,class OutputIterator,class NT> 00276 void symmetric_minors_to_subresultants(InputIterator in, 00277 OutputIterator out, 00278 NT divisor, 00279 int n, 00280 int m, 00281 bool swapped) { 00282 00283 typename CGAL::Algebraic_structure_traits<NT>::Integral_division idiv; 00284 00285 for(int i=0;i<m;i++) { 00286 bool negate = ((n-m+i+1) & 2)>>1; // (n-m+i+1)==2 or 3 mod 4 00287 negate=negate ^ (swapped & ((n-m+i+1)*(i+1))); 00288 //...XOR (swapped AND (n-m+i+1)* (i+1) is odd) 00289 00290 *out = idiv(*in, negate ? -divisor : divisor); 00291 in++; 00292 out++; 00293 } 00294 } 00295 00296 00308 template<class Polynomial_traits_d,class OutputIterator> 00309 OutputIterator symmetric_bezout_subresultants( 00310 typename Polynomial_traits_d::Polynomial_d f, 00311 typename Polynomial_traits_d::Polynomial_d g, 00312 OutputIterator sres) 00313 { 00314 00315 typedef typename Polynomial_traits_d::Polynomial_d Polynomial; 00316 typedef typename Polynomial_traits_d::Coefficient_type NT; 00317 typename Polynomial_traits_d::Degree degree; 00318 typename CGAL::Algebraic_structure_traits<Polynomial>::Is_zero is_zero; 00319 typename Polynomial_traits_d::Leading_coefficient lcoeff; 00320 00321 typedef typename CGALi::Simple_matrix<NT> Matrix; 00322 00323 int n = degree(f); 00324 int m = degree(g); 00325 00326 bool swapped=false; 00327 00328 if(n < m) { 00329 std::swap(f,g); 00330 std::swap(n,m); 00331 swapped=true; 00332 00333 } 00334 00335 Matrix B = symmetric_bezout_matrix<Polynomial_traits_d>(f,g); 00336 00337 // Compute a_0^{n-m} 00338 00339 NT divisor=ipower(lcoeff(f),n-m); 00340 00341 std::vector<NT> minors; 00342 minors_berkowitz(B,std::back_inserter(minors),n,m); 00343 CGAL::CGALi::symmetric_minors_to_subresultants(minors.begin(),sres, 00344 divisor,n,m,swapped); 00345 00346 return sres; 00347 } 00348 00349 /* 00350 * Return a modified version of the hybrid bezout matrix such that the minors 00351 * from the last k rows and columns give the subresultants 00352 */ 00353 template<class Polynomial_traits_d> 00354 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type> 00355 modified_hybrid_bezout_matrix 00356 (typename Polynomial_traits_d::Polynomial_d f, 00357 typename Polynomial_traits_d::Polynomial_d g) { 00358 00359 typedef typename Polynomial_traits_d::Coefficient_type NT; 00360 00361 typedef typename CGALi::Simple_matrix<NT> Matrix; 00362 00363 typename Polynomial_traits_d::Degree degree; 00364 00365 int n = degree(f); 00366 int m = degree(g); 00367 00368 int i,j; 00369 00370 bool negate, swapped=false; 00371 00372 if(n < m) { 00373 std::swap(f,g); //(*) 00374 std::swap(n,m); 00375 swapped=true; 00376 } 00377 00378 Matrix B = CGAL::CGALi::hybrid_bezout_matrix<Polynomial_traits_d>(f,g); 00379 00380 00381 // swap columns 00382 i=0; 00383 while(i<n-i-1) { 00384 B.swap_columns(i,n-i-1); // (**) 00385 i++; 00386 } 00387 for(i=0;i<n;i++) { 00388 negate=(n-i-1) & 1; // Negate every second column because of (**) 00389 negate=negate ^ (swapped & (n-m+1)); // XOR negate everything because of(*) 00390 if(negate) { 00391 for(j=0;j<n;j++) { 00392 B[j][i] *= -1; 00393 } 00394 } 00395 } 00396 return B; 00397 } 00398 00410 template<class Polynomial_traits_d,class OutputIterator> 00411 OutputIterator hybrid_bezout_subresultants( 00412 typename Polynomial_traits_d::Polynomial_d f, 00413 typename Polynomial_traits_d::Polynomial_d g, 00414 OutputIterator sres) 00415 { 00416 00417 typedef typename Polynomial_traits_d::Coefficient_type NT; 00418 typename Polynomial_traits_d::Degree degree; 00419 00420 typedef typename CGALi::Simple_matrix<NT> Matrix; 00421 00422 int n = degree(f); 00423 int m = degree(g); 00424 00425 Matrix B = CGAL::CGALi::modified_hybrid_bezout_matrix<Polynomial_traits_d> 00426 (f,g); 00427 00428 if(n<m) { 00429 std::swap(n,m); 00430 } 00431 00432 return minors_berkowitz(B,sres,n,m); 00433 } 00434 00435 00436 // Swap entry A_ij with A_(n-i)(n-j) for square matrix A of dimension n 00437 template<class NT> 00438 void swap_entries(typename CGALi::Simple_matrix<NT> & A) { 00439 CGAL_precondition(A.row_dimension()==A.column_dimension()); 00440 int n = A.row_dimension(); 00441 int i=0; 00442 while(i<n-i-1) { 00443 A.swap_rows(i,n-i-1); 00444 A.swap_columns(i,n-i-1); 00445 i++; 00446 } 00447 } 00448 00449 // Produce S-matrix with the given matrix and integers. 00450 template<class NT,class InputIterator> 00451 typename CGALi::Simple_matrix<NT> s_matrix( 00452 const typename CGALi::Simple_matrix<NT>& B, 00453 InputIterator num,int size) 00454 { 00455 typename CGALi::Simple_matrix<NT> S(size); 00456 CGAL_precondition_code(int n = B.row_dimension();) 00457 CGAL_precondition(n==(int)B.column_dimension()); 00458 int curr_num; 00459 bool negate; 00460 00461 for(int i=0;i<size;i++) { 00462 curr_num=(*num); 00463 num++; 00464 negate = curr_num<0; 00465 if(curr_num<0) { 00466 curr_num=-curr_num; 00467 } 00468 for(int j=0;j<size;j++) { 00469 00470 S[j][i]=negate ? -B[j][curr_num-1] : B[j][curr_num-1]; 00471 00472 } 00473 } 00474 return S; 00475 } 00476 00477 // Produces the integer sequence for the S-matrix, where c is the first entry 00478 // of the sequence, s the number of desired diagonals and n the dimension 00479 // of the base matrix 00480 template<class OutputIterator> 00481 OutputIterator s_matrix_integer_sequence(OutputIterator it, 00482 int c,int s,int n) { 00483 CGAL_precondition(0<s); 00484 CGAL_precondition(s<=n); 00485 // c is interpreted modulo s wrt to the representants {1,..,s} 00486 c=c%s; 00487 if(c==0) { 00488 c=s; 00489 } 00490 00491 int i, p=0, q=c; 00492 while(q<=n) { 00493 *it = q; 00494 it++; 00495 for(i=p+1;i<q;i++) { 00496 *it = -i; 00497 it++; 00498 } 00499 p = q; 00500 q = q+s; 00501 } 00502 return it; 00503 } 00504 00521 template<typename Polynomial_traits_d> 00522 typename CGALi::Simple_matrix<typename Polynomial_traits_d::Coefficient_type> 00523 polynomial_subresultant_matrix(typename Polynomial_traits_d::Polynomial_d f, 00524 typename Polynomial_traits_d::Polynomial_d g, 00525 int d=0) { 00526 00527 typedef typename Polynomial_traits_d::Coefficient_type NT; 00528 typename Polynomial_traits_d::Degree degree; 00529 typename Polynomial_traits_d::Leading_coefficient lcoeff; 00530 00531 int n = degree(f); 00532 int m = degree(g); 00533 00534 CGAL_precondition(n>=0); 00535 CGAL_precondition(m>=0); 00536 CGAL_precondition(d>=0); 00537 00538 typedef CGALi::Simple_matrix<NT> Matrix; 00539 00540 bool swapped=false; 00541 00542 if(n < m) { 00543 std::swap(f,g); 00544 std::swap(n,m); 00545 swapped=true; 00546 } 00547 00548 if(d==0) { 00549 d=m; 00550 }; 00551 00552 00553 Matrix B = CGAL::CGALi::symmetric_bezout_matrix<Polynomial_traits_d>(f,g); 00554 00555 // For easier notation, we swap all entries: 00556 CGALi::swap_entries<NT>(B); 00557 00558 // Compute the S-matrices and collect the minors 00559 std::vector<Matrix> s_mat(m); 00560 std::vector<std::vector<NT> > coeffs(d); 00561 for(int i = 1; i<=d;i++) { 00562 std::vector<int> intseq; 00563 CGALi::s_matrix_integer_sequence(std::back_inserter(intseq),i,d,n); 00564 00565 Matrix S = CGALi::s_matrix<NT>(B,intseq.begin(),(int)intseq.size()); 00566 CGALi::swap_entries<NT>(S); 00567 //std::cout << S << std::endl; 00568 int Sdim = S.row_dimension(); 00569 int number_of_minors=(Sdim < m) ? Sdim : Sdim; 00570 00571 CGALi::minors_berkowitz(S,std::back_inserter(coeffs[i-1]), 00572 Sdim,number_of_minors); 00573 00574 } 00575 00576 // Now, rearrange the minors in the matrix 00577 00578 Matrix Ret(m,m,NT(0)); 00579 00580 for(int i = 0; i < d; i++) { 00581 for(int j = 0;j < m-i ; j++) { 00582 int s_index=(n-m+j+i+1)%d; 00583 if(s_index==0) { 00584 s_index=d; 00585 } 00586 s_index--; 00587 Ret[j][j+i]=coeffs[s_index][n-m+j]; 00588 00589 } 00590 } 00591 00592 typename CGAL::Algebraic_structure_traits<NT>::Integral_division idiv; 00593 00594 NT divisor = ipower(lcoeff(f),n-m); 00595 00596 // Divide through the divisor and set the correct sign 00597 for(int i=0;i<m;i++) { 00598 for(int j = i;j<m;j++) { 00599 bool negate = ((n-m+i+1) & 2)>>1; // (n-m+i+1)==2 or 3 mod 4 00600 negate=negate ^ (swapped & ((n-m+i+1)*(i+1))); 00601 //...XOR (swapped AND (n-m+i+1)* (i+1) is odd) 00602 Ret[i][j] = idiv(Ret[i][j], negate ? -divisor : divisor); 00603 } 00604 } 00605 00606 return Ret; 00607 } 00608 00609 } 00610 00611 CGAL_END_NAMESPACE 00612 00613 00614 00615 #endif // CGAL_POLYNOMIAL_BEZOUT_MATRIX_H 00616 // EOF