algebramix_doc 0.3
|
00001 00002 /****************************************************************************** 00003 * MODULE : quotient.hpp 00004 * DESCRIPTION: Fractions 00005 * COPYRIGHT : (C) 2007 Joris van der Hoeven and Gregoire Lecerf 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 Quotient quotient<NT,DT> 00022 TMPL class quotient; 00023 TMPL inline NT numerator (const Quotient& x); 00024 TMPL inline DT denominator (const Quotient& x); 00025 00026 /****************************************************************************** 00027 * Normalization helper 00028 ******************************************************************************/ 00029 00030 TMPL_DEF 00031 struct quotient_normalization_helper { 00032 static inline void normalize (NT& a, DT& b) {} 00033 }; 00034 00035 struct rational; 00036 template<typename C,typename V> struct polynomial; 00037 00038 template<typename V> 00039 struct quotient_normalization_helper<polynomial<rational,V>, 00040 polynomial<rational,V> > { 00041 static inline void normalize (polynomial<rational,V>& a, 00042 polynomial<rational,V>& b) { 00043 ASSERT (b != 0, "unexpected null denominator"); 00044 rational c= b [N(b)-1]; 00045 a= a / c; b= b / c; } 00046 }; 00047 00048 /****************************************************************************** 00049 * The quotient type 00050 ******************************************************************************/ 00051 00052 TMPL_DEF 00053 class quotient { 00054 MMX_ALLOCATORS; 00055 private: 00056 NT n; 00057 DT d; 00058 public: 00059 inline quotient (): n (0), d (1) {} 00060 template<typename T> inline quotient (const format<T>& fm): 00061 n (promote (0, fm)), d (promote (1, fm)) {} 00062 template<typename T> inline quotient (const T& x): 00063 n (x), d (1) {} 00064 template<typename NT2, typename DT2> 00065 inline quotient (const quotient<NT2,DT2>& x): 00066 n (numerator (x)), d (denominator (x)) {} 00067 template<typename NT2, typename DT2> inline 00068 quotient (const NT2& x, const DT2& y): 00069 n (x), d (y) { if (n == 0) d= 1; else 00070 quotient_normalization_helper<NT,DT>::normalize (n, d); } 00071 template<typename NT2, typename DT2> inline 00072 quotient (const NT2& x, const DT2& y, bool simplify): 00073 n (x), d (y) { 00074 assert (simplify); 00075 if (n == 0) 00076 d= 1; 00077 else { 00078 DT g= gcd (n, d); 00079 n /= g; 00080 d /= g; 00081 } 00082 quotient_normalization_helper<NT,DT>::normalize (n, d); } 00083 friend NT numerator LESSGTR (const Quotient& x); 00084 friend DT denominator LESSGTR (const Quotient& x); 00085 }; 00086 DEFINE_UNARY_FORMAT_2 (quotient) 00087 00088 STYPE_TO_TYPE(TMPL,scalar_type,Quotient,NT); 00089 UNARY_RETURN_TYPE(TMPL,numerator_op,Quotient,NT); 00090 UNARY_RETURN_TYPE(TMPL,denominator_op,Quotient,DT); 00091 00092 /****************************************************************************** 00093 * Basic routines 00094 ******************************************************************************/ 00095 00096 TMPL inline NT numerator (const Quotient& x) { return x.n; } 00097 TMPL inline DT denominator (const Quotient& x) { return x.d; } 00098 00099 TMPL inline format<NT> CF (const Quotient& x) { 00100 return get_format (numerator (x)); } 00101 00102 TMPL inline nat precision (const Quotient& x) { 00103 return max (precision (numerator (x)), precision (denominator (x))); } 00104 00105 /* FIXME: why does this not work? A compiler bug in gcc 2.95.3? 00106 template<typename Op, typename NT, typename DT> inline nat 00107 unary_hash (const Quotient& x) { 00108 nat h= Op::op (numerator (x)); 00109 return (h<<1) ^ (h<<5) ^ (h>>29) ^ Op::op (denominator (x)); 00110 } 00111 00112 template<typename Op, typename NT, typename DT> bool 00113 binary_test (const Quotient& x1, const Quotient& x2) { 00114 return Op::op (numerator (x1), numerator (x2)) && 00115 Op::op (denominator (x1), denominator (x2)); 00116 } 00117 00118 TRUE_IDENTITY_OP_SUGAR(TMPL,Quotient) 00119 EXACT_IDENTITY_OP_SUGAR(TMPL,Quotient) 00120 HARD_IDENTITY_OP_SUGAR(TMPL,Quotient) 00121 */ 00122 00123 template<typename S1, typename D> quotient<D,D> 00124 map (const function_1<D,Argument(S1) >& fun, const quotient<S1,S1>& x) { 00125 return quotient<D,D> (fun (numerator (x)), fun (denominator (x))); 00126 } 00127 00128 template<typename S1, typename D> quotient<D,D> 00129 map (D (*fun) (const S1&), const quotient<S1,S1>& x) { 00130 return quotient<D,D> (fun (numerator (x)), fun (denominator (x))); 00131 } 00132 00133 TMPL inline nat hash (const Quotient& x) { 00134 nat h= hash (numerator (x)); 00135 return (h<<1) ^ (h<<5) ^ (h>>29) ^ hash (denominator (x)); } 00136 TMPL inline nat exact_hash (const Quotient& x) { 00137 nat h= exact_hash (numerator (x)); 00138 return (h<<1) ^ (h<<5) ^ (h>>29) ^ exact_hash (denominator (x)); } 00139 TMPL inline nat hard_hash (const Quotient& x) { 00140 nat h= hard_hash (numerator (x)); 00141 return (h<<1) ^ (h<<5) ^ (h>>29) ^ hard_hash (denominator (x)); } 00142 TMPL inline bool operator == (const Quotient& x1, const Quotient& x2) { 00143 return numerator (x1) * denominator (x2) == 00144 numerator (x2) * denominator (x1); } 00145 TMPL inline bool operator != (const Quotient& x1, const Quotient& x2) { 00146 return !(x1 == x2); } 00147 TMPL inline bool exact_eq (const Quotient& x1, const Quotient& x2) { 00148 return exact_eq (numerator (x1), numerator (x2)) && 00149 exact_eq (denominator (x1), denominator (x2)); } 00150 TMPL inline bool exact_neq (const Quotient& x1, const Quotient& x2) { 00151 return !exact_eq (x1, x2); } 00152 TMPL inline bool hard_eq (const Quotient& x1, const Quotient& x2) { 00153 return hard_eq (numerator (x1), numerator (x2)) && 00154 hard_eq (denominator (x1), denominator (x2)); } 00155 TMPL inline bool hard_neq (const Quotient& x1, const Quotient& x2) { 00156 return !hard_eq (x1, x2); } 00157 00158 EQUAL_INT_SUGAR(TMPL,Quotient); 00159 00160 TMPL syntactic 00161 flatten (const Quotient& x) { 00162 return flatten (numerator (x)) / flatten (denominator (x)); 00163 } 00164 00165 TMPL 00166 struct binary_helper<Quotient >: public void_binary_helper<Quotient > { 00167 static inline string short_type_name () { 00168 return "Qu" * Short_type_name (NT) * Short_type_name (DT); } 00169 static inline generic full_type_name () { 00170 return gen ("Quotient", Full_type_name (NT), Full_type_name (DT)); } 00171 static inline generic disassemble (const Quotient& q) { 00172 return gen_vec (as<generic> (numerator (q)), 00173 as<generic> (denominator (q))); } 00174 static inline Quotient assemble (const generic& v) { 00175 return Quotient (as<NT> (vector_access (v, 0)), 00176 as<DT> (vector_access (v, 1))); } 00177 static inline void write (const port& out, const Quotient& q) { 00178 binary_write<NT> (out, numerator (q)); 00179 binary_write<DT> (out, denominator (q)); } 00180 static inline Quotient read (const port& in) { 00181 NT n= binary_read<NT> (in); 00182 DT d= binary_read<DT> (in); 00183 return Quotient (n, d); } 00184 }; 00185 00186 GCD_SUGAR(TMPL,Quotient) 00187 00188 /****************************************************************************** 00189 * Basic arithmetic 00190 ******************************************************************************/ 00191 00192 TMPL inline Quotient 00193 operator + (const Quotient& x1, const Quotient& x2) { 00194 DT g = gcd (denominator (x1), denominator(x2)); 00195 DT y1 = denominator (x1) / g; 00196 DT y2 = denominator (x2) / g; 00197 NT n = numerator(x1) * y2 + numerator(x2) * y1; 00198 DT h = gcd (g, n); 00199 return Quotient (n / h, (g / h) * y1 * y2); 00200 } 00201 00202 TMPL inline Quotient 00203 operator + (const Quotient& x1, const NT& x2) { 00204 return Quotient (numerator (x1) + x2 * denominator (x1), 00205 denominator (x1)); 00206 } 00207 00208 TMPL inline Quotient 00209 operator + (const NT& x1, const Quotient& x2) { 00210 return Quotient (x1 * denominator (x2) + numerator (x2), 00211 denominator (x2)); 00212 } 00213 00214 TMPL inline Quotient 00215 operator - (const Quotient& x) { 00216 return Quotient (-numerator (x), denominator (x)); 00217 } 00218 00219 TMPL inline Quotient 00220 operator - (const Quotient& x1, const Quotient& x2) { 00221 DT g = gcd (denominator (x1), denominator(x2)); 00222 DT y1 = denominator (x1) / g; 00223 DT y2 = denominator (x2) / g; 00224 NT n = numerator(x1) * y2 - numerator(x2) * y1; 00225 DT h = gcd (g, n); 00226 return Quotient (n / h, (g / h) * y1 * y2); 00227 } 00228 00229 TMPL inline Quotient 00230 operator - (const Quotient& x1, const NT& x2) { 00231 return Quotient (numerator (x1) - x2 * denominator (x1), 00232 denominator (x1)); 00233 } 00234 00235 TMPL inline Quotient 00236 operator - (const NT& x1, const Quotient& x2) { 00237 return Quotient (x1 * denominator (x2) - numerator (x2), 00238 denominator (x2)); 00239 } 00240 00241 TMPL inline Quotient 00242 operator * (const NT& c, const Quotient& x) { 00243 DT g = gcd (c, denominator (x)); 00244 return Quotient ((c / g) * numerator (x), denominator (x) / g); 00245 } 00246 00247 TMPL inline Quotient 00248 operator * (const Quotient& x, const NT& c) { 00249 DT g = gcd (c, denominator (x)); 00250 return Quotient (numerator (x) * (c / g), denominator (x) / g); 00251 } 00252 00253 TMPL inline Quotient 00254 operator * (const Quotient& x1, const Quotient& x2) { 00255 DT g1 = gcd (numerator (x1), denominator (x2)); 00256 DT g2 = gcd (numerator (x2), denominator (x1)); 00257 return Quotient ((numerator (x1) / g1) * (numerator (x2) / g2), 00258 (denominator (x1) / g2) * (denominator (x2) / g1)); 00259 } 00260 00261 TMPL inline Quotient 00262 operator / (const NT& c, const Quotient& x) { 00263 // assumes NT = DT 00264 ASSERT (numerator (x) != 0, "division by zero"); 00265 DT g= gcd (c, numerator (x)); 00266 return Quotient ((c / g) * denominator (x), numerator (x) / g); 00267 } 00268 00269 TMPL inline Quotient 00270 operator / (const Quotient& x, const DT& c) { 00271 ASSERT (c != 0, "division by zero"); 00272 DT g= gcd (numerator (x), c); 00273 return Quotient (numerator (x) / g, denominator (x) * (c / g)); 00274 } 00275 00276 TMPL inline Quotient 00277 operator / (const Quotient& x1, const Quotient& x2) { 00278 // assumes NT = DT 00279 ASSERT (numerator (x2) != 0, "division by zero"); 00280 NT g1= gcd (numerator (x1), numerator (x2)); 00281 DT g2= gcd (denominator (x1), denominator (x2)); 00282 return Quotient ((numerator (x1) / g1) * (denominator (x2) / g2), 00283 (denominator (x1) / g2) * (numerator (x2) / g1)); 00284 } 00285 00286 ARITH_SCALAR_INT_SUGAR(TMPL,Quotient); 00287 00288 /****************************************************************************** 00289 * Ordering 00290 ******************************************************************************/ 00291 00292 TMPL inline int 00293 sign (const Quotient& x) { 00294 return sign (numerator (x)) * sign (denominator (x)); 00295 } 00296 00297 COMPARE_SUGAR(TMPL,Quotient); 00298 COMPARE_INT_SUGAR(TMPL,Quotient); 00299 00300 /****************************************************************************** 00301 * Other operations 00302 ******************************************************************************/ 00303 00304 TMPL Quotient 00305 derive (const Quotient& x) { 00306 return Quotient (derive (numerator (x)) * denominator (x) - 00307 numerator (x) * derive (denominator (x)), 00308 square (denominator (x)), 00309 true); 00310 } 00311 00312 TMPL Quotient 00313 xderive (const Quotient& x) { 00314 return Quotient (xderive (numerator (x)) * denominator (x) - 00315 numerator (x) * xderive (denominator (x)), 00316 square (denominator (x)), 00317 true); 00318 } 00319 00320 template<typename NT, typename DT, typename VT> Quotient 00321 derive (const Quotient& x, const VT& v) { 00322 return Quotient (derive (numerator (x), v) * denominator (x) - 00323 numerator (x) * derive (denominator (x), v), 00324 square (denominator (x)), 00325 true); 00326 } 00327 00328 #undef TMPL_DEF 00329 #undef TMPL 00330 #undef Quotient 00331 } // namespace mmx 00332 #endif // __MMX_QUOTIENT__HPP