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