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