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 // TODO: The comments are all original EXACUS comments and aren't adapted. So 00022 // they may be wrong now. 00023 00024 #ifndef CGAL_POLYNOMIAL_DETERMINANT_H 00025 #define CGAL_POLYNOMIAL_DETERMINANT_H 00026 00027 CGAL_BEGIN_NAMESPACE ; 00028 00029 #include <CGAL/basic.h> 00030 00031 namespace CGALi { 00032 00033 // TODO: Own simple matrix and vector to avoid importing the whole matrix stuff 00034 // from EXACUS. 00035 00036 // This is to be replaced by a corresponding CGAL Matrix and Vector. 00037 template< class Coeff > 00038 struct Simple_matrix 00039 : public std::vector< std::vector< Coeff > > { 00040 00041 typedef Coeff NT; 00042 00043 Simple_matrix() { 00044 } 00045 00046 Simple_matrix( int m ) { 00047 initialize( m, m, Coeff(0) ); 00048 } 00049 00050 Simple_matrix( int m, int n, Coeff x = Coeff(0) ) { 00051 initialize( m, n, x ); 00052 } 00053 00054 void swap_rows(int i, int j) { 00055 std::vector< Coeff > swap = this->operator[](i); 00056 this->operator[](i) = this->operator[](j); 00057 this->operator[](j) = swap; 00058 } 00059 00060 void swap_columns(int i, int j) { 00061 for(int k = 0; k < m; k++) { 00062 Coeff swap = this->operator[](k).operator[](i); 00063 this->operator[](k).operator[](i) 00064 = this->operator[](k).operator[](j); 00065 this->operator[](k).operator[](j) = swap; 00066 } 00067 } 00068 00069 int row_dimension() const { return m; } 00070 int column_dimension() const { return n; } 00071 00072 private: 00073 00074 void initialize( int m, int n, Coeff x ) { 00075 this->reserve( m ); 00076 this->m = m; 00077 this->n = n; 00078 for( int i = 0; i < m; ++i ) { 00079 this->push_back( std::vector< Coeff >() ); 00080 this->operator[](i).reserve(n); 00081 for( int j = 0; j < n; ++j ) { 00082 this->operator[](i).push_back( x ); 00083 } 00084 } 00085 } 00086 00087 int m,n; 00088 }; 00089 00090 template< class Coeff > 00091 struct Simple_vector 00092 : public std::vector< Coeff > { 00093 Simple_vector( int m ) { 00094 this->reserve( m ); 00095 for( int i = 0; i < m; ++i ) 00096 this->push_back( Coeff(0) ); 00097 } 00098 00099 Coeff operator*( const Simple_vector<Coeff>& v2 ) const { 00100 CGAL_precondition( v2.size() == this->size() ); 00101 Coeff result(0); 00102 00103 for( unsigned i = 0; i < this->size(); ++i ) 00104 result += ( this->operator[](i) * v2[i] ); 00105 00106 return result; 00107 } 00108 }; 00109 00110 // call for auto-selection of best routine (exact NT) 00111 template <class M> inline 00112 typename M::NT determinant (const M& matrix, 00113 int n, 00114 Integral_domain_without_division_tag, 00115 ::CGAL::Boolean_tag<true> ) 00116 { 00117 return det_berkowitz(matrix, n); 00118 } 00119 00120 // call for auto-selection of best routine (inexact NT) 00121 template <class M> inline 00122 typename M::NT determinant (const M& matrix, 00123 int n, 00124 Integral_domain_without_division_tag, 00125 ::CGAL::Boolean_tag<false> ) 00126 { 00127 typedef typename M::NT NT; 00128 NT type = NT(0); 00129 00130 return inexact_determinant_select(matrix, n, type); 00131 } 00132 00133 // (other datatypes) 00134 template <class M, class other> inline 00135 typename M::NT inexact_determinant_select (const M& matrix, 00136 int n, 00137 other type) 00138 { 00139 return det_berkowitz(matrix, n); 00140 } 00141 00147 template <class NT > inline 00148 NT determinant(const CGALi::Simple_matrix<NT>& A) 00149 { 00150 CGAL_assertion(A.row_dimension()==A.column_dimension()); 00151 return determinant(A,A.column_dimension()); 00152 } 00153 00159 template <class M> inline 00160 typename M::NT determinant(const M& matrix, 00161 int n) 00162 { 00163 typedef typename M::NT NT; 00164 typedef typename Algebraic_structure_traits<NT>::Algebraic_category Algebraic_category; 00165 typedef typename Algebraic_structure_traits<NT>::Is_exact Is_exact; 00166 00167 return CGALi::determinant (matrix, n, Algebraic_category(), Is_exact()); 00168 } 00169 00170 00171 // Part of det_berkowitz 00172 // Computes sum of all clows of length k 00173 template <class M> 00174 inline 00175 std::vector<typename M::NT> 00176 clow_lengths (const M& A,int k,int n) 00177 { 00178 typedef typename M::NT NT; 00179 00180 int i, j, l; 00181 00182 typename CGALi::Simple_vector<NT> r(k-1); 00183 typename CGALi::Simple_vector<NT> s(k-1); 00184 typename CGALi::Simple_vector<NT> t(k-1); 00185 std::vector<NT> rMks(k); 00186 00187 typename CGALi::Simple_matrix<NT> MM(k-1); 00188 00189 for (i=n-k+2;i<=n;++i) 00190 for (j=n-k+2;j<=n;++j) 00191 MM[i-n+k-2][j-n+k-2] = A[i-1][j-1]; 00192 00193 i = n-k+1; 00194 l = 1; 00195 00196 for (j=n-k+2;j<=n;++j,++l) 00197 { 00198 r[l-1] = A[i-1][j-1]; 00199 s[l-1] = A[j-1][i-1]; 00200 } 00201 00202 rMks[0] = A[i-1][i-1]; 00203 rMks[1] = r*s; 00204 00205 for (i=2;i<k;++i) 00206 { 00207 // r = r * M; 00208 for (j=0;j<k-1;++j) 00209 for (l=0;l<k-1;++l) 00210 t[j] += r[l] * MM[l][j]; 00211 for (j=0;j<k-1;++j) 00212 { 00213 r[j] = t[j]; 00214 t[j] = NT(0); 00215 } 00216 rMks[i] = r*s; 00217 } 00218 00219 return rMks; 00220 } 00221 00229 template <class NT > inline 00230 NT det_berkowitz(const CGALi::Simple_matrix<NT>& A) 00231 { 00232 CGAL_assertion(A.row_dimension()==A.column_dimension()); 00233 return det_berkowitz(A,A.column_dimension()); 00234 } 00235 00236 template <class M, class OutputIterator> inline 00237 OutputIterator minors_berkowitz (const M& A,OutputIterator minors,int n,int m=0) 00238 { 00239 CGAL_precondition(n>0); 00240 CGAL_precondition(m<=n); 00241 00242 00243 typedef typename M::NT NT; 00244 00245 // If default value is set, reset it to the second parameter 00246 if(m==0) { 00247 m=n; 00248 } 00249 00250 int i, j, k, offset; 00251 std::vector<NT> rMks; 00252 NT a; 00253 00254 typename CGALi::Simple_matrix<NT> B(n+1); // not square in original 00255 00256 typename CGALi::Simple_vector<NT> p(n+1); 00257 typename CGALi::Simple_vector<NT> q(n+1); 00258 00259 for (k=1;k<=n;++k) 00260 { 00261 // compute vector q = B*p; 00262 if (k == 1) 00263 { 00264 p[0] = NT(-1); 00265 q[0] = p[0]; 00266 p[1] = A[n-1][n-1]; 00267 q[1] = p[1]; 00268 } 00269 else if (k == 2) 00270 { 00271 p[0] = NT(1); 00272 q[0] = p[0]; 00273 p[1] = -A[n-2][n-2] - A[n-1][n-1]; 00274 q[1] = p[1]; 00275 p[2] = -A[n-2][n-1] * A[n-1][n-2] + A[n-2][n-2] * A[n-1][n-1]; 00276 q[2] = p[2]; 00277 } 00278 else if (k == n) 00279 { 00280 rMks = CGALi::clow_lengths<M>(A,k,n); 00281 // Setup for last row of matrix B 00282 i = n+1; 00283 B[i-1][n-1] = NT(-1); 00284 00285 for (j=1;j<=n;++j) 00286 B[i-1][i-j-1] = rMks[j-1]; 00287 00288 p[i-1] = NT(0); 00289 00290 for (j=1;j<=n;++j) 00291 p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1]; 00292 } 00293 else 00294 { 00295 rMks = CGALi::clow_lengths<M>(A,k,n); 00296 00297 // Setup for matrix B (diagonal after diagonal) 00298 00299 for (i=1;i<=k;++i) 00300 B[i-1][i-1] = NT(-1); 00301 00302 for (offset=1;offset<=k;++offset) 00303 { 00304 a = rMks[offset-1]; 00305 00306 for (i=1;i<=k-offset+1;++i) 00307 B[offset+i-1][i-1] = a; 00308 } 00309 00310 // Multiply s.t. p=B*q 00311 00312 for (i=1;i<=k;++i) 00313 { 00314 p[i-1] = NT(0); 00315 00316 for (j=1;j<=i;++j) 00317 p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1]; 00318 } 00319 00320 p[i-1] = NT(0); 00321 00322 for (j=1;j<=k;++j) 00323 p[i-1] = p[i-1] + B[i-1][j-1] * q[j-1]; 00324 00325 for (i=1;i<=k+1;++i) 00326 q[i-1] = p[i-1]; 00327 } 00328 00329 if(k > n-m) { 00330 (*minors)=p[k]; 00331 ++minors; 00332 } 00333 } 00334 return minors; 00335 } 00336 00343 template <class M> inline 00344 typename M::NT det_berkowitz (const M& A, 00345 int n) 00346 { 00347 typedef typename M::NT NT; 00348 if(n==0) { 00349 return NT(1); 00350 } 00351 NT det[1]; 00352 minors_berkowitz(A,det,n,1); 00353 return det[0]; 00354 } 00355 00356 00357 00358 } // namespace CGALi 00359 00360 00361 00362 CGAL_END_NAMESPACE 00363 00364 #endif // CGAL_POLYNOMIAL_DETERMINANT_H