diff --git a/check/fixes.frm b/check/fixes.frm index 14676cac..07ca8db7 100644 --- a/check/fixes.frm +++ b/check/fixes.frm @@ -1295,6 +1295,8 @@ assert succeeded? assert result("F") =~ expr("1") *--#] Issue126 : *--#[ Issue128 : +* The result check here requires the old prf sign convention: +On oldprfsign; * Rational arithmetic giving pi_ CF rat; PolyRatFun rat; diff --git a/doc/manual/statements.tex b/doc/manual/statements.tex index e0316ae2..55c27e83 100644 --- a/doc/manual/statements.tex +++ b/doc/manual/statements.tex @@ -3825,6 +3825,9 @@ \section{off} statement~\ref{substafactarg}\index{factarg} to the new mode of version 4 or later in which expressions in the argument of the mentioned function are completely factored over the rationals. The default is off.} + +\leftvitem{3.5cm}{oldprfsign\index{off!oldprfsign}} +\rightvitem{13cm}{\label{staoffoldprfsign} See \ref{staonoldprfsign}.} \leftvitem{3.5cm}{parallel\index{off!parallel}} \rightvitem{13cm}{Disallows the running of the program in parallel mode @@ -4044,6 +4047,12 @@ \section{on} version 4. This is a compatibility mode to allow oldprograms that rely on a specific working of the FactArg statement to still run. The default is off.} + +\leftvitem{3.5cm}{oldprfsign\index{on!oldprfsign}} +\rightvitem{13cm}{\label{staonoldprfsign} Forces the numerator/denominator +sign convention of PolyRatFun~\ref{substapolyratfun} of \FORM\ versions prior +to 5.1, when using FLINT for polynomial arithmetic. Enabling this leads to a +loss of performance in multivariate cases.} \leftvitem{3.5cm}{parallel\index{on!parallel}} \rightvitem{13cm}{Allows the running of the program in parallel mode unless diff --git a/sources/compcomm.c b/sources/compcomm.c index 07c7746d..ac38ead5 100644 --- a/sources/compcomm.c +++ b/sources/compcomm.c @@ -135,6 +135,7 @@ static KEYWORDV onoffoptions[] = { ,{"oldfactarg", &(AC.OldFactArgFlag), 1, 0} ,{"memdebugflag", &(AC.MemDebugFlag), 1, 0} ,{"oldgcd", &(AC.OldGCDflag), 1, 0} + ,{"oldprfsign", &(AC.OldPRFSignFlag), 1, 0} ,{"innertest", &(AC.InnerTest), 1, 0} ,{"wtimestats", &(AC.WTimeStatsFlag), 1, 0} ,{"sortreallocate", &(AC.SortReallocateFlag), 1, 0} diff --git a/sources/flintinterface.cc b/sources/flintinterface.cc index 2d736839..afe6aa98 100644 --- a/sources/flintinterface.cc +++ b/sources/flintinterface.cc @@ -89,7 +89,7 @@ void flint::cleanup_master(void) { #[ flint::divmod_mpoly : */ WORD* flint::divmod_mpoly(PHEAD const WORD *a, const WORD *b, const bool return_rem, - const WORD must_fit_term, const var_map_t &var_map) { + const WORD must_fit_term, const var_map_t &var_map, const bool sort_vars) { flint::mpoly_ctx ctx(var_map.size()); flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d); @@ -133,10 +133,10 @@ WORD* flint::divmod_mpoly(PHEAD const WORD *a, const WORD *b, const bool return_ const uint64_t prev_size = 0; const uint64_t out_size = return_rem ? (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size, - rem.d, var_map, ctx.d, scale.d) + rem.d, var_map, ctx.d, sort_vars, scale.d) : (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, must_fit_term, write, prev_size, - div.d, var_map, ctx.d, scale.d) + div.d, var_map, ctx.d, sort_vars, scale.d) ; WORD* res = (WORD *)Malloc1(sizeof(WORD)*out_size, "flint::divrem_mpoly"); @@ -145,11 +145,11 @@ WORD* flint::divmod_mpoly(PHEAD const WORD *a, const WORD *b, const bool return_ write = true; if ( return_rem ) { (uint64_t)flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, - rem.d, var_map, ctx.d, scale.d); + rem.d, var_map, ctx.d, sort_vars, scale.d); } else { (uint64_t)flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, - div.d, var_map, ctx.d, scale.d); + div.d, var_map, ctx.d, sort_vars, scale.d); } return res; @@ -233,7 +233,7 @@ WORD* flint::divmod_poly(PHEAD const WORD *a, const WORD *b, const bool return_r #[ flint::factorize_mpoly : */ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool with_arghead, - const bool is_fun_arg, const var_map_t &var_map) { + const bool is_fun_arg, const var_map_t &var_map, const bool sort_vars) { flint::mpoly_ctx ctx(var_map.size()); flint::mpoly arg(ctx.d), den(ctx.d), base(ctx.d); @@ -276,8 +276,9 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w uint64_t output_size = 1; // For finding the highest symbol, in FORM's lexicographic ordering - var_map_t var_map_inv; - for ( auto x: var_map ) { + vector var_map_inv; + var_map_inv.resize(var_map.size()); + for ( auto x : var_map ) { var_map_inv[x.second] = x.first; } @@ -301,10 +302,10 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w fmpz_mpoly_get_term_exp_si((slong*)base_term_exponents.data(), base.d, (slong)j, ctx.d); for ( size_t k = 0; k < var_map.size(); k++ ) { - if ( base_term_exponents[k] > 0 && ( var_map_inv.at(k) > max_var || - ( var_map_inv.at(k) == max_var && base_term_exponents[k] > max_pow ) ) ) { + if ( base_term_exponents[k] > 0 && ( var_map_inv[k] > max_var || + ( var_map_inv[k] == max_var && base_term_exponents[k] > max_pow ) ) ) { - max_var = var_map_inv.at(k); + max_var = var_map_inv[k]; max_pow = base_term_exponents[k]; base_sign[i] = fmpz_sgn(fmpz_mpoly_term_coeff_ref(base.d, j, ctx.d)); } @@ -321,7 +322,7 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w const bool write = false; for ( int64_t j = 0; j < exponent; j++ ) { output_size += (uint64_t)flint::to_argument_mpoly(BHEAD NULL, with_arghead, - is_fun_arg, write, 0, base.d, var_map, ctx.d); + is_fun_arg, write, 0, base.d, var_map, ctx.d, sort_vars); } } } @@ -368,7 +369,7 @@ WORD* flint::factorize_mpoly(PHEAD const WORD *argin, WORD *argout, const bool w const bool write = true; for ( int64_t j = 0; j < exponent; j++ ) { argout += flint::to_argument_mpoly(BHEAD argout, with_arghead, is_fun_arg, write, - argout-old_argout, base.d, var_map, ctx.d); + argout-old_argout, base.d, var_map, ctx.d, sort_vars); } } // Final trailing zero to denote the end of the factors. @@ -548,6 +549,7 @@ uint64_t flint::from_argument_mpoly(fmpz_mpoly_t poly, fmpz_mpoly_t denpoly, con // Search for numerical or symbol denominators to create "denpoly". flint::fmpz den_coeff, tmp; fmpz_set_si(den_coeff.d, 1); + vector exponents(var_map.size(), 0); vector neg_exponents(var_map.size(), 0); for ( const WORD* term = args; term < arg_stop; term += term[0] ) { @@ -599,7 +601,7 @@ uint64_t flint::from_argument_mpoly(fmpz_mpoly_t poly, fmpz_mpoly_t denpoly, con const WORD* symbol_stop = term_stop - ABS(coeff_size); const WORD* t = term; - vector exponents(var_map.size(), 0); + fill(exponents.begin(), exponents.end(), 0); t++; // skip over the total size entry if ( t == symbol_stop ) { @@ -913,7 +915,7 @@ void flint::fmpz_set_form(fmpz_t z, UWORD *a, WORD na) { // If must_fit_term, this should be a TermMalloc buffer. Otherwise Malloc1 the buffer. // For multi-variate cases. WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_term, - const var_map_t &var_map) { + const var_map_t &var_map, const bool sort_vars) { flint::mpoly_ctx ctx(var_map.size()); flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d), gcd(ctx.d); @@ -988,7 +990,7 @@ WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_t const bool write = false; const uint64_t prev_size = 0; const uint64_t gcd_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL, - with_arghead, must_fit_term, write, prev_size, gcd.d, var_map, ctx.d); + with_arghead, must_fit_term, write, prev_size, gcd.d, var_map, ctx.d, sort_vars); res = (WORD *)Malloc1(sizeof(WORD)*gcd_size, "flint::gcd_mpoly"); } @@ -997,7 +999,7 @@ WORD* flint::gcd_mpoly(PHEAD const WORD *a, const WORD *b, const WORD must_fit_t const bool write = true; const uint64_t prev_size = 0; flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, gcd.d, - var_map, ctx.d); + var_map, ctx.d, sort_vars); return res; } @@ -1125,20 +1127,25 @@ flint::var_map_t flint::get_variables(const vector &es, const bool with else { for ( WORD i = with_arghead ? ARGHEAD:0; with_arghead ? i < e[0]:e[i] != 0; i += e[i] ) { num_terms++; - if ( i+1 < i+e[i]-ABS(e[i+e[i]-1]) && e[i+1] != SYMBOL ) { + const WORD coeff_size = e[i+e[i]-1]; + const WORD symbols_size = e[i] - ABS(coeff_size); + if ( e[i+1] != SYMBOL && 1 < symbols_size ) { MLOCK(ErrorMessageLock); MesPrint("ERROR: polynomials and polyratfuns must contain symbols only"); MUNLOCK(ErrorMessageLock); Terminate(1); } - for ( WORD j = i+3; jsecond] = MaX(degrees[it->second], degree); } } } @@ -1283,7 +1290,8 @@ WORD* flint::inverse_poly(PHEAD const WORD *a, const WORD *b, const var_map_t &v */ // Return a pointer to a buffer containing the product of the 0-terminated term lists at a and b. // For multi-variate cases. -WORD* flint::mul_mpoly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_map) { +WORD* flint::mul_mpoly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_map, + const bool sort_vars) { flint::mpoly_ctx ctx(var_map.size()); flint::mpoly pa(ctx.d), pb(ctx.d), denpa(ctx.d), denpb(ctx.d); @@ -1320,12 +1328,12 @@ WORD* flint::mul_mpoly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_ const bool must_fit_term = false; const uint64_t prev_size = 0; const uint64_t mul_size = (uint64_t)flint::to_argument_mpoly(BHEAD NULL, - with_arghead, must_fit_term, write, prev_size, pa.d, var_map, ctx.d, den.d); + with_arghead, must_fit_term, write, prev_size, pa.d, var_map, ctx.d, sort_vars, den.d); res = (WORD*)Malloc1(sizeof(WORD)*mul_size, "flint::mul_mpoly"); write = true; flint::to_argument_mpoly(BHEAD res, with_arghead, must_fit_term, write, prev_size, pa.d, - var_map, ctx.d, den.d); + var_map, ctx.d, sort_vars, den.d); return res; } @@ -1387,7 +1395,7 @@ WORD* flint::mul_poly(PHEAD const WORD *a, const WORD *b, const var_map_t &var_m */ // Add the multi-variate FORM rational polynomials at t1 and t2. The result is written at out. void flint::ratfun_add_mpoly(PHEAD const WORD *t1, const WORD *t2, WORD *out, - const var_map_t &var_map) { + const var_map_t &var_map, const bool sort_vars) { flint::mpoly_ctx ctx(var_map.size()); flint::mpoly gcd(ctx.d), num1(ctx.d), den1(ctx.d), num2(ctx.d), den2(ctx.d); @@ -1426,9 +1434,9 @@ void flint::ratfun_add_mpoly(PHEAD const WORD *t1, const WORD *t2, WORD *out, const bool write = true; // prev_size + 4, to account for final term size and coeff of "1/1" out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4, - num1.d, var_map, ctx.d); + num1.d, var_map, ctx.d, sort_vars); out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-args_size+4, - den1.d, var_map, ctx.d); + den1.d, var_map, ctx.d, sort_vars); *args_size = out - args_size + 1; // The +1 is to include the function ID AT.WorkPointer = out; @@ -1491,7 +1499,8 @@ void flint::ratfun_add_poly(PHEAD const WORD *t1, const WORD *t2, WORD *out, */ // Multiply and simplify occurrences of the multi-variate FORM rational polynomials found in term. // The final term is written in place, with the rational polynomial at the end. -void flint::ratfun_normalize_mpoly(PHEAD WORD *term, const var_map_t &var_map) { +void flint::ratfun_normalize_mpoly(PHEAD WORD *term, const var_map_t &var_map, + const bool sort_vars) { // The length of the coefficient const WORD ncoeff = (term + *term)[-1]; @@ -1548,9 +1557,9 @@ void flint::ratfun_normalize_mpoly(PHEAD WORD *term, const var_map_t &var_map) { const bool must_fit_term = true; const bool write = true; out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size, - num1.d, var_map, ctx.d); + num1.d, var_map, ctx.d, sort_vars); out += flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, out-term_size, - den1.d, var_map, ctx.d); + den1.d, var_map, ctx.d, sort_vars); *args_size = out - args_size + 1; // The +1 is to include the function ID @@ -1779,7 +1788,8 @@ void flint::ratfun_read_poly(const WORD *a, fmpz_poly_t num, fmpz_poly_t den) { #define IFW(x) { if ( write ) {x;} } uint64_t flint::to_argument_mpoly(PHEAD WORD *out, const bool with_arghead, const bool must_fit_term, const bool write, const uint64_t prev_size, const fmpz_mpoly_t poly, - const var_map_t &var_map, const fmpz_mpoly_ctx_t ctx, const fmpz_t denscale) { + const var_map_t &var_map, const fmpz_mpoly_ctx_t ctx, const bool sort_vars, + const fmpz_t denscale) { // out is modified later, keep the pointer at entry const WORD* out_entry = out; @@ -1797,8 +1807,9 @@ uint64_t flint::to_argument_mpoly(PHEAD WORD *out, const bool with_arghead, } // Create the inverse of var_map, so we don't have to search it for each symbol written - var_map_t var_map_inv; - for ( auto x: var_map ) { + vector var_map_inv; + var_map_inv.resize(var_map.size()); + for ( auto x : var_map ) { var_map_inv[x.second] = x.first; } @@ -1956,8 +1967,10 @@ uint64_t flint::to_argument_mpoly(PHEAD WORD *out, const bool with_arghead, if ( with_arghead ) { IFW(*arg_size = out - arg_size); - if ( write ) { - // Sort into form highfirst ordering + if ( write && sort_vars ) { + // Sort into form highfirst ordering, if we have potentially re-ordered the variables by + // degree, in flint::get_variables. Otherwise, we can rely on FLINT's sorting with + // ORD_LEX and the variables ordered in FORM's lexicographic order. flint::form_sort(BHEAD (WORD*)(out_entry)); } } @@ -1975,13 +1988,13 @@ uint64_t flint::to_argument_mpoly(PHEAD WORD *out, const bool with_arghead, // If no denscale argument is supplied, just set it to 1 and call the usual function uint64_t flint::to_argument_mpoly(PHEAD WORD *out, const bool with_arghead, const bool must_fit_term, const bool write, const uint64_t prev_size, const fmpz_mpoly_t poly, - const var_map_t &var_map, const fmpz_mpoly_ctx_t ctx) { + const var_map_t &var_map, const fmpz_mpoly_ctx_t ctx, const bool sort_vars) { flint::fmpz tmp; fmpz_set_ui(tmp.d, 1); uint64_t ret = flint::to_argument_mpoly(BHEAD out, with_arghead, must_fit_term, write, - prev_size, poly, var_map, ctx, tmp.d); + prev_size, poly, var_map, ctx, sort_vars, tmp.d); return ret; } @@ -2012,8 +2025,9 @@ uint64_t flint::to_argument_poly(PHEAD WORD *out, const bool with_arghead, } // Create the inverse of var_map, so we don't have to search it for each symbol written - var_map_t var_map_inv; - for ( auto x: var_map ) { + vector var_map_inv; + var_map_inv.resize(var_map.size()); + for ( auto x : var_map ) { var_map_inv[x.second] = x.first; } diff --git a/sources/flintinterface.h b/sources/flintinterface.h index 88386b0f..a3a70b98 100644 --- a/sources/flintinterface.h +++ b/sources/flintinterface.h @@ -65,6 +65,7 @@ extern "C" { // The bits of std that are needed: using std::cout; using std::endl; +using std::fill; using std::map; using std::swap; using std::string; @@ -132,10 +133,12 @@ namespace flint { void cleanup(void); void cleanup_master(void); - WORD* divmod_mpoly(PHEAD const WORD *, const WORD *, const bool, const WORD, const var_map_t &); + WORD* divmod_mpoly(PHEAD const WORD *, const WORD *, const bool, const WORD, const var_map_t &, + const bool); WORD* divmod_poly(PHEAD const WORD *, const WORD *, const bool, const WORD, const var_map_t &); - WORD* factorize_mpoly(PHEAD const WORD *, WORD *, const bool, const bool, const var_map_t &); + WORD* factorize_mpoly(PHEAD const WORD *, WORD *, const bool, const bool, const var_map_t &, + const bool); WORD* factorize_poly(PHEAD const WORD *, WORD *, const bool, const bool, const var_map_t &); void form_sort(PHEAD WORD *); @@ -147,20 +150,20 @@ namespace flint { WORD fmpz_get_form(fmpz_t, WORD *); void fmpz_set_form(fmpz_t, UWORD *, WORD); - WORD* gcd_mpoly(PHEAD const WORD *, const WORD *, const WORD, const var_map_t &); + WORD* gcd_mpoly(PHEAD const WORD *, const WORD *, const WORD, const var_map_t &, const bool); WORD* gcd_poly(PHEAD const WORD *, const WORD *, const WORD, const var_map_t &); var_map_t get_variables(const vector &, const bool, const bool); WORD* inverse_poly(PHEAD const WORD *, const WORD *, const var_map_t &); - WORD* mul_mpoly(PHEAD const WORD *, const WORD *, const var_map_t &); + WORD* mul_mpoly(PHEAD const WORD *, const WORD *, const var_map_t &, const bool); WORD* mul_poly(PHEAD const WORD *, const WORD *, const var_map_t &); - void ratfun_add_mpoly(PHEAD const WORD *, const WORD *, WORD *, const var_map_t &); + void ratfun_add_mpoly(PHEAD const WORD *, const WORD *, WORD *, const var_map_t &, const bool); void ratfun_add_poly(PHEAD const WORD *, const WORD *, WORD *, const var_map_t &); - void ratfun_normalize_mpoly(PHEAD WORD *, const var_map_t &); + void ratfun_normalize_mpoly(PHEAD WORD *, const var_map_t &, const bool); void ratfun_normalize_poly(PHEAD WORD *, const var_map_t &); void ratfun_read_mpoly(const WORD *, fmpz_mpoly_t, fmpz_mpoly_t, const var_map_t &, @@ -168,9 +171,9 @@ namespace flint { void ratfun_read_poly(const WORD *, fmpz_poly_t, fmpz_poly_t); 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); + const fmpz_mpoly_t, const var_map_t &, const fmpz_mpoly_ctx_t, const bool); 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, const fmpz_t); + const fmpz_mpoly_t, const var_map_t &, const fmpz_mpoly_ctx_t, const bool, const fmpz_t); uint64_t to_argument_poly(PHEAD WORD *, const bool, const bool, const bool, const uint64_t, const fmpz_poly_t, const var_map_t &); uint64_t to_argument_poly(PHEAD WORD *, const bool, const bool, const bool, const uint64_t, diff --git a/sources/flintwrap.cc b/sources/flintwrap.cc index 83d97530..43937941 100644 --- a/sources/flintwrap.cc +++ b/sources/flintwrap.cc @@ -66,7 +66,7 @@ WORD* flint_div(PHEAD WORD *a, WORD *b, const WORD must_fit_term) { const bool return_rem = false; if ( var_map.size() > 1 ) { - return flint::divmod_mpoly(BHEAD a, b, return_rem, must_fit_term, var_map); + return flint::divmod_mpoly(BHEAD a, b, return_rem, must_fit_term, var_map, sort_vars); } else { return flint::divmod_poly(BHEAD a, b, return_rem, must_fit_term, var_map); @@ -85,7 +85,7 @@ int flint_factorize_argument(PHEAD WORD *argin, WORD *argout) { const bool is_fun_arg = true; if ( var_map.size() > 1 ) { - flint::factorize_mpoly(BHEAD argin, argout, with_arghead, is_fun_arg, var_map); + flint::factorize_mpoly(BHEAD argin, argout, with_arghead, is_fun_arg, var_map, sort_vars); } else { flint::factorize_poly(BHEAD argin, argout, with_arghead, is_fun_arg, var_map); @@ -106,7 +106,7 @@ WORD* flint_factorize_dollar(PHEAD WORD *argin) { const bool is_fun_arg = false; if ( var_map.size() > 1 ) { - return flint::factorize_mpoly(BHEAD argin, NULL, with_arghead, is_fun_arg, var_map); + return flint::factorize_mpoly(BHEAD argin, NULL, with_arghead, is_fun_arg, var_map, sort_vars); } else { return flint::factorize_poly(BHEAD argin, NULL, with_arghead, is_fun_arg, var_map); @@ -127,7 +127,7 @@ WORD* flint_gcd(PHEAD WORD *a, WORD *b, const WORD must_fit_term) { const flint::var_map_t var_map = flint::get_variables(e, with_arghead, sort_vars); if ( var_map.size() > 1 ) { - return flint::gcd_mpoly(BHEAD a, b, must_fit_term, var_map); + return flint::gcd_mpoly(BHEAD a, b, must_fit_term, var_map, sort_vars); } else { return flint::gcd_poly(BHEAD a, b, must_fit_term, var_map); @@ -164,10 +164,12 @@ WORD* flint_mul(PHEAD WORD *a, WORD *b) { e.reserve(2); e.push_back(a); e.push_back(b); - const flint::var_map_t var_map = flint::get_variables(e, false, false); + const bool with_arghead = false; + const bool sort_vars = false; + const flint::var_map_t var_map = flint::get_variables(e, with_arghead, sort_vars); if ( var_map.size() > 1 ) { - return flint::mul_mpoly(BHEAD a, b, var_map); + return flint::mul_mpoly(BHEAD a, b, var_map, sort_vars); } else { return flint::mul_poly(BHEAD a, b, var_map); @@ -200,11 +202,11 @@ WORD* flint_ratfun_add(PHEAD WORD *t1, WORD *t2) { NEXTARG(t); } const bool with_arghead = true; - const bool sort_vars = true; + const bool sort_vars = AC.OldPRFSignFlag ? true : false; const flint::var_map_t var_map = flint::get_variables(e, with_arghead, sort_vars); if ( var_map.size() > 1 ) { - flint::ratfun_add_mpoly(BHEAD t1, t2, oldworkpointer, var_map); + flint::ratfun_add_mpoly(BHEAD t1, t2, oldworkpointer, var_map, sort_vars); } else { flint::ratfun_add_poly(BHEAD t1, t2, oldworkpointer, var_map); @@ -266,11 +268,11 @@ int flint_ratfun_normalize(PHEAD WORD *term) { } } const bool with_arghead = true; - const bool sort_vars = true; + const bool sort_vars = AC.OldPRFSignFlag ? true : false; const flint::var_map_t var_map = flint::get_variables(e, with_arghead, sort_vars); if ( var_map.size() > 1 ) { - flint::ratfun_normalize_mpoly(BHEAD term, var_map); + flint::ratfun_normalize_mpoly(BHEAD term, var_map, sort_vars); } else { flint::ratfun_normalize_poly(BHEAD term, var_map); @@ -301,7 +303,7 @@ WORD* flint_rem(PHEAD WORD *a, WORD *b, const WORD must_fit_term) { const bool return_rem = true; if ( var_map.size() > 1 ) { - return flint::divmod_mpoly(BHEAD a, b, return_rem, must_fit_term, var_map); + return flint::divmod_mpoly(BHEAD a, b, return_rem, must_fit_term, var_map, sort_vars); } else { return flint::divmod_poly(BHEAD a, b, return_rem, must_fit_term, var_map); diff --git a/sources/normal.c b/sources/normal.c index a435944b..2c4e50c7 100644 --- a/sources/normal.c +++ b/sources/normal.c @@ -5208,10 +5208,12 @@ int SymbolNormalize(WORD *term) while ( t < tstop ) { /* Step 1: collect symbols */ if ( *t == SYMBOL && t < tstop ) { for ( i = 2; i < t[1]; i += 2 ) { + const WORD sym = t[i]; + const WORD pow = t[i+1]; bb = buffer+2; while ( bb < b ) { - if ( bb[0] == t[i] ) { /* add powers */ - bb[1] += t[i+1]; + if ( bb[0] == sym ) { /* add powers */ + bb[1] += pow; if ( bb[1] > MAXPOWER || bb[1] < -MAXPOWER ) { MLOCK(ErrorMessageLock); MesPrint("Power in SymbolNormalize out of range"); @@ -5226,18 +5228,18 @@ int SymbolNormalize(WORD *term) } goto Nexti; } - else if ( bb[0] > t[i] ) { /* insert it */ + else if ( bb[0] > sym ) { /* insert it */ m = b; while ( m > bb ) { m[1] = m[-1]; m[0] = m[-2]; m -= 2; } b += 2; - bb[0] = t[i]; - bb[1] = t[i+1]; + bb[0] = sym; + bb[1] = pow; goto Nexti; } bb += 2; } if ( bb >= b ) { /* add it to the end */ - *b++ = t[i]; *b++ = t[i+1]; + *b++ = sym; *b++ = pow; } Nexti:; } diff --git a/sources/setfile.c b/sources/setfile.c index 33bd3dbe..d15bb654 100644 --- a/sources/setfile.c +++ b/sources/setfile.c @@ -89,6 +89,7 @@ SETUPPARAMETERS setupparameters[] = ,{(UBYTE *)"oldgcd", ONOFFVALUE, 0, (LONG)1} ,{(UBYTE *)"oldorder", ONOFFVALUE, 0, (LONG)0} ,{(UBYTE *)"oldparallelstatistics", ONOFFVALUE, 0, (LONG)0} + ,{(UBYTE *)"oldprfsign", ONOFFVALUE, 0, (LONG)0} ,{(UBYTE *)"parentheses", NUMERICALVALUE, 0, (LONG)MAXPARLEVEL} ,{(UBYTE *)"path", PATHVALUE, 0, (LONG)curdirp} ,{(UBYTE *)"procedureextension", STRINGVALUE, 0, (LONG)procedureextension} @@ -708,6 +709,8 @@ int AllocSetups(void) AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag = sp->value; sp = GetSetupPar((UBYTE *)"oldgcd"); AC.OldGCDflag = AM.gOldGCDflag = AM.ggOldGCDflag = sp->value; + sp = GetSetupPar((UBYTE *)"oldprfsign"); + AC.OldPRFSignFlag = sp->value; sp = GetSetupPar((UBYTE *)"wtimestats"); if ( sp->value == 2 ) sp->value = AM.ggWTimeStatsFlag; AC.WTimeStatsFlag = AM.gWTimeStatsFlag = AM.ggWTimeStatsFlag = sp->value; diff --git a/sources/sort.c b/sources/sort.c index 13c5d20c..734ca1b8 100644 --- a/sources/sort.c +++ b/sources/sort.c @@ -2803,31 +2803,38 @@ WORD Compare1(PHEAD WORD *term1, WORD *term2, WORD level) WORD CompareSymbols(PHEAD WORD *term1, WORD *term2, WORD par) { - int sum1, sum2; WORD *t1, *t2, *tt1, *tt2; - int low, high; DUMMYUSE(par); - if ( AR.SortType == SORTLOWFIRST ) { low = 1; high = -1; } - else { low = -1; high = 1; } - t1 = term1 + 1; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); t1 += 2; - t2 = term2 + 1; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); t2 += 2; - if ( AN.polysortflag > 0 ) { - sum1 = 0; sum2 = 0; - while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; } - while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; } - if ( sum1 < sum2 ) return(low); - if ( sum1 > sum2 ) return(high); - t1 = term1+3; t2 = term2 + 3; - } + const int low = AR.SortType == SORTLOWFIRST ? 1 : -1; + const int high = - low; + + t1 = term1 + 3; tt1 = term1+*term1; tt1 -= ABS(tt1[-1]); + t2 = term2 + 3; tt2 = term2+*term2; tt2 -= ABS(tt2[-1]); + +// Currently, FORM never sets polysortflag != 0, so disable this code. +// if ( AN.polysortflag > 0 ) { +// WORD sum1, sum2; +// sum1 = 0; sum2 = 0; +// while ( t1 < tt1 ) { sum1 += t1[1]; t1 += 2; } +// while ( t2 < tt2 ) { sum2 += t2[1]; t2 += 2; } +// if ( sum1 < sum2 ) return(low); +// if ( sum1 > sum2 ) return(high); +// t1 = term1+3; t2 = term2 + 3; +// } + while ( t1 < tt1 && t2 < tt2 ) { - if ( *t1 > *t2 ) return(low); - if ( *t1 < *t2 ) return(high); - if ( t1[1] < t2[1] ) return(low); - if ( t1[1] > t2[1] ) return(high); + const WORD s1 = *t1; + const WORD s2 = *t2; + if ( s1 != s2 ) { return ( s1 > s2 ) ? low : high ; } + const WORD p1 = t1[1]; + const WORD p2 = t2[1]; + if ( p1 != p2 ) { return ( p1 < p2 ) ? low : high ; } t1 += 2; t2 += 2; } + if ( t1 < tt1 ) return(high); if ( t2 < tt2 ) return(low); + return(0); } diff --git a/sources/startup.c b/sources/startup.c index ffa414aa..6f85902d 100644 --- a/sources/startup.c +++ b/sources/startup.c @@ -1341,6 +1341,7 @@ void StartVariables(void) AC.OldParallelStats = AM.gOldParallelStats = AM.ggOldParallelStats = 0; AC.OldFactArgFlag = AM.gOldFactArgFlag = AM.ggOldFactArgFlag = NEWFACTARG; AC.OldGCDflag = AM.gOldGCDflag = AM.ggOldGCDflag = 1; + AC.OldPRFSignFlag = 0; AC.WTimeStatsFlag = AM.gWTimeStatsFlag = AM.ggWTimeStatsFlag = 0; AM.gcNumDollars = AP.DollarList.num; AC.SizeCommuteInSet = AM.gSizeCommuteInSet = 0; diff --git a/sources/structs.h b/sources/structs.h index 36787109..db06d2b4 100644 --- a/sources/structs.h +++ b/sources/structs.h @@ -1843,6 +1843,7 @@ struct C_const { int OldFactArgFlag; int MemDebugFlag; /* Only used when MALLOCDEBUG in tools.c */ int OldGCDflag; + int OldPRFSignFlag; int WTimeStatsFlag; int SortReallocateFlag; /* Controls reallocation of large+small buffer at module end. 0 : Off