62 int StudyPattern(WORD *lhs)
65 WORD *fullproto, *pat, *p, *p1, *p2, *pstop, *info, f, nn;
66 int numfun = 0, numsym = 0, allwilds = 0, i, j, k, nc;
67 FUN_INFO *finf, *fmin, *f1, *f2, funscratch;
69 fullproto = lhs + IDHEAD;
71 pat = fullproto + fullproto[1];
76 if ( *p >= FUNCTION ) {
79 if ( nn >= WILDOFFSET ) nn -= WILDOFFSET;
84 if ( ( functions[nn].symmetric == SYMMETRIC ) ||
85 ( functions[nn].symmetric == ANTISYMMETRIC ) ) {
86 p2 = p+p[1]; p1 = p+FUNHEAD;
88 if ( *p1 == FUNNYWILD ) {
89 MesPrint(
"&Argument field wildcards are not allowed inside (anti)symmetric functions or tensors");
98 if ( numfun == 0 )
return(0);
102 if ( numfun > AN.numfuninfo ) {
103 if ( AN.FunInfo ) M_free(AN.FunInfo,
"funinfo");
104 AN.numfuninfo = numfun + 10;
112 if ( *p >= FUNCTION ) AN.FunInfo[i++].location = p;
115 for ( i = 0, finf = AN.FunInfo; i < numfun; i++, finf++ ) {
119 if ( f > FUNCTION+WILDOFFSET ) f -= WILDOFFSET;
120 finf->numargs = finf->numfunnies = finf->numwildcards = 0;
121 finf->symmet = functions[f-FUNCTION].symmetric;
122 finf->tensor = functions[f-FUNCTION].spec;
123 finf->commute = functions[f-FUNCTION].commute;
124 if ( finf->tensor >= TENSORFUNCTION ) {
126 while ( p < pstop ) {
127 if ( *p == FUNNYWILD ) {
128 finf->numfunnies++; p+= 2;
continue;
131 if ( *p >= AM.OffsetVector + WILDOFFSET && *p < MINSPEC ) {
132 finf->numwildcards++;
136 if ( *p >= AM.OffsetIndex + WILDOFFSET &&
137 *p <= AM.OffsetIndex + 2*WILDOFFSET ) finf->numwildcards++;
145 while ( p < pstop ) {
146 if ( *p > 0 ) { finf->numargs++; p += *p;
continue; }
147 if ( *p <= -FUNCTION ) {
148 if ( *p <= -FUNCTION - WILDOFFSET ) finf->numwildcards++;
151 else if ( *p == -SYMBOL ) {
152 if ( p[1] >= 2*MAXPOWER ) finf->numwildcards++;
155 else if ( *p == -INDEX ) {
156 if ( p[1] >= AM.OffsetIndex + WILDOFFSET &&
157 p[1] <= AM.OffsetIndex + 2*WILDOFFSET ) finf->numwildcards++;
160 else if ( *p == -VECTOR || *p == -MINVECTOR ) {
161 if ( p[1] >= AM.OffsetVector + WILDOFFSET && p[1] < MINSPEC ) {
162 finf->numwildcards++;
166 else if ( *p == -ARGWILD ) {
174 if ( finf->symmet ) {
176 allwilds += finf->numwildcards + finf->numfunnies;
179 if ( numsym == 0 )
return(0);
180 if ( allwilds == 0 )
return(0);
189 for ( nc = numfun-1; nc >= 0; nc-- ) {
if ( AN.FunInfo[nc].commute )
break; }
192 for ( i = nc+2; i < numfun; i++ ) {
194 if ( ( finf->symmet < fmin->symmet ) || (
195 ( finf->symmet == fmin->symmet ) &&
196 ( ( finf->numwildcards+finf->numfunnies < fmin->numwildcards+fmin->numfunnies )
197 || ( ( finf->numwildcards+finf->numfunnies == fmin->numwildcards+fmin->numfunnies )
198 && ( finf->numwildcards < fmin->numfunnies ) ) ) ) ) {
199 funscratch = AN.FunInfo[i];
200 AN.FunInfo[i] = AN.FunInfo[i-1];
201 AN.FunInfo[i-1] = funscratch;
202 for ( j = i-1; j > nc && j > 0; j-- ) {
205 if ( ( f1->symmet < f2->symmet ) || (
206 ( f1->symmet == f2->symmet ) &&
207 ( ( f1->numwildcards+f1->numfunnies < f2->numwildcards+f2->numfunnies )
208 || ( ( f1->numwildcards+f1->numfunnies == f2->numwildcards+f2->numfunnies )
209 && ( f1->numwildcards < f2->numfunnies ) ) ) ) ) {
210 funscratch = AN.FunInfo[j];
211 AN.FunInfo[j] = AN.FunInfo[j-1];
212 AN.FunInfo[j-1] = funscratch;
225 for ( i = 0; i < numfun; i++ ) {
227 for ( k = 0; k <= nc; k++ ) {
228 if ( AN.FunInfo[k].commute ) {
229 p1 = AN.FunInfo[k].location; j = p1[1];
234 else if ( AN.FunInfo[i].commute == 0 ) {
235 p1 = AN.FunInfo[i].location; j = p1[1];
239 p = pat + 1; p1 = info;
240 while ( p1 < p2 ) *p++ = *p1++;
245 for ( i = 0; i < numfun; i++ ) {
247 for ( k = 0; k <= nc; k++ ) {
248 if ( AN.FunInfo[k].commute ) {
249 finf = AN.FunInfo + k;
250 *p2++ = finf->numargs;
251 *p2++ = finf->numwildcards;
252 *p2++ = finf->numfunnies;
253 *p2++ = finf->symmet;
257 else if ( AN.FunInfo[i].commute == 0 ) {
258 finf = AN.FunInfo + i;
259 *p2++ = finf->numargs;
260 *p2++ = finf->numwildcards;
261 *p2++ = finf->numfunnies;
262 *p2++ = finf->symmet;
278 int MatchIsPossible(WORD *pattern, WORD *term)
281 WORD *info = pattern + *pattern;
282 WORD *t, *tstop, *tt, *inf, *p;
283 int numfun = 0, inpat, i, j, numargs;
290 while ( t < tstop ) {
291 if ( *t >= FUNCTION ) numfun++;
294 if ( numfun == 0 )
goto NotPossible;
295 if ( *info == SETSET ) info += info[1];
297 if ( inpat > numfun )
goto NotPossible;
301 if ( numfun > AN.numfuninfo ) {
302 if ( AN.FunInfo ) M_free(AN.FunInfo,
"funinfo");
303 AN.numfuninfo = numfun + 10;
306 t = term + 1; finf = AN.FunInfo;
307 while ( t < tstop ) {
308 if ( *t >= FUNCTION ) {
310 if ( functions[*t-FUNCTION].spec >= TENSORFUNCTION ) {
311 numargs = t[1]-FUNHEAD;
323 finf->numargs = numargs;
332 for ( i = 0, inf = info+1, p = pattern+1; i < inpat; i++, inf += 4, p+=p[1] ) {
333 if ( inf[2] )
continue;
334 if ( *p >= FUNCTION+WILDOFFSET )
continue;
335 for ( j = 0, finf = AN.FunInfo; j < numfun; j++, finf++ ) {
336 if ( *p == *(finf->location) && *inf == finf->numargs ) {
337 finf->numargs = -finf->numargs-1;
341 if ( j >= numfun )
goto NotPossible;
343 for ( i = 0, inf = info+1, p = pattern+1; i < inpat; i++, inf += 4, p+=p[1] ) {
344 if ( inf[2] )
continue;
345 if ( *p < FUNCTION+WILDOFFSET )
continue;
346 for ( j = 0, finf = AN.FunInfo; j < numfun; j++, finf++ ) {
347 if ( *inf == finf->numargs ) {
348 finf->numargs = -finf->numargs-1;
352 if ( j >= numfun )
goto NotPossible;
354 for ( i = 0, inf = info+1, p = pattern+1; i < inpat; i++, inf += 4, p+=p[1] ) {
355 if ( inf[2] == 0 )
continue;
356 if ( *p >= FUNCTION+WILDOFFSET )
continue;
357 for ( j = 0, finf = AN.FunInfo; j < numfun; j++, finf++ ) {
358 if ( *p == *(finf->location) && *inf <= finf->numargs ) {
359 finf->numargs = -finf->numargs-1;
363 if ( j >= numfun )
goto NotPossible;
365 for ( i = 0, inf = info+1, p = pattern+1; i < inpat; i++, inf += 4, p+=p[1] ) {
366 if ( inf[2] == 0 )
continue;
367 if ( *p < FUNCTION+WILDOFFSET )
continue;
368 for ( j = 0, finf = AN.FunInfo; j < numfun; j++, finf++ ) {
369 if ( *inf <= finf->numargs ) {
370 finf->numargs = -finf->numargs-1;
374 if ( j >= numfun )
goto NotPossible;