Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
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
Project: cocalc-sagemath-dev-slelievre
Views: 4183461/**************************************************************************23util1.c4Colin Ramsay ([email protected])522 Dec 0067ADVANCED COSET ENUMERATOR, Version 3.00189Copyright 200010Centre for Discrete Mathematics and Computing,11Department of Mathematics and12Department of Computer Science & Electrical Engineering,13The University of Queensland, QLD 4072.14(http://staff.itee.uq.edu.au/havas)1516These are the utilities for Level 1 of ACE.1718**************************************************************************/1920#include "al1.h"2122#include <ctype.h>2324/******************************************************************25void al1_init(void)2627One-off initialisation of the Level 1 stuff, and all lower levels.28Note that there is no need to initialise, for example, genal[].29******************************************************************/3031void al1_init(void)32{33al0_init();3435workspace = DEFWORK;36workmult = 1;37costable = NULL;38tabsiz = 0;3940currrep = NULL;41repsiz = repsp = 0;4243asis = FALSE;4445grpname = NULL;46rellst = NULL;47trellen = 0;4849ndgen = 0;50geninv = NULL;51gencol = colgen = NULL;52galpha = FALSE;53algen[0] = algen[1] = '\0'; /* &algen[1] is printable string */5455subgrpname = NULL;56genlst = NULL;57tgenlen = 0;5859rfactor1 = cfactor1 = 0;60pdsiz1 = dedsiz1 = 0;61maxrow1 = ffactor1 = 0;62nrinsgp1 = -1;63}6465/******************************************************************66void al1_dump(Logic allofit)6768Dump out the internals of Level 1 of ACE, working through al1.h69more or less in order.70******************************************************************/7172void al1_dump(Logic allofit)73{74int i;75Wlelt *p;7677fprintf(fop, " #---- %s: Level 1 Dump ----\n", ACE_VER);7879/* workspace, workmult, costable, tabsiz; */80fprintf(fop, "workspace=%d workmult=%d", workspace, workmult);81if (costable == NULL)82{ fprintf(fop, " costable=NULL"); }83else84{ fprintf(fop, " costable=non-NULL"); }85fprintf(fop, " tabsiz=%d\n", tabsiz);8687/* currrep, repsiz, repsp; */88if (currrep == NULL)89{ fprintf(fop, "currrep=NULL"); }90else91{ fprintf(fop, "currrep=non-NULL"); }92fprintf(fop, " repsiz=%d repsp=%d\n", repsiz, repsp);9394/* LLL, asis */95fprintf(fop, "LLL=%d, asis=%d\n", LLL, asis);9697/* group: name, generators, geninv */98if (grpname == NULL)99{ fprintf(fop, "grpname=NULL\n"); }100else101{ fprintf(fop, "grpname=%s\n", grpname); }102103if (ndgen == 0)104{ fprintf(fop, "ndgen=%d\n", ndgen); }105else if (galpha)106{107fprintf(fop, "ndgen=%d galpha=%d algen[]=", ndgen, galpha);108for (i = 1; i <= ndgen; i++)109{ fprintf(fop, "%c", algen[i]); }110fprintf(fop, "\n");111112if (allofit)113{114fprintf(fop, " genal[]=");115for (i = 1; i <= 26; i++)116{ fprintf(fop, "%d ", genal[i]); }117fprintf(fop, "\n");118}119}120else121{ fprintf(fop, "ndgen=%d galpha=%d\n", ndgen, galpha); }122123if (geninv == NULL)124{ fprintf(fop, "geninv=NULL\n"); }125else126{127fprintf(fop, "geninv[]=");128for (i = 1; i <= ndgen; i++)129{ fprintf(fop, "%d ", geninv[i]); }130fprintf(fop, "\n");131}132133/* gencol, colgen */134if (gencol == NULL)135{ fprintf(fop, "gencol=NULL\n"); }136else137{138fprintf(fop, "gencol[]=");139for (i = -ndgen; i <= -1; i++)140{ fprintf(fop, "%d ", gencol[ndgen+i]); }141fprintf(fop, "x ");142for (i = 1; i <= ndgen; i++)143{ fprintf(fop, "%d ", gencol[ndgen+i]); }144fprintf(fop, "\n");145}146if (colgen == NULL)147{ fprintf(fop, "colgen=NULL\n"); }148else149{150fprintf(fop, "colgen[]=");151for (i = 1; i <= ncol; i++)152{ fprintf(fop, "%d ", colgen[i]); }153fprintf(fop, "\n");154}155156/* group relators + trellen */157if (rellst == NULL)158{ fprintf(fop, "rellst=NULL trellen=%d\n", trellen); }159else if (rellst->len == 0)160{ fprintf(fop, "rellst->len=0 trellen=%d\n", trellen); }161else162{163fprintf(fop, "rellst->len=%d trellen=%d\n", rellst->len, trellen);164if (allofit)165{166fprintf(fop, " len exp inv word\n");167for (p = rellst->first; ; p = p->next)168{169fprintf(fop, " %3d %3d %3d ", p->len, p->exp, p->invol);170for (i = 1; i <= p->len; i++)171{ fprintf(fop, "%d ", p->word[i]); }172fprintf(fop, "\n");173174if (p == rellst->last)175{ break; }176}177}178}179180/* subgroup: name */181if (subgrpname == NULL)182{ fprintf(fop, "subgrpname=NULL\n"); }183else184{ fprintf(fop, "subgrpname=%s\n", subgrpname); }185186/* subgroup generators + tgenlen */187if (genlst == NULL)188{ fprintf(fop, "genlst=NULL tgenlen=%d\n", tgenlen); }189else if (genlst->len == 0)190{ fprintf(fop, "genlst->len=0 tgenlen=%d\n", tgenlen); }191else192{193fprintf(fop, "genlst->len=%d tgenlen=%d\n", genlst->len, tgenlen);194if (allofit)195{196fprintf(fop, " len exp inv word\n");197for (p = genlst->first; ; p = p->next)198{199fprintf(fop, " %3d %3d %3d ", p->len, p->exp, p->invol);200for (i = 1; i <= p->len; i++)201{ fprintf(fop, "%d ", p->word[i]); }202fprintf(fop, "\n");203204if (p == genlst->last)205{ break; }206}207}208}209210/* rfactor1, cfactor1 */211fprintf(fop, "rfactor1=%d cfactor1=%d\n", rfactor1, cfactor1);212213/* pdsiz1, dedsiz1 */214fprintf(fop, "pdsiz1=%d dedsiz1=%d\n", pdsiz1, dedsiz1);215216/* maxrow1, ffactor1, nrinsgp1 */217fprintf(fop, "maxrow1=%d ffactor1=%d nrinsgp1=%d\n",218maxrow1, ffactor1, nrinsgp1);219220fprintf(fop, " #---------------------------------\n");221}222223/******************************************************************224void al1_prtdetails(int bits)225226This prints out details of the Level 0 & 1 settings, in a form227suitable for reading in by applications using the core enumerator228plus its wrapper (eg, ACE Level 2). If bits is 0, then enum, rel,229subg & gen are printed. If 1 then *all* of the presentation and230the enumerator control settings (this allows the run to be231duplicated at a later date). If bits is 2-5, then only enum, rel,232subg & gen, respectively, are printed. This routine is really233intended for the ACE Level 2 interface, where some items cannot be234examined by invoking them with an empty argument. However it is235put here (at Level 1), since it is a useful utility for any236application.237238If messaging in on, this routine (with bits 1) is called by239al1_start() after all the setup & just before the call to240al0_enum(). So it shows what the parameters actually were. They241may not match what you thought they were, since the Level 1 wrapper242(which interfaces between applications (ie, ACE's Level 2243interactive interface) and the Level 0 enumerator) trys to prevent244errors, and may occasionally ignore or change something. If you245call this after changing parameters, but before calling _start(),246the values do *not* reflect the new values. If you want to see247what the Level 2 parameters are (as opposed to the current Level 0248parameters), use the `empty argument' form of the commands, or the249"sr;" Level 2 command (which invokes this function with bits250false.251252To *exactly* duplicate a run, you may need to duplicate the entire253sequence of commands since ACE was started, the execution254environment, and use the same executable; but that's a project for255some rainy Sunday afternoon sometime in the future. However do256note that the allocation of generators to columns may have upset257your intended handling of involutions and/or the ordering of the258generators; do a (full) Level 0/1 dump to check this, if you care!259In particular, the value of asis is the *current* value, which may260not match that when the call to _start() which allocated columns &261determined which generators will be involutions was made.262******************************************************************/263264void al1_prtdetails(int bits)265{266if (bits < 2)267{ fprintf(fop, " #--- %s: Run Parameters ---\n", ACE_VER); }268269if (bits == 0 || bits == 1 || bits == 2)270{271if (grpname != NULL)272{ fprintf(fop, "Group Name: %s;\n", grpname); }273else274{ fprintf(fop, "Group Name: ;\n"); }275}276277if (bits == 1)278{279if (ndgen > 0)280{281fprintf(fop, "Group Generators: ");282if (!galpha)283{ fprintf(fop, "%d", ndgen); }284else285{ fprintf(fop, "%s", &algen[1]); }286fprintf(fop, ";\n");287}288}289290if (bits == 0 || bits == 1 || bits == 3)291{292if (rellst != NULL)293{294fprintf(fop, "Group Relators: ");295al1_prtwl(rellst, 16);296fprintf(fop, ";\n");297}298else299{ fprintf(fop, "Group Relators: ;\n"); }300}301302if (bits == 0 || bits == 1 || bits == 4)303{304if (subgrpname != NULL)305{ fprintf(fop, "Subgroup Name: %s;\n", subgrpname); }306else307{ fprintf(fop, "Subgroup Name: ;\n"); }308}309310if (bits == 0 || bits == 1 || bits == 5)311{312if (genlst != NULL)313{314fprintf(fop, "Subgroup Generators: ");315al1_prtwl(genlst, 21);316fprintf(fop, ";\n");317}318else319{ fprintf(fop, "Subgroup Generators: ;\n"); }320}321322if (bits == 1)323{324switch (workmult)325{326case 1:327fprintf(fop, "Wo:%d;", workspace);328break;329case KILO:330fprintf(fop, "Wo:%dK;", workspace);331break;332case MEGA:333fprintf(fop, "Wo:%dM;", workspace);334break;335case GIGA:336fprintf(fop, "Wo:%dG;", workspace);337break;338}339fprintf(fop, " Max:%d;", maxrow);340if (msgctrl)341{342if (msghol)343{ fprintf(fop, " Mess:-%d;", msgincr); }344else345{ fprintf(fop, " Mess:%d;", msgincr); }346}347else348{ fprintf(fop, " Mess:0;"); }349fprintf(fop, " Ti:%d; Ho:%d; Loop:%d;\n", tlimit, hlimit, llimit);350351if (asis)352{ fprintf(fop, "As:1;"); }353else354{ fprintf(fop, "As:0;"); }355if (pcomp)356{ fprintf(fop, " Path:1;"); }357else358{ fprintf(fop, " Path:0;"); }359if (rfill)360{ fprintf(fop, " Row:1;"); }361else362{ fprintf(fop, " Row:0;"); }363if (mendel)364{ fprintf(fop, " Mend:1;"); }365else366{ fprintf(fop, " Mend:0;"); }367fprintf(fop, " No:%d; Look:%d; Com:%d;\n", nrinsgp, lahead, comppc);368369/* Note that we printout using the aliases, since we want to know (or,370at least, be able to deduce) what style was used. Note that, although371ffactor is a float, the Level 1 (& Level 2) interfaces use ffactor1,372which is an int. So we need to convert for printout, to maintain the373ability to read the output back in. */374375fprintf(fop, "C:%d; R:%d; Fi:%d;", cfactor1, rfactor1, (int)ffactor);376fprintf(fop, " PMod:%d; PSiz:%d; DMod:%d;", pdefn, pdsiz, dedmode);377fprintf(fop, " DSiz:%d;\n", dedsiz);378}379380if (bits < 2)381{ fprintf(fop, " #---------------------------------\n"); }382}383384/******************************************************************385void al1_rslt(int rslt)386387Pretty-print the result of a run of al1_start(). If there were no388problems at Level 1, this will just be the result of the call to389al0_enum(), printed via al0_rslt().390******************************************************************/391392void al1_rslt(int rslt)393{394if (rslt > -8192)395{ al0_rslt(rslt); }396else397{398switch(rslt)399{400case -8194: fprintf(fop, "TABLE TOO SMALL\n"); break;401case -8193: fprintf(fop, "MEMORY PROBLEM\n"); break;402case -8192: fprintf(fop, "INVALID MODE\n"); break;403default: fprintf(fop, "UNKNOWN ERROR (%d)\n", rslt); break;404}405}406}407408/**************************************************************************409These are the utilities for the simple list manipulation package used to410handle the group's relators & the subgroup's generators. Note that it is411up to the caller to catch any errors (flagged by the return values).412**************************************************************************/413414/******************************************************************415Wlist *al1_newwl(void)416417Creates a new (empty) word list. Returns NULL on failure.418******************************************************************/419420Wlist *al1_newwl(void)421{422Wlist *p = (Wlist *)malloc(sizeof(Wlist));423424if (p != NULL)425{426p->len = 0;427p->first = p->last = NULL;428}429430return(p);431}432433/******************************************************************434Wlelt *al1_newelt(void)435436Creates a new (empty) word-list element. Returns NULL on failure.437******************************************************************/438439Wlelt *al1_newelt(void)440{441Wlelt *p = (Wlelt *)malloc(sizeof(Wlelt));442443if (p != NULL)444{445p->word = NULL;446p->len = p->exp = 0;447p->invol = FALSE;448p->next = NULL;449}450451return(p);452}453454/******************************************************************455void al1_addwl(Wlist *l, Wlelt *w)456457Adds a word (if it's non-null & non-empty) to a word list. l must458be non-null, but may be empty.459******************************************************************/460461void al1_addwl(Wlist *l, Wlelt *w)462{463if (w == NULL || w->len == 0) /* ignore null/empty words */464{ return; }465466if (l->len == 0)467{ l->first = w; } /* add word to start of list */468else469{ l->last->next = w; } /* add word to end of list */470471l->last = w;472l->len++;473}474475/******************************************************************476void al1_concatwl(Wlist *l, Wlist *m);477478Concatenate m's list to l's, and delete m's header node. Note that479l is guaranteed non-null, but may be empty. m may be null, empty,480or contain data.481******************************************************************/482483void al1_concatwl(Wlist *l, Wlist *m)484{485if (m == NULL)486{ return; }487else if (m->len == 0)488{489free(m);490return;491}492493/* If we get here, m contains data */494495if (l->len == 0) /* l is empty */496{497l->len = m->len;498l->first = m->first;499l->last = m->last;500}501else /* l is non-empty */502{503l->len += m->len;504l->last->next = m->first;505l->last = m->last;506}507508free(m);509}510511/******************************************************************512void al1_emptywl(Wlist *l)513514Delete the list of words in l, leaving l as an empty list. Does515*not* delete the storage for l.516******************************************************************/517518void al1_emptywl(Wlist *l)519{520Wlelt *p, *q;521522if (l == NULL || l->len == 0)523{ return; }524525for (p = l->first; p != NULL; )526{527q = p->next;528529if (p->word != NULL)530{ free(p->word); }531free(p);532533p = q;534}535536l->len = 0;537l->first = l->last = NULL;538}539540/******************************************************************541void al1_prtwl(Wlist *l, int n)542543Attempt to pretty-print a list of group relators or subgroup544generators within the allowed (i.e., LLL) number of columns. n is545the current output column. (Not quite sure how this would cope546with a really nasty presentation!) Note that this prints out words547in exp form. If no enumeration has yet been run, exp is at its548default of 1, so a printout will not be `exponentiated'. Note that549relators of the form xx are *always* printed out in the form (x)^2550*if* they were entered thus; in all other cases they are printed as551xx. This is to preserve the ability to specify whether or not a552generator should be treated as an involution when asis is true.553554Warning: if the list contains any empty words superfluous commas555may be introduced, rendering the list `invalid' to the Level 2556input parser! If _start() has been called in start/redo mode, then557the relator & generator lists are guaranteed to be free of empty558word (although they may contain duplicates).559******************************************************************/560561void al1_prtwl(Wlist *l, int n)562{563Wlelt *e;564int elen, eexp;565int i, len;566char c;567568if (l == NULL || l->len == 0)569{ return; }570571for (e = l->first; e != NULL; e = e->next)572{573elen = e->len; /* Alias e->len & e->exp ... */574eexp = e->exp;575576if (elen == 2 && e->word[1] == e->word[2])577{ /* ... adjust them if involn */578if (e->invol)579{ eexp = 2; }580else581{ eexp = 1; }582}583584len = elen/eexp;585586if (!galpha)587{ /* numeric generators */588if (eexp == 1)589{590n += 2 + len*2; /* +2 for \ , *2 for \ n */591if (n > LLL)592{593fprintf(fop, "\n ");594n = 2+2 + len*2;595}596}597else598{599n += 2+4 + len*2; /* 4 for ()^e */600if (n > LLL)601{602fprintf(fop, "\n ");603n = 4+4 + len*2;604}605fprintf(fop, "(");606}607608for (i = 1; i <= len; i++)609{ fprintf(fop, "%d ", e->word[i]); }610611if (eexp != 1)612{ fprintf(fop, ")^%d", eexp); }613if (e->next != NULL && len != 0) /* len = 0 not poss? */614{ fprintf(fop, ", "); }615}616else617{ /* alphabetic generators */618if (eexp == 1)619{620n += 2 + len;621if (n > LLL)622{623fprintf(fop, "\n ");624n = 2+1 + len;625}626}627else628{629n += 2+4 + len; /* 4 for ()^x */630if (n > LLL)631{632fprintf(fop, "\n ");633n = 3+4 + len;634}635fprintf(fop, "(");636}637638for (i = 1; i <= len; i++)639{640c = (e->word[i] > 0) ? algen[e->word[i]]641: toupper(algen[-e->word[i]]);642fprintf(fop, "%c", c);643}644645if (eexp != 1)646{ fprintf(fop, ")^%d", eexp); }647if (e->next != NULL && len !=0)648{ fprintf(fop, ", "); }649}650}651}652653/**************************************************************************654These are the utilities for handling coset representatives.655**************************************************************************/656657/******************************************************************658Logic al1_addrep(int col)659660Add #col to the current rep've, possibly extending its storage.661Fails if we can't allocate memory.662******************************************************************/663664Logic al1_addrep(int col)665{666if (currrep == NULL)667{668repsp = 8;669if ((currrep = (int*)malloc(repsp*sizeof(int))) == NULL)670{671repsiz = repsp = 0;672return(FALSE);673}674}675else if (repsiz == repsp) /* current entries are 0..repsiz-1 */676{677repsp *= 2;678if ((currrep = (int*)realloc(currrep, repsp*sizeof(int))) == NULL)679{680repsiz = repsp = 0;681return(FALSE);682}683}684685currrep[repsiz++] = col;686return(TRUE);687}688689/******************************************************************690Logic al1_bldrep(int cos)691692Traces back through the table, building up a rep've of #cos in693currrep. The rep've is in terms of column numbers, and is694guaranteed to be the `canonic' rep've (ie, first in `length + col695order' order) in terms of the *current* table. The table may or696may not be compact/standard. If the table is compact & standard,697then the rep've is guaranteed to be `really' canonic, independant698of the details of the enumeration. Fails if _addrep() fails.699700The order of the columns is *not* constrained in any way (apart701from the col 1/2 stuff), so we have to be careful to pick up the7021st col (ie, scol) in order (*after* they have been inverted) if703more than one entry in a row is minimal.704705Note that our ability to backtrace is predicated on the fact that706the first definition of a coset is always in terms of a lower-707numbered coset, and during coinc processing we keep the lower-708numbered coset & move data from the higher to the lower. So each709coset's row, apart from #1, *must* contain a lower-numbered entry.710In this routine we *assume* that this property of the table has not711been compromised in any way; if it has, then the behaviour is712undefined.713******************************************************************/714715Logic al1_bldrep(int cos)716{717int low, slow, col, scol, i;718719repsiz = 0;720if (cos <= 1 || cos >= nextdf || COL1(cos) < 0)721{ return(TRUE); }722723low = slow = cos;724while (low > 1)725{726scol = 0;727for (col = 1; col <= ncol; col++)728{729if ((i = CT(low,col)) > 0)730{731if (i < slow) /* Lower row number found */732{733slow = i;734scol = col;735}736else if (i == slow && scol != 0) /* Same row & slow < low */737{ /* ... earlier column? */738if (invcol[col] < invcol[scol])739{ scol = col; }740}741}742}743744/* Add it (increases repsiz); note the column inversion! Failure sets745repsiz to 0 */746747if (!al1_addrep(invcol[scol]))748{ return(FALSE); }749750low = slow;751}752753/* Reverse representative (note: inversion already done) */754755for (i = 1; i <= repsiz/2; i++)756{757col = currrep[i-1];758scol = currrep[repsiz-i];759760currrep[i-1] = scol;761currrep[repsiz-i] = col;762}763764return(TRUE);765}766767/******************************************************************768int al1_trrep(int cos)769770Traces currrep, starting at #cos. Returns 0 on redundant cosets,771on empty slot, or if there's no rep've.772******************************************************************/773774int al1_trrep(int cos)775{776int i;777778if (repsiz == 0)779{ return(0); }780781for (i = 0; i < repsiz; i++)782{783if ((COL1(cos) < 0) || ((cos = CT(cos,currrep[i])) == 0))784{ return(0); }785}786787return(cos);788}789790/******************************************************************791int al1_ordrep(void)792793Traces currrep repeatedly until we arrive back at #1, or an empty794slot. The number of times round the loop is the order; return 0 if795the tracing doesn't complete or the rep is empty. Note that796termination is guaranteed, since the table is finite!797******************************************************************/798799int al1_ordrep(void)800{801int i,j;802803if (repsiz == 0)804{ return(0); }805806for (i = j = 1; ; j++)807{808if ((i = al1_trrep(i)) == 1)809{ return(j); }810else if (i == 0)811{ return(0); }812}813814return(0); /* Can't get here; prevent compiler whinging */815}816817/******************************************************************818void al1_prtct(int f, int l, int s, Logic c, Logic or)819820This is a general-purpose coset table printer. It prints rows from821f[irst] to l[ast] inclusive, in steps of s. On a bad value, we try822to do the `right' thing. If c[oinc] is true then the print-out823includes coincident rows, else not; we skip the appropriate number824of rows whatever the c flag is. If or is true then the order and825a representative are printed. The rep've is found via a backtrace826of the table; if the table is in standard form, this rep will be827minimal & the `first' in `order' (length + *column* order). Note828that the table may or may not have been compacted and/or829standardised.830831Warnings/Notes:832i) If you print entries >999999, then the neatly aligned columns833will be lost, although the entries *will* be spaced.834ii) _bldrep() can fail. Most probably due to a lack of memory, but835also if the table is `corrupt' or it is called `inappropriately'.836In this situation we should perhaps alert the user, but we choose837simply to print `?'s instead!838******************************************************************/839840void al1_prtct(int f, int l, int s, Logic c, Logic or)841{842int i, j, row;843844if (f < 1)845{ f = 1; }846if (l > nextdf-1)847{ l = nextdf-1; }848if (s < 1)849{ s = 1; }850851fprintf(fop, " coset |"); /* above coset number */852if (!galpha)853{854for (i = 1; i <= ncol; i++)855{ fprintf(fop, " %6d", colgen[i]); }856}857else858{859for (i = 1; i <= ncol; i++)860{ fprintf(fop, " %c", (colgen[i] > 0)861? algen[colgen[i]] : toupper(algen[-colgen[i]])); }862}863if (or)864{ fprintf(fop," order rep've"); }865fprintf(fop, "\n");866867fprintf(fop, "-------+");868for (i = 1; i <= ncol; i++)869{ fprintf(fop, "-------"); }870if (or)871{ fprintf(fop,"-----------------"); }872fprintf(fop, "\n");873874row = f;875if (!c)876{877while (row < nextdf && COL1(row) < 0)878{ row++; }879}880while (row <= l)881{882fprintf(fop, "%6d |", row);883for (i = 1; i <= ncol; i++)884{ fprintf(fop, " %6d", CT(row,i)); }885if (or && row != 1)886{887if (COL1(row) < 0)888{ fprintf(fop, " - -"); }889else890{891if (al1_bldrep(row))892{893fprintf(fop, " %7d ", al1_ordrep());894for (i = 0; i < repsiz; i++)895{896j = colgen[currrep[i]]; /* generator number */897if (!galpha)898{ fprintf(fop, "%d ", j); }899else900{ fprintf(fop, "%c",901(j > 0) ? algen[j] : toupper(algen[-j])); }902}903}904else905{ fprintf(fop, " ? ?"); }906}907}908fprintf(fop, "\n");909910/* If we're printing *all* rows, we can just incr row by s. If not, we911have to jump over non-redundant rows. */912913if (c)914{ row += s; }915else916{917for (i = 1; i <= s; i++)918{919row++;920while (row < nextdf && COL1(row) < 0)921{ row++; }922if (row == nextdf)923{ break; }924}925}926}927}928929930931