algebramix_doc 0.3
/Users/mourrain/Devel/mmx/algebramix/include/algebramix/quotient.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Friends Defines