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

vermaseren / form / 9364948935

04 Jun 2024 09:49AM UTC coverage: 49.979% (-0.02%) from 49.999%
9364948935

Pull #526

github

web-flow
Merge 7062bd769 into 83e3d4185
Pull Request #526: RFC: better debugging

52 of 415 new or added lines in 46 files covered. (12.53%)

32 existing lines in 2 files now uncovered.

41391 of 82816 relevant lines covered (49.98%)

878690.77 hits per line

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

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

35
#include "form3.h"
36
 
37
static WORD one = 1;
38

39
/*
40
          #] Includes : 
41
          #[ CoCanonicalize :
42

43
        Syntax:
44
                Canonicalize,mainoption,...
45
        With the main options currently:
46
                Canonicalize,topology,vertexfunction,edgefunction,OutDollar,extraoptions;
47
                Canonicalize,polynomial,InDollar,set_or_setname_or_dollar,OutDollar,extraoptions;
48
        The vertex function needs to have the format (assume it is called vx):
49
                vx(p1,p2,-p3)  or vx(-p1,p2,p3,-p4) etc.
50
        The external lines have a vertex with only one line.
51
        All momenta that form connections should be unique.
52
        In principle the - signs are not relevant for the topology, but they
53
        may exist already in the remaining part of the diagram. They are also
54
        part of the canonical form.
55
        The edge function can be used in different ways, depending on the options.
56
        The extraoption(s) should be nonnegative integers or $variables that evaluate
57
        into nonnegative integers (integers less than 2^31).
58
        The Indollar variable contains the polynomial to be canonicalized.
59
        The OutDollar variable should be the name of a $-variable (as in $out) which
60
        will be filled with a replace_ function. The canonicalization can then
61
        be executed in the whole term with the   Multiply $out;  command.
62
*/
63

64
int CoCanonicalize(UBYTE *s)
×
65
{
66
        WORD args[10], *a, num;
×
67
        UBYTE *t, c;
×
68
        args[0] = TYPECANONICALIZE;
×
69
        a = args+2;
×
70
        while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
71
        t = s; while ( FG.cTable[*s] == 0 ) s++;
×
72
        c = *s; *s = 0;
×
73
        if ( StrICmp(t,(UBYTE *)("topology")) == 0 ) {
×
74
                *s = c; *a++ = 0;
×
75
                while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
76
                s = GetFunction(s,a);
×
77
                while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
78
                s = GetFunction(s,a+1);
×
79
                if ( *a == 0 || a[1] == 0 ) return(1);
×
80
                a += 2;
81
        }
82
        else if ( StrICmp(t,(UBYTE *)("polynomial")) == 0 ) {
×
83
                *s = c; *a++ = 1;
×
84
                while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
85
/*
86
                Now get the name of the input $-variable
87
*/
88
                if ( *s != '$' ) {
×
89
                        MesPrint("&Canonicalize statement needs a $-variable for its input.");
×
90
                        return(1);
×
91
                }
92
                s++; t = s; while ( FG.cTable[*s] < 2 ) s++;
×
93
                c = *s; *s = 0;
×
94
                if ( GetName(AC.dollarnames,t,&num,NOAUTO) == CDOLLAR ) *a++ = num;
×
95
                else { *a++ = AddDollar(t,DOLINDEX,&one,1); }
×
96
                *s = c;
×
97
/*
98
                Now the set
99
*/
100
                if ( *s == '{' ) {
×
101
                        t = s+1; SKIPBRA2(s)
×
102
                        c = *s; *s = 0;
×
103
                        *a++ = DoTempSet(t,s);
×
104
                        *s++ = c;
×
105
                }
106
                else if ( FG.cTable[*s] == 0 || *s == '[' ) {
×
107
                        t = s;
×
108
                        if ( ( s = SkipAName(s) ) == 0 ) {
×
109
                                MesPrint("&Illegal name for set in Canonicalize statement: %s",t);
×
110
                                return(1);
×
111
                        }
112
                        c = *s; *s = 0;
×
113
                        if ( GetName(AC.varnames,t,a,WITHAUTO) == CSET ) {
×
114
                                if ( Sets[*a].type != CSYMBOL ) {
×
115
                                        MesPrint("&In Canonicalize: %s is not a set of symbols.",t);
×
116
                                        return(1);
×
117
                                }
118
                        }
119
                        else {
120
                                MesPrint("&In Canonicalize: %s is not a set.",t);
×
121
                                return(1);
×
122
                        }
123
                        *s = c; a++;
×
124
                }
125
                else if ( *s == '$' ) {
×
126
                        s++; t = s; while ( FG.cTable[*s] < 2 ) s++;
×
127
                        c = *s; *s = 0;
×
128
                        if ( GetName(AC.dollarnames,t,&num,NOAUTO) == CDOLLAR ) *a++ = -num-2;
×
129
                        else {
130
                                MesPrint("&In Canonicalize: %s is undefined.",t-1);
×
131
                                return(1);
×
132
                        }
133
                        *s = c;
×
134
                }
135
                else {
136
                        MesPrint("&In Canonicalize: Illegal third(=set) argument.");
×
137
                        return(1);
×
138
                }
139
        }
140
        else {
141
                MesPrint("&Unrecognized option in Canonicalize statement: %s",t);
×
142
                return(1);
×
143
        }
144
/*
145
        Now get the name of the output $-variable
146
*/
147
        while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
148
        if ( *s != '$' ) {
×
149
                MesPrint("&Canonicalize statement needs a $-variable for its output.");
×
150
                return(1);
×
151
        }
152
        s++; t = s; while ( FG.cTable[*s] < 2 ) s++;
×
153
        c = *s; *s = 0;
×
154
        if ( GetName(AC.dollarnames,t,&num,NOAUTO) == CDOLLAR ) *a++ = num;
×
155
        else { *a++ = AddDollar(t,DOLINDEX,&one,1); }
×
156
        *s = c;
×
157
/*
158
        Now the options. At the moment we just do one of them.
159
        (the first extra option is relevant to determine the use of the edge function)
160
        In the future we may have to be more flexible.
161
*/
162
        a[0] = 0;  /* default value */
×
163
        while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
164
        if ( *s != 0 ) {
×
165
                s = GetNumber(s,a);
×
166
                if ( *a == -1 ) return(1);
×
167
                while ( *s == ',' || *s == '\t' || *s == ' ' ) s++;
×
168
                a++;
169
        }
170
/*
171
        Now complete the args string and put it in the compiler buffer
172
*/
173
        args[1] = a-args;
×
174
        AddNtoL(args[1],args);
×
175
        return(0);
×
176
}
177

178
/*
179
          #] CoCanonicalize : 
180
          #[ DoCanonicalize :
181

182
        Does the canonicalization. The output term overwrites the input term.
183
*/
184

185
int DoCanonicalize(PHEAD WORD *term, WORD *params)
×
186
{
187
        WORD args[10];
×
188
        int i;
×
189
/*
190
        First check whether we need to expand dollars;
191
*/
192
        for ( i = 0; i < params[1]; i++ ) args[i] = params[i];
×
193
        if ( args[2] == 0 ) { /* topology */
×
194
                for ( i = 3; i < 5; i++ ) {
×
195
                        if ( args[i] < 0 ) { /* This is a dollar */
×
196
                                args[i] = DolToFunction(BHEAD -args[i]-2);
×
197
                                if ( args[i] == 0 ) {
×
198
                                        MLOCK(ErrorMessageLock);
×
199
                                        MesPrint("Value of $-variable in Canonicalize statement should be a function.");
×
200
                                        MUNLOCK(ErrorMessageLock);
×
NEW
201
                                        TERMINATE(-1);
×
202
                                }
203
                        }
204
                }
205
                for ( i = 6; i < args[1]; i++ ) { /* Extra options */
×
206
                        if ( args[i] < 0 ) { /* This is a dollar */
×
207
                                args[i] = DolToNumber(BHEAD -args[i]-2);
×
208
                                if ( args[i] < 0 ) {
×
209
                                        MLOCK(ErrorMessageLock);
×
210
                                        MesPrint("Value of $-variable in Canonicalize statement should be a nonnegative number < %l.",(LONG)MAXPOSITIVE);
×
211
                                        MUNLOCK(ErrorMessageLock);
×
NEW
212
                                        TERMINATE(-1);
×
213
                                }
214
                        }
215
                }
216
                switch ( args[6] ) {
×
217
                        case 1: {/* pass the vertex and edge functions. */
×
218
                                WORD *tstop, *t, *tedge, *te;
×
219
                                tstop = term + *term; tstop -= ABS(tstop[-1]);
×
220
                                t = term+1;
×
221
                                tedge = AT.WorkPointer; te = tedge+1;
×
222
                                while ( t < tstop ) {
×
223
                                        if ( *t != args[3] && *t != args[4] ) { t += t[1]; continue; }
×
224
                                        for ( i = 0; i < t[1]; i++ ) te[i] = t[i];
×
225
                                        te += t[1]; t += t[1];
×
226
                                }
227
                                *te++ = 1; *te++ = 1; *te++ = 3;
×
228
                                tedge[0] = te-tedge;
×
229
                                AT.WorkPointer = te;
×
230
/*
231
                                DoVertexCanonicalize(BHEAD term,tedge,args[3],args[4],args[5],args[6]);
232
*/
233
                                AT.WorkPointer = tedge;
×
234
                        } break;
×
235
                        case 2: {/* pass the edge functions only */
×
236
                                WORD *tstop, *t, *tedge, *te;
×
237
                                tstop = term + *term; tstop -= ABS(tstop[-1]);
×
238
                                t = term+1;
×
239
                                tedge = AT.WorkPointer; te = tedge+1;
×
240
                                while ( t < tstop ) {
×
241
                                        if ( *t != args[4] ) { t += t[1]; continue; }
×
242
                                        for ( i = 0; i < t[1]; i++ ) te[i] = t[i];
×
243
                                        te += t[1]; t += t[1];
×
244
                                }
245
                                *te++ = 1; *te++ = 1; *te++ = 3;
×
246
                                tedge[0] = te-tedge;
×
247
                                AT.WorkPointer = te;
×
248
/*
249
                                DoEdgeCanonicalize(BHEAD term,tedge,args[5]);
250
*/
251
                                AT.WorkPointer = tedge;
×
252
                        } break;
×
253
                        default: {
×
254
                                DoTopologyCanonicalize(BHEAD term,args[3],args[4],args+5);
×
255
                        } break;
×
256
                }
257
/*
258
                Call here the topology canonicalization
259
                We will have the arguments:
260
                        args[3]: The function used as vertex function
261
                        args[4]: The function used as edge function
262
                        args[5]: The number of the dollar to be used for the output
263
                        args[6]: Potentially other options (like saying how to use args[4]).
264
                        term:    The term in which the topology resides.
265
*/
266

267
        }
268
        else if ( args[2] == 1 ) { /* polynomial */
×
269
                WORD *symlist, nsymlist;
270
                for ( i = 6; i < args[1]; i++ ) { /* Extra options */
×
271
                        if ( args[i] < 0 ) { /* This is a dollar */
×
272
                                args[i] = DolToNumber(BHEAD -args[i]-2);
×
273
                                if ( args[i] < 0 ) {
×
274
                                        MLOCK(ErrorMessageLock);
×
275
                                        MesPrint("Value of $-variable in Canonicalize statement should be a nonnegative number < %l.",(LONG)MAXPOSITIVE);
×
276
                                        MUNLOCK(ErrorMessageLock);
×
NEW
277
                                        TERMINATE(-1);
×
278
                                }
279
                        }
280
                }
281
/*
282
                Now we sort out the set. We create a pointer to the list of set
283
                elements, and we determine the number of elements in the set.
284
*/
285
                symlist = AT.WorkPointer;
×
286
                if ( args[4] < -1 ) { /* Dollar that should expand into a list of symbols */
×
287
                        DOLLARS d = Dollars - args[4] - 2;
×
288
                        WORD *ds, *insym;
×
289
                        if ( d->type != DOLWILDARGS ) {
×
290
NoWildArg:
×
291
                                MLOCK(ErrorMessageLock);
×
292
                                MesPrint("Value of $-variable in Canonicalize statement should be a argument wildcard of symbol arguments.");
×
293
                                MUNLOCK(ErrorMessageLock);
×
NEW
294
                                TERMINATE(-1);
×
295
                        }
296
                        insym = symlist; ds = d->where+1;
×
297
                        while ( *ds ) {
×
298
                                if ( *ds != -SYMBOL ) goto NoWildArg;
×
299
                                *insym++ = ds[1];
×
300
                                ds += 2;
×
301
                        }
302
                        nsymlist = insym-symlist;
×
303
                }
304
                else { /*if ( args[4] >= 0 ) */
305
                        WORD *ss, *sy, n;
×
306
                        ss = (WORD *)(AC.SetElementList.lijst)+Sets[args[4]].first;
×
307
                        nsymlist = n = Sets[args[4]].last-Sets[args[4]].first;
×
308
                        sy = symlist = AT.WorkPointer;
×
309
                        NCOPY(sy,ss,n);
×
310
                }
311
                AT.WorkPointer = symlist+nsymlist;
×
312
/*
313
                Call here the polynomial canonicalization
314
                We will have the arguments:
315
                        args[3]: The number of the dollar to be used for the input
316
                        symlist: an array of symbols
317
                        nsymlist: the number of symbols in symlist
318
                        args[5]: The number of the dollar to be used for the output
319
                        args[6]: Potentially other options.
320
*/
321
/*
322
                DoPolynomialCanonicalize(BHEAD args[3],symlist,nsymlist,args[5],args[6]);
323
*/
324
                AT.WorkPointer = symlist;
×
325
        }
326
        return(0);
×
327
}
328

329
/*
330
          #] DoCanonicalize : 
331
          #[ GenTopologies :
332

333
        This function has the syntax
334
                topologies_(nloops,    Number of loops
335
                        nlegs,             Number of legs
336
                        setvertexsizes,    A set which tells which vertices are allowed like {3,4}.
337
                        set_extmomenta,    The name of a set with the external momenta
338
                        set_intmomenta     The name of a set with the internal momenta
339
                        [,options])
340
        The output will be using the built in functions vertex_ and edge_.
341

342
        The test for whether this function can be evaluated is in TestSub (inside
343
        file proces.c) (search for the string TOPOLOGIES). 
344
        This passes the code -15 in AN.TeInFun to Generator, which then calls
345
        the GenTopologies routine.
346
*/
347

348
#ifdef OLDTOPO
349

350
WORD GenTopologies(PHEAD WORD *term,WORD level)
351
{
352
        WORD *t1, *tt1, *tstop, *t, *tt;
353
        WORD *oldworkpointer = AT.WorkPointer;
354
        WORD option1 = 0, option2 = 0, setoption = -1;
355
        WORD retval;
356
/*
357

358
        We have to go through the testing procedure again, because there could
359
        be more than one topologies_ function and not all have to be expandable.
360
*/
361
        tstop = term+*term; tstop -= ABS(tstop[-1]);
362
        tt = term+1;
363
        while ( tt < tstop ) {
364
                t = tt; tt = t+t[1];
365
                if ( *t != TOPOLOGIES ) continue;
366
                tt = t + t[1]; t1 = t + FUNHEAD;
367
                if ( t1+10 > tt || *t1 != -SNUMBER || t1[1] < 0 ||      /* loops */
368
                        t1[2] != -SNUMBER || ( t1[3] < 0 && t1[3] != -2 ) ||/* legs */
369
                        t1[4] != -SETSET || Sets[t1[5]].type != CNUMBER ||  /* set vertices */
370
                        t1[6] != -SETSET || Sets[t1[7]].type != CVECTOR ||  /* outvectors */
371
                        t1[8] != -SETSET || Sets[t1[9]].type != CVECTOR ) continue;
372
                tt1 = t1 + 10;
373
                if ( tt1+2 <= tt && tt1[0] == -SETSET ) {
374
                        if ( Sets[t1[5]].last-Sets[t1[5]].first !=
375
                                 Sets[tt1[1]].last-Sets[tt1[1]].first ) continue;
376
                        setoption = tt1[1]; tt1 += 2;
377
                }
378
                if ( tt1+2 <= tt && tt1[0] == -SNUMBER ) { option1 = tt1[1]; tt1 += 2; }
379
                if ( tt1+2 <= tt && tt1[0] == -SNUMBER ) { option2 = tt1[1]; tt1 += 2; }
380
                AT.setinterntopo = t1[9];
381
                AT.setexterntopo = t1[7];
382
                AT.TopologiesTerm = term;
383
                AT.TopologiesStart = t;
384
                AT.TopologiesLevel = level;
385
                AT.TopologiesOptions[0] = option1;
386
                AT.TopologiesOptions[1] = option2;
387
                retval = GenerateTopologies(BHEAD t1[1],t1[3],t1[5],setoption);
388
                AT.WorkPointer = oldworkpointer;
389
                return(retval);
390
        }
391
        MLOCK(ErrorMessageLock);
392
        MesPrint("Internal error: topologies_ function not encountered.");
393
        MUNLOCK(ErrorMessageLock);
394
        return(-1);
395

396
}
397

398
#endif
399

400
/*
401
          #] GenTopologies : 
402
          #[ DoTopologyCanonicalize :
403

404
        term: The term
405
        vert: the vertex function
406
        edge: the edge function
407
        args[0]: the number of the output dollar
408
        args[1]: options
409
        return value should be zero if all is correct.
410

411
        The external lines connect to an 'external vertex' which has only one line.
412
        The vertices are of a type: vertex_(p1,p2,-p3)*vertex_(p3,p4,p5) etc.
413
        The edges indicate noninteger powers of the lines:
414
                edge_(p1,2) means 1/p1.p1^(2*ep)
415
*/
416

417
int DoTopologyCanonicalize(PHEAD WORD *term,WORD vert,WORD edge,WORD *args)
×
418
{
419
        int nvert = 0, nvert2, i, ii, jj, flipnames = 0, nparts/*, level, num */;
×
420
        WORD *tstop, *t, *tt, *tend, *td;
×
421
        WORD *oldworkpointer = AT.WorkPointer;
×
422
        WORD *termcopy = TermMalloc("TopologyCanonize1");
×
423
        WORD *vet= TermMalloc("TopologyCanonize2");
×
424
        WORD *partition, *environ, *connect, *pparts, *p;
×
425
/*
426
        WORD *pparts;
427
*/
428
        WORD momenta[150],flips[50],nmomenta = 0, nflips = 0;
×
429
/*
430
        Step one: the vertices should get a number. We copy the term for this.
431
                  We need a high number for the vertex function to make sure 
432
                  that it comes after the edge function in the sorting.
433
*/
434
        if ( args[0] < args[1] ) { flipnames = 1; }
×
435
        tend = term + *term; tend -= ABS(tend[-1]); t = term+1; tt = termcopy+1;
×
436
        while ( t < tend ) {
×
437
                if ( *t == vert ) {
×
438
                        for ( i = FUNHEAD; i < t[1]; i += 2 ) {
×
439
                                if ( t[i] == -VECTOR || ( t[i] == -INDEX && t[i+1] < 0 ) ) {
×
440
                                        momenta[nmomenta++] = -VECTOR;
×
441
                                        momenta[nmomenta++] = t[i+1];
×
442
                                }
443
                                else if ( t[i] == -MINVECTOR ) {
×
444
                                        momenta[nmomenta++] = -MINVECTOR;
×
445
                                        momenta[nmomenta++] = t[i+1];
×
446
                                }
447
                                else goto notgoodvertex;
×
448
                                momenta[nmomenta++] = nvert;
×
449
                        }
450
                        ii = FUNHEAD; i = t[1]-FUNHEAD;
×
451
                        NCOPY(tt,t,ii)
×
452
                        if ( flipnames ) tt[-FUNHEAD] = edge;
×
453
                        tt[-FUNHEAD+1] += 2;
×
454
                        *tt++ = -CNUMBER; *tt++ = nvert++;
×
455
                }
456
                else if ( *t == edge && flipnames ) {
×
457
                        i = t[1] - 1; *tt++ = vert; t++;
×
458
                }
459
                else {
460
notgoodvertex:
×
461
                        i = t[1];
×
462
                }
463
                NCOPY(tt,t,i)
×
464
        }
465
        while ( t < tend ) *tt++ = *t++;
×
466
        termcopy[0] = tt - termcopy;
×
467
        if ( flipnames ) EXCH(edge,vert)
×
468
        nvert2 = nvert*nvert;
×
469
/*
470
        Sort the momenta. Keep the sign order.
471
*/
472
        for ( i = 0; i < nmomenta-3; i+=3 ) {
×
473
                jj = i;
474
                while ( jj >= 0 && momenta[jj+4] > momenta[jj+1] ) {
×
475
                        EXCH(momenta[jj+5],momenta[jj+2])
×
476
                        EXCH(momenta[jj+4],momenta[jj+1])
×
477
                        EXCH(momenta[jj+3],momenta[jj])
×
478
                        jj -= 3;
×
479
                }
480
        }
481
/*
482
        Step two: make now the edge functions in the proper notation.
483
*/
484
        t = vet+1;
×
485
        for ( i = 0; i < nmomenta; i += 6 ) {
×
486
                if ( momenta[i] == -VECTOR && momenta[i+3] == -MINVECTOR
×
487
                         && momenta[i+1] == momenta[i+4] ) {
×
488
                }
489
                else if ( momenta[i] == -MINVECTOR && momenta[i+3] == -VECTOR
×
490
                         && momenta[i+1] == momenta[i+4] ) {
×
491
                        flips[nflips++] = momenta[i+1];
×
492
                        DUMMYUSE(flips[nflips-1]);
493
                }
494
                else { /* something wrong with the momenta */
495
                        MLOCK(ErrorMessageLock);
×
496
                        MesPrint("No momentum conservation or wrong momenta in Canonicalize statement");
×
497
                        MUNLOCK(ErrorMessageLock);
×
NEW
498
                        TERMINATE(-1);
×
499
                }
500
                *t++ = EDGE; *t++ = FUNHEAD+10; FILLFUN(t)
×
501
                *t++ = -SNUMBER; *t++ = momenta[i+2];
×
502
                *t++ = -SNUMBER; *t++ = momenta[i+5];
×
503
                *t++ = -VECTOR; *t++ = momenta[i+1];
×
504
                *t++ = -SNUMBER; *t++ = 0; /* provisional power/color, multiple of ep */
×
505
                *t++ = -SNUMBER; *t++ = 0; /* provisional power/color, integer */
×
506
        }
507
        tend = t;
×
508
        *t++ = 1; *t++ = 1; *t++ = 3; vet[0] = t-vet; *t = 0;
×
509
/*
510
        Now the powers of the denominators
511
*/
512
        tstop = termcopy+*termcopy; tstop -= ABS(tstop[-1]); td = termcopy+1;
×
513
        while ( td < tstop ) {
×
514
                if ( *td == edge && td[1] == FUNHEAD+4 ) {
×
515
                        if ( td[FUNHEAD+2] == -SNUMBER && ( td[FUNHEAD] == -VECTOR || td[FUNHEAD] == -INDEX
×
516
                        || td[FUNHEAD] == -MINVECTOR ) ) {}
×
517
                        else {
518
                                MLOCK(ErrorMessageLock);
×
519
                                MesPrint("Illegal argument in edge function in Canonicalize statement");
×
520
                                MUNLOCK(ErrorMessageLock);
×
NEW
521
                                TERMINATE(-1);
×
522
                        }
523
                        tt = vet+1;
×
524
                        while ( tt < tend ) {
×
525
                                if ( tt[FUNHEAD+5] == td[FUNHEAD+1] ) { tt[FUNHEAD+7] = td[FUNHEAD+3]; break; }
×
526
                                tt += tt[1];
×
527
                        }
528
                }
529
                else if ( *td == DOTPRODUCT ) break;
×
530
                td += td[1];
×
531
        }
532
        if ( td < tstop ) {
×
533
                tt = vet+1;
534
                while ( tt < tend ) {
×
535
/*
536
                        tt[FUNHEAD+5] is a vector. We look for dotproducts with twice tt[FUNHEAD+5]
537
*/
538
                        for ( i = 2; i < td[1]; i += 3 ) {
×
539
                                if ( td[i] == tt[FUNHEAD+5] && td[i+1] == tt[FUNHEAD+5] ) {
×
540
                                        tt[FUNHEAD+9] = td[i+2];
×
541
                                        break;
×
542
                                }
543
                        }
544
                        tt += tt[1];
×
545
                }
546
        }
547
        Normalize(BHEAD vet);        
×
548
/*
549
        Now we have a term `vet' in the proper notation and we can start.
550
        To keep track of the shattering we use an array of 2*nvert.
551
        each entry is Number,marker
552
        When the marker is zero, the vertices are in the same partition.
553
        For the environment we need a matrix that is nvert x nvert
554
        At the same time we keep the connectivity matrix, because that will
555
        save much time later.
556
        The partitions are stored in a matrix as well. This allows them to be
557
        treated as a stack. The entries are separated by 0 if they belong to
558
        the same part, and by a 1 when they belong to different parts.
559
*/
560
        partition = AT.WorkPointer; AT.WorkPointer += 2*nvert2;
×
561
        for ( i = 0; i < nvert; i++ ) { partition[2*i] = i; partition[2*i+1] = 0; }
×
562
        partition[2*i-1] = -1;  /* end of the first part which is currently all vertices */
×
563
        nparts = 1;
×
564

565
        connect = AT.WorkPointer; AT.WorkPointer += nvert2;
×
566
        for ( i = 0; i < nvert2; i++ ) connect[i] = 0;
×
567
        tstop = vet+*vet; tstop -= ABS(tstop[-1]); t = vet+1;
×
568
        while ( t < tstop ) {
×
569
                if ( *t == EDGE ) {
×
570
                        connect[t[FUNHEAD+1]*nvert+t[FUNHEAD+3]]++;
×
571
                        connect[t[FUNHEAD+3]*nvert+t[FUNHEAD+1]]++;
×
572
                }
573
                t += t[1];
×
574
        }
575
for ( i = 0; i < nvert; i++ ) {
×
576
MesPrint("connectivity: %d -- %a",i,nvert,connect+i*nvert);
×
577
}
578
/*
579
        Create the environment matrix and sort it.
580
*/
581
        environ = AT.WorkPointer; AT.WorkPointer += nvert2;
×
582
/*
583
        And now the refinement process starts.
584
*/
585
        WantAddPointers(nvert+1);
×
586
        for ( i = 0; i < nvert2; i++ ) environ[i] = 0;
×
587
        /* level = 0; */
588
        pparts = partition;
589
        while ( nparts < nvert ) {
×
590
                nparts = DoShattering(BHEAD connect,environ,pparts,nvert);
×
591
                if ( nparts < nvert ) { /* raise level and make a copy and split a part */
×
592
                        p = pparts + 2*nvert;
×
593
                        /* level++; */
594
                        for ( i = 0; i < 2*nvert; i++ ) p[i] = pparts[i];
×
595
                        for ( ii = 0; ii < 2*nvert; ii += 2 ) {
×
596
                                if ( p[ii+1] == 0 ) { /* found a part with more than one */
×
597
                                        /* num = 2; */ i = ii+2;
×
598
                                        while ( p[i+1] == 0 ) { /* num++; */ i += 2; }
×
599
                                        p[ii+1] = -1; pparts = p;
×
600
                                        break;
×
601
                                }
602
                        }
603

604

605
                }
606
MesPrint("partition: %d -- %a",nparts,2*nvert,pparts);
×
607

608
        }
609
/*
610
        Just for now
611
*/
612
        PutTermInDollar(vet,args[0]);
×
613

614
        
615
        TermFree(vet,"TopologyCanonize2");
×
616
        TermFree(termcopy,"TopologyCanonize1");
×
617
        AT.WorkPointer = oldworkpointer;
×
618
        return(0);
×
619
}
620

621
/*
622
          #] DoTopologyCanonicalize : 
623
          #[ DoShattering :
624
*/
625

626
int DoShattering(PHEAD WORD *connect, WORD *environ, WORD *partitions, WORD nvert)
×
627
{
628
        int nparts, i, j, ii, jj, iii, jjj, newmarker;
×
629
        WORD **p = AT.pWorkSpace + AT.pWorkPointer, *part, *endpart;
×
630
        WORD *poin1, *poin2;
×
631
#ifdef SHATBUG
632
MesPrint("Entering DoShattering. partitions = %a",2*nvert,partitions);
633
#endif
634
restart:
×
635
/*
636
        Determine the number of parts
637
        p will be an array with pointers to the parts.
638
        We made space for this array in the calling routine and because this
639
        routine is not calling any other routines we do not need to raise
640
        the pointer in this stack (AT.pWorkPointer).
641
*/
642
        nparts = 0; newmarker = 0;
×
643
        part = partitions; endpart = part + 2*nvert;
×
644
        p[0] = part;
×
645
        while ( part < endpart ) {
×
646
                if ( part[1] != 0 ) { p[++nparts] = part+2; }
×
647
                part += 2;
×
648
        }
649
        for ( i = 0; i < nparts; i++ ) 
×
650
                AT.WorkPointer[i] = (p[i+1]-p[i])/2;
×
651
#ifdef SHATBUG
652
MesPrint("DoShattering: calculated the pointers");
653
MesPrint("DoShattering: sizes: %a",nparts,AT.WorkPointer);
654
MesPrint("DoShattering: p[0]: %a, p[1]: %a",6,p[0],6,p[1]);
655
#endif
656
        for ( i = 0; i < nparts; i++ ) {
×
657
         if ( AT.WorkPointer[i] > 1 ) {
×
658
          for ( j = 0; j < nparts; j++ ) {
×
659
/*
660
                Shatter part i wrt part j.
661
                if there is action, go to restart.
662
*/                        
663
                for ( ii = 0; ii < AT.WorkPointer[i]; ii++ ) {
×
664
                  for ( jj = 0; jj < AT.WorkPointer[j]; jj++ ) {
×
665
                        environ[ii*AT.WorkPointer[j]+jj] += connect[p[i][2*ii]*nvert+p[j][2*jj]];
×
666
                  }
667
                }
668
#ifdef SHATBUG
669
for ( ii = 0; ii < AT.WorkPointer[i]; ii++ ) {
670
MesPrint("Environ(%d,%d): %a",i,j,AT.WorkPointer[j],environ+ii*AT.WorkPointer[j]);
671
}
672
#endif
673
/*
674
                Sort the rows internally, then sort the rows wrt each other
675
                and finally place new markers. If a new marker, we restart.
676
                Don't forget to clean up the environ array.
677
*/
678
                for ( ii = 0; ii < nvert; ii++ ) {
×
679
                  poin1 = environ+ii*AT.WorkPointer[j];
×
680
                  for ( jj = 0; jj < AT.WorkPointer[j]-1; jj++ ) {
×
681
                        jjj = jj;
682
                        while ( jjj >= 0 && poin1[jjj+1] > poin1[jjj] ) {
×
683
                                EXCH(poin1[jjj+1],poin1[jjj])
×
684
                                jjj--;
×
685
                        }
686
                  }
687
                }
688
#ifdef SHATBUG
689
for ( ii = 0; ii < AT.WorkPointer[i]; ii++ ) {
690
MesPrint("environ(%d,%d): %a",i,j,AT.WorkPointer[j],environ+ii*AT.WorkPointer[j]);
691
}
692
#endif
693
                for ( ii = 0; ii < AT.WorkPointer[i]-1; ii++ ) {
×
694
                        poin2 = environ+ii*AT.WorkPointer[j]; poin1 = poin2+AT.WorkPointer[j];
×
695
                        iii = ii;
×
696
                        while ( iii >= 0 && ( CmpArray(poin1,poin2,AT.WorkPointer[j]) < 0 ) ) {
×
697
                                EXCHN(poin2,poin1,AT.WorkPointer[j])
×
698
                                EXCH(p[i][2*iii+2],p[i][2*iii])
×
699
                                iii--; poin1 = poin2; poin2 = poin1-AT.WorkPointer[j];
×
700
                        }
701
                }
702
#ifdef SHATBUG
703
for ( ii = 0; ii < AT.WorkPointer[i]; ii++ ) {
704
MesPrint("environ(%d,%d): %a",i,j,AT.WorkPointer[j],environ+ii*AT.WorkPointer[j]);
705
}
706
MesPrint("partitions = %a",2*nvert,partitions);
707
#endif
708
                for ( ii = 0; ii < AT.WorkPointer[i]-1; ii++ ) {
×
709
                        poin2 = environ+ii*AT.WorkPointer[j]; poin1 = poin2+AT.WorkPointer[j];
×
710
                        if ( CmpArray(poin1,poin2,AT.WorkPointer[j]) == 0 ) continue;
×
711
                        p[i][2*ii+1] = -1; nparts++; newmarker++;
×
712
                }
713
#ifdef SHATBUG
714
MesPrint("partitions = %a",2*nvert,partitions);
715
#endif
716
/*
717
                Clear environ. This is probably faster than just clearing the whole array.
718
                Maybe in the future a test could be done on nvert to decide how to clear.
719
*/
720
                for ( ii = 0; ii < AT.WorkPointer[i]; ii++ ) {
×
721
                  for ( jj = 0; jj < AT.WorkPointer[j]; jj++ ) {
×
722
                        environ[ii*AT.WorkPointer[j]+jj] = 0;
×
723
                  }
724
                }
725
                if ( newmarker ) { goto restart; }
×
726
          }
727
         }
728
        }
729
        return(nparts);
×
730
}
731

732
/*
733
          #] DoShattering : 
734
*/
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

© 2025 Coveralls, Inc