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