1 /* File readdes.c.  Contains routines to read and write block designs. */
2 
3 #include <stddef.h>
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 
8 #include "group.h"
9 #include "groupio.h"
10 
11 #include "code.h"
12 #include "field.h"
13 #include "errmesg.h"
14 #include "new.h"
15 #include "token.h"
16 
17 CHECK( readde)
18 
19 extern GroupOptions options;
20 
21 static Matrix_01 *xRead01Matrix(
22    FILE *libFile,
23    char *name,
24    BOOLEAN transposeFlag,
25    Unsigned requiredSetSize,
26    Unsigned requiredNumberOfRows,
27    Unsigned requiredNumberOfCols);
28 
29 
30 /*-------------------------- readDesign -----------------------------------*/
31 
32 /* This function reads in a block design and returns an (0,1)-matrix which
33    is the incidence matrix of the design.  Rows correspond to points and
34    columns to blocks.  Row and column numbering starts at 1.  NOTE THAT
35    THE STORAGE MANAGER IS NOT INITIALIZED. */
36 
readDesign(char * libFileName,char * libName,Unsigned requiredPointCount,Unsigned requiredBlockCount)37 Matrix_01 *readDesign(
38    char *libFileName,
39    char *libName,
40    Unsigned requiredPointCount,       /* 0 = any */
41    Unsigned requiredBlockCount)       /* 0 = any */
42 {
43    Unsigned pt, nRows, nCols;
44    Matrix_01 *matrix;
45    Token token, saveToken;
46    char inputBuffer[81];
47    FILE *libFile;
48    Unsigned j;
49    char matrixName[MAX_NAME_LENGTH+1];
50 
51    /* Open input file. */
52    libFile = fopen( libFileName, "r");
53    if ( libFile == NULL )
54       ERROR1s( "readDesign", "File ", libFileName,
55                " could not be opened for input.")
56 
57    /* Initialize input routines to correct file. */
58    setInputFile( libFile);
59    lowerCase( libName);
60 
61    /* Search for the correct library.  Terminate with error message if
62       not found. */
63    rewind( libFile);
64    for (;;) {
65       fgets( inputBuffer, 80, libFile);
66       if ( feof(libFile) )
67          ERROR1s( "readDesign", "Library block ", libName,
68                   " not found in specified library.")
69       if ( inputBuffer[0] == 'l' || inputBuffer[0] == 'L' ) {
70          setInputString( inputBuffer);
71          if ( ( (token = sReadToken()) , token.type == identifier &&
72                 strcmp(lowerCase(token.value.identValue),"library") == 0 )
73               &&
74               ( (token = sReadToken()) , token.type == identifier &&
75                 strcmp(lowerCase(token.value.identValue),libName) == 0 ) )
76             break;
77       }
78    }
79 
80    /* Read the design name. */
81    if ( (token = nkReadToken() , saveToken = token , token.type == identifier) &&
82          (token = nkReadToken() , token.type == equal) )
83       strcpy( matrixName, saveToken.value.identValue);
84 
85    if ( (token = readToken() , token.type != identifier) ||
86              strcmp( token.value.identValue, "seq") != 0 ||
87              (token = readToken() , token.type != leftParen) )
88       ERROR( "readDesign", "Invalid syntax in design library.")
89 
90    /* Read the number of points and number of blocks. */
91    if ( (token = readToken() , token.type != integer) ||
92         (nRows = token.value.intValue) < 2 ||
93         ( requiredPointCount != 0 && nRows != requiredPointCount ) ||
94         (token = readToken() , token.type != comma) ||
95         (token = readToken() , token.type != integer) ||
96         (nCols= token.value.intValue) < 2 ||
97         ( requiredBlockCount != 0 && nCols != requiredBlockCount ) ||
98         (token = readToken() , token.type != comma) )
99       ERROR( "readDesign", "Invalid syntax in design library.")
100    if ( nRows + nCols > options.maxDegree )
101       ERROR( "readDesign", "Too many rows+columns.")
102 
103    /* Allocate the (0,1) incidence matrix, and zero it. */
104    matrix = newZeroMatrix( 2, nRows, nCols);
105    strcpy( matrix->name, matrixName);
106 
107    /* Read the blocks. */
108    for ( j = 1 ; j <= nCols ; ++j ) {
109       if ( token = readToken() , token.type != leftBracket )
110          ERROR( "readDesign", "Invalid symbol in point list.")
111       while  (token = readToken() , token.type == integer ||
112                                     token.type == comma )
113          if ( token.type == integer && (pt = token.value.intValue) > 0 &&
114                                        pt <= nRows )
115             matrix->entry[pt][j] = 1;
116          else if ( token.type == integer )
117             ERROR1i( "readDesign", "Invalid point ", pt, ".")
118       if ( token.type != rightBracket || (token = readToken() ,
119                (j < nCols ? token.type != comma : token.type != rightParen)) )
120          ERROR( "readDesign", "Invalid symbol in point list.")
121    }
122 
123    /* Close the input file and return. */
124    fclose( libFile);
125    return matrix;
126 }
127 
128 
129 /*-------------------------- writeDesign ----------------------------------*/
130 
131 /* This function writes out an (0,1) matrix as a block design.  Rows
132    correspond to points and columns to blocks.  Row and column numbering
133    starts at 1. */
134 
writeDesign(char * libFileName,char * libName,Matrix_01 * matrix,char * comment)135 void writeDesign(
136    char *libFileName,
137    char *libName,
138    Matrix_01 *matrix,
139    char *comment)
140 {
141    Unsigned i, j, column, leadChar;
142    FILE *libFile;
143 
144    /* Open output file. */
145    libFile = fopen( libFileName, options.outputFileMode);
146    if ( libFile == NULL )
147       ERROR1s( "writeDesign", "File ", libFileName,
148                " could not be opened for output.")
149 
150    /* Write the library name. */
151    fprintf( libFile, "LIBRARY %s;\n", libName);
152 
153    /* Write the comment. */
154    if ( comment )
155       fprintf( libFile, "& %s &\n", comment);
156 
157    /* Write the matrix name. */
158    if ( !matrix->name[0] )
159       strcpy( matrix->name, "D");
160    fprintf( libFile, " %s = seq(", matrix->name);
161 
162    /* Write the numbers of points and blocks. */
163    fprintf( libFile, " %d, %d,", matrix->numberOfRows, matrix ->numberOfCols);
164 
165    /* For j = 1,2,.., write the j'th block. */
166    for ( j = 1 ; j <= matrix->numberOfCols ; ++j) {
167       fprintf( libFile, "\n    ");
168       column = 5;
169       leadChar = '[';
170       for ( i = 1 ; i <= matrix->numberOfRows ; ++i )
171          if ( matrix->entry[i][j] != 0 ) {
172             column += fprintf( libFile, "%c", leadChar);
173             if (column > 73 ) {
174                fprintf( libFile, "\n      ");
175                column = 7;
176             }
177             column += fprintf( libFile, "%d", i);
178             leadChar = ',';
179          }
180       fprintf( libFile, "]");
181       if ( j < matrix->numberOfCols )
182          fprintf( libFile, ",");
183    }
184 
185    /* Write terminators. */
186    fprintf( libFile, ");\nFINISH;\n");
187 
188    /* Close output file. */
189    fclose( libFile);
190 }
191 
192 
193 /*-------------------------- read01Matrix ---------------------------------*/
194 
195 /* This function reads in an (0,1)-matrix and returns a new matrix equal
196    to that read in.  NOTE THAT THE STORAGE MANAGER IS NOT INITIALIZED. */
197 
read01Matrix(char * libFileName,char * libName,BOOLEAN transposeFlag,BOOLEAN adjoinIdentity,Unsigned requiredSetSize,Unsigned requiredNumberOfRows,Unsigned requiredNumberOfCols)198 Matrix_01 *read01Matrix(
199    char *libFileName,
200    char *libName,
201    BOOLEAN transposeFlag,                /* If true, matrix is transposed. */
202    BOOLEAN adjoinIdentity,               /* If true, form (A|I), A = matrix read. */
203    Unsigned requiredSetSize,             /* 0 = any */
204    Unsigned requiredNumberOfRows,        /* 0 = any */
205    Unsigned requiredNumberOfCols)        /* 0 = any */
206 {
207    Unsigned  nRows, nCols, setSize;
208    Matrix_01 *matrix;
209    Token token, saveToken;
210    char inputBuffer[81];
211    FILE *libFile;
212    Unsigned i, j, temp;
213    char matrixName[MAX_NAME_LENGTH+1], str[100];
214    BOOLEAN firstIdent;
215 
216    /* Open input file. */
217    libFile = fopen( libFileName, "r");
218    if ( libFile == NULL )
219       ERROR1s( "read01Matrix", "File ", libFileName,
220                " could not be opened for input.")
221 
222    /* Initialize input routines to correct file. */
223    setInputFile( libFile);
224    lowerCase( libName);
225 
226    /* Search for the correct library.  Terminate with error message if
227       not found. */
228    rewind( libFile);
229    firstIdent = TRUE;
230    for (;;) {
231       fgets( inputBuffer, 80, libFile);
232       if ( feof(libFile) )
233          ERROR1s( "read01Matrix", "Library block ", libName,
234                   " not found in specified library.")
235       if ( firstIdent && sscanf( inputBuffer, "%s", str) == 1 &&
236            (firstIdent = FALSE , strcmp( lowerCase(str), "library") != 0) )
237               return xRead01Matrix( libFile, str, transposeFlag, requiredSetSize,
238                              requiredNumberOfRows, requiredNumberOfCols);
239       if ( inputBuffer[0] == 'l' || inputBuffer[0] == 'L' ) {
240          setInputString( inputBuffer);
241          if ( ( (token = sReadToken()) , token.type == identifier &&
242                 strcmp(lowerCase(token.value.identValue),"library") == 0 )
243               &&
244               ( (token = sReadToken()) , token.type == identifier &&
245                 strcmp(lowerCase(token.value.identValue),libName) == 0 ) )
246             break;
247       }
248    }
249 
250    /* Read the matrix name. */
251    if ( (token = nkReadToken() , saveToken = token , token.type == identifier) &&
252          (token = nkReadToken() , token.type == equal) )
253       strcpy( matrixName, saveToken.value.identValue);
254 
255    if ( (token = readToken() , token.type != identifier) ||
256              strcmp( token.value.identValue, "seq") != 0 ||
257              (token = readToken() , token.type != leftParen) )
258       ERROR( "read01Matrix", "Invalid syntax in matrix library.")
259 
260    /* Read the field or set size, the number of rows, and number of columns,
261       and exchange numbers if matrix is to be transposed. */
262    if ( (token = readToken() , token.type != integer) ||
263         (setSize = token.value.intValue) < 1 ||
264         (token = readToken() , token.type != comma) ||
265         (token = readToken() , token.type != integer) ||
266         (nRows = token.value.intValue) < 1 ||
267         (token = readToken() , token.type != comma) ||
268         (token = readToken() , token.type != integer) ||
269         (nCols= token.value.intValue) < 1 ||
270         (token = readToken() , token.type != comma) )
271       ERROR( "read01Matrix", "Invalid syntax in matrix library.")
272    if ( transposeFlag )
273       EXCHANGE( nRows, nCols, temp)
274    if ( nRows + nCols + adjoinIdentity * nRows> options.maxDegree )
275       ERROR( "read01Matrix", "Too many rows+columns.")
276    if ( requiredSetSize != 0 && setSize != requiredSetSize )
277       ERROR1s( "read01Matrix", "Matrix ", matrixName,
278                " has the wrong set/field size.")
279    if ( requiredNumberOfRows != 0 && nRows != requiredNumberOfRows )
280       ERROR1s( "read01Matrix", "Matrix ", matrixName,
281                " has the wrong number of rows.")
282    if ( requiredNumberOfCols != 0 && nCols != requiredNumberOfCols )
283       ERROR1s( "read01Matrix", "Matrix ", matrixName,
284                " has the wrong number of columns.")
285 
286    /* Allocate the (0,1) incidence matrix, and zero it. */
287    matrix = newZeroMatrix( setSize, nRows, nCols + adjoinIdentity * nRows);
288    strcpy( matrix->name, matrixName);
289    if ( adjoinIdentity )
290       for ( i = 1 ; i <= nRows ; ++i )
291          matrix->entry[i][nCols+i] = 1;
292 
293    /* Read the entries of the matrix in row-major order. */
294    if ( (token = readToken() , token.type != identifier) ||
295         strcmp( token.value.identValue, "seq") != 0 ||
296         (token = readToken() , token.type != leftParen) )
297       ERROR( "read01Matrix", "Invalid syntax at start of matrix entries.")
298    if ( !transposeFlag )
299       for ( i = 1 ; i <= nRows ; ++i )
300          for ( j = 1 ; j <= nCols ; ++j ) {
301             while ( token = readToken() , token.type == comma )
302                ;
303             if ( token.type != integer || token.value.intValue < 0 ||
304                                           token.value.intValue >= matrix->setSize )
305                ERROR( "read01Matrix", "Invalid syntax in matrix entries.")
306             matrix->entry[i][j] = token.value.intValue;
307          }
308    else
309       for ( i = 1 ; i <= nCols ; ++i )
310          for ( j = 1 ; j <= nRows ; ++j ) {
311             while ( token = readToken() , token.type == comma )
312                ;
313             if ( token.type != integer || token.value.intValue < 0 ||
314                                           token.value.intValue >= matrix->setSize )
315                ERROR( "read01Matrix", "Invalid syntax in matrix entries.")
316             matrix->entry[j][i] = token.value.intValue;
317          }
318 
319    /* Check for proper closing. */
320    if ( (token = readToken() , token.type != rightParen) ||
321         (token = readToken() , token.type != rightParen) ||
322         (token = readToken() , token.type != semicolon) )
323       ERROR( "read01Matrix", "Invalid syntax at end of matrix entries.")
324 
325    /* Close the input file and return. */
326    fclose( libFile);
327    return matrix;
328 }
329 
330 
331 /*-------------------------- xRead01Matrix --------------------------------*/
332 
333 /* This function reads in an (0,1)-matrix in the alternate format and returns
334    a new matrix equal to that read in.  It is called only by read01Matrix.
335    NOTE THAT THE STORAGE MANAGER IS NOT INITIALIZED. */
336 
xRead01Matrix(FILE * libFile,char * name,BOOLEAN transposeFlag,Unsigned requiredSetSize,Unsigned requiredNumberOfRows,Unsigned requiredNumberOfCols)337 static Matrix_01 *xRead01Matrix(
338    FILE *libFile,
339    char *name,
340    BOOLEAN transposeFlag,            /* If true, matrix is transposed. */
341    Unsigned requiredSetSize,         /* 0 = any */
342    Unsigned requiredNumberOfRows,    /* 0 = any */
343    Unsigned requiredNumberOfCols)    /* 0 = any */
344 {
345    Unsigned  nRows, nCols, setSize;
346    Matrix_01 *matrix;
347    Unsigned i, j, temp;
348    int symbol, maxSymbol;
349 
350    /* Read the field or set size, the number of rows, and number of columns,
351       and exchange numbers if matrix is to be transposed. */
352    if ( fscanf( libFile, "%d %d %d", &setSize, &nRows, &nCols) != 3 )
353       ERROR( "xRead01Matrix", "Invalid syntax set size, rows count, or col count")
354    if ( (requiredSetSize != 0 && setSize != requiredSetSize) ||
355            nRows < 1 ||
356            (requiredNumberOfRows != 0 && nRows != requiredNumberOfRows) ||
357            nCols < 1 ||
358            (requiredNumberOfCols != 0 && nCols != requiredNumberOfCols) )
359       ERROR( "xRead01Matrix", "Invalid syntax in matrix library.")
360    if ( nRows + nCols > options.maxDegree )
361       ERROR( "xRead01Matrix", "Too many rows+columns.")
362    if ( transposeFlag )
363       EXCHANGE( nRows, nCols, temp)
364 
365    /* Allocate the (0,1) incidence matrix, and zero it. */
366    matrix = newZeroMatrix( setSize, nRows, nCols);
367    if ( strlen(name) > MAX_NAME_LENGTH )
368       ERROR1i( "xRead01Matrix", "Name for code exceeds maximum of ",
369                MAX_NAME_LENGTH, " characters.")
370    strcpy( matrix->name, name);
371 
372    /* Read the entries of the matrix in row-major order. */
373    maxSymbol = '0' + setSize - 1;
374    if ( !transposeFlag )
375       for ( i = 1 ; i <= nRows ; ++i )
376          for ( j = 1 ; j <= nCols ; ++j ) {
377             while ( (symbol = getc(libFile)) == ' ' || symbol == ','  || symbol == '\n' )
378                ;
379             if ( symbol < '0' && symbol > maxSymbol )
380                if ( symbol == EOF )
381                   ERROR( "xRead01Matrix", "Premature end of file.")
382                else
383                   ERROR( "xRead01Matrix", "Invalid symbol in matrix entries.")
384             matrix->entry[i][j] = symbol - '0';
385          }
386    else
387       for ( i = 1 ; i <= nCols ; ++i )
388          for ( j = 1 ; j <= nRows ; ++j ) {
389             while ( (symbol = getc(libFile)) == ' ' || symbol == ',' || symbol == '\n' )
390                ;
391             if ( symbol < '0' && symbol > maxSymbol )
392                if ( symbol == EOF )
393                   ERROR( "xRead01Matrix", "Premature end of file.")
394                else
395                   ERROR( "xRead01Matrix", "Invalid symbol in matrix entries.")
396             matrix->entry[j][i] = symbol - '0';
397          }
398 
399    /* Close the input file and return. */
400    fclose( libFile);
401    return matrix;
402 }
403 
404 
405 /*-------------------------- write01Matrix --------------------------------*/
406 
407 /* This function writes out an (0,1) matrix.  The entries are written in
408    row-major order. */
409 
write01Matrix(char * libFileName,char * libName,Matrix_01 * matrix,BOOLEAN transposeFlag,char * comment)410 void write01Matrix(
411    char *libFileName,
412    char *libName,
413    Matrix_01 *matrix,
414    BOOLEAN transposeFlag,
415    char *comment)
416 {
417    Unsigned i, j, column,
418      outputRows = (transposeFlag) ? matrix->numberOfCols : matrix->numberOfRows,
419      outputCols = (transposeFlag) ? matrix->numberOfRows : matrix->numberOfCols;
420    FILE *libFile;
421 
422    /* Open output file. */
423    libFile = fopen( libFileName, options.outputFileMode);
424    if ( libFile == NULL )
425       ERROR1s( "write01Matrix", "File ", libFileName,
426                " could not be opened for output.")
427 
428    /* Write the library name. */
429    fprintf( libFile, "LIBRARY %s;\n", libName);
430 
431    /* Write the comment. */
432    if ( comment )
433       fprintf( libFile, "\" %s \"\n", comment);
434 
435    /* Write the matrix name. */
436    if ( !matrix->name[0] )
437       strcpy( matrix->name, "M");
438    fprintf( libFile, " %s = seq(", matrix->name);
439 
440    /* Write the set size and numbers of rows and columns and "seq(". */
441    fprintf( libFile, " %d, %d, %d, seq(", matrix->setSize, outputRows,
442                                           outputCols);
443 
444    /* For i = 1,2,..,nRows write the i'th block. */
445    for ( i = 1 ; i <= outputRows ; ++i) {
446       fprintf( libFile, "\n    ");
447       column = 5;
448       for ( j = 1 ; j <= outputCols ; ++j ) {
449          if ( column > 75 ) {
450             fprintf( libFile, "\n     ");
451             column = 6;
452          }
453          column += transposeFlag ?
454                       fprintf( libFile, "%d", matrix->entry[j][i]) :
455                       fprintf( libFile, "%d", matrix->entry[i][j]);
456          if ( i < outputRows || j < outputCols )
457             column += fprintf( libFile, ",");
458       }
459    }
460 
461    /* Write terminators. */
462    fprintf( libFile, "));\nFINISH;\n");
463 
464    /* Close output file. */
465    fclose( libFile);
466 }
467 
468 
469 
470 
471 /*-------------------------- readCode -------------------------------------*/
472 
473 /* This function reads in a binary code and returns a new code equal
474    to that read in.  NOTE THAT THE STORAGE MANAGER IS NOT INITIALIZED. */
475 
readCode(char * libFileName,char * libName,BOOLEAN reduceFlag,Unsigned requiredSetSize,Unsigned requiredDimension,Unsigned requiredLength)476 Code *readCode(
477    char *libFileName,
478    char *libName,
479    BOOLEAN reduceFlag,                   /* If true, gen matrix is reduced. */
480    Unsigned requiredSetSize,             /* 0 = any */
481    Unsigned requiredDimension,           /* 0 = any */
482    Unsigned requiredLength)              /* 0 = any */
483 {
484    Code *C;
485    Matrix_01 *M;
486 
487    M = read01Matrix( libFileName, libName, FALSE, FALSE, requiredSetSize,
488                      requiredDimension, requiredLength);
489    C = (Code *) M;
490    C->infoSet = NULL;
491    if ( C->fieldSize > 2 )
492       C->field = buildField( C->fieldSize);
493    if ( reduceFlag )
494       reduceBasis( C);
495    return C;
496 }
497 
498 
499 /*-------------------------- writeCode ------------------------------------*/
500 
501 /* This function writes out a code.  The information set is not written. */
502 
writeCode(char * libFileName,char * libName,Code * C,char * comment)503 void writeCode(
504    char *libFileName,
505    char *libName,
506    Code *C,
507    char *comment)
508 {
509    write01Matrix( libFileName, libName, (Matrix_01 *) C, FALSE, comment);
510 }
511 
512