00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "config.hpp"
00014
00015 #if !defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE) || \
00016 defined(ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_GAUSS)
00017
00018 #include <cstddef>
00019 #include <cmath>
00020 #include <limits>
00021
00022 #include "gauss.hpp"
00023 #include "cmp.hpp"
00024 #include "misc.hpp"
00025 #include "submatrix/hpair.hpp"
00026
00027
00028 namespace Arageli
00029 {
00030
00031
00032 template <typename M>
00033 void gauss_field_row_iter
00034 (
00035 M& a,
00036 typename M::size_type row,
00037 typename M::size_type col
00038 )
00039 {
00040 ARAGELI_ASSERT_0(row < a.nrows());
00041 ARAGELI_ASSERT_0(col < a.ncols());
00042
00043 a.div_row(row, safe_reference(a(row, col)));
00044
00045 typedef typename M::size_type size_type;
00046
00047 for(size_type i = 0; i < row; ++i)
00048 a.addmult_rows(i, row, -a(i, col));
00049 for(size_type i = row + 1; i < a.nrows(); ++i)
00050 a.addmult_rows(i, row, -a(i, col));
00051 }
00052
00053
00054 template <typename M>
00055 void gauss_field_col_iter
00056 (
00057 M& a,
00058 typename M::size_type row,
00059 typename M::size_type col
00060 )
00061 {
00062 ARAGELI_ASSERT_0(row < a.nrows());
00063 ARAGELI_ASSERT_0(col < a.ncols());
00064
00065 a.div_col(col, safe_reference(a(row, col)));
00066
00067 typedef typename M::size_type size_type;
00068
00069 for(size_type j = 0; j < col; ++j)
00070 a.addmult_cols(j, col, -a(row, j));
00071 for(size_type j = col + 1; j < a.ncols(); ++j)
00072 a.addmult_cols(j, col, -a(row, j));
00073 }
00074
00075
00076 template <typename M, typename T>
00077 void gauss_bareiss_row_iter
00078 (
00079 M& a,
00080 typename M::size_type row,
00081 typename M::size_type col,
00082 T& det, T& det_denom
00083 )
00084 {
00085
00086
00087 ARAGELI_ASSERT_0(row < a.nrows());
00088 ARAGELI_ASSERT_0(col < a.ncols());
00089
00090 typedef typename M::element_type TM;
00091 typedef typename M::size_type size_type;
00092
00093 TM pivot = a(row, col);
00094
00095 if(is_negative(pivot))
00096 {
00097 a.mult_row(row, opposite_unit<TM>());
00098 opposite(&pivot);
00099 opposite(&det);
00100 }
00101
00102 for(size_type i = 0; i < a.nrows(); i++)
00103 if(i != row)
00104 {
00105 TM alpha = a(i, col);
00106 TM delta = gcd(pivot, alpha);
00107 TM bi = -alpha / delta;
00108 TM brow = pivot / delta;
00109 a.mult_row(i, brow);
00110 a.addmult_rows(i, row, bi);
00111 alpha = gcd(a.copy_row(i));
00112 a.div_row(i, alpha);
00113
00114 det *= alpha;
00115 det_denom *= brow;
00116
00117
00118 }
00119 }
00120
00121
00122 template
00123 <
00124 typename A, typename B, typename Q, typename Basis,
00125 typename T, typename T_factory,
00126 typename Ctrler
00127 >
00128 void rref_gauss_field
00129 (
00130 const A& a, B& b, Q& q, Basis& basis,
00131 T& det,
00132 const T_factory& tfctr,
00133 Ctrler ctrler
00134 )
00135 {
00136 ARAGELI_ASSERT_0(!a.is_empty());
00137
00138 typedef typename B::element_type TB;
00139 typedef typename B::size_type size_type;
00140
00141 det = tfctr.unit(det);
00142 size_type m = a.nrows(); size_type n = a.ncols();
00143 q.assign_eye(m);
00144 b = a;
00145 basis.resize(0);
00146 TB bnull = null(b(0, 0));
00147 hpair_matrix<B, Q> bq(b, q);
00148
00149 ctrler.preamble(a);
00150
00151 for(size_type i = 0, j = 0; i < m && j < n; j++)
00152 {
00153 ctrler.before_iter(b, q, det, basis);
00154
00155
00156
00157
00158
00159 ctrler.find_biggest_in_col(j);
00160 TB max = bnull;
00161 size_type i_max = i;
00162
00163 for(size_type ii = i; ii < m; ii++)
00164 {
00165 TB absval = abs(b(ii, j));
00166 if(absval > max)
00167 {
00168 max = absval;
00169 i_max = ii;
00170 }
00171 }
00172
00173 if(is_null(max))
00174 {
00175
00176 ctrler.negligible_col(j);
00177 det = tfctr.null(det);
00178 ctrler.after_iter(b, q, det, basis);
00179 continue;
00180 }
00181
00182
00183
00184 ctrler.pivot_item(i_max, j);
00185
00186
00187
00188 if(i != i_max)
00189 {
00190 bq.swap_rows(i, i_max);
00191
00192 opposite(&det);
00193
00194 ctrler.swap_rows(i, i_max, b, q, det);
00195 }
00196
00197
00198
00199
00200 ctrler.eliminate_col(j);
00201
00202
00203
00204 det *= b(i, j);
00205
00206 gauss_field_row_iter(bq, i, j);
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 ctrler.after_elimination(b, q, det);
00220
00221 basis.push_back(j);
00222 i++;
00223
00224 ctrler.after_iter(b, q, det, basis);
00225 }
00226
00227 ctrler.conclusion(b, q, det, basis);
00228 }
00229
00230
00231 template <typename A1, typename A2, typename I>
00232 void mat_col_copy_order
00233 (const A1& a1, A2& a2, const I& idx)
00234 {
00235 A1 temp = a1;
00236 temp.take_cols(idx, a2);
00237
00238 for(typename A1::size_type i = 0; i < temp.ncols(); ++i)
00239 a2.insert_col(a2.ncols(), temp.copy_col(i));
00240 }
00241
00242
00243 template <typename A1, typename A2, typename I>
00244 void vec_copy_order
00245 (const A1& a1, A2& a2, const I& idx)
00246 {
00247 A1 temp = a1;
00248 temp.take_subvector(idx, a2);
00249
00250 for(typename A1::size_type i = 0; i < temp.size(); ++i)
00251 a2.push_back(temp[i]);
00252 }
00253
00254 template <typename A, typename B>
00255 void vec_inverse_permutation (const A& a, B& b)
00256 {
00257 b.resize(a.size());
00258 typedef typename A::size_type size_type;
00259 for(size_type i = 0; i < a.size(); ++i)
00260 {
00261 ARAGELI_ASSERT_0(size_type(a[i]) < a.size());
00262 size_type ii = std::find(a.begin(), a.end(), i) - a.begin();
00263 ARAGELI_ASSERT_0(ii < a.size());
00264 b[i] = ii;
00265 }
00266 }
00267
00268
00269 template
00270 <
00271 typename A, typename B, typename Q,
00272 typename Basis_in, typename Basis_out,
00273 typename Det
00274 >
00275 void rref_order
00276 (
00277 const A& a, B& b, Q& q,
00278 const Basis_in& basis_in, Basis_out& basis_out,
00279 Det& det
00280 )
00281 {
00282 A aa;
00283 Basis_in order = basis_in;
00284 for(std::size_t i = 0; i < a.ncols(); ++i)
00285 if(std::find(basis_in.begin(), basis_in.end(), i) == basis_in.end())
00286 order.push_back(i);
00287
00288 mat_col_copy_order(a, aa, order);
00289
00290
00291 Q qq = q; B bb;
00292 rref(aa, bb, qq, basis_out, det);
00293
00294 Basis_in invorder;
00295 vec_inverse_permutation(order, invorder);
00296
00297
00298 mat_col_copy_order(bb, b, invorder);
00299
00300
00301 }
00302
00303
00304 template <typename T, bool REFCNT>
00305 matrix<T, REFCNT> inverse (const matrix<T, REFCNT>& A)
00306 {
00307
00308
00309 ARAGELI_ASSERT_0(A.is_square());
00310
00311 matrix<T, false> B;
00312 matrix<T, true> Q;
00313 vector<std::size_t, false> basis;
00314 T det;
00315
00316 rref(A, B, Q, basis, det);
00317
00318 if(is_null(det))
00319 throw matrix_is_singular();
00320
00321 ARAGELI_ASSERT_1
00322 (
00323 !std::numeric_limits<T>::is_specialized ||
00324 !std::numeric_limits<T>::is_exact ||
00325 is_unit(A*Q)
00326 );
00327
00328 return Q;
00329 }
00330
00331
00332 template <typename T, bool REFCNT>
00333 T det (const matrix<T, REFCNT>& A)
00334 {
00335
00336
00337 ARAGELI_ASSERT_0(A.is_square());
00338
00339 matrix<T, false> B;
00340 matrix<T, false> Q;
00341 vector<std::size_t, false> basis;
00342 T det;
00343
00344 rref(A, B, Q, basis, det);
00345
00346 return basis.size() < A.nrows() ? null(det) : det;
00347 }
00348
00349
00350 template <typename T, bool REFCNT>
00351 typename matrix<T, REFCNT>::size_type rank
00352 (const matrix<T, REFCNT>& A)
00353 {
00354 matrix<T, false> B;
00355 matrix<T, false> Q;
00356 vector<std::size_t, false> basis;
00357 T det;
00358
00359 rref(A, B, Q, basis, det);
00360
00361 return basis.size();
00362 }
00363
00364
00365 template
00366 <
00367 typename A, typename B, typename Q, typename Basis,
00368 typename T, typename T_factory,
00369 typename Ctrler
00370 >
00371 void rref_gauss_bareiss
00372 (
00373 const A& a, B& b, Q& q, Basis& basis,
00374 T& det,
00375 const T_factory& tfctr,
00376 Ctrler ctrler
00377 )
00378 {
00379 typedef typename B::element_type TB;
00380 typedef typename B::size_type size_type;
00381
00382 det = tfctr.unit(det);
00383 T det_denom = tfctr.unit(det);
00384 size_type m = a.nrows();
00385 size_type n = a.ncols();
00386 q.assign_eye(m);
00387 b = a;
00388 basis.resize(0);
00389 TB bnull = null(b(0, 0));
00390 hpair_matrix<B, Q> bq(b, q);
00391
00392 ctrler.preamble(a);
00393
00394 for(size_type i = 0, j = 0; i < m && j < n; j++)
00395 {
00396
00397
00398 ctrler.before_iter(b, q, det, basis, det_denom);
00399
00400
00401
00402
00403
00404 ctrler.find_biggest_in_col(j);
00405 TB max = bnull;
00406 size_type i_max = i;
00407
00408 for(size_type ii = i; ii < m; ii++)
00409 {
00410 TB absval = abs(b(ii, j));
00411 if(absval > max)
00412 {
00413 max = absval;
00414 i_max = ii;
00415 }
00416 }
00417
00418 if(is_null(max))
00419 {
00420
00421 ctrler.negligible_col(j);
00422 det = tfctr.null(det);
00423 ctrler.after_iter(b, q, det, basis, det_denom);
00424 continue;
00425 }
00426
00427 ctrler.pivot_item(i_max, j);
00428
00429 if(i != i_max)
00430 {
00431 bq.swap_rows(i, i_max);
00432
00433 opposite(&det);
00434
00435 ctrler.swap_rows(i, i_max, b, q, det, det_denom);
00436 }
00437
00438 ctrler.eliminate_col(j);
00439
00440 gauss_bareiss_row_iter(bq, i, j, det, det_denom);
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 ctrler.after_elimination(b, q, det, det_denom);
00471
00472 basis.push_back(j);
00473 i++;
00474 ctrler.after_iter(b, q, det, basis, det_denom);
00475 }
00476
00477 for(size_type i = 0; i < basis.size(); i++)
00478 det *= b(i, basis[i]);
00479 det /= det_denom;
00480
00481 ctrler.conclusion(b, q, det, basis);
00482 }
00483
00484
00485 template <typename T, bool REFCNT>
00486 T det_int (const matrix<T, REFCNT>& A)
00487 {
00488
00489
00490 ARAGELI_ASSERT_0(A.is_square());
00491
00492 matrix<T, false> B;
00493 matrix<T, false> Q;
00494 vector<std::size_t, false> basis;
00495 T d;
00496
00497 rref_int(A, B, Q, basis, d);
00498
00499 return basis.size() < A.nrows() ? null(d) : d;
00500 }
00501
00502
00503 template <typename T, bool REFCNT>
00504 typename matrix<T, REFCNT>::size_type rank_int
00505 (const matrix<T, REFCNT>& A)
00506 {
00507 matrix<T, false> B;
00508 matrix<T, false> Q;
00509 vector<std::size_t, false> basis;
00510 T det;
00511
00512 rref_int(A, B, Q, basis, det);
00513
00514 return basis.size();
00515 }
00516
00517
00518
00519 }
00520
00521
00522 #endif // #ifndef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE