-/** Compute GCD of polynomials in Q[X] using the Euclidean algorithm (not
- * really suited for multivariate GCDs). This function is only provided for
- * testing purposes.
- *
- * @param a first multivariate polynomial
- * @param b second multivariate polynomial
- * @param x pointer to symbol (main variable) in which to compute the GCD in
- * @return the GCD as a new expression
- * @see gcd */
-
-static ex eu_gcd(const ex &a, const ex &b, const symbol *x)
-{
-//std::clog << "eu_gcd(" << a << "," << b << ")\n";
-
- // Sort c and d so that c has higher degree
- ex c, d;
- int adeg = a.degree(*x), bdeg = b.degree(*x);
- if (adeg >= bdeg) {
- c = a;
- d = b;
- } else {
- c = b;
- d = a;
- }
-
- // Normalize in Q[x]
- c = c / c.lcoeff(*x);
- d = d / d.lcoeff(*x);
-
- // Euclidean algorithm
- ex r;
- for (;;) {
-//std::clog << " d = " << d << endl;
- r = rem(c, d, *x, false);
- if (r.is_zero())
- return d / d.lcoeff(*x);
- c = d;
- d = r;
- }
-}
-
-
-/** Compute GCD of multivariate polynomials using the Euclidean PRS algorithm
- * with pseudo-remainders ("World's Worst GCD Algorithm", staying in Z[X]).
- * This function is only provided for testing purposes.
- *
- * @param a first multivariate polynomial
- * @param b second multivariate polynomial
- * @param x pointer to symbol (main variable) in which to compute the GCD in
- * @return the GCD as a new expression
- * @see gcd */
-
-static ex euprem_gcd(const ex &a, const ex &b, const symbol *x)
-{
-//std::clog << "euprem_gcd(" << a << "," << b << ")\n";
-
- // Sort c and d so that c has higher degree
- ex c, d;
- int adeg = a.degree(*x), bdeg = b.degree(*x);
- if (adeg >= bdeg) {
- c = a;
- d = b;
- } else {
- c = b;
- d = a;
- }
-
- // Calculate GCD of contents
- ex gamma = gcd(c.content(*x), d.content(*x), NULL, NULL, false);
-
- // Euclidean algorithm with pseudo-remainders
- ex r;
- for (;;) {
-//std::clog << " d = " << d << endl;
- r = prem(c, d, *x, false);
- if (r.is_zero())
- return d.primpart(*x) * gamma;
- c = d;
- d = r;
- }
-}
-
-
-/** Compute GCD of multivariate polynomials using the primitive Euclidean
- * PRS algorithm (complete content removal at each step). This function is
- * only provided for testing purposes.
- *
- * @param a first multivariate polynomial
- * @param b second multivariate polynomial
- * @param x pointer to symbol (main variable) in which to compute the GCD in
- * @return the GCD as a new expression
- * @see gcd */
-
-static ex peu_gcd(const ex &a, const ex &b, const symbol *x)
-{
-//std::clog << "peu_gcd(" << a << "," << b << ")\n";
-
- // Sort c and d so that c has higher degree
- ex c, d;
- int adeg = a.degree(*x), bdeg = b.degree(*x);
- int ddeg;
- if (adeg >= bdeg) {
- c = a;
- d = b;
- ddeg = bdeg;
- } else {
- c = b;
- d = a;
- ddeg = adeg;
- }
-
- // Remove content from c and d, to be attached to GCD later
- ex cont_c = c.content(*x);
- ex cont_d = d.content(*x);
- ex gamma = gcd(cont_c, cont_d, NULL, NULL, false);
- if (ddeg == 0)
- return gamma;
- c = c.primpart(*x, cont_c);
- d = d.primpart(*x, cont_d);
-
- // Euclidean algorithm with content removal
- ex r;
- for (;;) {
-//std::clog << " d = " << d << endl;
- r = prem(c, d, *x, false);
- if (r.is_zero())
- return gamma * d;
- c = d;
- d = r.primpart(*x);
- }
-}
-
-
-/** Compute GCD of multivariate polynomials using the reduced PRS algorithm.
- * This function is only provided for testing purposes.
- *
- * @param a first multivariate polynomial
- * @param b second multivariate polynomial
- * @param x pointer to symbol (main variable) in which to compute the GCD in
- * @return the GCD as a new expression
- * @see gcd */
-
-static ex red_gcd(const ex &a, const ex &b, const symbol *x)
-{
-//std::clog << "red_gcd(" << a << "," << b << ")\n";
-
- // Sort c and d so that c has higher degree
- ex c, d;
- int adeg = a.degree(*x), bdeg = b.degree(*x);
- int cdeg, ddeg;
- if (adeg >= bdeg) {
- c = a;
- d = b;
- cdeg = adeg;
- ddeg = bdeg;
- } else {
- c = b;
- d = a;
- cdeg = bdeg;
- ddeg = adeg;
- }
-
- // Remove content from c and d, to be attached to GCD later
- ex cont_c = c.content(*x);
- ex cont_d = d.content(*x);
- ex gamma = gcd(cont_c, cont_d, NULL, NULL, false);
- if (ddeg == 0)
- return gamma;
- c = c.primpart(*x, cont_c);
- d = d.primpart(*x, cont_d);
-
- // First element of divisor sequence
- ex r, ri = _ex1();
- int delta = cdeg - ddeg;
-
- for (;;) {
- // Calculate polynomial pseudo-remainder
-//std::clog << " d = " << d << endl;
- r = prem(c, d, *x, false);
- if (r.is_zero())
- return gamma * d.primpart(*x);
- c = d;
- cdeg = ddeg;
-
- if (!divide(r, pow(ri, delta), d, false))
- throw(std::runtime_error("invalid expression in red_gcd(), division failed"));
- ddeg = d.degree(*x);
- if (ddeg == 0) {
- if (is_ex_exactly_of_type(r, numeric))
- return gamma;
- else
- return gamma * r.primpart(*x);
- }
-
- ri = c.expand().lcoeff(*x);
- delta = cdeg - ddeg;
- }
-}
-
-