CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Path: gap4r8 / src / costab.c
Views: 418346
1
/****************************************************************************
2
**
3
*W costab.c GAP source Frank Celler
4
*W & Volkmar Felsch
5
*W & Martin Schönert
6
*W & Alexander Hulpke
7
**
8
**
9
*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
10
*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
11
*Y Copyright (C) 2002 The GAP Group
12
**
13
** This file contains the functions of for coset tables.
14
*/
15
#include "system.h" /* system dependent part */
16
17
18
#include "gasman.h" /* garbage collector */
19
#include "objects.h" /* objects */
20
#include "scanner.h" /* scanner */
21
22
#include "gap.h" /* error handling, initialisation */
23
24
#include "gvars.h" /* global variables */
25
#include "calls.h" /* generic call mechanism */
26
#include "opers.h" /* generic operations */
27
28
#include "integer.h" /* integers */
29
#include "bool.h" /* booleans */
30
31
#include "records.h" /* generic records */
32
#include "precord.h" /* plain records */
33
34
#include "lists.h" /* generic lists */
35
#include "plist.h" /* plain lists */
36
#include "string.h" /* strings */
37
38
#include "costab.h" /* coset table */
39
40
#include "code.h" /* coder */
41
#include "thread.h" /* threads */
42
#include "tls.h" /* thread-local storage */
43
44
45
/****************************************************************************
46
**
47
48
*V declaration of static variables
49
*/
50
static Obj objRel; /* handle of a relator */
51
static Obj objNums; /* handle of parallel numbers list */
52
static Obj objTable; /* handle of the coset table */
53
static Obj objTable2; /* handle of coset factor table */
54
static Obj objNext; /* */
55
static Obj objPrev; /* */
56
static Obj objFactor; /* */
57
static Obj objTree; /* handle of subgroup gens tree */
58
59
static Obj objTree1; /* first tree component */
60
static Obj objTree2; /* second tree component */
61
62
static Obj objExponent; /* handle of subgroup order */
63
static Obj objWordValue; /* handle of word value */
64
65
static Int treeType; /* tree type */
66
static Int treeWordLength; /* maximal tree word length */
67
static Int firstDef; /* */
68
static Int lastDef; /* */
69
static Int firstFree; /* */
70
static Int lastFree; /* */
71
72
static Int minGaps; /* switch for marking mingaps */
73
static Int nrdel; /* */
74
75
static Int dedfst; /* position of first deduction */
76
static Int dedlst; /* position of last deduction */
77
static Int dedgen [40960]; /* deduction list keeping gens */
78
static Int dedcos [40960]; /* deduction list keeping cosets */
79
static Int dedSize = 40960; /* size of deduction list buffers */
80
static Int dedprint; /* print flag for warning */
81
82
static Int wordList [1024]; /* coset rep word buffer */
83
static Int wordSize = 1023; /* maximal no. of coset rep words */
84
85
/* clean out global Obj-type variables to avoid hogging memory*/
86
static void CleanOut( void )
87
{
88
objRel = (Obj) 0;
89
objNums = (Obj) 0;
90
objTable = (Obj) 0;
91
objTable2 = (Obj) 0;
92
objNext = (Obj) 0;
93
objPrev = (Obj) 0;
94
objFactor = (Obj) 0;
95
objTree = (Obj) 0;
96
objTree1 = (Obj) 0;
97
objTree2 = (Obj) 0;
98
objExponent = (Obj) 0;
99
objWordValue = (Obj) 0;
100
}
101
102
/****************************************************************************
103
**
104
105
*F FuncApplyRel( <self>, <app>, <rel> ) apply a relator to a coset in a TC
106
**
107
** 'FuncApplyRel' implements the internal function 'ApplyRel'.
108
**
109
** 'ApplyRel( <app>, <rel> )'
110
**
111
** 'ApplyRel' applies the relator <rel> to the application list <app>.
112
**
113
** ... more about ApplyRel ...
114
*/
115
Obj FuncApplyRel (
116
Obj self,
117
Obj app, /* handle of the application list */
118
Obj rel ) /* handle of the relator */
119
{
120
121
Int lp; /* left pointer into relator */
122
Int lc; /* left coset to apply to */
123
Int rp; /* right pointer into relator */
124
Int rc; /* right coset to apply to */
125
Int tc; /* temporary coset */
126
127
/* check the application list */
128
/*T 1996/12/03 fceller this should be replaced by 'PlistConv' */
129
if ( ! IS_PLIST(app) ) {
130
ErrorQuit( "<app> must be a plain list (not a %s)",
131
(Int)TNAM_OBJ(app), 0L );
132
return 0;
133
}
134
if ( LEN_PLIST(app) != 4 ) {
135
ErrorQuit( "<app> must be a list of length 4 not %d",
136
(Int) LEN_PLIST(app), 0L );
137
return 0;
138
}
139
140
/* get the four entries */
141
lp = INT_INTOBJ( ELM_PLIST( app, 1 ) );
142
lc = INT_INTOBJ( ELM_PLIST( app, 2 ) );
143
rp = INT_INTOBJ( ELM_PLIST( app, 3 ) );
144
rc = INT_INTOBJ( ELM_PLIST( app, 4 ) );
145
146
/* get and check the relator (well, only a little bit) */
147
/*T 1996/12/03 fceller this should be replaced by 'PlistConv' */
148
if ( ! IS_PLIST(rel) ) {
149
ErrorQuit( "<rel> must be a plain list (not a %s)",
150
(Int)TNAM_OBJ(rel), 0L );
151
return 0;
152
}
153
154
/* fix right pointer if requested */
155
if ( rp == -1 )
156
rp = lp + INT_INTOBJ( ELM_PLIST( rel, 1 ) );
157
158
/* scan as long as possible from the right to the left */
159
while ( lp < rp
160
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ELM_PLIST(rel,rp),rc))) )
161
{
162
rc = tc; rp = rp - 2;
163
}
164
165
/* scan as long as possible from the left to the right */
166
while ( lp < rp
167
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ELM_PLIST(rel,lp),lc))) )
168
{
169
lc = tc; lp = lp + 2;
170
}
171
172
/* copy the information back into the application list */
173
SET_ELM_PLIST( app, 1, INTOBJ_INT( lp ) );
174
SET_ELM_PLIST( app, 2, INTOBJ_INT( lc ) );
175
SET_ELM_PLIST( app, 3, INTOBJ_INT( rp ) );
176
SET_ELM_PLIST( app, 4, INTOBJ_INT( rc ) );
177
178
/* return 'true' if a coincidence or deduction was found */
179
if ( lp == rp+1
180
&& INT_INTOBJ(ELM_PLIST(ELM_PLIST(rel,lp),lc)) != rc )
181
{
182
return True;
183
}
184
else
185
return False;
186
}
187
188
189
/****************************************************************************
190
**
191
*F CompressDeductionList() . . . . removes unused items from deduction list
192
**
193
** 'CompressDeductionList' tries to find and delete deduction list entries
194
** which are not used any more.
195
**
196
** 'dedgen', 'dedcos', 'dedfst', 'dedlst', 'dedSize' and 'objTable' are
197
** assumed to be known as static variables.
198
*/
199
static void CompressDeductionList ( void )
200
{
201
Obj * ptTable; /* pointer to the coset table */
202
Int i;
203
Int j;
204
205
/* check if the situation is as assumed */
206
if ( dedlst != dedSize ) {
207
ErrorQuit( "invalid call of CompressDeductionList", 0L, 0L );
208
return;
209
}
210
211
/* run through the lists and compress them */
212
ptTable = &(ELM_PLIST(objTable,1)) - 1;
213
j = 0;
214
for ( i = dedfst; i < dedlst; i++ ) {
215
if ( INT_INTOBJ(ELM_PLIST(ptTable[dedgen[i]],dedcos[i])) > 0
216
&& j < i )
217
{
218
dedgen[j] = dedgen[i];
219
dedcos[j] = dedcos[i];
220
j++;
221
}
222
}
223
224
/* update the pointers */
225
dedfst = 0;
226
dedlst = j;
227
228
/* check if we have at least one free position */
229
if ( dedlst == dedSize ) {
230
if ( dedprint == 0 ) {
231
Pr( "#I WARNING: deductions being discarded\n", 0L, 0L );
232
dedprint = 1;
233
}
234
dedlst--;
235
}
236
}
237
238
239
/****************************************************************************
240
**
241
*F HandleCoinc( <cos1>, <cos2> ) . . . . . . . . handle coincidences in a TC
242
**
243
** 'HandleCoinc' is a subroutine of 'FuncMakeConsequences' and handles the
244
** coincidence cos2 = cos1.
245
*/
246
static void HandleCoinc (
247
Int cos1,
248
Int cos2 )
249
{
250
Obj * ptTable; /* pointer to the coset table */
251
Obj * ptNext;
252
Obj * ptPrev;
253
Int c1;
254
Int c2;
255
Int c3;
256
Int i;
257
Int firstCoinc;
258
Int lastCoinc;
259
Obj * gen;
260
Obj * inv;
261
262
/* is this test necessary? */
263
if ( cos1 == cos2 ) return;
264
265
/* get some pointers */
266
ptTable = &(ELM_PLIST(objTable,1)) - 1;
267
ptNext = &(ELM_PLIST(objNext,1)) - 1;
268
ptPrev = &(ELM_PLIST(objPrev,1)) - 1;
269
270
/* take the smaller one as new representative */
271
if ( cos2 < cos1 ) { c3 = cos1; cos1 = cos2; cos2 = c3; }
272
273
/* if we are removing an important coset update it */
274
if ( cos2 == lastDef )
275
lastDef = INT_INTOBJ( ptPrev[lastDef ] );
276
if ( cos2 == firstDef )
277
firstDef = INT_INTOBJ( ptPrev[firstDef] );
278
279
/* remove <cos2> from the coset list */
280
ptNext[INT_INTOBJ(ptPrev[cos2])] = ptNext[cos2];
281
if ( ptNext[cos2] != INTOBJ_INT( 0 ) )
282
ptPrev[INT_INTOBJ(ptNext[cos2])] = ptPrev[cos2];
283
284
/* put the first coincidence into the list of coincidences */
285
firstCoinc = cos2;
286
lastCoinc = cos2;
287
ptNext[lastCoinc] = INTOBJ_INT( 0 );
288
289
/* <cos1> is the representative of <cos2> and its own representative */
290
ptPrev[cos2] = INTOBJ_INT( cos1 );
291
292
/* while there are coincidences to handle */
293
while ( firstCoinc != 0 ) {
294
295
/* replace <firstCoinc> by its representative in the table */
296
cos1 = INT_INTOBJ( ptPrev[firstCoinc] ); cos2 = firstCoinc;
297
for ( i = 1; i <= LEN_PLIST(objTable); i++ ) {
298
gen = &(ELM_PLIST(ptTable[i],1)) - 1;
299
/* inv = ADDR_OBJ(ptTable[ ((i-1)^1)+1 ] ); */
300
inv = &(ELM_PLIST( ptTable[ i + 2*(i % 2) - 1 ], 1 ) ) - 1;
301
302
/* replace <cos2> by <cos1> in the column of <gen>^-1 */
303
c2 = INT_INTOBJ( gen[cos2] );
304
if ( c2 > 0 ) {
305
c1 = INT_INTOBJ( gen[cos1] );
306
307
/* if the other entry is empty copy it */
308
if ( c1 <= 0 ) {
309
gen[cos1] = INTOBJ_INT( c2 );
310
gen[cos2] = INTOBJ_INT( 0 );
311
inv[c2] = INTOBJ_INT( cos1 );
312
if ( dedlst == dedSize )
313
CompressDeductionList( );
314
dedgen[dedlst] = i;
315
dedcos[dedlst] = cos1;
316
dedlst++;
317
}
318
319
/* otherwise check for a coincidence */
320
else {
321
inv[c2] = INTOBJ_INT( 0 );
322
gen[cos2] = INTOBJ_INT( 0 );
323
if ( gen[cos1] <= INTOBJ_INT( 0 ) ) {
324
gen[cos1] = INTOBJ_INT( cos1 );
325
if ( dedlst == dedSize )
326
CompressDeductionList( );
327
dedgen[dedlst] = i;
328
dedcos[dedlst] = cos1;
329
dedlst++;
330
}
331
332
/* find the representative of <c1> */
333
while ( c1 != 1
334
&& INT_INTOBJ(ptNext[INT_INTOBJ(ptPrev[c1])]) != c1 )
335
{
336
c1 = INT_INTOBJ(ptPrev[c1]);
337
}
338
339
/* find the representative of <c2> */
340
while ( c2 != 1
341
&& INT_INTOBJ(ptNext[INT_INTOBJ(ptPrev[c2])]) != c2 )
342
{
343
c2 = INT_INTOBJ(ptPrev[c2]);
344
}
345
346
/* if the representatives differ we got a coincindence */
347
if ( c1 != c2 ) {
348
349
/* take the smaller one as new representative */
350
if ( c2 < c1 ) { c3 = c1; c1 = c2; c2 = c3; }
351
352
/* if we are removing an important coset update it */
353
if ( c2 == lastDef )
354
lastDef = INT_INTOBJ(ptPrev[lastDef ]);
355
if ( c2 == firstDef )
356
firstDef = INT_INTOBJ(ptPrev[firstDef]);
357
358
/* remove <c2> from the coset list */
359
ptNext[INT_INTOBJ(ptPrev[c2])] = ptNext[c2];
360
if ( ptNext[c2] != INTOBJ_INT( 0 ) )
361
ptPrev[INT_INTOBJ(ptNext[c2])] = ptPrev[c2];
362
363
/* append <c2> to the coincidence list */
364
ptNext[lastCoinc] = INTOBJ_INT( c2 );
365
lastCoinc = c2;
366
ptNext[lastCoinc] = INTOBJ_INT( 0 );
367
368
/* <c1> is the rep of <c2> and its own rep. */
369
ptPrev[c2] = INTOBJ_INT( c1 );
370
}
371
}
372
}
373
374
/* save minimal gap flags */
375
else if ( minGaps != 0 && c2 == -1 ) {
376
if ( gen[cos1] <= INTOBJ_INT( 0 ) ) {
377
gen[cos1] = INTOBJ_INT( -1 );
378
}
379
gen[cos2] = INTOBJ_INT( 0 );
380
}
381
}
382
383
/* move the replaced coset to the free list */
384
if ( firstFree == 0 ) {
385
firstFree = firstCoinc;
386
lastFree = firstCoinc;
387
}
388
else {
389
ptNext[lastFree] = INTOBJ_INT( firstCoinc );
390
lastFree = firstCoinc;
391
}
392
firstCoinc = INT_INTOBJ( ptNext[firstCoinc] );
393
ptNext[lastFree] = INTOBJ_INT( 0 );
394
395
nrdel++;
396
}
397
}
398
399
400
/****************************************************************************
401
**
402
*F FuncMakeConsequences( <self>, <list> ) find consqs of a coset definition
403
*/
404
Obj FuncMakeConsequences (
405
Obj self,
406
Obj list )
407
{
408
Obj hdSubs; /* */
409
Obj objRels; /* */
410
Obj * ptRel; /* pointer to the relator bag */
411
Obj * ptNums; /* pointer to this list */
412
Int lp; /* left pointer into relator */
413
Int lc; /* left coset to apply to */
414
Int rp; /* right pointer into relator */
415
Int rc; /* right coset to apply to */
416
Int tc; /* temporary coset */
417
Int i; /* loop variable */
418
Obj hdTmp; /* temporary variable */
419
420
/*T 1996/12/03 fceller this should be replaced by 'PlistConv' */
421
if ( ! IS_PLIST(list) ) {
422
ErrorQuit( "<list> must be a plain list (not a %s)",
423
(Int)TNAM_OBJ(list), 0L );
424
return 0;
425
}
426
427
objTable = ELM_PLIST( list, 1 );
428
objNext = ELM_PLIST( list, 2 );
429
objPrev = ELM_PLIST( list, 3 );
430
431
firstFree = INT_INTOBJ( ELM_PLIST( list, 6 ) );
432
lastFree = INT_INTOBJ( ELM_PLIST( list, 7 ) );
433
firstDef = INT_INTOBJ( ELM_PLIST( list, 8 ) );
434
lastDef = INT_INTOBJ( ELM_PLIST( list, 9 ) );
435
minGaps = INT_INTOBJ( ELM_PLIST( list, 12 ) );
436
437
nrdel = 0;
438
439
/* initialize the deduction queue */
440
dedprint = 0;
441
dedfst = 0;
442
dedlst = 1;
443
dedgen[ 0 ] = INT_INTOBJ( ELM_PLIST( list, 10 ) );
444
dedcos[ 0 ] = INT_INTOBJ( ELM_PLIST( list, 11 ) );
445
446
/* while the deduction queue is not empty */
447
while ( dedfst < dedlst ) {
448
449
/* skip the deduction, if it got irrelevant by a coincidence */
450
hdTmp = ELM_PLIST( objTable, dedgen[dedfst] );
451
hdTmp = ELM_PLIST( hdTmp, dedcos[dedfst] );
452
if ( INT_INTOBJ(hdTmp) <= 0 ) {
453
dedfst++;
454
continue;
455
}
456
457
/* while there are still subgroup generators apply them */
458
hdSubs = ELM_PLIST( list, 5 );
459
for ( i = LEN_LIST( hdSubs ); 1 <= i; i-- ) {
460
if ( ELM_PLIST( hdSubs, i ) != 0 ) {
461
objNums = ELM_PLIST( ELM_PLIST( hdSubs, i ), 1 );
462
ptNums = &(ELM_PLIST(objNums,1)) - 1;
463
objRel = ELM_PLIST( ELM_PLIST( hdSubs, i ), 2 );
464
ptRel = &(ELM_PLIST(objRel,1)) - 1;
465
466
lp = 2;
467
lc = 1;
468
rp = LEN_LIST( objRel ) - 1;
469
rc = 1;
470
471
/* scan as long as possible from the right to the left */
472
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))) ) {
473
rc = tc; rp = rp - 2;
474
}
475
476
/* scan as long as possible from the left to the right */
477
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))) ) {
478
lc = tc; lp = lp + 2;
479
}
480
481
/* if a coincidence or deduction has been found, handle it */
482
if ( lp == rp + 1 ) {
483
if ( INT_INTOBJ(ELM_PLIST(ptRel[lp],lc)) != rc ) {
484
if ( INT_INTOBJ( ELM_PLIST(ptRel[lp],lc) ) > 0 ) {
485
HandleCoinc( INT_INTOBJ( ELM_PLIST(ptRel[lp],lc) ), rc );
486
}
487
else if ( INT_INTOBJ( ELM_PLIST(ptRel[rp],rc) ) > 0 ) {
488
HandleCoinc( INT_INTOBJ( ELM_PLIST(ptRel[rp],rc) ), lc );
489
}
490
else {
491
SET_ELM_PLIST( ptRel[lp], lc, INTOBJ_INT( rc ) );
492
SET_ELM_PLIST( ptRel[rp], rc, INTOBJ_INT( lc ) );
493
if ( dedlst == dedSize )
494
CompressDeductionList();
495
dedgen[ dedlst ] = INT_INTOBJ( ptNums[lp] );
496
dedcos[ dedlst ] = lc;
497
dedlst++;
498
}
499
}
500
501
/* remove the completed subgroup generator */
502
SET_ELM_PLIST( hdSubs, i, 0 );
503
if ( i == LEN_PLIST(hdSubs) ) {
504
while ( 0 < i && ELM_PLIST(hdSubs,i) == 0 )
505
--i;
506
SET_LEN_PLIST( hdSubs, i );
507
i++;
508
}
509
}
510
511
/* if a minimal gap has been found, set a flag */
512
else if ( minGaps != 0 && lp == rp - 1 ) {
513
SET_ELM_PLIST( ptRel[lp], lc, INTOBJ_INT( -1 ) );
514
SET_ELM_PLIST( ptRel[rp], rc, INTOBJ_INT( -1 ) );
515
}
516
}
517
}
518
519
/* apply all relators that start with this generator */
520
objRels = ELM_PLIST( ELM_PLIST( list, 4 ), dedgen[dedfst] );
521
for ( i = 1; i <= LEN_LIST( objRels ); i++ ) {
522
objNums = ELM_PLIST( ELM_PLIST(objRels,i), 1 );
523
ptNums = &(ELM_PLIST(objNums,1)) - 1;
524
objRel = ELM_PLIST( ELM_PLIST(objRels,i), 2 );
525
ptRel = &(ELM_PLIST(objRel,1)) - 1;
526
527
lp = INT_INTOBJ( ELM_PLIST( ELM_PLIST(objRels,i), 3 ) );
528
lc = dedcos[ dedfst ];
529
rp = lp + INT_INTOBJ( ptRel[1] );
530
rc = lc;
531
532
/* scan as long as possible from the right to the left */
533
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))) ) {
534
rc = tc; rp = rp - 2;
535
}
536
537
/* scan as long as possible from the left to the right */
538
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))) ) {
539
lc = tc; lp = lp + 2;
540
}
541
542
/* if a coincidence or deduction has been found, handle it */
543
if ( lp == rp+1 && INT_INTOBJ(ELM_PLIST(ptRel[lp],lc)) != rc ) {
544
if ( INT_INTOBJ( ELM_PLIST(ptRel[lp],lc) ) > 0 ) {
545
HandleCoinc( INT_INTOBJ( ELM_PLIST(ptRel[lp],lc) ), rc );
546
}
547
else if ( INT_INTOBJ( ELM_PLIST(ptRel[rp],rc) ) > 0 ) {
548
HandleCoinc( INT_INTOBJ( ELM_PLIST(ptRel[rp],rc) ), lc );
549
}
550
else {
551
SET_ELM_PLIST( ptRel[lp], lc, INTOBJ_INT( rc ) );
552
SET_ELM_PLIST( ptRel[rp], rc, INTOBJ_INT( lc ) );
553
if ( dedlst == dedSize )
554
CompressDeductionList();
555
dedgen[ dedlst ] = INT_INTOBJ( ptNums[lp] );
556
dedcos[ dedlst ] = lc;
557
dedlst++;
558
}
559
}
560
561
/* if a minimal gap has been found, set a flag */
562
else if ( minGaps != 0 && lp == rp - 1 ) {
563
SET_ELM_PLIST( ptRel[lp], lc, INTOBJ_INT( -1 ) );
564
SET_ELM_PLIST( ptRel[rp], rc, INTOBJ_INT( -1 ) );
565
}
566
}
567
568
dedfst++;
569
}
570
571
SET_ELM_PLIST( list, 6, INTOBJ_INT( firstFree ) );
572
SET_ELM_PLIST( list, 7, INTOBJ_INT( lastFree ) );
573
SET_ELM_PLIST( list, 8, INTOBJ_INT( firstDef ) );
574
SET_ELM_PLIST( list, 9, INTOBJ_INT( lastDef ) );
575
576
/* clean out */
577
CleanOut();
578
579
return INTOBJ_INT( nrdel );
580
}
581
582
583
/****************************************************************************
584
**
585
*F FuncMakeConsequencesPres( <self>, <list> ) . . . . . . find consequences
586
**
587
** This is a special version of `FuncMakeConsequences' for the subgroup
588
** presentation routines.
589
*/
590
Obj FuncMakeConsequencesPres (
591
Obj self,
592
Obj list )
593
{
594
Obj objDefs1; /* handle of defs list part 1 */
595
Obj objDefs2; /* handle of defs list part 2 */
596
Obj objRels; /* */
597
Obj * ptRel; /* pointer to the relator bag */
598
Obj * ptNums; /* pointer to this list */
599
Int ndefs; /* number of defs done so far */
600
Int undefined; /* maximal of undefined entreis */
601
Int apply; /* num of next def to be applied */
602
Int ndefsMax; /* maximal number of definitons */
603
Int coset; /* coset involved in current def */
604
Int gen; /* gen involved in current def */
605
Int lp; /* left pointer into relator */
606
Int lc; /* left coset to apply to */
607
Int rp; /* right pointer into relator */
608
Int rc; /* right coset to apply to */
609
Int tc; /* temporary coset */
610
Int i; /* loop variable */
611
612
/*T 1996/12/03 fceller this should be replaced by 'PlistConv' */
613
if ( ! IS_PLIST(list) ) {
614
ErrorQuit( "<list> must be a plain list (not a %s)",
615
(Int)TNAM_OBJ(list), 0L );
616
return 0;
617
}
618
619
objTable = ELM_PLIST( list, 1 );
620
objDefs1 = ELM_PLIST( list, 2 );
621
objDefs2 = ELM_PLIST( list, 3 );
622
623
undefined = INT_INTOBJ( ELM_PLIST( list, 4 ) );
624
ndefs = INT_INTOBJ( ELM_PLIST( list, 5 ) );
625
626
/* check the definitions lists */
627
if ( ! ( IS_PLIST(objDefs1) && IS_PLIST(objDefs2) &&
628
LEN_PLIST(objDefs1) == LEN_PLIST(objDefs2) ) ) {
629
ErrorQuit( "inconsistent definitions lists", 0L, 0L );
630
return 0;
631
}
632
ndefsMax = LEN_PLIST(objDefs1);
633
apply = 1;
634
635
/* while the deduction queue is not worked off */
636
while ( apply <= ndefs ) {
637
638
/* apply all relators that start with this generator */
639
coset = INT_INTOBJ( ELM_PLIST( objDefs1, apply ) );
640
gen = INT_INTOBJ( ELM_PLIST( objDefs2, apply ) );
641
objRels = ELM_PLIST( ELM_PLIST( list, 6 ), gen );
642
for ( i = 1; i <= LEN_LIST( objRels ); i++ ) {
643
objNums = ELM_PLIST( ELM_PLIST(objRels,i), 1 );
644
ptNums = &(ELM_PLIST(objNums,1)) - 1;
645
objRel = ELM_PLIST( ELM_PLIST(objRels,i), 2 );
646
ptRel = &(ELM_PLIST(objRel,1)) - 1;
647
648
lp = INT_INTOBJ( ELM_PLIST( ELM_PLIST(objRels,i), 3 ) );
649
lc = coset;
650
rp = lp + INT_INTOBJ( ptRel[1] );
651
rc = lc;
652
653
/* scan as long as possible from the right to the left */
654
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))) ) {
655
rc = tc; rp = rp - 2;
656
}
657
658
/* scan as long as possible from the left to the right */
659
while ( lp<rp && 0 < (tc=INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))) ) {
660
lc = tc; lp = lp + 2;
661
}
662
663
/* if a deduction has been found, handle it */
664
if ( lp == rp+1 && INT_INTOBJ(ELM_PLIST(ptRel[rp],rc)) <= 0 ) {
665
SET_ELM_PLIST( ptRel[lp], lc, INTOBJ_INT( rc ) );
666
undefined--;
667
if ( INT_INTOBJ(ELM_PLIST(ptRel[rp],rc)) <= 0 ) {
668
SET_ELM_PLIST( ptRel[rp], rc, INTOBJ_INT( lc ) );
669
undefined--;
670
}
671
ndefs++;
672
if ( ndefs > ndefsMax ) {
673
ErrorQuit( "inconsistent definitions lists", 0L, 0L );
674
return 0;
675
}
676
SET_ELM_PLIST( objDefs1, ndefs, INTOBJ_INT( lc ) );
677
SET_ELM_PLIST( objDefs2, ndefs, ptNums[lp] );
678
if ( undefined == 0 ) {
679
return INTOBJ_INT( 0 );
680
}
681
}
682
}
683
684
apply++;
685
}
686
687
/* clean out */
688
CleanOut();
689
690
return INTOBJ_INT( undefined );
691
}
692
693
694
/****************************************************************************
695
**
696
*F FuncStandardizeTableC(<self>,<table>,<stan>) . . . . . . standardize CT
697
**
698
** This is the kernel routine for standardizing a coset table. It is called
699
** by the GAP routine 'StandardizeTable'. The user should not call the
700
** kernel routine but only the GAP routine.
701
**
702
** If <stan> = 1 the table is standardized using the (old) semilenlex
703
** standard.
704
** If not <stan> = 1 the table is standardized using the (new) lenlex
705
** standard (this is the default).
706
*/
707
Obj FuncStandardizeTableC (
708
Obj self,
709
Obj list,
710
Obj stan )
711
{
712
Obj * ptTable; /* pointer to table */
713
UInt nrgen; /* number of rows of the table / 2 */
714
Obj * g; /* one generator list from table */
715
Obj * h; /* generator list */
716
Obj * i; /* and inverse */
717
UInt acos; /* actual coset */
718
UInt lcos; /* last seen coset */
719
UInt mcos; /* */
720
UInt c1, c2; /* coset temporaries */
721
Obj tmp; /* temporary for swap */
722
UInt j, k, nloop; /* loop variables */
723
724
/* get the arguments */
725
objTable = list;
726
if ( ! IS_PLIST(objTable) ) {
727
ErrorQuit( "<table> must be a plain list (not a %s)",
728
(Int)TNAM_OBJ(objTable), 0L );
729
return 0;
730
}
731
ptTable = &(ELM_PLIST(objTable,1)) - 1;
732
nrgen = LEN_PLIST(objTable) / 2;
733
for ( j = 1; j <= nrgen*2; j++ ) {
734
if ( ! IS_PLIST(ptTable[j]) ) {
735
ErrorQuit(
736
"<table>[%d] must be a plain list (not a %s)",
737
(Int)j,
738
(Int)TNAM_OBJ(ptTable[j]) );
739
return 0;
740
}
741
}
742
if ( IS_INTOBJ(stan) && INT_INTOBJ(stan) == 1 ) {
743
/* use semilenlex standard */
744
nloop = nrgen;
745
}
746
else {
747
/* use lenlex standard */
748
nloop = nrgen*2;
749
}
750
751
/* run over all cosets */
752
acos = 1;
753
lcos = 1;
754
while ( acos <= lcos ) {
755
756
/* scan through all columns of acos */
757
for ( j = 1; j <= nloop; j++ ) {
758
k = ( nloop == nrgen ) ? 2*j - 1 : j;
759
g = &(ELM_PLIST(ptTable[k],1)) - 1;
760
761
/* if we haven't seen this coset yet */
762
if ( lcos+1 < INT_INTOBJ( g[acos] ) ) {
763
764
/* swap rows lcos and g[acos] */
765
lcos = lcos + 1;
766
mcos = INT_INTOBJ( g[acos] );
767
for ( k = 1; k <= nrgen; k++ ) {
768
h = &(ELM_PLIST(ptTable[2*k-1],1)) - 1;
769
i = &(ELM_PLIST(ptTable[2*k],1)) - 1;
770
c1 = INT_INTOBJ( h[lcos] );
771
c2 = INT_INTOBJ( h[mcos] );
772
if ( c1 != 0 ) i[c1] = INTOBJ_INT( mcos );
773
if ( c2 != 0 ) i[c2] = INTOBJ_INT( lcos );
774
tmp = h[lcos];
775
h[lcos] = h[mcos];
776
h[mcos] = tmp;
777
if ( i != h ) {
778
c1 = INT_INTOBJ( i[lcos] );
779
c2 = INT_INTOBJ( i[mcos] );
780
if ( c1 != 0 ) h[c1] = INTOBJ_INT( mcos );
781
if ( c2 != 0 ) h[c2] = INTOBJ_INT( lcos );
782
tmp = i[lcos];
783
i[lcos] = i[mcos];
784
i[mcos] = tmp;
785
}
786
}
787
788
}
789
790
/* if this is already the next only bump lcos */
791
else if ( lcos < INT_INTOBJ( g[acos] ) ) {
792
lcos = lcos + 1;
793
}
794
795
}
796
797
acos = acos + 1;
798
}
799
800
/* shrink the table */
801
for ( j = 1; j <= nrgen; j++ ) {
802
SET_LEN_PLIST( ptTable[2*j-1], lcos );
803
SET_LEN_PLIST( ptTable[2*j ], lcos );
804
}
805
806
/* clean out */
807
CleanOut();
808
809
/* return void */
810
return 0;
811
}
812
813
814
/****************************************************************************
815
**
816
*F InitializeCosetFactorWord() . . . . . . . initialize a coset factor word
817
**
818
** 'InitializeCosetFactorWord' initializes a word in which a new coset
819
** factor is to be built up.
820
**
821
** 'wordList', 'treeType', 'objTree2', and 'treeWordLength' are assumed to
822
** be known as static variables.
823
*/
824
static void InitializeCosetFactorWord ( void )
825
{
826
Obj * ptWord; /* pointer to the word */
827
Int i; /* integer variable */
828
829
/* handle the one generator MTC case */
830
if ( treeType == 1 ) {
831
objWordValue = INTOBJ_INT(0);
832
}
833
834
/* handle the abelianized case */
835
else if ( treeType == 0 ) {
836
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
837
for ( i = 1; i <= treeWordLength; i++ ) {
838
ptWord[i] = INTOBJ_INT(0);
839
}
840
}
841
842
/* handle the general case */
843
else {
844
wordList[0] = 0;
845
}
846
}
847
848
849
/****************************************************************************
850
**
851
*F TreeEntryC() . . . . . . . . . . . . returns a tree entry for a rep word
852
**
853
** 'TreeEntryC' determines a tree entry which represents the word given in
854
** 'wordList', if it finds any, or it defines a new proper tree entry, and
855
** then returns it.
856
**
857
** Warning: It is assumed, but not checked, that the given word is freely
858
** reduced and that it does not contain zeros, and that the tree type is
859
** either 0 or 2.
860
**
861
** 'wordList' is assumed to be known as static variable.
862
**
863
*/
864
static Int TreeEntryC ( void )
865
{
866
Obj * ptTree1; /* ptr to first tree component */
867
Obj * ptTree2; /* ptr to second tree component */
868
Obj * ptWord; /* ptr to given word */
869
Obj * ptFac; /* ptr to old word */
870
Obj * ptNew; /* ptr to new word */
871
Obj objNew; /* handle of new word */
872
Int treesize; /* tree size */
873
Int numgens; /* tree length */
874
Int leng; /* word length */
875
Int sign; /* sign flag */
876
Int i, k; /* integer variables */
877
Int gen; /* generator value */
878
Int u, u1, u2; /* generator values */
879
Int v, v1, v2; /* generator values */
880
Int t1, t2; /* generator values */
881
Int uabs, vabs; /* generator values */
882
883
/* Get the tree components */
884
ptTree1 = &(ELM_PLIST(objTree1,1)) - 1;
885
ptTree2 = &(ELM_PLIST(objTree2,1)) - 1;
886
treesize = LEN_PLIST(objTree1);
887
numgens = INT_INTOBJ( ELM_PLIST( objTree, 3 ) );
888
889
/* handle the abelianized case */
890
if ( treeType == 0 )
891
{
892
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
893
for ( leng = treeWordLength; leng >= 1; leng-- ) {
894
if ( ptWord[leng] != INTOBJ_INT(0) ) {
895
break;
896
}
897
}
898
if ( leng == 0 ) {
899
return 0;
900
}
901
for ( k = 1; k <= leng; k++ ) {
902
if ( ptWord[k] != INTOBJ_INT(0) ) {
903
break;
904
}
905
}
906
sign = 1;
907
if ( INT_INTOBJ( ptWord[k] ) < 0 ) {
908
909
/* invert the word */
910
sign = - 1;
911
for ( i = k; i <= leng; i++ ) {
912
ptWord[i] = INTOBJ_INT( - INT_INTOBJ( ptWord[i] ) );
913
}
914
}
915
for ( k = 1; k <= numgens; k++ ) {
916
ptFac = &(ELM_PLIST(ptTree1[k],1)) - 1;
917
if ( LEN_PLIST(ptTree1[k]) == leng ) {
918
for ( i = 1; i <= leng; i++ ) {
919
if ( ptFac[i] != ptWord[i] ) {
920
break;
921
}
922
}
923
if ( i > leng ) {
924
return sign * k;
925
}
926
}
927
}
928
929
/* extend the tree */
930
numgens++;
931
if ( treesize < numgens ) {
932
treesize = 2 * treesize;
933
GROW_PLIST( objTree1, treesize );
934
CHANGED_BAG(objTree);
935
}
936
objNew = NEW_PLIST( T_PLIST, leng );
937
SET_LEN_PLIST( objNew, leng );
938
939
SET_ELM_PLIST( objTree, 3, INTOBJ_INT(numgens) );
940
941
SET_LEN_PLIST( objTree1, treesize );
942
SET_ELM_PLIST( objTree1, numgens, objNew );
943
CHANGED_BAG(objTree1);
944
945
/* copy the word to the new bag */
946
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
947
ptNew = &(ELM_PLIST(objNew,1)) - 1;
948
while ( leng > 0 ) {
949
ptNew[leng] = ptWord[leng];
950
leng--;
951
}
952
953
return sign * numgens;
954
}
955
956
/* handle the general case */
957
958
/* Get the length of the word */
959
leng = wordList[0];
960
961
gen = ( leng == 0 ) ? 0 : wordList[1];
962
u2 = 0; /* just to shut up gcc */
963
for ( i = 2; i <= leng; i++ ) {
964
u = gen;
965
v = wordList[i];
966
while ( i ) {
967
968
/* First handle the trivial cases */
969
if ( u == 0 || v == 0 || ( u + v ) == 0 ) {
970
gen = u + v;
971
break;
972
}
973
974
/* Cancel out factors, if possible */
975
u1 = INT_INTOBJ( ptTree1[ (u > 0) ? u : -u ] );
976
if ( u1 != 0 ) {
977
if ( u > 0 ) {
978
u2 = INT_INTOBJ( ptTree2[u] );
979
}
980
else {
981
u2 = - u1;
982
u1 = - INT_INTOBJ( ptTree2[-u] );
983
}
984
if ( u2 == -v ) {
985
gen = u1;
986
break;
987
}
988
}
989
v1 = INT_INTOBJ( ptTree1[ (v > 0) ? v : -v ] );
990
if ( v1 != 0 ) {
991
if ( v > 0 ) {
992
v2 = INT_INTOBJ( ptTree2[v] );
993
}
994
else {
995
v2 = - v1;
996
v1 = - INT_INTOBJ( ptTree2[-v] );
997
}
998
if ( v1 == -u ) {
999
gen = v2;
1000
break;
1001
}
1002
if ( u1 != 0 && v1 == - u2 ) {
1003
u = u1;
1004
v = v2;
1005
continue;
1006
}
1007
}
1008
1009
/* Check if there is already a tree entry [u,v] or [-v,-u] */
1010
if ( u < -v ) {
1011
t1 = u;
1012
t2 = v;
1013
}
1014
else {
1015
t1 = -v;
1016
t2 = -u;
1017
}
1018
uabs = ( u > 0 ) ? u : -u;
1019
vabs = ( v > 0 ) ? v : -v;
1020
k = ( uabs > vabs ) ? uabs : vabs;
1021
for ( k++; k <= numgens; k++ ) {
1022
if ( INT_INTOBJ(ptTree1[k]) == t1 &&
1023
INT_INTOBJ(ptTree2[k]) == t2 )
1024
{
1025
break;
1026
}
1027
}
1028
1029
/* Extend the tree, if necessary */
1030
if ( k > numgens ) {
1031
numgens++;
1032
if ( treesize < numgens ) {
1033
treesize = 2 * treesize;
1034
GROW_PLIST( objTree1, treesize );
1035
GROW_PLIST( objTree2, treesize );
1036
ptTree1 = &(ELM_PLIST(objTree1,1)) - 1;
1037
ptTree2 = &(ELM_PLIST(objTree2,1)) - 1;
1038
SET_LEN_PLIST( objTree1, treesize );
1039
SET_LEN_PLIST( objTree2, treesize );
1040
CHANGED_BAG(objTree);
1041
}
1042
ptTree1[numgens] = INTOBJ_INT( t1 );
1043
ptTree2[numgens] = INTOBJ_INT( t2 );
1044
SET_ELM_PLIST( objTree, 3, INTOBJ_INT(numgens) );
1045
}
1046
gen = ( u > - v ) ? -k : k;
1047
break;
1048
}
1049
}
1050
1051
return gen;
1052
}
1053
1054
1055
/****************************************************************************
1056
**
1057
*F AddCosetFactor2( <factor> ) . add a factor to a coset representative word
1058
**
1059
** 'AddCosetFactor2' adds a factor to a coset representative word and
1060
** extends the tree appropriately, if necessary.
1061
**
1062
** 'treeType', 'wordList', and 'wordSize' are assumed to be known as static
1063
** variables, and 'treeType' is assumed to be either 0 or 2,
1064
**
1065
** Warning: 'factor' is not checked for being zero.
1066
*/
1067
static void AddCosetFactor2 (
1068
Int factor )
1069
{
1070
Obj * ptFac; /* pointer to the factor */
1071
Obj * ptWord; /* pointer to the word */
1072
Int leng; /* length of the factor */
1073
Obj sum; /* intermediate result */
1074
Int i; /* integer variable */
1075
Obj tmp;
1076
1077
/* handle the abelianized case */
1078
if ( treeType == 0 ) {
1079
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
1080
if ( factor > 0 ) {
1081
tmp = ELM_PLIST( objTree1, factor );
1082
ptFac = &(ELM_PLIST(tmp,1)) - 1;
1083
leng = LEN_PLIST(tmp);
1084
for ( i = 1; i <= leng; i++ ) {
1085
if ( ! SUM_INTOBJS( sum, ptWord[i], ptFac[i] ) ) {
1086
ErrorQuit(
1087
"exponent too large, Modified Todd-Coxeter aborted",
1088
0L, 0L );
1089
return;
1090
}
1091
ptWord[i] = sum;
1092
}
1093
}
1094
else
1095
{
1096
tmp = ELM_PLIST( objTree1, -factor );
1097
ptFac = &(ELM_PLIST(tmp,1)) - 1;
1098
leng = LEN_PLIST(tmp);
1099
for ( i = 1; i <= leng; i++ ) {
1100
if ( ! DIFF_INTOBJS( sum, ptWord[i], ptFac[i] ) ) {
1101
ErrorQuit(
1102
"exponent too large, Modified Todd-Coxeter aborted",
1103
0L, 0L );
1104
return;
1105
}
1106
ptWord[i] = sum;
1107
}
1108
}
1109
}
1110
1111
/* handle the general case */
1112
else if ( wordList[0] == 0 ) {
1113
wordList[++wordList[0]] = factor;
1114
}
1115
else if ( wordList[wordList[0]] == -factor ) {
1116
--wordList[0];
1117
}
1118
else if ( wordList[0] < wordSize ) {
1119
wordList[++wordList[0]] = factor;
1120
}
1121
else {
1122
wordList[0] = ( wordList[1] = TreeEntryC( ) == 0 ) ? 0 : 1;
1123
AddCosetFactor2(factor);
1124
}
1125
}
1126
1127
1128
/****************************************************************************
1129
**
1130
*F FuncApplyRel2( <self>, <app>, <rel>, <nums> ) . . . . . . apply a relator
1131
**
1132
** 'FunApplyRel2' implements the internal function 'ApplyRel2'.
1133
**
1134
** 'ApplyRel2( <app>, <rel>, <nums> )'
1135
**
1136
** 'ApplyRel2' applies the relator <rel> to a coset representative and
1137
** returns the corresponding factors in "word"
1138
**
1139
** ...more about ApplyRel2...
1140
*/
1141
Obj FuncApplyRel2 (
1142
Obj self,
1143
Obj app,
1144
Obj rel,
1145
Obj nums )
1146
{
1147
Obj * ptApp; /* pointer to that list */
1148
Obj word; /* handle of resulting word */
1149
Obj * ptWord; /* pointer to this word */
1150
Obj * ptTree; /* pointer to the tree */
1151
Obj * ptTree2; /* ptr to second tree component */
1152
Obj * ptRel; /* pointer to the relator bag */
1153
Obj * ptNums; /* pointer to this list */
1154
Obj * ptTabl2; /* pointer to coset factor table */
1155
Obj objRep; /* handle of temporary factor */
1156
Int lp; /* left pointer into relator */
1157
Int lc; /* left coset to apply to */
1158
Int rp; /* right pointer into relator */
1159
Int rc; /* right coset to apply to */
1160
Int rep; /* temporary factor */
1161
Int tc; /* temporary coset */
1162
Int bound; /* maximal number of steps */
1163
Int last; /* proper word length */
1164
Int size; /* size of the word bag */
1165
Int i; /* loop variables */
1166
Int tmp;
1167
1168
/* get and check the application list */
1169
if ( ! IS_PLIST(app) ) {
1170
ErrorQuit( "<app> must be a plain list (not a %s)",
1171
(Int)TNAM_OBJ(app), 0L );
1172
return 0;
1173
}
1174
if ( LEN_PLIST(app) != 9 ) {
1175
ErrorQuit( "<app> must be a list of length 9 not %d",
1176
(Int) LEN_PLIST(app), 0L );
1177
return 0;
1178
}
1179
ptApp = &(ELM_PLIST(app,1)) - 1;
1180
1181
/* get the components of the proper application list */
1182
lp = INT_INTOBJ( ptApp[1] );
1183
lc = INT_INTOBJ( ptApp[2] );
1184
rp = INT_INTOBJ( ptApp[3] );
1185
rc = INT_INTOBJ( ptApp[4] );
1186
1187
/* get and check the relator (well, only a little bit) */
1188
objRel = rel;
1189
if ( ! IS_PLIST(rel) ) {
1190
ErrorQuit( "<rel> must be a plain list (not a %s)",
1191
(Int)TNAM_OBJ(rel), 0L );
1192
return 0;
1193
}
1194
1195
/* fix right pointer if requested */
1196
if ( rp == -1 )
1197
rp = lp + INT_INTOBJ( ELM_PLIST(objRel,1) );
1198
1199
/* get and check the numbers list parallel to the relator */
1200
objNums = nums;
1201
if ( ! IS_PLIST(objNums) ) {
1202
ErrorQuit( "<nums> must be a plain list (not a %s)",
1203
(Int)TNAM_OBJ(objNums), 0L );
1204
return 0;
1205
}
1206
1207
/* get and check the corresponding factors list */
1208
objTable2 = ptApp[6];
1209
if ( ! IS_PLIST(objTable2) ) {
1210
ErrorQuit( "<nums> must be a plain list (not a %s)",
1211
(Int)TNAM_OBJ(objTable2), 0L );
1212
return 0;
1213
}
1214
1215
/* get the tree type */
1216
treeType = INT_INTOBJ( ptApp[5] );
1217
1218
/* handle the one generator MTC case */
1219
if ( treeType == 1 ) {
1220
1221
/* initialize the resulting exponent by zero */
1222
objExponent = INTOBJ_INT( 0 );
1223
1224
/* scan as long as possible from the left to the right */
1225
while ( lp < rp + 2 &&
1226
0 < (tc = INT_INTOBJ(ELM_PLIST(ELM_PLIST(objRel,lp),lc))) )
1227
{
1228
tmp = INT_INTOBJ( ELM_PLIST(objNums,lp) );
1229
objRep = ELM_PLIST( objTable2, tmp );
1230
objRep = ELM_PLIST( objRep, lc );
1231
objExponent = DiffInt( objExponent, objRep );
1232
lc = tc;
1233
lp = lp + 2;
1234
}
1235
1236
/* scan as long as possible from the right to the left */
1237
while ( lp < rp + 2 &&
1238
0 < (tc = INT_INTOBJ(ELM_PLIST(ELM_PLIST(objRel,rp),rc))) )
1239
{
1240
tmp = INT_INTOBJ( ELM_PLIST(objNums,rp) );
1241
objRep = ELM_PLIST( objTable2, tmp );
1242
objRep = ELM_PLIST( objRep, rc );
1243
objExponent = SumInt( objExponent, objRep );
1244
rc = tc;
1245
rp = rp - 2;
1246
}
1247
1248
/* The functions DiffInt or SumInt may have caused a garbage */
1249
/* collections. So restore the pointer. */
1250
1251
/* save the resulting exponent */
1252
SET_ELM_PLIST( app, 9, objExponent );
1253
}
1254
1255
else {
1256
1257
/* get and check the corresponding word */
1258
word = ptApp[7];
1259
if ( ! IS_PLIST(word) ) {
1260
ErrorQuit( "<word> must be a plain list (not a %s)",
1261
(Int)TNAM_OBJ(word), 0L );
1262
return 0;
1263
}
1264
1265
/* handle the abelianized case */
1266
if ( treeType == 0 ) {
1267
objTree = ptApp[8];
1268
objTree1 = ELM_PLIST( objTree, 1 );
1269
objTree2 = ELM_PLIST( objTree, 2 );
1270
ptTree = &(ELM_PLIST(objTree,1)) - 1;
1271
treeWordLength = INT_INTOBJ( ptTree[4] );
1272
if ( LEN_PLIST(objTree2) != treeWordLength ) {
1273
ErrorQuit( "ApplyRel2: illegal word length", 0L, 0L );
1274
return 0;
1275
}
1276
1277
/* initialize the coset representative word */
1278
InitializeCosetFactorWord();
1279
1280
/* scan as long as possible from the left to the right */
1281
while ( lp < rp + 2 &&
1282
0 < (tc=INT_INTOBJ(ELM_PLIST(ELM_PLIST(objRel,lp),lc))) )
1283
{
1284
tmp = INT_INTOBJ( ELM_PLIST(objNums,lp) );
1285
objRep = ELM_PLIST(objTable2,tmp);
1286
objRep = ELM_PLIST(objRep,lc);
1287
rep = INT_INTOBJ(objRep);
1288
if ( rep != 0 ) {
1289
AddCosetFactor2(-rep);
1290
}
1291
lc = tc;
1292
lp = lp + 2;
1293
}
1294
1295
/* scan as long as possible from the right to the left */
1296
while ( lp < rp + 2 &&
1297
0 < (tc=INT_INTOBJ(ELM_PLIST(ELM_PLIST(objRel,rp),rc))) )
1298
{
1299
tmp = INT_INTOBJ( ELM_PLIST(objNums,rp) );
1300
objRep = ELM_PLIST(objTable2,tmp);
1301
objRep = ELM_PLIST(objRep,rc);
1302
rep = INT_INTOBJ(objRep);
1303
if ( rep != 0 ) {
1304
AddCosetFactor2(rep);
1305
}
1306
rc = tc;
1307
rp = rp - 2;
1308
}
1309
1310
/* initialize some local variables */
1311
ptWord = &(ELM_PLIST(word,1)) - 1;
1312
ptTree2 = &(ELM_PLIST(objTree2,1)) - 1;
1313
1314
/* copy the result to its destination, if necessary */
1315
if ( ptWord != ptTree2 ) {
1316
if ( LEN_PLIST(word) != treeWordLength ) {
1317
ErrorQuit( "illegal word length", 0L, 0L );
1318
return 0;
1319
}
1320
for ( i = 1; i <= treeWordLength; i++ ) {
1321
ptWord[i] = ptTree2[i];
1322
}
1323
SET_LEN_PLIST( word, LEN_PLIST(objTree2) );
1324
}
1325
}
1326
1327
/* handle the general case */
1328
else {
1329
1330
/* extend the word size, if necessary */
1331
bound = ( rp - lp + 3 ) / 2;
1332
size = SIZE_OBJ(word)/sizeof(Obj) - 1;
1333
if ( size < bound ) {
1334
size = ( bound > 2 * size ) ? bound : 2 * size;
1335
GROW_PLIST( word, size );
1336
CHANGED_BAG(app);
1337
}
1338
1339
/* initialize some local variables */
1340
ptRel = &(ELM_PLIST(objRel,1)) - 1;
1341
ptNums = &(ELM_PLIST(objNums,1)) - 1;
1342
ptTabl2 = &(ELM_PLIST(objTable2,1)) - 1;
1343
ptWord = &(ELM_PLIST(word,1)) - 1;
1344
last = 0;
1345
1346
/* scan as long as possible from the left to the right */
1347
while ( lp < rp + 2
1348
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))) )
1349
{
1350
objRep = ELM_PLIST( ptTabl2[INT_INTOBJ(ptNums[lp])], lc );
1351
rep = INT_INTOBJ(objRep);
1352
if ( rep != 0 ) {
1353
if ( last > 0 && INT_INTOBJ(ptWord[last]) == rep ) {
1354
last--;
1355
}
1356
else {
1357
ptWord[++last] = INTOBJ_INT(-rep);
1358
}
1359
}
1360
lc = tc;
1361
lp = lp + 2;
1362
}
1363
1364
/* revert the ordering of the word constructed so far */
1365
if ( last > 0 ) {
1366
last++;
1367
for ( i = last / 2; i > 0; i-- ) {
1368
objRep = ptWord[i];
1369
ptWord[i] = ptWord[last-i];
1370
ptWord[last-i] = objRep;
1371
}
1372
last--;
1373
}
1374
1375
/* scan as long as possible from the right to the left */
1376
while ( lp < rp + 2
1377
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))) )
1378
{
1379
objRep = ELM_PLIST( ptTabl2[INT_INTOBJ(ptNums[rp])], rc );
1380
rep = INT_INTOBJ(objRep);
1381
if ( rep != 0 ) {
1382
if ( last > 0 && INT_INTOBJ(ptWord[last]) == -rep ) {
1383
last--;
1384
}
1385
else {
1386
ptWord[++last] = INTOBJ_INT(rep);
1387
}
1388
}
1389
rc = tc;
1390
rp = rp - 2;
1391
}
1392
1393
/* save the word length */
1394
SET_LEN_PLIST( word, last );
1395
}
1396
}
1397
1398
/* copy the information back into the application list */
1399
SET_ELM_PLIST( app, 1, INTOBJ_INT( lp ) );
1400
SET_ELM_PLIST( app, 2, INTOBJ_INT( lc ) );
1401
SET_ELM_PLIST( app, 3, INTOBJ_INT( rp ) );
1402
SET_ELM_PLIST( app, 4, INTOBJ_INT( rc ) );
1403
1404
/* return nothing */
1405
return 0;
1406
}
1407
1408
1409
/****************************************************************************
1410
**
1411
*F FuncCopyRel( <self>, <rel> ) . . . . . . . . . . . . copy of a relator
1412
**
1413
** 'FuncCopyRel' returns a copy of the given RRS relator such that the bag
1414
** of the copy does not exceed the minimal required size.
1415
*/
1416
Obj FuncCopyRel (
1417
Obj self,
1418
Obj rel ) /* the given relator */
1419
{
1420
Obj * ptRel; /* pointer to the given relator */
1421
Obj copy; /* the copy */
1422
Obj * ptCopy; /* pointer to the copy */
1423
Int leng; /* length of the given word */
1424
1425
/* Get and check argument */
1426
if ( ! IS_PLIST(rel) ) {
1427
ErrorQuit( "<rel> must be a plain list (not a %s)",
1428
(Int)TNAM_OBJ(rel), 0L );
1429
return 0;
1430
}
1431
leng = LEN_PLIST(rel);
1432
1433
/* Allocate a bag for the copy */
1434
copy = NEW_PLIST( T_PLIST, leng );
1435
SET_LEN_PLIST( copy, leng );
1436
ptRel = &(ELM_PLIST(rel,1));
1437
ptCopy = &(ELM_PLIST(copy,1));
1438
1439
/* Copy the relator to the new bag */
1440
while ( leng > 0 ) {
1441
*ptCopy++ = *ptRel++;
1442
leng--;
1443
}
1444
1445
/* Return the copy */
1446
return copy;
1447
}
1448
1449
1450
/****************************************************************************
1451
**
1452
*F FuncMakeCanonical( <self>, <rel> ) . . . . . . . make a relator canonical
1453
**
1454
** 'FuncMakeCanonical' is a subroutine of the Reduced Reidemeister-Schreier
1455
** routines. It replaces the given relator by its canonical representative.
1456
** It does not return anything.
1457
*/
1458
Obj FuncMakeCanonical (
1459
Obj self,
1460
Obj rel ) /* the given relator */
1461
{
1462
Obj * ptRel; /* pointer to the relator */
1463
Obj obj1, obj2; /* handles 0f relator entries */
1464
Int leng, leng1; /* length of the relator */
1465
Int max, min, next; /* relator entries */
1466
Int i, j, k, l; /* integer variables */
1467
Int ii, jj, kk; /* integer variables */
1468
1469
/* Get and check the argument */
1470
if ( ! IS_PLIST(rel) ) {
1471
ErrorQuit( "<rel> must be a plain list (not a %s)",
1472
(Int)TNAM_OBJ(rel), 0L );
1473
return 0;
1474
}
1475
ptRel = &(ELM_PLIST(rel,1));
1476
leng = LEN_PLIST(rel);
1477
leng1 = leng - 1;
1478
1479
/* cyclically reduce the relator, if necessary */
1480
i = 0;
1481
while ( i<leng1 && INT_INTOBJ(ptRel[i]) == -INT_INTOBJ(ptRel[leng1]) ) {
1482
i++;
1483
leng1--;
1484
}
1485
if ( i > 0 ) {
1486
for ( j = i; j <= leng1; j++ ) {
1487
ptRel[j-i] = ptRel[j];
1488
}
1489
leng1 = leng1 - i;
1490
leng = leng1 + 1;
1491
SET_LEN_PLIST( rel, leng );
1492
}
1493
1494
/* Loop over the relator and find the maximal postitve and negative */
1495
/* entries */
1496
max = min = INT_INTOBJ(ptRel[0]);
1497
i = 0; j = 0;
1498
for ( k = 1; k < leng; k++ ) {
1499
next = INT_INTOBJ( ptRel[k] );
1500
if ( next > max ) {
1501
max = next;
1502
i = k;
1503
}
1504
else if ( next <= min ) {
1505
min = next;
1506
j = k;
1507
}
1508
}
1509
1510
/* Find the lexicographically last cyclic permutation of the relator */
1511
if ( max < -min ) {
1512
i = leng;
1513
}
1514
else {
1515
for ( k = i + 1; k < leng; k++ ) {
1516
for ( ii = i, kk = k, l = 0;
1517
l < leng;
1518
ii = (ii + 1) % leng, kk = (kk + 1) % leng, l++ )
1519
{
1520
if ( INT_INTOBJ(ptRel[kk]) < INT_INTOBJ(ptRel[ii]) ) {
1521
break;
1522
}
1523
else if ( INT_INTOBJ(ptRel[kk]) > INT_INTOBJ(ptRel[ii]) ) {
1524
i = k;
1525
break;
1526
}
1527
}
1528
if ( l == leng ) {
1529
break;
1530
}
1531
}
1532
}
1533
1534
/* Find the lexicographically last cyclic permutation of its inverse */
1535
if ( -max < min ) {
1536
j = leng;
1537
}
1538
else {
1539
for ( k = j - 1; k >= 0; k-- ) {
1540
for ( jj = j, kk = k, l = 0;
1541
l < leng;
1542
jj = (jj + leng1) % leng, kk = (kk + leng1) % leng, l++ )
1543
{
1544
if ( INT_INTOBJ(ptRel[kk]) > INT_INTOBJ(ptRel[jj]) ) {
1545
break;
1546
}
1547
else if ( INT_INTOBJ(ptRel[kk]) < INT_INTOBJ(ptRel[jj]) ) {
1548
j = k;
1549
break;
1550
}
1551
}
1552
if ( l == leng ) {
1553
break;
1554
}
1555
}
1556
}
1557
1558
/* Compare the two words and find the lexicographically last one */
1559
if ( -min == max ) {
1560
for ( ii = i, jj = j, l = 0;
1561
l < leng;
1562
ii = (ii + 1) % leng, jj = (jj + leng1) % leng, l++ )
1563
{
1564
if ( - INT_INTOBJ(ptRel[jj]) < INT_INTOBJ(ptRel[ii]) ) {
1565
break;
1566
}
1567
else if ( - INT_INTOBJ(ptRel[jj]) > INT_INTOBJ(ptRel[ii]) ) {
1568
i = leng;
1569
break;
1570
}
1571
}
1572
}
1573
1574
/* Invert the given relator, if necessary */
1575
if ( i == leng ) {
1576
for ( k = 0; k < leng / 2; k++ ) {
1577
next = INT_INTOBJ( ptRel[k] );
1578
ptRel[k] = INTOBJ_INT( - INT_INTOBJ( ptRel[leng1-k] ) );
1579
ptRel[leng1-k] = INTOBJ_INT( - next );
1580
}
1581
if ( leng % 2 ) {
1582
ptRel[leng1/2] = INTOBJ_INT( - INT_INTOBJ( ptRel[leng1/2] ) );
1583
}
1584
i = leng1 - j;
1585
}
1586
1587
/* Now replace the given relator by the resulting word */
1588
if ( i > 0 ) {
1589
k = INT_INTOBJ( GcdInt( INTOBJ_INT(i), INTOBJ_INT(leng) ) );
1590
l = leng / k;
1591
leng1 = leng - i;
1592
for ( j = 0; j < k; j++ ) {
1593
jj = (j + i) % leng;
1594
obj1 = ptRel[jj];
1595
for ( ii = 0; ii < l; ii++ ) {
1596
jj = (jj + leng1) % leng;
1597
obj2 = ptRel[jj]; ptRel[jj] = obj1; obj1 = obj2;
1598
}
1599
}
1600
}
1601
1602
/* return nothing */
1603
return 0;
1604
}
1605
1606
1607
/****************************************************************************
1608
**
1609
*F FuncTreeEntry( <self>, <tree>, <word> ) . tree entry for the given word
1610
**
1611
** 'FuncTreeEntry' determines a tree entry which represents the given word
1612
** in the current generators, if it finds any, or it defines a new proper
1613
** tree entry, and then returns it.
1614
*/
1615
Obj FuncTreeEntry(
1616
Obj self,
1617
Obj tree,
1618
Obj word )
1619
{
1620
Obj * ptTree1; /* pointer to that component */
1621
Obj * ptTree2; /* pointer to that component */
1622
Obj * ptWord; /* pointer to that word */
1623
Obj new; /* handle of new word */
1624
Obj * ptNew; /* pointer to new word */
1625
Obj * ptFac; /* pointer to old word */
1626
Int treesize; /* tree size */
1627
Int numgens; /* tree length */
1628
Int leng; /* word length */
1629
Int sign; /* integer variable */
1630
Int i, j, k; /* integer variables */
1631
Int gen; /* generator value */
1632
Int u, u1, u2; /* generator values */
1633
Int v, v1, v2; /* generator values */
1634
Int t1, t2; /* generator values */
1635
Int uabs, vabs; /* generator values */
1636
1637
/* Get and check the first argument (tree) */
1638
objTree = tree;
1639
if ( ! IS_PLIST(tree) || LEN_PLIST(tree) < 5 ) {
1640
ErrorQuit( "invalid <tree>", 0L, 0L );
1641
return 0;
1642
}
1643
1644
/* Get and check the tree components */
1645
objTree1 = ELM_PLIST(objTree,1);
1646
if ( ! IS_PLIST(objTree1) ) {
1647
ErrorQuit( "invalid <tree>[1]", 0L, 0L );
1648
return 0;
1649
}
1650
objTree2 = ELM_PLIST(objTree,2);
1651
if ( ! IS_PLIST(objTree2) ) {
1652
ErrorQuit( "invalid <tree>[2]", 0L, 0L );
1653
return 0;
1654
}
1655
ptTree1 = &(ELM_PLIST(objTree1,1)) - 1;
1656
ptTree2 = &(ELM_PLIST(objTree2,1)) - 1;
1657
treesize = LEN_PLIST(objTree1);
1658
numgens = INT_INTOBJ( ELM_PLIST( objTree, 3 ) );
1659
treeWordLength = INT_INTOBJ( ELM_PLIST( objTree, 4 ) );
1660
treeType = INT_INTOBJ( ELM_PLIST( objTree, 5 ) );
1661
1662
/* Get the second argument (word) */
1663
if ( ! IS_PLIST(word) ) {
1664
ErrorQuit( "invalid <word>", 0L, 0L );
1665
return 0;
1666
}
1667
1668
/* handle the abelianized case */
1669
ptWord = &(ELM_PLIST(word,1)) - 1;
1670
if ( treeType == 0 ) {
1671
if ( LEN_PLIST(word) != treeWordLength ) {
1672
ErrorQuit( "inconsistent <word> length", 0L, 0L );
1673
return 0;
1674
}
1675
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
1676
for ( leng = treeWordLength; leng >= 1; leng-- ) {
1677
if ( ptWord[leng] != INTOBJ_INT(0) ) {
1678
break;
1679
}
1680
}
1681
if ( leng == 0 ) {
1682
return INTOBJ_INT( 0 );
1683
}
1684
1685
for ( k = 1; k <= leng; k++ ) {
1686
if ( ptWord[k] != INTOBJ_INT(0) ) {
1687
break;
1688
}
1689
}
1690
sign = 1;
1691
1692
/* invert the word */
1693
if ( INT_INTOBJ(ptWord[k]) < 0 ) {
1694
sign = -1;
1695
for ( i = k; i <= leng; i++ ) {
1696
ptWord[i] = INTOBJ_INT( - INT_INTOBJ( ptWord[i] ) );
1697
}
1698
}
1699
1700
for ( k = 1; k <= numgens; k++ ) {
1701
ptFac = &(ELM_PLIST(ptTree1[k],1)) - 1;
1702
if ( LEN_PLIST(ptTree1[k]) == leng ) {
1703
for ( i = 1; i <= leng; i++ ) {
1704
if ( ptFac[i] != ptWord[i] ) {
1705
break;
1706
}
1707
}
1708
if ( i > leng ) {
1709
return INTOBJ_INT( sign * k );
1710
}
1711
}
1712
}
1713
1714
/* extend the tree */
1715
numgens++;
1716
if ( treesize < numgens ) {
1717
treesize = 2 * treesize;
1718
GROW_PLIST( objTree1, treesize );
1719
SET_LEN_PLIST( objTree1, treesize );
1720
CHANGED_BAG(objTree);
1721
}
1722
new = NEW_PLIST( T_PLIST, leng );
1723
SET_LEN_PLIST( new, leng );
1724
1725
SET_ELM_PLIST( objTree, 3, INTOBJ_INT(numgens) );
1726
SET_ELM_PLIST( objTree1, numgens, new );
1727
CHANGED_BAG(objTree1);
1728
1729
/* copy the word to the new bag */
1730
ptWord = &(ELM_PLIST(objTree2,1)) - 1;
1731
ptNew = &(ELM_PLIST(new,1)) - 1;
1732
while ( leng > 0 ) {
1733
ptNew[leng] = ptWord[leng];
1734
leng--;
1735
}
1736
1737
return INTOBJ_INT( sign * numgens );
1738
}
1739
1740
/* handle the general case */
1741
if ( LEN_PLIST(objTree1) != LEN_PLIST(objTree2) ) {
1742
ErrorQuit( "inconsistent <tree> components", 0L, 0L );
1743
return 0;
1744
}
1745
1746
for ( i = 1; i <= numgens; i++ ) {
1747
if ( INT_INTOBJ(ptTree1[i]) <= -i || INT_INTOBJ(ptTree1[i]) >= i
1748
|| INT_INTOBJ(ptTree2[i]) <= -i || INT_INTOBJ(ptTree2[i]) >= i )
1749
{
1750
ErrorQuit( "invalid <tree> components", 0L, 0L );
1751
return 0;
1752
}
1753
}
1754
1755
/* Freely reduce the given word */
1756
leng = LEN_PLIST(word);
1757
for ( j = 0, i = 1; i <= leng; i++ ) {
1758
gen = INT_INTOBJ(ptWord[i]);
1759
if ( gen == 0 ) {
1760
continue;
1761
}
1762
if ( gen > numgens || gen < -numgens ) {
1763
ErrorQuit( "invalid <word> entry [%d]", i, 0L );
1764
return 0;
1765
}
1766
if ( j > 0 && gen == - INT_INTOBJ(ptWord[j]) ) {
1767
j--;
1768
}
1769
else {
1770
ptWord[++j] = ptWord[i];
1771
}
1772
}
1773
for ( i = j + 1; i <= leng; i++ ) {
1774
ptWord[i] = INTOBJ_INT( 0 );
1775
}
1776
leng = j;
1777
1778
gen = ( leng == 0 ) ? 0 : INT_INTOBJ( ptWord[1] );
1779
u2 = 0; /* just to shut up gcc */
1780
for ( i = 2; i <= leng; i++ ) {
1781
u = gen;
1782
v = INT_INTOBJ( ELM_PLIST(word,i) );
1783
while ( i ) {
1784
1785
/* First handle the trivial cases */
1786
if ( u == 0 || v == 0 || ( u + v ) == 0 ) {
1787
gen = u + v;
1788
break;
1789
}
1790
1791
/* Cancel out factors, if possible */
1792
u1 = INT_INTOBJ( ptTree1[ (u > 0) ? u : -u ] );
1793
if ( u1 != 0 ) {
1794
if ( u > 0 ) {
1795
u2 = INT_INTOBJ( ptTree2[u] );
1796
}
1797
else {
1798
u2 = - u1;
1799
u1 = - INT_INTOBJ( ptTree2[-u] );
1800
}
1801
if ( u2 == -v ) {
1802
gen = u1;
1803
break;
1804
}
1805
}
1806
v1 = INT_INTOBJ( ptTree1[ (v > 0) ? v : -v ] );
1807
if ( v1 != 0 ) {
1808
if ( v > 0 ) {
1809
v2 = INT_INTOBJ( ptTree2[v] );
1810
}
1811
else {
1812
v2 = - v1;
1813
v1 = - INT_INTOBJ( ptTree2[-v] );
1814
}
1815
if ( v1 == -u ) {
1816
gen = v2;
1817
break;
1818
}
1819
if ( u1 != 0 && v1 == - u2 ) {
1820
u = u1;
1821
v = v2;
1822
continue;
1823
}
1824
}
1825
1826
/* Check if there is already a tree entry [u,v] or [-v,-u] */
1827
if ( u < -v ) {
1828
t1 = u;
1829
t2 = v;
1830
}
1831
else {
1832
t1 = -v;
1833
t2 = -u;
1834
}
1835
uabs = ( u > 0 ) ? u : -u;
1836
vabs = ( v > 0 ) ? v : -v;
1837
k = ( uabs > vabs ) ? uabs : vabs;
1838
for ( k++; k <= numgens; k++ ) {
1839
if ( INT_INTOBJ(ptTree1[k]) == t1 &&
1840
INT_INTOBJ(ptTree2[k]) == t2 )
1841
{
1842
break;
1843
}
1844
}
1845
1846
/* Extend the tree, if necessary */
1847
if ( k > numgens ) {
1848
numgens++;
1849
if ( treesize < numgens ) {
1850
treesize = 2 * treesize;
1851
GROW_PLIST( objTree1, treesize );
1852
GROW_PLIST( objTree2, treesize );
1853
SET_LEN_PLIST( objTree1, treesize );
1854
SET_LEN_PLIST( objTree2, treesize );
1855
ptTree1 = &(ELM_PLIST(objTree1,1)) - 1;
1856
ptTree2 = &(ELM_PLIST(objTree2,1)) - 1;
1857
CHANGED_BAG(objTree);
1858
}
1859
ptTree1[numgens] = INTOBJ_INT( t1 );
1860
ptTree2[numgens] = INTOBJ_INT( t2 );
1861
SET_ELM_PLIST( objTree, 3, INTOBJ_INT( numgens ) );
1862
}
1863
gen = ( u > - v ) ? -k : k;
1864
break;
1865
}
1866
}
1867
1868
return INTOBJ_INT( gen );
1869
}
1870
1871
1872
/****************************************************************************
1873
**
1874
*F AddCosetFactor( <factor> ) . . . . . . . . . . . . add a coset rep factor
1875
**
1876
** 'AddCosetFactor' adds a factor to a coset representative word by changing
1877
** its exponent appropriately.
1878
**
1879
** 'treeType', 'objWordValue', and 'objExponent' are assumed to be known as
1880
** static variables, and 'treeType' is assumed to be 1.
1881
**
1882
** Warning: 'factor' is not checked for being zero.
1883
*/
1884
static void AddCosetFactor (
1885
Obj factor )
1886
{
1887
/* handle the one generator MTC case */
1888
objWordValue = SumInt( objWordValue, factor );
1889
if ( objExponent != INTOBJ_INT(0) ) {
1890
objWordValue = RemInt( objWordValue, objExponent );
1891
}
1892
}
1893
1894
1895
/****************************************************************************
1896
**
1897
*F SubtractCosetFactor( <factor> ) . . . . . . subtract a coset rep factor
1898
**
1899
** 'SubtractCosetFactor' subtracts a factor from a coset representative word
1900
** by changing its exponent appropriately.
1901
**
1902
** 'treeType', 'objWordValue', and 'objExponent' are assumed to be known as
1903
** static variables, and 'treeType' is assumed to be 1.
1904
**
1905
** Warning: 'factor' is not checked for being zero.
1906
*/
1907
static void SubtractCosetFactor (
1908
Obj factor )
1909
{
1910
/* handle the one generator MTC case */
1911
objWordValue = DiffInt( objWordValue, factor );
1912
if ( objExponent != INTOBJ_INT(0) ) {
1913
objWordValue = RemInt( objWordValue, objExponent );
1914
}
1915
}
1916
1917
1918
/****************************************************************************
1919
**
1920
*F HandleCoinc2( <cos1>, <cos2>, <factor> ) . handle coincidences in an MTC
1921
**
1922
** 'HandleCoinc2' is a subroutine of 'FuncMakeConsequences2' and handles the
1923
** coincidence cos2 = factor * cos1.
1924
*/
1925
static void HandleCoinc2 (
1926
Int cos1,
1927
Int cos2,
1928
Obj factor )
1929
{
1930
Obj f, ff2; /* handles of temporary factors */
1931
Obj f1, f2; /* handles of temporary factors */
1932
Obj rem; /* handle of remainder */
1933
Obj tmp; /* temporary variable */
1934
Obj * gen2;
1935
Obj * gen;
1936
Obj * inv2;
1937
Obj * inv;
1938
Obj * ptNext;
1939
Obj * ptPrev;
1940
Int c1, c2;
1941
Int firstCoinc;
1942
Int i, j; /* loop variables */
1943
Int lastCoinc;
1944
Int length; /* length of coset rep word */
1945
Int save; /* temporary factor */
1946
1947
/* return, if cos1 = cos2 */
1948
if ( cos1 == cos2 ) {
1949
1950
/* but pick up a relator before in case treeType = 1 */
1951
if ( treeType == 1 && factor != INTOBJ_INT(0) ) {
1952
if ( objExponent == INTOBJ_INT(0) ) {
1953
objExponent = factor;
1954
}
1955
else {
1956
rem = RemInt( factor, objExponent );
1957
while ( rem != INTOBJ_INT(0) ) {
1958
factor = objExponent;
1959
objExponent = rem;
1960
rem = RemInt( factor, objExponent );
1961
}
1962
}
1963
}
1964
return;
1965
}
1966
1967
/* take the smaller one as new representative */
1968
if ( cos2 < cos1 ) {
1969
save = cos1; cos1 = cos2; cos2 = save;
1970
factor = ( treeType == 1 ) ?
1971
DiffInt( INTOBJ_INT(0), factor ) :
1972
INTOBJ_INT( -INT_INTOBJ(factor) );
1973
}
1974
1975
/* get some pointers */
1976
ptNext = &(ELM_PLIST(objNext,1)) - 1;
1977
ptPrev = &(ELM_PLIST(objPrev,1)) - 1;
1978
1979
/* if we are removing an important coset update it */
1980
if ( cos2 == lastDef ) {
1981
lastDef = INT_INTOBJ( ptPrev[lastDef ] );
1982
}
1983
if ( cos2 == firstDef ) {
1984
firstDef = INT_INTOBJ( ptPrev[firstDef] );
1985
}
1986
1987
/* remove <cos2> from the coset list */
1988
ptNext[INT_INTOBJ(ptPrev[cos2])] = ptNext[cos2];
1989
if ( ptNext[cos2] != INTOBJ_INT(0) ) {
1990
ptPrev[INT_INTOBJ(ptNext[cos2])] = ptPrev[cos2];
1991
}
1992
1993
/* put the first coincidence into the list of coincidences */
1994
firstCoinc = cos2;
1995
lastCoinc = cos2;
1996
ptNext[lastCoinc] = INTOBJ_INT(0);
1997
1998
/* <cos1> is the representative of <cos2> and its own representative */
1999
ptPrev[cos2] = INTOBJ_INT(cos1);
2000
SET_ELM_PLIST( objFactor, cos2, factor );
2001
2002
/* while there are coincidences to handle */
2003
while ( firstCoinc != 0 ) {
2004
2005
/* replace <firstCoinc> by its representative in the table */
2006
cos2 = firstCoinc;
2007
cos1 = INT_INTOBJ( ELM_PLIST( objPrev, cos2 ) );
2008
factor = ELM_PLIST( objFactor, cos2 );
2009
for ( i = 1; i <= LEN_PLIST(objTable); i++ ) {
2010
j = i + 2*(i % 2) - 1;
2011
2012
/* replace <cos2> by <cos1> in the column of <gen>^-1 */
2013
gen = &(ELM_PLIST(ELM_PLIST(objTable,i),1)) - 1;
2014
gen2 = &(ELM_PLIST(ELM_PLIST(objTable2,i),1)) - 1;
2015
c2 = INT_INTOBJ(gen[cos2]);
2016
if ( c2 != 0 ) {
2017
f2 = gen2[cos2];
2018
c1 = INT_INTOBJ(gen[cos1]);
2019
2020
/* if the other entry is empty copy it */
2021
if ( c1 == 0 ) {
2022
if ( f2 == factor ) {
2023
ff2 = INTOBJ_INT(0);
2024
}
2025
else {
2026
if ( treeType == 1 ) {
2027
objWordValue = INTOBJ_INT(0);
2028
if ( factor != INTOBJ_INT(0) ) {
2029
SubtractCosetFactor(factor);
2030
}
2031
if ( f2 != INTOBJ_INT(0) ) {
2032
AddCosetFactor( f2 );
2033
}
2034
ff2 = objWordValue;
2035
}
2036
else {
2037
InitializeCosetFactorWord();
2038
if ( factor != INTOBJ_INT(0) ) {
2039
AddCosetFactor2( -INT_INTOBJ(factor) );
2040
}
2041
if ( f2 != INTOBJ_INT(0) ) {
2042
AddCosetFactor2( INT_INTOBJ(f2) );
2043
}
2044
ff2 = INTOBJ_INT(TreeEntryC());
2045
}
2046
}
2047
tmp = ( treeType == 1 ) ?
2048
DiffInt( INTOBJ_INT(0), ff2 ) :
2049
INTOBJ_INT( -INT_INTOBJ(ff2) );
2050
gen = &(ELM_PLIST(ELM_PLIST(objTable,i),1)) - 1;
2051
gen2 = &(ELM_PLIST(ELM_PLIST(objTable2,i),1)) - 1;
2052
inv = &(ELM_PLIST(ELM_PLIST(objTable,j),1)) - 1;
2053
inv2 = &(ELM_PLIST(ELM_PLIST(objTable2,j),1)) - 1;
2054
gen[cos1] = INTOBJ_INT(c2);
2055
gen2[cos1] = ff2;
2056
gen[cos2] = INTOBJ_INT(0);
2057
gen2[cos2] = INTOBJ_INT(0);
2058
inv[c2] = INTOBJ_INT(cos1);
2059
inv2[c2] = tmp;
2060
if ( dedlst == dedSize ) {
2061
CompressDeductionList();
2062
}
2063
dedgen[dedlst] = i;
2064
dedcos[dedlst] = cos1;
2065
dedlst++;
2066
}
2067
2068
/* otherwise check for a coincidence */
2069
else {
2070
f1 = gen2[cos1];
2071
inv = &(ELM_PLIST(ELM_PLIST(objTable,j),1)) - 1;
2072
inv2 = &(ELM_PLIST(ELM_PLIST(objTable2,j),1)) - 1;
2073
inv[c2] = INTOBJ_INT(0);
2074
inv2[c2] = INTOBJ_INT(0);
2075
gen[cos2] = INTOBJ_INT(0);
2076
gen2[cos2] = INTOBJ_INT(0);
2077
2078
/* if gen = inv and c2 = cos1, reset the table entries */
2079
if ( gen[cos1] == INTOBJ_INT(0) ) {
2080
if ( f2 == factor ) {
2081
ff2 = INTOBJ_INT(0);
2082
}
2083
else {
2084
if ( treeType == 1 ) {
2085
objWordValue = INTOBJ_INT(0);
2086
if ( factor != INTOBJ_INT(0) ) {
2087
SubtractCosetFactor(factor);
2088
}
2089
if ( f2 != INTOBJ_INT(0) ) {
2090
AddCosetFactor(f2);
2091
}
2092
ff2 = objWordValue;
2093
}
2094
else {
2095
InitializeCosetFactorWord();
2096
if ( factor != INTOBJ_INT(0) ) {
2097
AddCosetFactor2( -INT_INTOBJ(factor) );
2098
}
2099
if ( f2 != INTOBJ_INT(0) ) {
2100
AddCosetFactor2( INT_INTOBJ(f2) );
2101
}
2102
ff2 = INTOBJ_INT( TreeEntryC() );
2103
}
2104
gen = &(ELM_PLIST(ELM_PLIST(objTable,i),1))-1;
2105
gen2 = &(ELM_PLIST(ELM_PLIST(objTable2,i),1))-1;
2106
}
2107
gen[cos1] = INTOBJ_INT(cos1);
2108
gen2[cos1] = ff2;
2109
if ( dedlst == dedSize ) {
2110
CompressDeductionList();
2111
}
2112
dedgen[dedlst] = i;
2113
dedcos[dedlst] = cos1;
2114
dedlst++;
2115
}
2116
2117
/* initialize the factor for the new coincidence */
2118
InitializeCosetFactorWord();
2119
2120
/* find the representative of <c2> */
2121
2122
/* handle the one generator MTC case */
2123
if ( treeType == 1 ) {
2124
2125
if ( f2 != INTOBJ_INT(0) ) {
2126
SubtractCosetFactor(f2);
2127
}
2128
while ( c2 != 1 && INT_INTOBJ( ELM_PLIST( objNext,
2129
INT_INTOBJ(ELM_PLIST(objPrev,c2)))) != c2 )
2130
{
2131
f2 = ELM_PLIST(objFactor,c2);
2132
c2 = INT_INTOBJ( ELM_PLIST(objPrev,c2) );
2133
if ( f2 != INTOBJ_INT(0) ) {
2134
SubtractCosetFactor(f2);
2135
}
2136
}
2137
if ( factor != INTOBJ_INT(0) ) {
2138
AddCosetFactor(factor);
2139
}
2140
if ( f1 != INTOBJ_INT(0) ) {
2141
AddCosetFactor(f1);
2142
}
2143
}
2144
2145
/* handle the abelianized case */
2146
else if ( treeType == 0 ) {
2147
if ( f2 != INTOBJ_INT(0) ) {
2148
AddCosetFactor2( -INT_INTOBJ(f2) );
2149
}
2150
while ( c2 != 1 && INT_INTOBJ( ELM_PLIST( objNext,
2151
INT_INTOBJ(ELM_PLIST(objPrev,c2)))) != c2 )
2152
{
2153
f2 = ELM_PLIST(objFactor,c2);
2154
c2 = INT_INTOBJ( ELM_PLIST(objPrev,c2) );
2155
if ( f2 != INTOBJ_INT(0) ) {
2156
AddCosetFactor2( -INT_INTOBJ(f2) );
2157
}
2158
}
2159
if ( factor != INTOBJ_INT(0) ) {
2160
AddCosetFactor2( INT_INTOBJ(factor) );
2161
}
2162
if ( f1 != INTOBJ_INT(0) ) {
2163
AddCosetFactor2( INT_INTOBJ(f1) );
2164
}
2165
}
2166
2167
/* handle the general case */
2168
else
2169
{
2170
if ( f2 != INTOBJ_INT(0) ) {
2171
AddCosetFactor2( INT_INTOBJ(f2) );
2172
}
2173
while ( c2 != 1 && INT_INTOBJ( ELM_PLIST( objNext,
2174
INT_INTOBJ(ELM_PLIST(objPrev,c2)))) != c2 )
2175
{
2176
f2 = ELM_PLIST(objFactor,c2);
2177
c2 = INT_INTOBJ( ELM_PLIST(objPrev,c2) );
2178
if ( f2 != INTOBJ_INT(0) ) {
2179
AddCosetFactor2( INT_INTOBJ(f2) );
2180
}
2181
}
2182
2183
/* invert the word constructed so far */
2184
if ( wordList[0] > 0 ) {
2185
length = wordList[0] + 1;
2186
for ( i = length / 2; i > 0; i-- ) {
2187
save = wordList[i];
2188
wordList[i] = - wordList[length-i];
2189
wordList[length-i] = - save;
2190
}
2191
}
2192
if ( factor != INTOBJ_INT(0) ) {
2193
AddCosetFactor2( INT_INTOBJ(factor) );
2194
}
2195
if ( f1 != INTOBJ_INT(0) ) {
2196
AddCosetFactor2( INT_INTOBJ(f1) );
2197
}
2198
}
2199
2200
/* find the representative of <c1> */
2201
while ( c1 != 1 && INT_INTOBJ( ELM_PLIST( objNext,
2202
INT_INTOBJ(ELM_PLIST(objPrev,c1)))) != c1 )
2203
{
2204
f1 = ELM_PLIST(objFactor,c1);
2205
c1 = INT_INTOBJ( ELM_PLIST(objPrev,c1) );
2206
if ( f1 != INTOBJ_INT(0) ) {
2207
if ( treeType == 1 ) {
2208
AddCosetFactor( f1 );
2209
}
2210
else {
2211
AddCosetFactor2( INT_INTOBJ(f1) );
2212
}
2213
}
2214
}
2215
2216
/* if the representatives differ we got a coincidence */
2217
if ( c1 != c2 ) {
2218
2219
/* get the quotient of c2 by c1 */
2220
f = (treeType == 1 ) ?
2221
objWordValue : INTOBJ_INT(TreeEntryC());
2222
2223
/* take the smaller one as new representative */
2224
if ( c2 < c1 ) {
2225
save = c1; c1 = c2; c2 = save;
2226
f = ( treeType == 1 ) ?
2227
DiffInt( INTOBJ_INT(0), f ) :
2228
INTOBJ_INT( -INT_INTOBJ(f) );
2229
}
2230
2231
/* get some pointers */
2232
ptNext = &(ELM_PLIST(objNext,1)) - 1;
2233
ptPrev = &(ELM_PLIST(objPrev,1)) - 1;
2234
2235
/* if we are removing an important coset update it */
2236
if ( c2 == lastDef ) {
2237
lastDef = INT_INTOBJ(ptPrev[lastDef]);
2238
}
2239
if ( c2 == firstDef ) {
2240
firstDef = INT_INTOBJ(ptPrev[firstDef]);
2241
}
2242
2243
/* remove <c2> from the coset list */
2244
ptNext[INT_INTOBJ(ptPrev[c2])] = ptNext[c2];
2245
if ( ptNext[c2] != INTOBJ_INT(0) ) {
2246
ptPrev[INT_INTOBJ(ptNext[c2])] = ptPrev[c2];
2247
}
2248
2249
/* append <c2> to the coincidence list */
2250
ptNext[lastCoinc] = INTOBJ_INT(c2);
2251
lastCoinc = c2;
2252
ptNext[lastCoinc] = INTOBJ_INT(0);
2253
2254
/* <c1> is the rep of <c2> and its own rep. */
2255
ptPrev[c2] = INTOBJ_INT( c1 );
2256
SET_ELM_PLIST( objFactor, c2, f );
2257
}
2258
2259
/* pick up a relator in case treeType = 1 */
2260
else if ( treeType == 1 ) {
2261
f = objWordValue;
2262
if ( f != INTOBJ_INT(0) ) {
2263
if ( objExponent == INTOBJ_INT(0) ) {
2264
objExponent = f;
2265
}
2266
else {
2267
rem = RemInt( f, objExponent );
2268
while ( rem != INTOBJ_INT(0) ) {
2269
f = objExponent;
2270
objExponent = rem;
2271
rem = RemInt( f, objExponent );
2272
}
2273
}
2274
}
2275
}
2276
}
2277
}
2278
}
2279
2280
/* move the replaced coset to the free list */
2281
ptNext = &(ELM_PLIST(objNext,1)) - 1;
2282
if ( firstFree == 0 ) {
2283
firstFree = firstCoinc;
2284
lastFree = firstCoinc;
2285
}
2286
else {
2287
ptNext[lastFree] = INTOBJ_INT(firstCoinc);
2288
lastFree = firstCoinc;
2289
}
2290
firstCoinc = INT_INTOBJ( ptNext[firstCoinc] );
2291
ptNext[lastFree] = INTOBJ_INT(0);
2292
2293
nrdel++;
2294
}
2295
}
2296
2297
2298
/****************************************************************************
2299
**
2300
*F FuncMakeConsequences2( <self>, <list> ) . . . . . . . find consequences
2301
*/
2302
Obj FuncMakeConsequences2 (
2303
Obj self,
2304
Obj list )
2305
{
2306
Obj subs; /* */
2307
Obj rels; /* */
2308
Obj * ptRel; /* pointer to the relator bag */
2309
Int lp; /* left pointer into relator */
2310
Int lc; /* left coset to apply to */
2311
Int rp; /* right pointer into relator */
2312
Int rc; /* right coset to apply to */
2313
Int tc; /* temporary coset */
2314
Int length; /* length of coset rep word */
2315
Obj objNum; /* handle of temporary factor */
2316
Obj objRep; /* handle of temporary factor */
2317
Int rep; /* temporary factor */
2318
Int i, j; /* loop variables */
2319
Obj tmp; /* temporary variable */
2320
2321
/* get the list of arguments */
2322
if ( ! IS_PLIST(list) ) {
2323
ErrorQuit( "<list> must be a plain list (not a %s)",
2324
(Int)TNAM_OBJ(list), 0L );
2325
return 0;
2326
}
2327
if ( LEN_PLIST(list) != 16 ) {
2328
ErrorQuit( "<list> must be a list of length 16", 0L, 0L );
2329
return 0;
2330
}
2331
2332
/* get the coset table, the corresponding factor table, the subgroup */
2333
/* generators tree, and its components */
2334
objTable = ELM_PLIST(list,1);
2335
objTable2 = ELM_PLIST(list,12);
2336
objTree = ELM_PLIST(list,14);
2337
objTree1 = ELM_PLIST(objTree,1);
2338
objTree2 = ELM_PLIST(objTree,2);
2339
treeType = INT_INTOBJ( ELM_PLIST(objTree,5) );
2340
treeWordLength = INT_INTOBJ( ELM_PLIST(list,15) );
2341
objExponent = ELM_PLIST(list,16);
2342
2343
objNext = ELM_PLIST(list,2);
2344
objPrev = ELM_PLIST(list,3);
2345
objFactor = ELM_PLIST(list,13);
2346
2347
firstFree = INT_INTOBJ( ELM_PLIST(list,6) );
2348
lastFree = INT_INTOBJ( ELM_PLIST(list,7) );
2349
firstDef = INT_INTOBJ( ELM_PLIST(list,8) );
2350
lastDef = INT_INTOBJ( ELM_PLIST(list,9) );
2351
2352
nrdel = 0;
2353
2354
/* initialize the deduction queue */
2355
dedprint = 0;
2356
dedfst = 0;
2357
dedlst = 1;
2358
dedgen[0] = INT_INTOBJ( ELM_PLIST(list,10) );
2359
dedcos[0] = INT_INTOBJ( ELM_PLIST(list,11) );
2360
2361
/* while the deduction queue is not empty */
2362
while ( dedfst < dedlst ) {
2363
2364
/* skip the deduction, if it got irrelevant by a coincidence */
2365
tmp = ELM_PLIST( objTable, dedgen[dedfst] );
2366
tmp = ELM_PLIST( tmp, dedcos[dedfst] );
2367
if ( INT_INTOBJ(tmp) == 0 ) {
2368
dedfst++;
2369
continue;
2370
}
2371
2372
/* while there are still subgroup generators apply them */
2373
subs = ELM_PLIST(list,5);
2374
for ( i = LEN_PLIST(subs); 1 <= i; i-- ) {
2375
if ( ELM_PLIST(subs,i) != 0 ) {
2376
tmp = ELM_PLIST(subs,i);
2377
objNums = ELM_PLIST(tmp,1);
2378
objRel = ELM_PLIST(tmp,2);
2379
ptRel = &(ELM_PLIST(objRel,1)) - 1;
2380
2381
lp = 2;
2382
lc = 1;
2383
rp = LEN_PLIST(objRel) - 1;
2384
rc = 1;
2385
2386
/* scan as long as possible from the left to the right */
2387
while ( lp < rp
2388
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))) )
2389
{
2390
lc = tc;
2391
lp = lp + 2;
2392
}
2393
2394
/* scan as long as possible from the right to the left */
2395
while ( lp < rp
2396
&& 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))) )
2397
{
2398
rc = tc;
2399
rp = rp - 2;
2400
}
2401
2402
/* scan once more, but now with factors, if a coincidence or */
2403
/* a deduction has been found */
2404
if (lp == rp+1 && INT_INTOBJ(ELM_PLIST(ptRel[lp],lc)) != rc) {
2405
lp = 2;
2406
lc = 1;
2407
rp = LEN_PLIST(objRel) - 1;
2408
rc = 1;
2409
2410
/* initialize the coset representative word */
2411
InitializeCosetFactorWord();
2412
2413
/* scan as long as possible from the left to the right */
2414
2415
/* handle the one generator MTC case */
2416
if ( treeType == 1 ) {
2417
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2418
ELM_PLIST(ELM_PLIST(objRel,lp),lc))) )
2419
{
2420
objRep = ELM_PLIST(objNums,lp);
2421
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2422
objRep = ELM_PLIST(objRep,lc);
2423
if ( objRep != INTOBJ_INT(0) ) {
2424
SubtractCosetFactor(objRep);
2425
}
2426
lc = tc;
2427
lp = lp + 2;
2428
}
2429
2430
/* add the factor defined by the ith subgrp generator*/
2431
if ( i != 0 ) {
2432
AddCosetFactor( INTOBJ_INT(i) );
2433
}
2434
2435
/* scan as long as poss from the right to the left */
2436
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2437
ELM_PLIST(ELM_PLIST(objRel,rp),rc))) )
2438
{
2439
objRep = ELM_PLIST(objNums,rp);
2440
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2441
objRep = ELM_PLIST(objRep,rc);
2442
if ( objRep != INTOBJ_INT(0) ) {
2443
AddCosetFactor(objRep);
2444
}
2445
rc = tc;
2446
rp = rp - 2;
2447
}
2448
}
2449
2450
/* handle the abelianized case */
2451
else if ( treeType == 0 ) {
2452
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2453
ELM_PLIST(ELM_PLIST(objRel,lp),lc))) )
2454
{
2455
objRep = ELM_PLIST(objNums,lp);
2456
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2457
objRep = ELM_PLIST(objRep,lc);
2458
rep = INT_INTOBJ(objRep);
2459
if ( rep != 0 ) {
2460
AddCosetFactor2(-rep);
2461
}
2462
lc = tc;
2463
lp = lp + 2;
2464
}
2465
2466
/* add the factor defined by the ith subgrp generator*/
2467
if ( i != 0 ) {
2468
AddCosetFactor2(i);
2469
}
2470
2471
/* scan as long as poss from the right to the left */
2472
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2473
ELM_PLIST(ELM_PLIST(objRel,rp),rc))) )
2474
{
2475
objRep = ELM_PLIST(objNums,rp);
2476
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2477
objRep = ELM_PLIST(objRep,rc);
2478
rep = INT_INTOBJ(objRep);
2479
if ( rep != 0 ) {
2480
AddCosetFactor2(rep);
2481
}
2482
rc = tc;
2483
rp = rp - 2;
2484
}
2485
}
2486
2487
/* handle the general case */
2488
else {
2489
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2490
ELM_PLIST(ELM_PLIST(objRel,lp),lc))) )
2491
{
2492
objRep = ELM_PLIST(objNums,lp);
2493
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2494
objRep = ELM_PLIST(objRep,lc);
2495
rep = INT_INTOBJ(objRep);
2496
if ( rep != 0 ) {
2497
AddCosetFactor2(rep);
2498
}
2499
lc = tc;
2500
lp = lp + 2;
2501
}
2502
2503
/* invert the word constructed so far */
2504
if ( wordList[0] > 0 ) {
2505
length = wordList[0] + 1;
2506
for ( j = length / 2; j > 0; j-- ) {
2507
rep = wordList[j];
2508
wordList[j] = - wordList[length-j];
2509
wordList[length-j] = - rep;
2510
}
2511
}
2512
2513
/* add the factor defined by the ith subgrp generator*/
2514
if ( i != 0 ) {
2515
AddCosetFactor2(i);
2516
}
2517
2518
/* scan as long as poss from the right to the left */
2519
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ(
2520
ELM_PLIST(ELM_PLIST(objRel,rp),rc))) )
2521
{
2522
objRep = ELM_PLIST(objNums,rp);
2523
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2524
objRep = ELM_PLIST(objRep,rc);
2525
rep = INT_INTOBJ(objRep);
2526
if ( rep != 0 ) {
2527
AddCosetFactor2(rep);
2528
}
2529
rc = tc;
2530
rp = rp - 2;
2531
}
2532
}
2533
2534
/* enter the word into the tree and return its number */
2535
objNum = ( treeType == 1 ) ?
2536
objWordValue : INTOBJ_INT(TreeEntryC());
2537
2538
/* work off a coincidence */
2539
if ( lp >= rp + 2 ) {
2540
HandleCoinc2( rc, lc, objNum );
2541
}
2542
2543
/* enter a decuction to the tables */
2544
else {
2545
objRep = ELM_PLIST(objRel,lp);
2546
SET_ELM_PLIST( objRep, lc, INTOBJ_INT(rc) );
2547
2548
objRep = ELM_PLIST(objNums,lp);
2549
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2550
SET_ELM_PLIST( objRep, lc, objNum );
2551
2552
objRep = ELM_PLIST(objRel,rp);
2553
SET_ELM_PLIST( objRep, rc, INTOBJ_INT(lc) );
2554
2555
tmp = ( treeType == 1 ) ?
2556
DiffInt( INTOBJ_INT(0), objNum ) :
2557
INTOBJ_INT( -INT_INTOBJ( objNum ) );
2558
objRep = ELM_PLIST(objNums,rp);
2559
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2560
SET_ELM_PLIST( objRep, rc, tmp );
2561
2562
if ( dedlst == dedSize ) {
2563
CompressDeductionList();
2564
}
2565
dedgen[dedlst] = INT_INTOBJ( ELM_PLIST(objNums,lp) );
2566
dedcos[dedlst] = lc;
2567
dedlst++;
2568
}
2569
2570
/* remove the completed subgroup generator */
2571
SET_ELM_PLIST( subs, i, 0 );
2572
if ( i == LEN_PLIST(subs) ) {
2573
while ( 0 < i && ELM_PLIST(subs,i) == 0 ) {
2574
--i;
2575
}
2576
SET_LEN_PLIST( subs, i );
2577
}
2578
}
2579
}
2580
}
2581
2582
/* apply all relators that start with this generator */
2583
rels = ELM_PLIST( ELM_PLIST(list,4), dedgen[dedfst] );
2584
for ( i = 1; i <= LEN_PLIST(rels); i++ ) {
2585
tmp = ELM_PLIST(rels,i);
2586
objNums = ELM_PLIST(tmp,1);
2587
objRel = ELM_PLIST(tmp,2);
2588
ptRel = &(ELM_PLIST(objRel,1)) - 1;
2589
2590
lp = INT_INTOBJ( ELM_PLIST(tmp,3) );
2591
lc = dedcos[dedfst];
2592
rp = lp + INT_INTOBJ(ptRel[1]);
2593
rc = lc;
2594
2595
/* scan as long as possible from the left to the right */
2596
while (lp < rp && 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[lp],lc))))
2597
{
2598
lc = tc;
2599
lp = lp + 2;
2600
}
2601
2602
/* scan as long as possible from the right to the left */
2603
while (lp < rp && 0 < (tc = INT_INTOBJ(ELM_PLIST(ptRel[rp],rc))))
2604
{
2605
rc = tc;
2606
rp = rp - 2;
2607
}
2608
2609
/* scan once more, but now with factors, if a coincidence or a */
2610
/* deduction has been found */
2611
if ( lp == rp+1 && ( INT_INTOBJ(ELM_PLIST(ptRel[lp],lc)) != rc
2612
|| treeType == 1 ) )
2613
{
2614
2615
lp = INT_INTOBJ( ELM_PLIST( ELM_PLIST(rels,i), 3 ) );
2616
lc = dedcos[dedfst];
2617
rp = lp + INT_INTOBJ(ptRel[1]);
2618
rc = lc;
2619
2620
/* initialize the coset representative word */
2621
InitializeCosetFactorWord();
2622
2623
/* scan as long as possible from the left to the right */
2624
/* handle the one generator MTC case */
2625
2626
if ( treeType == 1 ) {
2627
2628
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2629
ELM_PLIST(objRel,lp),lc))) )
2630
{
2631
objRep = ELM_PLIST(objNums,lp);
2632
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2633
objRep = ELM_PLIST(objRep,lc);
2634
if ( objRep != INTOBJ_INT(0) ) {
2635
SubtractCosetFactor(objRep);
2636
}
2637
lc = tc;
2638
lp = lp + 2;
2639
}
2640
2641
/* scan as long as possible from the right to the left */
2642
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2643
ELM_PLIST(objRel,rp),rc))) )
2644
{
2645
objRep = ELM_PLIST(objNums,rp);
2646
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2647
objRep = ELM_PLIST(objRep,rc);
2648
if ( objRep != INTOBJ_INT(0) ) {
2649
AddCosetFactor( objRep );
2650
}
2651
rc = tc;
2652
rp = rp - 2;
2653
}
2654
}
2655
2656
/* handle the abelianized case */
2657
else if ( treeType == 0 ) {
2658
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2659
ELM_PLIST(objRel,lp),lc))) )
2660
{
2661
objRep = ELM_PLIST(objNums,lp);
2662
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2663
objRep = ELM_PLIST(objRep,lc);
2664
rep = INT_INTOBJ(objRep);
2665
if ( rep != 0 ) {
2666
AddCosetFactor2(-rep);
2667
}
2668
lc = tc;
2669
lp = lp + 2;
2670
}
2671
2672
/* scan as long as possible from the right to the left */
2673
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2674
ELM_PLIST(objRel,rp),rc))) )
2675
{
2676
objRep = ELM_PLIST(objNums,rp);
2677
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2678
objRep = ELM_PLIST(objRep,rc);
2679
rep = INT_INTOBJ(objRep);
2680
if ( rep != 0 ) {
2681
AddCosetFactor2(rep);
2682
}
2683
rc = tc;
2684
rp = rp - 2;
2685
}
2686
}
2687
2688
/* handle the general case */
2689
else {
2690
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2691
ELM_PLIST(objRel,lp),lc))) )
2692
{
2693
objRep = ELM_PLIST(objNums,lp);
2694
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2695
objRep = ELM_PLIST(objRep,lc);
2696
rep = INT_INTOBJ(objRep);
2697
if ( rep != 0 ) {
2698
AddCosetFactor2(rep);
2699
}
2700
lc = tc;
2701
lp = lp + 2;
2702
}
2703
2704
/* invert the word constructed so far */
2705
if ( wordList[0] > 0 ) {
2706
length = wordList[0] + 1;
2707
for ( j = length / 2; j > 0; j-- ) {
2708
rep = wordList[j];
2709
wordList[j] = - wordList[length-j];
2710
wordList[length-j] = - rep;
2711
}
2712
}
2713
2714
/* scan as long as possible from the right to the left */
2715
while ( lp < rp + 2 && 0 < (tc = INT_INTOBJ( ELM_PLIST(
2716
ELM_PLIST(objRel,rp),rc))) )
2717
{
2718
objRep = ELM_PLIST(objNums,rp);
2719
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2720
objRep = ELM_PLIST(objRep,rc);
2721
rep = INT_INTOBJ(objRep);
2722
if ( rep != 0 ) {
2723
AddCosetFactor2( rep );
2724
}
2725
rc = tc;
2726
rp = rp - 2;
2727
}
2728
}
2729
2730
/* enter the word into the tree and return its number */
2731
objNum = ( treeType == 1 ) ?
2732
objWordValue : INTOBJ_INT(TreeEntryC());
2733
2734
/* work off a coincidence */
2735
if ( lp >= rp + 2 ) {
2736
HandleCoinc2( rc, lc, objNum );
2737
}
2738
2739
/* enter a decuction to the tables */
2740
else {
2741
objRep = ELM_PLIST(objRel,lp);
2742
SET_ELM_PLIST( objRep, lc, INTOBJ_INT(rc) );
2743
2744
objRep = ELM_PLIST(objNums,lp);
2745
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2746
SET_ELM_PLIST( objRep, lc, objNum );
2747
2748
objRep = ELM_PLIST(objRel,rp);
2749
SET_ELM_PLIST( objRep, rc, INTOBJ_INT(lc) );
2750
2751
tmp = ( treeType == 1 ) ?
2752
DiffInt( INTOBJ_INT(0), objNum ) :
2753
INTOBJ_INT( -INT_INTOBJ(objNum) );
2754
objRep = ELM_PLIST(objNums,rp);
2755
objRep = ELM_PLIST(objTable2,INT_INTOBJ(objRep));
2756
SET_ELM_PLIST( objRep, rc, tmp );
2757
2758
if ( dedlst == dedSize ) {
2759
CompressDeductionList();
2760
}
2761
dedgen[dedlst] = INT_INTOBJ( ELM_PLIST(objNums,lp) );
2762
dedcos[dedlst] = lc;
2763
dedlst++;
2764
}
2765
2766
}
2767
2768
}
2769
dedfst++;
2770
}
2771
2772
SET_ELM_PLIST( list, 6, INTOBJ_INT(firstFree) );
2773
SET_ELM_PLIST( list, 7, INTOBJ_INT(lastFree) );
2774
SET_ELM_PLIST( list, 8, INTOBJ_INT(firstDef) );
2775
SET_ELM_PLIST( list, 9, INTOBJ_INT(lastDef) );
2776
if ( treeType == 1 ) {
2777
SET_ELM_PLIST( list, 16, objExponent );
2778
}
2779
2780
/* clean out */
2781
CleanOut();
2782
2783
return INTOBJ_INT(nrdel);
2784
}
2785
2786
2787
/****************************************************************************
2788
**
2789
*F FuncStandardizeTable2C(<self>,<table>,<table2>,<stan>) . standardize ACT
2790
**
2791
** This is the kernel routine for standardizing an augmented coset table. It
2792
** is called by the GAP routine 'StandardizeTable2'. The user should not
2793
** call the kernel routine but only the GAP routine.
2794
**
2795
** If <stan> = 1 the table is standardized using the (old) semilenlex
2796
** standard.
2797
** If not <stan> = 1 the table is standardized using the (new) lenlex
2798
** standard (this is the default).
2799
*/
2800
Obj FuncStandardizeTable2C (
2801
Obj self,
2802
Obj list,
2803
Obj list2,
2804
Obj stan )
2805
{
2806
Obj * ptTable; /* pointer to table */
2807
Obj * ptTabl2; /* pointer to coset factor table */
2808
UInt nrgen; /* number of rows of the table / 2 */
2809
Obj * g; /* one generator list from table */
2810
Obj * h; /* generator list */
2811
Obj * i; /* and inverse */
2812
Obj * h2; /* corresponding factor lists */
2813
Obj * i2; /* and inverse */
2814
UInt acos; /* actual coset */
2815
UInt lcos; /* last seen coset */
2816
UInt mcos; /* */
2817
UInt c1, c2; /* coset temporaries */
2818
Obj tmp; /* temporary for swap */
2819
UInt j, k, nloop; /* loop variables */
2820
2821
/* get the arguments */
2822
objTable = list;
2823
if ( ! IS_PLIST(objTable) ) {
2824
ErrorQuit( "<table> must be a plain list (not a %s)",
2825
(Int)TNAM_OBJ(objTable), 0L );
2826
return 0;
2827
}
2828
ptTable = &(ELM_PLIST(objTable,1)) - 1;
2829
nrgen = LEN_PLIST(objTable) / 2;
2830
for ( j = 1; j <= nrgen*2; j++ ) {
2831
if ( ! IS_PLIST(ptTable[j]) ) {
2832
ErrorQuit(
2833
"<table>[%d] must be a plain list (not a %s)",
2834
(Int)j,
2835
(Int)TNAM_OBJ(ptTable[j]) );
2836
return 0;
2837
}
2838
}
2839
objTable2 = list2;
2840
if ( ! IS_PLIST(objTable2) ) {
2841
ErrorQuit( "<table2> must be a plain list (not a %s)",
2842
(Int)TNAM_OBJ(objTable), 0L );
2843
return 0;
2844
}
2845
ptTabl2 = &(ELM_PLIST(objTable2,1)) - 1;
2846
if ( IS_INTOBJ(stan) && INT_INTOBJ(stan) == 1 ) {
2847
/* use semilenlex standard */
2848
nloop = nrgen;
2849
}
2850
else {
2851
/* use lenlex standard */
2852
nloop = nrgen*2;
2853
}
2854
2855
/* run over all cosets */
2856
acos = 1;
2857
lcos = 1;
2858
while ( acos <= lcos ) {
2859
2860
/* scan through all columns of acos */
2861
for ( j = 1; j <= nloop; j++ ) {
2862
k = ( nloop == nrgen ) ? 2*j - 1 : j;
2863
g = &(ELM_PLIST(ptTable[k],1)) - 1;
2864
2865
/* if we haven't seen this coset yet */
2866
if ( lcos+1 < INT_INTOBJ( g[acos] ) ) {
2867
2868
/* swap rows lcos and g[acos] */
2869
lcos = lcos + 1;
2870
mcos = INT_INTOBJ( g[acos] );
2871
for ( k = 1; k <= nrgen; k++ ) {
2872
h = &(ELM_PLIST(ptTable[2*k-1],1)) - 1;
2873
i = &(ELM_PLIST(ptTable[2*k],1)) - 1;
2874
h2 = &(ELM_PLIST(ptTabl2[2*k-1],1)) - 1;
2875
i2 = &(ELM_PLIST(ptTabl2[2*k],1)) - 1;
2876
c1 = INT_INTOBJ( h[lcos] );
2877
c2 = INT_INTOBJ( h[mcos] );
2878
if ( c1 != 0 ) i[c1] = INTOBJ_INT( mcos );
2879
if ( c2 != 0 ) i[c2] = INTOBJ_INT( lcos );
2880
tmp = h[lcos];
2881
h[lcos] = h[mcos];
2882
h[mcos] = tmp;
2883
tmp = h2[lcos];
2884
h2[lcos] = h2[mcos];
2885
h2[mcos] = tmp;
2886
if ( i != h ) {
2887
c1 = INT_INTOBJ( i[lcos] );
2888
c2 = INT_INTOBJ( i[mcos] );
2889
if ( c1 != 0 ) h[c1] = INTOBJ_INT( mcos );
2890
if ( c2 != 0 ) h[c2] = INTOBJ_INT( lcos );
2891
tmp = i[lcos];
2892
i[lcos] = i[mcos];
2893
i[mcos] = tmp;
2894
tmp = i2[lcos];
2895
i2[lcos] = i2[mcos];
2896
i2[mcos] = tmp;
2897
}
2898
}
2899
2900
}
2901
2902
/* if this is already the next only bump lcos */
2903
else if ( lcos < INT_INTOBJ( g[acos] ) ) {
2904
lcos = lcos + 1;
2905
}
2906
2907
}
2908
2909
acos = acos + 1;
2910
}
2911
2912
/* shrink the tables */
2913
for ( j = 1; j <= nrgen; j++ ) {
2914
SET_LEN_PLIST( ptTable[2*j-1], lcos );
2915
SET_LEN_PLIST( ptTable[2*j ], lcos );
2916
SET_LEN_PLIST( ptTabl2[2*j-1], lcos );
2917
SET_LEN_PLIST( ptTabl2[2*j ], lcos );
2918
}
2919
2920
/* return void */
2921
return 0;
2922
}
2923
2924
2925
/****************************************************************************
2926
**
2927
*F FuncAddAbelianRelator( <hdCall> ) . . . . . . internal 'AddAbelianRelator'
2928
**
2929
** 'FuncAddAbelianRelator' implements 'AddAbelianRelator(<rels>,<number>)'
2930
*/
2931
Obj FuncAddAbelianRelator (
2932
Obj self,
2933
Obj rels, /* relators list */
2934
Obj number )
2935
{
2936
Obj * ptRels; /* pointer to relators list */
2937
Obj * pt1; /* pointer to a relator */
2938
Obj * pt2; /* pointer to another relator */
2939
Obj tmp;
2940
Int numcols; /* list length of the rel vectors */
2941
Int numrows; /* number of relators */
2942
Int i, j; /* loop variables */
2943
2944
/* check the arguments */
2945
if ( ! IS_PLIST(rels) ) {
2946
ErrorQuit( "<rels> must be a plain list (not a %s)",
2947
(Int)TNAM_OBJ(rels), 0L );
2948
return 0;
2949
}
2950
ptRels = &(ELM_PLIST(rels,1)) - 1;
2951
if ( TNUM_OBJ(number) != T_INT ) {
2952
ErrorQuit( "<number> must be a small integer (not a %s)",
2953
(Int)TNAM_OBJ(number), 0L );
2954
return 0;
2955
}
2956
2957
/* get the length of the given relators list */
2958
numrows = INT_INTOBJ(number);
2959
if ( numrows < 1 || LEN_PLIST(rels) < numrows ) {
2960
ErrorQuit( "inconsistent relator number", 0L, 0L );
2961
return 0;
2962
}
2963
tmp = ELM_PLIST( rels, numrows );
2964
if ( tmp == 0 ) {
2965
ErrorQuit( "inconsistent relator number", 0L, 0L );
2966
return 0;
2967
}
2968
pt2 = &(ELM_PLIST(tmp,1)) - 1;
2969
2970
/* get the length of the exponent vectors (the number of generators) */
2971
numcols = LEN_PLIST(tmp);
2972
2973
/* remove the last relator if it has length zero */
2974
for ( i = 1; i <= numcols; i++ ) {
2975
if ( INT_INTOBJ(pt2[i]) ) {
2976
break;
2977
}
2978
}
2979
if ( i > numcols ) {
2980
return INTOBJ_INT(numrows-1);
2981
}
2982
2983
/* invert the relator if its first non-zero exponent is negative */
2984
if ( INT_INTOBJ(pt2[i]) < 0 ) {
2985
for ( j = i; j <= numcols; j++ ) {
2986
pt2[j] = INTOBJ_INT( -INT_INTOBJ( pt2[j] ) );
2987
}
2988
}
2989
2990
/* if the last relator occurs twice, remove one of its occurrences */
2991
for ( i = 1; i < numrows; i++ ) {
2992
pt1 = &(ELM_PLIST(ptRels[i],1)) - 1;
2993
for ( j = 1; j <= numcols; j++ ) {
2994
if ( pt1[j] != pt2[j] ) {
2995
break;
2996
}
2997
}
2998
if ( j > numcols ) {
2999
break;
3000
}
3001
}
3002
if ( i < numrows ) {
3003
for ( i = 1; i <= numcols; i++ ) {
3004
pt2[i] = INTOBJ_INT(0);
3005
}
3006
numrows = numrows - 1;
3007
}
3008
3009
return INTOBJ_INT( numrows );
3010
}
3011
3012
/* new type functions that use different data structures */
3013
3014
UInt ret1,ret2;
3015
3016
UInt RelatorScan (
3017
Obj t,
3018
UInt di,
3019
Obj r )
3020
{
3021
UInt m,i,p,a,j;
3022
UInt pa=0,pb=0;
3023
UInt * rp;
3024
rp=(UInt*)ADDR_OBJ(r);
3025
m=rp[1]; /* length is in position 1 */
3026
i=2;
3027
p=di;
3028
while ((p!=0) && (i<=(m+1))){
3029
a=rp[i];
3030
pa=p;
3031
p=INT_INTOBJ(ELM_PLIST(ELM_PLIST(t,a),p));
3032
if (p!=0) i++;
3033
}
3034
3035
if (i>(m+1)) {
3036
if (p==di)
3037
return 1;
3038
else
3039
return 0;
3040
}
3041
3042
/* backwards scan */
3043
j=m+1;
3044
p=di;
3045
while ((p!=0) && (j>=i)) {
3046
/* a=INT_INTOBJ(ELM_PLIST(invtab,INT_INTOBJ(ELM_PLIST(r,j))));*/
3047
3048
a=rp[j];
3049
if ((a%2)==1)
3050
a++;
3051
else
3052
a--;
3053
pb=p;
3054
p=INT_INTOBJ(ELM_PLIST(ELM_PLIST(t,a),p));
3055
if (p!=0) j--;
3056
}
3057
3058
if (j<i) {
3059
if (p==pa)
3060
return 1;
3061
else
3062
return 0;
3063
}
3064
else {
3065
if (j==i) {
3066
a=rp[i];
3067
if ((a%2)==0) {
3068
p=a-1;
3069
ret1=pb;
3070
ret2=p;
3071
}
3072
else {
3073
p=a+1;
3074
ret1=pa;
3075
ret2=a;
3076
}
3077
SET_ELM_PLIST(ELM_PLIST(t,a),pa,INTOBJ_INT(pb));
3078
SET_ELM_PLIST(ELM_PLIST(t,p),pb,INTOBJ_INT(pa));
3079
3080
return 2;
3081
}
3082
else
3083
return 1;
3084
}
3085
3086
}
3087
3088
/* data object type for the mangled relators */
3089
Obj TYPE_LOWINDEX_DATA;
3090
3091
/****************************************************************************
3092
**
3093
*F FuncLOWINDEX_COSET_SCAN( <t>,<r>,<s1>,<s2>)
3094
**
3095
*/
3096
Obj FuncLOWINDEX_COSET_SCAN (
3097
Obj self,
3098
Obj t, /* table */
3099
Obj r, /* relators */
3100
Obj s1, /* stack */
3101
Obj s2 ) /* stack */
3102
{
3103
UInt ok,i,j,d,e,x,y,l,sd;
3104
Obj rx;
3105
UInt * s1a;
3106
UInt * s2a;
3107
3108
ok=1;
3109
j=1;
3110
/* we convert stack entries to c-integers to avoid conversion */
3111
sd=LEN_PLIST(s1);
3112
s1a=(UInt*)ADDR_OBJ(s1);
3113
s2a=(UInt*)ADDR_OBJ(s2);
3114
s1a[1]=INT_INTOBJ(s1a[1]);
3115
s2a[1]=INT_INTOBJ(s2a[1]);
3116
while ((ok==1) && (j>0)) {
3117
d=s1a[j];
3118
x=s2a[j];
3119
j--;
3120
rx=ELM_PLIST(r,x);
3121
l=LEN_PLIST(rx);
3122
i=1;
3123
while ((ok==1)&&(i<=l)) {
3124
ok=RelatorScan(t,d,ELM_PLIST(rx,i));
3125
if (ok==2) {
3126
j++;
3127
if (j>sd) {
3128
sd=2*sd;
3129
GROW_PLIST(s1,sd);
3130
SET_LEN_PLIST(s1,sd);
3131
CHANGED_BAG(s1);
3132
GROW_PLIST(s2,sd);
3133
SET_LEN_PLIST(s2,sd);
3134
CHANGED_BAG(s2);
3135
s1a=(UInt*)ADDR_OBJ(s1);
3136
s2a=(UInt*)ADDR_OBJ(s2);
3137
}
3138
s1a[j]=ret1;
3139
s2a[j]=ret2;
3140
ok=1;
3141
}
3142
i++;
3143
}
3144
3145
e=INT_INTOBJ(ELM_PLIST(ELM_PLIST(t,x),d));
3146
y=x+1;
3147
rx=ELM_PLIST(r,y);
3148
i=1;
3149
while ((ok==1)&&(i<=l)) {
3150
ok=RelatorScan(t,e,ELM_PLIST(rx,i));
3151
if (ok==2) {
3152
j++;
3153
if (j>sd) {
3154
sd=2*sd;
3155
GROW_PLIST(s1,sd);
3156
GROW_PLIST(s2,sd);
3157
s1a=(UInt*)ADDR_OBJ(s1);
3158
s2a=(UInt*)ADDR_OBJ(s2);
3159
}
3160
s1a[j]=ret1;
3161
s2a[j]=ret2;
3162
ok=1;
3163
}
3164
i++;
3165
}
3166
}
3167
/* clean up the mess we made */
3168
for (i=1;i<=sd;i++) {
3169
s1a[i]=(Int)INTOBJ_INT(0);
3170
s2a[i]=(Int)INTOBJ_INT(0);
3171
}
3172
if (ok==1)
3173
return True;
3174
else
3175
return False;
3176
}
3177
3178
/****************************************************************************
3179
**
3180
*F FuncLOWINDEX_IS_FIRST( <t>,<n>,<mu>,<nu>)
3181
**
3182
*/
3183
Obj FuncLOWINDEX_IS_FIRST (
3184
Obj self,
3185
Obj t, /* table */
3186
Obj nobj, /* relators */
3187
Obj muo, /* stack */
3188
Obj nuo ) /* stack */
3189
{
3190
UInt l,ok,b,g,ga,de,a,n,mm;
3191
UInt * mu;
3192
UInt * nu;
3193
3194
mm=LEN_PLIST(t)-1;
3195
n=INT_INTOBJ(nobj);
3196
mu=(UInt*)ADDR_OBJ(muo);
3197
nu=(UInt*)ADDR_OBJ(nuo);
3198
for (b=1;b<=n;nu[b++]=0);
3199
l=0;
3200
for (a=2;a<=n;a++) {
3201
for (b=1;b<=l;nu[mu[b++]]=0);
3202
mu[1]=a;
3203
nu[a]=1;
3204
l=1;
3205
ok=1;
3206
b=1;
3207
while ((ok==1) && (b<=n)) {
3208
g=1;
3209
while ((ok==1)&&(g<=mm)) {
3210
ga=INT_INTOBJ(ELM_PLIST(ELM_PLIST(t,g),b));
3211
de=INT_INTOBJ(ELM_PLIST(ELM_PLIST(t,g),mu[b]));
3212
if ((ga==0)||(de==0))
3213
ok=0;
3214
else {
3215
if (nu[de]==0) {
3216
l++;
3217
mu[l]=de;
3218
nu[de]=l;
3219
}
3220
if (nu[de]<ga)
3221
return False;
3222
else {
3223
if (nu[de]>ga) {
3224
ok=0;
3225
}
3226
}
3227
}
3228
g=g+2;
3229
}
3230
b=b+1;
3231
}
3232
}
3233
return True;
3234
}
3235
3236
/****************************************************************************
3237
**
3238
*F FuncLOWINDEX_PREPARE_RELS( <rels> )
3239
**
3240
*/
3241
Obj FuncLOWINDEX_PREPARE_RELS (
3242
Obj self,
3243
Obj r ) /* rels */
3244
{
3245
UInt i,j,k,l;
3246
Obj ri, rel;
3247
UInt * rp;
3248
3249
for (i=1;i<=LEN_PLIST(r);i++) {
3250
ri=ELM_PLIST(r,i);
3251
for (j=1;j<=LEN_PLIST(ri);j++) {
3252
rel=ELM_PLIST(ri,j); /* single relator */
3253
l=LEN_PLIST(rel);
3254
rp=(UInt*)ADDR_OBJ(rel);
3255
for (k=1;k<=l;k++)
3256
rp[k]=INT_INTOBJ(rp[k]); /* convert relator entries to C-integers */
3257
/* change type */
3258
TYPE_DATOBJ(rel) = TYPE_LOWINDEX_DATA;
3259
RetypeBag(rel,T_DATOBJ);
3260
3261
}
3262
}
3263
return (Obj) 0;
3264
}
3265
3266
/****************************************************************************
3267
**
3268
3269
*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
3270
*/
3271
3272
/****************************************************************************
3273
**
3274
3275
*V GVarFuncs . . . . . . . . . . . . . . . . . . list of functions to export
3276
*/
3277
static StructGVarFunc GVarFuncs [] = {
3278
3279
{ "ApplyRel", 2, "app, relator",
3280
FuncApplyRel, "src/costab.c:ApplyRel" },
3281
3282
{ "MakeConsequences", 1, "list",
3283
FuncMakeConsequences, "src/costab.c:MakeConsequences" },
3284
3285
{ "MakeConsequencesPres", 1, "list",
3286
FuncMakeConsequencesPres, "src/costab.c:MakeConsequencesPres" },
3287
3288
{ "StandardizeTableC", 2, "table, standard",
3289
FuncStandardizeTableC, "src/costab.c:StandardizeTableC" },
3290
3291
{ "ApplyRel2", 3, "app, relators, nums",
3292
FuncApplyRel2, "src/costab.c:ApplyRel2" },
3293
3294
{ "CopyRel", 1, "relator",
3295
FuncCopyRel, "src/costab.c:CopyRel" },
3296
3297
{ "MakeCanonical", 1, "relator",
3298
FuncMakeCanonical, "src/costab.c:MakeCanonical" },
3299
3300
{ "TreeEntry", 2, "relator, word",
3301
FuncTreeEntry, "src/costab.c:TreeEntry" },
3302
3303
{ "MakeConsequences2", 1, "list",
3304
FuncMakeConsequences2, "src/costab.c:MakeConsequences2" },
3305
3306
{ "StandardizeTable2C", 3, "table, table, standard",
3307
FuncStandardizeTable2C, "src/costab.c:StandardizeTable2C" },
3308
3309
{ "AddAbelianRelator", 2, "rels, number",
3310
FuncAddAbelianRelator, "src/costab.c:AddAbelianRelator" },
3311
3312
{ "LOWINDEX_COSET_SCAN", 4, "table, relators, stack1,stack2",
3313
FuncLOWINDEX_COSET_SCAN, "src/costab.c:LOWINDEX_COSET_SCAN" },
3314
3315
{ "LOWINDEX_IS_FIRST", 4, "table, n, mu, nu",
3316
FuncLOWINDEX_IS_FIRST, "src/costab.c:LOWINDEX_IS_FIRST" },
3317
3318
{ "LOWINDEX_PREPARE_RELS", 1, "rels",
3319
FuncLOWINDEX_PREPARE_RELS, "src/costab.c:LOWINDEX_PREPARE_RELS" },
3320
3321
{ 0 }
3322
3323
};
3324
3325
3326
/****************************************************************************
3327
**
3328
3329
*F InitKernel( <module> ) . . . . . . . . initialise kernel data structures
3330
*/
3331
static Int InitKernel (
3332
StructInitInfo * module )
3333
{
3334
/* init filters and functions */
3335
InitHdlrFuncsFromTable( GVarFuncs );
3336
3337
/* import kind (and unkind) functions */
3338
ImportGVarFromLibrary( "TYPE_LOWINDEX_DATA",&TYPE_LOWINDEX_DATA );
3339
3340
/* static variables */
3341
InitGlobalBag( &objRel , "src/costab.c:objRel" );
3342
InitGlobalBag( &objNums , "src/costab.c:objNums" );
3343
InitGlobalBag( &objFactor , "src/costab.c:objFactor" );
3344
InitGlobalBag( &objTable , "src/costab.c:objTable" );
3345
InitGlobalBag( &objTable2 , "src/costab.c:objTable2" );
3346
InitGlobalBag( &objNext , "src/costab.c:objNext" );
3347
InitGlobalBag( &objPrev , "src/costab.c:objPrev" );
3348
InitGlobalBag( &objTree , "src/costab.c:objTree" );
3349
InitGlobalBag( &objTree1 , "src/costab.c:objTree1" );
3350
InitGlobalBag( &objTree2 , "src/costab.c:objTree2" );
3351
InitGlobalBag( &objWordValue, "src/costab.c:objWordValue" );
3352
InitGlobalBag( &objExponent , "src/costab.c:objExponent" );
3353
3354
/* return success */
3355
return 0;
3356
}
3357
3358
3359
/****************************************************************************
3360
**
3361
*F InitLibrary( <module> ) . . . . . . . initialise library data structures
3362
*/
3363
static Int InitLibrary (
3364
StructInitInfo * module )
3365
{
3366
/* init filters and functions */
3367
InitGVarFuncsFromTable( GVarFuncs );
3368
3369
/* return success */
3370
return 0;
3371
}
3372
3373
3374
/****************************************************************************
3375
**
3376
*F InitInfoCosetTable() . . . . . . . . . . . . . . table of init functions
3377
*/
3378
static StructInitInfo module = {
3379
MODULE_BUILTIN, /* type */
3380
"costab", /* name */
3381
0, /* revision entry of c file */
3382
0, /* revision entry of h file */
3383
0, /* version */
3384
0, /* crc */
3385
InitKernel, /* initKernel */
3386
InitLibrary, /* initLibrary */
3387
0, /* checkInit */
3388
0, /* preSave */
3389
0, /* postSave */
3390
0 /* postRestore */
3391
};
3392
3393
StructInitInfo * InitInfoCosetTable ( void )
3394
{
3395
return &module;
3396
}
3397
3398
3399
/****************************************************************************
3400
**
3401
3402
*E costab.c . . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
3403
*/
3404
3405