• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tueda / form / 18994787624

01 Nov 2025 09:29AM UTC coverage: 56.953% (-0.1%) from 57.071%
18994787624

push

github

tueda
build: fix coverage flags

* -coverage -> --coverage
* no optimization (-O0)

46394 of 81460 relevant lines covered (56.95%)

5394012.23 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.23
/sources/function.c
1
/** @file function.c
2
 * 
3
 *  The file with the central routines for the pattern matching of
4
 *        functions and their arguments.
5
 *        The file also contains the routines for the execution of the
6
 *        Symmetrize statement and its variations (like antisymmetrize etc).
7
 */
8
/* #[ License : */
9
/*
10
 *   Copyright (C) 1984-2023 J.A.M. Vermaseren
11
 *   When using this file you are requested to refer to the publication
12
 *   J.A.M.Vermaseren "New features of FORM" math-ph/0010025
13
 *   This is considered a matter of courtesy as the development was paid
14
 *   for by FOM the Dutch physics granting agency and we would like to
15
 *   be able to track its scientific use to convince FOM of its value
16
 *   for the community.
17
 *
18
 *   This file is part of FORM.
19
 *
20
 *   FORM is free software: you can redistribute it and/or modify it under the
21
 *   terms of the GNU General Public License as published by the Free Software
22
 *   Foundation, either version 3 of the License, or (at your option) any later
23
 *   version.
24
 *
25
 *   FORM is distributed in the hope that it will be useful, but WITHOUT ANY
26
 *   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27
 *   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
28
 *   details.
29
 *
30
 *   You should have received a copy of the GNU General Public License along
31
 *   with FORM.  If not, see <http://www.gnu.org/licenses/>.
32
 */
33
/* #] License : */ 
34
/*
35
          #[ Includes : function.c
36
*/
37

38
#include "form3.h"
39

40
/*
41
          #] Includes : 
42
         #[ Utilities :
43
                 #[ MakeDirty :
44

45
                Routine finds the function with the address x in it
46
                and mark all arguments that contain x as dirty.
47
                if par == 0 term is a full term, else term is the start of a 
48
                function
49
*/
50

51
int MakeDirty(WORD *term, WORD *x, WORD par)
24✔
52
{
53
        WORD *next, *n;
54
        if ( !par ) {
24✔
55
                next = term; next += *term;
×
56
                next -= ABS(next[-1]);
×
57
                term++;
×
58
                if ( x < term ) return(0);
×
59
                if ( x >= next ) return(0);
×
60
                while ( term < next ) {
×
61
                        n = term + term[1];
×
62
                        if ( x < n ) break;
×
63
                        term = n;
×
64
                }
65
/*                next = n; */
66
        }
67
        else {
68
                next = term + term[1];
24✔
69
                if ( x < term || x >= next ) return(0);
24✔
70
        }
71
        if ( *term < FUNCTION ) return(0);
24✔
72
        if ( functions[*term-FUNCTION].spec >= TENSORFUNCTION ) return(0);
24✔
73
        term += FUNHEAD;
24✔
74
        if ( x < term ) return(0);
24✔
75
        next = term; NEXTARG(next)
24✔
76
        while ( x >= next ) { term = next; NEXTARG(next) }
24✔
77
        if ( *term < 0 ) return(0);
24✔
78
        term[1] = 1;
×
79
        term += ARGHEAD;
×
80
        if ( x < term ) return(1);
×
81
        next = term + *term;
×
82
        while ( x >= next ) { term = next; next += *next; }
×
83
        MakeDirty(term,x,0);
×
84
        return(1);
×
85
}
86

87
/*
88
                 #] MakeDirty : 
89
                 #[ MarkDirty :
90

91
                Routine marks all functions dirty with the given flags.
92
                Is to be used when there is a possibility that symmetrization
93
                properties of functions may have changed. In that case we play
94
                it safe.
95
*/
96

97
void MarkDirty(WORD *term, WORD flags)
816✔
98
{
99
        WORD *t, *r, *m, *tstop;
100
        GETSTOP(term,tstop);
816✔
101
        t = term+1;
816✔
102
        while ( t < tstop ) {
1,788✔
103
                if ( *t < FUNCTION ) { t += t[1]; continue; }
972✔
104
                t[2] |= flags;
456✔
105
                if ( *t < FUNCTION+WILDOFFSET && functions[*t-FUNCTION].spec > 0 ) {
456✔
106
                        t += t[1]; continue;
48✔
107
                }
108
                if ( *t >= FUNCTION+WILDOFFSET && functions[*t-FUNCTION-WILDOFFSET].spec > 0 ) {
408✔
109
                        t += t[1]; continue;
×
110
                }
111
                r = t + FUNHEAD;
408✔
112
                t += t[1];
408✔
113
                while ( r < t ) {
1,146✔
114
                        if ( *r <= 0 ) {
738✔
115
                                if ( *r <= -FUNCTION ) r++;
618✔
116
                                else r += 2;
606✔
117
                                continue;
618✔
118
                        }
119
                        r[1] |= DIRTYFLAG;
120✔
120
                        m = r + ARGHEAD;
120✔
121
                        r += *r;
120✔
122
                        while ( m < r ) {
270✔
123
                                MarkDirty(m,flags);
150✔
124
                                m += *m;
150✔
125
                        }
126
                }
127
        }
128
}
816✔
129

130
/*
131
                 #] MarkDirty : 
132
                 #[ PolyFunDirty :
133

134
                Routine marks the PolyFun or the PolyRatFun dirty.
135
                This is used when there is modular calculus and the modulus
136
                has changed for the current module.
137
*/
138

139
void PolyFunDirty(PHEAD WORD *term)
705,210✔
140
{
141
        GETBIDENTITY
142
        WORD *t, *tstop, *endarg;
143
        tstop = term + *term;
705,210✔
144
        tstop -= ABS(tstop[-1]);
705,210✔
145
        t = term+1;
705,210✔
146
        while ( t < tstop ) {
2,092,230✔
147
                if ( *t == AR.PolyFun ) {
1,387,020✔
148
                        if ( AR.PolyFunType == 2 ) t[2] |= MUSTCLEANPRF;
34,038✔
149
                        endarg = t + t[1];
34,038✔
150
                        t[2] |= DIRTYFLAG;
34,038✔
151
                        t += FUNHEAD;
34,038✔
152
                        while ( t < endarg ) {
86,838✔
153
                                if ( *t > 0 ) {
52,800✔
154
                                        t[1] |= DIRTYFLAG;
50,646✔
155
                                }
156
                                NEXTARG(t);
52,800✔
157
                        }
158
                }
159
                else {
160
                        t += t[1];
1,352,982✔
161
                }
162
        }
163
}
705,210✔
164

165
/*
166
                 #] PolyFunDirty : 
167
                 #[ PolyFunClean :
168

169
                Routine marks the PolyFun or the PolyRatFun clean.
170
                This is used when there is modular calculus and the modulus
171
                has changed for the current module.
172
*/
173

174
void PolyFunClean(PHEAD WORD *term)
3,002,736✔
175
{
176
        GETBIDENTITY
177
        WORD *t, *tstop;
178
        tstop = term + *term;
3,002,736✔
179
        tstop -= ABS(tstop[-1]);
3,002,736✔
180
        t = term+1;
3,002,736✔
181
        while ( t < tstop ) {
14,860,914✔
182
                if ( *t == AR.PolyFun ) {
11,858,178✔
183
                        t[2] &= ~MUSTCLEANPRF;
2,996,742✔
184
                }
185
                t += t[1];
11,858,178✔
186
        }
187
}
3,002,736✔
188

189
/*
190
                 #] PolyFunClean : 
191
                 #[ Symmetrize :
192

193
                (Anti)Symmetrizes the arguments of a function. 
194
                Nlist tells of how many arguments are involved.
195
                Nlist == 0                All arguments must be sorted.
196
                Nlist > 0                Arguments mentioned are to be sorted, rest skipped.
197
                type = SYMMETRIC       Full symmetrization
198
                type = ANTISYMMETRIC:  Full symmetrization
199
                type = CYCLESYMMETRIC: Cyclic
200
                type = RCYCLESYMMETRIC:Cyclic or reverse
201
                Return value: OR of:
202
                        0 even, 1 odd
203
                        2 equal groups
204
                        4 there was a permutation.
205

206
                The information in Lijst tells what grouping is to be applied.
207
                The information is:
208
                ngroups number of groups
209
                gsize size of groups
210
                Lijst[0]....  The groups.
211
*/
212

213
WORD Symmetrize(PHEAD WORD *func, WORD *Lijst, WORD ngroups, WORD gsize,
260,844✔
214
                WORD type)
215
{
216
        GETBIDENTITY
217
        WORD **args,**arg,nargs;
218
        WORD *to, *r, *fstop;
219
        WORD i, j, k, ff, exch, nexch, neq;
220
        WORD *a1, *a2, *a3;
221
        WORD reverseorder;
222
        if ( ( type & REVERSEORDER ) != 0 ) reverseorder = -1;
260,844✔
223
        else                                reverseorder = 1;
260,844✔
224
        type &= ~REVERSEORDER;
260,844✔
225

226
        ff = ( *func > FUNCTION ) ? functions[*func-FUNCTION].spec: 0;
260,844✔
227

228
        if ( 2*func[1] > AN.arglistsize ) {
260,844✔
229
                if ( AN.arglist ) M_free(AN.arglist,"Symmetrize");
227✔
230
                AN.arglistsize = 2*func[1] + 8;
227✔
231
                AN.arglist = (WORD **)Malloc1(AN.arglistsize*sizeof(WORD *),"Symmetrize");
227✔
232
        }
233
        arg = args = AN.arglist;
260,844✔
234
        to = AT.WorkPointer;
260,844✔
235
        r = func;
260,844✔
236
        fstop = r + r[1];
260,844✔
237
        r += FUNHEAD;
260,844✔
238
        nargs = 0;
260,844✔
239
        while ( r < fstop ) {        /* Make list of arguments */
1,107,756✔
240
                *arg++ = r;
846,912✔
241
                nargs++;
846,912✔
242
                if ( ff ) {
846,912✔
243
                        if ( *r == FUNNYWILD ) r++;
205,446✔
244
                        r++;
205,446✔
245
                }
246
                else { NEXTARG(r); }
641,466✔
247
        }
248
        exch = 0;
260,844✔
249
        nexch = 0;
260,844✔
250
        neq = 0;
260,844✔
251
        a1 = Lijst;
260,844✔
252
        if ( type == SYMMETRIC || type == ANTISYMMETRIC ) {
260,844✔
253
        for ( i = 1; i < ngroups; i++ ) {
792,102✔
254
                a3 = a2 = a1 + gsize;
543,450✔
255
                k = reverseorder*CompGroup(BHEAD ff,args,a1,a2,gsize);
543,450✔
256
                if ( k < 0 ) {
543,450✔
257
                        j = i-1;
88,494✔
258
                        for(;;) {
259
                                for ( k = 0; k < gsize; k++ ) {
291,816✔
260
                                        r = args[a1[k]]; args[a1[k]] = args[a2[k]]; args[a2[k]] = r;
145,908✔
261
                                }
262
                                exch ^= 1;
145,908✔
263
                                nexch = 4;
145,908✔
264
                                if ( j <= 0 ) break;
145,908✔
265
                                a1 -= gsize;
81,555✔
266
                                a2 -= gsize;
81,555✔
267
                                k = reverseorder*CompGroup(BHEAD ff,args,a1,a2,gsize);
81,555✔
268
                                if ( k == 0 ) neq = 2;
81,555✔
269
                                if ( k >= 0 ) break;
81,555✔
270
                                j--;
57,414✔
271
                        }
272
                }
273
                else if ( k == 0 ) neq = 2;
454,956✔
274
                a1 = a3;
543,450✔
275
        }
276
        }
277
        else if ( type == CYCLESYMMETRIC || type == RCYCLESYMMETRIC ) {
12,192✔
278
                WORD rev = 0, jmin = 0, ii, iimin;
12,192✔
279
recycle:
12,192✔
280
                for ( j = 1; j < ngroups; j++ ) {
54,810✔
281
                        for ( i = 0; i < ngroups; i++ ) {
53,046✔
282
                                iimin = jmin + i;
51,636✔
283
                                if ( iimin >= ngroups ) iimin -= ngroups;
51,636✔
284
                                ii = j + i;
51,636✔
285
                                if ( ii >= ngroups ) ii -= ngroups;
51,636✔
286
                                k = reverseorder*CompGroup(BHEAD ff,args,Lijst+gsize*iimin,Lijst+gsize*ii,gsize);
51,636✔
287
                                if ( k > 0 ) break;
51,636✔
288
                                if ( k < 0 ) { jmin = j; nexch = 4; break; }
12,372✔
289
                        }
290
                }
291
                if ( type == RCYCLESYMMETRIC && rev == 0 && ngroups > 1 ) {
12,192✔
292
                        for ( j = 0; j < ngroups; j++ ) {
×
293
                                for ( i = 0; i < ngroups; i++ ) {
×
294
                                        iimin = jmin + i;
×
295
                                        if ( iimin >= ngroups ) iimin -= ngroups;
×
296
                                        ii = j - i;
×
297
                                        if ( ii < 0 ) ii += ngroups;
×
298
                                        k = reverseorder*CompGroup(BHEAD ff,args,Lijst+gsize*iimin,Lijst+gsize*ii,gsize);
×
299
                                        if ( k > 0 ) break;
×
300
                                        if ( k < 0 ) {
×
301
                                                nexch = 4;
×
302
                                                jmin = 0;
×
303
                                                a1 = Lijst;
×
304
                                                a2 = Lijst + gsize * (ngroups-1);
×
305
                                                while ( a2 > a1 ) {
×
306
                                                        for ( k = 0; k < gsize; k++ ) {
×
307
                                                                r = args[a1[k]];
×
308
                                                                args[a1[k]] = args[a2[k]];
×
309
                                                                args[a2[k]] = r;
×
310
                                                        }
311
                                                        a1 += gsize; a2 -= gsize;
×
312
                                                }
313
                                                rev = 1;
×
314
                                                goto recycle;
×
315
                                        }
316
                                }
317
                        }
318
                }
319
                if ( jmin != 0 ) {
12,192✔
320
                        arg = AN.arglist + func[1];
1,386✔
321
                        a1 = Lijst + gsize * jmin;
1,386✔
322
                        k = gsize * ngroups;
1,386✔
323
                        a2 = Lijst + k;
1,386✔
324
                        for ( i = 0; i < k; i++ ) {
7,344✔
325
                                if ( a1 >= a2 ) a1 = Lijst;
5,958✔
326
                                *arg++ = args[*a1++];
5,958✔
327
                        }
328
                        arg = AN.arglist + func[1];
1,386✔
329
                        a1 = Lijst;
1,386✔
330
                        for ( i = 0; i < k; i++ ) args[*a1++] = *arg++;
7,344✔
331
                }
332
        }
333
        r = func;
260,844✔
334
        i = FUNHEAD;
260,844✔
335
        NCOPY(to,r,i);
1,043,376✔
336
        for ( i = 0; i < nargs; i++ ) {
1,107,756✔
337
                if ( ff ) {
846,912✔
338
                        if ( *(args[i]) == FUNNYWILD ) {
205,446✔
339
                                *to++ = *(args[i]);
1,632✔
340
                                *to++ = args[i][1];
1,632✔
341
                        }
342
                        else *to++ = *(args[i]);
203,814✔
343
                }
344
                else if ( ( j = *args[i] ) < 0 ) {
641,466✔
345
                        *to++ = j;
641,352✔
346
                        if ( j > -FUNCTION ) *to++ = args[i][1];
641,352✔
347
                }
348
                else {
349
                        r = args[i];
114✔
350
                        NCOPY(to,r,j);
8,220✔
351
                }
352
        }
353
        i = func[1];
260,844✔
354
        to = func;
260,844✔
355
        r = AT.WorkPointer;
260,844✔
356
        NCOPY(to,r,i);
2,541,264✔
357
        return ( exch | nexch | neq );
260,844✔
358
}
359

360
/*
361
                 #] Symmetrize : 
362
                 #[ CompGroup :
363

364
                        Routine compares two groups of arguments
365
                        The arguments are in args[a1[i]] and args[a2[i]]
366
                        for i = 0 to num
367
                        type indicates the type of function.
368
                        return value: -1 if there should be an exchange
369
                        0 if they are equal
370
                        1 if they are OK.
371
*/
372

373
int CompGroup(PHEAD WORD type, WORD **args, WORD *a1, WORD *a2, WORD num)
676,641✔
374
{
375
        GETBIDENTITY
376
        WORD *t1, *t2, i1, i2, n, k;
377

378
        for ( n = 0; n < num; n++ ) {
689,679✔
379
                t1 = args[a1[n]]; t2 = args[a2[n]];
676,641✔
380
                if ( type >= TENSORFUNCTION ) {
676,641✔
381
                        if ( AR.Eside == LHSIDE || AR.Eside == LHSIDEX ) {
162,336✔
382
                                if ( *t1 == FUNNYWILD ) {
47,682✔
383
                                        if ( *t2 == FUNNYWILD ) {
270✔
384
                                                if ( t1[1] < t2[1] ) return(1);
270✔
385
                                                if ( t1[1] > t2[1] ) return(-1);
×
386
                                        }
387
                                        return(-1);
×
388
                                }
389
                                else if ( *t2 == FUNNYWILD ) {
47,412✔
390
                                        return(1);
2,226✔
391
                                }
392
                                else {
393
                                        if ( *t1 < *t2 ) return(1);
45,186✔
394
                                        if ( *t1 > *t2 ) return(-1);
3,198✔
395
                                }
396
                        }
397
                        else {
398
                                if ( *t1 < *t2 ) return(1);
114,654✔
399
                                if ( *t1 > *t2 ) return(-1);
26,232✔
400
                        }
401
                }
402
                else if ( type == 0 ) {
514,305✔
403
                        if ( AC.properorderflag ) {
514,305✔
404
                                k = CompArg(t1,t2);
×
405
                                if ( k < 0 ) return(1);
×
406
                                if ( k > 0 ) return(-1);
×
407
                                NEXTARG(t1)
×
408
                                NEXTARG(t2)
×
409
                        }
410
                        else {
411
                                if ( *t1 > 0 ) {
514,305✔
412
                                        i1 = *t1 - ARGHEAD - 1;
1,437✔
413
                                        t1 += ARGHEAD + 1;
1,437✔
414
                                        if ( *t2 > 0 ) {
1,437✔
415
                                                i2 = *t2 - ARGHEAD - 1;
105✔
416
                                                t2 += ARGHEAD + 1;
105✔
417
                                                while ( i1 > 0 && i2 > 0 ) {
630✔
418
                                                        if ( *t1 > *t2 ) return(-1);
618✔
419
                                                        else if ( *t1 < *t2 ) return(1);
558✔
420
                                                        i1--; i2--; t1++; t2++;
525✔
421
                                                }
422
                                                if ( i1 > 0 ) return(-1);
12✔
423
                                                else if ( i2 > 0 ) return(1);
12✔
424
                                        }
425
/*
426
                                        This seems to be a bug. Reported by Aneesh Monahar, 28-sep-2005
427
                                        else return(1);
428
*/
429
                                        else return(-1);
1,332✔
430
                                }
431
                                else if ( *t2 > 0 ) return(1);
512,868✔
432
                                else {
433
                                        if ( *t1 != *t2 ) {
512,850✔
434
                                                if ( *t1 <= -FUNCTION && *t2 <= -FUNCTION ) {
4,224✔
435
                                                        if ( *t1 < *t2 ) return(-1);
×
436
                                                        return(1);
×
437
                                                }
438
                                                else {
439
                                                        if ( *t1 < *t2 ) return(1);
4,224✔
440
                                                        return(-1);
576✔
441
                                                }
442
                                        }
443
                                        if ( *t1 > -FUNCTION ) {
508,626✔
444
                                                if ( t1[1] != t2[1] ) {
508,626✔
445
                                                        if ( t1[1] < t2[1] ) return(1);
506,670✔
446
                                                        return(-1);
127,530✔
447
                                                }
448
                                        }
449
                                }
450
                        }
451
                }
452
        }
453
        return(0);
13,038✔
454
}
455

456
/*
457
                 #] CompGroup : 
458
                 #[ FullSymmetrize :
459

460
                Relay function for Normalize to execute a full symmetrization
461
                of a function fun. It hooks into Symmetrize according to the
462
                calling conventions for it.
463
                type = 0: Symmetrize
464
                type = 1: AntiSymmetrize
465
                type = 2: CycleSymmetrize
466
                type = 3: RCycleSymmetrize
467
                Return values:
468
                bit 0: odd permutation
469
                bit 1: identical arguments
470
                bit 2: there was a permutation.
471
*/
472

473
int FullSymmetrize(PHEAD WORD *fun, int type)
272,478✔
474
{
475
        GETBIDENTITY
476
        WORD *Lijst, count = 0;
272,478✔
477
        WORD *t, *funstop, i;
478
        int retval;
479

480
        if ( functions[*fun-FUNCTION].spec > 0 ) {
272,478✔
481
                count = fun[1] - FUNHEAD;
60,666✔
482
                for ( i = fun[1]-1; i >= FUNHEAD; i-- ) {
267,948✔
483
                        if ( fun[i] == FUNNYWILD ) count--;
207,282✔
484
                }
485
        }
486
        else {
487
                funstop = fun + fun[1];
211,812✔
488
                t = fun + FUNHEAD;
211,812✔
489
                while ( t < funstop ) { count++; NEXTARG(t) }
858,234✔
490
        }
491
        if ( count < 2 ) {
272,478✔
492
                fun[2] &= ~DIRTYSYMFLAG;
13,350✔
493
                return(0);
13,350✔
494
        }
495
        Lijst = AT.WorkPointer;
259,128✔
496
        for ( i = 0; i < count; i++ ) Lijst[i] = i;
1,098,948✔
497
        AT.WorkPointer += count;
259,128✔
498
        retval = Symmetrize(BHEAD fun,Lijst,count,1,type);
259,128✔
499
        fun[2] &= ~DIRTYSYMFLAG;
259,128✔
500
        AT.WorkPointer = Lijst;
259,128✔
501
        return(retval);
259,128✔
502
}
503

504
/*
505
                 #] FullSymmetrize : 
506
                 #[ SymGen :
507

508
                Routine does the outer work in the symmetrization.
509
                It locates the function(s) and loads up the parameters.
510
                It also studies the result.
511

512
                if params[4] = -1 and no extra -> all
513
                                      extra -> strip groups with elements too large
514
                               0  -> if group with element too large: nofun
515
                                           >0 -> must have right number of arguments
516
*/
517

518
int SymGen(PHEAD WORD *term, WORD *params, WORD num, WORD level)
240✔
519
{
520
        GETBIDENTITY
521
        WORD *t, *r, *m;
522
        WORD i, j, k, c1, c2, ngroup;
523
        WORD *rstop, Nlist, *inLijst, *Lijst, sign = 1, sumch = 0, count;
240✔
524
        DUMMYUSE(num);
525
        c1 = params[3];                /* function number */
240✔
526
        c2 = FUNCTION + WILDOFFSET;
240✔
527
        Nlist = params[4];
240✔
528
        if ( Nlist < 0 ) Nlist = 0;
240✔
529
        else Nlist = params[0] - 7;
240✔
530
        t = term;
240✔
531
        m = t + *t;
240✔
532
        m -= ABS(m[-1]);
240✔
533
        t++;
240✔
534
        while ( t < m ) {
7,440✔
535
                if ( *t == c1 || c1 > c2 ) {        /* Candidate function */
7,200✔
536
                        if ( *t >= FUNCTION && functions[*t-FUNCTION].spec
1,656✔
537
                        >= TENSORFUNCTION ) {
538
                                count = t[1] - FUNHEAD;
×
539
                        }
540
                        else {
541
                                count = 0;
1,656✔
542
                                r = t;
1,656✔
543
                                rstop = t + t[1];
1,656✔
544
                                r += FUNHEAD;
1,656✔
545
                                while ( r < rstop ) { count++; NEXTARG(r) }
8,256✔
546
                        }
547
                        if ( ( j = params[4] ) > 0 && j != count ) goto NextFun;
1,656✔
548
                        if ( j == 0 ) {
1,656✔
549
                                inLijst = params+7;
1,656✔
550
                                for ( i = 0; i < Nlist; i++ )
1,656✔
551
                                        if ( inLijst[i] > count-1 ) goto NextFun;
×
552
                        }
553

554
                        if ( Nlist > (params[0] - 7) ) Nlist = params[0] - 7;
1,656✔
555
                        Lijst = AT.WorkPointer;
1,656✔
556
                        inLijst = params + 7;
1,656✔
557
                        ngroup = params[5];
1,656✔
558
                        if ( Nlist > 0 && j < 0 ) {
1,656✔
559
                                k = 0;
×
560
                                for ( i = 0; i < ngroup; i++ ) {
×
561
                                        for ( j = 0; j < params[6]; j++ ) {
×
562
                                                if ( inLijst[j] > count+1 ) {
×
563
                                                        inLijst += params[6];
×
564
                                                        goto NextGroup;
×
565
                                                }
566
                                        }
567
                                        j = params[6];
×
568
                                        NCOPY(Lijst,inLijst,j);
×
569
                                        k++;
×
570
NextGroup:;
×
571
                                }
572
                                if ( k <= 1 ) goto NextFun;
×
573
                                ngroup = k;
×
574
                                inLijst = AT.WorkPointer;
×
575
                                AT.WorkPointer = Lijst;
×
576
                                Lijst = inLijst;
×
577
                        }
578
                        else if ( Nlist == 0 ) {
1,656✔
579
                                for ( i = 0; i < count; i++ ) Lijst[i] = i;
8,256✔
580
                                AT.WorkPointer += count;
1,656✔
581
                                ngroup = count;
1,656✔
582
                        }
583
                        else {
584
                                for ( i = 0; i < Nlist; i++ ) Lijst[i] = inLijst[i];
×
585
                                AT.WorkPointer += Nlist;
×
586
                        }
587
                        j = Symmetrize(BHEAD t,Lijst,ngroup,params[6],params[2]);
1,656✔
588
                        AT.WorkPointer = Lijst;
1,656✔
589
                        if ( params[2] == 4 ) { /* antisymmetric */
1,656✔
590
                                if ( ( j & 1 ) != 0 ) sign = -sign;
×
591
                                if ( ( j & 2 ) != 0 ) return(0); /* equal arguments */
×
592
                        }
593
                        if ( ( j & 4 ) != 0 ) sumch++;
1,656✔
594
                        t[2] &= ~DIRTYSYMFLAG;
1,656✔
595
                }
596
NextFun:
5,544✔
597
                t += t[1];
7,200✔
598
        }
599
        if ( sign < 0 ) {
240✔
600
                t = term;
×
601
                t += *t - 1;
×
602
                *t = -*t;
×
603
        }
604
        if ( sumch ) {
240✔
605
                if ( Normalize(BHEAD term) ) {
228✔
606
                        MLOCK(ErrorMessageLock);
607
                        MesCall("SymGen");
×
608
                        MUNLOCK(ErrorMessageLock);
609
                        return(-1);
×
610
                }
611
                if ( !*term ) return(0);
228✔
612
                *AN.RepPoint = 1;
228✔
613
                AR.expchanged = 1;
228✔
614
                if ( AR.CurDum > AM.IndDum && AR.sLevel <= 0 ) ReNumber(BHEAD term);
228✔
615
        }
616
        return(Generator(BHEAD term,level));
240✔
617
}
618

619
/*
620
                 #] SymGen : 
621
                 #[ SymFind :
622

623
                There is a certain amount of double work here, as this routine
624
                finds the function to be treated, while the SymGen routine has
625
                to find it again. Note however that this way things remain
626
                uniform and simple. Moreover this avoids problems with actions
627
                on more than one function simultaneously.
628
                Output in AT.TMout:
629
                Number,sym/anti,fun,lenpar,ngroups,gsize,fields
630

631
*/
632

633
int SymFind(PHEAD WORD *term, WORD *params)
780✔
634
{
635
        GETBIDENTITY
636
        WORD *t, *r, *m;
637
        WORD j, c1, c2, count;
638
        WORD *rstop;
639
        c1 = params[4];                /* function number */
780✔
640
        c2 = FUNCTION + WILDOFFSET;
780✔
641
        t = term;
780✔
642
        m = t + *t;
780✔
643
        m -= ABS(m[-1]);
780✔
644
        t++;
780✔
645
        while ( t < m ) {
5,952✔
646
                if ( *t == c1 || c1 > c2 ) {        /* Candidate function */
5,412✔
647
                        if ( *t >= FUNCTION && functions[*t-FUNCTION].spec
240✔
648
                                >= TENSORFUNCTION ) { count = t[1] - FUNHEAD; }
×
649
                        else {
650
                                count = 0;
240✔
651
                                r = t;
240✔
652
                                rstop = t + t[1];
240✔
653
                                r += FUNHEAD;
240✔
654
                                while ( r < rstop ) { count++; NEXTARG(r) }
1,152✔
655
                        }
656
                        if ( ( j = params[5] ) > 0 && j != count ) goto NextFun;
240✔
657
                        if ( j == 0 ) {
240✔
658
                                r = params + 8;
240✔
659
                                rstop = params + params[1];
240✔
660
                                while ( r < rstop ) {
240✔
661
                                        if ( *r > count + 1 ) goto NextFun;
×
662
                                        r++;
×
663
                                }
664
                        }
665
                        
666
                        t = AT.TMout;
240✔
667
                        r = params;
240✔
668
                        j = r[1] - 1;
240✔
669
                        *t++ = j;
240✔
670
                        *t++ = SYMMETRIZE;
240✔
671
                        r += 3;
240✔
672
                        j--;
240✔
673
                        NCOPY(t,r,j);
1,680✔
674
                        return(1);
240✔
675
                }
676
NextFun:
5,172✔
677
                t += t[1];
5,172✔
678
        }
679
        return(0);
540✔
680
}
681

682
/*
683
                 #] SymFind : 
684
                 #[ ChainIn :
685

686
                Equivalent to repeat id f(?a)*f(?b) = f(?a,?b);
687

688
                This one always takes less space.
689
*/
690

691
int ChainIn(PHEAD WORD *term, WORD funnum)
258✔
692
{
693
        GETBIDENTITY
694
        WORD *t, *tend, *m, *tt, *ts;
695
        int action, normFlag = 0;
258✔
696
        if ( funnum < 0 ) {        /* Dollar to be expanded */
258✔
697
                funnum = DolToFunction(BHEAD -funnum);
×
698
                if ( AN.ErrorInDollar || funnum <= 0 ) {
×
699
                        MLOCK(ErrorMessageLock);
700
                        MesPrint("Dollar variable does not evaluate to function in ChainIn statement");
×
701
                        MUNLOCK(ErrorMessageLock);
702
                        return(-1);
×
703
                }
704
        }
705
        do {
706
                action = 0;
444✔
707
                tend = term+*term;
444✔
708
                tend -= ABS(tend[-1]);
444✔
709
                t = term+1;
444✔
710
                while ( t < tend ) {
942✔
711
                        if ( *t != funnum ) { t += t[1]; continue; }
684✔
712
                        m = t;
438✔
713
                        t += t[1];
438✔
714
                        tt = t;
438✔
715
                        if ( t >= tend || *t != funnum ) continue;
438✔
716
                        action = 1;
186✔
717
                        normFlag = 1;
186✔
718
                        while ( t < tend && *t == funnum ) {
444✔
719
                                ts = t + t[1];
258✔
720
                                t += FUNHEAD;
258✔
721
                                while ( t < ts ) *tt++ = *t++;
774✔
722
                        }
723
                        m[1] = tt - m;
186✔
724
                        ts = term + *term;
186✔
725
                        while ( t < ts ) *tt++ = *t++;
2,724✔
726
                        *term = tt - term;
186✔
727
                        break;
186✔
728
                }
729
        } while ( action );
444✔
730

731
        if ( normFlag ) {
258✔
732
                /* We need to check the newly-constructed arguments w.r.t symmetry properties */
733
                MarkDirty(term, DIRTYSYMFLAG);
186✔
734
                AT.WorkPointer = term + *term;
186✔
735
                Normalize(BHEAD term);
186✔
736
        }
737

738
        return(0);
258✔
739
}
740

741
/*
742
                 #] ChainIn : 
743
                 #[ ChainOut :
744

745
                Equivalent to repeat id f(x1?,x2?,?a) = f(x1)*f(x2,?a);
746
*/
747

748
int ChainOut(PHEAD WORD *term, WORD funnum)
1,548✔
749
{
750
        GETBIDENTITY
751
        WORD *t, *tend, *tt, *ts, *w, *ws;
752
        int flag = 0, i;
1,548✔
753
        if ( funnum < 0 ) {        /* Dollar to be expanded */
1,548✔
754
                funnum = DolToFunction(BHEAD -funnum);
×
755
                if ( AN.ErrorInDollar || funnum <= 0 ) {
×
756
                        MLOCK(ErrorMessageLock);
757
                        MesPrint("Dollar variable does not evaluate to function in ChainOut statement");
×
758
                        MUNLOCK(ErrorMessageLock);
759
                        return(-1);
×
760
                }
761
        }
762
        tend = term+*term;
1,548✔
763
        if ( AT.WorkPointer < tend ) AT.WorkPointer = tend;
1,548✔
764
        tend -= ABS(tend[-1]);
1,548✔
765
        t = term+1; tt = term; w = AT.WorkPointer;
1,548✔
766
        while ( t < tend ) {
3,096✔
767
                if ( *t != funnum || t[1] == FUNHEAD ) { t += t[1]; continue; }
1,548✔
768
                flag = 1;
18✔
769
                while ( tt < t ) *w++ = *tt++;
36✔
770
                ts = t + t[1];
18✔
771
                t += FUNHEAD;
18✔
772
                while ( t < ts ) {
414✔
773
                        ws = w;
396✔
774
                        for ( i = 0; i < FUNHEAD; i++ ) *w++ = tt[i];
1,584✔
775
                        if ( functions[*tt-FUNCTION].spec >= TENSORFUNCTION ) {
396✔
776
                                *w++ = *t++;
×
777
                        }
778
                        else if ( *t < 0 ) {
396✔
779
                                if ( *t <= -FUNCTION ) *w++ = *t++;
342✔
780
                                else { *w++ = *t++; *w++ = *t++; }
342✔
781
                        }
782
                        else {
783
                                i = *t; NCOPY(w,t,i);
3,738✔
784
                        }
785
                        ws[1] = w - ws;
396✔
786
                }
787
                tt = t;
18✔
788
        }
789
        if ( flag == 1 ) {
1,548✔
790
                ts = term + *term;
18✔
791
                while ( tt < ts ) *w++ = *tt++;
72✔
792
                *AT.WorkPointer = w - AT.WorkPointer;
18✔
793
                t = term; w = AT.WorkPointer; i = *w;
18✔
794
                NCOPY(t,w,i)
5,646✔
795
                AT.WorkPointer = term + *term;
18✔
796
                Normalize(BHEAD term);
18✔
797
        }
798
        return(0);
1,548✔
799
}
800

801
/*
802
                 #] ChainOut : 
803
          #] Utilities : 
804
        #[ Patterns :
805
                 #[ MatchFunction :                        WORD MatchFunction(pattern,interm,wilds)
806

807
                The routine assumes that the function numbers are the same.
808
                The contents are compared and a possible wildcard assignment
809
                is made. Note that it may be necessary to use a wildcard
810
                assignment stack to do things right.
811
                The routine can become arbitrarily complicated as there is
812
                no end to the possible wildcarding.
813
                Examples:
814
                -        a:        No wildcarding -> straight match
815
                -        b:        Individual arguments (object -> object)
816
                -        c:        whole arguments (object to subexpression)
817
                -        d:        any argumentlist
818
                        e:        part of an argument (object inside subexpression)
819

820
                The ones with a minus sign in front have been implemented.
821

822
                Note: the argument wilds allows backtracking when multiple
823
                ?a,?b give a match that later turns out to be useless.
824
*/
825

826
int MatchFunction(PHEAD WORD *pattern, WORD *interm, WORD *wilds)
33,711,486✔
827
{
828
        GETBIDENTITY
829
        WORD *m, *t, *r, i;
830
        WORD *mstop = 0, *tstop = 0;
33,711,486✔
831
        WORD *argmstop, *argtstop;
832
        WORD *mtrmstop, *ttrmstop;
833
        WORD *msubstop, *mnextsub;
834
        WORD msizcoef, mcount, tcount, newvalue, j;
835
        WORD *oldm, *oldt;
836
        WORD *OldWork, numofwildarg;
837
        WORD nwstore, tobeeaten, reservevalue = 0, resernum = 0, withwild;
33,711,486✔
838
        WORD *wildargtaken;
839
        CBUF *C = cbuf+AT.ebufnum;
33,711,486✔
840
        int ntwa = AN.NumTotWildArgs;
33,711,486✔
841
        LONG oldcpointer = C->Pointer - C->Buffer;
33,711,486✔
842
/*
843
        Test first for a straight match
844
*/
845
        AN.RepFunList[AN.RepFunNum+1] = 0;
33,711,486✔
846
        if ( *wilds == 0 ) {
33,711,486✔
847
                m = pattern; t = interm;
33,705,942✔
848

849
                if ( *m != *t ) {
33,705,942✔
850
                        if ( *m < (FUNCTION + WILDOFFSET) ) return(0);
8,556✔
851
                        if ( *t < FUNCTION ) return(0);
8,556✔
852
                        if ( functions[*t-FUNCTION].spec !=
8,556✔
853
                        functions[*m-FUNCTION-WILDOFFSET].spec ) return(0);
8,556✔
854
                }
855
                i = m[1];
33,705,744✔
856
                if ( *m >= (FUNCTION + WILDOFFSET) ) { i--; m++; t++; }
33,705,744✔
857
                do { if ( *m++ != *t++ ) break; } while ( --i > 0 );
110,645,556✔
858
                if ( i <= 0 ) {                        /* Arguments match */
33,705,744✔
859
                        if ( AN.SignCheck && AN.ExpectedSign ) return(0);
147,018✔
860
                        i = *pattern - WILDOFFSET;
147,018✔
861
                        if ( i >= FUNCTION ) {
147,018✔
862
                                if ( *interm != GAMMA
×
863
#ifdef WITHFLOAT
864
                                && ( *interm != FLOATFUN )
×
865
#endif
866

867
                                && !CheckWild(BHEAD i,FUNTOFUN,*interm,&newvalue) ) {
×
868
                                        AddWild(BHEAD i,FUNTOFUN,newvalue);
×
869
                                        return(1);
×
870
                                }
871
                                return(0);
×
872
                        }
873
                        else return(1);
147,018✔
874
                }
875
        }
876
/*
877
        Store the current Wildcard assignments
878
*/
879
        t = wildargtaken = OldWork = AT.WorkPointer;
33,564,270✔
880
        t += ntwa;
33,564,270✔
881
        m = AN.WildValue;
33,564,270✔
882
        nwstore = i = (m[-SUBEXPSIZE+1]-SUBEXPSIZE)/4;
33,564,270✔
883
        if ( i > 0 ) {
33,564,270✔
884
                r = AT.WildMask;
33,434,088✔
885
                do {
886
                        *t++ = *m++; *t++ = *m++; *t++ = *m++; *t++ = *m++; *t++ = *r++;
109,385,292✔
887
                } while ( --i > 0 );
109,385,292✔
888
                *t++ = C->numrhs;
33,434,088✔
889
        }
890
        if ( t >= AT.WorkTop ) {
33,564,270✔
891
                MLOCK(ErrorMessageLock);
892
                MesWork();
×
893
                MUNLOCK(ErrorMessageLock);
894
                Terminate(-1);
×
895
        }
896
        AT.WorkPointer = t;
33,564,270✔
897

898
        if ( *wilds ) {
33,564,270✔
899
                if ( *wilds == 1 ) goto endoloop;
5,544✔
900
                else               goto enloop;                        /* tensors = 2 */
×
901
        }
902
        m = pattern; t = interm;
33,558,726✔
903
/*
904
        Single out the specials
905
*/
906
        if ( *t == GAMMA ) {
33,558,726✔
907
/*
908
                 #[ GAMMA :
909

910
                For the gamma's we need to do two things:
911
                a:        Find that there is a match
912
                b:        Find where the match occurs in the string
913
                This last thing cannot be stored in the current conventions,
914
                but once the wildcard assignments have been made it is much
915
                easier to find it back.
916
                Alternative: replace the function number in the term temporarily
917
                by the offset inside the string. This makes things maybe easier.
918
*/
919
                if ( *m != GAMMA ) goto NoCaseB;
72✔
920
                i = t[1] - m[1];
72✔
921
                if ( m[1] == FUNHEAD+1 ) {
72✔
922
                        if ( i ) goto NoCaseB;
×
923
                        if ( m[FUNHEAD] < (AM.OffsetIndex+WILDOFFSET) ||
×
924
                        t[FUNHEAD] >= (AM.OffsetIndex+WILDOFFSET) ) goto NoCaseB;
×
925

926
                        if ( CheckWild(BHEAD m[FUNHEAD]-WILDOFFSET,INDTOIND,t[FUNHEAD],&newvalue) ) goto NoCaseB;
×
927
                        AddWild(BHEAD m[FUNHEAD]-WILDOFFSET,INDTOIND,newvalue);
×
928
                        
929
                        AT.WorkPointer = OldWork;
×
930
                        if ( AN.SignCheck && AN.ExpectedSign ) return(0);
×
931
                        return(1);                /* m was eaten. we have a match! */
×
932
                }
933
                if ( i < 0 ) goto NoCaseB;        /* Pattern longer than target */
72✔
934
                mstop = m + m[1];
72✔
935
                tstop = t + t[1];
72✔
936
                m += FUNHEAD; t += FUNHEAD;
72✔
937
                if ( *m >= (AM.OffsetIndex+WILDOFFSET) && *t < (AM.OffsetIndex+WILDOFFSET) ) {
72✔
938
                        if ( CheckWild(BHEAD *m-WILDOFFSET,INDTOIND,*t,&newvalue) ) goto NoCaseB;
72✔
939
                        reservevalue = newvalue;
72✔
940
                        withwild = 1;
72✔
941
                        resernum = *m-WILDOFFSET;
72✔
942
                        AddWild(BHEAD *m-WILDOFFSET,INDTOIND,newvalue);
72✔
943
                }
944
                else if ( *m != *t ) goto NoCaseB;
×
945
                else withwild = 0;
×
946
                m++; t++;
72✔
947
                oldm = m; argtstop = oldt = t;
72✔
948
                j = 0;                                        /* No wildcard assignments yet */
72✔
949
                while ( i >= 0 ) {
936✔
950
                        if ( *m == *t ) {
864✔
951
WithGamma:                m++; t++;
×
952
                                if ( m >= mstop ) {
×
953
                                        if ( t < tstop && mstop < AN.patstop ) {
×
954
                                                WORD k;
955
                                                mnextsub = pattern + pattern[1];
×
956
                                                k = *mnextsub;
×
957
                                                while ( k == GAMMA && mnextsub[FUNHEAD]
×
958
                                                != pattern[FUNHEAD] ) {
×
959
                                                        mnextsub += mnextsub[1];
×
960
                                                        if ( mnextsub >= AN.patstop ) goto FullOK;
×
961
                                                        k = *mnextsub;
×
962
                                                }
963
                                                if ( k >= FUNCTION ) {
×
964
                                                        if ( k > (FUNCTION + WILDOFFSET) ) k -= WILDOFFSET;
×
965
                                                        if ( functions[k-FUNCTION].commute ) goto NoGamma;
×
966
                                                }
967
                                        }
968
FullOK:                                if ( AN.SignCheck && AN.ExpectedSign ) goto NoGamma;
×
969
                                        AN.RepFunList[AN.RepFunNum+1] = WORDDIF(oldt,argtstop);
×
970
                                        return(1);
×
971
                                }
972
                                if ( t >= tstop ) goto NoCaseB;
×
973
                        }
974
                        else if ( *m >= (AM.OffsetIndex+WILDOFFSET)
864✔
975
                        && *m < (AM.OffsetIndex + (WILDOFFSET<<1)) && ( *t >= 0 ||
×
976
                        *t < MINSPEC ) ) {                        /* Wildcard index */
×
977
                                if ( !CheckWild(BHEAD *m-WILDOFFSET,INDTOIND,*t,&newvalue) ) {
×
978
                                        AddWild(BHEAD *m-WILDOFFSET,INDTOIND,newvalue);
×
979
                                        j = 1;
×
980
                                        goto WithGamma;
×
981
                                }
982
                                else goto NoGamma;
×
983
                        }
984
                        else if ( *m < MINSPEC && *m >= (AM.OffsetVector+WILDOFFSET)
864✔
985
                        && *t < MINSPEC ) {                        /* Wildcard vector */
×
986
                                if ( !CheckWild(BHEAD *m-WILDOFFSET,VECTOVEC,*t,&newvalue) ) {
×
987
                                        AddWild(BHEAD *m-WILDOFFSET,VECTOVEC,newvalue);
×
988
                                        j = 1;
×
989
                                        goto WithGamma;
×
990
                                }
991
                                else goto NoGamma;
×
992
                        }
993
                        else {
994
NoGamma:
864✔
995
                                if ( j ) {                /* Undo wildcards */
864✔
996
                                        m = AN.WildValue;
×
997
                                        t = OldWork + AN.NumTotWildArgs; r = AT.WildMask; j = nwstore;
×
998
                                        if ( j > 0 ) {
×
999
                                                do {
1000
                                                        *m++ = *t++; *m++ = *t++;
×
1001
                                                        *m++ = *t++; *m++ = *t++; *r++ = *t++;
×
1002
                                                } while ( --j > 0 );
×
1003
                                                C->numrhs = *t++;
×
1004
                                                C->Pointer = C->Buffer + oldcpointer;
×
1005
                                        }
1006
                                        j = 0;
×
1007
                                }
1008
                                m = oldm; t = ++oldt; i--;
864✔
1009
                                if ( withwild ) {
864✔
1010
                                        AddWild(BHEAD resernum,INDTOIND,reservevalue);
864✔
1011
                                }
1012
                        }
1013
                }
1014
                goto NoCaseB;
72✔
1015
/*
1016
                 #] GAMMA : 
1017
                 #[ Tensors :
1018
*/
1019
        }
1020
        else if ( *t >= FUNCTION && functions[*t-FUNCTION].spec >= TENSORFUNCTION ) {
33,558,654✔
1021
                mstop = m + m[1];
87,702✔
1022
                tstop = t + t[1];
87,702✔
1023
                mcount = 0;
87,702✔
1024
                m += FUNHEAD;
87,702✔
1025
                t += FUNHEAD;
87,702✔
1026
                AN.WildArgs = 0;
87,702✔
1027
                tcount = WORDDIF(tstop,t);
87,702✔
1028
                while ( m < mstop ) {
192,624✔
1029
                        if ( *m == FUNNYWILD ) { m++; AN.WildArgs++; }
104,922✔
1030
                        m++; mcount++;
104,922✔
1031
                }
1032
                tobeeaten = tcount - mcount + AN.WildArgs;
87,702✔
1033
                if ( tobeeaten ) {
87,702✔
1034
                        if ( tobeeaten < 0 || AN.WildArgs == 0 ) {
34,062✔
1035
                                AT.WorkPointer = OldWork;
11,664✔
1036
                                return(0);        /* Cannot match */
11,664✔
1037
                        }
1038
                }
1039
                AT.WildArgTaken[0] = AN.WildEat = tobeeaten;
76,038✔
1040
                for ( i = 1; i < AN.WildArgs; i++ ) AT.WildArgTaken[i] = 0;
76,038✔
1041
toploop:
76,038✔
1042
                numofwildarg = 0;
76,038✔
1043

1044
                m = pattern; t = interm;
76,038✔
1045
                mstop = m + m[1];
76,038✔
1046
                if ( *m != *t ) {
76,038✔
1047
                        i = *m - WILDOFFSET;
×
1048
                        if ( CheckWild(BHEAD i,FUNTOFUN,*t,&newvalue) ) goto NoCaseB;
×
1049
                        AddWild(BHEAD i,FUNTOFUN,newvalue);
×
1050
                }
1051
                m += FUNHEAD;
76,038✔
1052
                t += FUNHEAD;
76,038✔
1053
                while ( m < mstop ) {
165,408✔
1054
/*
1055
                        First test for an exact match
1056
*/
1057
                        if ( *m == *t ) { m++; t++; continue; }
89,490✔
1058
/*
1059
                        No exact match. Try ARGWILD
1060
*/
1061
                        AN.argaddress = t;
89,490✔
1062
                        if ( *m == FUNNYWILD ) {
89,490✔
1063
                                tobeeaten = AT.WildArgTaken[numofwildarg++];
29,442✔
1064
                                if ( CheckWild(BHEAD m[1],ARGTOARG|EATTENSOR,tobeeaten,t) ) goto endloop;
29,442✔
1065
                                AddWild(BHEAD m[1],ARGTOARG|EATTENSOR,tobeeaten);
29,442✔
1066
                                m += 2;
29,442✔
1067
                                t += tobeeaten;
29,442✔
1068
                                continue;
29,442✔
1069
                        }
1070
/*
1071
                        Now the various cases:
1072
*/
1073
                        i = *m;
60,048✔
1074
                        if ( i < MINSPEC ) {
60,048✔
1075
                                if ( *t != i ) {
×
1076
                                        if ( *t >= MINSPEC ) goto endloop;
×
1077
                                        i -= WILDOFFSET;
×
1078
                                        if ( i < AM.OffsetVector ) goto endloop;
×
1079
                                        if ( CheckWild(BHEAD i,VECTOVEC,*t,&newvalue) )
×
1080
                                                goto endloop;
×
1081
                                        AddWild(BHEAD i,VECTOVEC,newvalue);
×
1082
                                }
1083
                        }
1084
                        else if ( i >= AM.OffsetIndex ) {                        /* Index */
60,048✔
1085
                                if ( i < ( AM.OffsetIndex + WILDOFFSET ) ) goto endloop;
60,048✔
1086
                                if ( i >= ( AM.OffsetIndex + (WILDOFFSET<<1) ) ) {
60,048✔
1087
                                                                                                /* Summed over index */
1088
                                        goto endloop;                                /* For the moment */
×
1089
                                }
1090
                                i -= WILDOFFSET;
60,048✔
1091
                                if ( CheckWild(BHEAD i,INDTOIND,*t,&newvalue) )
60,048✔
1092
                                        goto endloop;                /* Assignment not allowed */
120✔
1093
                                AddWild(BHEAD i,INDTOIND,newvalue);
59,928✔
1094
                        }
1095
                        else goto endloop;
×
1096
                        m++; t++;
59,928✔
1097
                }
1098
                if ( AN.SignCheck && AN.ExpectedSign ) goto endloop;
75,918✔
1099
                AT.WorkPointer = OldWork;
75,918✔
1100
                if ( AN.WildArgs > 1 ) *wilds = 2;
75,918✔
1101
                return(1);                /* m was eaten. we have a match! */
75,918✔
1102

1103
endloop:;
120✔
1104
/*
1105
        restore the current Wildcard assignments
1106
*/
1107
                i = nwstore;
120✔
1108
                if ( i > 0 ) {
120✔
1109
                        m = AN.WildValue;
120✔
1110
                        t = OldWork + ntwa; r = AT.WildMask;
120✔
1111
                        do {
1112
                                *m++ = *t++; *m++ = *t++; *m++ = *t++; *m++ = *t++; *r++ = *t++;
600✔
1113
                        } while ( --i > 0 );
600✔
1114
                        C->numrhs = *t++;
120✔
1115
                        C->Pointer = C->Buffer + oldcpointer;
120✔
1116
                }
1117
enloop:;
×
1118
                i = AN.WildArgs - 1;
120✔
1119
                if ( i <= 0 ) {
120✔
1120
                        AT.WorkPointer = OldWork;
120✔
1121
                        return(0);
120✔
1122
                }
1123
                while ( --i >= 0 ) {
×
1124
                        if ( AT.WildArgTaken[i] == 0 ) {
×
1125
                                if ( i == 0 ) {
×
1126
                                        AT.WorkPointer = OldWork;
×
1127
                                        *wilds = 0;
×
1128
                                        return(0);
×
1129
                                }
1130
                        }
1131
                        else {
1132
                                (AT.WildArgTaken[i])--;
×
1133
                                numofwildarg = 0;
×
1134
                                for ( j = 0; j <= i; j++ ) {
×
1135
                                        numofwildarg += AT.WildArgTaken[j];
×
1136
                                }
1137
                                AT.WildArgTaken[j] = AN.WildEat-numofwildarg;
×
1138
                                for ( j++; j < AN.WildArgs; j++ ) AT.WildArgTaken[j] = 0;
×
1139
                                break;
×
1140
                        }
1141
                }
1142
                goto toploop;
×
1143
/*
1144
                 #] Tensors : 
1145
*/
1146
        }
1147
/*
1148
        Count the number of arguments. Either equal or an argument wildcard.
1149
*/
1150
        mstop = m + m[1];
33,470,952✔
1151
        tstop = t + t[1];
33,470,952✔
1152
        mcount = 0; tcount = 0;
33,470,952✔
1153
        m += FUNHEAD; t += FUNHEAD;
33,470,952✔
1154
        while ( t < tstop ) { tcount++; NEXTARG(t) }
91,793,694✔
1155
        AN.WildArgs = 0;
33,470,952✔
1156
        while ( m < mstop ) {
86,983,506✔
1157
                mcount++;
53,512,554✔
1158
                if ( *m == -ARGWILD ) AN.WildArgs++;
53,512,554✔
1159
                NEXTARG(m)
53,512,554✔
1160
        }
1161
        tobeeaten = tcount - mcount + AN.WildArgs;
33,470,952✔
1162
        if ( tobeeaten ) {
33,470,952✔
1163
                if ( tobeeaten < 0 || AN.WildArgs == 0 ) {
2,800,638✔
1164
                        AT.WorkPointer = OldWork;
10,242✔
1165
                        return(0);        /* Cannot match */
10,242✔
1166
                }
1167
        }
1168
/*
1169
        Set up the array AT.WildArgTaken for the number of arguments that each
1170
        wildarg eats.
1171
*/
1172
        AT.WildArgTaken[0] = AN.WildEat = tobeeaten;
33,460,710✔
1173
        for ( i = 1; i < AN.WildArgs; i++ ) AT.WildArgTaken[i] = 0;
33,828,912✔
1174
topofloop:
33,460,710✔
1175
        numofwildarg = 0;
39,885,738✔
1176
/*
1177
        Test for single wildcard object/argument
1178
*/
1179
        m = pattern; t = interm;
39,885,738✔
1180
        if ( *m != *t ) {
39,885,738✔
1181
                i = *m - WILDOFFSET;
8,142✔
1182
                if ( CheckWild(BHEAD i,FUNTOFUN,*t,&newvalue) ) goto NoCaseB;
8,142✔
1183
                AddWild(BHEAD i,FUNTOFUN,newvalue);
8,142✔
1184
        }
1185
        mstop = m + m[1];
39,885,738✔
1186
/*        tstop = t + t[1];  */
1187
        m += FUNHEAD;
39,885,738✔
1188
        t += FUNHEAD;
39,885,738✔
1189
        while ( m < mstop ) {
78,361,920✔
1190
                argmstop = oldm = m;
61,808,940✔
1191
                argtstop = oldt = t;
61,808,940✔
1192
                NEXTARG(argmstop)
61,808,940✔
1193
                NEXTARG(argtstop)
61,808,940✔
1194
                if ( t == tstop ) { /* This concerns a very rare bug */
61,808,940✔
1195
                        if ( *m == -ARGWILD ) goto ArgAll;
50,998✔
1196
                        goto endofloop;
×
1197
                }
1198
                if ( *m < 0 && *t < 0 ) {
61,757,942✔
1199
                        if ( *t <= -FUNCTION ) {
47,756,876✔
1200
                                if ( *t == *m ) {}
13,356✔
1201
                                else if ( *m <= -FUNCTION-WILDOFFSET
13,356✔
1202
                                && functions[-*t-FUNCTION].spec
×
1203
                                == functions[-*m-FUNCTION-WILDOFFSET].spec ) {
×
1204
                                        i = -*m - WILDOFFSET;
×
1205
                                        if ( CheckWild(BHEAD i,FUNTOFUN,-*t,&newvalue) ) goto endofloop;
×
1206
                                        AddWild(BHEAD i,FUNTOFUN,newvalue);
×
1207
                                }
1208
                                else if ( *m == -SYMBOL && m[1] >= 2*MAXPOWER ) {
13,356✔
1209
                                        i = m[1] - 2*MAXPOWER;
13,344✔
1210
                                        AN.argaddress = AT.FunArg;
13,344✔
1211
                                        AT.FunArg[ARGHEAD+1] = -*t;
13,344✔
1212
                                        if ( CheckWild(BHEAD i,SYMTOSUB,1,AN.argaddress) ) goto endofloop;
13,344✔
1213
                                        AddWild(BHEAD i,SYMTOSUB,0);
13,344✔
1214
                                }
1215
                                else if ( *m == -ARGWILD ) {
12✔
1216
ArgAll:                                i = AT.WildArgTaken[numofwildarg++];
12✔
1217
                                        AN.argaddress = t;
14,894,514✔
1218
                                        if ( CheckWild(BHEAD m[1],ARGTOARG,i,t) ) goto endofloop;
14,894,514✔
1219
                                        AddWild(BHEAD m[1],ARGTOARG,i);
14,893,002✔
1220
/*                                        m += 2; */
1221
                                        while ( --i >= 0 ) { NEXTARG(t) }
329,049,494✔
1222
                                        argtstop = t;
14,893,002✔
1223
                                }
1224
                                else goto endofloop;
×
1225
                        }
1226
                        else if ( *t == *m ) {
47,743,520✔
1227
                                if ( t[1] == m[1] ) {}
23,847,738✔
1228
                                else if ( *t == -SYMBOL ) {
22,982,322✔
1229
                                        j = SYMTOSYM;
538,824✔
1230
SymAll:
8,795,052✔
1231
                                        if ( ( i = m[1] - 2*MAXPOWER ) < 0 ) goto endofloop;
8,795,052✔
1232
                                        if ( CheckWild(BHEAD i,j,t[1],&newvalue) ) goto endofloop;
8,774,760✔
1233
                                        AddWild(BHEAD i,j,newvalue);
5,074,686✔
1234
                                }
1235
                                else if ( *t == -INDEX ) {
22,443,498✔
1236
IndAll:                                i = m[1] - WILDOFFSET;
4,140✔
1237
                                        if ( i < AM.OffsetIndex || i >= WILDOFFSET+AM.OffsetIndex )
7,074✔
1238
                                                                                                                        goto endofloop;
×
1239
                                                                /* We kill the summed over indices here */
1240
                                        if ( CheckWild(BHEAD i,INDTOIND,t[1],&newvalue) ) goto endofloop;
7,074✔
1241
                                        AddWild(BHEAD i,INDTOIND,newvalue);
5,154✔
1242
                                }
1243
                                else if ( *t == -VECTOR || *t == -MINVECTOR ) {
22,439,358✔
1244
                                        i = m[1] - WILDOFFSET;
11,561,934✔
1245
                                        if ( i < AM.OffsetVector ) goto endofloop;
11,561,934✔
1246
                                        if ( CheckWild(BHEAD i,VECTOVEC,t[1],&newvalue) ) goto endofloop;
11,557,098✔
1247
                                        AddWild(BHEAD i,VECTOVEC,newvalue);
5,848,638✔
1248
                                }
1249
                                else goto endofloop;
10,877,424✔
1250
                        }
1251
                        else if ( *m == -ARGWILD ) goto ArgAll;
23,895,782✔
1252
                        else if ( *m == -INDEX && m[1] >= AM.OffsetIndex+WILDOFFSET
9,058,962✔
1253
                        && m[1] < AM.OffsetIndex+(WILDOFFSET<<1) ) {
3,096✔
1254
                                if ( *t == -VECTOR ) goto IndAll;
3,096✔
1255
                                if ( *t == -SNUMBER && t[1] >= 0 && t[1] < AM.OffsetIndex ) goto IndAll;
1,860✔
1256
                                if ( *t == -MINVECTOR ) {
162✔
1257
                                        i = m[1] - WILDOFFSET;
×
1258
                                        AN.argaddress = AT.MinVecArg;
×
1259
                                        AT.MinVecArg[ARGHEAD+3] = t[1];
×
1260
                                        if ( CheckWild(BHEAD i,INDTOSUB,1,AN.argaddress) ) goto endofloop;
×
1261
                                        AddWild(BHEAD i,INDTOSUB,(WORD)0);
×
1262
                                }
1263
                                else goto endofloop;
162✔
1264
                        }
1265
                        else if ( *m == -SYMBOL && m[1] >= 2*MAXPOWER && *t == -SNUMBER ) {
9,055,866✔
1266
                                j = SYMTONUM;
8,256,228✔
1267
                                goto SymAll;
8,256,228✔
1268
                        }
1269
                        else if ( *m == -VECTOR && *t == -MINVECTOR &&
799,638✔
1270
                        ( i = m[1] - WILDOFFSET ) >= AM.OffsetVector ) {
14,232✔
1271
/*
1272
================================
1273
                                AN.argaddress = AT.MinVecArg;
1274
                                AT.MinVecArg[ARGHEAD+3] = t[1];
1275
                                if ( CheckWild(BHEAD i,VECTOSUB,1,AN.argaddress) ) goto endofloop;
1276
                                AddWild(BHEAD i,VECTOSUB,(WORD)0);
1277
================================
1278
*/
1279
                                if ( CheckWild(BHEAD i,VECTOMIN,t[1],&newvalue) ) goto endofloop;
14,232✔
1280
                                AddWild(BHEAD i,VECTOMIN,newvalue);
6,618✔
1281

1282
                        }
1283
                        else if ( *m == -MINVECTOR && *t == -VECTOR &&
785,406✔
1284
                        ( i = m[1] - WILDOFFSET ) >= AM.OffsetVector ) {
752,112✔
1285
/*
1286
================================
1287
                                AN.argaddress = AT.MinVecArg;
1288
                                AT.MinVecArg[ARGHEAD+3] = t[1];
1289
                                if ( CheckWild(BHEAD i,VECTOSUB,1,AN.argaddress) ) goto endofloop;
1290
                                AddWild(BHEAD i,VECTOSUB,(WORD)0);
1291
================================
1292
*/
1293
                                if ( CheckWild(BHEAD i,VECTOMIN,t[1],&newvalue) ) goto endofloop;
752,112✔
1294
                                AddWild(BHEAD i,VECTOMIN,newvalue);
7,818✔
1295
                        }
1296
                        else goto endofloop;
33,294✔
1297
                }
1298
                else if ( *t <= -FUNCTION && *m > 0 ) {
14,001,066✔
1299
                        if ( ( m[ARGHEAD]+ARGHEAD == *m ) && m[*m-1] == 3
228✔
1300
                        && m[*m-2] == 1 && m[*m-3] == 1 && m[ARGHEAD+1] >= FUNCTION
228✔
1301
                        && m[ARGHEAD+2] == *m-ARGHEAD-4 ) { /* Check for f(?a) etc */
456✔
1302
                                WORD *mmmst, *mmm;
1303
                                if ( m[ARGHEAD+1] >= FUNCTION+WILDOFFSET ) {
228✔
1304
/*                                        i = *m - WILDOFFSET; */
1305
                                        i = m[ARGHEAD+1] - WILDOFFSET;
228✔
1306
                                        if ( CheckWild(BHEAD i,FUNTOFUN,-*t,&newvalue) ) goto endofloop;
228✔
1307
                                        AddWild(BHEAD i,FUNTOFUN,newvalue);
228✔
1308
                                }
1309
                                else if ( m[ARGHEAD+1] != -*t ) goto endofloop;
×
1310
/*
1311
                                        Only arguments allowed are ?a etc.
1312
*/
1313
                                mmmst = m+*m-3;
228✔
1314
                                mmm = m + ARGHEAD + FUNHEAD + 1;
228✔
1315
                                while ( mmm < mmmst ) {
456✔
1316
                                        if ( *mmm != -ARGWILD ) goto endofloop;
228✔
1317
                                        i = 0;
228✔
1318
                                        AN.argaddress = t;
228✔
1319
                                        if ( CheckWild(BHEAD mmm[1],ARGTOARG,i,t) ) goto endofloop;
228✔
1320
                                        AddWild(BHEAD mmm[1],ARGTOARG,i);
228✔
1321
                                        mmm += 2;
228✔
1322
                                }
1323
                        }
1324
                        else goto endofloop;
×
1325
                }
1326
                else if ( *m < 0 && *t > 0 ) {
14,000,838✔
1327
                        if ( *m == -SYMBOL ) {                        /* SYMTOSUB */
13,986,360✔
1328
                                if ( m[1] < 2*MAXPOWER ) goto endofloop;
13,978,506✔
1329
                                i = m[1] - 2*MAXPOWER;
13,978,488✔
1330
                                AN.argaddress = t;
13,978,488✔
1331
                                if ( CheckWild(BHEAD i,SYMTOSUB,1,AN.argaddress) ) goto endofloop;
13,978,488✔
1332
                                AddWild(BHEAD i,SYMTOSUB,0);
11,752,290✔
1333
                        }
1334
                        else if ( *m == -VECTOR ) {
7,854✔
1335
                                if ( ( i = m[1] - WILDOFFSET ) < AM.OffsetVector )
×
1336
                                                                                                                        goto endofloop;
×
1337
                                AN.argaddress = t;
×
1338
                                if ( CheckWild(BHEAD i,VECTOSUB,1,t) ) goto endofloop;
×
1339
                                AddWild(BHEAD i,VECTOSUB,(WORD)0);
×
1340
                        }
1341
                        else if ( *m == -INDEX ) {
7,854✔
1342
                                if ( ( i = m[1] - WILDOFFSET ) < AM.OffsetIndex ) goto endofloop;
966✔
1343
                                if ( i >= AM.OffsetIndex + WILDOFFSET ) goto endofloop;
966✔
1344
                                AN.argaddress = t;
966✔
1345
                                if ( CheckWild(BHEAD i,INDTOSUB,1,AN.argaddress) ) goto endofloop;
966✔
1346
                                AddWild(BHEAD i,INDTOSUB,(WORD)0);
×
1347
                        }
1348
                        else if ( *m == -ARGWILD ) goto ArgAll;
6,888✔
1349
                        else goto endofloop;
204✔
1350
                }
1351
                else if ( *m > 0 && *t > 0 ) {
23,466✔
1352
                        WORD ii = *t-*m;
14,478✔
1353
                        i = *m;
14,478✔
1354
                        do { if ( *m++ != *t++ ) break; } while ( --i > 0 );
16,530✔
1355
                        if ( i == 1 && ii == 0 ) {        /* sign difference */
14,478✔
1356
                                goto endofloop;
6✔
1357
                        }
1358
                        else if ( i > 0 ) {
14,472✔
1359
                                WORD *cto, *cfrom, *csav, ci;
1360
                                WORD oRepFunNum;
1361
                                WORD *oRepFunList;
1362
                                WORD *oterstart,*oterstop,*opatstop;
1363
                                WORD oExpectedSign;
1364
                                WORD wildargs, wildeat;
1365
/*
1366
                                Not an exact match here.
1367
                                We have to hope that the pattern contains a composite wildcard.
1368
*/
1369
                                m = oldm; t = oldt;
14,472✔
1370
                                m += ARGHEAD; t += ARGHEAD;                        /* Point at (first?) term */
14,472✔
1371
                                mtrmstop = m + *m;
14,472✔
1372
                                ttrmstop = t + *t;
14,472✔
1373
                                if ( mtrmstop < argmstop ) goto endofloop;/* More than one term */
14,472✔
1374
                                msizcoef = mtrmstop[-1];
14,472✔
1375
                                if ( msizcoef < 0 ) msizcoef = -msizcoef;
14,472✔
1376
                                msubstop = mtrmstop - msizcoef;
14,472✔
1377
                                m++;
14,472✔
1378
                                if ( m >= msubstop ) goto endofloop;        /* Only coefficient */
14,472✔
1379
/*
1380
                                Here we have a composite term. It can match provided it
1381
                                matches the entire argument. This argument must be a
1382
                                single term also and the coefficients should match
1383
                                (more or less).
1384
                                The matching takes:
1385
                                1:        Match the functions etc. Nothing can be left.
1386
                                2:        Match dotproducts and symbols. ONLY must match
1387
                                        and nothing may be left.
1388
                                For safety it is best to take the term out and put it
1389
                                in workspace.
1390
*/
1391

1392
                                if ( argtstop > ttrmstop ) goto endofloop;
14,472✔
1393
                                m--;
9,168✔
1394
                                oterstart = AN.terstart;
9,168✔
1395
                                oterstop = AN.terstop;
9,168✔
1396
                                opatstop = AN.patstop;
9,168✔
1397
                                oRepFunList = AN.RepFunList;
9,168✔
1398
                                oRepFunNum = AN.RepFunNum;
9,168✔
1399
                                AN.RepFunNum = 0;
9,168✔
1400
                                AN.RepFunList = AT.WorkPointer;
9,168✔
1401
                        AT.WorkPointer = (WORD *)(((UBYTE *)(AT.WorkPointer)) + AM.MaxTer);
9,168✔
1402
                                if ( AT.WorkPointer+*t+5 > AT.WorkTop ) {
9,168✔
1403
                                        MLOCK(ErrorMessageLock);
1404
                                        MesWork();
×
1405
                                        MUNLOCK(ErrorMessageLock);
1406
                                        return(-1);
×
1407
                                }
1408
                                csav = cto = AT.WorkPointer;
9,168✔
1409
                                cfrom = t;
9,168✔
1410
                                ci = *t;
9,168✔
1411
                                while ( --ci >= 0 ) *cto++ = *cfrom++;
202,170✔
1412
                                AT.WorkPointer = cto;
9,168✔
1413
                                ci = msizcoef;
9,168✔
1414
                                cfrom = mtrmstop;
9,168✔
1415
                                --ci;
9,168✔
1416
                                if ( abs(*--cfrom) != abs(*--cto) ) {
9,168✔
1417
                                        AT.WorkPointer = csav;
×
1418
                                        AN.RepFunList = oRepFunList;
×
1419
                                        AN.RepFunNum = oRepFunNum;
×
1420
                                        AN.terstart = oterstart;
×
1421
                                        AN.terstop = oterstop;
×
1422
                                        AN.patstop = opatstop;
×
1423
                                        goto endofloop;
×
1424
                                }
1425
                                i = (*cfrom != *cto) ? 1 : 0; /* buffer AN.ExpectedSign until we are beyond the goto */
9,168✔
1426
                                while ( --ci >= 0 ) {
27,504✔
1427
                                        if ( *--cfrom != *--cto ) {
18,336✔
1428
                                                AT.WorkPointer = csav;
×
1429
                                                AN.RepFunList = oRepFunList;
×
1430
                                                AN.RepFunNum = oRepFunNum;
×
1431
                                                AN.terstart = oterstart;
×
1432
                                                AN.terstop = oterstop;
×
1433
                                                AN.patstop = opatstop;
×
1434
                                                goto endofloop;
×
1435
                                        }
1436
                                }
1437
                                oExpectedSign =  AN.ExpectedSign; /* buffer AN.ExpectedSign until we are beyond FindRest/FindOnly */
9,168✔
1438
                                AN.ExpectedSign = i;
9,168✔
1439
                                *m -= msizcoef;
9,168✔
1440
                                wildargs = AN.WildArgs;
9,168✔
1441
                                wildeat = AN.WildEat;
9,168✔
1442
                                for ( i = 0; i < wildargs; i++ ) wildargtaken[i] = AT.WildArgTaken[i];
9,168✔
1443
                                AN.ForFindOnly = 0; AN.UseFindOnly = 1;
9,168✔
1444
                                AN.nogroundlevel++;
9,168✔
1445
                                if ( FindRest(BHEAD csav,m) && ( AN.UsedOtherFind || FindOnly(BHEAD csav,m) ) ) {}
9,168✔
1446
                                else {
1447
nomatch:
180✔
1448
                                        *m += msizcoef;
180✔
1449
                                        AT.WorkPointer = csav;
180✔
1450
                                        AN.RepFunList = oRepFunList;
180✔
1451
                                        AN.RepFunNum = oRepFunNum;
180✔
1452
                                        AN.terstart = oterstart;
180✔
1453
                                        AN.terstop = oterstop;
180✔
1454
                                        AN.patstop = opatstop;
180✔
1455
                                        AN.WildArgs = wildargs;
180✔
1456
                                        AN.WildEat = wildeat;
180✔
1457
                                        AN.ExpectedSign = oExpectedSign;
180✔
1458
                                        AN.nogroundlevel--;
180✔
1459
                                        for ( i = 0; i < wildargs; i++ ) AT.WildArgTaken[i] = wildargtaken[i];
180✔
1460
                                        goto endofloop;
180✔
1461
                                }
1462
/*                                if ( *m == 1 || m[1] < FUNCTION || functions[m[1]-FUNCTION].spec >= TENSORFUNCTION ) { */
1463
                                if ( *m == 1 || m[1] < FUNCTION ) {
8,988✔
1464
                                        if ( AN.ExpectedSign ) goto nomatch;
×
1465
                                }
1466
                                else {
1467
                                        if ( m[1] > FUNCTION + WILDOFFSET ) {
8,988✔
1468
                                                if ( functions[m[1]-FUNCTION-WILDOFFSET].spec >= TENSORFUNCTION ) {
7,248✔
1469
                                                        if ( AN.ExpectedSign != AN.RepFunList[AN.RepFunNum-1] ) goto nomatch;
×
1470
                                                }
1471
                                        }
1472
                             else {
1473
                                                if ( AN.ExpectedSign != AN.RepFunList[AN.RepFunNum-1] ) goto nomatch;
1,740✔
1474
/*
1475
                                                if ( functions[m[1]-FUNCTION].spec >= TENSORFUNCTION ) {
1476
                                                        if ( AN.ExpectedSign != AN.RepFunList[AN.RepFunNum-1] ) goto nomatch;
1477
                                                }
1478
*/
1479
                                        }
1480
                                }
1481
                                AN.nogroundlevel--;
8,988✔
1482
                                AN.ExpectedSign = oExpectedSign;
8,988✔
1483
                                AN.WildArgs = wildargs;
8,988✔
1484
                                AN.WildEat = wildeat;
8,988✔
1485
                                for ( i = 0; i < wildargs; i++ ) AT.WildArgTaken[i] = wildargtaken[i];
8,988✔
1486
                                Substitute(BHEAD csav,m,1);
8,988✔
1487
                                cto = csav;
8,988✔
1488
                                cfrom = cto + *cto - msizcoef;
8,988✔
1489
                                cto++;
8,988✔
1490
                                *m += msizcoef;
8,988✔
1491
                                AT.WorkPointer = csav;
8,988✔
1492
                                AN.RepFunList = oRepFunList;
8,988✔
1493
                                AN.RepFunNum = oRepFunNum;
8,988✔
1494
                                AN.terstart = oterstart;
8,988✔
1495
                                AN.terstop = oterstop;
8,988✔
1496
                                AN.patstop = opatstop;
8,988✔
1497
                                if ( *cto != SUBEXPRESSION ) goto endofloop;
8,988✔
1498
                                cto += cto[1];
8,988✔
1499
                                if ( cto < cfrom ) goto endofloop;
8,988✔
1500
                        }
1501
                }
1502
                else goto endofloop;
×
1503

1504
                t = argtstop;                                                /* Next argument */
38,476,182✔
1505
                m = argmstop;
38,476,182✔
1506
        }
1507
        if ( AN.SignCheck && AN.ExpectedSign ) goto endofloop;
16,552,980✔
1508
        AT.WorkPointer = OldWork;
16,552,980✔
1509
        if ( AN.WildArgs > 1 ) *wilds = 1;
16,552,980✔
1510
        if ( AN.SignCheck && AN.ExpectedSign ) return(0);
16,552,980✔
1511
        return(1);                /* m was eaten. we have a match! */
16,552,980✔
1512

1513
endofloop:;
23,332,758✔
1514
/*
1515
        restore the current Wildcard assignments
1516
*/
1517
        i = nwstore;
23,332,758✔
1518
        if ( i > 0 ) {
23,332,758✔
1519
                m = AN.WildValue;
23,210,148✔
1520
                t = OldWork + ntwa; r = AT.WildMask;
23,210,148✔
1521
                do {
1522
                        *m++ = *t++; *m++ = *t++; *m++ = *t++; *m++ = *t++; *r++ = *t++;
85,610,556✔
1523
                } while ( --i > 0 );
85,610,556✔
1524
                C->numrhs = *t++;
23,210,148✔
1525
                C->Pointer = C->Buffer + oldcpointer;
23,210,148✔
1526
        }
1527

1528
endoloop:;
122,610✔
1529
        i = AN.WildArgs-1;
23,338,302✔
1530
        if ( i <= 0 ) {
23,338,302✔
1531
                AT.WorkPointer = OldWork;
16,688,796✔
1532
                return(0);
16,688,796✔
1533
        }
1534
        while ( --i >= 0 ) {
6,904,816✔
1535
                if ( AT.WildArgTaken[i] == 0 ) {
6,904,816✔
1536
                        if ( i == 0 ) {
479,788✔
1537
                                AT.WorkPointer = OldWork;
224,478✔
1538
                                return(0);
224,478✔
1539
                        }
1540
                }
1541
                else {
1542
                        (AT.WildArgTaken[i])--;
6,425,028✔
1543
                        numofwildarg = 0;
6,425,028✔
1544
                        for ( j = 0; j <= i; j++ ) {
18,297,626✔
1545
                                numofwildarg += AT.WildArgTaken[j];
11,872,598✔
1546
                        }
1547
                        AT.WildArgTaken[j] = AN.WildEat-numofwildarg;
6,425,028✔
1548
/* ----> bug to be replaced in other source code */
1549
                        for ( j++; j < AN.WildArgs; j++ ) AT.WildArgTaken[j] = 0;
6,677,830✔
1550
                        break;
6,425,028✔
1551
                }
1552
        }
1553
        goto topofloop;
6,425,028✔
1554
NoCaseB:
72✔
1555
/*
1556
        Restore the old Wildcard assignments
1557
*/
1558
        i = nwstore;
72✔
1559
        if ( i > 0 ) {
72✔
1560
                m = AN.WildValue;
72✔
1561
                t = OldWork + ntwa; r = AT.WildMask;
72✔
1562
                do {
1563
                        *m++ = *t++; *m++ = *t++; *m++ = *t++; *m++ = *t++; *r++ = *t++;
72✔
1564
                } while ( --i > 0 );
72✔
1565
                C->numrhs = *t++;
72✔
1566
                C->Pointer = C->Buffer + oldcpointer;
72✔
1567
        }
1568
        AT.WorkPointer = OldWork;
72✔
1569
        return(0);                /* no match */
72✔
1570
}
1571

1572
/*
1573
                 #] MatchFunction : 
1574
                 #[ ScanFunctions :                        WORD ScanFunctions(inpat,inter,par)
1575

1576
                Finds in which functions to look for a match.
1577
                inpat is the start of the pattern still to be matched.
1578
                inter is the start of the term still to be matched.
1579
                par gives information about commutativity.
1580
                        par = 0: nothing special
1581
                        par = 1: regular noncommuting function
1582
                        par = 2: GAMMA function
1583

1584
                AN.patstop: end of the functions field in the search pattern
1585
                AN.terstop: end of the functions field in the target pattern
1586
                AN.terstart: address of entire term;
1587

1588
                The actual matching of the functions and their arguments is done
1589
                in a number of different routines. Mainly MatchFunction when there
1590
                are no symmetry properties.
1591
                Also: MatchE
1592
                      MatchCy
1593
                      FunMatchSy
1594
                      FunMatchCy
1595

1596
                The main problem here is backtracking, ie continuing with wildcard
1597
                possibilities when a first assignment doesn't work.
1598
                Important note: this was completely forgotten in the symmetric
1599
                functions till 6-jan-2009. As of the moment this still has to
1600
                be fixed.  ??????21-mar-2023????? Is this still unfixed?????
1601

1602
                Functions inside functions can cause problems when antisymmetric
1603
                functions are involved. The sign of the term may be at stake.
1604
                At the lowest level this is no problem but in f(-fas(n2,n1)) this
1605
                plays a role. Next is when we have a product of functions inside
1606
                an argument. The strategy must be that we test the sign only at the
1607
                last function. Hence, when inpat+inpat[1] >= AN.patstop.
1608
                We might relax that to the last antisymmetric function at a later stage.
1609

1610
        New scheme to be implemented for non-commuting objects:
1611
        When we are matching a second (or higher) function, any match can only
1612
        be directly after the last matched non-commuting function or a commuting
1613
        function. This will take care of whatever happens in MatchE etc.
1614
*/
1615

1616
int ScanFunctions(PHEAD WORD *inpat, WORD *inter, WORD par)
40,375,332✔
1617
{
1618
        GETBIDENTITY
1619
        WORD i, *m, *t, *r, sym, psym;
1620
        WORD *newpat, *newter, *instart, *oinpat = 0, *ointer = 0;
40,375,332✔
1621
        WORD nwstore, offset, *OldWork, SetStop = 0, oRepFunNum = AN.RepFunNum;
40,375,332✔
1622
        WORD wilds, wildargs = 0, wildeat = 0, *wildargtaken;
40,375,332✔
1623
        WORD *Oterfirstcomm = AN.terfirstcomm;
40,375,332✔
1624
        CBUF *C = cbuf+AT.ebufnum;
40,375,332✔
1625
        int ntwa = AN.NumTotWildArgs;
40,375,332✔
1626
        LONG oldcpointer = C->Pointer - C->Buffer;
40,375,332✔
1627
        WORD oldSignCheck = AN.SignCheck;
40,375,332✔
1628
        instart = inter;
40,375,332✔
1629
/*
1630
        Only active for the last function in the pattern.
1631
        The actual test on the sign is in MatchFunction or the symmetric functions
1632
*/
1633
        if ( AN.nogroundlevel ) {
40,375,332✔
1634
                AN.SignCheck = ( inpat + inpat[1] >= AN.patstop ) ? 1 : 0;
8,988✔
1635
        }
1636
        else {
1637
                AN.SignCheck = 0;
40,366,344✔
1638
        }
1639
/*
1640
                        Store the current Wildcard assignments
1641
*/
1642
        t = wildargtaken = OldWork = AT.WorkPointer;
40,375,332✔
1643
        t += ntwa;
40,375,332✔
1644
        m = AN.WildValue;
40,375,332✔
1645
        nwstore = i = (m[-SUBEXPSIZE+1]-SUBEXPSIZE)/4;
40,375,332✔
1646
        if ( i > 0 ) {
40,375,332✔
1647
                r = AT.WildMask;
40,030,308✔
1648
                do {
1649
                        *t++ = *m++; *t++ = *m++; *t++ = *m++; *t++ = *m++; *t++ = *r++;
135,104,802✔
1650
                } while ( --i > 0 );
135,104,802✔
1651
                *t++ = C->numrhs;
40,030,308✔
1652
        }
1653
        if ( t >= AT.WorkTop ) {
40,375,332✔
1654
                MLOCK(ErrorMessageLock);
1655
                MesWork();
×
1656
                MUNLOCK(ErrorMessageLock);
1657
                Terminate(-1);
×
1658
        }
1659
        AT.WorkPointer = t;
40,375,332✔
1660
        do {
1661
#ifndef NEWCOMMUTE
1662
/*
1663
                Find an eligible unsubstituted function
1664
*/
1665
                if ( AN.RepFunNum > 0 ) {
254,399,814✔
1666
/*
1667
                        First try a non-commuting function, just after the last
1668
                        substituted non-commuting function.
1669
*/
1670
                        if ( *inter >= FUNCTION && functions[*inter-FUNCTION].commute ) {
80,524,728✔
1671
                                do {
1672
                                        offset = WORDDIF(inter,AN.terstart);
6✔
1673
                                        for ( i = 0; i < AN.RepFunNum; i += 2 ) {
12✔
1674
                                                if ( AN.RepFunList[i] >= offset ) break;
6✔
1675
                                        }
1676
                                        if ( i >= AN.RepFunNum ) break;
6✔
1677
                                        inter += inter[1];
×
1678
                                } while ( inter < AN.terfirstcomm );
×
1679
                                if ( inter < AN.terfirstcomm ) { /* Check that it is directly after */
6✔
1680
                                        for ( i = 0; i < AN.RepFunNum; i += 2 ) {
6✔
1681
                                                if ( functions[AN.terstart[AN.RepFunList[i]]-FUNCTION].commute
6✔
1682
                                                && AN.RepFunList[i]+AN.terstart[AN.RepFunList[i]+1] == offset ) break;
6✔
1683
                                        }
1684
                                        if ( i < AN.RepFunNum ) goto trythis;
6✔
1685
                                }
1686
                                inter = AN.terfirstcomm;
×
1687
                        }
1688
/*
1689
                        Now try one of the commuting functions
1690
*/
1691
                        while ( inter < AN.terstop ) {
92,657,742✔
1692
                                offset = WORDDIF(inter,AN.terstart);
92,532,246✔
1693
                                for ( i = 0; i < AN.RepFunNum; i += 2 ) {
176,966,082✔
1694
                                        if ( AN.RepFunList[i] == offset ) break;
96,566,856✔
1695
                                }
1696
                                if ( i >= AN.RepFunNum ) break;
92,532,246✔
1697
                                inter += inter[1];
12,133,020✔
1698
                        }
1699
                        if ( inter >= AN.terstop ) goto Failure;
80,524,722✔
1700
trythis:;
80,399,232✔
1701
                }
1702
                else {
1703
/*
1704
                        The first function can be anywhere. We have no problems.
1705
*/
1706
                        offset = WORDDIF(inter,AN.terstart);
173,875,086✔
1707
                }
1708
#else
1709
                /* first find an unsubstituted function */
1710
                do {
1711
                        offset = WORDDIF(inter,AN.terstart);
1712
                        for ( i = 0; i < AN.RepFunNum; i += 2 ) {
1713
                                if ( AN.RepFunList[i] == offset ) break;
1714
                        }
1715
                        if ( i >= AN.RepFunNum ) break;
1716
                        inter += inter[1];
1717
                } while ( inter < AN.terstop );
1718
                if ( inter >= AN.terstop ) goto Failure;
1719
#endif
1720
                wilds = 0;
254,274,318✔
1721
                /* We found one */
1722
                if ( *inter >= FUNCTION && *inpat >= FUNCTION ) {
254,274,318✔
1723
                        if ( *inpat == *inter || *inpat >= FUNCTION + WILDOFFSET ) {
249,630,528✔
1724
/*
1725
                                if ( inter[1] == FUNHEAD ) goto rewild;
1726
*/
1727
                                if ( functions[*inter-FUNCTION].spec >= TENSORFUNCTION
34,973,034✔
1728
                                && ( *inter == *inpat ||
137,058✔
1729
                                functions[*inpat-FUNCTION-WILDOFFSET].spec >= TENSORFUNCTION ) ) {
420✔
1730
                                        sym = functions[*inter-FUNCTION].symmetric & ~REVERSEORDER;
137,058✔
1731
                                        if ( *inpat == *inter ) psym = sym;
137,058✔
1732
                                        else psym = functions[*inpat-FUNCTION-WILDOFFSET].symmetric & ~REVERSEORDER;
420✔
1733
                                        if ( sym == ANTISYMMETRIC || sym == SYMMETRIC
137,058✔
1734
                                        || psym == SYMMETRIC || psym == ANTISYMMETRIC ) {
107,208✔
1735
                                                if ( sym == ANTISYMMETRIC && psym == SYMMETRIC ) goto rewild;
29,850✔
1736
                                                if ( sym == SYMMETRIC && psym == ANTISYMMETRIC ) goto rewild;
29,634✔
1737
/*
1738
                                                Special function call for (anti)symmetric tensors
1739
*/
1740
                                                if ( MatchE(BHEAD inpat,inter,instart,par) ) goto OnSuccess;
29,634✔
1741
                                        }
1742
                                        else if ( sym == CYCLESYMMETRIC || sym == RCYCLESYMMETRIC
107,208✔
1743
                                        || psym == CYCLESYMMETRIC || psym == RCYCLESYMMETRIC ) {
87,558✔
1744
/*
1745
                                                Special function call for (r)cyclic tensors
1746
*/
1747
                                                if ( MatchCy(BHEAD inpat,inter,instart,par) ) goto OnSuccess;
19,650✔
1748
                                        }
1749
                                        else goto rewild;
87,558✔
1750
                                }
1751
                                else if ( functions[*inter-FUNCTION].spec <= 0
34,835,976✔
1752
                                && ( *inter == *inpat ||
34,835,976✔
1753
                                functions[*inpat-FUNCTION-WILDOFFSET].spec <= 0 ) ) {
10,986✔
1754
                                        sym = functions[*inter-FUNCTION].symmetric & ~REVERSEORDER;
34,835,778✔
1755
                                        if ( *inpat == *inter ) psym = sym;
34,835,778✔
1756
                                        else psym = functions[*inpat-FUNCTION-WILDOFFSET].symmetric & ~REVERSEORDER;
10,788✔
1757
                                        if ( psym == SYMMETRIC || sym == SYMMETRIC
34,835,778✔
1758
/*
1759
                                        The next statement was commented out. Why????
1760
                                        Werkt nog niet. Teken wordt nog niet bijgehouden.
1761
                                        5-nov-2001
1762
*/
1763
                                        || psym == ANTISYMMETRIC || sym == ANTISYMMETRIC
33,601,920✔
1764
                                        ) {
1765
                                                if ( sym == ANTISYMMETRIC && psym == SYMMETRIC ) goto rewild;
1,233,948✔
1766
                                                if ( sym == SYMMETRIC && psym == ANTISYMMETRIC ) goto rewild;
1,233,066✔
1767
                                                if ( FunMatchSy(BHEAD inpat,inter,instart,par) ) goto OnSuccess;
1,233,066✔
1768
                                        }
1769
                                        else
1770
                                                if ( sym == CYCLESYMMETRIC || sym == RCYCLESYMMETRIC
33,601,830✔
1771
                                        || psym == CYCLESYMMETRIC || psym == RCYCLESYMMETRIC ) {
33,601,830✔
1772
                                                if ( FunMatchCy(BHEAD inpat,inter,instart,par) ) goto OnSuccess;
×
1773
                                        }
1774
                                        else goto rewild;
33,601,830✔
1775
                                }
1776
                                else goto rewild;
198✔
1777
                                AN.terfirstcomm = Oterfirstcomm;
1,275,246✔
1778
                        }
1779
                        else if ( par > 0 ) { SetStop = 1; goto maybenext; }
214,657,494✔
1780
                }
1781
                else {
1782
rewild:
4,643,790✔
1783
                AN.terfirstcomm = Oterfirstcomm;
38,340,018✔
1784
                if ( *inter != SUBEXPRESSION && MatchFunction(BHEAD inpat,inter,&wilds) ) {
38,340,018✔
1785
                        AN.terfirstcomm = Oterfirstcomm;
16,760,658✔
1786
                        if ( wilds ) {
16,760,658✔
1787
/*
1788
                                Store wildcards to continue in MatchFunction if the current
1789
                                wildcards do not work out.
1790
*/
1791
                                wildargs = AN.WildArgs;
140,724✔
1792
                                wildeat = AN.WildEat;
140,724✔
1793
                                for ( i = 0; i < wildargs; i++ ) wildargtaken[i] = AT.WildArgTaken[i];
428,208✔
1794
                                oinpat = inpat; ointer = inter;
140,724✔
1795
                        }
1796
                        if ( par && *inter == GAMMA && AN.RepFunList[AN.RepFunNum+1] ) {
16,760,658✔
1797
                                SetStop = 1; goto NoMat;
×
1798
                        }
1799
                        if ( par == 2 ) {
16,760,658✔
1800
                                if ( *inter < FUNCTION || functions[*inter-FUNCTION].commute ) {
×
1801
                                        goto NoMat;
×
1802
                                }
1803
                                par = 1;
×
1804
                        }
1805
                        AN.RepFunList[AN.RepFunNum] = offset;
16,760,658✔
1806
                        AN.RepFunNum += 2;
16,760,658✔
1807
                        newpat = inpat + inpat[1];
16,760,658✔
1808
                        if ( newpat >= AN.patstop ) {
16,760,658✔
1809
                                if ( AN.UseFindOnly == 0 ) {
5,426,196✔
1810
                                        if ( FindOnce(BHEAD AN.findTerm,AN.findPattern) ) {
28,908✔
1811
                                                AN.UsedOtherFind = 1;
28,908✔
1812
                                                goto OnSuccess;
28,908✔
1813
                                        }
1814
                                        AN.RepFunNum -= 2;
×
1815
                                        goto NoMat;
×
1816
                                }
1817
                                goto OnSuccess;
5,397,288✔
1818
                        }
1819
                        if ( *inter < FUNCTION || functions[*inter-FUNCTION].commute ) {
11,334,462✔
1820
                                newter = inter + inter[1];
12✔
1821
                                if ( newter >= AN.terstop ) goto Failure;
12✔
1822
                                if ( *inter == GAMMA && inpat[1] <
12✔
1823
                                inter[1] - AN.RepFunList[AN.RepFunNum-1] ) {
×
1824
                                        if ( ScanFunctions(BHEAD newpat,newter,2) ) goto OnSuccess;
×
1825
                                        AN.terfirstcomm = Oterfirstcomm;
×
1826
                                }
1827
                                else if ( *newter ==  SUBEXPRESSION ) {}
12✔
1828
                                else if ( functions[*inter-FUNCTION].commute ) {
12✔
1829
                                        if ( ScanFunctions(BHEAD newpat,newter,1) ) goto OnSuccess;
12✔
1830
                                        AN.terfirstcomm = Oterfirstcomm;
×
1831
                                        if ( ( *newpat < (FUNCTION+WILDOFFSET)
×
1832
                                                && ( functions[*newpat-FUNCTION].commute == 0 ) ) ||
×
1833
                                                ( *newpat >= (FUNCTION+WILDOFFSET)
×
1834
                                                && ( functions[*newpat-FUNCTION-WILDOFFSET].commute == 0 ) ) ) {
×
1835
                                                newter = AN.terfirstcomm;
×
1836
                                                if ( newter < AN.terstop && ScanFunctions(BHEAD newpat,newter,1) ) goto OnSuccess;
×
1837
                                        }
1838
                                }
1839
                                else {
1840
                                        if ( ScanFunctions(BHEAD newpat,instart,1) ) goto OnSuccess;
×
1841
                                        AN.terfirstcomm = Oterfirstcomm;
×
1842
                                }
1843
                                SetStop = par;
×
1844
                        }
1845
                        else {
1846
/*
1847
                                Shouldn't this be newpat instead of inpat?????
1848
*/
1849
                                if ( par && inter > instart && ( ( *newpat < (FUNCTION+WILDOFFSET)
11,334,450✔
1850
                                && functions[*newpat-FUNCTION].commute ) ||
×
1851
                                ( *newpat >= (FUNCTION+WILDOFFSET)
×
1852
                                && functions[*newpat-FUNCTION-WILDOFFSET].commute ) ) ) {
×
1853
                                        SetStop = 1;
×
1854
                                }
1855
                                else {
1856
                                        newter = instart;
11,334,450✔
1857
                                        if ( ScanFunctions(BHEAD newpat,newter,par) ) goto OnSuccess;
11,334,450✔
1858
                                        AN.terfirstcomm = Oterfirstcomm;
11,211,834✔
1859
                                }
1860
                        }
1861
/*
1862
                        Restore the old Wildcard assignments
1863
*/
1864
NoMat:
11,211,870✔
1865
                        i = nwstore;
11,211,870✔
1866
                        if ( i > 0 ) {
11,211,870✔
1867
                                m = AN.WildValue;
11,071,602✔
1868
                                t = OldWork + ntwa; r = AT.WildMask;
11,071,602✔
1869
                                do {
1870
                                        *m++ = *t++; *m++ = *t++; *m++ = *t++; *m++ = *t++; *r++ = *t++;
41,026,278✔
1871
                                } while ( --i > 0 );
41,026,278✔
1872
                                C->numrhs = *t++;
11,071,602✔
1873
                                C->Pointer = C->Buffer + oldcpointer;
11,071,602✔
1874
                        }
1875
/*                        AN.RepFunNum -= 2; */
1876
                        AN.RepFunNum = oRepFunNum;
11,211,870✔
1877
                        if ( wilds ) {
11,211,870✔
1878
                                inter = ointer; inpat = oinpat;
5,544✔
1879
                                AN.WildArgs = wildargs;
5,544✔
1880
                                AN.WildEat = wildeat;
5,544✔
1881
                                for ( i = 0; i < wildargs; i++ ) AT.WildArgTaken[i] = wildargtaken[i];
16,632✔
1882
                                goto rewild;
5,544✔
1883
                        }
1884
                        if ( SetStop ) break;
11,206,326✔
1885
                }
1886
                else if ( par ) {
21,579,360✔
1887
maybenext:
×
1888
                        if ( *inpat < (FUNCTION+WILDOFFSET) ) {
×
1889
                                if ( *inpat < FUNCTION ||
×
1890
                                functions[*inpat-FUNCTION].commute ) break;
×
1891
                        }
1892
                        else {
1893
                                if ( functions[*inpat-FUNCTION-WILDOFFSET].commute ) break;
×
1894
                        }
1895
                }}
1896
                inter += inter[1];
248,718,426✔
1897
        } while ( inter < AN.terstop );
248,718,426✔
1898
Failure:
34,693,944✔
1899
    AN.SignCheck = oldSignCheck;
34,819,440✔
1900
        AT.WorkPointer = OldWork;
34,819,440✔
1901
        return(0);
34,819,440✔
1902
OnSuccess:
5,555,928✔
1903
        if ( AT.idallflag && AN.nogroundlevel <= 0 ) {
5,555,928✔
1904
                if ( AT.idallmaxnum > 0 && AT.idallnum >= AT.idallmaxnum ) {
36✔
1905
                        AN.terfirstcomm = Oterfirstcomm;
×
1906
                    AN.SignCheck = oldSignCheck;
×
1907
                        AT.WorkPointer = OldWork;
×
1908
                        return(0);
×
1909
                }
1910
                SubsInAll(BHEAD0);
36✔
1911
                AT.idallnum++;
36✔
1912
                if ( AT.idallmaxnum == 0 || AT.idallnum < AT.idallmaxnum ) goto NoMat;
36✔
1913
        }
1914
        AN.terfirstcomm = Oterfirstcomm;
5,555,892✔
1915
    AN.SignCheck = oldSignCheck;
5,555,892✔
1916
/*
1917
        Now the disorder test
1918
*/
1919
        if ( AN.DisOrderFlag && AN.RepFunNum >= 4 ) {
5,555,892✔
1920
                WORD k, kk;
1921
                for ( i = 2; i < AN.RepFunNum; i += 2 ) {
×
1922
/*
1923
------------> We still have to copy the code from Normalize wrt properorderflag
1924
*/
1925
                        m = AN.terstart + AN.RepFunList[i-2];
×
1926
                        t = AN.terstart + AN.RepFunList[i];
×
1927
                        if ( *m != *t ) {
×
1928
                                if ( *m > *t ) continue;
×
1929
                                goto doesmatch;
×
1930
                        }
1931
                        if ( *m >= FUNCTION && functions[*m-FUNCTION].spec >=
×
1932
                                TENSORFUNCTION ) {
1933
                                k = m[1] - FUNHEAD;
×
1934
                                kk = t[1] - FUNHEAD;
×
1935
                                m += FUNHEAD;
×
1936
                                t += FUNHEAD;
×
1937
                        }
1938
                        else {
1939
                                k = m[1] - FUNHEAD;
×
1940
                                kk = t[1] - FUNHEAD;
×
1941
                                m += FUNHEAD;
×
1942
                                t += FUNHEAD;
×
1943
                        }
1944
                        while ( k > 0 && kk > 0 ) {
×
1945
                                if ( *m < *t ) goto NextFor;
×
1946
                                else if ( *m++ > *t++ ) goto doesmatch;
×
1947
                                k--; kk--;
×
1948
                        }
1949
                        if ( k > 0 ) goto doesmatch;
×
1950
NextFor:;
×
1951
                }
1952
                SetStop = 1;
×
1953
                goto NoMat;
×
1954
        }
1955
doesmatch:
5,555,892✔
1956
        AT.WorkPointer = OldWork;
5,555,892✔
1957
        return(1);
5,555,892✔
1958
}
1959

1960
/*
1961
                 #] ScanFunctions : 
1962
        #] Patterns :
1963
*/
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc