]> www.ginac.de Git - ginac.git/blobdiff - ginac/factor.cpp
Add support for Texinfo-5.0.
[ginac.git] / ginac / factor.cpp
index b8a1fb8ed296dc0b2a5a573e9c390d984c6b1512..24f828cb793e9ad9d11e5104a4904d64345cd993 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 /*
- *  GiNaC Copyright (C) 1999-2009 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -218,8 +218,32 @@ static void expt_pos(umodpoly& a, unsigned int q)
        }
 }
 
+template<bool COND, typename T = void> struct enable_if
+{
+       typedef T type;
+};
+
+template<typename T> struct enable_if<false, T> { /* empty */ };
+
+template<typename T> struct uvar_poly_p
+{
+       static const bool value = false;
+};
+
+template<> struct uvar_poly_p<upoly>
+{
+       static const bool value = true;
+};
+
+template<> struct uvar_poly_p<umodpoly>
+{
+       static const bool value = true;
+};
+
 template<typename T>
-static T operator+(const T& a, const T& b)
+// Don't define this for anything but univariate polynomials.
+static typename enable_if<uvar_poly_p<T>::value, T>::type
+operator+(const T& a, const T& b)
 {
        int sa = a.size();
        int sb = b.size();
@@ -250,7 +274,11 @@ static T operator+(const T& a, const T& b)
 }
 
 template<typename T>
-static T operator-(const T& a, const T& b)
+// Don't define this for anything but univariate polynomials. Otherwise
+// overload resolution might fail (this actually happens when compiling
+// GiNaC with g++ 3.4).
+static typename enable_if<uvar_poly_p<T>::value, T>::type
+operator-(const T& a, const T& b)
 {
        int sa = a.size();
        int sb = b.size();
@@ -663,90 +691,75 @@ public:
        cl_MI operator()(size_t row, size_t col) const { return m[row*c + col]; }
        void mul_col(size_t col, const cl_MI x)
        {
-               mvec::iterator i = m.begin() + col;
                for ( size_t rc=0; rc<r; ++rc ) {
-                       *i = *i * x;
-                       i += c;
+                       std::size_t i = c*rc + col;
+                       m[i] = m[i] * x;
                }
        }
        void sub_col(size_t col1, size_t col2, const cl_MI fac)
        {
-               mvec::iterator i1 = m.begin() + col1;
-               mvec::iterator i2 = m.begin() + col2;
                for ( size_t rc=0; rc<r; ++rc ) {
-                       *i1 = *i1 - *i2 * fac;
-                       i1 += c;
-                       i2 += c;
+                       std::size_t i1 = col1 + c*rc;
+                       std::size_t i2 = col2 + c*rc;
+                       m[i1] = m[i1] - m[i2]*fac;
                }
        }
        void switch_col(size_t col1, size_t col2)
        {
-               cl_MI buf;
-               mvec::iterator i1 = m.begin() + col1;
-               mvec::iterator i2 = m.begin() + col2;
                for ( size_t rc=0; rc<r; ++rc ) {
-                       buf = *i1; *i1 = *i2; *i2 = buf;
-                       i1 += c;
-                       i2 += c;
+                       std::size_t i1 = col1 + rc*c;
+                       std::size_t i2 = col2 + rc*c;
+                       std::swap(m[i1], m[i2]);
                }
        }
        void mul_row(size_t row, const cl_MI x)
        {
-               vector<cl_MI>::iterator i = m.begin() + row*c;
                for ( size_t cc=0; cc<c; ++cc ) {
-                       *i = *i * x;
-                       ++i;
+                       std::size_t i = row*c + cc; 
+                       m[i] = m[i] * x;
                }
        }
        void sub_row(size_t row1, size_t row2, const cl_MI fac)
        {
-               vector<cl_MI>::iterator i1 = m.begin() + row1*c;
-               vector<cl_MI>::iterator i2 = m.begin() + row2*c;
                for ( size_t cc=0; cc<c; ++cc ) {
-                       *i1 = *i1 - *i2 * fac;
-                       ++i1;
-                       ++i2;
+                       std::size_t i1 = row1*c + cc;
+                       std::size_t i2 = row2*c + cc;
+                       m[i1] = m[i1] - m[i2]*fac;
                }
        }
        void switch_row(size_t row1, size_t row2)
        {
-               cl_MI buf;
-               vector<cl_MI>::iterator i1 = m.begin() + row1*c;
-               vector<cl_MI>::iterator i2 = m.begin() + row2*c;
                for ( size_t cc=0; cc<c; ++cc ) {
-                       buf = *i1; *i1 = *i2; *i2 = buf;
-                       ++i1;
-                       ++i2;
+                       std::size_t i1 = row1*c + cc;
+                       std::size_t i2 = row2*c + cc;
+                       std::swap(m[i1], m[i2]);
                }
        }
        bool is_col_zero(size_t col) const
        {
-               mvec::const_iterator i = m.begin() + col;
                for ( size_t rr=0; rr<r; ++rr ) {
-                       if ( !zerop(*i) ) {
+                       std::size_t i = col + rr*c;
+                       if ( !zerop(m[i]) ) {
                                return false;
                        }
-                       i += c;
                }
                return true;
        }
        bool is_row_zero(size_t row) const
        {
-               mvec::const_iterator i = m.begin() + row*c;
                for ( size_t cc=0; cc<c; ++cc ) {
-                       if ( !zerop(*i) ) {
+                       std::size_t i = row*c + cc;
+                       if ( !zerop(m[i]) ) {
                                return false;
                        }
-                       ++i;
                }
                return true;
        }
        void set_row(size_t row, const vector<cl_MI>& newrow)
        {
-               mvec::iterator i1 = m.begin() + row*c;
-               mvec::const_iterator i2 = newrow.begin(), end = newrow.end();
-               for ( ; i2 != end; ++i1, ++i2 ) {
-                       *i1 = *i2;
+               for (std::size_t i2 = 0; i2 < newrow.size(); ++i2) {
+                       std::size_t i1 = row*c + i2;
+                       m[i1] = newrow[i2];
                }
        }
        mvec::const_iterator row_begin(size_t row) const { return m.begin()+row*c; }
@@ -1496,7 +1509,17 @@ static ex factor_univariate(const ex& poly, const ex& x, unsigned int& prime)
        cl_modint_ring R;
        unsigned int trials = 0;
        unsigned int minfactors = 0;
-       cl_I lc = lcoeff(prim) * the<cl_I>(ex_to<numeric>(cont).to_cl_N());
+
+       const numeric& cont_n = ex_to<numeric>(cont);
+       cl_I i_cont;
+       if (cont_n.is_integer()) {
+               i_cont = the<cl_I>(cont_n.to_cl_N());
+       } else {
+               // poly \in Q[x] => poly = q ipoly, ipoly \in Z[x], q \in Q
+               // factor(poly) \equiv q factor(ipoly)
+               i_cont = cl_I(1);
+       }
+       cl_I lc = lcoeff(prim)*i_cont;
        upvec factors;
        while ( trials < 2 ) {
                umodpoly modpoly;