1 /* File wtdist.c. */
2
3 /* Copyright (C) 1992 by Jeffrey S. Leon. This software may be used freely
4 for educational and research purposes. Any other use requires permission
5 from the author. */
6
7 /* Highly optimized main program to compute weight distribution
8 of a linear code The command format is
9
10 wtdist <options> <code> <weightToSave> <matrix>
11 or
12 wtdist <options> <code>
13
14 where in the second case all vectors of weight <weightToSave> (except
15 scalar multiples) are saved as a matrix whose rows are the vectors. If
16 the -1 option is coded, only one vector of this weight is saved. If there
17 are no vectors of the given weight, the matrix is not created.
18
19 For most binary codes, bit string operations on vectors are used.
20
21 For nonbinary codes (and for binary codes whose parameters fail to meet
22 certain constraints), several columns of each codeword are packed into a
23 single integer in order to make computations much faster, for large codes,
24 than would otherwise be possible. The number of columns packed into a
25 single integer is referred to as the "packing factor". It may be
26 specified explicitly by the -pf option (within limits) or allowed to
27 default. Optimal choice of the packing factor can improve performance
28 considerably.
29
30 Let the code be an (n,k) code over GF(q), where q = p^e. Let F(x) =
31 a[0] + a[1]*x + ... + a[e]*x^e be the irreducible polynomial over
32 GF(p) used to construct GF(q). The elements of GF(q) are represented
33 as integers in the range 0..q-1, where field element
34 g[0] + g[1]*x + ... + g[e-1]*x^(e-1) is represented by the integer
35 g[0] + g[1] * q + ... + g[e-1] * q^(e-1).
36
37 Let P denote the packing factor. In order to save space and time, up
38 to P components of a vector over GF(q) are represented as a single
39 integer in the range 0..(q^P-1). Specifically, the sequence of
40 components b[i],b[i+1],...,b[i+P-1] is represented by the integer
41 b[i] + b[i+1] * q + ... + b[i+P-1] * q^(P-1).
42
43 The integer representing a sequence of field elements (components) is
44 referred to as a "packed field sequence". The number of packed field
45 sequences required to represent one codeword is called the "packed
46 length" of the code; it equals ceil(n/P). The set of columns of the
47 code corresponding to a packed field sequence is referred to as a "packed column".
48
49 The packing factor P must satisfy the constraints
50 i) P <= MaxPackingFactor,
51 ii) FieldSize ^ P - 1 <= MaxPackedInteger,
52 iii) ceil(n/P) <= MaxPackedLength,
53 where MaxPackingFactor, MaxPackedInteger, and MaxPackedLength are
54 symbolic constant (see above).
55
56 In general, a large packing factor will increase memory requirements
57 and will increase the time required to initialize various tables, but
58 it will decrease the time required to compute the weight distribution,
59 once initialization has been completed. The largest single data
60 structure contains e * k * q^P * MaxPackedLength * r bytes,
61 where r is the number of bytes used to represent type
62 0..MaxPackedInteger.
63
64 In general, a relatively small packing factor (say 8 for binary codes)
65 is indicated for codes of moderate size. For large codes, a larger
66 packing factor (say 12 for binary codes) leads to lower execution times,
67 at the cost of a higher memory requirement.
68
69 The user may specify the value of the packing factor in the input,
70 subject to the limits specified above. An input value of 0 will cause
71 the program to choose a default value, which may not give as good
72 performance as a user-specified value.
73 */
74
75 /* Note: BINARY_CUTOFF_DIMENSION must be at least 3. */
76 #define BINARY_CUTOFF_DIMENSION 12
77 #define DEFAULT_INIT_ALLOC_SIZE 10000
78
79 #include <stddef.h>
80 #include <stdlib.h>
81 #include <errno.h>
82 #include <stdio.h>
83 #include <string.h>
84
85 #ifdef HUGE
86 #include <alloc.h>
87 #endif
88
89 #define MAIN
90
91 #include "group.h"
92 #include "groupio.h"
93
94 #include "errmesg.h"
95 #include "field.h"
96 #include "new.h"
97 #include "readdes.h"
98 #include "storage.h"
99 #include "token.h"
100 #include "util.h"
101
102 GroupOptions options;
103
104 static void verifyOptions(void);
105
106 static void binaryWeightDist(
107 const Code *const C,
108 const Unsigned saveWeight,
109 const BOOLEAN oneCodeWordOnly,
110 Unsigned *const allocatedSize,
111 unsigned long *const freq,
112 Matrix_01 *const matrix);
113
114 static void generalWeightDist(
115 const Code *const C,
116 Unsigned saveWeight,
117 const BOOLEAN oneCodeWordOnly,
118 const Unsigned packingFactor,
119 const Unsigned largestPackedInteger,
120 const Unsigned packedLength,
121 Unsigned *const allocatedSize,
122 unsigned long *const freq,
123 Matrix_01 *matrix);
124
125 static void binaryCosetWeightDist(
126 const Code *const C,
127 const Unsigned maxCosetWeight,
128 const BOOLEAN oneCodeWordOnly,
129 const Unsigned passes,
130 Unsigned *const allocatedSize,
131 unsigned long *const freq,
132 Matrix_01 *const matrix);
133
134
main(int argc,char * argv[])135 int main( int argc, char *argv[])
136 {
137 char codeFileName[MAX_FILE_NAME_LENGTH] = "",
138 matrixFileName[MAX_FILE_NAME_LENGTH] = "";
139 Unsigned i, j, temp, optionCountPlus1, packingFactor, packedLength,
140 largestPackedInteger, saveWeight, allocatedSize,
141 maxCosetWeight, passes;
142 char matrixObjectName[MAX_NAME_LENGTH+1] = "",
143 codeLibraryName[MAX_NAME_LENGTH+1] = "",
144 matrixLibraryName[MAX_NAME_LENGTH+1] = "",
145 prefix[MAX_FILE_NAME_LENGTH],
146 suffix[MAX_NAME_LENGTH];
147 Code *C;
148 Matrix_01 *matrix;
149 BOOLEAN saveCodeWords, oneCodeWordOnly, defaultForBinaryProcedure,
150 useBinaryProcedure = FALSE, cWtDistFlag;
151 char comment[100];
152 unsigned long *freq = malloc( (MAX_CODE_LENGTH+2) * sizeof(unsigned long));
153
154 /* Provide help if no arguments are specified. */
155 if ( argc == 1 ) {
156 printf( "\nUsage: wtdist [options] code [saveWeight matrix]\n");
157 return 0;
158 }
159
160 /* Check for limits option. If present in position 1, give limits and
161 return. */
162 if ( strcmp(argv[1], "-l") == 0 || strcmp(argv[1], "-L") == 0 ) {
163 showLimits();
164 return 0;
165 }
166
167 /* Check for verify option. If present in position 1, perform verify (Note
168 verifyOptions terminates program). */
169 if ( strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "-V") == 0 )
170 verifyOptions();
171
172 /* Check for exactly 1 or 3 parameters following options. */
173 for ( optionCountPlus1 = 1 ; optionCountPlus1 < argc &&
174 argv[optionCountPlus1][0] == '-' ; ++optionCountPlus1 )
175 ;
176
177 if ( argc - optionCountPlus1 == 1 || argc - optionCountPlus1 == 3) {
178 saveCodeWords = (argc - optionCountPlus1 == 3);
179 } else {
180 ERROR( "main (wtdist)",
181 "1 or 3 non-option parameters are required.");
182 exit(ERROR_RETURN_CODE);
183 }
184
185 /* Process options. */
186 prefix[0] = '\0';
187 suffix[0] = '\0';
188 options.inform = TRUE;
189 packingFactor = 0;
190 cWtDistFlag = FALSE;
191 oneCodeWordOnly = FALSE;
192 defaultForBinaryProcedure = TRUE;
193 allocatedSize = 0;
194 parseLibraryName( argv[optionCountPlus1+2], "", "", matrixFileName,
195 matrixLibraryName);
196 strncpy( options.genNamePrefix, matrixLibraryName, 4);
197 options.genNamePrefix[4] = '\0';
198 strcpy( options.outputFileMode, "w");
199
200 /* Retrieve command-line options. */
201 for ( i = 1 ; i < optionCountPlus1 ; ++i ) {
202 for ( j = 1 ; argv[i][j] != ':' && argv[i][j] != '\0' ; ++j )
203 #ifdef EBCDIC
204 argv[i][j] = ( argv[i][j] >= 'A' && argv[i][j] <= 'I' ||
205 argv[i][j] >= 'J' && argv[i][j] <= 'R' ||
206 argv[i][j] >= 'S' && argv[i][j] <= 'Z' ) ?
207 (argv[i][j] + 'a' - 'A') : argv[i][j];
208 #else
209 argv[i][j] = (argv[i][j] >= 'A' && argv[i][j] <= 'Z') ?
210 (argv[i][j] + 'a' - 'A') : argv[i][j];
211 #endif
212 errno = 0;
213 if ( strcmp( argv[i], "-a") == 0 )
214 strcpy( options.outputFileMode, "a");
215 else if ( strcmp( argv[i], "-cwtdist") == 0 ) {
216 cWtDistFlag = TRUE;
217 }
218 else if ( strncmp( argv[i], "-p:", 3) == 0 ) {
219 strcpy( prefix, argv[i]+3);
220 }
221 else if ( strncmp( argv[i], "-t:", 3) == 0 ) {
222 strcpy( suffix, argv[i]+3);
223 }
224 else if ( strncmp( argv[i], "-n:", 3) == 0 )
225 if ( isValidName( argv[i]+3) )
226 strcpy( matrixObjectName, argv[i]+3);
227 else
228 ERROR1s( "main (wtdist)", "Invalid name ", matrixObjectName,
229 " for codewords to be saved.")
230 else if ( strcmp( argv[i], "-q") == 0 )
231 options.inform = FALSE;
232 else if ( strcmp( argv[i], "-overwrite") == 0 )
233 strcpy( options.outputFileMode, "w");
234 else if ( strcmp( argv[i], "-b") == 0 ) {
235 defaultForBinaryProcedure = FALSE;
236 useBinaryProcedure = TRUE;
237 }
238 else if ( strcmp( argv[i], "-g") == 0 ) {
239 defaultForBinaryProcedure = FALSE;
240 useBinaryProcedure = FALSE;
241 }
242 else if ( strncmp( argv[i], "-pf:", 4) == 0 ) {
243 errno = 0;
244 packingFactor = (Unsigned) strtol(argv[i]+4,NULL,0);
245 if ( errno )
246 ERROR( "main (wtdist)", "Invalid syntax for -pf option")
247 }
248 else if ( strncmp( argv[i], "-s:", 3) == 0 ) {
249 errno = 0;
250 allocatedSize = (Unsigned) strtol(argv[i]+3,NULL,0);
251 if ( errno )
252 ERROR( "main (wtdist)", "Invalid syntax for -s option")
253 }
254 else if ( strcmp( argv[i], "-1") == 0 )
255 oneCodeWordOnly = TRUE;
256 else
257 ERROR1s( "main (compute subgroup)", "Invalid option ", argv[i], ".")
258 }
259
260 options.maxBaseSize = DEFAULT_MAX_BASE_SIZE;
261 options.maxWordLength = 200 + 5 * options.maxBaseSize;
262 options.maxDegree = MAX_INT - 2 - options.maxBaseSize;
263
264 if ( cWtDistFlag )
265 maxCosetWeight = saveWeight;
266
267 /* Compute names for files and name for matrix of codewords saved. Also
268 determine weight of codewords to save. */
269 parseLibraryName( argv[optionCountPlus1], prefix, suffix,
270 codeFileName, codeLibraryName);
271 if ( saveCodeWords ) {
272 errno = 0;
273 saveWeight = (Unsigned) strtol(argv[optionCountPlus1+1], NULL, 0);
274 if ( errno )
275 ERROR( "main (wtdist)", "Invalid syntax weight to save.")
276 parseLibraryName( argv[optionCountPlus1+2], prefix, suffix,
277 matrixFileName, matrixLibraryName);
278 if ( matrixObjectName[0] == '\0' )
279 strncpy( matrixObjectName, matrixLibraryName, MAX_NAME_LENGTH+1);
280 }
281 else
282 saveWeight = UNKNOWN;
283
284 /* Read in the code. */
285 C = readCode( codeFileName, codeLibraryName, TRUE, 0, 0, 0);
286
287 /* Partially allocate matrix for saving codewords. Compute initial
288 allocatedSize, unless specified as input. */
289 if ( saveCodeWords ) {
290 if ( allocatedSize == 0 )
291 allocatedSize = DEFAULT_INIT_ALLOC_SIZE;
292 matrix = (Matrix_01 *) malloc( sizeof(Matrix_01) );
293 if ( !matrix )
294 ERROR( "main (wtdist)", "Out of memory.")
295 matrix->unused = NULL;
296 matrix->field = NULL;
297 matrix->entry = (FieldElement **) malloc( sizeof(FieldElement *) *
298 (allocatedSize+2) );
299 if ( !matrix->entry )
300 ERROR( "main (wtdist)", "Out of memory.")
301 matrix->setSize = C->fieldSize;
302 matrix->numberOfRows = 0;
303 matrix->numberOfCols = C->length;
304 }
305
306 #ifdef xxxxxx
307 /* If a coset weight distribution is requested, check the size limits,
308 call cosetWeightDist if ok, and return. */
309 if ( cWtDistFlag ) {
310 if ( C->fieldSize != 2 || C->length > 128 || C->length - C->dimension > 32 )
311 ERROR( "main (wtdist)",
312 "Coset weight dist requires binary code, length <= 128, codimension <= 32.")
313 binaryCosetWeightDist( C, maxCosetWeight, oneCodeWordOnly, passes, &allocatedSize,
314 matrix);
315 return 0;
316 }
317 #endif
318
319 /* Decide whether to use binary or general procedure. The general
320 procedure is used on binary codes of small dimension. */
321 if ( defaultForBinaryProcedure )
322 useBinaryProcedure &= (C->fieldSize == 2 &&
323 C->length <= 128 &&
324 C->dimension > BINARY_CUTOFF_DIMENSION);
325 else if ( useBinaryProcedure && (C->fieldSize != 2 || C->length > 128 ||
326 C->dimension <= 3) ) {
327 useBinaryProcedure = FALSE;
328 if ( options.inform )
329 printf( "\n\n Special binary procedure cannot be used.\n");
330 }
331
332 /* If the general procedure is to be used, determine the packing factor if
333 one was not specified. Determine the packed length and the largest
334 packed integer. */
335 if ( !useBinaryProcedure ) {
336 if ( packingFactor == 0 ) {
337 packingFactor = 1;
338 largestPackedInteger = C->fieldSize;
339 while ( (largestPackedInteger <= 0x7fff / C->fieldSize) &&
340 (packingFactor <= C->dimension / 2) ) {
341 ++packingFactor;
342 largestPackedInteger *= C->fieldSize;
343 }
344 --largestPackedInteger;
345 }
346 else {
347 temp = 1;
348 largestPackedInteger = C->fieldSize;
349 while ( (largestPackedInteger <= 0x7fff / C->fieldSize) &&
350 (temp < packingFactor) ) {
351 ++temp;
352 largestPackedInteger *= C->fieldSize;
353 }
354 packingFactor = temp;
355 --largestPackedInteger;
356 }
357 packedLength = (C->length + packingFactor - 1) / packingFactor;
358 }
359
360 /* Compute the weight distribution. */
361 if ( useBinaryProcedure )
362 binaryWeightDist( C, saveWeight, oneCodeWordOnly, &allocatedSize, freq,
363 matrix);
364 else
365 generalWeightDist( C, saveWeight, oneCodeWordOnly, packingFactor,
366 largestPackedInteger, packedLength,
367 &allocatedSize, freq, matrix);
368
369 /* Write out the weight distribution. */
370 if ( options.inform ) {
371 printf( "\n\n Weight Distribution of code %s", C->name);
372 printf( "\n\n Weight Frequency");
373 printf( "\n ------ ---------");
374 for ( i = 0 ; i <= C->length ; ++i )
375 if ( freq[i] != 0 )
376 printf( "\n %3u %10lu", i, freq[i]);
377 printf( "\n");
378 }
379
380 /* Write out the codewords of weight saveWeight. */
381 if ( saveCodeWords && matrix->numberOfRows > 0 ) {
382 if ( oneCodeWordOnly )
383 sprintf( comment, "One codeword of weight %u in code %s.",
384 saveWeight, C->name);
385 else if ( C->fieldSize == 2 )
386 sprintf( comment, "The %u codewords of weight %u in code %s.",
387 matrix->numberOfRows, saveWeight, C->name);
388 else
389 sprintf( comment,
390 "%u of %u codewords of weight %u in code %s"
391 " (scalar multiples excluded).",
392 matrix->numberOfRows, matrix->numberOfRows * (C->fieldSize-1),
393 saveWeight, C->name);
394 strcpy( matrix->name, matrixObjectName);
395 write01Matrix( matrixFileName, matrixLibraryName, matrix, FALSE,
396 comment);
397 }
398 if ( saveCodeWords ) {
399 deleteMatrix(matrix, matrix->numberOfRows);//free(matrix->entry);
400 //free(matrix);
401 }
402 free(freq);
403 free(C->infoSet);
404 deleteMatrix((Matrix_01 *)C, C->dimension);
405 return 0;
406 }
407
408
409 /*-------------------------- packBinaryCodeWord ---------------------------*/
410
411
packBinaryCodeWord(const Unsigned length,const FieldElement * const codeWordToPack,unsigned long * const packedWord1,unsigned long * const packedWord2,unsigned long * const packedWord3,unsigned long * const packedWord4)412 void packBinaryCodeWord(
413 const Unsigned length,
414 const FieldElement *const codeWordToPack,
415 unsigned long *const packedWord1,
416 unsigned long *const packedWord2,
417 unsigned long *const packedWord3,
418 unsigned long *const packedWord4)
419 {
420 Unsigned col;
421
422 *packedWord1 = *packedWord2 = *packedWord3 = *packedWord4 = 0;
423 for ( col = 1 ; col <= length ; ++col )
424 if ( col <= 32 )
425 *packedWord1 |= codeWordToPack[col] << (col-1);
426 else if (col <= 64 )
427 *packedWord2 |= codeWordToPack[col] << (col-33);
428 else if (col <= 96 )
429 *packedWord3 |= codeWordToPack[col] << (col-65);
430 else if (col <= 128 )
431 *packedWord4 |= codeWordToPack[col] << (col-97);
432 }
433
434
435 /*-------------------------- buildOnesCount -------------------------------*/
436
437 /* This function allocates and constructs an array of size 2^16 in which
438 entry i contains the number of ones in the binary representation of i,
439 0 <= i < 2^16. It returns (a pointer to) the array. It is assumed that
440 type short has length 16 bits. */
441
442 #ifdef HUGE
buildOnesCount(void)443 char huge *buildOnesCount(void)
444 #else
445 char *buildOnesCount(void)
446 #endif
447 {
448 long i, j;
449 #ifdef HUGE
450 char huge *onesCount = (char huge *) farmalloc( 65536L * sizeof(char) );
451 #else
452 char *onesCount = (char *) malloc( 65536L * sizeof(char) );
453 #endif
454
455 if ( !onesCount )
456 ERROR( "buildOnesCount",
457 "Not enough memory to run program. Program terminated.")
458 for ( i = 0 ; i <= 65535L ; ++i ) {
459 onesCount[i] = 0;
460 for ( j = 0 ; j <= 15 ; ++j )
461 onesCount[i] += ( i & (1 << j)) != 0;
462 }
463 return onesCount;
464 }
465
466
467 /*-------------------------- binaryWeightDist ----------------------------*/
468
469 /* Assumes length <= 128. */
470
471 #define SAVE if ( curWt == saveWeight ) { \
472 if ( ++matrix->numberOfRows > *allocatedSize ) { \
473 *allocatedSize *= 2; \
474 matrix->entry = (FieldElement **) realloc( matrix->entry, \
475 *allocatedSize); \
476 } \
477 if ( !matrix->entry ) \
478 ERROR( "binaryWeightDist", "Out of memory.") \
479 vec = matrix->entry[matrix->numberOfRows] = (FieldElement *) \
480 malloc( (C->length+1) * sizeof(FieldElement) ); \
481 if ( !vec ) \
482 ERROR( "binaryWeightDist", "Out of memory.") \
483 for ( j = 0 ; j < length ; ++j ) \
484 if ( j < 32 ) \
485 vec[j+1] = ((cw1 >> j) & 1); \
486 else if ( j < 64 ) \
487 vec[j+1] = ((cw2 >> (j-32)) & 1); \
488 else if ( j < 96 ) \
489 vec[j+1] = ((cw3 >> (j-64)) & 1); \
490 else if ( j < 128 ) \
491 vec[j+1] = ((cw4 >> (j-96)) & 1); \
492 if ( oneCodeWordOnly ) \
493 saveWeight = UNKNOWN; \
494 }
495
496 /* Added parentheses around (e.g.) j-32 in previous code to eliminate a compiler warning */
497
binaryWeightDist(const Code * const C,Unsigned saveWeight,const BOOLEAN oneCodeWordOnly,Unsigned * const allocatedSize,unsigned long * const freq,Matrix_01 * const matrix)498 void binaryWeightDist(
499 const Code *const C,
500 Unsigned saveWeight,
501 const BOOLEAN oneCodeWordOnly,
502 Unsigned *const allocatedSize,
503 unsigned long *const freq,
504 Matrix_01 *const matrix)
505 {
506 Unsigned length = C->length,
507 dimension = C->dimension,
508 i, j, curWt;
509 FieldElement *vec;
510 unsigned long m;
511 #ifdef HUGE
512 char huge *onesCount = buildOnesCount();
513 #else
514 char *onesCount = buildOnesCount();
515 #endif
516 unsigned long basis1[35], basis2[35], basis3[35], basis4[35];
517 unsigned long cw1, cw2, cw3, cw4;
518 unsigned long loopIndex, lastPass, temp;
519
520
521 /* Initializations. */
522 for ( i = 0 ; i <=C->length ; ++i )
523 freq[i] = 0;
524 cw1 = cw2 = cw3 = cw4 = 0;
525
526 /* Pack the code words. */
527 for ( i = 1 ; i <= C->dimension ; ++i )
528 packBinaryCodeWord( C->length, C->basis[i], &basis1[i-1], &basis2[i-1],
529 &basis3[i-1], &basis4[i-1]);
530
531 /* Enumerate the codewords. */
532 lastPass = (1L << (dimension-3)) - 1;
533 if ( saveWeight == UNKNOWN ) {
534 if ( length <= 32 )
535 #define MAXLEN 32
536 #include "wt.h"
537 else if ( length <= 48 )
538 #define MAXLEN 48
539 #include "wt.h"
540 else if ( length <= 64 )
541 #define MAXLEN 64
542 #include "wt.h"
543 else if ( length <= 80 )
544 #define MAXLEN 80
545 #include "wt.h"
546 else if ( length <= 96 )
547 #define MAXLEN 96
548 #include "wt.h"
549 else if ( length <= 112 )
550 #define MAXLEN 112
551 #include "wt.h"
552 else if ( length <= 128 )
553 #define MAXLEN 128
554 #include "wt.h"
555 }
556 else
557 if ( length <= 32 )
558 #define MAXLEN 32
559 #include "swt.h"
560 else if ( length <= 48 )
561 #define MAXLEN 48
562 #include "swt.h"
563 else if ( length <= 64 )
564 #define MAXLEN 64
565 #include "swt.h"
566 else if ( length <= 80 )
567 #define MAXLEN 80
568 #include "swt.h"
569 else if ( length <= 96 )
570 #define MAXLEN 96
571 #include "swt.h"
572 else if ( length <= 112 )
573 #define MAXLEN 112
574 #include "swt.h"
575 else if ( length <= 128 )
576 #define MAXLEN 128
577 #include "swt.h"
578
579 }
580
581
582
583 /*-------------------------- buildWeightArray -------------------------------------*/
584
585 /* The procedure BuildWeightArray constructs the array Weight
586 of size 0..LargestPackedInteger. For t = 0,1,...,HighPackedInteger,
587 Weight[t] is set to the number of nonzero field elements in the
588 sequence of PackingFactor field elements represented by integer t. */
589
buildWeightArray(const Unsigned fieldSize,const Unsigned packingFactor,const Unsigned largestPackedInteger)590 char *buildWeightArray(
591 const Unsigned fieldSize, /* Size of the field. */
592 const Unsigned packingFactor, /* No of cols packed into integer. */
593 const Unsigned largestPackedInteger)
594 {
595 Unsigned i, v;
596 char *weight;
597
598 weight = (char *) malloc( sizeof(char) * (largestPackedInteger+1) );
599 if ( !weight )
600 ERROR( "buildWeightArray", "Out of memory.");
601
602 for ( i = 0 ; i <= largestPackedInteger ; ++i ) {
603 weight[i] = 0;
604 v = i;
605 while ( v > 0 ) {
606 if ( v % fieldSize )
607 ++weight[i];
608 v /= fieldSize;
609 }
610 }
611
612 return weight;
613 }
614
615
616 /*-------------------------- packNonBinaryCodeWord --------------------------------*/
617
618 /* This procedure packs a codeword over a field of size greater than 2.
619 (If the field size is 2, it works, but it returns an array of type
620 unsigned short, whereas type unsigned would be preferable.)
621 It returns a new packed code word which is obtained by packing the code
622 word supplied as a parameter. If p denotes the PackingFactor, then p
623 columns of the input codeword (Word) are packed into each integer of the
624 output packed codeword (PackedWord). If q denotes the field size and if
625 c(1),...,c(n) denotes the input codeword, then the output packed word will
626 have components
627 c(1)+c(2)*q+...+c(p)*q**(p-1), c(p+1)+c(p+2)*q+...+c(2*p)*q**(p-1), etc. */
628
packNonBinaryCodeWord(const Unsigned fieldSize,const Unsigned length,const Unsigned packingFactor,const FieldElement * codeWord)629 unsigned short *packNonBinaryCodeWord(
630 const Unsigned fieldSize, /* Field size for codeword. */
631 const Unsigned length, /* Length of codeword to pack. */
632 const Unsigned packingFactor, /* No of cols packed into integer. */
633 const FieldElement *codeWord) /* The codeword to pack. */
634 {
635 Unsigned index = 0,
636 offset = 0,
637 col,
638 powerOfFieldSize = 1;
639 const Unsigned colsPerArrayElt = (length+packingFactor) / packingFactor;
640 unsigned short *packedCodeWord;
641
642 packedCodeWord = (unsigned short *)
643 malloc( colsPerArrayElt * sizeof(unsigned short *));
644 if ( !packedCodeWord )
645 ERROR( "packNonBinaryCodeWord", "Out of memory.");
646 packedCodeWord[0] = 0;
647
648 for ( col = 1 ; col <= length ; ++col ) {
649 if ( offset >= packingFactor ) {
650 packedCodeWord[++index] = 0;
651 offset = 0;
652 powerOfFieldSize = 1;
653 }
654 packedCodeWord[index] += codeWord[col] * powerOfFieldSize;
655 ++offset;
656 powerOfFieldSize *= fieldSize;
657 }
658
659 return packedCodeWord;
660 }
661
662
663 /*-------------------------- unpackNonBinaryCodeWord --------------------------------*/
664
665 /* This procedure unpacks a codeword over a field of size greater than 2.
666 It performs the reverse of the packNonBinaryCodeword procedure above. */
667
unpackNonBinaryCodeWord(const Unsigned fieldSize,const Unsigned length,const Unsigned packingFactor,const unsigned short * packedCodeWord,FieldElement * const codeWord)668 void unpackNonBinaryCodeWord(
669 const Unsigned fieldSize, /* Field size for codeword. */
670 const Unsigned length, /* Length of codeword to unpack. */
671 const Unsigned packingFactor, /* No of cols packed into integer. */
672 const unsigned short *packedCodeWord, /* The codeword to unpack pack. */
673 FieldElement *const codeWord) /* Set to unpacked code word. */
674 {
675 Unsigned index = 0,
676 offset = 0,
677 col, temp;
678
679 temp = packedCodeWord[0];
680 for ( col = 1 ; col <= length ; ++col ) {
681 if ( offset >= packingFactor ) {
682 temp = packedCodeWord[++index];
683 offset = 0;
684 }
685 codeWord[col] = temp % fieldSize;
686 ++offset;
687 temp /= fieldSize;
688 }
689 }
690
691
692
693 /*-------------------------- buildAddBasisElement -----------------------------------*/
694
695 /* This procedure constructs a data structure AddBasisElement which
696 specifies how to add a a prime-basis element to an arbitrary
697 codeword. addBasisElement[i][p][j] gives the sum of packed column j
698 of the i'th prime basis vector and packed field sequence k, for
699 1 <= i <= C->dimension * C->field->exponent,
700 0 <= j < packedLength,
701 0 <= p <= largestPackedInteger.
702 */
703
buildAddBasisElement(const Code * const C,const Unsigned packingFactor,const Unsigned packedLength,const Unsigned largestPackedInteger)704 unsigned short ***buildAddBasisElement(
705 const Code *const C,
706 const Unsigned packingFactor,
707 const Unsigned packedLength,
708 const Unsigned largestPackedInteger)
709 {
710 unsigned short ***addBasisElement;
711 Unsigned a, h, i, j, k, m, z, primeRow;
712 FieldElement s;
713 FieldElement *x, *y;
714 Unsigned *primeBasisVector;
715 const Unsigned fieldExponent = (C->fieldSize == 2) ? 1 : C->field->exponent;
716 const Unsigned primeDimension = C->dimension * fieldExponent;
717
718 primeBasisVector = (Unsigned *) malloc( (C->length+1) * sizeof(Unsigned));
719 if ( !primeBasisVector )
720 ERROR( "buildAddBasisElement", "Out of memory.");
721 addBasisElement = (unsigned short ***)
722 malloc( (primeDimension+1) * sizeof(unsigned short **));
723 if ( !addBasisElement )
724 ERROR( "buildAddBasisElement", "Out of memory.");
725 x = (FieldElement *) malloc( (C->length+2) * sizeof(FieldElement));
726 if ( !x )
727 ERROR( "buildAddBasisElement", "Out of memory.");
728 y = (FieldElement *) malloc( (C->length+2) * sizeof(FieldElement));
729 if ( !y )
730 ERROR( "buildAddBasisElement", "Out of memory.");
731
732 for ( i = 1 , primeRow = 0 ; i <= C->dimension ; ++i )
733 for ( m = 0 ; m < fieldExponent ; ++m ) {
734
735 /* This part works only for prime fields or GF(4). */
736 s = (m == 0) ? 1 : 2;
737 ++primeRow;
738 if ( m > 0 && C->fieldSize != 4 )
739 ERROR( "buildAddBasisElement", "Field whose order is not prime or 4.")
740 if ( C->fieldSize == 2 )
741 for ( k = 1 ; k <= C->length ; ++k )
742 primeBasisVector[k] = C->basis[i][k];
743 else
744 for ( k = 1 ; k <= C->length ; ++k )
745 primeBasisVector[k] = C->field->prod[C->basis[i][k]][s];
746 addBasisElement[primeRow] = (unsigned short **)
747 malloc( (largestPackedInteger+1) * sizeof(unsigned short **));
748 if ( !addBasisElement[primeRow] )
749 ERROR( "buildAddBasisElement", "Out of memory.")
750 for ( h = 1 ; h <= C->length ; ++h )
751 x[h] = 0;
752 for ( z = 0 ; z <= largestPackedInteger ; ++z ) {
753 if ( C->fieldSize == 2 )
754 for ( j = 1 ; j <= C->length ; ++j )
755 y[j] = primeBasisVector[j] ^ x[j];
756 else
757 for ( j = 1 ; j <= C->length ; ++j )
758 y[j] = C->field->sum[primeBasisVector[j]][x[j]];
759 addBasisElement[primeRow][z] = packNonBinaryCodeWord( C->fieldSize,
760 C->length, packingFactor, y);
761 a = 1;
762 while ( (a <= C->length) && (x[a] == C->fieldSize - 1 ) )
763 ++a;
764 ++x[a];
765 for ( h = 1; h < a ; ++h)
766 x[h] = 0;
767 for ( h = packingFactor+1 ; h <= C->length ; ++h )
768 x[h] = x[h-packingFactor];
769 }
770 }
771 free(primeBasisVector);
772 free(x);
773 free(y);
774 return addBasisElement;
775 }
776
777 /*-------------------------- destroyAddBasisElement -----------------------------------*/
778
779 /* This procedure destructs a data structure AddBasisElement */
780
destroyAddBasisElement(unsigned short *** addBasisElement,int primeDimension,int largestPackedInteger)781 void destroyAddBasisElement(unsigned short ***addBasisElement, int primeDimension, int largestPackedInteger) {
782 int i, j;
783 for (i = 1; i <= primeDimension; i++) {
784 for (j = 0; j <= largestPackedInteger; j++) {
785 free(addBasisElement[i][j]);
786 }
787 free(addBasisElement[i]);
788 }
789 free(addBasisElement);
790 }
791
792
793 /*-------------------------- generalWeightDist ----------------------------*/
794
generalWeightDist(const Code * const C,Unsigned saveWeight,const BOOLEAN oneCodeWordOnly,const Unsigned packingFactor,const Unsigned largestPackedInteger,const Unsigned packedLength,Unsigned * const allocatedSize,unsigned long * const freq,Matrix_01 * matrix)795 void generalWeightDist(
796 const Code *const C,
797 Unsigned saveWeight,
798 const BOOLEAN oneCodeWordOnly,
799 const Unsigned packingFactor,
800 const Unsigned largestPackedInteger,
801 const Unsigned packedLength,
802 Unsigned *const allocatedSize,
803 unsigned long *const freq,
804 Matrix_01 *matrix)
805 {
806 const Unsigned fieldExponent = (C->fieldSize == 2) ? 1 : C->field->exponent;
807 const Unsigned fieldCharacteristic =
808 (C->fieldSize == 2) ? 2 : C->field->characteristic;
809 const Unsigned primeDimension = C->dimension * fieldExponent;
810 Unsigned currentWeight, h, m, primeRow, packedCol, wt;
811 char *weight;
812 unsigned short ***addBasisElement;
813 unsigned short *currentWord; /* Array of size packedLength+1 */
814 Unsigned *x; /* Array of size primeDimension+1 */
815 FieldElement *vec;
816
817 /* Allocate the arrays x and currentWord. */
818 x = (Unsigned *) malloc( (primeDimension+1) * sizeof(Unsigned *));
819 if ( !x )
820 ERROR( "generalWeightDist", "Out of memory")
821 currentWord =
822 (unsigned short *) malloc( (packedLength+1) * sizeof(Unsigned *));
823 if ( !currentWord )
824 ERROR( "generalWeightDist", "Out of memory")
825
826 /* Construct the weight array. */
827 weight = buildWeightArray( C->fieldSize, packingFactor,
828 largestPackedInteger);
829
830 /* Construct structure AddBasisElement, used to add a prime basis codeword
831 to an arbitrary codeword. */
832 addBasisElement = buildAddBasisElement( C, packingFactor, packedLength,
833 largestPackedInteger);
834
835 /* Initialize freq and saveCount. Upon termination, freq will hold the
836 weight distribution. */
837 for ( wt = 1 ; wt <= C->length ; ++wt )
838 freq[wt] = 0;
839 freq[0] = 1;
840
841 /* Traverse the code. */
842 for ( h = C->dimension ; h >= 1 ; --h ) {
843
844 /* Traverse codewords of form 0*basis[1] +...+ 0*basis[h-1] +
845 1*basis[h] + (anything) * basis[h+1] +...+ (anything) * basis[k]),
846 where k is the dimension. */
847 for ( primeRow = 0 ; primeRow <= primeDimension ; ++primeRow )
848 x[primeRow] = 0;
849 for ( packedCol = 0 ; packedCol < packedLength ; ++packedCol )
850 currentWord[packedCol] = 0;
851 m = (h - 1) * fieldExponent + 1;
852
853 do {
854
855 /* Add prime basis codeword m to current word and find weight
856 of result. */
857 currentWeight = 0;
858 for ( packedCol = 0 ; packedCol < packedLength ; ++packedCol ) {
859 currentWord[packedCol] =
860 addBasisElement[m][currentWord[packedCol]][packedCol];
861 currentWeight += weight[currentWord[packedCol]];
862 }
863
864 /* Record weight. */
865 freq[currentWeight] += (C->fieldSize - 1);
866
867 /* Save the codeword, if appropriate. */
868 if ( currentWeight == saveWeight ) {
869 ++matrix->numberOfRows;
870 if ( matrix->numberOfRows > *allocatedSize ) {
871 *allocatedSize *= 2;
872 matrix->entry = (FieldElement **) realloc( matrix->entry,
873 *allocatedSize);
874 if ( !matrix->entry )
875 ERROR( "binaryWeightDist", "Out of memory.")
876 }
877 vec = matrix->entry[matrix->numberOfRows] =
878 malloc( (C->length+1) * sizeof(FieldElement) );
879 if ( !vec )
880 ERROR( "binaryWeightDist", "Out of memory.")
881 unpackNonBinaryCodeWord( C->fieldSize, C->length, packingFactor,
882 currentWord, vec);
883 if ( oneCodeWordOnly )
884 saveWeight = UNKNOWN+1;
885 }
886
887 /* Find m such that prime basis codeword number X[m] is the
888 basis codeword to add next. */
889 m = primeDimension;
890 while ( x[m] == fieldCharacteristic - 1 )
891 --m;
892
893 /* Adjust array X, which determines which basis codeword to add
894 next. */
895 ++x[m];
896 for ( primeRow = m+1 ; primeRow <= primeDimension ; ++primeRow )
897 x[primeRow] = 0;
898
899 } while ( m > h * fieldExponent );
900 }
901 free(currentWord);
902 free(x);
903 free(weight);
904 destroyAddBasisElement(addBasisElement, primeDimension, largestPackedInteger);
905
906
907 }
908
909 #ifdef xxxxxx
910
911 /*-------------------------- binaryCosetWeightDist -----------------------*/
912
binaryCosetWeightDist(const Code * const C,const Unsigned maxCosetWeight,const BOOLEAN oneCodeWordOnly,const Unsigned passes,Unsigned * const allocatedSize,unsigned long * const freq,Matrix_01 * const matrix)913 void binaryCosetWeightDist(
914 const Code *const C,
915 const Unsigned maxCosetWeight,
916 const BOOLEAN oneCodeWordOnly,
917 const Unsigned passes,
918 Unsigned *const allocatedSize,
919 unsigned long *const freq,
920 Matrix_01 *const matrix)
921 {
922 unsigned long sum;
923 const unsigned coDimension = C->length - C->dimension;
924 const unsigned long numberOfCosetsLess1 = (2L << coDimension) - 1;
925 const unsigned long maxCosetsPerPass = numberOfCosetsLess1 / passes + 1;
926
927 /* Initializations. */
928 for ( i = 0 ; i <=C->length ; ++i )
929 freq[i] = 0;
930 cw1 = cw2 = cw3 = cw4 = 0;
931
932 for ( wt = 1 ; wt <= maxCosetWeight && cosetsFound <= goal ; ++wt ) {
933 for ( i = 1 ; i <= wt ; ++i )
934
935
936 /* Write out the coset weight distribution. */
937 sumLess1 = 0;
938 if ( options.inform ) {
939 printf( "\n\n Coset Weight Distribution of code %s", C->name);
940 printf( "\n\n Coset Min Wt Number Of Cosets");
941 printf( "\n ------------ ----------------");
942 for ( i = 0 ; i <= maxCosetWeight ; ++i )
943 if ( freq[i] != 0 )
944 if ( i != 0 )
945 sumLess1 += freq[i];
946 printf( "\n %2u %10lu", i, freq[i]);
947 if ( sumLess1 < numberOfCosetsLess1 )
948 printf( "\n at least %2u %10lu", maxCosetWeight+1,
949 numberOfCosetsLess1 - sumLess1);
950 printf( "\n");
951 }
952 #endif
953
954 /*-------------------------- verifyOptions -------------------------------*/
955
956 static void verifyOptions(void)
957 {
958 CompileOptions mainOpts = { DEFAULT_MAX_BASE_SIZE, MAX_NAME_LENGTH,
959 MAX_PRIME_FACTORS,
960 MAX_REFINEMENT_PARMS, MAX_FAMILY_PARMS,
961 MAX_EXTRA, XLARGE, SGND, NFLT};
962 extern void xbitman( CompileOptions *cOpts);
963 extern void xcode ( CompileOptions *cOpts);
964 extern void xcopy ( CompileOptions *cOpts);
965 extern void xerrmes( CompileOptions *cOpts);
966 extern void xessent( CompileOptions *cOpts);
967 extern void xfactor( CompileOptions *cOpts);
968 extern void xfield ( CompileOptions *cOpts);
969 extern void xnew ( CompileOptions *cOpts);
970 extern void xpartn ( CompileOptions *cOpts);
971 extern void xpermut( CompileOptions *cOpts);
972 extern void xpermgr( CompileOptions *cOpts);
973 extern void xprimes( CompileOptions *cOpts);
974 extern void xreadde( CompileOptions *cOpts);
975 extern void xstorag( CompileOptions *cOpts);
976 extern void xtoken ( CompileOptions *cOpts);
977 extern void xutil ( CompileOptions *cOpts);
978
979 xbitman( &mainOpts);
980 xcode ( &mainOpts);
981 xcopy ( &mainOpts);
982 xerrmes( &mainOpts);
983 xessent( &mainOpts);
984 xfactor( &mainOpts);
985 xfield ( &mainOpts);
986 xnew ( &mainOpts);
987 xpartn ( &mainOpts);
988 xpermut( &mainOpts);
989 xpermgr( &mainOpts);
990 xprimes( &mainOpts);
991 xreadde( &mainOpts);
992 xstorag( &mainOpts);
993 xtoken ( &mainOpts);
994 xutil ( &mainOpts);
995 }
996