00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00023 #ifndef _ARAGELI_sparse_polynom_hpp_
00024 #define _ARAGELI_sparse_polynom_hpp_
00025
00026 #include "config.hpp"
00027
00028 #include <iostream>
00029 #include <list>
00030 #include <iomanip>
00031 #include <algorithm>
00032 #include <cmath>
00033
00034 #include "frwrddecl.hpp"
00035
00036 #include "type_traits.hpp"
00037 #include "config.hpp"
00038 #include "exception.hpp"
00039 #include "refcntr.hpp"
00040 #include "iteradapt.hpp"
00041 #include "type_opers.hpp"
00042 #include "factory.hpp"
00043 #include "cmp.hpp"
00044 #include "io.hpp"
00045 #include "powerest.hpp"
00046 #include "big_int.hpp"
00047 #include "rational.hpp"
00048 #include "_utility.hpp"
00049
00050 #include "std_import.hpp"
00051
00052
00053
00054 namespace Arageli
00055 {
00056
00057 template <typename T> class rational;
00058
00059
00061
00065 template
00066 <
00067 typename F,
00068 typename I
00069 >
00070 class monom
00071 {
00072 template <typename F1, typename I1>
00073 friend class monom;
00074
00075 public:
00076
00077 typedef F coef_type;
00078 typedef I degree_type;
00079
00081
00082 monom () : coef_m(factory<coef_type>::null()), degree_m(factory<degree_type>::null()) {}
00083
00085
00087 monom (const F& c) : coef_m(c), degree_m(factory<degree_type>::null()) {}
00088
00090
00092 monom (const F& c, const I& d) : coef_m(c), degree_m(d) {}
00093
00095 template <typename F1, typename I1>
00096 monom (const monom<F1, I1>& x)
00097 : coef_m(x.coef_m), degree_m(x.degree_m) {}
00098
00100
00101 monom (const char* s);
00102
00103 template <typename F1, typename I1>
00104 monom& operator= (const monom<F1, I1>& x)
00105 {
00106 coef_m = x.coef_m; degree_m = x.degree_m;
00107 return *this;
00108 }
00109
00110 monom& operator= (const char* s)
00111 { return *this = monom(s); }
00112
00114
00115 bool is_const () const { return Arageli::is_null(degree_m); }
00116
00118
00120 bool is_null () const { return Arageli::is_null(coef_m); }
00121
00123
00125 bool is_unit () const
00126 { return Arageli::is_unit(coef_m) && Arageli::is_null(degree_m); }
00127
00129
00131 bool is_opposite_unit () const
00132 {
00133 return Arageli::is_opposite_unit(coef_m) &&
00134 Arageli::is_null(degree_m);
00135 }
00136
00137
00139
00140 bool is_x () const
00141 { return Arageli::is_unit(coef_m) && Arageli::is_unit(degree_m); }
00142
00144 const coef_type& coef () const { return coef_m; }
00145
00147 coef_type& coef () { return coef_m; }
00148
00150 const degree_type& degree () const { return degree_m; }
00151
00153 degree_type& degree () { return degree_m; }
00154
00156
00158 template <typename F1, typename I1>
00159 bool can_add (const monom<F1, I1>& x) const
00160 { return degree_m == x.degree_m; }
00161
00163 monom& opposite ()
00164 {
00165 Arageli::opposite(&coef_m);
00166 return *this;
00167 }
00168
00170 monom operator- () const
00171 { return monom(Arageli::opposite(coef_m), degree_m); }
00172
00174 const monom& operator+ () const { return *this; }
00175
00176 monom& operator++ ()
00177 {
00178 ARAGELI_ASSERT_0(is_const());
00179 ++coef_m;
00180 return *this;
00181 }
00182
00183 monom operator++ (int) { monom t = *this; operator++(); return t; }
00184
00185 monom& operator-- ()
00186 {
00187 ARAGELI_ASSERT_0(is_const());
00188 --coef_m;
00189 return *this;
00190 }
00191
00192 monom operator-- (int) { monom t = *this; operator--(); return t; }
00193
00195
00197 template <typename F1>
00198 monom& operator+= (const F1& x)
00199 {
00200 ARAGELI_ASSERT_0(is_const());
00201 coef_m += x;
00202 return *this;
00203 }
00204
00206
00209 template <typename F1>
00210 monom& operator-= (const F1& x)
00211 {
00212 ARAGELI_ASSERT_0(is_const());
00213 coef_m -= x;
00214 return *this;
00215 }
00216
00218
00220 template <typename F1>
00221 monom& operator*= (const F1& x)
00222 {
00223 coef_m *= x;
00224 return *this;
00225 }
00226
00228
00231 template <typename F1>
00232 monom& operator/= (const F1& x)
00233 {
00234 ARAGELI_ASSERT_0(!Arageli::is_null(x));
00235 coef_m /= x;
00236 return *this;
00237 }
00238
00240
00243 template <typename F1>
00244 monom& operator%= (const F1& x)
00245 {
00246 ARAGELI_ASSERT_0(!Arageli::is_null(x));
00247 coef_m %= x;
00248 return *this;
00249 }
00250
00252
00254 template <typename F1, typename I1>
00255 monom& operator+= (const monom<F1, I1>& x)
00256 {
00257 ARAGELI_ASSERT_0(can_add(x));
00258 coef_m += x.coef_m;
00259 return *this;
00260 }
00261
00263
00266 template <typename F1, typename I1>
00267 monom& operator-= (const monom<F1, I1>& x)
00268 {
00269 ARAGELI_ASSERT_0(can_add(x));
00270 coef_m -= x.coef_m;
00271 return *this;
00272 }
00273
00275
00277 template <typename F1, typename I1>
00278 monom& operator*= (const monom<F1, I1>& x)
00279 {
00280 coef_m *= x.coef_m;
00281 degree_m += x.degree_m;
00282 return *this;
00283 }
00284
00286
00288 template <typename F1, typename I1>
00289 monom& operator/= (const monom<F1, I1>& x)
00290 {
00291 ARAGELI_ASSERT_0(!Arageli::is_null(x.coef_m));
00292
00293 if(degree_m >= x.degree_m)
00294 {
00295 coef_m /= x.coef_m;
00296 degree_m -= x.degree_m;
00297 }
00298 else
00299 {
00300 coef_m = factory<coef_type>::null();
00301 degree_m = null<degree_type>();
00302 }
00303
00304 return *this;
00305 }
00306
00308
00311 template <typename F1, typename I1>
00312 monom& operator%= (const monom<F1, I1>& x)
00313 {
00314 ARAGELI_ASSERT_0(!Arageli::is_null(x.coef_m));
00315 if(degree_m >= x.degree_m)coef_m %= x.coef_m;
00316 return *this;
00317 }
00318
00320 template <typename F1, typename I1>
00321 void swap (monom<F1, I1>& x)
00322 {
00323 std::swap(coef_m, x.coef_m);
00324 std::swap(degree_m, x.degree_m);
00325 }
00326
00327 private:
00328
00329 coef_type coef_m;
00330 degree_type degree_m;
00331
00332 };
00333
00334
00335
00336
00337
00338 template <typename F, typename I>
00339 struct type_traits<monom<F, I> >
00340 : public type_traits_default<monom<F, I> >
00341 {
00342 static const bool is_specialized =
00343 type_traits<F>::is_specialized &&
00344 type_traits<I>::is_specialized;
00345
00346 static const bool is_integer_number = false;
00347 static const bool is_polynom = false;
00348 static const bool is_real_number = false;
00349 static const bool is_rational_number = false;
00350 static const bool is_complex_number = false;
00351 static const bool is_ring = false;
00352 static const bool is_field = false;
00353
00354 static const bool is_finite =
00355 type_traits<F>::is_finite &&
00356 type_traits<I>::is_finite;
00357
00358 static const bool is_additive_group = type_traits<F>::is_ring;
00359 static const bool is_multiplicative_group = false;
00360
00361 static const bool has_zero_divisor =
00362 type_traits<F>::has_zero_divisor &&
00363 type_traits<I>::has_null;
00364
00365 static const bool is_integer_modulo_ring = false;
00366 static const bool is_matrix = false;
00367 static const bool is_vector = false;
00368
00369 static const bool has_commutative_multiplication =
00370 type_traits<F>::has_commutative_multiplication &&
00371 type_traits<I>::has_commutative_addition;
00372
00373 static const bool has_commutative_addition =
00374 type_traits<F>::has_commutative_addition;
00375
00376 static const bool has_null =
00377 type_traits<F>::has_null &&
00378 type_traits<I>::has_null;
00379
00380 static const bool has_unit =
00381 type_traits<F>::has_unit &&
00382 type_traits<I>::has_null;
00383
00384 static const bool has_opposite_unit =
00385 type_traits<F>::has_opposite_unit &&
00386 type_traits<I>::has_null;
00387
00389 static const bool is_aggregate = true;
00390
00392 typedef F element_type;
00393
00394 };
00395
00396
00397
00398
00399
00400
00401 template <typename F, typename I>
00402 struct factory<monom<F, I> >
00403 {
00404 static const bool is_specialized = true;
00405
00406 static const monom<F, I>& unit ()
00407 {
00408 static const monom<F, I> unit_s(Arageli::unit<F>());
00409 return unit_s;
00410 }
00411
00412 static monom<F, I> unit (const monom<F, I>& x)
00413 { return monom<F, I>(Arageli::unit(x.coef())); }
00414
00415 static const monom<F, I>& opposite_unit ()
00416 {
00417 static const monom<F, I> opposite_unit_s(Arageli::opposite_unit<F>());
00418 return opposite_unit_s;
00419 }
00420
00421 static monom<F, I> opposite_unit (const monom<F, I>& x)
00422 { return monom<F, I>(opposite_unit(x.coef())); }
00423
00424 static const monom<F, I>& null ()
00425 {
00426 static const monom<F, I> null_s(Arageli::null<F>());
00427 return null_s;
00428 }
00429
00430 static monom<F, I> null (const monom<F, I>& x)
00431 { return monom<F, I>(Arageli::null(x.coef())); }
00432
00433 };
00434
00435
00436 template <typename F, typename I>
00437 inline bool is_unit (const monom<F, I>& x)
00438 { return x.is_unit(); }
00439
00440 template <typename F, typename I>
00441 inline bool is_opposite_unit (const monom<F, I>& x)
00442 { return x.is_opposite_unit(); }
00443
00444 template <typename F, typename I>
00445 inline bool is_null (const monom<F, I>& x)
00446 { return x.is_null(); }
00447
00448 template <typename F, typename I>
00449 inline monom<F, I> opposite (const monom<F, I>& x)
00450 { return -x; }
00451
00452 template <typename F, typename I>
00453 inline monom<F, I>& opposite (const monom<F, I>& x, monom<F, I>* y)
00454 { return (*y = x).opposite(); }
00455
00456 template <typename F, typename I>
00457 inline monom<F, I>& opposite (monom<F, I>* x)
00458 { return x->opposite(); }
00459
00460 template <typename F, typename I>
00461 inline monom<F, I> inverse (const monom<F, I>& x)
00462 {
00463 ARAGELI_ASSERT_0(x.is_const());
00464 return inverse(x.coef());
00465 }
00466
00467 template <typename F, typename I>
00468 inline monom<F, I>& inverse (const monom<F, I>& x, monom<F, I>* y)
00469 {
00470 ARAGELI_ASSERT_0(x.is_const());
00471 inverse(x.coef(), &y->coef());
00472 y->degree() = x.degree();
00473 return *y;
00474 }
00475
00476 template <typename F, typename I>
00477 inline monom<F, I>& inverse (monom<F, I>* x)
00478 {
00479 ARAGELI_ASSERT_0(x.is_const());
00480 inverse(&x->coef());
00481 return *x;
00482 }
00483
00484 template <typename F, typename I>
00485 inline std::ostream& output_polynom_first (std::ostream& out, const monom<F, I>& x)
00486 { return out << '(' << x << ')'; }
00487
00488 template <typename F, typename I>
00489 inline std::ostream& output_polynom_internal
00490 (std::ostream& out, const monom<F, I>& x)
00491 { return out << "+(" << x << ')'; }
00492
00493 template <typename F, typename I>
00494 inline std::ostream& output_pow (std::ostream& out, const monom<F, I>& x)
00495 { return out << '(' << x << ')'; }
00496
00497 template <typename F, typename I>
00498 std::istream& input_polynom_first (std::istream& in, monom<F, I>& x);
00499
00500 template <typename F, typename I>
00501 std::istream& input_polynom_internal
00502 (std::istream& in, monom<F, I>& x);
00503
00504 template <typename F, typename I>
00505 inline std::istream& input_pow (std::istream& in, monom<F, I>& x)
00506 { return input_polynom_first(in, x); }
00507
00508
00509
00512
00513
00514
00521
00544
00545
00574
00590
00591
00600
00601
00623
00625
00647
00663
00678
00696
00722
00726
00744
00755
00805
00819
00831
00844
00848
00852
00853
00856
00858
00861
00862
00865
00867
00873
00878
00888
00890
00893
00894
00897
00900
00916
00919
00922
00925
00940
00943
00944
00947
00948
00953
00955
00961
00970
00979
00982
00991
00992
00996
01025
01026
01034
01042
01050
01058
01060
01068
01070
01074
01075
01085
01086
01095
01096
01108
01109
01121
01122
01133
01134
01137
01138
01142
01143
01147
01148
01159
01160
01172
01179
01182
01187
01190
01192
01195
01204
01275
01276
01327
01328
01350
01351
01377
01381
01382
01388
01391
01394
01397
01401
01405
01409
01416
01426
01429
01432
01435
01438
01441
01445
01449
01453
01457
01461
01465
01469
01476
01479
01483
01488
01489
01495
01496
01504
01506
01524
01531
01615
01617
01620
01633
01634
01638
01639
01720
01729
01736
01743
01760
01765
01781
01797
01814
01839
01843
01861
01872
01984
01985
01999
02007
02138
02390
02393
02441
02463
02516
02517
02523
02525
02596
02597
02603
02605