From 3251644311f451500985c8ab0bd3dfddda4819ef Mon Sep 17 00:00:00 2001 From: Josh Davies Date: Tue, 15 Sep 2026 14:30:52 +0100 Subject: [PATCH] fix+feat: use only thread-local buffers for local poly conversion This fixes #138 by having local polynomial conversions use only thread-local storage. We lock once, to store a copy of the global numxsymbol. After that everything is local and no further locks are required for the local conversion. This means that we can now also allow simultaneous use of global extrasymbols (ArgToExtraSymbol, ToPolynomial/FromPolynomial) and functions which may trigger local conversion to polynomials: FactArg, FactDollar, gcd_, etc. Historically this has been forbidden in both FORM and TFORM, although FORM should not ever have had an issue. Presumably it was forbidden for both for consistency. --- check/fixes.frm | 57 ++++++++++++++++ sources/argument.c | 8 +-- sources/compcomm.c | 19 +----- sources/comtool.c | 2 + sources/declare.h | 8 +-- sources/dollar.c | 8 +-- sources/ftypes.h | 1 - sources/notation.c | 159 +++++++++++++++++++++++--------------------- sources/polywrap.cc | 11 +-- sources/ratio.c | 24 +++---- sources/structs.h | 4 +- 11 files changed, 176 insertions(+), 125 deletions(-) diff --git a/check/fixes.frm b/check/fixes.frm index 3ad37168c..d16b85234 100644 --- a/check/fixes.frm +++ b/check/fixes.frm @@ -1409,6 +1409,63 @@ assert stdout =~ exact_pattern(<<'EOF') F EOF *--#] Issue129_2 : +*--#[ Issue138_1 : +CFunction f,a,b,c,d; +Symbol x,y; +Local F = (1+f((a+b)^2,(a+b)*(c*d)))^20; +.sort +Identify f(x?,y?) = f(gcd_(x,y)); +ToPolynomial; +.sort +FromPolynomial; +Identify f(a+b) = -1; +Print; +.end +assert succeeded? +assert result("F") =~ expr("0") +*--#] Issue138_1 : +*--#[ Issue138_2 : +CFunction f,g; +Symbol x,y; +Local F = (1+f((g(x)+g(y))^2))^20; +FactArg f; +ToPolynomial; +.sort +FromPolynomial; +Identify f(g(x)+g(y),g(x)+g(y)) = -1; +Print; +.end +assert succeeded? +assert result("F") =~ expr("0") +*--#] Issue138_2 : +*--#[ Issue138_3 : +CFunction f,g; +Symbol x,y; +Local F = (1+f((g(x)+g(y))^2))^20; +FactArg f; +ArgToExtraSymbol g; +.sort +FromPolynomial; +Identify f(g(x)+g(y),g(x)+g(y)) = -1; +Print; +.end +assert succeeded? +assert result("F") =~ expr("0") +*--#] Issue138_3 : +*--#[ Issue138_4 : +CFunction f,g,h; +Symbol x,y; +Local F = (1+f((g(x)+g(y)+h(x)+h(y))^2))^20; +ArgToExtraSymbol g; +FactArg f; +.sort +FromPolynomial; +Identify f(g(x)+g(y)+h(x)+h(y),g(x)+g(y)+h(x)+h(y)) = -1; +Print; +.end +assert succeeded? +assert result("F") =~ expr("0") +*--#] Issue138_4 : *--#[ Issue139 : * Corrupted characters in printing f(-2147483648) CF f; diff --git a/sources/argument.c b/sources/argument.c index 12a2308fe..069d37f5d 100644 --- a/sources/argument.c +++ b/sources/argument.c @@ -2076,7 +2076,7 @@ int ArgFactorize(PHEAD WORD *argin, WORD *argout) #ifdef NEWORDER WORD *tt; #endif - WORD startebuf = cbuf[AT.ebufnum].numrhs,oldword; + WORD startebuf = cbuf[AT.ebufnum].numrhs, extrasymbolbase = -1, oldword; WORD oldsorttype = AR.SortType, numargs; int error = 0, action = 0, i, ii, number, sign = 1; @@ -2254,7 +2254,7 @@ int ArgFactorize(PHEAD WORD *argin, WORD *argout) argextra = AT.WorkPointer; NewSort(BHEAD0); while ( t < tstop ) { - if ( LocalConvertToPoly(BHEAD t,argextra,startebuf,0) < 0 ) { + if ( LocalConvertToPoly(BHEAD t,argextra,startebuf,0,&extrasymbolbase) < 0 ) { error = -1; getout: AR.SortType = oldsorttype; @@ -2309,8 +2309,8 @@ int ArgFactorize(PHEAD WORD *argin, WORD *argout) argextra = AT.WorkPointer; NewSort(BHEAD0); while ( t < tstop ) { - if ( ConvertFromPoly(BHEAD t,argextra,numxsymbol,CC->numrhs-startebuf+numxsymbol - ,startebuf-numxsymbol,1) <= 0 ) { + if ( ConvertFromPoly(BHEAD t,argextra,extrasymbolbase,CC->numrhs-startebuf+extrasymbolbase + ,startebuf-extrasymbolbase,1) <= 0 ) { TermFree(argcopy2,"argcopy2"); LowerSortLevel(); error = -3; diff --git a/sources/compcomm.c b/sources/compcomm.c index 4c281613b..55a117667 100644 --- a/sources/compcomm.c +++ b/sources/compcomm.c @@ -2223,11 +2223,6 @@ int CoSplitLastArg(UBYTE *s) { return(DoArgument(s,TYPESPLITLASTARG)); } */ int CoFactArg(UBYTE *s) { - if ( ( AC.topolynomialflag & TOPOLYNOMIALFLAG ) != 0 ) { - MesPrint("&ToPolynomial statement and FactArg statement are not allowed in the same module"); - return(1); - } - AC.topolynomialflag |= FACTARGFLAG; return(DoArgument(s,TYPEFACTARG)); } @@ -5953,9 +5948,8 @@ int CoDropSymbols(UBYTE *s) Converts the current term as much as possible to symbols. Keeps a list of all objects converted to symbols in AM.sbufnum. - Note that this cannot be executed in parallel because we have only - a single compiler buffer for this. Hence we switch on the noparallel - module option. + There is only a single compiler buffer for this. In TFORM we protect access + to it with AM.sbuflock; in ParFORM the statement is executed on the master. Option(s): OnlyFunctions [,name1][,name2][,...,namem]; @@ -5965,10 +5959,6 @@ int CoToPolynomial(UBYTE *inp) { int error = 0; while ( *inp == ' ' || *inp == ',' || *inp == '\t' ) inp++; - if ( ( AC.topolynomialflag & ~TOPOLYNOMIALFLAG ) != 0 ) { - MesPrint("&ToPolynomial statement and FactArg statement are not allowed in the same module"); - return(1); - } if ( AO.OptimizeResult.code != NULL ) { MesPrint("&Using ToPolynomial statement when there are still optimization results active."); MesPrint("&Please use #ClearOptimize instruction first."); @@ -6067,11 +6057,6 @@ int CoArgToExtraSymbol(UBYTE *s) CBUF *C = cbuf + AC.cbufnum; WORD *lhs; - /* TODO: resolve interference with rational arithmetic. (#138) */ - if ( ( AC.topolynomialflag & ~TOPOLYNOMIALFLAG ) != 0 ) { - MesPrint("&ArgToExtraSymbol statement and FactArg statement are not allowed in the same module"); - return(1); - } if ( AO.OptimizeResult.code != NULL ) { MesPrint("&Using ArgToExtraSymbol statement when there are still optimization results active."); MesPrint("&Please use #ClearOptimize instruction first."); diff --git a/sources/comtool.c b/sources/comtool.c index 06ee9263a..a54f41338 100644 --- a/sources/comtool.c +++ b/sources/comtool.c @@ -526,6 +526,8 @@ balance:; Returns -1 if the element is not in the tree. The advantage of this routine over InsTree is that this routine can be run in parallel. + Note that this function is not actually thread-safe, due to the update + of "usage". */ int FindTree(int bufnum, WORD *subexpr) diff --git a/sources/declare.h b/sources/declare.h index cd4fb2e40..a8d62dfbf 100644 --- a/sources/declare.h +++ b/sources/declare.h @@ -1576,10 +1576,10 @@ extern int RunHtoZArg(PHEAD WORD *fun, WORD *args); extern int NormPolyTerm(PHEAD WORD *); extern WORD ComparePoly(WORD *, WORD *, WORD); extern int ConvertToPoly(PHEAD WORD *, WORD *,WORD *,WORD); -extern int LocalConvertToPoly(PHEAD WORD *, WORD *, WORD,WORD); +extern int LocalConvertToPoly(PHEAD WORD *, WORD *, WORD,WORD,WORD *); extern int ConvertFromPoly(PHEAD WORD *, WORD *, WORD, WORD, WORD, WORD); extern int FindSubterm(WORD *); -extern int FindLocalSubterm(PHEAD WORD *, WORD); +extern int FindLocalSubterm(PHEAD WORD *, WORD, WORD); extern void PrintSubtermList(int,int); extern void PrintExtraSymbol(int,WORD *,int); extern int FindSubexpression(WORD *); @@ -1606,8 +1606,8 @@ extern WORD *PolyDiv(PHEAD WORD *,WORD *,char *); extern void GCDclean(PHEAD WORD *, WORD *); extern WORD *TakeSymbolContent(PHEAD WORD *,WORD *); extern int GCDterms(PHEAD WORD *,WORD *,WORD *); -extern WORD *PutExtraSymbols(PHEAD WORD *,WORD,int *); -extern WORD *TakeExtraSymbols(PHEAD WORD *,WORD); +extern WORD *PutExtraSymbols(PHEAD WORD *,WORD,int *,WORD *); +extern WORD *TakeExtraSymbols(PHEAD WORD *,WORD,WORD); extern WORD *MultiplyWithTerm(PHEAD WORD *, WORD *,WORD); extern WORD *TakeContent(PHEAD WORD *, WORD *); extern int MergeSymbolLists(PHEAD WORD *, WORD *, int); diff --git a/sources/dollar.c b/sources/dollar.c index 0b50ff52a..0d3238081 100644 --- a/sources/dollar.c +++ b/sources/dollar.c @@ -2949,7 +2949,7 @@ int DollarFactorize(PHEAD WORD numdollar) #endif int i, j, jj, action = 0, sign = 1; LONG insize, ii; - WORD startebuf = cbuf[AT.ebufnum].numrhs; + WORD startebuf = cbuf[AT.ebufnum].numrhs, extrasymbolbase = -1; WORD nfactors, factorsincontent, extrafactor = 0; WORD oldsorttype = AR.SortType; @@ -3144,7 +3144,7 @@ int DollarFactorize(PHEAD WORD numdollar) NewSort(BHEAD0); NewSort(BHEAD0); while ( *t ) { - if ( LocalConvertToPoly(BHEAD t,termextra,startebuf,0) < 0 ) { + if ( LocalConvertToPoly(BHEAD t,termextra,startebuf,0,&extrasymbolbase) < 0 ) { getout: AR.SortType = oldsorttype; M_free(buf1,"DollarFactorize-2"); @@ -3274,8 +3274,8 @@ int DollarFactorize(PHEAD WORD numdollar) NewSort(BHEAD0); NewSort(BHEAD0); while ( *term ) { - if ( ConvertFromPoly(BHEAD term,argextra,numxsymbol,CC->numrhs-startebuf+numxsymbol - ,startebuf-numxsymbol,1) <= 0 ) { + if ( ConvertFromPoly(BHEAD term,argextra,extrasymbolbase,CC->numrhs-startebuf+extrasymbolbase + ,startebuf-extrasymbolbase,1) <= 0 ) { LowerSortLevel(); getout2: AR.SortType = oldsorttype; M_free(d->factors,"factors in dollar"); diff --git a/sources/ftypes.h b/sources/ftypes.h index 999a90147..091accb73 100644 --- a/sources/ftypes.h +++ b/sources/ftypes.h @@ -1043,7 +1043,6 @@ typedef int (*TFUN1)(UBYTE *,int); #define NOLYNDON 2 #define TOPOLYNOMIALFLAG 1 -#define FACTARGFLAG 2 #define OLDFACTARG 1 #define NEWFACTARG 0 diff --git a/sources/notation.c b/sources/notation.c index 64107ad8c..6f7c2d191 100644 --- a/sources/notation.c +++ b/sources/notation.c @@ -505,13 +505,25 @@ int ConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD *comlist, WORD par) * buffer and represented by a symbol. The numbering of the extra * symbols is down from the maximum. In principle there can be a * problem when running into the already assigned ones. - * This uses the FindTree for searching in the global tree and - * then looks further in the AT.ebufnum. This allows fully parallel - * processing. Hence we need no locks. Cannot be used in the same - * module as ConvertToPoly. + * The temporary extrasymbol definitions live in the private AT.ebufnum. + * We don't touch the global definitions, beyond determining the current + * number of global extrasymbols, under a lock. */ -int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par) +/** Helper function: copy the current numxsymbol, under a lock. Local temporary + * extrasymbol numbers will follow this. If the argument is positive, we have + * already stored the global numxsymbol and don't store it again. */ +static WORD LocalExtraSymbolBase(WORD *base) +{ + if ( *base < 0 ) { + LOCK(AM.sbuflock); + *base = numxsymbol; + UNLOCK(AM.sbuflock); + } + return(*base); +} + +int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par, WORD *base) { WORD *tout, *tstop, ncoef, *t, *r, *tt, *ttwo = 0; int i, action = 0; @@ -536,7 +548,7 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par tout[2] = 4; tout[3] = r[0]; tout[4] = -1; - i = FindLocalSubterm(BHEAD tout+1,startebuf); + i = FindLocalSubterm(BHEAD tout+1,startebuf,LocalExtraSymbolBase(base)); *tout++ = SYMBOL; *tout++ = 4; *tout++ = MAXVARIABLES-i; @@ -560,7 +572,7 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par else { tout[5] = 1; } - i = FindLocalSubterm(BHEAD tout+1,startebuf); + i = FindLocalSubterm(BHEAD tout+1,startebuf,LocalExtraSymbolBase(base)); *tout++ = SYMBOL; *tout++ = 4; *tout++ = MAXVARIABLES-i; @@ -577,7 +589,7 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par tout[2] = 4; tout[3] = r[0]; tout[4] = r[1]; - i = FindLocalSubterm(BHEAD tout+1,startebuf); + i = FindLocalSubterm(BHEAD tout+1,startebuf,LocalExtraSymbolBase(base)); *tout++ = SYMBOL; *tout++ = 4; *tout++ = MAXVARIABLES-i; @@ -593,7 +605,7 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par tout[1] = INDEX; tout[2] = 3; tout[3] = r[0]; - i = FindLocalSubterm(BHEAD tout+1,startebuf); + i = FindLocalSubterm(BHEAD tout+1,startebuf,LocalExtraSymbolBase(base)); *tout++ = SYMBOL; *tout++ = 4; *tout++ = MAXVARIABLES-i; @@ -615,7 +627,7 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par else { t += t[1]; } } else if ( *t >= FUNCTION ) { - i = FindLocalSubterm(BHEAD t,startebuf); + i = FindLocalSubterm(BHEAD t,startebuf,LocalExtraSymbolBase(base)); t += t[1]; *tout++ = SYMBOL; *tout++ = 4; @@ -661,65 +673,61 @@ int LocalConvertToPoly(PHEAD WORD *term, WORD *outterm, WORD startebuf, WORD par subexpressions when extra symbols have been replaced. */ +#ifdef WITHPTHREADS +/** Helper function: we only lock sbuflock if the term actually has an + * extrasymbol to replace. Search for one. */ +static int PolyHasExtraSymbols(WORD *term, WORD from, WORD to) +{ + WORD *t, *tt, *tstop, *tstop1; + + tstop = term + *term - ABS(term[*term-1]); + for ( t = term + 1; t < tstop; t += t[1] ) { + if ( *t != SYMBOL ) { + continue; + } + tstop1 = t + t[1]; + for ( tt = t + 2; tt < tstop1; tt += 2 ) { + if ( *tt >= MAXVARIABLES - to && *tt < MAXVARIABLES - from ) { + return(1); + } + } + } + return(0); +} +#endif + +static int ConvertFromPolyImpl(PHEAD WORD *term, WORD *outterm, WORD from, WORD to, WORD offset, WORD par); + int ConvertFromPoly(PHEAD WORD *term, WORD *outterm, WORD from, WORD to, WORD offset, WORD par) +{ + int locked = 0, result; + /* LocalConvertToPoly uses only AT.ebufnum. Expression-level FromPolynomial + * needs the global lock if the term contains a global extrasymbol. */ +#ifdef WITHPTHREADS + if ( ! par && PolyHasExtraSymbols(term,from,to) ) { + LOCK(AM.sbuflock); + locked = 1; + } +#endif + result = ConvertFromPolyImpl(BHEAD term,outterm,from,to,offset,par); +#ifdef WITHPTHREADS + if ( locked ) { + UNLOCK(AM.sbuflock); + } +#else + DUMMYUSE(locked); +#endif + return(result); +} + +static int ConvertFromPolyImpl(PHEAD WORD *term, WORD *outterm, WORD from, WORD to, WORD offset, WORD par) { WORD *tout, *tstop, *tstop1, ncoef, *t, *r, *tt; int i; -/* first = 1; */ tt = term + *term; tout = outterm+1; ncoef = ABS(tt[-1]); tstop = tt - ncoef; -/* - r = t = term + 1; - while ( t < tstop ) { - if ( *t == SYMBOL ) { - tstop1 = t + t[1]; - tt = t + 2; - while ( tt < tstop1 ) { - if ( ( *tt < MAXVARIABLES - to ) - || ( *tt >= MAXVARIABLES - from ) ) { - tt += 2; - } - else break; - } - if ( tt >= tstop1 ) { t = tstop1; continue; } - while ( r < t ) *tout++ = *r++; - t += 2; - first = 0; - while ( t < tstop1 ) { - if ( ( *t < MAXVARIABLES - to ) - || ( *t >= MAXVARIABLES - from ) ) { - *tout++ = SYMBOL; - *tout++ = 4; - *tout++ = *t++; - *tout++ = *t++; - } - else { - *tout++ = SUBEXPRESSION; - *tout++ = SUBEXPSIZE; - *tout++ = MAXVARIABLES - *t++ + offset; - *tout++ = *t++; - if ( par ) *tout++ = AT.ebufnum; - else *tout++ = AM.sbufnum; - FILLSUB(tout) - } - } - r = t; - } - else { - t += t[1]; - } - } - if ( first ) { - i = *term; t = term; - NCOPY(outterm,t,i); - return(*term); - } - while ( r < t ) *tout++ = *r++; - NCOPY(tout,tstop,ncoef) - *outterm = tout-outterm; -*/ t = term + 1; while ( t < tstop ) { if ( *t == SYMBOL ) { @@ -771,7 +779,8 @@ int ConvertFromPoly(PHEAD WORD *term, WORD *outterm, WORD from, WORD to, WORD of Searching is by tree structure. Adding changes the tree. - Notice that in TFORM we should be in sequential mode. + Writing to the global extra-symbol buffer and its search tree is protected + in TFORM by AM.sbuflock. */ int FindSubterm(WORD *subterm) @@ -837,14 +846,15 @@ int FindSubterm(WORD *subterm) #[ FindLocalSubterm : In this routine we look up a variable. - If we don't find it we will enter it in the subterm compiler buffer - Searching is by tree structure. - Adding changes the tree. + If we don't find it we enter it in the thread-private compiler buffer. - Notice that in TFORM we should be in sequential mode. + The definitions and lookup are private to this thread. The numbering + starts after the stored global base, but may overlap global symbols + created by other threads after that store. The definitions are temporary, + so this doesn't matter. */ -int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf) +int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf, WORD base) { WORD old[5], *ss, *term, i, j, *t1, *t2; int number; @@ -857,13 +867,7 @@ int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf) old[0] = *term; old[1] = ss[0]; old[2] = ss[1]; old[3] = ss[2]; old[4] = ss[3]; ss[0] = 1; ss[1] = 1; ss[2] = 3; ss[3] = 0; *term = subterm[1]+4; /* - First see whether we have this one already in the global buffer. -*/ - number = FindTree(AM.sbufnum,term); - if ( number > 0 ) goto wearehappy; -/* - Now look whether it is in the ebufnum between startebuf and numrhs - Note however that we need an offset of (numxsymbol-startebuf) + Look whether it is in the private ebufnum between startebuf and numrhs. */ for ( i = startebuf+1; i <= C->numrhs; i++ ) { t1 = C->rhs[i]; t2 = term; @@ -871,7 +875,7 @@ int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf) j = *t1; while ( *t1 == *t2 && j > 0 ) { t1++; t2++; j--; } if ( j <= 0 ) { - number = i-startebuf+numxsymbol; + number = i-startebuf+base; goto wearehappy; } } @@ -882,7 +886,7 @@ int FindLocalSubterm(PHEAD WORD *subterm, WORD startebuf) AddRHS(AT.ebufnum,1); AddNtoC(AT.ebufnum,*term,term,9); AddToCB(C,0) - number = C->numrhs-startebuf+numxsymbol; + number = C->numrhs-startebuf+base; wearehappy: *term = old[0]; ss[0] = old[1]; ss[1] = old[2]; ss[2] = old[3]; ss[3] = old[4]; return(number); @@ -1094,7 +1098,8 @@ void PrintExtraSymbol(int num, WORD *terms,int par) Searching is by tree structure. Adding changes the tree. - Notice that in TFORM we should be in sequential mode. + Writing to the global extra-symbol buffer and its search tree is protected + in TFORM by AM.sbuflock. */ int FindSubexpression(WORD *subexpr) diff --git a/sources/polywrap.cc b/sources/polywrap.cc index db0851075..072daa2cb 100644 --- a/sources/polywrap.cc +++ b/sources/polywrap.cc @@ -1194,6 +1194,7 @@ int poly_factorize_expression(EXPRESSIONS expr) { WORD *term = AT.WorkPointer; WORD startebuf = cbuf[AT.ebufnum].numrhs; + WORD extrasymbolbase = -1; FILEHANDLE *file; POSITION pos; @@ -1275,7 +1276,7 @@ int poly_factorize_expression(EXPRESSIONS expr) { Terminate(-1); } buffer.check_memory(bufpos); - if (LocalConvertToPoly(BHEAD term, buffer.terms + bufpos, startebuf,0) < 0) { + if (LocalConvertToPoly(BHEAD term, buffer.terms + bufpos,startebuf,0,&extrasymbolbase) < 0) { /* INTERNAL_ERROR_EXCL_START */ MesPrint("!>ERROR: in LocalConvertToPoly [factorize_expression]"); Terminate(-1); @@ -1413,8 +1414,8 @@ int poly_factorize_expression(EXPRESSIONS expr) { for (WORD *t=buffer.terms; *t!=0; t+=*t) { // substitute extra symbols - if (ConvertFromPoly(BHEAD t, term, numxsymbol, CC->numrhs-startebuf+numxsymbol, - startebuf-numxsymbol, 1) <= 0 ) { + if (ConvertFromPoly(BHEAD t, term, extrasymbolbase, CC->numrhs-startebuf+extrasymbolbase, + startebuf-extrasymbolbase, 1) <= 0 ) { /* INTERNAL_ERROR_EXCL_START */ MesPrint("!>ERROR: in ConvertFromPoly [factorize_expression]"); Terminate(-1); @@ -1430,7 +1431,9 @@ int poly_factorize_expression(EXPRESSIONS expr) { // sort and store in buffer WORD *buffer; - if (EndSort(BHEAD (WORD *)((void *)(&buffer)),2) < 0) return -1; + if (EndSort(BHEAD (WORD *)((void *)(&buffer)),2) < 0) { + return -1; + } LONG bufsize=0; for (WORD *t=buffer; *t!=0; t+=*t) diff --git a/sources/ratio.c b/sources/ratio.c index e1f29daa4..6849d3f8c 100644 --- a/sources/ratio.c +++ b/sources/ratio.c @@ -1150,7 +1150,7 @@ WORD *GCDfunction3(PHEAD WORD *in1, WORD *in2) WORD oldsorttype = AR.SortType, *ow = AT.WorkPointer;; WORD *t, *tt, *gcdout, *term1, *term2, *confree1, *confree2, *gcdout1, *proper1, *proper2; int i, actionflag1, actionflag2; - WORD startebuf = cbuf[AT.ebufnum].numrhs; + WORD startebuf = cbuf[AT.ebufnum].numrhs, extrasymbolbase = -1; WORD tryterm1, tryterm2; if ( in2[*in2] == 0 ) { t = in1; in1 = in2; in2 = t; } if ( in1[*in1] == 0 ) { /* First input with only one term */ @@ -1187,7 +1187,7 @@ WORD *GCDfunction3(PHEAD WORD *in1, WORD *in2) Now we have to replace all non-symbols and symbols to a negative power by extra symbols. */ - if ( ( proper1 = PutExtraSymbols(BHEAD confree1,startebuf,&actionflag1) ) == 0 ) goto CalledFrom; + if ( ( proper1 = PutExtraSymbols(BHEAD confree1,startebuf,&actionflag1,&extrasymbolbase) ) == 0 ) goto CalledFrom; if ( confree1 != in1 ) { if ( tryterm1 ) { TermFree(confree1,"TakeContent"); } else { M_free(confree1,"TakeContent"); } @@ -1195,7 +1195,7 @@ WORD *GCDfunction3(PHEAD WORD *in1, WORD *in2) /* TermFree(confree1,"TakeSymbolContent"); */ - if ( ( proper2 = PutExtraSymbols(BHEAD confree2,startebuf,&actionflag2) ) == 0 ) goto CalledFrom; + if ( ( proper2 = PutExtraSymbols(BHEAD confree2,startebuf,&actionflag2,&extrasymbolbase) ) == 0 ) goto CalledFrom; if ( confree2 != in2 ) { if ( tryterm2 ) { TermFree(confree2,"TakeContent"); } else { M_free(confree2,"TakeContent"); } @@ -1212,7 +1212,7 @@ WORD *GCDfunction3(PHEAD WORD *in1, WORD *in2) AR.SortType = oldsorttype; if ( actionflag1 || actionflag2 ) { - if ( ( gcdout = TakeExtraSymbols(BHEAD gcdout1,startebuf) ) == 0 ) goto CalledFrom; + if ( ( gcdout = TakeExtraSymbols(BHEAD gcdout1,startebuf,extrasymbolbase) ) == 0 ) goto CalledFrom; M_free(gcdout1,"gcdout"); } else { @@ -1246,14 +1246,14 @@ WORD *GCDfunction3(PHEAD WORD *in1, WORD *in2) #[ PutExtraSymbols : */ -WORD *PutExtraSymbols(PHEAD WORD *in,WORD startebuf,int *actionflag) +WORD *PutExtraSymbols(PHEAD WORD *in,WORD startebuf,int *actionflag,WORD *extrasymbolbase) { WORD *termout = AT.WorkPointer; int action; *actionflag = 0; NewSort(BHEAD0); while ( *in ) { - if ( ( action = LocalConvertToPoly(BHEAD in,termout,startebuf,0) ) < 0 ) { + if ( ( action = LocalConvertToPoly(BHEAD in,termout,startebuf,0,extrasymbolbase) ) < 0 ) { LowerSortLevel(); goto CalledFrom; } @@ -1275,7 +1275,7 @@ WORD *PutExtraSymbols(PHEAD WORD *in,WORD startebuf,int *actionflag) #[ TakeExtraSymbols : */ -WORD *TakeExtraSymbols(PHEAD WORD *in,WORD startebuf) +WORD *TakeExtraSymbols(PHEAD WORD *in,WORD startebuf,WORD extrasymbolbase) { CBUF *C = cbuf+AC.cbufnum; CBUF *CC = cbuf+AT.ebufnum; @@ -1284,7 +1284,7 @@ WORD *TakeExtraSymbols(PHEAD WORD *in,WORD startebuf) termout = AT.WorkPointer; NewSort(BHEAD0); while ( *in ) { - if ( ConvertFromPoly(BHEAD in,termout,numxsymbol,CC->numrhs-startebuf+numxsymbol,startebuf-numxsymbol,1) <= 0 ) { + if ( ConvertFromPoly(BHEAD in,termout,extrasymbolbase,CC->numrhs-startebuf+extrasymbolbase,startebuf-extrasymbolbase,1) <= 0 ) { LowerSortLevel(); goto CalledFrom; } @@ -2851,7 +2851,7 @@ int DIVfunction(PHEAD WORD *term,WORD level,int par) WORD *tstop, *tend, *r3, *rr, *rstop, tlength, rlength, newlength; WORD *proper1, *proper2, *proper3 = 0, numdol = -1; int numargs = 0, type1, type2, actionflag1, actionflag2; - WORD startebuf = cbuf[AT.ebufnum].numrhs; + WORD startebuf = cbuf[AT.ebufnum].numrhs, extrasymbolbase = -1; int division = ( par <= 2 ); /* false for mul_ */ if ( par < 0 || par > 3 ) { /* INTERNAL_ERROR_EXCL_START */ @@ -2939,8 +2939,8 @@ divzero:; M_free(arg1,"DIVfunction"); return(0); } - if ( ( proper1 = PutExtraSymbols(BHEAD arg1,startebuf,&actionflag1) ) == 0 ) goto CalledFrom; - if ( ( proper2 = PutExtraSymbols(BHEAD arg2,startebuf,&actionflag2) ) == 0 ) goto CalledFrom; + if ( ( proper1 = PutExtraSymbols(BHEAD arg1,startebuf,&actionflag1,&extrasymbolbase) ) == 0 ) goto CalledFrom; + if ( ( proper2 = PutExtraSymbols(BHEAD arg2,startebuf,&actionflag2,&extrasymbolbase) ) == 0 ) goto CalledFrom; /* if ( type2 == 0 ) M_free(arg2,"DIVfunction"); else { @@ -2965,7 +2965,7 @@ divzero:; else if ( par == 3 ) proper3 = poly_mul(BHEAD proper1, proper2); if ( proper3 == 0 ) goto CalledFrom; if ( actionflag1 || actionflag2 ) { - if ( ( arg3 = TakeExtraSymbols(BHEAD proper3,startebuf) ) == 0 ) goto CalledFrom; + if ( ( arg3 = TakeExtraSymbols(BHEAD proper3,startebuf,extrasymbolbase) ) == 0 ) goto CalledFrom; M_free(proper3,"DIVfunction"); } else { diff --git a/sources/structs.h b/sources/structs.h index 707e3e0f1..6789af4d8 100644 --- a/sources/structs.h +++ b/sources/structs.h @@ -1438,7 +1438,7 @@ struct M_const { #ifdef WITHPTHREADS pthread_rwlock_t handlelock; /* (M) */ pthread_mutex_t storefilelock; /* (M) */ - pthread_mutex_t sbuflock; /* (M) Lock for writing in the AM.sbuffer */ + pthread_mutex_t sbuflock; /* (M) Lock for the global AM.sbuffer */ LONG ThreadScratSize; /* (M) Size of Fscr[0/2] buffers of the workers */ LONG ThreadScratOutSize; /* (M) Size of Fscr[1] buffers of the workers */ #endif @@ -1843,7 +1843,7 @@ struct C_const { int NoCompress; /* (R) Controls native compression */ int IsFortran90; /* Tells whether the Fortran is Fortran90 */ int MultiBracketLevels; /* Number of elements in MultiBracketBuf */ - int topolynomialflag; /* To avoid ToPolynomial and FactArg together */ + int topolynomialflag; /* Module can add entries to the global extra-symbol buffer */ int ffbufnum; /* Buffer number for user defined factorizations */ int OldFactArgFlag; int MemDebugFlag; /* Only used when MALLOCDEBUG in tools.c */