File: atlasimp.g

package info (click to toggle)
gap-ctbllib 1.3.11-1
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 76,256 kB
  • sloc: xml: 41,608; makefile: 219; javascript: 155
file content (507 lines) | stat: -rw-r--r-- 18,011 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
#############################################################################
##
#W  atlasimp.g           GAP 4 package CTblLib                  Thomas Breuer
##
##  This file contains the function 'BrowseAtlasImprovements'
##  and some code that was used to translate the contents of the file
##  'app2a.tex' to the JSON format file that is contained in
##  'data/atlasimp.json'.
##


#############################################################################
##
#F  CTblLib.SplitAtSubstring( <string>, <substring> )
##
CTblLib.SplitAtSubstring:= function( string, substring )
    local result, len, sublen, pos, pos2;

    result:= [];
    len:= Length( string );
    sublen:= Length( substring );
    pos:= 1;
    while pos <> fail do
      pos2:= PositionSublist( string, substring, pos - 1 );
      if pos2 = fail then
        Add( result, string{ [ pos .. len ] } );
      else
        Add( result, string{ [ pos .. pos2 - 1 ] } );
        pos2:= pos2 + sublen;
      fi;
      pos:= pos2;
    od;

    return result;
end;


#############################################################################
##
#F  CTblLib.AtlasErrorsData( <filename> )
##
##  Create the data list from the LaTeX file 'app2a.tex' or 'ABCerr.tex'
##  (if you have it).
##
CTblLib.AtlasErrorsData:= function( filename )
    local ABC, str, sections, records, sstr, pos, pos2, r, new, start,
          next, curr, line, type, text, page, lpage, lgroup, group, entry;

    ABC:= EndsWith( filename, "ABCerr.tex" );

    # Fetch the relevant sections
    str:= StringFile( filename );
    if ABC then
      sections:= CTblLib.SplitAtSubstring( str, "\\bf " );
      sections:= sections{ [ 2 .. Length( sections ) ] };
    else
      # from ``Introduction'' to ``Bibliography''.
      sections:= CTblLib.SplitAtSubstring( str, "\\section*" );
      sections:= sections{ [ 3 .. Length( sections ) - 1 ] };
    fi;

    # Run over the sections.
    records:= [];
    for sstr in sections do
      # Extract the title.
      if ABC then
        pos:= 0;
      else
        pos:= Position( sstr, '{' );
      fi;
      pos2:= Position( sstr, '}' );
      r:= rec( title:= sstr{ [ pos + 1 .. pos2 - 1 ] } );

      # Remove comments (from '%' to the next line break).
      new:= "";
      start:= 1;
      pos:= Position( sstr, '%' );
      while pos <> fail do
        pos2:= Position( sstr, '\n', pos );
        if pos2 = fail then
          Append( new, sstr{ [ start .. Length( sstr ) ] } );
          pos:= fail;
        else
          Append( new, sstr{ [ start .. pos-1 ] } );
          start:= pos2;
          pos:= Position( sstr, '%', start );
        fi;
      od;
      if new = "" then
        new:= sstr;
      fi;

      # Split the section into entries.
      # Omit the first line, which consists of formatting instructions.
      new:= CTblLib.SplitAtSubstring( new, "\\cr" );
      new:= new{ [ 2 .. Length( new ) ] };

      # Split each entry into column values.  We create the columns
      # - type (one of "***", "C", "M", "NEW"),
      # - page number,
      # - group name (may be empty),
      # - text.
      next:= [];
      curr:= 0;
      for line in new do
        pos:= Position( line, '&' );
        if pos <> fail then
          type:= line{ [ 1 .. pos - 1 ] };
          type:= ReplacedString( type, " ", "" );
          type:= ReplacedString( type, "\n", "" );
          if type = "" then
            # continuation of the previous text
            pos2:= PositionSublist( line, "&&&&&" );
            if pos2 <> fail then
              Append( next[ curr ][4],
                  Concatenation( "\n", line{ [ pos2+5 .. Length( line ) ] } ) );
            else
              pos2:= PositionSublist( line, "&&&&" );
              if pos2 = fail then
                Error( "&?" );
              fi;
              Append( next[ curr ][4],
                  Concatenation( "\n", line{ [ pos2+4 .. Length( line ) ] } ) );
            fi;
          elif PositionSublist( line, "\\halign" ) = fail then
            if not type in [ "***", "C", "M", "NEW" ] then
              Error( "unexpected type '", type, "'" );
            fi;
            pos2:= Position( line, '&', pos );
            if pos2 <> fail then
              if pos2 <> pos + 1 then
                page:= line{ [ pos + 1 .. pos2 - 1 ] };
              fi;
              if line{ [ pos2 .. pos2+2 ] } = "&:&" then
                # three columns, not group related
                text:= line{ [ pos2+3 .. Length( line ) ] };
                curr:= curr + 1;
                next[ curr ]:= [ type, page, "", text ];
              else
                # five to seven columns
                pos:= pos2;
                pos2:= Position( line, '&', pos );
                page:= Concatenation( page, " ",
                           line{ [ pos + 1 .. pos2 - 1 ] } );
                pos:= pos2;
                pos2:= Position( line, '&', pos );
                lgroup:= line{ [ pos + 1 .. pos2 - 1 ] };
                if lgroup = ":" then
                  # five columns, not group related
                  curr:= curr + 1;
                  text:= line{ [ pos2+1 .. Length( line ) ] };
                  next[ curr ]:= [ type, page, "", text ];
                elif line{ [ pos2 .. pos2+2 ] } = "&:&" then
                  # six columns
                  text:= line{ [ pos2+3 .. Length( line ) ] };
                  curr:= curr + 1;
                  if lgroup <> "" then
                    group:= lgroup;
                  fi;
                  next[ curr ]:= [ type, page, group, text ];
                elif line{ [ pos2 .. pos2+1 ] } = "&&" then
                  # six columns
                  text:= line{ [ pos2+2 .. Length( line ) ] };
                  curr:= curr + 1;
                  if lgroup <> "" then
                    group:= lgroup;
                  fi;
                  next[ curr ]:= [ type, page, group, text ];
                else
                  # seven columns (belongs to bibliography, page and line)
                  pos:= pos2;
                  pos2:= Position( line, '&', pos );
                  lpage:= Concatenation( page, " ",
                              line{ [ pos + 1 .. pos2 - 1 ] } );
                  pos:= pos2;
                  pos2:= Position( line, '&', pos );
                  lpage:= Concatenation( lpage, " ",
                              line{ [ pos + 1 .. pos2 - 1 ] } );
                  text:= line{ [ pos2+1 .. Length( line ) ] };
                  curr:= curr + 1;
                  if lgroup <> "" then
                    group:= lgroup;
                  fi;
                  next[ curr ]:= [ type, lpage, group, text ];
                fi;
              fi;
            fi;
          fi;
        fi;
      od;

      for entry in next do
        # Keep empty lines as paragraph separators.
        entry[4]:= ReplacedString( entry[4], "\n\n", " <<nl>> " );
        # Omit a trailing comma in group names.
        if entry[3] <> "" and entry[3][ Length( entry[3] ) ] = ',' then
          Unbind( entry[3][ Length( entry[3] ) ] );
        fi;
        # Omit a trailing colon in page numbers.
        if entry[2] <> "" and entry[2][ Length( entry[2] ) ] = ':' then
          Unbind( entry[2][ Length( entry[2] ) ] );
        fi;
      od;
      r.entries:= List( next, entry -> List( entry, NormalizedWhitespace ) );
      for entry in r.entries do
        entry[4]:= ReplacedString( entry[4], " <<nl>> ", "<<nl>>" );
      od;
      Add( records, r );
    od;

    return records;
end;


#############################################################################
##
#F  BrowseAtlasImprovements( [<choice>] )
##
##  <#GAPDoc Label="BrowseAtlasImprovements">
##  <ManSection>
##  <Func Name="BrowseAtlasImprovements" Arg='[choice]'/>
##
##  <Returns>
##  nothing.
##  </Returns>
##
##  <Description>
##  Called without argument or with the string <C>"ordinary"</C>,
##  <Ref Func="BrowseAtlasImprovements"/> shows the lists of improvements to
##  the &ATLAS; of Finite Groups <Cite Key="CCN85"/>
##  that are contained in <Cite Key="BN95"/> and <Cite Key="AtlasImpII"/>.
##  <P/>
##  Called with the string <C>"modular"</C>,
##  <Ref Func="BrowseAtlasImprovements"/> shows the list of improvements to
##  the &ATLAS; of Brauer Characters <Cite Key="JLPW95"/>
##  that are contained in <Cite Key="ABCImp"/>.
##  <P/>
##  Called with <K>true</K>, the concatenation of the above lists are shown.
##  <P/>
##  The overview table contains one row for each improvement,
##  and has the following columns.
##  <P/>
##  <List>
##  <Mark><C>Section</C></Mark>
##  <Item>
##    the part in the &ATLAS; to which the entry belongs
##    (Introduction, The Groups, Additional information, Bibliography,
##    Appendix 1, Appendix 2),
##  </Item>
##  <Mark><C>Src</C></Mark>
##  <Item>
##    <C>1</C> for entries from <Cite Key="BN95"/>,
##    <C>2</C> for entries from <Cite Key="AtlasImpII"/>,
##    and <C>3</C> for entries from <Cite Key="ABCImp"/>,
##  </Item>
##  <Mark><C>Typ</C></Mark>
##  <Item>
##    the type of the improvement, one of
##    <C>***</C> (for mathematical errors),
##    <C>NEW</C> (for new information),
##    <C>C</C> (for improvements concerning grammar or notational
##    consistency), or
##    <C>M</C> (for misprints or cases of illegibility),
##  </Item>
##  <Mark><C>Page</C></Mark>
##  <Item>
##    the page and perhaps the line in the (ordinary or modular) &ATLAS;,
##  </Item>
##  <Mark><C>Group</C></Mark>
##  <Item>
##    the name of the simple group to which the entry belongs
##    (empty for entries not from the section <Q>The Groups</Q>),
##  </Item>
##  <Mark><C>Text</C></Mark>
##  <Item>
##    the description of the entry,
##  </Item>
##  <Mark><C>**</C></Mark>
##  <Item>
##    for each entry of the type <C>***</C>, the subtype of the error
##    to which some statements in <Cite Key="BMO17"/> refer, one of
##    <C>CH</C> (character values),
##    <C>P</C> (power maps, element orders, and class names),
##    <C>FI</C> (fusions and indicators),
##    <C>I</C> (Introduction, Bibliography, the list showing
##    the orders of multipliers and outer automorphism group,
##    and the list of Conway polynomials),
##    <C>MP</C> (maps),
##    <C>MX</C> (descriptions of maximal subgroups), and
##    <C>G</C> (other information about the group).
##  </Item>
##  </List>
##  <P/>
##  The full functionality of the function
##  <Ref Func="NCurses.BrowseGeneric" BookName="Browse"/> is available.
##  <P/>
##  The following example shows the input for
##  first restricting the list to errors (type <C>***</C>),
##  then categorizing the filtered list by the subtype of the error,
##  and then expanding the category for the subtype <C>CH</C>.
##  <P/>
##  <Example><![CDATA[
##  gap> n:= [ 14, 14, 14, 14, 14, 14 ];;  # ``do nothing''
##  gap> enter:= [ NCurses.keys.ENTER ];;
##  gap> BrowseData.SetReplay( Concatenation(
##  >        "scrr",                   # select the 'Typ' column,
##  >        "f***", enter,            # filter rows containing '***',
##  >        "scrrrrrrsc", enter,      # categorize by the error kind
##  >        "sr", enter,              # expand the 'CH' category
##  >        n, "Q" ) );               # and quit
##  gap> BrowseAtlasImprovements();
##  gap> BrowseData.SetReplay( false );
##  ]]></Example>
##  </Description>
##  </ManSection>
##  <#/GAPDoc>
##
BindGlobal( "BrowseAtlasImprovements", function( choice... )
    local ordinary, modular, dir, file, str, simplifiedPageNumber,
          simplifiedGroupName, formattedText, data, matrix, sections, r,
          entry, source, row, pagewidth, groupwidth, descrwidth, t, i;

    ordinary:= true;
    modular:= false;
    if Length( choice ) = 1 then
      if choice[1] = true or choice[1] = "modular" then
        modular:= true;
      fi;
      if choice[1] = "modular" then
        ordinary:= false;
      fi;
    fi;

    dir:= DirectoriesPackageLibrary( "ctbllib", "data" )[1];
    if ordinary and not IsBound( CTblLib.AtlasImprovements ) then
      file:= Filename( dir, "atlasimp.json" );
      str:= StringFile( file );
      if str = fail then
        Error( "the data file '", file, "' is not available" );
      fi;
      CTblLib.AtlasImprovements:= AGR.GapObjectOfJsonText( str ).value.data;
    fi;
    if modular and not IsBound( CTblLib.ABCImprovements ) then
      file:= Filename( dir, "abcimp.json" );
      str:= StringFile( file );
      if str = fail then
        Error( "the data file '", file, "' is not available" );
      fi;
      CTblLib.ABCImprovements:= AGR.GapObjectOfJsonText( str ).value.data;
    fi;

    simplifiedPageNumber:= function( pagenumber )
      pagenumber:= ReplacedString( pagenumber, "p. ", "" );
      return ReplacedString( pagenumber, "Page ", "" );
    end;

    # Remove LaTeX markup from group names, and uniformize
    # O_n^+(q) and O^+_n(q) (both occur in the source files).
    simplifiedGroupName:= function( latexname )
      local list, entry;

      list:= [ [ "$", "" ], [ "O^-_8", "O_8^-" ], [ "O^+_8", "O_8^+" ],
               [ "O^-_{10}", "O_{10}^-" ], [ "O^+_{10}", "O_{10}^+"],
               [ "^", "" ], [ "_", "" ], [ "{", "" ], [ "}", "" ] ];

      for entry in list do
        latexname:= ReplacedString( latexname, entry[1], entry[2] );
      od;

      return latexname;
    end;

    formattedText:= function( text, width )
      # Remove \\- (hyphenation).
      text:= ReplacedString( text, "\\-", "" );

      # Finally, format the text; the <<nl>> marks separate paragraphs.
      text:= List( CTblLib.SplitAtSubstring( text, "<<nl>>" ),
               x -> BrowseData.ReallyFormatParagraph( x, width, "left" ) );
      return SplitString( JoinStringsWithSeparator( text, "\n\n" ), "\n" );
    end;

    data:= [];
    if ordinary then
      Append( data, CTblLib.AtlasImprovements );
    fi;
    if modular then
      Append( data, CTblLib.ABCImprovements );
    fi;
    matrix:= [];
    sections:= [];
    for r in data do
      if not r.section in sections then
        Add( sections, r.section );
      fi;
      for entry in r.entries do
        source:= "3";
        if IsBound( r.source ) then
          source:= r.source;
        fi;
        if Length( entry ) = 4 then
          row:= Concatenation( [ r.section, source ], entry, [ "" ] );
        else
          row:= Concatenation( [ r.section, source ], entry );
        fi;
        row[4]:= simplifiedPageNumber( row[4] );
        row[5]:= simplifiedGroupName( row[5] );
        Add( matrix, row );
      od;
    od;
    sections:= List( sections, LowercaseString );

    # Prescribe widths:
    # Columns 2, 3, 7 are assumed to have widths 3, 3, 2.
    # The widths of columns 4 and 5 are computed.
    # Column 1 is assumed to be used for categorizing,
    # in order to leave more space for column 6, which takes what is left.
    pagewidth:= Maximum( List( matrix, l -> Length( l[4] ) ) );
    groupwidth:= Maximum( List( matrix, l -> Length( l[5] ) ) );
    descrwidth:= SizeScreen()[1] - pagewidth - groupwidth - 18;

    matrix:= List( matrix, entry ->
      [ rec( align:= "tl", rows:= [ entry[1] ] ),
        rec( align:= "tc", rows:= [ entry[2] ] ),
        rec( align:= "tr", rows:= [ entry[3] ] ),
        rec( align:= "tl", rows:= [ entry[4] ] ),
        rec( align:= "tl", rows:= [ entry[5] ] ),
        rec( align:= "tl", rows:= formattedText( entry[6], descrwidth ) ),
        rec( align:= "tl", rows:= [ entry[7] ] ) ] );

    # Construct the browse table.
    t:= rec(
      work:= rec(
        align:= "tl",
        header:= t -> BrowseData.HeaderWithRowCounter( t,
                   "Improvements to the ATLAS",
                   Length( matrix ) ),
        main:= matrix,
        labelsCol:= [ [ rec( rows:= [ "Section" ], align:= "l" ),
                        rec( rows:= [ "Src" ], align:= "l" ),
                        rec( rows:= [ "Typ" ], align:= "l" ),
                        rec( rows:= [ "Page" ], align:= "l" ),
                        rec( rows:= [ "Group" ], align:= "l" ),
                        rec( rows:= [ "Text" ], align:= "l" ),
                        rec( rows:= [ "**" ], align:= "l" ) ] ],
        sepLabelsCol:= "=",
        sepRow:= "-",
        sepCol:= [ "|" ],
        widthCol:= [ ,,, 3,, 3,, pagewidth,, groupwidth,, descrwidth,, 2 ],
        SpecialGrid:= BrowseData.SpecialGridLineDraw,
        CategoryValues:= function( t, i, j )
          local val;

          val:= BrowseData.defaults.work.CategoryValues( t, i, j );
          if val = [ "(empty category)" ] then
            if j = 10 then   # "Group"
              val:= [ "(not assigned to a group)" ];
            elif j = 14 then # "**"
              val:= [ "(not a mathematical error)" ];
            fi;
          elif j = 4 then # "Src"
            if val = [ "1" ] then
              val:= [ "from [BN95]" ];
            elif val = [ "2" ] then
              val:= [ "from [Nor]" ];
            elif val = [ "3" ] then
              val:= [ "from [ABC]" ];
            fi;
          fi;

          return val;
        end,
      ),
      dynamic:= rec(
        sortFunctionsForColumns:= [
          function( val1, val2 )
            return Position( sections, val1 ) < Position( sections, val2 );
          end ],
      ),
    );

    # Customize the sort parameters.
    for i in [ 1, 2, 3, 4, 5, 7 ] do
      BrowseData.SetSortParameters( t, "column", i,
          [ "add counter on categorizing", "yes" ] );
    od;

    # Show the browse table.
    NCurses.BrowseGeneric( t );
end );


#############################################################################
##
##  Add the Browse application to the list shown by `BrowseGapData'.
##
BrowseGapDataAdd( "ATLAS Improvements",
    BrowseAtlasImprovements, false, "\
the lists of improvements to the ATLAS of Finite Groups \
that are contained in [BN95] and [Nor]. \\
Try ?BrowseAtlasImprovements for details" );


#############################################################################
##
#E