00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #ifndef _ARAGELI_rational_hpp_
00012 #define _ARAGELI_rational_hpp_
00013
00014 #include "config.hpp"
00015
00016 #include <iostream>
00017 #include <cstdlib>
00018 #include <sstream>
00019 #include <string>
00020 #include <cctype>
00021 #include <cmath>
00022 #include <functional>
00023
00024 #include "type_traits.hpp"
00025 #include "type_pair_traits.hpp"
00026 #include "exception.hpp"
00027 #include "factory.hpp"
00028 #include "cmp.hpp"
00029 #include "io.hpp"
00030 #include "powerest.hpp"
00031 #include "big_int.hpp"
00032
00033 #include "std_import.hpp"
00034
00042 namespace Arageli
00043 {
00044
00045
00046
00048 class rational_base
00049 {
00050 public:
00051
00053 class exception : public virtual Arageli::exception
00054 {
00055 std::string msg_m;
00056 public:
00057 exception (const std::string& msg_a) : msg_m(msg_a) {}
00058 virtual std::string msg () const { return msg_m; }
00059 };
00060 };
00061
00062
00064
00067 template <typename T = big_int>
00068 class rational : public rational_base
00069 {
00070 template <typename T1>
00071 friend class rational;
00072
00073 public:
00074
00076 typedef T value_type;
00077
00079 rational () : p(factory<T>::null()), q(factory<T>::unit()) {}
00080
00082 rational (const char* str);
00083
00085 template <typename T1>
00086 rational (const rational<T1>& x)
00087 {
00088 ARAGELI_ASSERT_1
00089 (
00090 reinterpret_cast<const void*>(this) !=
00091 reinterpret_cast<const void*>(&x)
00092 );
00093
00094 p = x.p; q = x.q;
00095 }
00096
00098
00099 template <typename T1>
00100 rational (const T1& w) : p(w), q(factory<T>::unit(p)) {}
00101
00103
00104 rational (const T& u, const T& v) : p(u), q(v)
00105 { ARAGELI_ASSERT_0(!Arageli::is_null(q)); normalize(); }
00106
00107
00108 rational (double x)
00109 {
00110 if(x == 0)
00111 {
00112 p = null<T>();
00113 q = unit<T>();
00114 }
00115 else
00116 {
00117 int pp;
00118 static const double powdig2 = pow(2.0, std::numeric_limits<double>::digits);
00119 p = powdig2 * frexp(x, &pp);
00120 q = powdig2;
00121 if(pp > 0)p *= pow(T(2), pp);
00122 else if(pp < 0)q *= pow(T(2), -pp);
00123 normalize();
00124 }
00125 }
00126
00127
00130
00131
00132
00133
00134
00135
00136 #define _ARAGELI_RATIONAL_OPERATOR_TO(TYPE) \
00137 operator TYPE () const { return double(*this); }
00138
00140 _ARAGELI_RATIONAL_OPERATOR_TO(int);
00141
00143 operator big_int () const
00144 {
00145 ARAGELI_ASSERT_0(is_normal());
00146 return numerator()/denominator();
00147 }
00148
00150
00155 operator float () const
00156 {
00157 ARAGELI_ASSERT_0(is_normal());
00158 return float(numerator())/float(denominator());
00159 }
00160
00162
00167 operator double () const
00168 {
00169 ARAGELI_ASSERT_0(is_normal());
00170 return double(numerator())/double(denominator());
00171 }
00172
00174
00180 operator long double () const
00181 {
00182 ARAGELI_ASSERT_0(is_normal());
00183 return (long double)(numerator())/(long double)(denominator());
00184 }
00185
00187 operator bool () const
00188 {
00189 ARAGELI_ASSERT_0(is_normal());
00190 return !Arageli::is_null(numerator());
00191 }
00192
00193 bool operator! () const { return !bool(*this); }
00194
00195
00196
00197
00198
00199
00200
00202 template <typename T1>
00203 rational& operator= (const rational<T1>& x)
00204 {
00205 ARAGELI_ASSERT_1
00206 (
00207 reinterpret_cast<const void*>(this) !=
00208 reinterpret_cast<const void*>(&x)
00209 );
00210
00211 p = x.p; q = x.q;
00212 return *this;
00213 }
00214
00216
00217 template <typename T1>
00218 rational& operator= (const T1& x)
00219 {
00220 p = x;
00221 q = unit(p);
00222 return *this;
00223 }
00224
00225 rational& operator= (double x)
00226 { return *this = rational(x); }
00227
00228
00229 rational& operator= (const char* s)
00230 { return *this = rational(s); }
00231
00232
00234 const T& numerator () const { return p; }
00235
00237 const T& denominator () const { return q; }
00238
00240 T& numerator () { return p; }
00241
00243 T& denominator () { return q; }
00244
00246
00248 rational operator- () const { return rational(Arageli::opposite(p), q); }
00249
00251 const rational& operator+ () const { return *this; }
00252
00253
00254 rational& operator++ ()
00255 {
00256 p += q;
00257 normalize();
00258 return *this;
00259 }
00260
00261 rational operator++ (int) { rational t = *this; operator++(); return t; }
00262
00263 rational& operator-- ()
00264 {
00265 p -= q;
00266 normalize();
00267 return *this;
00268 }
00269
00270 rational operator-- (int) { rational t = *this; operator--(); return t; }
00271
00272
00274
00276 rational& opposite () { Arageli::opposite(&p); return *this; }
00277
00279
00282 rational& inverse ();
00283
00284
00286
00290 int sign () const;
00291
00293
00294 bool is_integer () const { return Arageli::is_unit(q); }
00295
00297
00298 bool is_null () const { return Arageli::is_null(p); }
00299
00301
00302 bool is_unit () const { return Arageli::is_unit(p) && Arageli::is_unit(q); }
00303
00305
00306 bool is_opposite_unit () const
00307 { return Arageli::is_opposite_unit(p) && Arageli::is_unit(q); }
00308
00310
00313 void normalize ();
00314
00316
00318 bool is_normal () const;
00319
00320
00322 template <typename T1>
00323 void swap (rational<T1>& x)
00324 {
00325 std::swap(p, x.p);
00326 std::swap(q, x.q);
00327 }
00328
00329 private:
00330
00331 T p;
00332 T q;
00333
00334 };
00335
00336
00337 extern const char* rational_output_list_first_bracket_default;
00338 extern const char* rational_output_list_second_bracket_default;
00339 extern const char* rational_output_list_separator_default;
00340 extern const char* rational_input_list_first_bracket_default;
00341 extern const char* rational_input_list_second_bracket_default;
00342 extern const char* rational_input_list_separator_default;
00343 extern const char* rational_output_default_oblique_default;
00344 extern const char* rational_input_default_oblique_default;
00345
00346
00347 template <typename T, typename Ch, typename ChT>
00348 inline std::basic_ostream<Ch, ChT>& output_list
00349 (
00350 std::basic_ostream<Ch, ChT>& out,
00351 const rational<T>& x,
00352 const Ch* first_bracket = rational_output_list_first_bracket_default,
00353 const Ch* second_bracket = rational_output_list_second_bracket_default,
00354 const Ch* separator = rational_output_list_separator_default
00355 )
00356 {
00357 return
00358 out << first_bracket << x.numerator()
00359 << separator << x.denominator() << second_bracket;
00360 }
00361
00362
00363 template <typename T, typename Ch, typename ChT>
00364 std::basic_istream<Ch, ChT>& input_list
00365 (
00366 std::basic_istream<Ch, ChT>& in,
00367 rational<T>& x,
00368 const Ch* first_bracket = rational_input_list_first_bracket_default,
00369 const Ch* second_bracket = rational_input_list_second_bracket_default,
00370 const Ch* separator = rational_input_list_separator_default
00371 );
00372
00373
00374 template <typename T, typename Ch, typename ChT>
00375 std::basic_ostream<Ch, ChT>& output_default
00376 (
00377 std::basic_ostream<Ch, ChT>& out,
00378 const rational<T>& x,
00379 const Ch* oblique = rational_output_default_oblique_default
00380 );
00381
00382
00383 template <typename T, typename Ch, typename ChT>
00384 std::basic_istream<Ch, ChT>& input_default
00385 (
00386 std::basic_istream<Ch, ChT>& in,
00387 rational<T>& x,
00388 const Ch* oblique = rational_input_default_oblique_default
00389 );
00390
00391
00393
00394 template <typename T, typename Ch, typename ChT>
00395 inline std::basic_ostream<Ch, ChT>& operator<<
00396 (
00397 std::basic_ostream<Ch, ChT>& out,
00398 const rational<T>& x
00399 )
00400 { return output_default(out, x); }
00401
00402
00404
00405 template <typename T, typename Ch, typename ChT>
00406 inline std::basic_istream<Ch, ChT>& operator>>
00407 (
00408 std::basic_istream<Ch, ChT>& in,
00409 rational<T>& x
00410 )
00411 { return input_default(in, x); }
00412
00413
00415
00416
00417 template <typename T1, typename T2>
00418 rational<T1> operator+
00419 (const rational<T1>& b, const rational<T2>& c);
00420
00421 template <typename T1, typename T2>
00422 rational<T1> operator-
00423 (const rational<T1>& b, const rational<T2>& c);
00424
00425 template <typename T1, typename T2>
00426 rational<T1> operator*
00427 (const rational<T1>& b, const rational<T2>& c);
00428
00429 template <typename T1, typename T2>
00430 rational<T1> operator/
00431 (const rational<T1>& b, const rational<T2>& c);
00432
00433 template <typename T1, typename T2>
00434 inline rational<T1> operator%
00435 (const rational<T1>& b, const rational<T2>& c)
00436 {
00437 ARAGELI_ASSERT_0(!is_null(c));
00438 return null(b);
00439 }
00440
00441
00442
00443
00444 #define _ARAGELI_RATIONAL_OPERS(OPER) \
00445 template <typename T1, typename T2> \
00446 inline rational<T1>& operator OPER##= \
00447 (rational<T1>& a, const rational<T2>& b) \
00448 { return a = a OPER b; } \
00449 \
00450 template <typename T1, typename T2> \
00451 inline rational<T1>& operator OPER##= \
00452 (rational<T1>& a, const T2& b) \
00453 { return a = a OPER rational<T1>(b); } \
00454 \
00455 template <typename T1, typename T2> \
00456 inline rational<T1> operator OPER \
00457 (const rational<T1>& a, const T2& b) \
00458 { return a OPER rational<T1>(b); } \
00459 \
00460 template <typename T1, typename T2> \
00461 inline rational<T1> operator OPER \
00462 (const T2& a, const rational<T1>& b) \
00463 { return rational<T1>(a) OPER b; }
00464
00465
00467
00468
00469 _ARAGELI_RATIONAL_OPERS(+)
00470 _ARAGELI_RATIONAL_OPERS(-)
00471 _ARAGELI_RATIONAL_OPERS(*)
00472 _ARAGELI_RATIONAL_OPERS(/)
00473 _ARAGELI_RATIONAL_OPERS(%)
00474
00475
00476
00477
00478
00479
00480
00481
00483
00487 template <typename T1, typename T2>
00488 inline int cmp
00489 (
00490 const rational<T1>& a,
00491 const rational<T2>& b
00492 )
00493 { return (a - b).sign(); }
00494
00495
00496 template <typename T>
00497 inline int sign (const rational<T>& x)
00498 { return x.sign(); }
00499
00500 template <typename T>
00501 inline bool is_coprime
00502 (const rational<T>& a, const rational<T>& b)
00503 { return true; }
00504
00505 template <typename T>
00506 inline rational<T> gcd
00507 (const rational<T>& a, const rational<T>& b)
00508 {
00509 if(is_null(a) && is_null(b))return a;
00510 else return unit(a);
00511 }
00512
00513
00514
00515 #define _ARAGELI_RATIONAL_CMP1(OPER) \
00516 template <typename T1, typename T2> \
00517 inline bool operator OPER \
00518 (const rational<T1>& a, const rational<T2>& b) \
00519 { return cmp(a, b) OPER 0; } \
00520 \
00521 template <typename T1, typename T2> \
00522 inline bool operator OPER \
00523 (const rational<T1>& a, const T2& b) \
00524 { return cmp(a, rational<T2>(b)) OPER 0; } \
00525 \
00526 template <typename T1, typename T2> \
00527 inline bool operator OPER \
00528 (const T1& a, const rational<T2>& b) \
00529 { return cmp(rational<T1>(a), b) OPER 0; }
00530
00531
00533
00534
00535 _ARAGELI_RATIONAL_CMP1(<)
00536 _ARAGELI_RATIONAL_CMP1(>)
00537 _ARAGELI_RATIONAL_CMP1(==)
00538 _ARAGELI_RATIONAL_CMP1(!=)
00539 _ARAGELI_RATIONAL_CMP1(<=)
00540 _ARAGELI_RATIONAL_CMP1(>=)
00541
00542
00543
00544
00545
00546
00547
00549
00550 template <typename T>
00551 T ifloor (const rational<T>& x);
00552
00554
00555 template <typename T>
00556 T iceil (const rational<T>& x);
00557
00559
00560 template <typename T>
00561 inline rational<T> frac (const rational<T>& x)
00562 { return x - ifloor(x); }
00563
00564
00565
00567 template <typename T>
00568 struct select_numer : public std::unary_function<rational<T>, T>
00569 { T operator() (const rational<T>& x) const { return x.numerator(); } };
00570
00572 template <typename T>
00573 struct select_denom : public std::unary_function<rational<T>, T>
00574 { T operator() (const rational<T>& x) const { return x.denominator(); } };
00575
00576 template <typename T1>
00577 struct factory<rational<T1> >
00578 {
00579 private:
00580
00581 typedef rational<T1> T;
00582
00583 public:
00584
00585 static const bool is_specialized = true;
00586
00587 static const T& unit ()
00588 {
00589 static const T unit_s(Arageli::unit<T1>());
00590 return unit_s;
00591 }
00592
00593 static T unit (const T& x)
00594 { return T(Arageli::unit(x.numerator()), Arageli::unit(x.denominator())); }
00595
00596 static const T& opposite_unit ()
00597 {
00598 static const T opposite_unit_s(Arageli::opposite_unit<T1>());
00599 return opposite_unit_s;
00600 }
00601
00602 static T opposite_unit (const T& x)
00603 { return T(Arageli::opposite_unit(x.numerator()), Arageli::unit(x.denominator())); }
00604
00605 static const T& null ()
00606 {
00607 static const T null_s(Arageli::null<T1>());
00608 return null_s;
00609 }
00610
00611 static T null (const T& x)
00612 { return T(Arageli::null(x.numerator()), Arageli::unit(x.denominator())); }
00613
00614
00615 };
00616
00618
00619
00621
00622
00624
00625
00626
00627 template <typename T1>
00628 inline bool is_null (const rational<T1>& x)
00629 { return x.is_null(); }
00630
00631 template <typename T1>
00632 inline rational<T1> opposite (const rational<T1>& x)
00633 { return -x; }
00634
00635 template <typename T1>
00636 inline rational<T1>& opposite (const rational<T1>& x, rational<T1>* y)
00637 { return *y = -x; }
00638
00639 template <typename T1>
00640 inline rational<T1>& opposite (rational<T1>* x)
00641 { return x->opposite(); }
00642
00643 template <typename T1>
00644 inline rational<T1> inverse (const rational<T1>& x)
00645 {
00646 rational<T1> xx = x;
00647 return xx.inverse();
00648 }
00649
00650 template <typename T1>
00651 inline rational<T1>& inverse (const rational<T1>& x, rational<T1>* y)
00652 {
00653 *y = x;
00654 return y->inverse();
00655 }
00656
00657 template <typename T1>
00658 inline rational<T1>& inverse (rational<T1>* x)
00659 { return x->inverse(); }
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677 template <typename T1>
00678 inline std::ostream& output_polynom_first (std::ostream& out, const rational<T1>& x)
00679 { return output_polynom_first_default(out, x); }
00680
00681 template <typename T1>
00682 inline std::ostream& output_polynom_internal
00683 (std::ostream& out, const rational<T1>& x)
00684 { return output_polynom_internal_default(out, x); }
00685
00686 template <typename T1>
00687 inline std::ostream& output_pow (std::ostream& out, const rational<T1>& x)
00688 { return output_pow_default(out, x); }
00689
00690 template <typename T1>
00691 inline std::istream& input_polynom_first (std::istream& in, rational<T1>& x)
00692 { return input_polynom_first_default(in, x); }
00693
00694 template <typename T1>
00695 inline std::istream& input_polynom_internal
00696 (std::istream& in, rational<T1>& x)
00697 { return input_polynom_internal_default(in, x); }
00698
00699 template <typename T1>
00700 inline std::istream& input_pow (std::istream& in, rational<T1>& x)
00701 { return input_pow_default(in, x); }
00702
00704 template <typename T>
00705 inline rational<T> abs (const rational<T>& x)
00706 { if(x.sign() < 0)return -x; else return x; }
00707
00709
00710 template <typename T>
00711 inline rational<T> floor (const rational<T>& x)
00712 { return ifloor(x); }
00713
00715
00716 template <typename T>
00717 inline rational<T> ceil (const rational<T>& x)
00718 { return iceil(x); }
00719
00720 }
00721
00722
00723 namespace std
00724 {
00725
00727 template <typename T>
00728 inline Arageli::rational<T> abs (const Arageli::rational<T>& x)
00729 { return Arageli::abs(x); }
00730
00732
00733 template <typename T>
00734 inline Arageli::rational<T> floor (const Arageli::rational<T>& x)
00735 { return Arageli::floor(x); }
00736
00738
00739 template <typename T>
00740 inline Arageli::rational<T> ceil (const Arageli::rational<T>& x)
00741 { return Arageli::ceil(x); }
00742
00743
00745 template <typename T> class numeric_limits<Arageli::rational<T> >
00746 {
00747 typedef Arageli::rational<T> TTT;
00748
00749 public:
00750
00751 static const bool is_specialized = true;
00752
00753
00754
00755
00756 static TTT min () throw() { return TTT(Arageli::factory<T>::unit(), numeric_limits<T>::max()); }
00757 static TTT max () throw() { return TTT(numeric_limits<T>::max, Arageli::factory<T>::unit()); }
00758
00759 static const int digits = 2*numeric_limits<T>::digits;
00760 static const int digits10 = 2*numeric_limits<T>::digits10;
00761 static const bool is_signed = numeric_limits<T>::is_signed;
00762 static const bool is_integer = false;
00763 static const bool is_exact = numeric_limits<T>::is_exact;
00764 static const int radix = 2;
00765 static TTT epsilon () throw() { return TTT(); }
00766 static TTT round_error () throw() { return TTT(); }
00767 static const int min_exponent = 0;
00768 static const int min_exponent10 = 0;
00769 static const int max_exponent = 0;
00770 static const int max_exponent10 = 0;
00771 static const bool has_infinity = false;
00772 static const bool has_quiet_NaN = false;
00773 static const bool has_signaling_NaN = false;
00774 static const float_denorm_style has_denorm = denorm_absent;
00775 static const bool has_denorm_loss = false;
00776 static TTT infinity () throw() { return TTT(); }
00777 static TTT quiet_NaN () throw() { return TTT(); }
00778 static TTT signaling_NaN () throw() { return TTT(); }
00779 static TTT denorm_min () throw() { return TTT(); }
00780 static const bool is_iec559 = false;
00781 static const bool is_bounded = numeric_limits<T>::is_bounded;
00782 static const bool is_modulo = false;
00783 static const bool traps = true;
00784 static const bool tinyness_before = false;
00785 static const float_round_style round = round_toward_zero;
00786 };
00787
00788
00790 template <typename T>
00791 void swap (Arageli::rational<T>& a, Arageli::rational<T>& b)
00792 { a.swap(b); }
00793
00795 template <typename T1, typename T2>
00796 void swap (Arageli::rational<T1>& a, Arageli::rational<T2>& b)
00797 { a.swap(b); }
00798
00799
00800 }
00801
00802
00803 namespace Arageli
00804 {
00805
00807 template <typename T>
00808 struct type_traits<rational<T> >
00809 : public type_traits_default<rational<T> >
00810 {
00811 static const bool is_specialized = type_traits<T>::is_specialized;
00812 static const bool is_number = type_traits<T>::is_number;
00813 static const bool is_rational = true;
00814 static const bool is_integer_number = false;
00815 static const bool is_polynom = false;
00816 static const bool is_real_number = false;
00817 static const bool is_rational_number = type_traits<T>::is_number;
00818 static const bool is_complex_number = false;
00819 static const bool is_ring = type_traits<T>::is_ring;
00820 static const bool is_field = type_traits<T>::is_ring;
00821 static const bool is_finite = type_traits<T>::is_finite;
00822
00823 static const bool is_additive_group =
00824 type_traits<T>::is_additive_group &&
00825 type_traits<T>::is_ring;
00826
00827 static const bool is_multiplicative_group =
00828 type_traits<T>::is_additive_group &&
00829 type_traits<T>::is_ring;
00830
00831 static const bool has_zero_divisor = type_traits<T>::has_zero_divisor;
00832 static const bool is_integer_modulo_ring = false;
00833 static const bool is_matrix = false;
00834 static const bool is_vector = false;
00835
00836 static const bool has_commutative_multiplication =
00837 type_traits<T>::has_commutative_multiplication;
00838
00839 static const bool has_commutative_addition =
00840 type_traits<T>::has_commutative_multiplication &&
00841 type_traits<T>::has_commutative_addition;
00842
00843 static const bool has_null = type_traits<T>::has_null;
00844 static const bool has_unit = type_traits<T>::has_unit;
00845
00846 static const bool has_opposite_unit =
00847 type_traits<T>::has_opposite_unit &&
00848 type_traits<T>::has_unit;
00849
00850 static const bool is_aggregate = true;
00851 typedef T element_type;
00852 typedef type_category::rational category_type;
00853 static const category_type category_value;
00854 };
00855
00856 template <typename T>
00857 const type_category::rational
00858 type_traits<rational<T> >::category_value =
00859 type_category::rational();
00860
00861
00862 #if 0
00863
00865
00868 template <typename TE1, typename T2>
00869 struct type_pair_traits<rational<TE1>, T2>
00870 {
00871 static const bool is_specialized =
00872 type_traits<TE1>::is_specialized &&
00873 type_traits<T2>::is_specialized;
00874
00875 static const bool is_convertible =
00876 type_pair_traits<TE1, T2>::is_convertible;
00877
00878 static const bool is_safe_convertible =
00879 type_traits<T2>::is_rational &&
00880 type_traits<T2>::is_aggregate &&
00881 type_pair_traits<TE1, typename type_traits<T2>::element_type>::is_specialized &&
00882 type_pair_traits<TE1, typename type_traits<T2>::element_type>::is_safe_convertible;
00883
00884 static const bool is_assignable = is_convertible;
00885 static const bool is_safe_assignable = is_safe_convertible;
00886 static const bool is_initializable = is_convertible;
00887 static const bool is_safe_initializable = is_safe_convertible;
00888 };
00889
00890
00892 template <typename T1, typename TE2>
00893 struct type_pair_traits<T1, rational<TE2> >
00894 : public type_pair_traits_for_unknown_and_rational<T1, rational<TE2> > {};
00895
00896
00898 template <typename TE1, typename TE2>
00899 struct type_pair_traits<rational<TE1>, rational<TE2> >
00900 : public type_pair_traits_for_similar_aggregates
00901 <rational<TE1>, rational<TE2> > {};
00902
00903
00905 template <typename TE>
00906 struct type_pair_traits<rational<TE>, rational<TE> >
00907 : public type_pair_traits_for_the_same
00908 <rational<TE>, rational<TE> > {};
00909
00910
00912 template <typename TE2>
00913 struct type_pair_traits<big_int, rational<TE2> >
00914 : public type_pair_traits_for_unknown_and_rational<big_int, rational<TE2> > {};
00915
00916
00918 template <typename TE1>
00919 struct type_pair_traits<rational<TE1>, big_int>
00920 {
00921 static const bool is_specialized =
00922 type_traits<TE1>::is_specialized &&
00923 type_traits<big_int>::is_specialized;
00924
00925 static const bool is_convertible =
00926 type_pair_traits<TE1, big_int>::is_convertible;
00927
00928 static const bool is_safe_convertible = false;
00929 static const bool is_assignable = is_convertible;
00930 static const bool is_safe_assignable = is_safe_convertible;
00931 static const bool is_initializable = is_convertible;
00932 static const bool is_safe_initializable = is_safe_convertible;
00933 };
00934
00936
00937
00938
00939
00940
00942 template <typename TE1, typename TE2, bool REFCNTE2>
00943 struct type_pair_traits<rational<TE1>, matrix<TE2, REFCNTE2> >
00944 : public type_pair_traits_for_unknown_and_vector_matrix
00945 <rational<TE1>, matrix<TE2, REFCNTE2> > {};
00946
00948 template <typename TE1, typename TE2, typename TD2, bool REFCNTE2>
00949 struct type_pair_traits<rational<TE1>, sparse_polynom<TE2, TD2, REFCNTE2> >
00950 : public type_pair_traits_for_unknown_and_polynom
00951 <rational<TE1>, sparse_polynom<TE2, TD2, REFCNTE2> > {};
00952
00953 #endif
00954
00955
00956 }
00957
00958
00959 #ifdef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE
00960 #define ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_RATIONAL
00961 #include "rational.cpp"
00962 #undef ARAGELI_INCLUDE_CPP_WITH_EXPORT_TEMPLATE_RATIONAL
00963 #endif
00964
00965
00966 #endif