diff --git a/sources/argument.c b/sources/argument.c index 4a73b454..803375d0 100644 --- a/sources/argument.c +++ b/sources/argument.c @@ -48,7 +48,7 @@ level = C->lhs[level][2]; goto SkipCount; } - Note that there will be cases that extra space is needed. + Note that there will be cases in which extra space is needed. In addition the compare with C->numlhs isn't very fine, because we need to insert a different value (C->lhs[level][2]). */ @@ -1561,7 +1561,7 @@ nextterm: mm = mnext; } } /* - #] Numerical factor : + #] Numerical factor : */ else { oneterm:; diff --git a/sources/comexpr.c b/sources/comexpr.c index ec536765..82fce485 100644 --- a/sources/comexpr.c +++ b/sources/comexpr.c @@ -55,10 +55,11 @@ static struct id_options { ,{(UBYTE *)"ifnotmatch", SUBAFTERNOT ,0} ,{(UBYTE *)"disorder", SUBDISORDER ,0} ,{(UBYTE *)"select", SUBSELECT ,0} + ,{(UBYTE *)"all", SUBALL ,0} }; /* - #] Includes : + #] Includes : #[ CoLocal : */ @@ -496,7 +497,7 @@ int CoIdExpression(UBYTE *inp, int type) oldnumrhs, *ow, oldEside; UBYTE *p, *pp, c; CBUF *C = cbuf+AC.cbufnum; - LONG oldcpointer; + LONG oldcpointer, x; FirstWork = OldWork = AT.WorkPointer; /* Don't forget to change in StudyPattern if we change/add_to the @@ -669,6 +670,45 @@ findsets:; OldWork[3] = GetLabel(inp); *p++ = c; inp = p; break; + case SUBALL: + x = 0; + if ( *pp == '(' ) { + while ( *inp >= '0' && *inp <= '9' ) x = 10*x+*inp++ - '0'; + if ( *inp != ')' || inp+1 != p ) { + c = *p; *p = 0; + MesPrint("&Illegal ALL option in id-statement: ",pp); + *p++ = c; + error = 1; + continue; + } + pp = inp; + inp = pp+1; + } +/* + Note that the following statement limits x to +*/ + if ( x > MAXPOSITIVE ) { + MesPrint("&Requested maximum number of matches %l in ALL option in id-statement is greater than %l ",x,MAXPOSITIVE); + error = 1; + } + OldWork[3] = x; + if ( type != TYPEIDNEW ) { + if ( type == TYPEIDOLD ) { + MesPrint("&Requested ALL option not allowed in idold/also statement."); + error = 1; + } + else if ( type == TYPEIF ) { + MesPrint("&Requested ALL option not allowed in if(match())"); + error = 1; + } + else { + MesPrint("&ALL option only allowed in regular id-statement."); + error = 1; + } + } + p++; inp = p; + AC.idoption = opt; + break; default: if ( pp != p ) { IllField: c = *p; *p = 0; @@ -810,7 +850,7 @@ IllLeft:MesPrint("&Illegal LHS"); error = 1; } AC.DumNum = AM.IndDum; - OldWork[2] = ( OldWork[2] - ( OldWork[2] & SUBMASK ) ) | SUBALL; + OldWork[2] = ( OldWork[2] - ( OldWork[2] & SUBMASK ) ) | SUBVECTOR; c1 = w[3]; /* We overwrite the LHS */ *w++ = INDTOIND; @@ -920,6 +960,18 @@ IllLeft:MesPrint("&Illegal LHS"); Actual adding happens only now after numrhs insertion */ /* if ( !error ) */ { AddNtoL(OldWork[1],OldWork); } + if ( type == TYPEIDOLD ) { + if ( C->numlhs <= 1 || + ( C->lhs[C->numlhs-1][0] != TYPEIDNEW && + C->lhs[C->numlhs-1][0] != TYPEIDOLD ) ) { + MesPrint("&Idold/also should follow an id/idnew statement."); + error = 1; + } + else if ( (C->lhs[C->numlhs-1][2] & SUBMASK) == SUBALL ) { + MesPrint("&Idold/also cannot follow an id,all statement."); + error = 1; + } + } AllDone: AC.lhdollarflag = 0; AT.WorkPointer = FirstWork; @@ -927,7 +979,7 @@ IllLeft:MesPrint("&Illegal LHS"); } /* - #] CoIdExpression : + #] CoIdExpression : #[ CoMultiply : */ diff --git a/sources/compiler.c b/sources/compiler.c index 849ffc3b..c64c3e22 100644 --- a/sources/compiler.c +++ b/sources/compiler.c @@ -758,8 +758,8 @@ int CompileSubExpressions(SBYTE *tokens) this minimum. Ignoring this might lead to really rare and hard to find errors, years from now. */ - if ( insubexpbuffers >= 0x3FFFFFL ) { - MesPrint("&More than 2^22 subexpressions inside one expression"); + if ( insubexpbuffers >= MAXSUBEXPRESSIONS ) { + MesPrint("&More than %d subexpressions inside one expression",(WORD)MAXSUBEXPRESSIONS); Terminate(-1); } if ( subexpbuffers+insubexpbuffers >= topsubexpbuffers ) { @@ -1910,8 +1910,8 @@ int CodeFactors(SBYTE *tokens) || t[-1] == TSETCLOSE || t[-1] == TFUNCLOSE ) { subexp = CodeGenerator(tokens); if ( subexp < 0 ) error = -1; - if ( insubexpbuffers >= 0x3FFFFFL ) { - MesPrint("&More than 2^22 subexpressions inside one expression"); + if ( insubexpbuffers >= MAXSUBEXPRESSIONS ) { + MesPrint("&More than %d subexpressions inside one expression",(WORD)MAXSUBEXPRESSIONS); Terminate(-1); } if ( subexpbuffers+insubexpbuffers >= topsubexpbuffers ) { @@ -2151,8 +2151,8 @@ int CodeFactors(SBYTE *tokens) e->vflags |= ISFACTORIZED; subexp = CodeGenerator(outtokens); if ( subexp < 0 ) error = -1; - if ( insubexpbuffers >= 0x3FFFFFL ) { - MesPrint("&More than 2^22 subexpressions inside one expression"); + if ( insubexpbuffers >= MAXSUBEXPRESSIONS ) { + MesPrint("&More than %d subexpressions inside one expression",(WORD)MAXSUBEXPRESSIONS); Terminate(-1); } if ( subexpbuffers+insubexpbuffers >= topsubexpbuffers ) { @@ -2198,8 +2198,8 @@ WORD GenerateFactors(WORD n,WORD inc) subexp = CodeGenerator(tokenbuffer); if ( subexp < 0 ) error = -1; M_free(tokenbuffer,"GenerateFactors"); - if ( insubexpbuffers >= 0x3FFFFFL ) { - MesPrint("&More than 2^22 subexpressions inside one expression"); + if ( insubexpbuffers >= MAXSUBEXPRESSIONS ) { + MesPrint("&More than %d subexpressions inside one expression",(WORD)MAXSUBEXPRESSIONS); Terminate(-1); } if ( subexpbuffers+insubexpbuffers >= topsubexpbuffers ) { diff --git a/sources/declare.h b/sources/declare.h index 6c0bf863..dd9bf25f 100644 --- a/sources/declare.h +++ b/sources/declare.h @@ -1147,6 +1147,8 @@ extern DOLLARS DolToTerms(PHEAD WORD); extern WORD EvalDoLoopArg(PHEAD WORD *,WORD); extern int SetExprCases(int,int,int); extern int TestSelect(WORD *,WORD *); +extern VOID SubsInAll(PHEAD0); +extern VOID TransferBuffer(int,int,int); extern int TakeIDfunction(PHEAD WORD *); extern int MakeSetupAllocs(VOID); extern int TryFileSetups(VOID); @@ -1504,6 +1506,9 @@ extern VOID AddToSymbolList(PHEAD WORD); extern int AddToListPoly(PHEAD0); extern int InvPoly(PHEAD WORD *,WORD,WORD); +extern int ReadFromScratch(FILEHANDLE *,POSITION *,UBYTE *,POSITION *); +extern int AddToScratch(FILEHANDLE *,POSITION *,UBYTE *,POSITION *,int); + /* #] Declarations : */ diff --git a/sources/execute.c b/sources/execute.c index bfe4dba5..8e04129b 100644 --- a/sources/execute.c +++ b/sources/execute.c @@ -28,7 +28,7 @@ * You should have received a copy of the GNU General Public License along * with FORM. If not, see . */ -/* #] License : */ +/* #] License : */ /* #[ Includes : execute.c */ @@ -36,7 +36,7 @@ #include "form3.h" /* - #] Includes : + #] Includes : #[ DoExecute : #[ CleanExpr : @@ -196,7 +196,7 @@ WORD CleanExpr(WORD par) } /* - #] CleanExpr : + #] CleanExpr : #[ PopVariables : Pops the local variables from the tables. @@ -366,7 +366,7 @@ WORD PopVariables() } /* - #] PopVariables : + #] PopVariables : #[ MakeGlobal : */ @@ -462,7 +462,7 @@ VOID MakeGlobal() } /* - #] MakeGlobal : + #] MakeGlobal : #[ TestDrop : */ @@ -532,6 +532,7 @@ VOID TestDrop() break; default: ClearBracketIndex(j); + e->bracketinfo = 0; break; } if ( e->replace == NEWLYDEFINEDEXPRESSION ) e->replace = REGULAREXPRESSION; @@ -539,7 +540,7 @@ VOID TestDrop() } /* - #] TestDrop : + #] TestDrop : #[ PutInVflags : */ @@ -587,7 +588,7 @@ restart:; } /* - #] PutInVflags : + #] PutInVflags : #[ DoExecute : */ @@ -976,7 +977,7 @@ WORD DoExecute(WORD par, WORD skip) } /* - #] DoExecute : + #] DoExecute : #[ PutBracket : Routine uses the bracket info to split a term into two pieces: @@ -1281,7 +1282,7 @@ nextdot:; } /* - #] PutBracket : + #] PutBracket : #[ SpecialCleanup : */ @@ -1293,7 +1294,7 @@ VOID SpecialCleanup(PHEAD0) } /* - #] SpecialCleanup : + #] SpecialCleanup : #[ SetMods : */ @@ -1311,7 +1312,7 @@ void SetMods() #endif /* - #] SetMods : + #] SetMods : #[ UnSetMods : */ @@ -1326,7 +1327,7 @@ void UnSetMods() #endif /* - #] UnSetMods : + #] UnSetMods : #] DoExecute : #[ Expressions : #[ ExchangeExpressions : @@ -1402,7 +1403,7 @@ void ExchangeExpressions(int num1, int num2) } /* - #] ExchangeExpressions : + #] ExchangeExpressions : #[ GetFirstBracket : */ @@ -1512,7 +1513,7 @@ int GetFirstBracket(WORD *term, int num) } /* - #] GetFirstBracket : + #] GetFirstBracket : #[ GetFirstTerm : */ @@ -1607,7 +1608,7 @@ int GetFirstTerm(WORD *term, int num) } /* - #] GetFirstTerm : + #] GetFirstTerm : #[ GetContent : */ @@ -1722,7 +1723,7 @@ int GetContent(WORD *content, int num) } /* - #] GetContent : + #] GetContent : #[ CleanupTerm : Removes noncommuting objects from the term @@ -1748,7 +1749,7 @@ int CleanupTerm(WORD *term) } /* - #] CleanupTerm : + #] CleanupTerm : #[ ContentMerge : */ @@ -1968,7 +1969,7 @@ WORD ContentMerge(PHEAD WORD *content, WORD *term) } /* - #] ContentMerge : + #] ContentMerge : #[ TermsInExpression : */ @@ -1980,7 +1981,7 @@ LONG TermsInExpression(WORD num) } /* - #] TermsInExpression : + #] TermsInExpression : #[ UpdatePositions : */ @@ -2031,7 +2032,7 @@ void UpdatePositions() } /* - #] UpdatePositions : + #] UpdatePositions : #[ CountTerms1 : LONG CountTerms1() Counts the terms in the current deferred bracket @@ -2131,7 +2132,7 @@ Thatsit:; } /* - #] CountTerms1 : + #] CountTerms1 : #[ TermsInBracket : LONG TermsInBracket(term,level) The function TermsInBracket_() @@ -2322,7 +2323,7 @@ IllBraReq:; return(numterms); } /* - #] TermsInBracket : LONG TermsInBracket(term,level) + #] TermsInBracket : LONG TermsInBracket(term,level) #] Expressions : */ diff --git a/sources/fsizes.h b/sources/fsizes.h index b1ecb9c4..c8d81189 100644 --- a/sources/fsizes.h +++ b/sources/fsizes.h @@ -52,6 +52,7 @@ #define WORKBUFFER 40000000 #define MAXTER 40000 #define HALFMAX 0x10000 +#define MAXSUBEXPRESSIONS 0x1FFFFFF #else #define MAXPOWER 10000 #define MAXVARIABLES 8050 @@ -62,6 +63,7 @@ #define WORKBUFFER 10000000 #define MAXTER 10000 #define HALFMAX 0x100 +#define MAXSUBEXPRESSIONS 0x3FFF #endif #define MAXENAME 16 #define MAXSAVEFUNCTION 16384 diff --git a/sources/ftypes.h b/sources/ftypes.h index c1ca2343..0ce98fa6 100644 --- a/sources/ftypes.h +++ b/sources/ftypes.h @@ -769,8 +769,9 @@ typedef int (*TFUN1)(); #define SUBONCE 2 #define SUBONLY 3 #define SUBMANY 4 -#define SUBALL 5 +#define SUBVECTOR 5 #define SUBSELECT 6 +#define SUBALL 7 #define SUBMASK 15 #define SUBDISORDER 16 #define SUBAFTER 32 diff --git a/sources/function.c b/sources/function.c index be0fb692..22c1b3d6 100644 --- a/sources/function.c +++ b/sources/function.c @@ -810,11 +810,8 @@ int ChainOut(PHEAD WORD *term, WORD funnum) The ones with a minus sign in front have been implemented. - There are still a few considerations: - 1: the dummy indices should be reset in multiple ?? matches. - 2: currently we cannot have a match with multiple ?? if - first there is a match and later the assignment isn't right. - we cannot go back at the moment to continue searching. + Note: the argument wilds allows backtracking when multiple + ?a,?b give a match that later turns out to be useless. */ WORD MatchFunction(PHEAD WORD *pattern, WORD *interm, WORD *wilds) @@ -1761,6 +1758,10 @@ trythis:; if ( *inter != SUBEXPRESSION && MatchFunction(BHEAD inpat,inter,&wilds) ) { AN.terfirstcomm = Oterfirstcomm; if ( wilds ) { +/* + Store wildcards to continue in MatchFunction if the current + wildcards do not work out. +*/ wildargs = AN.WildArgs; wildeat = AN.WildEat; for ( i = 0; i < wildargs; i++ ) wildargtaken[i] = AT.WildArgTaken[i]; @@ -1873,6 +1874,11 @@ trythis:; AT.WorkPointer = OldWork; return(0); OnSuccess: + if ( AT.idallflag ) { + SubsInAll(BHEAD0); + AT.idallnum++; + if ( AT.idallmaxnum == 0 || AT.idallnum < AT.idallmaxnum ) goto NoMat; + } AN.terfirstcomm = Oterfirstcomm; AN.SignCheck = oldSignCheck; /* @@ -1888,8 +1894,7 @@ trythis:; t = AN.terstart + AN.RepFunList[i]; if ( *m != *t ) { if ( *m > *t ) continue; -jexch: AT.WorkPointer = OldWork; - return(1); + goto doesmatch; } if ( *m >= FUNCTION && functions[*m-FUNCTION].spec >= TENSORFUNCTION ) { @@ -1906,15 +1911,16 @@ jexch: AT.WorkPointer = OldWork; } while ( k > 0 && kk > 0 ) { if ( *m < *t ) goto NextFor; - else if ( *m++ > *t++ ) goto jexch; + else if ( *m++ > *t++ ) goto doesmatch; k--; kk--; } - if ( k > 0 ) goto jexch; + if ( k > 0 ) goto doesmatch; NextFor:; } SetStop = 1; goto NoMat; } +doesmatch: AT.WorkPointer = OldWork; return(1); } diff --git a/sources/if.c b/sources/if.c index 59365c9a..ff5c40f1 100644 --- a/sources/if.c +++ b/sources/if.c @@ -249,7 +249,7 @@ int FindVar(WORD *v, WORD *term) } /* - #] FindVar : + #] FindVar : #[ DoIfStatement : WORD DoIfStatement(PHEAD ifcode,term) The execution time part of the if-statement. @@ -963,7 +963,7 @@ WORD HowMany(PHEAD WORD *ifcode, WORD *term) case SUBMULTI : RetVal = FindMulti(BHEAD term,m); break; - case SUBALL : + case SUBVECTOR : RetVal = 0; for ( i = 0; i < *term; i++ ) ww[i] = term[i]; while ( ( power = FindAll(BHEAD ww,m,AR.Cnumlhs,ifcode) ) != 0 ) { RetVal += power; } @@ -1021,6 +1021,6 @@ VOID DoubleIfBuffers() /* #] DoubleIfBuffers : - #] If statement : + #] If statement : */ diff --git a/sources/pattern.c b/sources/pattern.c index d908ba6c..581b55cb 100644 --- a/sources/pattern.c +++ b/sources/pattern.c @@ -97,10 +97,11 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) { GETBIDENTITY - WORD *ll, *m, *w, *llf, *OldWork, *StartWork, *ww, *mm; - WORD power = 0, match = 0, /* *rep, */ i, msign = 0; - int numdollars = 0, protosize; - CBUF *C = cbuf+AM.rbufnum; + WORD *ll, *m, *w, *llf, *OldWork, *StartWork, *ww, *mm, *OldTermBuffer = 0; + WORD power = 0, match = 0, i, msign = 0; + int numdollars = 0, protosize, oldallnumrhs; + CBUF *C = cbuf+AM.rbufnum, *CC; + AT.idallflag = 0; do { /* #[ Preliminaries : @@ -146,7 +147,9 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) OldWork = AT.WorkPointer; if ( AT.WorkPointer < term + *term ) AT.WorkPointer = term + *term; ww = AT.WorkPointer; +/* #ifdef WITHPTHREADS +*/ /* Here we need to make a copy of the subexpression object because we will be writing the values of the wildcards in it. @@ -188,9 +191,11 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) CC->Pointer = ma; */ } +/* #else m = ll + IDHEAD; #endif +*/ AN.FullProto = m; AN.WildValue = w = m + SUBEXPSIZE; protosize = IDHEAD + m[1]; @@ -268,8 +273,38 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) /* #] Expand dollars : - AT.WorkPointer = ww = term + *term; + In case of id,all we have to check at this point that there are only + functions in the pattern. +*/ + if ( ( ll[2] & SUBMASK ) == SUBALL ) { + WORD *t = AN.patternbuffer+IDHEAD, *tt; + WORD *tstop, *ttstop, ii; + t += t[1]; tstop = t + *t; t++; + while ( t < tstop ) { + if ( *t < FUNCTION ) break; + t += t[1]; + } + if ( t < tstop ) { + MLOCK(ErrorMessageLock); + MesPrint("Error: id,all can only be used with (products of) functions and/or tensors."); + MUNLOCK(ErrorMessageLock); + return(-1); + } + OldTermBuffer = AN.termbuffer; + AN.termbuffer = TermMalloc("id,all"); +/* + Now make sure that only regular functions and tensors can take part. */ + tt = term; ttstop = tt+*tt; ttstop -= ABS(ttstop[-1]); tt++; + t = AN.termbuffer+1; + while ( tt < ttstop ) { + if ( *tt >= FUNCTION && *tt != AR.PolyFun && *tt != AR.PolyFunInv ) { + ii = tt[1]; NCOPY(t,tt,ii); + } + else tt += tt[1]; + } + *t++ = 1; *t++ = 1; *t++ = 3; AN.termbuffer[0] = t-AN.termbuffer; + } ClearWild(BHEAD0); while ( w < AN.WildStop ) { if ( *w == LOADDOLLAR ) numdollars++; @@ -399,16 +434,12 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) match = 1; } } -#if IDHEAD > 3 if ( match ) { if ( ( ll[2] & SUBAFTER ) != 0 ) *level = AC.Labels[ll[3]]; } else { if ( ( ll[2] & SUBAFTERNOT ) != 0 ) *level = AC.Labels[ll[3]]; } -#endif -/* AT.WorkPointer = AN.RepFunList; - return(match); */ goto nextlevel; case SUBONCE : AN.UseFindOnly = 0; @@ -422,7 +453,7 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) power = FindMulti(BHEAD term,m); if ( ( power & 1 ) != 0 && msign ) term[term[0]-1] = -term[term[0]-1]; break; - case SUBALL : + case SUBVECTOR : while ( ( power = FindAll(BHEAD term,m,*level,(WORD *)0) ) != 0 ) { if ( ( power & 1 ) != 0 && msign ) term[term[0]-1] = -term[term[0]-1]; match = 1; @@ -470,21 +501,82 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) numdollars = 0; } match = 1; -#if IDHEAD > 3 if ( ( ll[2] & SUBAFTER ) != 0 ) { *level = AC.Labels[ll[3]]; } -#endif } else { -#if IDHEAD > 3 if ( ( ll[2] & SUBAFTERNOT ) != 0 ) { *level = AC.Labels[ll[3]]; } -#endif power = 0; } goto nextlevel; + case SUBALL: + AN.UseFindOnly = 0; + CC = cbuf+AT.allbufnum; + oldallnumrhs = CC->numrhs; + AddRHS(AT.allbufnum,1); + AT.idallflag = 1; + AT.idallmaxnum = ll[3]; + AT.idallnum = 0; + if ( FindRest(BHEAD AN.termbuffer,m) || AT.idallflag > 1 ) { + WORD *t, *tstop, *tt, first = 1, ii; + power = 1; + if ( msign ) term[term[0]-1] = -term[term[0]-1]; +/* + If we come here the matches are all already in the + compiler buffer. All we need to do is take out all + functions and replace them by a SUBEXPRESSION that + points to this buffer. + Note: the PolyFun/PolyRatFun should be excluded from this. + This works because each match writes incrementally to + the buffer using the routine SubsInAll. + + The call to WildDollars should be made in Generator..... +*/ + t = term; tstop = t + *t; ii = ABS(tstop[-1]); tstop -= ii; + tt = AT.WorkPointer+1; + t++; + while ( t < tstop ) { + if ( *t >= FUNCTION && *t != AR.PolyFun && *t != AR.PolyFunInv ) { + if ( first ) { /* SUBEXPRESSION */ + *tt++ = SUBEXPRESSION; + *tt++ = SUBEXPSIZE; + *tt++ = CC->numrhs; + *tt++ = 1; + *tt++ = AT.allbufnum; + FILLSUB(tt) + first = 0; + } + t += t[1]; + } + else { + i = t[1]; NCOPY(tt,t,i); + } + } + NCOPY(tt,t,ii); + ii = tt-AT.WorkPointer; + *(AT.WorkPointer) = ii; + tt = AT.WorkPointer; t = term; + NCOPY(t,tt,ii); + + if ( ( ll[2] & SUBAFTER ) != 0 ) { /* ifmatch -> */ + *level = AC.Labels[ll[3]]; + } + TermFree(AN.termbuffer,"id,all"); + AN.termbuffer = OldTermBuffer; + AT.WorkPointer = AN.RepFunList; + AT.idallflag = 0; + TransferBuffer(AT.aebufnum,AT.ebufnum,AT.allbufnum); + return(1); + } + AT.idallflag = 0; + power = 0; + CC->numrhs = oldallnumrhs; + TermFree(AN.termbuffer,"id,all"); + AN.termbuffer = OldTermBuffer; + break; default : break; } @@ -495,19 +587,15 @@ WORD TestMatch(PHEAD WORD *term, WORD *level) numdollars = 0; } match = 1; -#if IDHEAD > 3 - if ( ( ll[2] & SUBAFTER ) != 0 ) { + if ( ( ll[2] & SUBAFTER ) != 0 ) { /* ifmatch -> */ *level = AC.Labels[ll[3]]; } -#endif } else { AT.WorkPointer = AN.RepFunList; -#if IDHEAD > 3 - if ( ( ll[2] & SUBAFTERNOT ) != 0 ) { + if ( ( ll[2] & SUBAFTERNOT ) != 0 ) { /* ifnomatch -> */ *level = AC.Labels[ll[3]]; } -#endif } nextlevel:; } while ( (*level)++ < AR.Cnumlhs && C->lhs[*level][0] == TYPEIDOLD ); @@ -1263,7 +1351,7 @@ CopRest: t = tstop; && C->lhs[level][0] == TYPEIDOLD ) { m = C->lhs[level]; m += IDHEAD; - if ( m[-IDHEAD+2] == SUBALL ) { + if ( m[-IDHEAD+2] == SUBVECTOR ) { if ( ( vv = m[m[1]+3] ) == r[1] ) { OnePV: TwoProto = AN.FullProto; TwoPV: m = AT.WorkPointer; @@ -1384,7 +1472,7 @@ Hitlevel1: level2 = level; if ( !par ) m = C->lhs[level2]; else m = par; m += IDHEAD; - if ( m[-IDHEAD+2] == SUBALL ) { + if ( m[-IDHEAD+2] == SUBVECTOR ) { if ( ( vv = m[m[1]+3] ) == r[1] ) goto OnePV; else if ( vv >= OffNum ) { @@ -1440,7 +1528,7 @@ Hitlevel2: level2 = level; if ( !par ) m = C->lhs[level2]; else m = par; m += IDHEAD; - if ( m[-IDHEAD+2] == SUBALL ) { + if ( m[-IDHEAD+2] == SUBVECTOR ) { if ( ( vv = m[6] ) == *r ) goto OnePV; else if ( vv >= OffNum ) { @@ -1849,6 +1937,227 @@ int TestSelect(WORD *term, WORD *setp) /* #] TestSelect : + #[ SubsInAll : VOID SubsInAll() + + This routine takes a match in id,all and stores it away in + the AT.allbufnum 'compiler' buffer, after taking out the pattern. + The main problem here is that id,all usually has (lots of) wildcards + and their assignments are on stack and the difficult ones are in + AT.ebufnum. Popping the stack while looking for more matches would + loose those. Hence we have to copy them into yet another compiler + buffer: AT.aebufnum. Because this may involve many matches and + because the original term has only a limited number of arguments, + it will pay to look for already existing ones in this buffer. + (to be done later). +*/ + +VOID SubsInAll(PHEAD0) +{ + GETBIDENTITY + WORD *TemTerm; + WORD *t, *m, *term; + WORD *tstop, *mstop, *xstop; + WORD nt, *fill, nq, mt; + WORD *tcoef, i = 0; + WORD PutExpr = 0, sign = 0; +/* + We start with building the term in the WorkSpace. + Afterwards we will transfer it to AT.allbufnum. + We have to make sure there is room in the WorkSpace. +*/ + AT.idallflag = 2; + TemTerm = AT.WorkPointer; + if ( ( (WORD *)(((UBYTE *)(AT.WorkPointer)) + AM.MaxTer*2) ) > AT.WorkTop ) { + MLOCK(ErrorMessageLock); + MesWork(); + MUNLOCK(ErrorMessageLock); + Terminate(-1); + } + m = AN.patternbuffer + IDHEAD; m += m[1]; + mstop = m + *m; + m++; + term = AN.termbuffer; + tstop = term + *term; tcoef = tstop-1; tstop -= ABS(tstop[-1]); + t = term; + t++; + fill = TemTerm; + fill++; + while ( m < mstop ) { + while ( t < tstop ) { + nt = WORDDIF(t,term); + for ( mt = 0; mt < AN.RepFunNum; mt += 2 ) { + if ( nt == AN.RepFunList[mt] ) break; + } + if ( mt >= AN.RepFunNum ) { + nq = t[1]; + NCOPY(fill,t,nq); + } + else { + WORD *oldt = 0; + if ( *m == GAMMA && m[1] != FUNHEAD+1 ) { + oldt = t; + if ( ( i = AN.RepFunList[mt+1] ) > 0 ) { + *fill++ = GAMMA; + *fill++ = i + FUNHEAD+1; + FILLFUN(fill) + nq = i + 1; + t += FUNHEAD; + NCOPY(fill,t,nq); + } + t = oldt; + } + else if ( ( *t == LEVICIVITA ) || ( *t >= FUNCTION + && (functions[*t-FUNCTION].symmetric & ~REVERSEORDER) == ANTISYMMETRIC ) + ) sign += AN.RepFunList[mt+1]; + else if ( *m >= FUNCTION+WILDOFFSET + && (functions[*m-FUNCTION-WILDOFFSET].symmetric & ~REVERSEORDER) == ANTISYMMETRIC + ) sign += AN.RepFunList[mt+1]; + if ( !PutExpr ) { + WORD *pstart = fill, *p, *w, *ww; + xstop = t + t[1]; + t = AN.FullProto; + nq = t[1]; + t[3] = 1; + NCOPY(fill,t,nq); + t = xstop; + PutExpr = 1; +/* + Here we need provisions for keeping wildcard matches + that reside in AT.ebufnum. We will move them to + AT.aebufnum. + Problem: the SUBEXPRESSION assumes automatically + that the compiler buffer is AT.ebufnum. We have to + correct that in TranferBuffer. +*/ + p = pstart + SUBEXPSIZE; + while ( p < fill ) { + switch ( *p ) { + case SYMTOSUB: + case VECTOSUB: + case INDTOSUB: + case ARGTOARG: + case ARLTOARL: + w = cbuf[AT.ebufnum].rhs[p[3]]; + ww = cbuf[AT.ebufnum].rhs[p[3]+1]; +/* + Here we could search for whether this + object sits in the buffer already. + To be done later. + By the way: ww-w fits inside a WORD. +*/ + AddRHS(AT.aebufnum,1); + AddNtoC(AT.aebufnum,ww-w,w); + p[3] = cbuf[AT.aebufnum].numrhs; + cbuf[AT.aebufnum].rhs[p[3]+1] = cbuf[AT.aebufnum].Pointer; + p += p[1]; + break; + case FROMSET: + case SETTONUM: + case LOADDOLLAR: + p += p[1]; + break; + default: + p += p[1]; + break; + } + + } + } + else t += t[1]; + if ( *m == GAMMA && m[1] != FUNHEAD+1 ) { + i = oldt[1] - m[1] - i; + if ( i > 0 ) { + *fill++ = GAMMA; + *fill++ = i + FUNHEAD+1; + FILLFUN(fill) + *fill++ = oldt[FUNHEAD]; + t = t - i; + NCOPY(fill,t,i); + } + } + break; + } + } + m += m[1]; + } + while ( t < tstop ) *fill++ = *t++; + if ( !PutExpr ) { + t = AN.FullProto; + nq = t[1]; + t[3] = 1; + NCOPY(fill,t,nq); + } + t = tcoef; + nq = ABS(*t); + t = tstop; + NCOPY(fill,t,nq); + if ( sign ) { + if ( ( sign & 1 ) != 0 ) fill[-1] = -fill[-1]; + } + *TemTerm = fill-TemTerm; +/* + And now we copy this to AT.allbufnum +*/ + AddNtoC(AT.allbufnum,TemTerm[0],TemTerm); + AN.RepFunNum = 0; +} + +/* + #] SubsInAll : + #[ TransferBuffer : + + Adds the whole content of a (compiler)buffer to another buffer. + In spectator we have an expression in the RHS that needs the + wildcard resolutions adapted by an offset. +*/ + +VOID TransferBuffer(int from,int to,int spectator) +{ + CBUF *C = cbuf + spectator; + CBUF *Cf = cbuf + from; + CBUF *Ct = cbuf + to; + int offset = Ct->numrhs; + LONG i; + WORD *t, *tt, *ttt, *tstop, size; + for ( i = 1; i <= Cf->numrhs; i++ ) { + size = Cf->rhs[i+1]-Cf->rhs[i]; + AddRHS(to,1); + AddNtoC(to,size,Cf->rhs[i]); + } + Ct->rhs[Ct->numrhs+1] = Ct->Pointer; + Cf->numrhs = 0; +/* + Now we have to update the 'pointers' in the spectator. +*/ + t = C->rhs[C->numrhs]; + while ( *t ) { + tt = t+1; t += *t; + tstop = t-ABS(t[-1]); + while ( tt < tstop ) { + if ( *tt == SUBEXPRESSION ) { + ttt = tt+SUBEXPSIZE; tt += tt[1]; + while ( ttt < tt ) { + switch ( *ttt ) { + case SYMTOSUB: + case VECTOSUB: + case INDTOSUB: + case ARGTOARG: + case ARLTOARL: + ttt[3] += offset; + break; + default: + break; + } + ttt += 4; + } + } + else tt += tt[1]; + } + } +} + +/* + #] TransferBuffer : #[ TakeIDfunction : */ diff --git a/sources/proces.c b/sources/proces.c index 215ac320..0d99bc94 100644 --- a/sources/proces.c +++ b/sources/proces.c @@ -257,7 +257,7 @@ WORD Processor() if ( AR.expchanged ) AR.expflags |= ISUNMODIFIED; AR.GetFile = 0; /* - #] in memory : + #] in memory : */ } else { @@ -286,7 +286,12 @@ WORD Processor() case INTOHIDELEXPRESSION: case INTOHIDEGEXPRESSION: AR.outtohide = 1; +/* + BugFix 12-feb-2016 + This may not work when the file is open and we move around. AR.hidefile->POfill = AR.hidefile->POfull; +*/ + SetEndHScratch(AR.hidefile,&position); case LOCALEXPRESSION: case GLOBALEXPRESSION: AR.GetFile = 0; diff --git a/sources/smart.c b/sources/smart.c index baee7b57..54cb0f71 100644 --- a/sources/smart.c +++ b/sources/smart.c @@ -96,6 +96,16 @@ int StudyPattern(WORD *lhs) p += p[1]; } if ( numfun == 0 ) return(0); + if ( ( lhs[2] & SUBMASK ) == SUBALL ) { + p = pat + 1; + while ( p < info ) { + if ( *p == SYMBOL || *p == VECTOR || *p == DOTPRODUCT || *p == INDEX ) { + MesPrint("&id,all can have only functions and/or tensors in the lhs."); + return(1); + } + p += p[1]; + } + } /* We need now some room for the information about the functions */ diff --git a/sources/startup.c b/sources/startup.c index 953d78f6..e04e8822 100644 --- a/sources/startup.c +++ b/sources/startup.c @@ -855,6 +855,8 @@ VOID StartVariables() #ifndef WITHPTHREADS AT.ebufnum = inicbufs(); /* Buffer for extras during execution */ AT.fbufnum = inicbufs(); /* Buffer for caching in factorization */ + AT.allbufnum = inicbufs(); /* Buffer for id,all */ + AT.aebufnum = inicbufs(); /* Buffer for id,all */ #else AS.MasterSort = 0; #endif diff --git a/sources/store.c b/sources/store.c index d9db0dbe..bd4d34f9 100644 --- a/sources/store.c +++ b/sources/store.c @@ -265,6 +265,91 @@ WORD ResetScratch() /* #] ResetScratch : + #[ ReadFromScratch : + + Routine is used to copy files from scratch to hide. +*/ + +int ReadFromScratch(FILEHANDLE *fi, POSITION *pos, UBYTE *buffer, POSITION *length) +{ + GETIDENTITY + LONG l = BASEPOSITION(*length); + if ( fi->handle < 0 ) { + memcpy(buffer,fi->POfill,l); + } + else { + SeekFile(fi->handle,pos,SEEK_SET); + if ( ReadFile(fi->handle,buffer,l) != l ) { + if ( fi == AR.hidefile ) + MesPrint("Error reading from hide file."); + else + MesPrint("Error reading from scratch file."); + return(-1); + } + } + return(0); +} + +/* + #] ReadFromScratch : + #[ AddToScratch : + + Routine is used to copy files from scratch to hide. +*/ + +int AddToScratch(FILEHANDLE *fi, POSITION *pos, UBYTE *buffer, POSITION *length, + int withflush) +{ + GETIDENTITY + LONG l = BASEPOSITION(*length), avail; + fi->POfill = fi->POfull; + while ( fi->POfill+l/sizeof(WORD) > fi->POstop ) { + avail = (fi->POstop-fi->POfill)*sizeof(WORD); + if ( avail > 0 ) { + memcpy(fi->POfill,buffer,avail); + l -= avail; buffer += avail; + } + if ( fi->handle < 0 ) { + if ( ( fi->handle = (WORD)CreateFile(fi->name) ) < 0 ) { + if ( fi == AR.hidefile ) + MesPrint("Cannot create hide file %s",fi->name); + else + MesPrint("Cannot create scratch file %s",fi->name); + return(-1); + } + PUTZERO(fi->POposition); + } + SeekFile(fi->handle,&(fi->POposition),SEEK_SET); + if ( WriteFile(fi->handle,(UBYTE *)fi->PObuffer,fi->POsize) != fi->POsize ) + goto writeerror; + ADDPOS(fi->POposition,fi->POsize); + fi->POfill = fi->POfull = fi->PObuffer; + } + if ( l > 0 ) { + memcpy(fi->POfill,buffer,l); + fi->POfill += l/sizeof(WORD); + fi->POfull = fi->POfill; + } + if ( withflush && fi->handle >= 0 && fi->POfill > fi->PObuffer ) { /* flush */ + l = (LONG)fi->POfill - (LONG)fi->PObuffer; + SeekFile(fi->handle,&(fi->POposition),SEEK_SET); + if ( WriteFile(fi->handle,(UBYTE *)fi->PObuffer,l) != l ) goto writeerror; + ADDPOS(fi->POposition,fi->POsize); + fi->POfill = fi->POfull = fi->PObuffer; + } + if ( withflush && fi->handle >= 0 ) + SETBASEPOSITION(fi->filesize,TellFile(fi->handle)); + return(0); +writeerror: + if ( fi == AR.hidefile ) + MesPrint("Error writing to hide file. Disk full?"); + else + MesPrint("Error writing to scratch file. Disk full?"); + return(-1); +} + +/* + #] AddToScratch : #[ CoSave : The syntax of the save statement is: diff --git a/sources/structs.h b/sources/structs.h index 60483094..22aa0188 100644 --- a/sources/structs.h +++ b/sources/structs.h @@ -1953,6 +1953,11 @@ struct T_const { int mfac; /* (T) size of the pfac array. */ int ebufnum; /* (R) extra compiler buffer */ int fbufnum; /* extra compiler buffer for factorization cache */ + int allbufnum; /* extra compiler buffer for id,all */ + int aebufnum; /* extra compiler buffer for id,all */ + int idallflag; /* indicates use of id,all buffers */ + int idallnum; + int idallmaxnum; int WildcardBufferSize; /* () local copy for updates */ #ifdef WITHPTHREADS int identity; /* () When we work with B->T */ @@ -2000,12 +2005,12 @@ struct T_const { WORD fromindex; /* Tells the compare routine whether call from index */ #ifdef WITHPTHREADS #ifdef WITHSORTBOTS - PADPOINTER(4,20,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); + PADPOINTER(4,25,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); #else - PADPOINTER(4,18,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); + PADPOINTER(4,23,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); #endif #else - PADPOINTER(4,16,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); + PADPOINTER(4,21,100+SUBEXPSIZE*4+FUNHEAD*2+ARGHEAD*2,0); #endif }; /* @@ -2064,6 +2069,7 @@ struct N_const { TRACES *tracestack; /* () used in opera.c */ WORD *selecttermundo; /* () Used in pattern.c */ WORD *patternbuffer; /* () Used in pattern.c */ + WORD *termbuffer; /* () Used in pattern.c */ WORD **PoinScratch; /* () used in reshuf.c */ WORD **FunScratch; /* () used in reshuf.c */ WORD *RenumScratch; /* () used in reshuf.c */ @@ -2157,29 +2163,29 @@ struct N_const { #ifdef WITHPTHREADS #ifdef WHICHSUBEXPRESSION #ifdef WITHZLIB - PADPOSITION(54,11,23,26,sizeof(SHvariables)); + PADPOSITION(55,11,23,26,sizeof(SHvariables)); #else - PADPOSITION(52,11,23,26,sizeof(SHvariables)); + PADPOSITION(53,11,23,26,sizeof(SHvariables)); #endif #else #ifdef WITHZLIB - PADPOSITION(53,9,23,24,sizeof(SHvariables)); + PADPOSITION(54,9,23,24,sizeof(SHvariables)); #else - PADPOSITION(51,9,23,24,sizeof(SHvariables)); + PADPOSITION(52,9,23,24,sizeof(SHvariables)); #endif #endif #else #ifdef WHICHSUBEXPRESSION #ifdef WITHZLIB - PADPOSITION(52,9,23,26,sizeof(SHvariables)); + PADPOSITION(53,9,23,26,sizeof(SHvariables)); #else - PADPOSITION(50,9,23,26,sizeof(SHvariables)); + PADPOSITION(51,9,23,26,sizeof(SHvariables)); #endif #else #ifdef WITHZLIB - PADPOSITION(51,7,23,24,sizeof(SHvariables)); + PADPOSITION(52,7,23,24,sizeof(SHvariables)); #else - PADPOSITION(49,7,23,24,sizeof(SHvariables)); + PADPOSITION(50,7,23,24,sizeof(SHvariables)); #endif #endif #endif diff --git a/sources/threads.c b/sources/threads.c index e1ef691c..fddb7635 100644 --- a/sources/threads.c +++ b/sources/threads.c @@ -586,6 +586,8 @@ ALLPRIVATES *InitializeOneThread(int identity) LOCK(availabilitylock); AT.ebufnum = inicbufs(); /* Buffer for extras during execution */ AT.fbufnum = inicbufs(); /* Buffer for caching in factorization */ + AT.allbufnum = inicbufs(); /* Buffer for id,all */ + AT.aebufnum = inicbufs(); /* Buffer for id,all */ UNLOCK(availabilitylock); AT.RepCount = (int *)Malloc1((LONG)((AM.RepMax+3)*sizeof(int)),"repeat buffers");