755 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			755 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* MOD2DENSE.C - Procedures for handling dense mod2 matrices. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* Copyright (c) 1995-2012 by Radford M. Neal.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Permission is granted for anyone to copy, use, modify, and distribute
							 | 
						||
| 
								 | 
							
								 * these programs and accompanying documents for any purpose, provided
							 | 
						||
| 
								 | 
							
								 * this copyright notice is retained and prominently displayed, and note
							 | 
						||
| 
								 | 
							
								 * is made of any changes made to these programs.  These programs and
							 | 
						||
| 
								 | 
							
								 * documents are distributed without any warranty, express or implied.
							 | 
						||
| 
								 | 
							
								 * As the programs were written for research purposes only, they have not
							 | 
						||
| 
								 | 
							
								 * been tested to the degree that would be advisable in any important
							 | 
						||
| 
								 | 
							
								 * application.  All use of these programs is entirely at the user's own
							 | 
						||
| 
								 | 
							
								 * risk.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* NOTE:  See mod2dense.html for documentation on these procedures. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdlib.h>
							 | 
						||
| 
								 | 
							
								#include <stdio.h>
							 | 
						||
| 
								 | 
							
								#include <math.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "alloc.h"
							 | 
						||
| 
								 | 
							
								#include "intio.h"
							 | 
						||
| 
								 | 
							
								#include "mod2dense.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ALLOCATE SPACE FOR A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mod2dense *mod2dense_allocate 
							 | 
						||
| 
								 | 
							
								( int n_rows, 		/* Number of rows in matrix */
							 | 
						||
| 
								 | 
							
								  int n_cols		/* Number of columns in matrix */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2dense *m;
							 | 
						||
| 
								 | 
							
								  int j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (n_rows<=0 || n_cols<=0)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_allocate: Invalid number of rows or columns\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m = chk_alloc (1, sizeof *m);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m->n_rows = n_rows;
							 | 
						||
| 
								 | 
							
								  m->n_cols = n_cols;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m->n_words = (n_rows+mod2_wordsize-1) >> mod2_wordsize_shift;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m->col = chk_alloc (m->n_cols, sizeof *m->col);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m->bits = chk_alloc(m->n_words*m->n_cols, sizeof *m->bits);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<m->n_cols; j++)
							 | 
						||
| 
								 | 
							
								  { m->col[j] = m->bits + j*m->n_words;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return m;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* FREE SPACE OCCUPIED BY A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_free
							 | 
						||
| 
								 | 
							
								( mod2dense *m		/* Matrix to free */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ if (m)
							 | 
						||
| 
								 | 
							
								  { free(m->bits);
							 | 
						||
| 
								 | 
							
								    free(m->col);
							 | 
						||
| 
								 | 
							
								    free(m);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* CLEAR A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_clear
							 | 
						||
| 
								 | 
							
								( mod2dense *r
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int k, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(r); j++)
							 | 
						||
| 
								 | 
							
								  { for (k = 0; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* COPY A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_copy
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* Matrix to copy */
							 | 
						||
| 
								 | 
							
								  mod2dense *r		/* Place to store copy of matrix */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int k, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m)>mod2dense_rows(r) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m)>mod2dense_cols(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_copy: Destination matrix is too small\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(m); j++)
							 | 
						||
| 
								 | 
							
								  { for (k = 0; k<m->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = m->col[j][k];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for ( ; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for ( ; j<mod2dense_cols(r); j++)
							 | 
						||
| 
								 | 
							
								  { for (k = 0; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* COPY ROWS OF A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_copyrows
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* Matrix to copy */
							 | 
						||
| 
								 | 
							
								  mod2dense *r,		/* Place to store copy of matrix */
							 | 
						||
| 
								 | 
							
								  int *rows		/* Indexes of rows to copy, from 0 */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int i, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_cols(m)>mod2dense_cols(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								      "mod2dense_copyrows: Destination matrix has fewer columns than source\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<mod2dense_rows(r); i++)
							 | 
						||
| 
								 | 
							
								  { if (rows[i]<0 || rows[i]>=mod2dense_rows(m))
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"mod2dense_copyrows: Row index out of range\n");
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for (j = 0; j<mod2dense_cols(m); j++)
							 | 
						||
| 
								 | 
							
								    { mod2dense_set(r,i,j,mod2dense_get(m,rows[i],j));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* COPY COLUMNS OF A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_copycols
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* Matrix to copy */
							 | 
						||
| 
								 | 
							
								  mod2dense *r,		/* Place to store copy of matrix */
							 | 
						||
| 
								 | 
							
								  int *cols		/* Indexes of columns to copy, from 0 */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int k, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m)>mod2dense_rows(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								      "mod2dense_copycols: Destination matrix has fewer rows than source\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(r); j++)
							 | 
						||
| 
								 | 
							
								  { if (cols[j]<0 || cols[j]>=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								    { fprintf(stderr,"mod2dense_copycols: Column index out of range\n");
							 | 
						||
| 
								 | 
							
								      exit(1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for (k = 0; k<m->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = m->col[cols[j]][k];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    for ( ; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* PRINT A DENSE MOD2 MATRIX IN HUMAN-READABLE FORM. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_print     
							 | 
						||
| 
								 | 
							
								( FILE *f,
							 | 
						||
| 
								 | 
							
								  mod2dense *m
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int i, j;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<mod2dense_rows(m); i++)
							 | 
						||
| 
								 | 
							
								  { for (j = 0; j<mod2dense_cols(m); j++)
							 | 
						||
| 
								 | 
							
								    { fprintf(f," %d",mod2dense_get(m,i,j));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    fprintf(f,"\n");
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* WRITE A DENSE MOD2 MATRIX TO A FILE IN MACHINE-READABLE FORM.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   Data is written using intio_write, so that it will be readable on a machine
							 | 
						||
| 
								 | 
							
								   with a different byte-ordering.  At present, this assumes that the words 
							 | 
						||
| 
								 | 
							
								   used to pack bits into are no longer than 32 bits. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_write     
							 | 
						||
| 
								 | 
							
								( FILE *f, 
							 | 
						||
| 
								 | 
							
								  mod2dense *m
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int j, k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  intio_write(f,m->n_rows);
							 | 
						||
| 
								 | 
							
								  if (ferror(f)) return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  intio_write(f,m->n_cols);
							 | 
						||
| 
								 | 
							
								  if (ferror(f)) return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(m); j++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    for (k = 0; k<m->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { intio_write(f,m->col[j][k]);
							 | 
						||
| 
								 | 
							
								      if (ferror(f)) return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* READ A DENSE MOD2 MATRIX STORED IN MACHINE-READABLE FORM FROM A FILE. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mod2dense *mod2dense_read  
							 | 
						||
| 
								 | 
							
								( FILE *f
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  int n_rows, n_cols;
							 | 
						||
| 
								 | 
							
								  mod2dense *m;
							 | 
						||
| 
								 | 
							
								  int j, k;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  n_rows = intio_read(f);
							 | 
						||
| 
								 | 
							
								  if (feof(f) || ferror(f) || n_rows<=0) return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  n_cols = intio_read(f);
							 | 
						||
| 
								 | 
							
								  if (feof(f) || ferror(f) || n_cols<=0) return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m = mod2dense_allocate(n_rows,n_cols);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(m); j++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    for (k = 0; k<m->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { m->col[j][k] = intio_read(f);
							 | 
						||
| 
								 | 
							
								      if (feof(f) || ferror(f)) 
							 | 
						||
| 
								 | 
							
								      { mod2dense_free(m);
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return m;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* GET AN ELEMENT FROM A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_get  
							 | 
						||
| 
								 | 
							
								( mod2dense *m, 	/* Matrix to get element from */
							 | 
						||
| 
								 | 
							
								  int row,		/* Row of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								  int col		/* Column of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (row<0 || row>=mod2dense_rows(m) || col<0 || col>=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_get: row or column index out of bounds\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return mod2_getbit (m->col[col][row>>mod2_wordsize_shift], 
							 | 
						||
| 
								 | 
							
								                      row&mod2_wordsize_mask);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* SET AN ELEMENT IN A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_set 
							 | 
						||
| 
								 | 
							
								( mod2dense *m, 	/* Matrix to modify element of */
							 | 
						||
| 
								 | 
							
								  int row,		/* Row of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								  int col,		/* Column of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								  int value		/* New value of element (0 or 1) */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{ 
							 | 
						||
| 
								 | 
							
								  mod2word *w;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (row<0 || row>=mod2dense_rows(m) || col<0 || col>=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_set: row or column index out of bounds\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  w = &m->col[col][row>>mod2_wordsize_shift];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  *w = value ? mod2_setbit1(*w,row&mod2_wordsize_mask) 
							 | 
						||
| 
								 | 
							
								             : mod2_setbit0(*w,row&mod2_wordsize_mask);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* FLIP AN ELEMENT OF A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_flip  
							 | 
						||
| 
								 | 
							
								( mod2dense *m, 	/* Matrix to flip element in */
							 | 
						||
| 
								 | 
							
								  int row,		/* Row of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								  int col		/* Column of element (starting with zero) */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2word *w;
							 | 
						||
| 
								 | 
							
								  int b;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (row<0 || row>=mod2dense_rows(m) || col<0 || col>=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_flip: row or column index out of bounds\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  b = 1 ^ mod2_getbit (m->col[col][row>>mod2_wordsize_shift], 
							 | 
						||
| 
								 | 
							
								                       row&mod2_wordsize_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  w = &m->col[col][row>>mod2_wordsize_shift];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  *w = b ? mod2_setbit1(*w,row&mod2_wordsize_mask) 
							 | 
						||
| 
								 | 
							
								         : mod2_setbit0(*w,row&mod2_wordsize_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return b;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* COMPUTE THE TRANSPOSE OF A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_transpose
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* Matrix to compute transpose of (left unchanged) */
							 | 
						||
| 
								 | 
							
								  mod2dense *r		/* Result of transpose operation */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2word w, v, *p;
							 | 
						||
| 
								 | 
							
								  int k1, j1, i2, j2;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m)!=mod2dense_cols(r) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m)!=mod2dense_rows(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								     "mod2dense_transpose: Matrices have incompatible dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (r==m)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr, 
							 | 
						||
| 
								 | 
							
								     "mod2dense_transpose: Result matrix is the same as the operand\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j1 = 0; j1<mod2dense_cols(m); j1++)
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    i2 = j1 >> mod2_wordsize_shift;
							 | 
						||
| 
								 | 
							
								    v = 1 << (j1 & mod2_wordsize_mask);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    p = m->col[j1];
							 | 
						||
| 
								 | 
							
								    k1 = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j2 = 0; j2<mod2dense_cols(r); j2++)
							 | 
						||
| 
								 | 
							
								    { if (k1==0)
							 | 
						||
| 
								 | 
							
								      { w = *p++;
							 | 
						||
| 
								 | 
							
								        k1 = mod2_wordsize;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (w&1)
							 | 
						||
| 
								 | 
							
								      { r->col[j2][i2] |= v;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      w >>= 1;     
							 | 
						||
| 
								 | 
							
								      k1 -= 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* ADD TWO DENSE MOD2 MATRICES. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_add
							 | 
						||
| 
								 | 
							
								( mod2dense *m1,	/* Left operand of add */
							 | 
						||
| 
								 | 
							
								  mod2dense *m2,	/* Right operand of add */
							 | 
						||
| 
								 | 
							
								  mod2dense *r		/* Place to store result of add */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int j, k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m1)!=mod2dense_rows(r) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m1)!=mod2dense_cols(r) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_rows(m2)!=mod2dense_rows(r)
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m2)!=mod2dense_cols(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_add: Matrices have different dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(r); j++)
							 | 
						||
| 
								 | 
							
								  { for (k = 0; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								    { r->col[j][k] = m1->col[j][k] ^ m2->col[j][k];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* MULTIPLY TWO DENSE MOD2 MATRICES. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   The algorithm used runs faster if the second matrix (right operand of the
							 | 
						||
| 
								 | 
							
								   multiply) is sparse, but it is also appropriate for dense matrices.  This
							 | 
						||
| 
								 | 
							
								   procedure could be speeded up a bit by replacing the call of mod2dense_get
							 | 
						||
| 
								 | 
							
								   with in-line code that avoids division, but this doesn't seem worthwhile
							 | 
						||
| 
								 | 
							
								   at the moment. 
							 | 
						||
| 
								 | 
							
								*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void mod2dense_multiply 
							 | 
						||
| 
								 | 
							
								( mod2dense *m1, 	/* Left operand of multiply */
							 | 
						||
| 
								 | 
							
								  mod2dense *m2,	/* Right operand of multiply */
							 | 
						||
| 
								 | 
							
								  mod2dense *r		/* Place to store result of multiply */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int i, j, k;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_cols(m1)!=mod2dense_rows(m2) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_rows(m1)!=mod2dense_rows(r) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m2)!=mod2dense_cols(r))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								     "mod2dense_multiply: Matrices have incompatible dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (r==m1 || r==m2)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								      "mod2dense_multiply: Result matrix is the same as one of the operands\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(r); j++)
							 | 
						||
| 
								 | 
							
								  { for (i = 0; i<mod2dense_rows(m2); i++)
							 | 
						||
| 
								 | 
							
								    { if (mod2dense_get(m2,i,j))
							 | 
						||
| 
								 | 
							
								      { for (k = 0; k<r->n_words; k++)
							 | 
						||
| 
								 | 
							
								        { r->col[j][k] ^= m1->col[i][k];
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* SEE WHETHER TWO DENSE MOD2 MATRICES ARE EQUAL. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_equal
							 | 
						||
| 
								 | 
							
								( mod2dense *m1,
							 | 
						||
| 
								 | 
							
								  mod2dense *m2
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  int k, j, w;
							 | 
						||
| 
								 | 
							
								  mod2word m;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m1)!=mod2dense_rows(m2) 
							 | 
						||
| 
								 | 
							
								   || mod2dense_cols(m1)!=mod2dense_cols(m2))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_equal: Matrices have different dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  w = m1->n_words;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* Form a mask that has 1s in the lower bit positions corresponding to
							 | 
						||
| 
								 | 
							
								     bits that contain information in the last word of a matrix column. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m = (1 << (mod2_wordsize - (w*mod2_wordsize-m1->n_rows))) - 1;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<mod2dense_cols(m1); j++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    for (k = 0; k<w-1; k++)
							 | 
						||
| 
								 | 
							
								    { if (m1->col[j][k] != m2->col[j][k]) return 0;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ((m1->col[j][k]&m) != (m2->col[j][k]&m)) return 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* INVERT A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_invert 
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* The matrix to find the inverse of (destroyed) */
							 | 
						||
| 
								 | 
							
								  mod2dense *r		/* Place to store the inverse */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2word *s, *t;
							 | 
						||
| 
								 | 
							
								  int i, j, k, n, w, k0, b0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m)!=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,"mod2dense_invert: Matrix to invert is not square\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (r==m)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr, 
							 | 
						||
| 
								 | 
							
								      "mod2dense_invert: Result matrix is the same as the operand\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  n = mod2dense_rows(m);
							 | 
						||
| 
								 | 
							
								  w = m->n_words;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(r)!=n || mod2dense_cols(r)!=n)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								     "mod2dense_invert: Matrix to receive inverse has wrong dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++) 
							 | 
						||
| 
								 | 
							
								  { mod2dense_set(r,i,i,1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    k0 = i >> mod2_wordsize_shift;
							 | 
						||
| 
								 | 
							
								    b0 = i & mod2_wordsize_mask;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j = i; j<n; j++) 
							 | 
						||
| 
								 | 
							
								    { if (mod2_getbit(m->col[j][k0],b0)) break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (j==n) return 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (j!=i)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      t = m->col[i];
							 | 
						||
| 
								 | 
							
								      m->col[i] = m->col[j];
							 | 
						||
| 
								 | 
							
								      m->col[j] = t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      t = r->col[i];
							 | 
						||
| 
								 | 
							
								      r->col[i] = r->col[j];
							 | 
						||
| 
								 | 
							
								      r->col[j] = t;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j = 0; j<n; j++)
							 | 
						||
| 
								 | 
							
								    { if (j!=i && mod2_getbit(m->col[j][k0],b0))
							 | 
						||
| 
								 | 
							
								      { s = m->col[j];
							 | 
						||
| 
								 | 
							
								        t = m->col[i];
							 | 
						||
| 
								 | 
							
								        for (k = k0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								        s = r->col[j];
							 | 
						||
| 
								 | 
							
								        t = r->col[i];
							 | 
						||
| 
								 | 
							
								        for (k = 0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* INVERT A DENSE MOD2 MATRIX WITH ROWS & COLUMNS SELECTED FROM BIGGER MATRIX.*/
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_invert_selected
							 | 
						||
| 
								 | 
							
								( mod2dense *m,		/* Matrix from which to pick a submatrix to invert */
							 | 
						||
| 
								 | 
							
								  mod2dense *r,		/* Place to store the inverse */
							 | 
						||
| 
								 | 
							
								  int *rows,		/* Set to indexes of rows used and not used */
							 | 
						||
| 
								 | 
							
								  int *cols		/* Set to indexes of columns used and not used */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2word *s, *t;
							 | 
						||
| 
								 | 
							
								  int i, j, k, n, n2, w, k0, b0, c, R;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (r==m)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr, 
							 | 
						||
| 
								 | 
							
								      "mod2dense_invert_selected2: Result matrix is the same as the operand\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  n = mod2dense_rows(m);
							 | 
						||
| 
								 | 
							
								  w = m->n_words;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  n2 = mod2dense_cols(m);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(r)!=n || mod2dense_cols(r)!=n2)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								"mod2dense_invert_selected2: Matrix to receive inverse has wrong dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { rows[i] = i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = 0; j<n2; j++)
							 | 
						||
| 
								 | 
							
								  { cols[j] = j;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  R = 0;
							 | 
						||
| 
								 | 
							
								  i = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (;;)
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    while (i<n-R)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      k0 = rows[i] >> mod2_wordsize_shift;
							 | 
						||
| 
								 | 
							
								      b0 = rows[i] & mod2_wordsize_mask;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (j = i; j<n2; j++) 
							 | 
						||
| 
								 | 
							
								      { if (mod2_getbit(m->col[cols[j]][k0],b0)) break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (j<n2) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      R += 1;
							 | 
						||
| 
								 | 
							
								      c = rows[i];
							 | 
						||
| 
								 | 
							
								      rows[i] = rows[n-R];
							 | 
						||
| 
								 | 
							
								      rows[n-R] = c;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (i==n-R) break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    c = cols[j];
							 | 
						||
| 
								 | 
							
								    cols[j] = cols[i];
							 | 
						||
| 
								 | 
							
								    cols[i] = c;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mod2dense_set(r,rows[i],c,1);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j = 0; j<n2; j++)
							 | 
						||
| 
								 | 
							
								    { if (j!=c && mod2_getbit(m->col[j][k0],b0))
							 | 
						||
| 
								 | 
							
								      { s = m->col[j];
							 | 
						||
| 
								 | 
							
								        t = m->col[c];
							 | 
						||
| 
								 | 
							
								        for (k = 0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								        s = r->col[j];
							 | 
						||
| 
								 | 
							
								        t = r->col[c];
							 | 
						||
| 
								 | 
							
								        for (k = 0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    i += 1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (j = n-R; j<n; j++)
							 | 
						||
| 
								 | 
							
								  { s = r->col[cols[j]];
							 | 
						||
| 
								 | 
							
								    for (k = 0; k<w; k++) s[k] = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return R;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* FORCIBLY INVERT A DENSE MOD2 MATRIX. */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mod2dense_forcibly_invert 
							 | 
						||
| 
								 | 
							
								( mod2dense *m, 	/* The matrix to find the inverse of (destroyed) */
							 | 
						||
| 
								 | 
							
								  mod2dense *r,		/* Place to store the inverse */
							 | 
						||
| 
								 | 
							
								  int *a_row,		/* Place to store row indexes of altered elements */
							 | 
						||
| 
								 | 
							
								  int *a_col		/* Place to store column indexes of altered elements */
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  mod2word *s, *t;
							 | 
						||
| 
								 | 
							
								  int i, j, k, n, w, k0, b0;
							 | 
						||
| 
								 | 
							
								  int u, c;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(m)!=mod2dense_cols(m))
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								      "mod2dense_forcibly_invert: Matrix to invert is not square\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (r==m)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr, 
							 | 
						||
| 
								 | 
							
								      "mod2dense_forcibly_invert: Result matrix is the same as the operand\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  n = mod2dense_rows(m);
							 | 
						||
| 
								 | 
							
								  w = m->n_words;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (mod2dense_rows(r)!=n || mod2dense_cols(r)!=n)
							 | 
						||
| 
								 | 
							
								  { fprintf(stderr,
							 | 
						||
| 
								 | 
							
								 "mod2dense_forcibly_invert: Matrix to receive inverse has wrong dimensions\n");
							 | 
						||
| 
								 | 
							
								    exit(1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  mod2dense_clear(r);
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++) 
							 | 
						||
| 
								 | 
							
								  { mod2dense_set(r,i,i,1);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { a_row[i] = -1;
							 | 
						||
| 
								 | 
							
								    a_col[i] = i;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { 
							 | 
						||
| 
								 | 
							
								    k0 = i >> mod2_wordsize_shift;
							 | 
						||
| 
								 | 
							
								    b0 = i & mod2_wordsize_mask;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j = i; j<n; j++) 
							 | 
						||
| 
								 | 
							
								    { if (mod2_getbit(m->col[j][k0],b0)) break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (j==n)
							 | 
						||
| 
								 | 
							
								    { j = i;
							 | 
						||
| 
								 | 
							
								      mod2dense_set(m,i,j,1);
							 | 
						||
| 
								 | 
							
								      a_row[i] = i;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (j!=i)
							 | 
						||
| 
								 | 
							
								    { 
							 | 
						||
| 
								 | 
							
								      t = m->col[i];
							 | 
						||
| 
								 | 
							
								      m->col[i] = m->col[j];
							 | 
						||
| 
								 | 
							
								      m->col[j] = t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      t = r->col[i];
							 | 
						||
| 
								 | 
							
								      r->col[i] = r->col[j];
							 | 
						||
| 
								 | 
							
								      r->col[j] = t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      u = a_col[i];
							 | 
						||
| 
								 | 
							
								      a_col[i] = a_col[j];
							 | 
						||
| 
								 | 
							
								      a_col[j] = u;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (j = 0; j<n; j++)
							 | 
						||
| 
								 | 
							
								    { if (j!=i && mod2_getbit(m->col[j][k0],b0))
							 | 
						||
| 
								 | 
							
								      { s = m->col[j];
							 | 
						||
| 
								 | 
							
								        t = m->col[i];
							 | 
						||
| 
								 | 
							
								        for (k = k0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								        s = r->col[j];
							 | 
						||
| 
								 | 
							
								        t = r->col[i];
							 | 
						||
| 
								 | 
							
								        for (k = 0; k<w; k++) s[k] ^= t[k];
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  c = 0;
							 | 
						||
| 
								 | 
							
								  for (i = 0; i<n; i++)
							 | 
						||
| 
								 | 
							
								  { if (a_row[i]!=-1)
							 | 
						||
| 
								 | 
							
								    { a_row[c] = a_row[i];
							 | 
						||
| 
								 | 
							
								      a_col[c] = a_col[i];
							 | 
						||
| 
								 | 
							
								      c += 1;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return c;
							 | 
						||
| 
								 | 
							
								}
							 |