diff --git a/check/fixes.frm b/check/fixes.frm index 94c7198c..232ba4e2 100644 --- a/check/fixes.frm +++ b/check/fixes.frm @@ -5245,6 +5245,53 @@ Print; assert succeeded? assert result("test") =~ expr("4+4*x") *--#] Issue882_6 : +*--#[ Issue916_1 : +Vector l1; +CFunction den; + +#$k = -l1; + +Local expr = 1; +Local match = den(l1,1); +Identify den(-$k,1) = 1; + +Print; +.end +assert succeeded? +assert result("expr") =~ expr("1") +assert result("match") =~ expr("1") +*--#] Issue916_1 : +*--#[ Issue916_2 : +Symbol x,y,z; +CFunction den,g; + +#$s = -x-y; + +Local rhs1 = den(-$s); +Local rhs2 = den(g(-$s),z); +Local cancel = den(-$s-x-y); +Local match1 = den(x+y+z); +Local match2 = den(g(x+y+z),z); +Local match3 = den(x^2+x*y+y); +Local match4 = den(x+y+z+g(x+y)); +.sort + +Identify den(-$s+z) = 1; +Identify den(g(-$s+z),z) = 2; +Identify den(-$s*x+y) = 3; +Identify den(-$s+z+g(-$s)) = 4; + +Print; +.end +assert succeeded? +assert result("rhs1") =~ expr("den(y+x)") +assert result("rhs2") =~ expr("den(g(y+x),z)") +assert result("cancel") =~ expr("den(0)") +assert result("match1") =~ expr("1") +assert result("match2") =~ expr("2") +assert result("match3") =~ expr("3") +assert result("match4") =~ expr("4") +*--#] Issue916_2 : *--#[ PullReq535 : * This test requires more than the specified 50K workspace. #:maxtermsize 200 diff --git a/sources/proces.c b/sources/proces.c index b0fc8f74..cf1106e7 100644 --- a/sources/proces.c +++ b/sources/proces.c @@ -1687,30 +1687,15 @@ doesnotwork:; AN.ncmod = oldncmod; DONE(retvalue) } - else { - // For a long time, Normalize was called in-place here. This was - // very dangerous, since Normalize can increase the size of the - // term, and overwrite term data at outer nesting levels. We - // can instead just rely on the Normalize call (which uses the - // WorkSpace) just before calling StoreTerm later. - WORD *tend = t + *t, *tt = t+1; - stilldirty = 0; - tend -= ABS(tend[-1]); - while ( tt < tend ) { - if ( *tt == SUBEXPRESSION || *tt == EXPRESSION ) { - stilldirty = 1; break; - } - tt += tt[1]; - } - } AN.subsubveto = 0; AT.RecFlag--; t += *t; } AT.NestPoin--; /* - Argument contains no subexpressions. - It should be normalized and sorted. + Normalize and sort the terms of the argument. Normalize may possibly + introduce new SUBEXPRESSIONs, for example due to dollar-var inserts. + Check after sorting if the argument is clean, or needs further work. The main problem is the storage: we need to Normalize a copy of the term data in the WorkSpace, since Normalize can increase the size of the term, which would overwrite the data which follows! @@ -1732,7 +1717,8 @@ doesnotwork:; do { *m++ = *t++; } while ( t < r ); r = AT.WorkPointer; AT.WorkPointer = r + *r; - if ( Normalize(BHEAD r) ) { + /* Allow positive return values: there may still be SUBEXPRESSIONs to process */ + if ( Normalize(BHEAD r) < 0 ) { if ( *t1 == AR.PolyFun && AR.PolyFunType == 2 ) { AR.SortType = oldsorttype; AR.CompareRoutine = (COMPAREDUMMY)oldcompareroutine; @@ -1767,7 +1753,21 @@ doesnotwork:; AR.CompareRoutine = (COMPAREDUMMY)oldcompareroutine; t1[2] |= MUSTCLEANPRF; } - while ( *m ) m += *m; + /* Check the normalized, sorted result for remaining processing */ + stilldirty = 0; + while ( *m ) { + if ( !stilldirty ) { + WORD *tend = m + *m, *tt = m+1; + tend -= ABS(tend[-1]); + while ( tt < tend ) { + if ( *tt == SUBEXPRESSION || *tt == EXPRESSION ) { + stilldirty = 1; break; + } + tt += tt[1]; + } + } + m += *m; + } i = WORDDIF(m,AT.WorkPointer); *AT.WorkPointer = i; AT.WorkPointer[1] = stilldirty;