[GiNaC-devel] [PATCH] gcd: fix heuristics to chose main variable properly
Alexei Sheplyakov
varg at theor.jinr.ru
Mon Nov 20 20:01:40 CET 2006
Hello!
Heuristic code in gcd [very] often makes bad choice of the main variable.
In particular, if one of polynomials (say, p2) does not contain
the variable x which _is contained_ in another one (say, p1), than
gcd(p1, p2) will use such a variable as a main, so subsequent calculation
becomes unnecessary complicated. Fixing this substantially improves worst
case performance (less than minute versus infinity).
Best regards,
Alexei
--
All science is either physics or stamp collecting.
---
ginac/normal.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 43 insertions(+), 3 deletions(-)
diff --git a/ginac/normal.cpp b/ginac/normal.cpp
index b2a4e8c..1cbf3c2 100644
--- a/ginac/normal.cpp
+++ b/ginac/normal.cpp
@@ -1589,11 +1589,51 @@ factored_b:
}
}
+ if (is_exactly_a<numeric>(aex)) {
+ numeric bcont = bex.integer_content();
+ numeric g = gcd(ex_to<numeric>(aex), bcont);
+ if (ca)
+ *ca = ex_to<numeric>(aex)/g;
+ if (cb)
+ *cb = bex/g;
+ return g;
+ }
+
+ if (is_exactly_a<numeric>(bex)) {
+ numeric acont = aex.integer_content();
+ numeric g = gcd(ex_to<numeric>(bex), acont);
+ if (ca)
+ *ca = aex/g;
+ if (cb)
+ *cb = ex_to<numeric>(bex)/g;
+ return g;
+ }
+
// Gather symbol statistics
sym_desc_vec sym_stats;
get_symbol_stats(a, b, sym_stats);
- // The symbol with least degree is our main variable
+ // The symbol with least degree which is contained in both polynomials
+ // is our main variable
+ sym_desc_vec::iterator vari = sym_stats.begin();
+ while ( (vari != sym_stats.end()) &&
+ (((vari->ldeg_b == 0) && (vari->deg_b == 0)) ||
+ ((vari->ldeg_a == 0) && (vari->deg_a == 0))))
+ vari++;
+
+ // No common symbols at all, just return 1:
+ if (vari == sym_stats.end()) {
+ // N.B: keep cofactors factored
+ if (ca)
+ *ca = a;
+ if (cb)
+ *cb = b;
+ return _ex1;
+ }
+ // move symbols which contained only in one of the polynomials
+ // to the end:
+ rotate(sym_stats.begin(), vari, sym_stats.end());
+
sym_desc_vec::const_iterator var = sym_stats.begin();
const ex &x = var->sym;
@@ -1607,14 +1647,14 @@ factored_b:
}
// Try to eliminate variables
- if (var->deg_a == 0) {
+ if ((var->deg_a == 0) && (var->deg_b != 0)) {
ex bex_u, bex_c, bex_p;
bex.unitcontprim(x, bex_u, bex_c, bex_p);
ex g = gcd(aex, bex_c, ca, cb, false);
if (cb)
*cb *= bex_u * bex_p;
return g;
- } else if (var->deg_b == 0) {
+ } else if ((var->deg_b == 0) && (var->deg_a != 0)) {
ex aex_u, aex_c, aex_p;
aex.unitcontprim(x, aex_u, aex_c, aex_p);
ex g = gcd(aex_c, bex, ca, cb, false);
--
1.4.3.3
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 827 bytes
Desc: Digital signature
URL: <http://www.ginac.de/pipermail/ginac-devel/attachments/20061120/3a58c97c/attachment.sig>
More information about the GiNaC-devel
mailing list