Merged master 8748
This commit is contained in:
@@ -1,754 +0,0 @@
|
||||
/* 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;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
|
||||
make-ldpc ex-ldpc36-1000a.pchk 1000 2000 1 evenboth 3 no4cycle
|
||||
Eliminated 24 cycles of length four by moving checks within column
|
||||
make-gen ex-ldpc36-1000a.pchk ex-ldpc36-1000a.gen dense
|
||||
Number of 1s per check in Inv(A) X B is 400.3
|
||||
rand-src ex-ldpc36-1000a.src 1 1000x100
|
||||
encode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.gen ex-ldpc36-1000a.src \
|
||||
ex-ldpc36-1000a.enc
|
||||
Encoded 100 blocks, source block size 1000, encoded block size 2000
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
|
||||
|
||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.80
|
||||
Transmitted 200000 bits
|
||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.80\
|
||||
prprp 250
|
||||
Decoded 100 blocks, 100 valid. Average 10.8 iterations, 11% bit changes
|
||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
||||
ex-ldpc36-1000a.src
|
||||
Block counts: tot 100, with chk errs 0, with src errs 0, both 0
|
||||
Bit error rate (on message bits only): 0.000e+00
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
|
||||
|
||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.85
|
||||
Transmitted 200000 bits
|
||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.85\
|
||||
prprp 250
|
||||
Decoded 100 blocks, 88 valid. Average 52.2 iterations, 12% bit changes
|
||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
||||
ex-ldpc36-1000a.src
|
||||
Block counts: tot 100, with chk errs 12, with src errs 12, both 12
|
||||
Bit error rate (on message bits only): 7.490e-03
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
|
||||
|
||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.90
|
||||
Transmitted 200000 bits
|
||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.90\
|
||||
prprp 250
|
||||
Decoded 100 blocks, 19 valid. Average 209.4 iterations, 11% bit changes
|
||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
||||
ex-ldpc36-1000a.src
|
||||
Block counts: tot 100, with chk errs 81, with src errs 81, both 81
|
||||
Bit error rate (on message bits only): 6.529e-02
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
|
||||
|
||||
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.95
|
||||
Transmitted 200000 bits
|
||||
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.95\
|
||||
prprp 250
|
||||
Decoded 100 blocks, 1 valid. Average 248.0 iterations, 9% bit changes
|
||||
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
|
||||
ex-ldpc36-1000a.src
|
||||
Block counts: tot 100, with chk errs 99, with src errs 99, both 99
|
||||
Bit error rate (on message bits only): 1.055e-01
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.2 KiB |
Reference in New Issue
Block a user