Skip to content

Commit 33e4743

Browse files
committed
Fix: match the sign conventions of poly gcd
1 parent b2adfa2 commit 33e4743

File tree

1 file changed

+71
-2
lines changed

1 file changed

+71
-2
lines changed

sources/flintinterface.cc

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,49 @@ WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_t
963963
Terminate(-1);
964964
}
965965

966-
fmpz_mpoly_gcd(gcd, pa, pb, ctx);
966+
// poly returns pa if pa == pb, regardless of the lcoeff sign
967+
if ( fmpz_mpoly_equal(pa, pb, ctx) ) {
968+
fmpz_mpoly_set(gcd, pa, ctx);
969+
}
970+
else {
971+
// We need some gymnastics to have the same sign conventions as the poly class. It takes the
972+
// integer or univar content out of a,b, with the convention that the content sign matches
973+
// the lcoeff sign. Since FORM has already taken out the content, we are left with +-1. In
974+
// Flint, the content always has a positive sign so here we should find +1. Check this:
975+
fmpz_mpoly_t tmp;
976+
fmpz_mpoly_init(tmp, ctx);
977+
fmpz_mpoly_term_content(tmp, pa, ctx);
978+
if ( fmpz_mpoly_is_one(tmp, ctx) != 1 ) {
979+
MLOCK(ErrorMessageLock);
980+
MesPrint("flint::gcd_mpoly: error: content of 1st arg != 1");
981+
MUNLOCK(ErrorMessageLock);
982+
Terminate(-1);
983+
}
984+
fmpz_mpoly_term_content(tmp, pb, ctx);
985+
if ( fmpz_mpoly_is_one(tmp, ctx) != 1 ) {
986+
MLOCK(ErrorMessageLock);
987+
MesPrint("flint::gcd_mpoly: error: content of 2nd arg != 1");
988+
MUNLOCK(ErrorMessageLock);
989+
Terminate(-1);
990+
}
991+
fmpz_mpoly_clear(tmp, ctx);
992+
993+
// The poly class now divides the content out of a,b so that they have a positive lcoeff.
994+
// Then it muliplies the final gcd (which is given a positive lcoeff also) by
995+
// gcd(cont a, cont b). There it has gcd(1,1) = gcd(-1,1) = gcd(1,-1) = 1, and
996+
// gcd(-1,-1) = -1 (because of the pa==pb early return). So: if both input polys have a
997+
// negative lcoeff, we will flip the sign in the final result.
998+
bool flip_sign = 0;
999+
if ( ( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pa, 0, ctx)) == -1 ) &&
1000+
( fmpz_sgn(fmpz_mpoly_term_coeff_ref(pb, 0, ctx)) == -1 ) ) {
1001+
flip_sign = 1;
1002+
}
1003+
1004+
fmpz_mpoly_gcd(gcd, pa, pb, ctx);
1005+
if ( flip_sign ) {
1006+
fmpz_mpoly_neg(gcd, gcd, ctx);
1007+
}
1008+
}
9671009

9681010
// This is freed by the caller
9691011
WORD *res;
@@ -1030,7 +1072,34 @@ WORD* flint::gcd_poly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_te
10301072
Terminate(-1);
10311073
}
10321074

1033-
fmpz_poly_gcd(gcd, pa, pb);
1075+
// poly returns pa if pa == pb, regardless of the lcoeff sign
1076+
if ( fmpz_poly_equal(pa, pb) ) {
1077+
fmpz_poly_set(gcd, pa);
1078+
}
1079+
else {
1080+
// Here, we don't have to make any sign flips like the mpoly case, because poly's
1081+
// integer_gcd(1,1) = integer_gcd(-1,1) = integer_gcd(1,-1) = integer_gcd(-1,-1) = +1.
1082+
// Still, verify that the content is 1:
1083+
fmpz_t tmp;
1084+
fmpz_init(tmp);
1085+
fmpz_poly_content(tmp, pa);
1086+
if ( fmpz_is_one(tmp) != 1 ) {
1087+
MLOCK(ErrorMessageLock);
1088+
MesPrint("flint::gcd_poly: error: content of 1st arg != 1");
1089+
MUNLOCK(ErrorMessageLock);
1090+
Terminate(-1);
1091+
}
1092+
fmpz_poly_content(tmp, pb);
1093+
if ( fmpz_is_one(tmp) != 1 ) {
1094+
MLOCK(ErrorMessageLock);
1095+
MesPrint("flint::gcd_poly: error: content of 2nd arg != 1");
1096+
MUNLOCK(ErrorMessageLock);
1097+
Terminate(-1);
1098+
}
1099+
fmpz_clear(tmp);
1100+
1101+
fmpz_poly_gcd(gcd, pa, pb);
1102+
}
10341103

10351104
// This is freed by the caller
10361105
WORD *res;

0 commit comments

Comments
 (0)