00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 #ifndef __MMX_QUOTIENT__HPP
00014 #define __MMX_QUOTIENT__HPP
00015 #include <basix/port.hpp>
00016 #include <basix/function.hpp>
00017 namespace mmx {
00018 struct std_quotient {};
00019 #define TMPL_DEF template<typename NT, typename DT>
00020 #define TMPL template<typename NT, typename DT>
00021 #define TMPLK template<typename NT, typename DT, typename K>
00022 #define Quotient quotient<NT,DT>
00023 TMPL class quotient;
00024 TMPL inline NT numerator (const Quotient& x);
00025 TMPL inline DT denominator (const Quotient& x);
00026 
00027 
00028 
00029 
00030 
00031 TMPL_DEF
00032 struct quotient_normalization_helper {
00033   static inline void normalize (NT& a, DT& b) {}
00034 };
00035 
00036 template<typename C,typename V> struct polynomial;
00037 
00038 template<typename C,typename V>
00039 struct quotient_normalization_helper<polynomial<C,V>,
00040                                      polynomial<C,V> > {
00041   static inline void normalize (polynomial<C,V>& a,
00042                                 polynomial<C,V>& b) {
00043     ASSERT (b != 0, "unexpected null denominator");
00044     C c= b [N(b)-1];
00045     if (is_invertible (c)) { a= a / c; b= b / c; } }
00046 };
00047 
00048 
00049 
00050 
00051 
00052 TMPL_DEF
00053 class quotient {
00054 MMX_ALLOCATORS;
00055 private:
00056   NT n;
00057   DT d;
00058 public:
00059   inline quotient ():
00060     n (), d (1) {}
00061   template<typename T> inline quotient (const format<T>& fm):
00062     n (promote (0, fm)), d (promote (1, fm)) {}
00063   template<typename T> inline quotient (const T& x):
00064     n (outplace_set_as<NT> (x)), d (outplace_set_as<DT> ((int) 1)) {}
00065   template<typename NT2, typename DT2>
00066   inline quotient (const quotient<NT2,DT2>& x):
00067     n (numerator (x)), d (denominator (x)) {}
00068   template<typename NT2, typename DT2> inline
00069   quotient (const NT2& x, const DT2& y):
00070     n (x), d (y) {
00071       if (n == promote (0, n)) d= promote (1, d);
00072       else quotient_normalization_helper<NT,DT>::normalize (n, d); }
00073   template<typename NT2, typename DT2> inline
00074   quotient (const NT2& x, const DT2& y, bool simplify):
00075     n (x), d (y) {
00076     assert (simplify);
00077     if (n == promote (0, n))
00078       d= promote (1, d);
00079     else {
00080       DT g= gcd (n, d);
00081       n /= g;
00082       d /= g;
00083     }
00084     quotient_normalization_helper<NT,DT>::normalize (n, d); }
00085   friend NT numerator LESSGTR (const Quotient& x);
00086   friend DT denominator LESSGTR (const Quotient& x);
00087 };
00088 DEFINE_UNARY_FORMAT_2 (quotient)
00089 
00090 STYPE_TO_TYPE(TMPL,scalar_type,Quotient,NT);
00091 UNARY_RETURN_TYPE(TMPL,numerator_op,Quotient,NT);
00092 UNARY_RETURN_TYPE(TMPL,denominator_op,Quotient,DT);
00093 
00094 
00095 
00096 
00097 
00098 TMPL inline NT numerator   (const Quotient& x) { return x.n; }
00099 TMPL inline DT denominator (const Quotient& x) { return x.d; }
00100 
00101 TMPL inline format<NT> CF (const Quotient& x) {
00102   return get_format (numerator (x)); }
00103 
00104 TMPL inline nat precision (const Quotient& x) {
00105   return max (precision (numerator (x)), precision (denominator (x))); }
00106 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 template<typename S1, typename D> quotient<D,D>
00126 map (const function_1<D,Argument(S1) >& fun, const quotient<S1,S1>& x) {
00127   return quotient<D,D> (fun (numerator (x)), fun (denominator (x)));
00128 }
00129 
00130 template<typename S1, typename D> quotient<D,D>
00131 map (D (*fun) (const S1&), const quotient<S1,S1>& x) {
00132   return quotient<D,D> (fun (numerator (x)), fun (denominator (x)));
00133 }
00134 
00135 TMPL inline nat hash (const Quotient& x) {
00136   nat h= hash (numerator (x));
00137   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hash (denominator (x)); }
00138 TMPL inline nat exact_hash (const Quotient& x) {
00139   nat h= exact_hash (numerator (x));
00140   return (h<<1) ^ (h<<5) ^ (h>>29) ^ exact_hash (denominator (x)); }
00141 TMPL inline nat hard_hash (const Quotient& x) {
00142   nat h= hard_hash (numerator (x));
00143   return (h<<1) ^ (h<<5) ^ (h>>29) ^ hard_hash (denominator (x)); }
00144 TMPL inline bool operator == (const Quotient& x1, const Quotient& x2) {
00145   return numerator (x1) * denominator (x2) ==
00146          numerator (x2) * denominator (x1); }
00147 TMPL inline bool operator != (const Quotient& x1, const Quotient& x2) {
00148   return !(x1 == x2); }
00149 TMPL inline bool exact_eq (const Quotient& x1, const Quotient& x2) {
00150   return exact_eq (numerator (x1), numerator (x2)) &&
00151          exact_eq (denominator (x1), denominator (x2)); }
00152 TMPL inline bool exact_neq (const Quotient& x1, const Quotient& x2) {
00153   return !exact_eq (x1, x2); }
00154 TMPL inline bool hard_eq (const Quotient& x1, const Quotient& x2) {
00155   return hard_eq (numerator (x1), numerator (x2)) &&
00156          hard_eq (denominator (x1), denominator (x2)); }
00157 TMPL inline bool hard_neq (const Quotient& x1, const Quotient& x2) {
00158   return !hard_eq (x1, x2); }
00159 
00160 EQUAL_INT_SUGAR(TMPL,Quotient);
00161 EQUAL_SCALAR_SUGAR(TMPL,Quotient,NT)
00162 EQUAL_SCALAR_SUGAR_BIS(TMPL,Quotient,NT)
00163 
00164 TMPL syntactic
00165 flatten (const Quotient& x) {
00166   return flatten (numerator (x)) / flatten (denominator (x));
00167 }
00168 
00169 TMPL
00170 struct binary_helper<Quotient >: public void_binary_helper<Quotient > {
00171   static inline string short_type_name () {
00172     return "Qu" * Short_type_name (NT) * Short_type_name (DT); }
00173   static inline generic full_type_name () {
00174     return gen ("Quotient", Full_type_name (NT), Full_type_name (DT)); }
00175   static inline generic disassemble (const Quotient& q) {
00176     return gen_vec (as<generic> (numerator (q)),
00177                     as<generic> (denominator (q))); }
00178   static inline Quotient assemble (const generic& v) {
00179     return Quotient (as<NT> (vector_access (v, 0)),
00180                      as<DT> (vector_access (v, 1))); }
00181   static inline void write (const port& out, const Quotient& q) {
00182     binary_write<NT> (out, numerator (q));
00183     binary_write<DT> (out, denominator (q)); }
00184   static inline Quotient read (const port& in) {
00185     NT n= binary_read<NT> (in);
00186     DT d= binary_read<DT> (in);
00187     return Quotient (n, d); }
00188 };
00189 
00190 GCD_SUGAR(TMPL,Quotient)
00191 
00192 
00193 
00194 
00195 
00196 TMPL inline Quotient
00197 operator + (const Quotient& x1, const Quotient& x2) {
00198   DT g  = gcd (denominator (x1), denominator(x2));
00199   DT y1 = denominator (x1) / g;
00200   DT y2 = denominator (x2) / g;
00201   NT n  = numerator(x1) * y2 + numerator(x2) * y1;
00202   DT h  = gcd (g, n);
00203   return Quotient (n / h, (g / h) * y1 * y2);
00204 }
00205 
00206 TMPL inline Quotient
00207 operator + (const Quotient& x1, const NT& x2) {
00208   return Quotient (numerator (x1) + x2 * denominator (x1),
00209                    denominator (x1));
00210 }
00211 
00212 TMPL inline Quotient
00213 operator + (const NT& x1, const Quotient& x2) {
00214   return Quotient (x1 * denominator (x2) + numerator (x2),
00215                    denominator (x2));
00216 }
00217 
00218 TMPL inline Quotient
00219 operator - (const Quotient& x) {
00220   return Quotient (-numerator (x), denominator (x));
00221 }
00222 
00223 TMPL inline Quotient
00224 operator - (const Quotient& x1, const Quotient& x2) {
00225   DT g  = gcd (denominator (x1), denominator(x2));
00226   DT y1 = denominator (x1) / g;
00227   DT y2 = denominator (x2) / g;
00228   NT n  = numerator(x1) * y2 - numerator(x2) * y1;
00229   DT h  = gcd (g, n);
00230   return Quotient (n / h, (g / h) * y1 * y2);
00231 }
00232 
00233 TMPL inline Quotient
00234 operator - (const Quotient& x1, const NT& x2) {
00235   return Quotient (numerator (x1) - x2 * denominator (x1),
00236                    denominator (x1));
00237 }
00238 
00239 TMPL inline Quotient
00240 operator - (const NT& x1, const Quotient& x2) {
00241   return Quotient (x1 * denominator (x2) - numerator (x2),
00242                    denominator (x2));
00243 }
00244 
00245 TMPL inline Quotient
00246 operator * (const NT& c, const Quotient& x) {
00247   DT g = gcd (c, denominator (x));
00248   return Quotient ((c / g) * numerator (x), denominator (x) / g);
00249 }
00250 
00251 TMPL inline Quotient
00252 operator * (const Quotient& x, const NT& c) {
00253   DT g = gcd (c, denominator (x));
00254   return Quotient (numerator (x) * (c / g), denominator (x) / g);
00255 }
00256 
00257 TMPL inline Quotient
00258 operator * (const Quotient& x1, const Quotient& x2) {
00259   DT g1 = gcd (numerator (x1), denominator (x2));
00260   DT g2 = gcd (numerator (x2), denominator (x1));
00261   return Quotient ((numerator (x1) / g1) * (numerator (x2) / g2),
00262                    (denominator (x1) / g2) * (denominator (x2) / g1));
00263 }
00264 
00265 TMPL inline Quotient
00266 operator / (const NT& c, const Quotient& x) {
00267   
00268   ASSERT (numerator (x) != 0, "division by zero");
00269   DT g= gcd (c, numerator (x));
00270   return Quotient ((c / g) * denominator (x), numerator (x) / g);
00271 }
00272 
00273 TMPL inline Quotient
00274 operator / (const Quotient& x, const DT& c) {
00275   ASSERT (c != 0, "division by zero");
00276   DT g= gcd (numerator (x), c);
00277   return Quotient (numerator (x) / g, denominator (x) * (c / g));
00278 }
00279 
00280 TMPL inline Quotient
00281 operator / (const Quotient& x1, const Quotient& x2) {
00282   
00283   ASSERT (numerator (x2) != 0, "division by zero");
00284   NT g1= gcd (numerator (x1), numerator (x2));
00285   DT g2= gcd (denominator (x1), denominator (x2));
00286   return Quotient ((numerator (x1) / g1) * (denominator (x2) / g2),
00287                    (denominator (x1) / g2) * (numerator (x2) / g1));
00288 }
00289 
00290 TMPL inline bool
00291 is_invertible (const Quotient& x) {
00292   return !is_exact_zero (x);  
00293 }
00294 
00295 ARITH_SCALAR_INT_SUGAR(TMPL,Quotient);
00296 
00297 
00298 
00299 
00300 
00301 TMPL inline int
00302 sign (const Quotient& x) {
00303   return sign (numerator (x)) * sign (denominator (x));
00304 }
00305 
00306 COMPARE_SUGAR(TMPL,Quotient);
00307 COMPARE_INT_SUGAR(TMPL,Quotient);
00308 COMPARE_SCALAR_SUGAR(TMPL,Quotient,NT)
00309 COMPARE_SCALAR_SUGAR_BIS(TMPL,Quotient,NT)
00310 
00311 
00312 
00313 
00314 
00315 TMPL Quotient
00316 derive (const Quotient& x) {
00317   return Quotient (derive (numerator (x)) * denominator (x) -
00318                    numerator (x) * derive (denominator (x)),
00319                    square (denominator (x)),
00320                    true);
00321 }
00322 
00323 TMPL Quotient
00324 xderive (const Quotient& x) {
00325   return Quotient (xderive (numerator (x)) * denominator (x) -
00326                    numerator (x) * xderive (denominator (x)),
00327                    square (denominator (x)),
00328                    true);
00329 }
00330 
00331 template<typename NT, typename DT, typename VT> Quotient
00332 derive (const Quotient& x, const VT& v) {
00333   return Quotient (derive (numerator (x), v) * denominator (x) -
00334                    numerator (x) * derive (denominator (x), v),
00335                    square (denominator (x)),
00336                    true);
00337 }
00338 
00339 
00340 
00341 
00342 
00343 BINARY_RETURN_TYPE(TMPLK,evaluate_op,Quotient,K,
00344                    Binary_return_type(evaluate_op,NT,K));
00345 
00346 TMPLK Binary_return_type(evaluate_op,Quotient,K)
00347 evaluate (const Quotient& x, const K& a) {
00348   return evaluate (numerator (x), a) / evaluate (denominator (x), a); } 
00349 
00350 TMPLK bool
00351 is_evaluable (const Quotient& x, const K& a, Evaluate_type(Quotient,K)& b) {
00352   Evaluate_type(NT,K) num= b;
00353   Evaluate_type(DT,K) den= b;
00354   if (!is_evaluable (numerator (x), a, num)) return false;
00355   if (!is_evaluable (denominator (x), a, den)) return false;
00356   if (is_exact_zero (den)) return false; 
00357   b= num / den; return true; }
00358 
00359 #undef TMPL_DEF
00360 #undef TMPL
00361 #undef TMPLK
00362 #undef Quotient
00363 } 
00364 #endif // __MMX_QUOTIENT__HPP