diff --git a/configure.ac b/configure.ac index e0dc5246..a75ffd5b 100644 --- a/configure.ac +++ b/configure.ac @@ -401,6 +401,17 @@ AC_ARG_WITH([flint], AS_IF([test "x$with_flint" != xno], [flag=: AS_IF([$flag], [AC_CHECK_HEADER([flint/flint.h], [], [flag=false])]) + AS_IF([$flag], + [AC_MSG_CHECKING([for a suitable FLINT version]) + AC_PREPROC_IFELSE([AC_LANG_SOURCE([[#include +#if __FLINT_RELEASE < 30200 +#error "FLINT version must be >= 3.2.0: https://github.com/form-dev/form/issues/679" +#endif]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_NOTICE([FLINT version 3.2.0 or higher is required]) + flag=false] + )]) AS_IF([$flag], [# Check how to link against the math library. AC_SEARCH_LIBS([pow], [m]) diff --git a/sources/declare.h b/sources/declare.h index 85e186f3..c3251054 100644 --- a/sources/declare.h +++ b/sources/declare.h @@ -1625,7 +1625,7 @@ extern WORD* flint_mul(PHEAD WORD *, WORD *); extern WORD* flint_ratfun_add(PHEAD WORD *, WORD *); extern int flint_ratfun_normalize(PHEAD WORD *); extern WORD* flint_rem(PHEAD WORD *, WORD *, const WORD); -extern void flint_startup_init(void); +extern void flint_check_version(void); #endif extern void optimize_print_code (int); diff --git a/sources/flintinterface.cc b/sources/flintinterface.cc index ea9a168f..0c4fa78c 100644 --- a/sources/flintinterface.cc +++ b/sources/flintinterface.cc @@ -1720,36 +1720,6 @@ void flint::ratfun_read_poly(const WORD *a, fmpz_poly_t num, fmpz_poly_t den) { } /* #] flint::ratfun_read_poly : - - #[ flint::startup_init : -*/ -// The purpose of this function is it work around threading issues in flint, reported in -// https://github.com/flintlib/flint/issues/1652 and fixed in -// https://github.com/flintlib/flint/pull/1658 . This implies versions prior to 3.1.0, -// but at least 3.0.0 (when gr was introduced). -void flint::startup_init(void) { - -#if __FLINT_RELEASE >= 30000 - // Here we initialize some gr contexts so that their method tables are populated. Crashes have - // otherwise been observed due to these two contexts in particular. - fmpz_t dummy_fmpz; - fmpz_init(dummy_fmpz); - fmpz_set_si(dummy_fmpz, 19); - - gr_ctx_t dummy_gr_ctx_fmpz_mod; - gr_ctx_init_fmpz_mod(dummy_gr_ctx_fmpz_mod, dummy_fmpz); - gr_ctx_clear(dummy_gr_ctx_fmpz_mod); - - gr_ctx_t dummy_gr_ctx_nmod; - gr_ctx_init_nmod(dummy_gr_ctx_nmod, 19); - gr_ctx_clear(dummy_gr_ctx_nmod); - - fmpz_clear(dummy_fmpz); -#endif -} -/* - #] flint::startup_init : - #[ flint::to_argument_mpoly : */ // Convert a fmpz_mpoly_t to a FORM argument (or 0-terminated list of terms: with_arghead==false). diff --git a/sources/flintinterface.h b/sources/flintinterface.h index 0d10e0b8..203c15dd 100644 --- a/sources/flintinterface.h +++ b/sources/flintinterface.h @@ -141,8 +141,6 @@ namespace flint { fmpz_mpoly_ctx_t); void ratfun_read_poly(const WORD *, fmpz_poly_t, fmpz_poly_t); - void startup_init(void); - uint64_t to_argument_mpoly(PHEAD WORD *, const bool, const bool, const bool, const uint64_t, const fmpz_mpoly_t, const var_map_t &, const fmpz_mpoly_ctx_t); uint64_t to_argument_mpoly(PHEAD WORD *, const bool, const bool, const bool, const uint64_t, diff --git a/sources/flintwrap.cc b/sources/flintwrap.cc index 35ba30a1..7a9b34a8 100644 --- a/sources/flintwrap.cc +++ b/sources/flintwrap.cc @@ -7,6 +7,7 @@ extern "C" { #include "form3.h" } +#include #include "flintinterface.h" @@ -282,11 +283,38 @@ WORD* flint_rem(PHEAD WORD *a, WORD *b, const WORD must_fit_term) { } /* #] flint_rem : - #[ flint_startup_init : + #[ flint_check_version : */ -void flint_startup_init(void) { - flint::startup_init(); + +/** + * Checks the FLINT library version at runtime. + * + * This function should be called at startup. + * The program will terminate if a known buggy version of FLINT is detected. + */ +void flint_check_version(void) { + bool ok = true; + std::stringstream ss(flint_version); + int major, minor, patch; + char dot1, dot2; + if ( ss >> major >> dot1 >> minor >> dot2 >> patch ) { + if ( dot1 != '.' || dot2 != '.' || major < 0 || minor < 0 || patch < 0 ) { + ok = false; + } + else if ( major * 10000 + minor * 100 + patch < 30200 ) { + // flint < 3.2.0: https://github.com/form-dev/form/issues/679 + ok = false; + } + } + else { + ok = false; + } + if ( !ok ) { + MesPrint("Bad FLINT version detected at runtime: %s",flint_version); + Terminate(-2); + } } + /* - #] flint_startup_init : + #] flint_check_version : */ diff --git a/sources/setfile.c b/sources/setfile.c index de2bea8e..6f75b3df 100644 --- a/sources/setfile.c +++ b/sources/setfile.c @@ -776,18 +776,6 @@ int AllocSetups(void) AM.TempDir = strDup1((UBYTE *)(sp->value),"tempdir"); } */ - -/* - As part of the setup, we possibly need to work around a flint multi-threading - bug which was fixed in version 3.1.0. This function should be called by the - master only, before the worker threads start processing terms. -*/ -#ifdef WITHFLINT -#if __FLINT_RELEASE < 30100 - flint_startup_init(); -#endif -#endif - return(error); } diff --git a/sources/startup.c b/sources/startup.c index 788e9c63..d6cdb62d 100644 --- a/sources/startup.c +++ b/sources/startup.c @@ -1739,6 +1739,9 @@ int main(int argc, char **argv) Globalize(1); #ifdef WITH_ALARM if ( AM.TimeLimit > 0 ) alarm(AM.TimeLimit); +#endif +#ifdef WITHFLINT + flint_check_version(); #endif TimeCPU(0); TimeChildren(0);