Skip to content

Commit b79cc4c

Browse files
committed
flint: perf: use mpoly for sparse univariate computations
This improves performance for things like "gcd_(1-x^20,1-x^1000000)" since FLINT poly has a dense representation whereas mpoly is sparse. "Real life" benchmarks such as forcer or minceex are unchanged, they have dense polynomials.
1 parent 7ed2880 commit b79cc4c

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

sources/flintinterface.cc

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ static_assert(sizeof(slong) == sizeof(int64_t), "flint interface expects slong i
3737
#] Types
3838
*/
3939

40+
/*
41+
* FLINT's univariate poly has a dense representation. For sufficiently sparse polynomials it is
42+
* faster to use mpoly instead, which is sparse. For a density <= this threshold we switch, where
43+
* the density defined as is "number of terms" / "maximum degree".
44+
*/
45+
#define UNIVARIATE_DENSITY_THR 0.02f
46+
4047
/*
4148
#[ flint::cleanup :
4249
*/
@@ -1061,7 +1068,9 @@ flint::var_map_t flint::get_variables(const vector <WORD *> &es, const bool with
10611068
const bool sort_vars) {
10621069

10631070
int32_t num_vars = 0;
1064-
// To be used if we sort by highest degree, as the polu code does.
1071+
// We count the total number of terms to determine "density".
1072+
uint32_t num_terms = 0;
1073+
// To be used if we sort by highest degree, as the poly code does.
10651074
vector<int32_t> degrees;
10661075
var_map_t var_map;
10671076

@@ -1071,8 +1080,10 @@ flint::var_map_t flint::get_variables(const vector <WORD *> &es, const bool with
10711080

10721081
// fast notation
10731082
if ( *e == -SNUMBER ) {
1083+
num_terms++;
10741084
}
10751085
else if ( *e == -SYMBOL ) {
1086+
num_terms++;
10761087
if ( !var_map.count(e[1]) ) {
10771088
var_map[e[1]] = num_vars++;
10781089
degrees.push_back(1);
@@ -1087,6 +1098,7 @@ flint::var_map_t flint::get_variables(const vector <WORD *> &es, const bool with
10871098
}
10881099
else {
10891100
for ( WORD i = with_arghead ? ARGHEAD:0; with_arghead ? i < e[0]:e[i] != 0; i += e[i] ) {
1101+
num_terms++;
10901102
if ( i+1 < i+e[i]-ABS(e[i+e[i]-1]) && e[i+1] != SYMBOL ) {
10911103
MLOCK(ErrorMessageLock);
10921104
MesPrint("ERROR: polynomials and polyratfuns must contain symbols only");
@@ -1152,6 +1164,16 @@ flint::var_map_t flint::get_variables(const vector <WORD *> &es, const bool with
11521164
}
11531165
}
11541166

1167+
if ( var_map.size() == 1 ) {
1168+
// In the univariate case, if the polynomials are sufficiently sparse force the use of the
1169+
// multivariate routines, which use a sparse representation, by adding a dummy map entry.
1170+
if ( (float)num_terms <= UNIVARIATE_DENSITY_THR * (float)degrees[0] ) {
1171+
// -1 will never be a symbol code. Built-in symbols from 0 to 19, and 20 is the first
1172+
// user symbol.
1173+
var_map[-1] = num_vars;
1174+
}
1175+
}
1176+
11551177
return var_map;
11561178
}
11571179
/*

0 commit comments

Comments
 (0)