Spring cleaning

This commit is contained in:
Bill Somerville 2018-06-05 17:44:06 +01:00
parent 3fa691b353
commit 0f33b7e6b5
149 changed files with 0 additions and 19300 deletions

View File

@ -1,15 +0,0 @@
Except as otherwise specified, all program code and documentation in this
directory is 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.
Some routines in the module rand.c are taken from the GNU C Library,
and are copyrighted as described there and in the file LGPL.

View File

@ -1,28 +0,0 @@
#!/bin/sh
# Copy the LPDC programs to the directory specified. The program file
# might be the name of the program, or (eg, on Cygwin) the name of the
# program with .exe appended.
if [ x$1 == x -o x$2 != x ]; then
echo Usage: LDPC-install bin-directory
exit 1
fi
echo Installing LPDC programs in $1
mkdir -p $1
for prog in make-pchk alist-to-pchk pchk-to-alist \
make-ldpc print-pchk make-gen print-gen \
rand-src encode transmit decode extract verify; do
if [ -f $prog ]; then
cp $prog $1
elif [ -f $prog.exe ]; then
cp $prog.exe $1
else
echo No program $prog to install
fi
done
echo Done

View File

@ -1,463 +0,0 @@
The following is the license under which the portions of the GNU C
library used in the rand.c module is distributed. Note that this
license does not apply to the rest of this software.
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of e Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

View File

@ -1,115 +0,0 @@
# MAKEFILE FOR LDPC PROGRAMS & ASSOCIATED UTILITIES.
# 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: The natural random numbers in "randfile" are accessed by the
# 'rand' module via a path to this directory. Change the definition of
# RAND_FILE in the compilation command for rand.c below if this is not
# appropriate.
# NOTE: This makefile is trivial, simply recompiling everything from
# scratch every time. Since this takes only about 5 seconds on a modern
# PC, there's no point in putting in dependency-based rules, which just
# make things more complex and error-prone.
COMPILE = cc -c -O # Command to compile a module from .c to .o
LINK = cc # Command to link a program
# MAKE ALL THE MAIN PROGRAMS. First makes the modules used.
progs: modules
$(COMPILE) make-pchk.c
$(LINK) make-pchk.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o alloc.o intio.o open.o -lm -o make-pchk
$(COMPILE) alist-to-pchk.c
$(LINK) alist-to-pchk.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o alloc.o intio.o open.o -lm -o alist-to-pchk
$(COMPILE) pchk-to-alist.c
$(LINK) pchk-to-alist.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o alloc.o intio.o open.o -lm -o pchk-to-alist
$(COMPILE) make-ldpc.c
$(LINK) make-ldpc.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o rand.o alloc.o intio.o open.o distrib.o -lm -o make-ldpc
$(COMPILE) print-pchk.c
$(LINK) print-pchk.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o rand.o alloc.o intio.o open.o -lm -o print-pchk
$(COMPILE) make-gen.c
$(LINK) make-gen.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o alloc.o intio.o open.o -lm -o make-gen
$(COMPILE) print-gen.c
$(LINK) print-gen.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o rand.o alloc.o intio.o open.o -lm -o print-gen
$(COMPILE) rand-src.c
$(LINK) rand-src.o rand.o open.o -lm -o rand-src
$(COMPILE) encode.c
$(LINK) encode.o mod2sparse.o mod2dense.o mod2convert.o \
enc.o rcode.o rand.o alloc.o intio.o blockio.o open.o -lm -o encode
$(COMPILE) transmit.c
$(LINK) transmit.o channel.o rand.o open.o -lm -o transmit
$(COMPILE) decode.c
$(LINK) decode.o channel.o mod2sparse.o mod2dense.o mod2convert.o \
enc.o check.o \
rcode.o rand.o alloc.o intio.o blockio.o dec.o open.o -lm -o decode
$(COMPILE) extract.c
$(LINK) extract.o mod2sparse.o mod2dense.o mod2convert.o \
rcode.o alloc.o intio.o blockio.o open.o -lm -o extract
$(COMPILE) verify.c
$(LINK) verify.o mod2sparse.o mod2dense.o mod2convert.o check.o \
rcode.o alloc.o intio.o blockio.o open.o -lm -o verify
# MAKE THE TEST PROGRAMS. First makes the modules used.
tests: modules
$(COMPILE) mod2dense-test.c
$(LINK) mod2dense-test.o mod2dense.o alloc.o intio.o \
-lm -o mod2dense-test
$(COMPILE) mod2sparse-test.c
$(LINK) mod2sparse-test.o mod2sparse.o alloc.o intio.o \
-lm -o mod2sparse-test
$(COMPILE) mod2convert-test.c
$(LINK) mod2convert-test.o mod2convert.o mod2dense.o mod2sparse.o \
alloc.o intio.o rand.o open.o -lm -o mod2convert-test
$(COMPILE) rand-test.c
$(LINK) rand-test.o rand.o -lm -o rand-test
# MAKE THE MODULES USED BY THE PROGRAMS.
modules:
$(COMPILE) rcode.c
$(COMPILE) channel.c
$(COMPILE) dec.c
$(COMPILE) enc.c
$(COMPILE) alloc.c
$(COMPILE) intio.c
$(COMPILE) blockio.c
$(COMPILE) check.c
$(COMPILE) open.c
$(COMPILE) mod2dense.c
$(COMPILE) mod2sparse.c
$(COMPILE) mod2convert.c
$(COMPILE) distrib.c
$(COMPILE) -DRAND_FILE=\"`pwd`/randfile\" rand.c
# CLEAN UP ALL PROGRAMS AND REMOVE ALL FILES PRODUCED BY TESTS AND EXAMPLES.
clean:
rm -f core *.o *.exe ex-*.* test-file \
make-pchk alist-to-pchk pchk-to-alist \
make-ldpc print-pchk make-gen print-gen \
rand-src encode transmit decode extract verify \
mod2dense-test mod2sparse-test mod2convert-test rand-test

View File

@ -1,39 +0,0 @@
# Compilers
CC = gcc
CXX = g++
FC = gfortran
AR = ar cr
RANLIB = ranlib
MKDIR = mkdir -p
CP = cp
RM = rm -f
FFLAGS = -O2 -fbounds-check -Wall -Wno-conversion
CFLAGS = -O2 -I.
# Default rules
%.o: %.c
${CC} ${CFLAGS} -c $<
%.o: %.f
${FC} ${FFLAGS} -c $<
%.o: %.F
${FC} ${FFLAGS} -c $<
%.o: %.f90
${FC} ${FFLAGS} -c $<
%.o: %.F90
${FC} ${FFLAGS} -c $<
all: ldpcsim
OBJS = ldpcsim.o alloc.o rcode.o dec.o enc.o \
intio.o blockio.o check.o open.o mod2dense.o \
mod2sparse.o mod2convert.o distrib.o rand.o gran.o
ldpcsim:$(OBJS)
$(FC) -o ldpcsim $(OBJS)
rand.o:
$(CC) $(CFLAGS) -DRAND_FILE=\"./randfile\" -c rand.c
clean:
$(RM) *.o msksim

View File

@ -1,6 +0,0 @@
This is a collection of programs and modules, written in C, that
support research and education concerning Low Density Parity Check
(LDPC) codes.
See index.html in this directory for an index to the documentation.
Copyright information can be found there, and in the file COPYRIGHT.

View File

@ -1,168 +0,0 @@
/* ALIST-TO-PCHK.C - Convert a parity check matrix from alist format. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "alloc.h"
#include "intio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
void bad_alist_file(void);
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *alist_file, *pchk_file;
FILE *af, *pf;
int mxrw, mxcw;
int *rw, *cw;
int i, j, k;
int tot, trans;
int nxt;
trans = 0;
for (;;)
{
if (argc>1 && strcmp(argv[1],"-t")==0)
{ trans = 1;
argc -= 1;
argv += 1;
}
else
{ break;
}
}
if (argc!=3)
{ usage();
}
pchk_file = argv[2];
alist_file = argv[1];
af = open_file_std(alist_file,"r");
if (af==NULL)
{ fprintf(stderr,"Can't open alist file: %s\n",alist_file);
exit(1);
}
if (fscanf(af,"%d",&M)!=1 || M<1
|| fscanf(af,"%d",&N)!=1 || N<1
|| fscanf(af,"%d",&mxrw)!=1 || mxrw<0 || mxrw>N
|| fscanf(af,"%d",&mxcw)!=1 || mxcw<0 || mxcw>M)
{ bad_alist_file();
}
rw = (int *) chk_alloc (M, sizeof *rw);
for (i = 0; i<M; i++)
{ if (fscanf(af,"%d",&rw[i])!=1 || rw[i]<0 || rw[i]>N)
{ bad_alist_file();
}
}
cw = (int *) chk_alloc (N, sizeof *cw);
for (j = 0; j<N; j++)
{ if (fscanf(af,"%d",&cw[j])!=1 || cw[j]<0 || cw[j]>M)
{ bad_alist_file();
}
}
H = mod2sparse_allocate(M,N);
do { if (fscanf(af,"%d",&nxt)!=1) nxt = -1; } while (nxt==0);
tot = 0;
for (i = 0; i<M; i++)
{ for (k = 0; k<rw[i]; k++)
{ if (nxt<=0 || nxt>N || mod2sparse_find(H,i,nxt-1))
{ bad_alist_file();
}
mod2sparse_insert(H,i,nxt-1);
tot += 1;
do { if (fscanf(af,"%d",&nxt)!=1) nxt = -1; } while (nxt==0);
}
}
for (j = 0; j<N; j++)
{ for (k = 0; k<cw[j]; k++)
{ if (nxt<=0 || nxt>M || !mod2sparse_find(H,nxt-1,j))
{ bad_alist_file();
}
tot -= 1;
do { if (fscanf(af,"%d",&nxt)!=1) nxt = -1; } while (nxt==0);
}
}
if (tot!=0 || nxt!=-1 || !feof(af))
{ bad_alist_file();
}
if (trans)
{ mod2sparse *HT;
HT = H;
H = mod2sparse_allocate(N,M);
mod2sparse_transpose(HT,H);
}
pf = open_file_std(pchk_file,"wb");
if (pf==NULL)
{ fprintf(stderr,"Can't create parity check file: %s\n",pchk_file);
exit(1);
}
intio_write(pf,('P'<<8)+0x80);
if (ferror(pf) || !mod2sparse_write(pf,H) || fclose(pf)!=0)
{ fprintf(stderr,"Error writing to parity check file %s\n",pchk_file);
exit(1);
}
return 0;
}
/* COMPLAIN THAT ALIST FILE IS BAD. */
void bad_alist_file()
{ fprintf(stderr,"Alist file doesn't have the right format\n");
exit(1);
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage: alist-to-pchk [ -t ] alist-file pchk-file\n");
exit(1);
}

View File

@ -1,42 +0,0 @@
/* ALLOC.C - Routine to allocate memory and complain if it doesn't work. */
/* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include "alloc.h"
/* ALLOCATE SPACE AND CHECK FOR ERROR. Calls 'calloc' to allocate space,
and then displays an error message and exits if the space couldn't be
found. */
void *chk_alloc
( unsigned n, /* Number of elements */
unsigned size /* Size of each element */
)
{
void *p;
p = calloc(n,size);
if (p==0)
{ fprintf(stderr,"Ran out of memory (while trying to allocate %d bytes)\n",
n*size);
exit(1);
}
return p;
}

View File

@ -1,18 +0,0 @@
/* ALLOC.H - Interface to memory allocation procedure. */
/* 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.
*/
void *chk_alloc (unsigned, unsigned); /* Calls 'calloc' and exits with error
if it fails */

View File

@ -1,85 +0,0 @@
/* BLOCKIO.C - Routines to read/write blocks of bits from/to a text file. */
/* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include "blockio.h"
int blockio_flush = 0; /* Should blocks written be immediately flushed? */
/* READ A BLOCK OF BITS. The bits must be given as '0' or '1' characters,
with whitespace allowed (but not required) between bits. Returns 0 if
a block is read successfully, and EOF if eof or an error occurs. If
EOF is returned, a warning will be printed if a partial block had already
been read. */
int blockio_read
( FILE *f, /* File to read from */
char *b, /* Place to store bits read */
int l /* Length of block */
)
{
int i, c;
for (i = 0; i<l; i++)
{
do
{ c = getc(f);
if (c==EOF)
{ if (i>0)
{ fprintf(stderr,
"Warning: Short block (%d long) at end of input file ignored\n",i);
}
return EOF;
}
} while (c==' ' || c=='\t' || c=='\n' || c=='\r');
if (c!='0' && c!='1')
{ fprintf(stderr,"Bad character in binary file (not '0' or '1')\n");
exit(1);
}
b[i] = c=='1';
}
return 0;
}
/* WRITE A BLOCK OF BITS. Bits are written as '0' and '1' characters, with
no spaces between them, followed by a newline. */
void blockio_write
( FILE *f, /* File to write to */
char *b, /* Block of bits to write */
int l /* Length of block */
)
{
int i;
for (i = 0; i<l; i++)
{ if (b[i]!=0 && b[i]!=1) abort();
putc("01"[b[i]],f);
}
putc('\n',f);
if (blockio_flush)
{ fflush(f);
}
}

View File

@ -1,19 +0,0 @@
/* BLOCKIO.H - Interface to block input/output routines. */
/* 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.
*/
extern int blockio_flush; /* Should blocks written be immediately flushed? */
int blockio_read (FILE *, char *, int);
void blockio_write (FILE *, char *, int);

View File

@ -1,99 +0,0 @@
/* CHANNEL.C - Procedures and variables regarding channels. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "channel.h"
/* GLOBAL VARIABLES. Declared in channel.h. */
channel_type channel; /* Type of channel */
double error_prob; /* Error probability for BSC */
double std_dev; /* Noise standard deviation for AWGN */
double lwidth; /* Width of noise distribution for AWLN */
/* PARSE A COMMAND-LINE SPECIFICATION OF A CHANNEL. Takes a pointer to an
argument list and an argument count; returns the number of arguments that
make up a channel specification at this point in the command line. Returns
zero if the argument list does not start with a channel specification.
Returns -1 if there seems to be a channel specification here, but it's
invalid.
Sets the variables declared in channel.h to the type and parameters of
the channel.
*/
int channel_parse
( char **argv, /* Pointer to argument list */
int argc /* Number of arguments in list */
)
{
char junk;
if (argc==0) return 0;
if (strcmp(argv[0],"bsc")==0 || strcmp(argv[0],"BSC")==0)
{
channel = BSC;
if (argc<2 || sscanf(argv[1],"%lf%c",&error_prob,&junk)!=1
|| error_prob<=0 || error_prob>=1)
{ return -1;
}
else
{ return 2;
}
}
else if (strcmp(argv[0],"awgn")==0 || strcmp(argv[0],"AWGN")==0)
{
channel = AWGN;
if (argc<2 || sscanf(argv[1],"%lf%c",&std_dev,&junk)!=1
|| std_dev<=0)
{ return -1;
}
else
{ return 2;
}
}
else if (strcmp(argv[0],"awln")==0 || strcmp(argv[0],"AWLN")==0)
{
channel = AWLN;
if (argc<2 || sscanf(argv[1],"%lf%c",&lwidth,&junk)!=1
|| lwidth<=0)
{ return -1;
}
else
{ return 2;
}
}
else
{
return 0;
}
}
/* PRINT USAGE MESSAGE REGARDING CHANNEL SPECIFICATIONS. */
void channel_usage(void)
{
fprintf(stderr,
"Channel: bsc error-probability | awgn standard-deviation | awln width\n");
}

View File

@ -1,32 +0,0 @@
/* CHANNEL.H - Declarations regarding channels. */
/* 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.
*/
/* TYPES OF CHANNEL, AND CHANNEL PARAMETERS. The global variables declared
here are located in channel.c. */
typedef enum { BSC, AWGN, AWLN } channel_type;
extern channel_type channel; /* Type of channel */
extern double error_prob; /* Error probability for BSC */
extern double std_dev; /* Noise standard deviation for AWGN */
extern double lwidth; /* Width of noise distributoin for AWLN */
/* PROCEDURES TO DO WITH CHANNELS. */
int channel_parse (char **, int);
void channel_usage (void);

View File

@ -1,182 +0,0 @@
<HTML><HEAD>
<TITLE> Transmission Through a Simulated Channel </TITLE>
</HEAD><BODY>
<H1> Transmission Through a Simulated Channel </H1>
<P>Once a codeword has been found to represent a source message, it
can be sent through a <I>channel</I>, with the result that certain
data is received as the output of the channel, which will be related
to the codeword sent, but with random noise. This software currently
handles only memoryless binary channels, for which each bit sent
through the channel results in a separate piece of data being
received, and the noise affecting one bit is independent of the noise
affecting other bits.
<P>For a <I>Binary Symmetric Channel</I> (BSC), each bit sent
results in a bit being received. The bit received differs from the
bit sent with some error probability, <I>p</I>, which is the same for
0 bits and for 1 bits. In other words, the probability distribution
for the bit received given the bit sent is as follows:
<BLOCKQUOTE>
P(receive 1 | send 1) = P(receive 0 | send 0) = 1-<I>p</I><BR>
P(receive 1 | send 0) = P(receive 0 | send 1) = <I>p</I>
</BLOCKQUOTE>
<P>For an <I>Additive White Gaussian Noise</I> (AWGN) channel, the
data received at each time is equal to the data sent plus Gaussian
noise with mean zero and some standard deviation, <I>s</I>,
independently for each bit. For this software, the data sent is -1
for a 0 bit and +1 for a 1 bit. In other words, the distribution
of the received data given the bit sent is as follows:
<BLOCKQUOTE>
data received | send 1 ~ N(+1,<I>s</I><SUP><SMALL>2</SMALL></SUP>)<BR>
data received | send 0 ~ N(-1,<I>s</I><SUP><SMALL>2</SMALL></SUP>)
</BLOCKQUOTE>
<P>It is typically assumed that the standard deviation of the noise
varies with the rate at which bits are sent, increasing in proportion
to the square root of the rate. The error rate obtained from sending
unencoded bits at rate <I>R</I> will then be the same as is obtained
using a code that repeats each bit <I>n</I> times, and sends these
bits at rate <I>nR</I> (assuming optimal decoding of each bit by
thresholding the sum of the <I>n</I> channel outputs corresponding to
that bit). Another way of looking at this scaling for <I>s</I> is
that when bits are send at a lower rate, the receiver will be
accumulating the channel output for a longer time, with the result
that the amount of noise will decrease (relative to the signal) as a
result of averaging.
<P>To account for this, it is common to compare codes for AWGN
channels in terms of their bit error rate and the value of
<BLOCKQUOTE>
<I>E<SUB><SMALL>b</SMALL></SUB></I> / <I>N<SUB><SMALL>0</SMALL></SUB></I>
= 1 / 2<I>R</I><I>s</I><SUP><SMALL>2</SMALL></SUP>
</BLOCKQUOTE>
at which they operate, where <I>R</I>=<I>K</I>/<I>N</I> is the rate
of the code, and <I>s</I> is the noise level at which the code
achieves the quoted bit error rate. Hence, a code operating at a lower
rate is allowed to assume a lower noise level to make the comparison fair.
It is common to quote
<I>E<SUB><SMALL>b</SMALL></SUB></I> /
<I>N<SUB><SMALL>0</SMALL></SUB></I> in decibels (db), equal to
10 log<SUB><SMALL>10</SMALL></SUB>(<I>E<SUB><SMALL>b</SMALL></SUB></I>
/ <I>N<SUB><SMALL>0</SMALL></SUB></I>).
<P>The <I>Additive White Logistic Noise</I> (AWLN) channel is similar
to the AWGN channel, except that the noise comes from a logistic rather
than a Gaussian distribution. The probability density function for the
noise is
<BLOCKQUOTE>
(1/<I>w</I>) exp(-<I>n</I>/<I>w</I>) / [1 + exp(-<I>n</I>/<I>w</I>)]<SUP>2</SUP>
</BLOCKQUOTE>
where <I>n</I> is the amount of noise, and <I>w</I> is a width parameter
for the distribution, analogous to the <I>s</I> parameter for
Gaussian noise. (However, <I>w</I> is not equal to the standard deviation
for the logistic distribution, which is
sqrt(pi<SUP><SMALL>2</SMALL></SUP>/3)<I>w</I>.) <B>Note:</B> Although I've
named this channel in analogy with the AWGN channel, it does not share
the properties discussed above regarding how noise levels would be expected
to change when the data rate changes.
<P><A NAME="transmit"><HR><B>transmit</B>: Transmit bits through a
simulated channel.
<BLOCKQUOTE><PRE>
transmit <I>encoded-file</I>|<I>n-zeros received-file seed channel</I>
</PRE>
<BLOCKQUOTE>
where <TT><I>channel</I></TT> is one of the following:
<BLOCKQUOTE><PRE>
bsc <I>error-probability</I>
awgn <I>standard-deviation</I>
awln <I>width</I>
</PRE></BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>Simulates the transmission of the bits in
<TT><I>encoded-file</I></TT> through a channel, with the received data
being stored in <TT><I>received-file</I></TT>. Typically,
<TT><I>encoded-file</I></TT> will have been produced by the <A
HREF="encoding.html#encode"><TT>encode</TT></A> program, but it could
also come from <A HREF="support.html#rand-src"><TT>rand-src</TT></A>
or another program. If newlines separate blocks in
<TT><I>encoded-file</I></TT>, these block boundaries will be preserved
in <TT><I>received-file</I></TT>.
<P>Alternatively, a count of zeros to transmit can be given, rather
than a <I>encoded-file</I>. This count can be the product of the
block size and the number of blocks, written with <TT>x</TT>
separating these numbers, with no spaces. The
<TT><I>received-file</I></TT> will mark the block boundaries with
newlines, assuming a block size of one if a simple bit count is given.
Note that zero messages are sufficient for assessing the performance
of a linear code with a symmetrical channel and a symmetrical decoding
algorithm. <B>Warning:</B> Ties, messages that lead to floating-point
overflow, and program bugs can easily make a decoding algorithm
non-symmetrical, so it's best not to test exclusively on zero
messages. Indeed, it is best not to do this at all unless you
really need to avoid the time needed to generate and encode random
messages.
<P>The transmission will be corrupted by random noise, which will be
generated pseudo-randomly based on <TT><I>seed</I></TT>. The actual
random seed used will be <TT><I>seed</I></TT> times 10 plus 3, so that
the stream of pseudo-random numbers will not be the same as any that
might have been used by another program.
<P>The fourth argument specifies the type of channel, currently either
<TT>bsc</TT> (or <TT>BSC</TT>) for the Binary Symmetric Channel, or
<TT>awgn</TT> (or <TT>AWGN</TT>) for the Additive White Gaussian
Noise channel, or <TT>awln</TT> (or <TT>AWLN</TT>) for the Additive White
Logistic Noise channel. The channel type is followed by an argument
specifying the characteristics of the channel, as follows:
<BLOCKQUOTE>
<P>BSC: The probability that a bit will be flipped by noise - ie, the
probability that the bit received is an error.
<P>AWGN: The standard deviation of the Gaussian noise that is added to the
encodings of the bits.
<P>AWLN: The width parameter of the logistic distribution for the noise
that is added to the encodings of the bits.
</BLOCKQUOTE>
See the description of <A HREF="channel.html">channel transmission</A>
for more details.
<P><B>Examples</B>: The command:
<UL><PRE>
<LI>transmit 10x3 rec 1 bsc 0.1
</PRE></UL>
will simulate the transmission of 30 zero bits (3 blocks of size 10) through
a Binary Symmetric Channel with error probability of 0.1. The result will
be to store something like the following in the file <TT>rec</TT>:
<BLOCKQUOTE><PRE>
0000000000
1000000000
0100000000
</PRE></BLOCKQUOTE>
If an AWGN channel is used instead, as follows:
<UL><PRE>
<LI>transmit 10x3 rec 1 awgn 0.5
</PRE></UL>
then the file <TT>rec</TT> will contain data such as:
<BLOCKQUOTE><PRE>
-1.36 -0.86 -0.80 -1.19 -1.18 -0.64 -0.31 -1.16 -1.56 -0.79
-2.20 -1.62 -0.53 -1.29 -1.08 -2.05 -0.75 -1.22 -0.81 -0.52
-0.86 -0.34 -1.10 -1.30 -1.10 -1.20 -0.37 -1.07 -0.22 -1.46
</PRE></BLOCKQUOTE>
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,177 +0,0 @@
/* CHECK.C - Compute parity checks and other stats on decodings. */
/* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mod2sparse.h"
#include "check.h"
/* COMPUTE PARITY CHECKS. Returns the number of parity checks violated by
dblk. The results of all the parity checks are stored in pchk. */
int check
( mod2sparse *H, /* Parity check matrix */
char *dblk, /* Guess for codeword */
char *pchk /* Place to store parity checks */
)
{
int M, i, c;
M = mod2sparse_rows(H);
mod2sparse_mulvec (H, dblk, pchk);
c = 0;
for (i = 0; i<M; i++)
{ c += pchk[i];
}
return c;
}
/* COUNT HOW MANY BITS HAVED CHANGED FROM BIT INDICATED BY LIKELIHOOD. The
simple decoding based on likelihood ratio is compared to the given decoding.
A bit for which the likelihood ratio is exactly one counts as half a
change, which explains why the result is a double rather than an int.
*/
double changed
( double *lratio, /* Likelihood ratios for bits */
char *dblk, /* Candidate decoding */
int N /* Number of bits */
)
{
double changed;
int j;
changed = 0;
for (j = 0; j<N; j++)
{ changed += lratio[j]==1 ? 0.5 : dblk[j] != (lratio[j]>1);
}
return changed;
}
/* COMPUTE THE EXPECTED NUMBER OF PARITY CHECK ERRORS. Computes the
expected number of parity check errors with respect to the distribution
given by the bit probabilities passed, with bits assumed to be independent.
*/
double expected_parity_errors
( mod2sparse *H, /* Parity check matrix */
double *bpr /* Bit probabilities */
)
{
mod2entry *f;
double ee, p;
int M, i, j;
M = mod2sparse_rows(H);
ee = 0;
for (i = 0; i<M; i++)
{ p = 0;
for (f = mod2sparse_first_in_row(H,i);
!mod2sparse_at_end(f);
f = mod2sparse_next_in_row(f))
{ j = mod2sparse_col(f);
p = p * (1-bpr[j]) + (1-p) * bpr[j];
}
ee += p;
}
return ee;
}
/* COMPUTE LOG LIKELIHOOD OF A DECODING. */
double loglikelihood
( double *lratio, /* Likelihood ratios for bits */
char *bits, /* Bits in decoding */
int N /* Length of codeword */
)
{
double ll;
int j;
ll = 0;
for (j = 0; j<N; j++)
{ ll -= bits[j] ? log(1+1/lratio[j]) : log(1+lratio[j]);
}
return ll;
}
/* COMPUTE THE EXPECTED LOG LIKELIHOOD BASED ON BIT PROBABILITIES. Computes
the expected value of the log likelihood with respect to the distribution
given by the bit probabilities passed, with bits assumed to be independent.
*/
double expected_loglikelihood
( double *lratio, /* Likelihood ratios for bits */
double *bpr, /* Bit probabilities */
int N /* Length of codeword */
)
{
double ll;
int j;
ll = 0;
for (j = 0; j<N; j++)
{ if (bpr[j]>0)
{ ll -= bpr[j]*log(1+1/lratio[j]);
}
if (bpr[j]<1)
{ ll -= (1-bpr[j])*log(1+lratio[j]);
}
}
return ll;
}
/* COMPUTE ENTROPY FROM BIT PROBABILITIES. Computes the entropy of the
distribution given by the bit probabilities, on the assumption that
bits are independent.
*/
double entropy
( double *bpr, /* Bit probabilities */
int N /* Length of codeword */
)
{
double e;
int j;
e = 0;
for (j = 0; j<N; j++)
{ if (bpr[j]>0 && bpr[j]<1)
{ e -= bpr[j]*log(bpr[j]) + (1-bpr[j])*log(1-bpr[j]);
}
}
return e/log(2.0);
}

View File

@ -1,25 +0,0 @@
/* CHECK.H - Interface to procedure for computing parity checks, etc. */
/* 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.
*/
int check (mod2sparse *, char *, char *);
double changed (double *, char *, int);
double expected_parity_errors (mod2sparse *, double *);
double loglikelihood (double *, char *, int);
double expected_loglikelihood (double *, double *, int);
double entropy (double *, int);

View File

@ -1,420 +0,0 @@
/* DEC.C - Decoding procedures. */
/* 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 decoding.html for general documentation on the decoding methods */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "alloc.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
/*#include "rand.h"*/
#include "rcode.h"
#include "check.h"
#include "dec.h"
#include "enc.h"
/* GLOBAL VARIABLES. Declared in dec.h. */
decoding_method dec_method; /* Decoding method to use */
int ldpc_table; /* Trace option, 2 for a table of decoding details */
int block_no; /* Number of current block, from zero */
int max_iter; /* Maximum number of iteratons of decoding to do */
char *gen_file; /* Generator file for Enum_block and Enum_bit */
/* DECODE BY EXHAUSTIVE ENUMERATION. Decodes by trying all possible source
messages (and hence all possible codewords, unless the parity check matrix
was redundant). If the last argument is 1, it sets dblk to the most likely
entire block; if this argument is 0, each bit of dblk is set to the most
likely value for that bit. The marginal probabilities of each bit being 1
are returned in bitpr.
The function value returned is the total number of codewords tried (which
will be the same for all blocks). The return valued is "unsigned" because
it might conceivably be as big as 2^31.
The parity check matrix and other data are taken from the global variables
declared in rcode.h.
The number of message bits should not be greater than 31 for this procedure.
The setup procedure immediately below checks this, reads the generator file,
and outputs headers for the detailed trace file, if required.
*/
void enum_decode_setup(void)
{
read_gen(gen_file,0,0);
if (N-M>31)
{ fprintf(stderr,
"Trying to decode messages with %d bits by exhaustive enumeration is absurd!\n",
N-M);
exit(1);
}
if (ldpc_table==2)
{ printf(" block decoding likelihood\n");
}
}
unsigned enum_decode
( double *lratio, /* Likelihood ratios for bits */
char *dblk, /* Place to stored decoded message */
double *bitpr, /* Place to store marginal bit probabilities */
int max_block /* Maximize probability of whole block being correct? */
)
{
mod2dense *u, *v;
double lk, maxlk, tpr;
double *bpr, *lk0, *lk1;
char sblk[31];
char *cblk;
unsigned d;
int i, j;
if (N-M>31) abort();
/* Allocate needed space. */
bpr = bitpr;
if (bpr==0 && max_block==0)
{ bpr = chk_alloc (N, sizeof *bpr);
}
cblk = chk_alloc (N, sizeof *cblk);
if (type=='d')
{ u = mod2dense_allocate(N-M,1);
v = mod2dense_allocate(M,1);
}
if (type=='m')
{ u = mod2dense_allocate(M,1);
v = mod2dense_allocate(M,1);
}
lk0 = chk_alloc (N, sizeof *lk0);
lk1 = chk_alloc (N, sizeof *lk1);
/* Pre-compute likelihoods for bits. */
for (j = 0; j<N; j++)
{ lk0[j] = 1/(1+lratio[j]);
lk1[j] = 1 - lk0[j];
}
/* Initialize marginal bit probabilities. */
if (bpr)
{ for (j = 0; j<N; j++) bpr[j] = 0.0;
}
/* Exhaustively try all possible decoded messages. */
tpr = 0.0;
for (d = 0; d<=(1<<(N-M))-1; d++)
{
/* Unpack message into source block. */
for (i = N-M-1; i>=0; i--)
{ sblk[i] = (d>>i)&1;
}
/* Find full codeword for this message. */
switch (type)
{ case 's':
{ sparse_encode (sblk, cblk);
break;
}
case 'd':
{ dense_encode (sblk, cblk, u, v);
break;
}
case 'm':
{ mixed_encode (sblk, cblk, u, v);
break;
}
}
/* Compute likelihood for this decoding. */
lk = 1;
for (j = 0; j<N; j++)
{ lk *= cblk[j]==0 ? lk0[j] : lk1[j];
}
/* Update maximum likelihood decoding. */
if (max_block)
{ if (d==0 || lk>maxlk)
{ for (j = 0; j<N; j++)
{ dblk[j] = cblk[j];
}
maxlk = lk;
}
}
/* Update bit probabilities. */
if (bpr)
{ for (j = 0; j<N; j++)
{ if (cblk[j]==1)
{ bpr[j] += lk;
}
}
tpr += lk;
}
/* Output data to trace file. */
if (ldpc_table==2)
{ printf("%7d %10x %10.4e\n",block_no,d,lk);
}
}
/* Normalize bit probabilities. */
if (bpr)
{ for (j = 0; j<N; j++) bpr[j] /= tpr;
}
/* Decoding to maximize bit-by-bit success, if that's what's wanted.
In case of a tie, decode to a 1. */
if (!max_block)
{ for (j = 0; j<N; j++)
{ dblk[j] = bpr[j]>=0.5;
}
}
/* Free space. */
if (bpr!=0 && bpr!=bitpr) free(bpr);
free(cblk);
free(lk0);
free(lk1);
return 1<<(N-M);
}
/* DECODE USING PROBABILITY PROPAGATION. Tries to find the most probable
values for the bits of the codeword, given a parity check matrix (H), and
likelihood ratios (lratio) for each bit. If max_iter is positive, up to
that many iterations of probability propagation are done, stopping before
then if the tentative decoding is a valid codeword. If max_iter is
negative, abs(max_iter) iterations are done, regardless of whether a
codeword was found earlier.
Returns the number of iterations done (as an "unsigned" for consistency
with enum_decode). Regardless of whether or not a valid codeword was
reached, the bit vector from thresholding the bit-by-bit probabilities is
stored in dblk, and the resulting parity checks are stored in pchk (all
will be zero if the codeword is valid). The final probabilities for each
bit being a 1 are stored in bprb.
The setup procedure immediately below outputs headers for the detailed trace
file, if required.
*/
void prprp_decode_setup (void)
{
if (ldpc_table==2)
{ printf(
" block iter changed perrs loglik Eperrs Eloglik entropy\n");
}
}
unsigned prprp_decode
( mod2sparse *H, /* Parity check matrix */
double *lratio, /* Likelihood ratios for bits */
char *dblk, /* Place to store decoding */
char *pchk, /* Place to store parity checks */
double *bprb /* Place to store bit probabilities */
)
{
int N, n, c;
N = mod2sparse_cols(H);
/* Initialize probability and likelihood ratios, and find initial guess. */
initprp(H,lratio,dblk,bprb);
/* Do up to abs(max_iter) iterations of probability propagation, stopping
early if a codeword is found, unless max_iter is negative. */
for (n = 0; ; n++)
{
c = check(H,dblk,pchk);
if (ldpc_table==2)
{ printf("%7d %5d %8.1f %6d %+9.2f %8.1f %+9.2f %7.1f\n",
block_no, n, changed(lratio,dblk,N), c, loglikelihood(lratio,dblk,N),
expected_parity_errors(H,bprb), expected_loglikelihood(lratio,bprb,N),
entropy(bprb,N));
}
if (n==max_iter || n==-max_iter || (max_iter>0 && c==0))
{ break;
}
iterprp(H,lratio,dblk,bprb);
}
return n;
}
/* INITIALIZE PROBABILITY PROPAGATION. Stores initial ratios, probabilities,
and guess at decoding. */
void initprp
( mod2sparse *H, /* Parity check matrix */
double *lratio, /* Likelihood ratios for bits */
char *dblk, /* Place to store decoding */
double *bprb /* Place to store bit probabilities, 0 if not wanted */
)
{
mod2entry *e;
int N;
int j;
N = mod2sparse_cols(H);
for (j = 0; j<N; j++)
{ for (e = mod2sparse_first_in_col(H,j);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_col(e))
{ e->pr = lratio[j];
e->lr = 1;
}
if (bprb) bprb[j] = 1 - 1/(1+lratio[j]);
dblk[j] = lratio[j]>=1;
}
}
/* DO ONE ITERATION OF PROBABILITY PROPAGATION. */
void iterprp
( mod2sparse *H, /* Parity check matrix */
double *lratio, /* Likelihood ratios for bits */
char *dblk, /* Place to store decoding */
double *bprb /* Place to store bit probabilities, 0 if not wanted */
)
{
double pr, dl, t;
mod2entry *e;
int N, M;
int i, j;
M = mod2sparse_rows(H);
N = mod2sparse_cols(H);
/* Recompute likelihood ratios. */
for (i = 0; i<M; i++)
{ dl = 1;
for (e = mod2sparse_first_in_row(H,i);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_row(e))
{ e->lr = dl;
dl *= 2/(1+e->pr) - 1;
}
dl = 1;
for (e = mod2sparse_last_in_row(H,i);
!mod2sparse_at_end(e);
e = mod2sparse_prev_in_row(e))
{ t = e->lr * dl;
e->lr = (1-t)/(1+t);
dl *= 2/(1+e->pr) - 1;
}
}
/* Recompute probability ratios. Also find the next guess based on the
individually most likely values. */
for (j = 0; j<N; j++)
{ pr = lratio[j];
for (e = mod2sparse_first_in_col(H,j);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_col(e))
{ e->pr = pr;
pr *= e->lr;
}
if (isnan(pr))
{ pr = 1;
}
if (bprb) bprb[j] = 1 - 1/(1+pr);
dblk[j] = pr>=1;
pr = 1;
for (e = mod2sparse_last_in_col(H,j);
!mod2sparse_at_end(e);
e = mod2sparse_prev_in_col(e))
{ e->pr *= pr;
if (isnan(e->pr))
{ e->pr = 1;
}
pr *= e->lr;
}
}
}
void ldpc_decode_ ( double lratio[], char decoded[], int *max_iterations, int *niterations, int *max_dither, int *ndither)
{
int i, j, itry, valid;
char dblk[N],pchk[M];
double bprb[N],lr[N];
float fac;
max_iter=*max_iterations;
srand(-1);
for (itry=0; itry< *max_dither; itry++) {
for (i=0; i<N; i++) {
if( itry == 0 ) {
fac=0.0;
} else {
fac=(rand()%1024-512)/512.0;
}
lr[i]=lratio[i]*exp(fac);
}
*niterations = prprp_decode ( H, lr, dblk, pchk, bprb );
valid = check( H, dblk, pchk )==0;
if( !valid ) {
*niterations=-1;
} else {
j=0;
for( i=M; i<N; i++ ) {
decoded[j]=dblk[cols[i]];
j=j+1;
}
*ndither=itry;
// printf("ldpc_decode %d %d \n",*niterations, *ndither);
return;
}
}
}

View File

@ -1,43 +0,0 @@
/* DEC.H - Interface to decoding procedures. */
/* 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.
*/
/* DECODING METHOD, ITS PARAMETERS, AND OTHER VARIABLES. The global variables
declared here are located in dec.c. */
typedef enum
{ Enum_block, Enum_bit, Prprp
} decoding_method;
extern decoding_method dec_method; /* Decoding method to use */
extern int ldpc_table; /* Trace option, 2 for a table of decoding details */
extern int block_no; /* Number of current block, from zero */
extern int max_iter; /* Maximum number of iteratons of decoding to do */
extern char *gen_file; /* Generator file for Enum_block and Enum_bit */
/* PROCEDURES RELATING TO DECODING METHODS. */
void enum_decode_setup (void);
unsigned enum_decode (double *, char *, double *, int);
void prprp_decode_setup (void);
unsigned prprp_decode
(mod2sparse *, double *, char *, char *, double *);
void initprp (mod2sparse *, double *, char *, double *);
void iterprp (mod2sparse *, double *, char *, double *);

View File

@ -1,99 +0,0 @@
<HTML><HEAD>
<TITLE> Detailed Decoding Trace Information </TITLE>
</HEAD><BODY>
<H1> Detailed Decoding Trace Information </H1>
The <B>-T</B> option to <A HREF="decoding.html#decode"><TT>decode</TT></A>
causes a detailed trace of information on the process of decoding to
be written to standard output, in a multi-column format, with the first
line containing the headers for each column. This format is suitable
for reading into S-Plus or R.
The first column is always the number of the block being decoded;
several lines may be output for each block. The other columns vary
with the decoding method used, as described below.
<H2>Enum-bit and Enum-block decoding methods</H2>
For source messages with <I>K</I> bits, 2<SUP><I>K</I></SUP> lines are output
for each block, containing the following information:
<BLOCKQUOTE>
<TABLE>
<tr align="left" valign="top">
<td> <B>block</B> </td>
<td>The number of the block, from zero</td></tr>
<tr align="left" valign="top">
<td> <B>decoding</B> </td>
<td>A possible decoding for the message bits, expressed as a hexadecimal
number. The other bits are determined by the message bits.</td></tr>
<tr align="left" valign="top">
<td> <B>likelihood</B> </td>
<td>The likelihood for this decoding (ie, the probability of obtaining
the data received if this was the message sent).</td></tr>
</TABLE>
</BLOCKQUOTE>
For these methods, the number of "iterations" (output with the
<B>-t</B> option) is always 2<SUP><I>K</I></SUP>.
<H2>Prprp decoding method</H2>
Each block results in one line of output for the initial state (based
on individual likelihood ratios), and one line for each subsequent
iteration, containing the following information:
<BLOCKQUOTE>
<TABLE>
<tr align="left" valign="top">
<td> <B>block</B> </td>
<td>The number of the block, from zero</td></tr>
<tr align="left" valign="top">
<td> <B>iter</B> </td>
<td>The number of an iteration, zero for the initial state.</td></tr>
<tr align="left" valign="top">
<td> <B>changed</B> </td>
<td>The number of bits in the decoding that differ from the bit that would
be chosen based just on the likelihood ratio for that bit. Bits whose
likelihood ratios are exactly one contribute 0.5 to this
count. (Likelihood ratios of exactly one can arise when the output
of an AWGN channel rounds to exactly 0.00.)</td></tr>
<tr align="left" valign="top">
<td> <B>perrs</B> </td>
<td>The number of parity check errors in the current tentative
decoding.</td></tr>
<tr align="left" valign="top">
<td> <B>loglik</B> </td>
<td>The log likelihood of the current tentative decoding.</td></tr>
<tr align="left" valign="top">
<td> <B>Eperrs</B> </td>
<td>The expected number of parity check errors in a decoding found
by randomly picking a value for each bit, independently, according
to the current bit probabilities.</td></tr>
<tr align="left" valign="top">
<td> <B>Eloglik</B> </td>
<td>The expected log likelihood of a decoding found by randomly picking
a value for each bit, independently, according to the current bit
probabilities.
</td></tr>
<tr align="left" valign="top">
<td> <B>entropy</B> </td>
<td>The entropy (in bits) of the distribution defined by the current bit
probablities, assumed to apply to bits independently.</td></tr>
</TABLE>
</BLOCKQUOTE>
The number of "iterations" (output with the <B>-t</B> option) is
the obvious count of probability propagation iterations. The
initial state does not count as an iteration.
<HR>
<A HREF="decoding.html">Back to decoding documentation</A><BR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,384 +0,0 @@
/* DECODE.C - Decode blocks of received data. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "rand.h"
#include "alloc.h"
#include "blockio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "channel.h"
#include "rcode.h"
#include "check.h"
#include "dec.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *pchk_file, *rfile, *dfile, *pfile;
char **meth;
FILE *rf, *df, *pf;
char *dblk, *pchk;
double *lratio;
double *bitpr;
double *awn_data; /* Places to store channel data */
int *bsc_data;
unsigned iters; /* Unsigned because can be huge for enum */
double tot_iter; /* Double because can be huge for enum */
double chngd, tot_changed; /* Double because can be fraction if lratio==1*/
int tot_valid;
char junk;
int valid;
int i, j, k;
/* Look at initial flag arguments. */
ldpc_table = 0;
blockio_flush = 0;
while (argc>1)
{
if (strcmp(argv[1],"-t")==0)
{ if (ldpc_table!=0) usage();
ldpc_table = 1;
}
else if (strcmp(argv[1],"-T")==0)
{ if (ldpc_table!=0) usage();
ldpc_table = 2;
}
else if (strcmp(argv[1],"-f")==0)
{ if (blockio_flush!=0) usage();
blockio_flush = 1;
}
else
{ break;
}
argc -= 1;
argv += 1;
}
/* Look at arguments up to the decoding method specification. */
if (!(pchk_file = argv[1])
|| !(rfile = argv[2])
|| !(dfile = argv[3]))
{ usage();
}
if (argv[4]==0 || argv[5]==0) usage();
k = channel_parse(argv+4,argc-4);
if (k<=0)
{ pfile = argv[4];
k = channel_parse(argv+5,argc-5);
if (k<=0) usage();
meth = argv+5+k;
}
else
{ pfile = 0;
meth = argv+4+k;
}
/* Look at the specification of the decoding method, which starts at meth and
continues to the end of the command line (marked by a zero pointer). */
if (!meth[0]) usage();
if (strcmp(meth[0],"prprp")==0)
{ dec_method = Prprp;
if (!meth[1] || sscanf(meth[1],"%d%c",&max_iter,&junk)!=1 || meth[2])
{ usage();
}
}
else if (strcmp(meth[0],"enum-block")==0)
{ dec_method = Enum_block;
if (!(gen_file = meth[1]) || meth[2]) usage();
}
else if (strcmp(meth[0],"enum-bit")==0)
{ dec_method = Enum_bit;
if (!(gen_file = meth[1]) || meth[2]) usage();
}
else
{ usage();
}
/* Check that we aren't overusing standard input or output. */
if ((strcmp(pchk_file,"-")==0)
+ (strcmp(rfile,"-")==0) > 1)
{ fprintf(stderr,"Can't read more than one stream from standard input\n");
exit(1);
}
if ((ldpc_table>0)
+ (strcmp(dfile,"-")==0)
+ (pfile!=0 && strcmp(pfile,"-")==0) > 1)
{ fprintf(stderr,"Can't send more than one stream to standard output\n");
exit(1);
}
/* Read parity check file. */
read_pchk(pchk_file);
if (N<=M)
{ fprintf(stderr,
"Number of bits (%d) should be greater than number of checks (%d)\n",N,M);
exit(1);
}
/* Open file of received data. */
rf = open_file_std(rfile,"r");
if (rf==NULL)
{ fprintf(stderr,"Can't open file of received data: %s\n",rfile);
exit(1);
}
/* Create file for decoded data. */
df = open_file_std(dfile,"w");
if (df==NULL)
{ fprintf(stderr,"Can't create file for decoded data: %s\n",dfile);
exit(1);
}
/* Create file for bit probabilities, if specified. */
if (pfile)
{ pf = open_file_std(pfile,"w");
if (pf==NULL)
{ fprintf(stderr,"Can't create file for bit probabilities: %s\n",pfile);
exit(1);
}
}
/* Allocate space for data from channel. */
switch (channel)
{ case BSC:
{ bsc_data = chk_alloc (N, sizeof *bsc_data);
break;
}
case AWGN: case AWLN:
{ awn_data = chk_alloc (N, sizeof *awn_data);
break;
}
default:
{ abort();
}
}
/* Allocate other space. */
dblk = chk_alloc (N, sizeof *dblk);
lratio = chk_alloc (N, sizeof *lratio);
pchk = chk_alloc (M, sizeof *pchk);
bitpr = chk_alloc (N, sizeof *bitpr);
/* Print header for summary table. */
if (ldpc_table==1)
{ printf(" block iterations valid changed\n");
}
/* Do the setup for the decoding method. */
switch (dec_method)
{ case Prprp:
{ prprp_decode_setup();
break;
}
case Enum_block: case Enum_bit:
{ enum_decode_setup();
break;
}
default: abort();
}
/* Read received blocks, decode, and write decoded blocks. */
tot_iter = 0;
tot_valid = 0;
tot_changed = 0;
for (block_no = 0; ; block_no++)
{
/* Read block from received file, exit if end-of-file encountered. */
for (i = 0; i<N; i++)
{ int c;
switch (channel)
{ case BSC:
{ c = fscanf(rf,"%1d",&bsc_data[i]);
break;
}
case AWGN: case AWLN:
{ c = fscanf(rf,"%lf",&awn_data[i]);
break;
}
default: abort();
}
if (c==EOF)
{ if (i>0)
{ fprintf(stderr,
"Warning: Short block (%d long) at end of received file ignored\n",i);
}
goto done;
}
if (c<1 || channel==BSC && bsc_data[i]!=0 && bsc_data[i]!=1)
{ fprintf(stderr,"File of received data is garbled\n");
exit(1);
}
}
/* Find likelihood ratio for each bit. */
switch (channel)
{ case BSC:
{ for (i = 0; i<N; i++)
{ lratio[i] = bsc_data[i]==1 ? (1-error_prob) / error_prob
: error_prob / (1-error_prob);
}
break;
}
case AWGN:
{ for (i = 0; i<N; i++)
{ lratio[i] = exp(2*awn_data[i]/(std_dev*std_dev));
}
break;
}
case AWLN:
{ for (i = 0; i<N; i++)
{ double e, d1, d0;
e = exp(-(awn_data[i]-1)/lwidth);
d1 = 1 / ((1+e)*(1+1/e));
e = exp(-(awn_data[i]+1)/lwidth);
d0 = 1 / ((1+e)*(1+1/e));
lratio[i] = d1/d0;
}
break;
}
default: abort();
}
/* Try to decode using the specified method. */
switch (dec_method)
{ case Prprp:
{ iters = prprp_decode (H, lratio, dblk, pchk, bitpr);
break;
}
case Enum_block: case Enum_bit:
{ iters = enum_decode (lratio, dblk, bitpr, dec_method==Enum_block);
break;
}
default: abort();
}
/* See if it worked, and how many bits were changed. */
valid = check(H,dblk,pchk)==0;
chngd = changed(lratio,dblk,N);
tot_iter += iters;
tot_valid += valid;
tot_changed += chngd;
/* Print summary table entry. */
if (ldpc_table==1)
{ printf ("%7d %10f %d %8.1f\n",
block_no, (double)iters, valid, (double)chngd);
/* iters is printed as a double to avoid problems if it's >= 2^31 */
fflush(stdout);
}
/* Write decoded block. */
blockio_write(df,dblk,N);
/* Write bit probabilities, if asked to. */
if (pfile)
{ for (j = 0; j<N; j++)
{ fprintf(pf," %.5f",bitpr[j]);
}
fprintf(pf,"\n");
}
/* Check for errors when writing. */
if (ferror(df) || pfile && ferror(pf))
{ break;
}
}
/* Finish up. */
done:
fprintf(stderr,
"Decoded %d blocks, %d valid. Average %.1f iterations, %.0f%% bit changes\n",
block_no, tot_valid, (double)tot_iter/block_no,
100.0*(double)tot_changed/(N*block_no));
if (ferror(df) || fclose(df)!=0)
{ fprintf(stderr,"Error writing decoded blocks to %s\n",dfile);
exit(1);
}
if (pfile)
{ if (ferror(pf) || fclose(pf)!=0)
{ fprintf(stderr,"Error writing bit probabilities to %s\n",dfile);
exit(1);
}
}
exit(0);
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage:\n");
fprintf(stderr,
" decode [ -f ] [ -t | -T ] pchk-file received-file decoded-file [ bp-file ] channel method\n");
channel_usage();
fprintf(stderr,
"Method: enum-block gen-file | enum-bit gen-file | prprp [-]max-iterations\n");
exit(1);
}

View File

@ -1,342 +0,0 @@
<HTML><HEAD>
<TITLE> Decoding Received Blocks </TITLE>
</HEAD><BODY>
<H1> Decoding Received Blocks </H1>
Transmitted codewords are decoded from the received data on the basis
of the <I>likelihood</I> of the possible codewords, which is the
probability of receiving the data that was actually received if the
codeword is question were the one that was sent. This software
presently deals only with memoryless channels, in which the noise is
independent from bit to bit. For such a channel, the likelihood
factorizes into a product of likelihoods for each bit.
For decoding purposes, all that matters is the relative likelihood
for a bit to be 1 versus 0. This is captured by the <I>likelihood
ratio</I> in favour of a 1, which is P(data | bit is 1) / P(data |
bit is 0).
<P>For a Binary Symmetric Channel with error probability <I>p</I>,
the likelihood ratio in favour of a 1 bit is as follows:
<BLOCKQUOTE>
If the received data was +1: (1-<I>p</I>) / <I>p</I><BR>
If the received data was -1: <I>p</I> / (1-<I>p</I>)
</BLOCKQUOTE>
For an Additive White Gaussian Noise channel, with signals of +1 for a 1 bit
and or -1 for a 0 bit, and with noise standard deviation <I>s</I>, the
likelihood ratio in favour of a 1 bit when data <I>y</I> was received is
<BLOCKQUOTE>
exp ( 2y / s<SUP><SMALL>2</SMALL></SUP> )
</BLOCKQUOTE>
For an Additive White Logistic Noise channel, the corresponding
likelihood ratio is
<I>d</I><SUB><SMALL>1</SMALL></SUB>/<I>d</I><SUB><SMALL>0</SMALL></SUB>,
where
<I>d</I><SUB><SMALL>1</SMALL></SUB>=<I>e</I><SUB><SMALL>1</SMALL></SUB>
/ (1+<I>e</I><SUB><SMALL>1</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP> and
<I>d</I><SUB><SMALL>0</SMALL></SUB>=<I>e</I><SUB><SMALL>0</SMALL></SUB>
/ (1+<I>e</I><SUB><SMALL>0</SMALL></SUB>)<SUP><SMALL>2</SMALL></SUP>,
with <I>e</I><SUB><SMALL>1</SMALL></SUB>=exp(-(<I>y</I>-1)/<I>w</I>) and
<I>e</I><SUB><SMALL>0</SMALL></SUB>=exp(-(<I>y</I>+1)/<I>w</I>).
<BLOCKQUOTE> </BLOCKQUOTE>
<P>It is usual to consider codewords to be equally likely <I>a
priori</I>. This is reasonable if the source messages are all equally
likely (any source redundancy being ignored, or remove by a
preliminary data compression stage), provided that the mapping from
source messages to codewords is onto. Decoding can then be done using
only the parity check matrix defining the codewords, without reference
to the generator matrix defining the mapping from source messages to
codewords. Note that the condition that this mapping be onto isn't
true with this software in the atypical case where the code is defined
by a parity check matrix with redundant rows; see the discussion of <A
HREF="dep-H.html">linear dependence in parity check matrices</A>.
This minor complication is mostly ignored here, except by the exhaustive
enumeration decoding methods.
<P>Assuming equal <I>a priori</I> probabilities for codewords, the
probability of correctly decoding an entire codeword is minimized by
picking the codeword with the highest likelihood. One might instead
wish to decode each bit to the value that is most probable. This
minimizes the bit error rate, but is not in general guaranteed to lead
a decoding for each block to the most probable complete codeword;
indeed, the decoding may not be a codeword at all. Minimizing the bit
error rate seems nevertheless to be the most sensible objective,
unless block boundaries have some significance in a wider context.
<P>Optimal decoding by either criterion is infeasible for general
linear codes when messages are more than about 20 or 30 bits in
length. The fundamental advantage of Low Density Parity Check codes
is that good (though not optimal) decodings can be obtained by methods
such as probability propagation, described next.
<A NAME="prprp"><H2>Decoding by probability propagation</H2></A>
<P>The probability propagation algorithm was originally devised by
Robert Gallager in the early 1960's and later reinvented by David
MacKay and myself. It can be seen as an instance of the sum-product
algorithm for inference on factor graphs, and as an instance of belief
propagation in probabilistic networks. See the <A
HREF="refs.html">references</A> for details. Below, I give a fairly
intuitive description of the algorithm.
<P>The algorithm uses only the parity check matrix for the code, whose
columns correspond to codeword bits, and whose rows correspond to
parity checks, and the likelihood ratios for the bits derived from the
data. It aims to find the probability of each bit of the transmitted
codeword being 1, though the results of the algorithm are in general
only approximate.
<P>The begin, information about each bit of the codeword derived from
the received data for that bit alone is expressed as a <I>probability
ratio</I>, the probability of the bit being 1 divided by the
probability of the bit being 0. This probability ratio is equal to
the likelihood ratio (see above) for that bit, since 0 and 1 are
assumed to be equally likely <I>a priori</I>. As the algorithm
progresses, these probability ratios will be modified to take account
of information obtained from other bits, in conjunction with the
requirement that the parity checks be satisfied. To avoid double
counting of information, for every bit, the algorithm maintains a
separate probability ratio for each parity check that that bit
participates in, giving the probability for that bit to be 1 versus 0
based only on information derived from <I>other</I> parity checks,
along with the data received for the bit.
<P>For each parity check, the algorithm maintains separate
<I>likelihood ratios</I> (analogous to, but distinct from, the
likelihood ratios based on received data), for every bit that
participates in that parity check. These ratios give the probability
of that parity check being satisfied if the bit in question is 1
divided by the probability of the check being satisfied if the bit is
0, taking account of the probabilities of each of the <I>other</I>
bits participating in this check being 1, as derived from the
probability ratios for these bits with respect to this check.
<P>The algorithm alternates between recalculating the likelihood
ratios for each check, which are stored in the <B>lr</B> fields of the
parity check matrix entries, and recalculating the probability ratios
for each bit, which are stored in the <B>pr</B> fields of the entries
in the sparse matrix representation of the parity check matrix. (See
the documentation on <A HREF="mod2sparse.html#rep">representation of
sparse matrices</A> for details on these entries.)
<P>Recalculating the likelihood ratio for a check with respect to some
bit may appear time consuming, requiring that all possible
combinations of values for the other bits participating in the check
be considered. Fortunately, there is a short cut. One can calculate
<BLOCKQUOTE>
<I>t</I>
= product of [ 1 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>)
- <I>p<SUB><SMALL>i</SMALL></SUB></I> /
(1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) ]
= product of [ 2 / (1+<I>p<SUB><SMALL>i</SMALL></SUB></I>) - 1 ]
</BLOCKQUOTE>
where the product is over the probability ratios
<I>p<SUB><SMALL>i</SMALL></SUB></I> for the other bits participating
in this check. Factor <I>i</I> in this product is equal to probability
of bit <I>i</I> being 0 minus the probability that it is 1. The terms
in the expansion of this product (in the first form above) correspond to
possible combinations of values for the other bits, with the result that
<I>t</I> will be the probability of the check being satisfied if the bit
in question is 0 minus the probability if the bit in question is 1. The
likelihood ratio for this check with respect to the bit in question can then
be calculated as (1-<I>t</I>)/(1+<I>t</I>).
<P>For a particular check, the product above differs for different
bits, with respect to which we wish to calculate a likelihood ratio,
only in that for each bit the factor corresponding to that bit is left
out. We can calculate all these products easily by ordering the bits
arbitrarily, computing running products of the factor for the first
bit, the factors for the first two bits, etc., and also running
products of the factor for the last bit, the factors for the last two
bits, etc. Multiplying the running product of the factors up to
<I>i</I>-1 by the running product of the factors from <I>i</I>+1 on
gives the product needed for bit <I>i</I>. The second form of the
factors above is used, as it requires less computation, and is still
well defined even if some ratios are infinite.
<P>To recalculate the probability ratio for a bit with respect to a
check, all that is need is to multiply together the likelihood ratio
for this bit derived from the received data (see above), and the
current values of the likelihood ratios for all the <I>other</I>
checks that this bit participates in, with respect to this bit. To
save time, these products are computed by combining forward and
backward products, similarly to the method used for likelihood ratios.
<P>By including likelihood ratios from all checks, a similar
calculation produces the current probability ratio for the bit to be 1
versus 0 based on all information that has propagated to the bit so
far. This ratio can be thresholded at one to produce the current best
guess as to whether this bit is a 1 or a 0.
<P>The hope is that this algorithm will eventually converge to a state
where these bit probabilities give a near-optimal decoding. This is
does not always occur, but the algorithm behaves well enough to
produce very good results at rates approaching (though not yet
reaching) the theoretical Shannon limit.
<P><A NAME="decode"><HR><B>decode</B>: Decode blocks of received data
into codewords.
<BLOCKQUOTE><PRE>
decode [ -f ] [ -t | -T ] <I>pchk-file received-file decoded-file</I> [ <I>bp-file</I> ] <I>channel method</I>
</PRE>
<BLOCKQUOTE>
where <TT><I>channel</I></TT> is one of:
<BLOCKQUOTE><PRE>
bsc <I>error-probability</I>
awgn <I>standard-deviation</I>
awln <I>width</I>
</PRE></BLOCKQUOTE>
and <TT><I>method</I></TT> is one of:
<BLOCKQUOTE><PRE>
enum-block <TT><I>gen-file</I></TT>
enum-bit <TT><I>gen-file</I></TT>
prprp <TT>[-]<I>max-iterations</I></TT>
</PRE></BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>Decodes the blocks in <TT><I>received-file</I></TT>, which are
assumed to be have been received through the specified channel. The
results written to <TT><I>decoded-file</I></TT> are the specified
decoding method's guesses as to what bits were sent through the
channel, given what was received. The probability of each bit being a
1, as judged by the decoding method being used, is written to
<TT><I>bp-file</I></TT>, if given.
<P>A newline is output at the end of each block written to
<TT><I>decoded-file</I></TT> and <TT><I>bp-file</I></TT>. Newlines in
<TT><I>received-file</I></TT> are ignored. A warning is displayed on
standard error if the number of bits in <TT><I>received-file</I></TT>
is not a multiple of the block length.
<P>A summary is displayed on standard error, giving the total number
of blocks decoded, the number of blocks that decoded to valid
codewords, the average number of iterations of the decoding algorithm
used, and the percent of bits that were changed from the values one
would guess for them based just on their individual likelihood ratios.
<P>If the <B>-t</B> option is given, a line of information regarding each block
decoded is written to standard output, preceded by a line of headers.
The information for each block is as follows:
<BLOCKQUOTE>
<TABLE>
<tr align="left" valign="top">
<td> <B>block</B> </td>
<td>The number of the block, from zero</td></tr>
<tr align="left" valign="top">
<td> <B>iterations</B> </td>
<td>The number of "iterations" used in decoding. What exactly an iteration
is depends on the decoding method used (see
<A HREF="decode-detail.html">here</A>).</td></tr>
<tr align="left" valign="top">
<td> <B>valid</B> </td>
<td>Has the value 1 if the decoding is a valid codeword, 0 if not.</td></tr>
<tr align="left" valign="top">
<td> <B>changed</B> </td>
<td>The number of bits in the decoding that differ from the bit that would
be chosen based just on the likelihood ratio for that bit. Bits whose
likelihood ratios are exactly one contribute 0.5 to this count.</td></tr>
</TABLE>
</BLOCKQUOTE>
The file produced is is suitable for
reading into the S-Plus or R statistics packages, with a command such as
<BLOCKQUOTE><PRE>
data <- read.table(<I>file</I>,header=T)
</PRE></BLOCKQUOTE>
<P>If instead the <B>-T</B> option is given, detailed information on
the process of decoding each block will be written to standard output.
For a description, see the <A HREF="decode-detail.html">documentation
on detailed decoding trace information</A>.
<P>The type of channel that is assumed is specified after the file
name arguments. This may currently be either <TT>bsc</TT> (or
<TT>BSC</TT>) for the Binary Symmetric Channel, or <TT>awgn</TT> (or
<TT>AWGN</TT>) for the Additive White Gaussian Noise channel, or
<TT>awln</TT> (or <TT>AWLN</TT>) for the Additive White Logistic Noise
channel. The channel type is followed by an argument specifying the
assumed characteristics of the channel, as follows:
<BLOCKQUOTE>
<P>BSC: The probability that a bit will be flipped by noise - ie, the
probability that the bit received is an error.
<P>AWGN: The standard deviation of the Gaussian noise added to the
encodings of the bits.
<P>AWLN: The width parameter of the logistic distribution for the noise
that is added to the encodings of the bits.
</BLOCKQUOTE>
See the description of <A HREF="channel.html">channel transmission</A>
for more about these channels.
<P>Following the channel specification is a specification of the
decoding method to use. The <TT>enum-block</TT> and <TT>enum-bit</TT>
methods find the optimal decoding by exhaustive enumeration of
codewords derived from all possible source messages. They differ in
that <TT>enum-block</TT> decodes to the most likely codeword, whereas
<TT>enum-bit</TT> decodes to the bits that are individually most
probable. These methods require that a file containing a
representation of a generator matrix be given, to allow enumeration of
codewords. If the parity check matrix has no redundant rows, any
valid generator matrix will give the same decoding (except perhaps if
there is a tie). If redundant rows exist, the generator matrix should
specify the same set of message bits as the generator matrix that was
used for the actual encoding, since the redundancy will lead to some
codeword bits being fixed at zero (see <A HREF="dep-H.html">linear
dependence in parity check matrices</A>).
<P>The <TT>prprp</TT> decoding method decodes using <A
HREF="#prprp">probability propagation</A>. The maximum number of
iterations of probability propagation to do is given following
<TT>prprp</TT>. If a minus sign precedes this number, the maximum
number of iterations is always done. If no minus sign is present, the
algorithm stops once the tentative decoding, based on bit-by-bit
probabilities, is a valid codeword. Note that continuing to the
maximum number of iterations will usually result in
at least slightly different bit probabilities (written to
<TT><I>bp-file</I></TT> if specified), and could conceivably change
the decoding compared to stopping at the first valid codeword, or
result in a failure to decode to a valid codeword even though one was
found earlier.
<P>If the <B>-f</B> option is given, output to <TT><I>decoded-file</I></TT>
is flushed after each block. This allows one to use decode as a server,
reading blocks to decode from a named pipe, and writing the decoded block
to another named pipe.
<P><A NAME="extract"><HR><B>extract</B>: Extract the message bits from a block.
<BLOCKQUOTE><PRE>
extract <I>gen-file decoded-file extracted-file</I>
</PRE></BLOCKQUOTE>
<P>Given a file of codewords in <TT><I>decoded-file</I></TT> (usually,
decoded blocks output by <A HREF="#decode"><TT>decode</TT></A>), and a
generator matrix from <TT><I>gen-file</I></TT> (needed only to
determine where the message bits are located in a codeword), this
program writes the message bits extracted from these codewords to the
file <TT><I>extracted-file</I></TT>.
<P>A newline is output at the end of each block written to
<TT><I>extracted-file</I></TT>. Newlines in
<TT><I>decoded-file</I></TT> are ignored. A warning is displayed on
standard error if the number of bits in <TT><I>decoded-file</I></TT>
is not a multiple of the block length.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,85 +0,0 @@
<HTML><HEAD>
<TITLE> Linear Dependence in Parity Check Matrices </TITLE>
</HEAD><BODY>
<H1> Linear Dependence in Parity Check Matrices </H1>
<P>If a code is specified by means of a <I>M</I> by <I>N</I> parity
check matrix, <B>H</B>, in which some rows are linearly dependent - a
situation that is usually avoided - it would be possible to map more
than the usual <I>K=N-M</I> message bits into a codeword, since one or
more rows of <B>H</B> could have been deleted without affecting which
bit vectors are codewords.
<P>However, this software does not increase the number of message bits
in this case, but instead produces a generator matrix in which some
rows are all zero, which will cause some bits of the codeword to
always be zero, regardless of the source message. Referring to the <A
HREF="encoding.html#gen-rep">description of generator matrix
representations</A>, this is accomplished by partially computing
what would normally be <B>A</B><SUP><SMALL>-1</SMALL></SUP> (for a
dense or mixed representations) or the <B>L</B> and <B>U</B> matrices
(for a sparse representation), even though singularity prevents this
computation from being carried out fully.
<P><B>Example:</B> The parity check matrix created below is redundant,
since the 10100 row is equal to the sum of the 11000 and 01100 rows.
<UL><PRE>
<LI>make-pchk dep.pchk 4 5 0:0 0:1 1:1 1:2 2:0 2:2 3:3 3:4
<LI>print-pchk -d dep.pchk
Parity check matrix in dep.pchk (dense format):
1 1 0 0 0
0 1 1 0 0
1 0 1 0 0
0 0 0 1 1
<LI>make-gen dep.pchk dep.gen dense
Note: Parity check matrix has 1 redundant checks
Number of 1s per check in Inv(A) X B is 0.2
<LI>print-gen dep.gen
Generator matrix (dense representation):
Column order (message bits at end):
0 1 3 2 4
Inv(A) X B:
0
0
1
0
</PRE></UL>
The generator matrix above can be used to encode message blocks containing
one bit. This message bit is copied unchanged to the last bit (numbered 4)
of the codeword, and the first four bits of the codeword are set by multiplying
this message bit (seen as a vector of length one) by
<B>A</B><SUP><SMALL>-1</SMALL></SUP><B>B</B>, shown above, and then
storing the results in positions given by the column ordering.
The result is that bit 3 of the codeword produced is
also set to the message bit, and bits 0, 1, and 2 are set to zero.
<P>Which bits are used for message bits, and which bits are fixed at
zero, depends on arbitrary choices in the algorithm, which may differ
from one encoding method to another. No attempt is made to make the
best choice.
<P>Note that codeword bits that are always zero can arise even when <B>H</B>
does not have linearly dependent rows. For example, if a row of <B>H</B>
has just one 1 in it, the codeword bit at that position must be zero in any
codeword. The way the software handles parity check matrices with less
than <I>M</I> independent rows is equivalent to adding additional rows
to <B>H</B> in which only one bit is 1, in order to produce <I>M</I>
independent checks.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,188 +0,0 @@
/* DISTRIB.C - Procedures for handling distributions over numbers. */
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "alloc.h"
#include "distrib.h"
/* CREATE A DISTRIBUTION AS SPECIFIED IN A STRING. Space for the distribution
is allocated; the string is not freed.
The string must consist either of a single positive integer, representing
the distribution over just that number, or have a form such as the
following:
5x2/3.5x1/1.5x4
This specifies a distribution over 3 numbers, 2, 1, and 4, specified by
the second number in each pair, with proportions of 0.5, 0.35, and 0.15,
respectively, specified by the first number in each pair. The actual
proportions are found by dividing the first number in each pair by the sum
of these numbers.
The distrib type represents the distribution list. It stores a pointer to
an array of distrib_entry elements along with the length of this array.
Each distrib_entry contains a (number,proportion) pair.
*/
distrib *distrib_create
( char *c /* String describing distribution over numbers */
)
{
distrib *d;
char *str, *tstr;
int i, n, scan_num, size;
double prop, sum;
char junk;
/* Check for special case of a single number. */
if (sscanf(c,"%d%c",&n,&junk)==1 && n>0)
{ tstr = chk_alloc ( (int)(4.1+log10(n)), sizeof(*tstr));
sprintf(tstr,"1x%d",n);
d = distrib_create(tstr);
free(tstr);
return d;
}
/* Initial scan of string for size and proper usage. */
str = c;
size = 0;
sum = 0;
d = chk_alloc(1, sizeof *d);
for (;;)
{
scan_num = sscanf(str, "%lgx%d%c", &prop, &n, &junk);
if ((scan_num!=2 && scan_num!=3) || prop<=0 || n<=0)
{ return 0;
}
if (scan_num==3 && junk!='/')
{ return 0;
}
size += 1;
sum += prop;
if (scan_num==2)
{ break;
}
else
{ str = (char*)strchr(str, '/') + 1;
}
}
/* Allocate memory for the list and fill it in */
d->size = size;
d->list = chk_alloc (size, sizeof(distrib_entry));
i = 0;
str = c;
for (;;)
{
scan_num = sscanf(str, "%lgx%d%c", &prop, &n, &junk);
d->list[i].prop = prop/sum;
d->list[i].num = n;
i += 1;
if (scan_num==2)
{ break;
}
else if (scan_num==3)
{ str = (char*)strchr(str, '/') + 1;
}
else
{ abort();
}
}
return d;
}
/* FREE SPACE OCCUPIED A DISTRIBUTION LIST. */
void distrib_free
( distrib *d /* List to free */
)
{ free(d->list);
free(d);
}
/* RETURN THE MAXIMUM NUMBER IN A DISTRIBUTION LIST. Returns 0 if the list
pointer is 0. */
int distrib_max
( distrib *d /* List to examine */
)
{
int i;
int cur;
if (d==0) return 0;
cur = 0;
for (i = 1; i<d->size; i++)
{ if (d->list[i].num > d->list[cur].num)
{ cur = i;
}
}
return d->list[cur].num;
}
/* TEST PROGRAM. */
#ifdef TEST_DISTRIB
main
( int argc,
char **argv
)
{
distrib *d;
int i, j;
for (i = 1; i<argc; i++)
{ d = distrib_create(argv[i]);
if (d==0)
{ printf("Error\n\n");
}
else
{ for (j = 0; j<distrib_size(d); j++)
{ printf("%.3f %d\n",distrib_prop(d,j),distrib_num(d,j));
}
printf("\n");
}
}
exit(0);
}
#endif

View File

@ -1,49 +0,0 @@
/* DISTRIB.H - Interface to module for handling distributions over numbers. */
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
*
* 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.
*/
/* DATA STRUCTURES USED TO STORE A DISTRIBUTION LIST. Entries in the list
* (distrib_entry) are stored in an array (distrib->list[]). */
typedef struct distrib_entry
{ int num; /* A positive number */
double prop; /* Proportion for this number */
} distrib_entry;
typedef struct distrib
{ struct distrib_entry *list; /* The list of numbers and proportions */
int size; /* Number of entries in the list */
} distrib;
/* MACROS TO ACCESS ELEMENTS OF A DISTRIBUTION LIST. Note that indexes for
entries start at 0. */
#define distrib_num(d,i) \
((d)->list[i].num) /* The number for the i'th entry */
#define distrib_prop(d,i) \
((d)->list[i].prop) /* The i'th entry's proportion [probability] */
#define distrib_size(d) \
((d)->size) /* The length of the list (integer) */
/* PROCEDURES FOR DISTRIBUTION LISTS. */
distrib *distrib_create (char *);
void distrib_free (distrib *);
int distrib_max(distrib *);

View File

@ -1,173 +0,0 @@
/* ENC.C - Encoding procedures. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/*#include "rand.h"*/
#include "alloc.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
#include "enc.h"
/* The procedures in this module obtain the generator matrix to use for
encoding from the global variables declared in rcode.h */
/* ENCODE A BLOCK USING A SPARSE REPRESENTATION OF THE GENERATOR MATRIX. */
void sparse_encode
( char *sblk,
char *cblk
)
{
int i, j;
mod2entry *e;
char *x, *y;
x = chk_alloc (M, sizeof *x);
y = chk_alloc (M, sizeof *y);
/* Multiply the vector of source bits by the systematic columns of the
parity check matrix, giving x. Also copy these bits to the coded block. */
for (i = 0; i<M; i++) x[i] = 0;
for (j = M; j<N; j++)
{
cblk[cols[j]] = sblk[j-M];
if (sblk[j-M]==1)
{ for (e = mod2sparse_first_in_col(H,cols[j]);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_col(e))
{ x[mod2sparse_row(e)] ^= 1;
}
}
}
/* Solve Ly=x for y by forward substitution, then U(cblk)=y by backward
substitution. */
if (!mod2sparse_forward_sub(L,rows,x,y)
|| !mod2sparse_backward_sub(U,cols,y,cblk))
{
abort(); /* Shouldn't occur, even if the parity check matrix has
redundant rows */
}
free(x);
free(y);
}
/* ENCODE A BLOCK USING DENSE REPRESENTATION OF GENERATOR MATRIX. */
void dense_encode
( char *sblk,
char *cblk,
mod2dense *u,
mod2dense *v
)
{
int j;
/* Copy source bits to the systematic part of the coded block. */
for (j = M; j<N; j++)
{ cblk[cols[j]] = sblk[j-M];
}
/* Multiply by Inv(A) X B to produce check bits. */
for (j = M; j<N; j++)
{ mod2dense_set(u,j-M,0,sblk[j-M]);
}
mod2dense_multiply(G,u,v);
/* Copy check bits to the right places in the coded block. */
for (j = 0; j<M; j++)
{ cblk[cols[j]] = mod2dense_get(v,j,0);
}
}
/* ENCODE A BLOCK USING MIXED REPRESENTATION OF GENERATOR MATRIX. */
void mixed_encode
( char *sblk,
char *cblk,
mod2dense *u,
mod2dense *v
)
{
mod2entry *e;
int j;
/* Multiply the vector of source bits by the message bit columns of the
parity check matrix. Also copy these bits to the coded block. Take
account of how columns have been reordered. */
mod2dense_clear(u);
for (j = M; j<N; j++)
{
cblk[cols[j]] = sblk[j-M];
if (sblk[j-M]==1)
{ for (e = mod2sparse_first_in_col(H,cols[j]);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_col(e))
{ (void) mod2dense_flip(u,mod2sparse_row(e),0);
}
}
}
/* Multiply by Inv(A) to produce check bits. */
mod2dense_multiply(G,u,v);
/* Copy check bits to the right places in the coded block. */
for (j = 0; j<M; j++)
{ cblk[cols[j]] = mod2dense_get(v,j,0);
}
}
// Wrapper for calling sparse_encode from fortran
void ldpc_encode_(
char msg[N-M],
char cdw[N]
){
int i;
char checks[M];
sparse_encode(msg,cdw);
mod2sparse_mulvec (H, cdw, checks);
for (i = 0; i<M; i++) {
if( checks[i] == 1 ) {
printf("Failed to encode.\n");
abort();
}
}
}

View File

@ -1,19 +0,0 @@
/* ENC.H - Interface to encoding procedures. */
/* 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.
*/
void sparse_encode (char *, char *);
void dense_encode (char *, char *, mod2dense *, mod2dense *);
void mixed_encode (char *, char *, mod2dense *, mod2dense *);
void ldpc_encode_ (char *, char *);

View File

@ -1,195 +0,0 @@
/* ENCODE.C - Encode message blocks. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "rand.h"
#include "alloc.h"
#include "blockio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
#include "enc.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *source_file, *encoded_file;
char *pchk_file, *gen_file;
mod2dense *u, *v;
FILE *srcf, *encf;
char *sblk, *cblk, *chks;
int i, n;
/* Look at initial flag arguments. */
blockio_flush = 0;
while (argc>1)
{
if (strcmp(argv[1],"-f")==0)
{ if (blockio_flush!=0) usage();
blockio_flush = 1;
}
else
{ break;
}
argc -= 1;
argv += 1;
}
/* Look at remaining arguments. */
if (!(pchk_file = argv[1])
|| !(gen_file = argv[2])
|| !(source_file = argv[3])
|| !(encoded_file = argv[4])
|| argv[5])
{ usage();
}
if ((strcmp(pchk_file,"-")==0)
+ (strcmp(gen_file,"-")==0)
+ (strcmp(source_file,"-")==0) > 1)
{ fprintf(stderr,"Can't read more than one stream from standard input\n");
exit(1);
}
/* Read parity check file */
read_pchk(pchk_file);
if (N<=M)
{ fprintf(stderr,
"Can't encode if number of bits (%d) not greater than number of checks (%d)\n",
N,M);
exit(1);
}
/* Read generator matrix file. */
read_gen(gen_file,0,0);
/* Allocate needed space. */
if (type=='d')
{ u = mod2dense_allocate(N-M,1);
v = mod2dense_allocate(M,1);
}
if (type=='m')
{ u = mod2dense_allocate(M,1);
v = mod2dense_allocate(M,1);
}
/* Open source file. */
srcf = open_file_std(source_file,"r");
if (srcf==NULL)
{ fprintf(stderr,"Can't open source file: %s\n",source_file);
exit(1);
}
/* Create encoded output file. */
encf = open_file_std(encoded_file,"w");
if (encf==NULL)
{ fprintf(stderr,"Can't create file for encoded data: %s\n",encoded_file);
exit(1);
}
sblk = chk_alloc (N-M, sizeof *sblk);
cblk = chk_alloc (N, sizeof *cblk);
chks = chk_alloc (M, sizeof *chks);
/* Encode successive blocks. */
for (n = 0; ; n++)
{
/* Read block from source file. */
if (blockio_read(srcf,sblk,N-M)==EOF)
{ break;
}
/* Compute encoded block. */
switch (type)
{ case 's':
{ sparse_encode (sblk, cblk);
break;
}
case 'd':
{ dense_encode (sblk, cblk, u, v);
break;
}
case 'm':
{ mixed_encode (sblk, cblk, u, v);
break;
}
}
/* Check that encoded block is a code word. */
mod2sparse_mulvec (H, cblk, chks);
for (i = 0; i<M; i++)
{ if (chks[i]==1)
{ fprintf(stderr,"Output block %d is not a code word! (Fails check %d)\n",n,i);
abort();
}
}
/* Write encoded block to encoded output file. */
blockio_write(encf,cblk,N);
if (ferror(encf))
{ break;
}
}
// fprintf(stderr,
// "Encoded %d blocks, source block size %d, encoded block size %d\n",n,N-M,N);
if (ferror(encf) || fclose(encf)!=0)
{ fprintf(stderr,"Error writing encoded blocks to %s\n",encoded_file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,
"Usage: encode [ -f ] pchk-file gen-file source-file encoded-file\n");
exit(1);
}

View File

@ -1,283 +0,0 @@
<HTML><HEAD>
<TITLE> Encoding Message Blocks </TITLE>
</HEAD><BODY>
<H1> Encoding Message Blocks </H1>
To use a code to send messages, we must define a mapping from a bit
vector, <B>s</B>, of length <I>K</I>, representing a source message,
to a codeword, <B>x</B>, of length <I>N</I>&gt;<I>K</I>. We will
consider only linear mappings, which can be written in the form
<B>x</B>=<B>G</B><SUP><SMALL>T</SMALL></SUP><B>s</B>, where <B>G</B>
is a <I>generator matrix</I>. For a code with parity check matrix
<B>H</B>, whose codewords satisfy <B>Hx</B>=<B>0</B>, the generator
matrix must satisfy <B>HG</B><SUP><SMALL>T</SMALL></SUP>=<B>0</B>.
This software assumes that the number of rows in the parity check
matrix, <I>M</I>, is equal to <I>N-K</I>, as would normally be the
case.
<P>This software deals only with <I>systematic</I> encodings, in which
the <I>K</I> bits of <B>s</B> are copied unchanged to some subset of
the <I>N</i> bits of <B>x</B> (the <I>message bits</I>), and the
remaining <I>M=N-K</I> <I>check bits</I> of <B>x</B> are then set so
as to make the result a codeword. For a linear code, a systematic
encoding scheme always exists, for some choice of which bits of a
codeword are message bits. It is conventional to rearrange the order
of the bits in a codeword so that the message bits come first. The
first <I>K</I> columns of the <I>K</I> by <I>N</I> generator matrix
will then be the identity matrix.
<P>However, this software does <I>not</I> assume that the message bits
come first, since different encoding methods prefer different
locations for the message bits. Instead, a vector of indexes of where
each message bit is located within a codeword is recorded in a file
along with a representation of the part of the generator matrix that
produces the check bits. More than one such generator matrix file can
be created for a single parity check file, in which the locations of
the message bits may be different. Decoding of a received message
into a codeword (with <A
HREF="decoding.html#decode"><TT>decode</TT></A>) does not depend on
knowing which are the message bits, though this does need to be known
in order to reconstruct the original message (with <A
HREF="decoding.html#extract"><TT>extract</TT></A>).
<P>This software stores representations of generator matrices in files
in a format that is not human-readable (except by using the <A
HREF="#print-gen"><TT>print-gen</TT></A> program). However, these
files <I>are</I> readable on a machine with a different architecture
than they were written on.
<A NAME="gen-rep"><H2>Generator matrix representations</H2></A>
<P>For simplicity of exposition, it will be assumed for the next few
paragraphs that the message bits are located at the <I>end</I> of the
codeword, so a codeword can be divided into <I>M</I> check bits,
<B>c</B>, followed by <I>K</I> message bits, <B>s</B>.
<P>On the above assumption, the parity check matrix, <B>H</B>, can be divided
into an <I>M</I> by <I>M</I> matrix <B>A</B> occupying
the first <I>M</I> columns of <B>H</B> and an <I>M</I> by <I>K</I> matrix
<B>B</B> occupying the remaining columns of <B>H</B>. The requirement that
a codeword, <B>x</B>, satisfy all parity checks (ie, that <B>Hx</B>=<B>0</B>)
can then be written as
<BLOCKQUOTE>
<B>Ac</B> + <B>Bs</B> = <B>0</B>
</BLOCKQUOTE>
Provided that <B>A</B> is non-singular, it follows that
<BLOCKQUOTE>
<B>c</B> = <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>Bs</B>
</BLOCKQUOTE>
<B>A</B> may be singular for some choices of which codeword bits are message
bits, but a choice for which <B>A</B> is non-singular always exists if the
rows of <B>H</B> are linearly independent. It is possible, however, that the
rows of <B>H</B> are not linearly independent (ie, some rows are redundant).
This is an exceptional
and not particularly interesting case, which is mostly ignored in the
descriptions below; see the discussion of <A HREF="dep-H.html">linear
dependence in parity check matrices</A> for the details.
<P>The equation <B>c</B> = <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>Bs</B>
defines what the check bits should be, but actual computation of these
check bits can be done in several ways, three of which are implemented
in this software. Each method involves a different representation of
the generator matrix. (Note that none of these methods involves the
explicit representation of the matrix <B>G</B> mentioned above.)
<P>In the <I>dense representation</I>, the <I>M</I> by <I>K</I> matrix
<B>A</B><SUP><SMALL>-1</SMALL></SUP><B>B</B> is computed, and stored
in a dense format (see the <A HREF="mod2dense.html">dense modulo-2
matrix package</A>). A message is encoded by multiplying the
source bits, <B>s</B>, by this matrix to obtain the required check bits.
<P>In the <I>mixed representation</I>, the <I>M</I> by <I>M</I> matrix
<B>A</B><SUP><SMALL>-1</SMALL></SUP> is computed and stored in a dense
format, and the <I>M</I> by <I>K</I> matrix <B>B</B>, the right
portion of the parity check matrix, is also stored, in a sparse format
(see the <A HREF="mod2sparse.html">sparse modulo-2 matrix package</A>).
To encode a message, the source vector <B>s</B> is first multiplied on
the left by <B>B</B>, an operation which can be done very quickly if
<B>B</B> is sparse (as it will be for LDPC codes). The result is then
multiplied on the left by <B>A</B><SUP><SMALL>-1</SMALL></SUP>. If
<I>M</I>&lt;<I>K</I>, the total time may be less than when using the
dense representation above.
<P>The <I>sparse representation</I> goes further, and avoids
explicitly computing <B>A</B><SUP><SMALL>-1</SMALL></SUP>, which tends
to be dense even if <B>H</B> is sparse. Instead, a <I>LU
decomposition</I> of <B>A</B> is found, consisting of a lower
triangular matrix <B>L</B> and an upper triangular matrix <B>U</B> for
which <B>LU</B>=<B>A</B>. The effect of multiplying <B>Bs</B>=<B>z</B> by
<B>A</B><SUP><SMALL>-1</SMALL></SUP> can then be obtained by
<BLOCKQUOTE>
Solving <B>Ly</B>=<B>z</B> for <B>y</B> using forward substitution.<BR>
Solving <B>Uc</B>=<B>y</B> for <B>c</B> using backward substitution.
</BLOCKQUOTE>
Both of these operations will be fast if <B>L</B> and <B>U</B> are
sparse. Heuristics are used to try to achieve this, by rearranging the
rows and columns of <B>H</B> in the process of selecting <B>A</B> and
finding its LU decomposition.
<P><A NAME="make-gen"><HR><B>make-gen</B>: Make a generator matrix from
a parity check matrix.
<BLOCKQUOTE><PRE>
make-gen <I>pchk-file gen-file method</I>
</PRE>
<BLOCKQUOTE>
where <TT><I>method</I></TT> is one of the following:
<BLOCKQUOTE><PRE>
sparse [ first | mincol | minprod ] [ <I>abandon-num abandon-when</I> ]
dense [ <I>other-gen-file </I> ]
mixed [ <I>other-gen-file </I> ]
</PRE></BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>Finds a generator matrix for the code whose parity check matrix is
in <TT><I>pchk-file</I></TT>, and writes a representation of this
generator matrix to <TT><I>gen-file</I></TT>. The remaining arguments
specify what representation of the generator matrix is to be used (see
the <A HREF="#gen-rep">description above</A>), and the method to be
used in finding it. A message regarding the density of 1s in the
resulting representation is displayed on standard error. For a sparse
representation, a smaller number of 1s will produce faster encoding.
<P>All representations include a specification for how the columns of
the parity check matrix should be re-ordered so that the message bits
come last. References to columns of the parity check matrix below
refer to their order after this reordering. For the <I>dense</I> and
<I>mixed</I> representations, an <TT><I>other-gen-file</I></TT> may be
specified, in which case the ordering of columns will be the same as
the ordering stored in that file (which must produce a non-singular
<B>A</B> matrix; redundant rows of <B>H</B> are not allowed with this
option). Otherwise, <TT>make-gen</TT> decides on an appropriate
ordering of columns itself. Note that the column rearrangement is
recorded as part of the representation of the generator matrix; the
parity check matrix as stored in its file is not altered.
<P>The <I>dense</I> representation consists of a dense representation
of the matrix <B>A</B><SUP><SMALL>-1</SMALL></SUP><B>B</B>, where
<B>A</B> is the matrix consisting of the first <I>M</I> columns (after
reordering) of the parity check matrix, and <B>B</B> is the remaining
columns. If <B>H</B> contains redundant rows, there is an additional
reordering of columns of <B>A</B> in order create the same effect as
if the redundant rows came last.
<P>The <I>mixed</I> representation consists of a dense representation
of the matrix <B>A</B><SUP><SMALL>-1</SMALL></SUP>, where <B>A</B> is
the matrix consisting of the first <I>M</I> columns (after reordering)
of the parity check matrix. The remaining columns of the parity check
matrix, making up the matrix <B>B</B>, are also part of the
representation, but are not written to <TT><I>gen-file</I></TT>, since
they can be obtained from <TT><I>pchk-file</I></TT>. As for mixed
representations, an additional reordering of columns of <B>A</B> may
be needed if <B>H</B> has redundant rows.
<P>A <I>sparse</I> representation consists of sparse representations
of the <B>L</B> and <B>U</B> matrices, whose product is <B>A</B>, the
first <I>M</I> columns of the parity check matrix (whose columns and
rows may both have been reordered). The matrix <B>B</B>, consisting
of the remaining columns of the parity check matrix, is also part of
the representation, but it is not written to <TT><I>gen-file</I></TT>,
since it can be obtained from <TT><I>pchk-file</I></TT>.
<P>If a sparse representation is chosen, arguments after
<TT>sparse</TT> specify what heuristic is used when reordering columns
and rows in order to try to make <B>L</B> and <B>U</B> as sparse as
possible. The default if no heuristic is specified is
<TT>minprod</TT>. If the <TT><I>abandon-num</I></TT> and
<TT><I>abandon-when</I></TT> options are given, some information is
discarded in order to speed up the process of finding <B>L</B> and
<B>U</B>, at a possible cost in terms of how good a result is
obtained. For details on these heuristics, see the descriptions of <A
HREF="sparse-LU.html">sparse LU decomposition methods</A>.
<P><B>Example:</B> A dense representation of a generator matrix for the
Hamming code created by the example for <A
HREF="pchk.html#make-pchk"><TT>make-pchk</TT></A> can be created as follows:
<UL><PRE>
<LI>make-gen ham7.pchk ham7.gen dense
Number of 1s per check in Inv(A) X B is 3.0
</PRE></UL>
<P><A NAME="print-gen"><HR><B>print-gen</B>: Print a representation of a
generator matrix.
<BLOCKQUOTE><PRE>
print-gen [ -d ] <I>gen-file</I>
</PRE></BLOCKQUOTE>
<P>Prints in human-readable form the representation of the generator
matrix that is stored in <TT><I>gen-file</I></TT>. The <B>-d</B>
option causes the matrices involved to be printed in a dense format,
even if they are stored in the file in a sparse format. See the <A
HREF="#gen-rep">description above</A> for details of generator matrix
representations. Note that the <B>L</B> matrix for a sparse representation
will be lower triangular only after the rows are rearranged, and the <B>U</B>
matrix will be upper triangular only after the columns are rearranged.
The matrix <B>B</B> that is part of the sparse
and mixed representations is not printed, since it is not stored
in the <TT><I>gen-file</I></TT>, but is rather a subset of columns
of the parity check matrix.
<P><B>Example:</B> The generator matrix for the
Hamming code created by the example for <A
HREF="#make-gen"><TT>make-gen</TT></A> can be printed as follows:
<UL><PRE>
<LI>print-gen ham7.gen
Generator matrix (dense representation):
Column order:
0 1 2 3 4 5 6
Inv(A) X B:
1 1 1 0
1 1 0 1
0 1 1 1
</PRE></UL>
For this example, the columns did not need to be rearranged, and hence the
message bits will be in positions 3, 4, 5, and 6 of a codeword.
<P><A NAME="encode"><HR><B>encode</B>: Encode message blocks as codewords
<BLOCKQUOTE><PRE>
encode [ -f ] <I>pchk-file gen-file source-file encoded-file</I>
</PRE></BLOCKQUOTE>
Encodes message blocks of length <I>K</I>, read from
<TT><I>source-file</I></TT>, as codewords of length <I>N</I>, which
are written to <TT><I>encoded-file</I></TT>, replacing any previous
data in this file. Here, <I>N</I> is the number of columns in the
parity check matrix in <TT><I>pchk-file</I></TT>, and
<I>K</I>=<I>N-M</I>, where <I>M</I> is the number of rows in the
parity check matrix. The generator matrix used, from
<TT><I>gen-file</I></TT>, determines which bits of the codeword are
set to the message bits, and how the remaining check bits are
computed. The generator matrix is created from
<TT><I>pchk-file</I></TT> using <A HREF="#make-gen"><TT>make-gen</TT></A>.
<P>A newline is output at the end of each block written to
<TT><I>encoded-file</I></TT>. Newlines in <TT><I>source-file</I></TT>
are ignored.
<P>If the <B>-f</B> option is given, output to <TT><I>encoded-file</I></TT>
is flushed after each block. This allows one to use encode as a server,
reading blocks to encode from a named pipe, and writing the encoded block
to another named pipe.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,60 +0,0 @@
#!/bin/sh
# Examples of a how a parity check matrix with dependent rows is handled.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
# CODE 1
make-pchk ex-dep.pchk 4 6 0:0 0:5 3:1 3:2
print-pchk -d ex-dep.pchk
echo 00011011 >ex-dep.src
# SPARSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen sparse
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
# DENSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen dense
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
# MIXED REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen mixed
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
# CODE 2
make-pchk ex-dep.pchk 4 5 0:0 0:1 1:1 1:2 2:0 2:2 3:3 3:4
print-pchk -d ex-dep.pchk
echo 01 >ex-dep.src
# SPARSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen sparse
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
# DENSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen dense
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
# MIXED REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen mixed
print-gen -d ex-dep.gen
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src

View File

@ -1,224 +0,0 @@
# CODE 1
make-pchk ex-dep.pchk 4 6 0:0 0:5 3:1 3:2
print-pchk -d ex-dep.pchk
Parity check matrix in ex-dep.pchk (dense format):
1 0 0 0 0 1
0 0 0 0 0 0
0 0 0 0 0 0
0 1 1 0 0 0
echo 00011011 >ex-dep.src
# SPARSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen sparse
Note: Parity check matrix has 2 redundant checks
Number of 1s per check in L is 0.8, U is 0.5, B is 0.2, total is 1.5
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (sparse representation):
Column order (message bits at end):
5 2 1 3 4 0
Row order:
0 3 2 1
L:
1 0 0 0
0 0 0 0
0 0 0 0
0 1 0 0
U:
0 0 0 0 0 1
0 1 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 4 blocks, source block size 2, encoded block size 6
000000
100001
000010
100011
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
# DENSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen dense
Note: Parity check matrix has 2 redundant checks
Number of 1s per check in Inv(A) X B is 0.2
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (dense representation):
Column order (message bits at end):
0 1 2 3 4 5
Inv(A) X B:
0 1
0 0
0 0
0 0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 4 blocks, source block size 2, encoded block size 6
000000
100001
000010
100011
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
# MIXED REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen mixed
Note: Parity check matrix has 2 redundant checks
Number of 1s per check in Inv(A) is 0.5, in B is 0.2, total is 0.8
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (mixed representation):
Column order (message bits at end):
0 1 2 3 4 5
Inv(A):
1 0 0 0
0 0 0 1
0 0 0 0
0 0 0 0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 4 blocks, source block size 2, encoded block size 6
000000
100001
000010
100011
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 4, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
# CODE 2
make-pchk ex-dep.pchk 4 5 0:0 0:1 1:1 1:2 2:0 2:2 3:3 3:4
print-pchk -d ex-dep.pchk
Parity check matrix in ex-dep.pchk (dense format):
1 1 0 0 0
0 1 1 0 0
1 0 1 0 0
0 0 0 1 1
echo 01 >ex-dep.src
# SPARSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen sparse
Note: Parity check matrix has 1 redundant checks
Number of 1s per check in L is 1.0, U is 1.2, B is 0.5, total is 2.8
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (sparse representation):
Column order (message bits at end):
4 1 2 3 0
Row order:
3 0 1 2
L:
0 1 0 0
0 1 1 0
0 0 1 0
1 0 0 0
U:
0 0 0 1 1
0 1 0 0 0
0 0 1 0 0
0 0 0 0 0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 2 blocks, source block size 1, encoded block size 5
00000
11100
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
# DENSE REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen dense
Note: Parity check matrix has 1 redundant checks
Number of 1s per check in Inv(A) X B is 0.2
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (dense representation):
Column order (message bits at end):
0 1 3 2 4
Inv(A) X B:
0
0
1
0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 2 blocks, source block size 1, encoded block size 5
00000
00011
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
# MIXED REPRESENTATION
make-gen ex-dep.pchk ex-dep.gen mixed
Note: Parity check matrix has 1 redundant checks
Number of 1s per check in Inv(A) is 1.0, in B is 0.2, total is 1.2
print-gen -d ex-dep.gen
Generator matrix in ex-dep.gen (mixed representation):
Column order (message bits at end):
0 1 3 2 4
Inv(A):
1 1 0 0
0 1 0 0
0 0 0 1
0 0 0 0
encode ex-dep.pchk ex-dep.gen ex-dep.src ex-dep.enc; cat ex-dep.enc
Encoded 2 blocks, source block size 1, encoded block size 5
00000
00011
verify ex-dep.pchk ex-dep.enc ex-dep.gen ex-dep.src
Block counts: tot 2, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00

View File

@ -1,38 +0,0 @@
#!/bin/sh
# Example of decoding a (7,4) Hamming code using exhaustive enumeration and
# probability propagation, with an Additive White Gaussian Noise channel with
# noise standard deviation of 0.5, for which Eb/N0 = 5.44 dB.
#
# Testing is done by transmitting zero blocks, which is sufficient because
# both the channel and the decoding procedure are symmetrical. WARNING: But
# things can easily become non-symmetrical with bugs, so this technique should
# be used with caution, and only when necessary for performance reasons.
# Decoding is done three times, once minimizing block error probability, once
# minimizing bit error probability, and once by up to 200 iterations of
# probability propagation.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-pchk ex-ham7a.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
make-gen ex-ham7a.pchk ex-ham7a.gen dense
transmit 7x100000 ex-ham7a.rec 1 awgn 0.5
# DECODE BY ENUMERATION TO MINIMIZE BLOCK ERROR PROBABILITY
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-blk awgn 0.5 \
enum-block ex-ham7a.gen
verify ex-ham7a.pchk ex-ham7a.dec-blk ex-ham7a.gen
# DECODE BY ENUMERATION TO MINIMIZE BIT ERROR PROBABILITY
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-bit awgn 0.5 \
enum-bit ex-ham7a.gen
verify ex-ham7a.pchk ex-ham7a.dec-bit ex-ham7a.gen
# DECODE BY PROBABILITY PROPAGATION
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-prp awgn 0.5 \
prprp 200
verify ex-ham7a.pchk ex-ham7a.dec-prp ex-ham7a.gen

View File

@ -1,33 +0,0 @@
make-pchk ex-ham7a.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
make-gen ex-ham7a.pchk ex-ham7a.gen dense
Number of 1s per check in Inv(A) X B is 3.0
transmit 7x100000 ex-ham7a.rec 1 awgn 0.5
Transmitted 700000 bits
# DECODE BY ENUMERATION TO MINIMIZE BLOCK ERROR PROBABILITY
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-blk awgn 0.5 \
enum-block ex-ham7a.gen
Decoded 100000 blocks, 100000 valid. Average 16.0 iterations, 2% bit changes
verify ex-ham7a.pchk ex-ham7a.dec-blk ex-ham7a.gen
Block counts: tot 100000, with chk errs 0, with src errs 186, both 0
Bit error rate (on message bits only): 7.950e-04
# DECODE BY ENUMERATION TO MINIMIZE BIT ERROR PROBABILITY
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-bit awgn 0.5 \
enum-bit ex-ham7a.gen
Decoded 100000 blocks, 99988 valid. Average 16.0 iterations, 2% bit changes
verify ex-ham7a.pchk ex-ham7a.dec-bit ex-ham7a.gen
Block counts: tot 100000, with chk errs 12, with src errs 186, both 7
Bit error rate (on message bits only): 7.775e-04
# DECODE BY PROBABILITY PROPAGATION
decode ex-ham7a.pchk ex-ham7a.rec ex-ham7a.dec-prp awgn 0.5 \
prprp 200
Decoded 100000 blocks, 99927 valid. Average 0.3 iterations, 2% bit changes
verify ex-ham7a.pchk ex-ham7a.dec-prp ex-ham7a.gen
Block counts: tot 100000, with chk errs 73, with src errs 276, both 52
Bit error rate (on message bits only): 1.290e-03

View File

@ -1,21 +0,0 @@
#!/bin/sh
# Example of coding using a (7,4) Hamming code, with transmission through
# a Binary Symmetric Channel with error probability of 0.05.
#
# This example shows how random source messages can be encoded as codewords,
# transmitted through the simulated channel, decoded, and the message bits
# extracted from the codewords. The final result is in ex-ham7b.ext, which can
# be compared to ex-ham7b.src.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-pchk ex-ham7b.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
make-gen ex-ham7b.pchk ex-ham7b.gen dense
rand-src ex-ham7b.src 1 4x1000
encode ex-ham7b.pchk ex-ham7b.gen ex-ham7b.src ex-ham7b.enc
transmit ex-ham7b.enc ex-ham7b.rec 1 bsc 0.05
decode ex-ham7b.pchk ex-ham7b.rec ex-ham7b.dec bsc 0.05 enum-bit ex-ham7b.gen
verify ex-ham7b.pchk ex-ham7b.dec ex-ham7b.gen ex-ham7b.src
extract ex-ham7b.gen ex-ham7b.dec ex-ham7b.ext

View File

@ -1,15 +0,0 @@
make-pchk ex-ham7b.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
make-gen ex-ham7b.pchk ex-ham7b.gen dense
Number of 1s per check in Inv(A) X B is 3.0
rand-src ex-ham7b.src 1 4x1000
encode ex-ham7b.pchk ex-ham7b.gen ex-ham7b.src ex-ham7b.enc
Encoded 1000 blocks, source block size 4, encoded block size 7
transmit ex-ham7b.enc ex-ham7b.rec 1 bsc 0.05
Transmitted 7000 bits
decode ex-ham7b.pchk ex-ham7b.rec ex-ham7b.dec bsc 0.05 enum-bit ex-ham7b.gen
Decoded 1000 blocks, 1000 valid. Average 16.0 iterations, 4% bit changes
verify ex-ham7b.pchk ex-ham7b.dec ex-ham7b.gen ex-ham7b.src
Block counts: tot 1000, with chk errs 0, with src errs 47, both 0
Bit error rate (on message bits only): 2.000e-02
extract ex-ham7b.gen ex-ham7b.dec ex-ham7b.ext

View File

@ -1,45 +0,0 @@
#!/bin/sh
# Example of how an LDPC code can be encoded using using sparse,
# dense, and mixed representations of the generator matrix. The dense
# and mixed representations are based on the same set of message bits
# as the sparse method with minprod heuristic. This allows the correctness
# of these methods to be checked by verifying that they all produce the same
# result when encoding random messages. The results are also checked by
# 'verify'.
#
# A (400,200) LDPC code with 3 checks per bit is used for the test.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-ldpc ex-ldpc-encode.pchk 200 400 1 evenboth 3
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genf sparse first
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genc sparse mincol
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genp sparse minprod
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.gend dense ex-ldpc-encode.genp
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genm mixed ex-ldpc-encode.genp
rand-src ex-ldpc-encode.src 1 200x10
encode ex-ldpc-encode.pchk ex-ldpc-encode.genf ex-ldpc-encode.src \
ex-ldpc-encode.encf
encode ex-ldpc-encode.pchk ex-ldpc-encode.genc ex-ldpc-encode.src \
ex-ldpc-encode.encc
encode ex-ldpc-encode.pchk ex-ldpc-encode.genp ex-ldpc-encode.src \
ex-ldpc-encode.encp
encode ex-ldpc-encode.pchk ex-ldpc-encode.gend ex-ldpc-encode.src \
ex-ldpc-encode.encd
encode ex-ldpc-encode.pchk ex-ldpc-encode.genm ex-ldpc-encode.src \
ex-ldpc-encode.encm
cmp ex-ldpc-encode.encp ex-ldpc-encode.encd
cmp ex-ldpc-encode.encp ex-ldpc-encode.encm
verify ex-ldpc-encode.pchk ex-ldpc-encode.encf ex-ldpc-encode.genf \
ex-ldpc-encode.src
verify ex-ldpc-encode.pchk ex-ldpc-encode.encc ex-ldpc-encode.genc \
ex-ldpc-encode.src
verify ex-ldpc-encode.pchk ex-ldpc-encode.encp ex-ldpc-encode.genp \
ex-ldpc-encode.src

View File

@ -1,47 +0,0 @@
make-ldpc ex-ldpc-encode.pchk 200 400 1 evenboth 3
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genf sparse first
Number of 1s per check in L is 6.4, U is 6.4, B is 3.0, total is 15.8
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genc sparse mincol
Number of 1s per check in L is 3.0, U is 3.3, B is 3.0, total is 9.3
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genp sparse minprod
Number of 1s per check in L is 2.4, U is 3.2, B is 3.0, total is 8.6
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.gend dense ex-ldpc-encode.genp
Number of 1s per check in Inv(A) X B is 69.2
make-gen ex-ldpc-encode.pchk ex-ldpc-encode.genm mixed ex-ldpc-encode.genp
Number of 1s per check in Inv(A) is 64.7, in B is 3.0, total is 67.7
rand-src ex-ldpc-encode.src 1 200x10
encode ex-ldpc-encode.pchk ex-ldpc-encode.genf ex-ldpc-encode.src \
ex-ldpc-encode.encf
Encoded 10 blocks, source block size 200, encoded block size 400
encode ex-ldpc-encode.pchk ex-ldpc-encode.genc ex-ldpc-encode.src \
ex-ldpc-encode.encc
Encoded 10 blocks, source block size 200, encoded block size 400
encode ex-ldpc-encode.pchk ex-ldpc-encode.genp ex-ldpc-encode.src \
ex-ldpc-encode.encp
Encoded 10 blocks, source block size 200, encoded block size 400
encode ex-ldpc-encode.pchk ex-ldpc-encode.gend ex-ldpc-encode.src \
ex-ldpc-encode.encd
Encoded 10 blocks, source block size 200, encoded block size 400
encode ex-ldpc-encode.pchk ex-ldpc-encode.genm ex-ldpc-encode.src \
ex-ldpc-encode.encm
Encoded 10 blocks, source block size 200, encoded block size 400
cmp ex-ldpc-encode.encp ex-ldpc-encode.encd
cmp ex-ldpc-encode.encp ex-ldpc-encode.encm
verify ex-ldpc-encode.pchk ex-ldpc-encode.encf ex-ldpc-encode.genf \
ex-ldpc-encode.src
Block counts: tot 10, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
verify ex-ldpc-encode.pchk ex-ldpc-encode.encc ex-ldpc-encode.genc \
ex-ldpc-encode.src
Block counts: tot 10, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00
verify ex-ldpc-encode.pchk ex-ldpc-encode.encp ex-ldpc-encode.genp \
ex-ldpc-encode.src
Block counts: tot 10, with chk errs 0, with src errs 0, both 0
Bit error rate (on message bits only): 0.000e+00

View File

@ -1,50 +0,0 @@
#!/bin/sh
# Example of a (2000,1000) LDPC code with 3 checks per bit and 6 bits per
# check, tested on Additive White Gaussian Noise channels with noise standard
# deviations varying from 0.80 to 0.95.
#
# Testing is done by transmitting random messages, which is safer (though
# slower) than using only zero messages. Decoding is done using a maximum
# of 250 iterations of probability propagation.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-ldpc ex-ldpc36-1000a.pchk 1000 2000 1 evenboth 3 no4cycle
make-gen ex-ldpc36-1000a.pchk ex-ldpc36-1000a.gen dense
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
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.80
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.80\
prprp 250
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
ex-ldpc36-1000a.src
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.85
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.85\
prprp 250
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
ex-ldpc36-1000a.src
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.90
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.90\
prprp 250
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
ex-ldpc36-1000a.src
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
transmit ex-ldpc36-1000a.enc ex-ldpc36-1000a.rec 1 awgn 0.95
decode ex-ldpc36-1000a.pchk ex-ldpc36-1000a.rec ex-ldpc36-1000a.dec awgn 0.95\
prprp 250
verify ex-ldpc36-1000a.pchk ex-ldpc36-1000a.dec ex-ldpc36-1000a.gen \
ex-ldpc36-1000a.src

View File

@ -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

View File

@ -1,44 +0,0 @@
#!/bin/sh
# Example of a (10000,5000) LDPC code with 3 checks per bit and 6 bits per
# check, tested on Additive White Gaussian Noise channels with noise standard
# deviations varying from 0.80 to 0.95.
#
# Testing is done by transmitting random messages, with pipes used so that
# intermediate files are avoided. Decoding is done using a maximum of 250
# iterations of probability propagation.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-ldpc ex-ldpc36-5000a.pchk 5000 10000 2 evenboth 3 no4cycle
make-gen ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen dense
rand-src ex-ldpc36-5000a.src 1 5000x100
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.80 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.80 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.85 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.85 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.90 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.90 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.95 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.95 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src

View File

@ -1,54 +0,0 @@
make-ldpc ex-ldpc36-5000a.pchk 5000 10000 2 evenboth 3 no4cycle
Eliminated 25 cycles of length four by moving checks within column
make-gen ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen dense
Number of 1s per check in Inv(A) X B is 2068.3
rand-src ex-ldpc36-5000a.src 1 5000x100
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.80 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.80 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 100 valid. Average 11.1 iterations, 11% bit changes
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
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.85 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.85 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 95 valid. Average 33.7 iterations, 12% bit changes
Block counts: tot 100, with chk errs 5, with src errs 5, both 5
Bit error rate (on message bits only): 2.706e-03
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.90 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.90 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 2 valid. Average 246.2 iterations, 10% bit changes
Block counts: tot 100, with chk errs 98, with src errs 98, both 98
Bit error rate (on message bits only): 7.650e-02
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
encode ex-ldpc36-5000a.pchk ex-ldpc36-5000a.gen ex-ldpc36-5000a.src - \
| transmit - - 1 awgn 0.95 \
| decode ex-ldpc36-5000a.pchk - - awgn 0.95 prprp 250 \
| verify ex-ldpc36-5000a.pchk - ex-ldpc36-5000a.gen ex-ldpc36-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 0 valid. Average 250.0 iterations, 9% bit changes
Block counts: tot 100, with chk errs 100, with src errs 100, both 100
Bit error rate (on message bits only): 1.092e-01

View File

@ -1,46 +0,0 @@
#!/bin/sh
# Example of a (10000,5000) LDPC code with varying numbers of check per bit,
# tested on Additive White Gaussian Noise channels with noise standard
# deviations varying from 0.80 to 0.95. The code has 20% columns with two
# check bits, 70% columns with three check bits, and 10% columns with seven
# check bits.
#
# Testing is done by transmitting random messages, with pipes used so that
# intermediate files are avoided. Decoding is done using a maximum of 250
# iterations of probability propagation.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-ldpc ex-ldpcvar-5000a.pchk 5000 10000 2 evenboth 2x2/7x3/1x7 no4cycle
make-gen ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen dense
rand-src ex-ldpcvar-5000a.src 1 5000x100
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.80 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.80 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.85 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.85 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.90 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.90 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.95 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.95 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src

View File

@ -1,54 +0,0 @@
make-ldpc ex-ldpcvar-5000a.pchk 5000 10000 2 evenboth 2x2/7x3/1x7 no4cycle
Eliminated 46 cycles of length four by moving checks within column
make-gen ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen dense
Number of 1s per check in Inv(A) X B is 1437.1
rand-src ex-ldpcvar-5000a.src 1 5000x100
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.80 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.80 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 100 valid. Average 11.3 iterations, 11% bit changes
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
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.85 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.85 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 100 valid. Average 18.0 iterations, 12% bit changes
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.90, Eb/N0 = 0.92 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.90 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.90 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 65 valid. Average 119.8 iterations, 12% bit changes
Block counts: tot 100, with chk errs 35, with src errs 35, both 35
Bit error rate (on message bits only): 2.438e-02
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
encode ex-ldpcvar-5000a.pchk ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src - \
| transmit - - 1 awgn 0.95 \
| decode ex-ldpcvar-5000a.pchk - - awgn 0.95 prprp 250 \
| verify ex-ldpcvar-5000a.pchk - ex-ldpcvar-5000a.gen ex-ldpcvar-5000a.src
Encoded 100 blocks, source block size 5000, encoded block size 10000
Transmitted 1000000 bits
Decoded 100 blocks, 0 valid. Average 250.0 iterations, 9% bit changes
Block counts: tot 100, with chk errs 100, with src errs 100, both 100
Bit error rate (on message bits only): 1.017e-01

View File

@ -1,124 +0,0 @@
#!/bin/sh
# These tests investigate what happens when the wrong model is used for
# decoding. A (1800,1000) LDPC code with 3 check per bit is used.
# Testing is done by transmitting random messages. Decoding is done using
# a maximum of 100 iterations of probability propagation.
#
# The first set of tests compares decoding of messages sent through an
# AWGN channel using the correct AWGN model with sigma=0.90 to decoding
# using AWGN models with incorrect values for sigma and to decoding
# using AWLN models with varying width parameters for the logistic noise
# distribution.
#
# A second set of tests compares decoding of messages sent through an
# AWLN channel using the correct AWLN model with width=0.50 to decoding
# using AWLN models with incorrect values for width and to decoding
# using AWGN models with varying sigma parameters.
set -e # Stop if an error occurs
set -v # Echo commands as they are read
make-ldpc ex-wrong-model.pchk 1000 1800 1 evenboth 3 no4cycle
make-gen ex-wrong-model.pchk ex-wrong-model.gen dense
rand-src ex-wrong-model.src 1 800x1000
encode ex-wrong-model.pchk ex-wrong-model.gen ex-wrong-model.src \
ex-wrong-model.enc
# FIRST SET OF TESTS, TRANSMITTING THROUGH AWGN CHANNEL WITH SIGMA=0.90
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awgn 0.90
# DECODING WITH CORRECT AWGN NOISE MODEL, SIGMA=0.90
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.40
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.40 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.50
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.60
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.60 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.65
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.65 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# SECOND SET OF TESTS, TRANSMITTING THROUGH AWLN CHANNEL WITH WIDTH=0.50
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awln 0.50
# DECODING WITH CORRECT AWLN NOISE MODEL, WIDTH=0.50
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.80
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.80 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.90
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.00
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.00 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.05
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.05 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src

View File

@ -1,163 +0,0 @@
make-ldpc ex-wrong-model.pchk 1000 1800 1 evenboth 3 no4cycle
Eliminated 19 cycles of length four by moving checks within column
make-gen ex-wrong-model.pchk ex-wrong-model.gen dense
Number of 1s per check in Inv(A) X B is 318.6
rand-src ex-wrong-model.src 1 800x1000
encode ex-wrong-model.pchk ex-wrong-model.gen ex-wrong-model.src \
ex-wrong-model.enc
Encoded 1000 blocks, source block size 800, encoded block size 1800
# FIRST SET OF TESTS, TRANSMITTING THROUGH AWGN CHANNEL WITH SIGMA=0.90
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awgn 0.90
Transmitted 1800000 bits
# DECODING WITH CORRECT AWGN NOISE MODEL, SIGMA=0.90
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 910 valid. Average 25.8 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 90, with src errs 89, both 89
Bit error rate (on message bits only): 6.484e-03
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 909 valid. Average 25.7 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 91, with src errs 91, both 91
Bit error rate (on message bits only): 6.540e-03
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 900 valid. Average 27.7 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 100, with src errs 100, both 100
Bit error rate (on message bits only): 7.604e-03
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.40
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.40 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 755 valid. Average 42.3 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 245, with src errs 245, both 245
Bit error rate (on message bits only): 1.884e-02
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 827 valid. Average 34.7 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 173, with src errs 172, both 172
Bit error rate (on message bits only): 1.306e-02
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.50
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 849 valid. Average 31.7 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 151, with src errs 151, both 151
Bit error rate (on message bits only): 1.069e-02
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 855 valid. Average 32.3 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 145, with src errs 145, both 145
Bit error rate (on message bits only): 1.022e-02
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.60
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.60 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 790 valid. Average 40.0 iterations, 13% bit changes
Block counts: tot 1000, with chk errs 210, with src errs 210, both 210
Bit error rate (on message bits only): 1.452e-02
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.65
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.65 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 540 valid. Average 63.3 iterations, 11% bit changes
Block counts: tot 1000, with chk errs 460, with src errs 460, both 460
Bit error rate (on message bits only): 3.247e-02
# SECOND SET OF TESTS, TRANSMITTING THROUGH AWLN CHANNEL WITH WIDTH=0.50
transmit ex-wrong-model.enc ex-wrong-model.rec 1 awln 0.50
Transmitted 1800000 bits
# DECODING WITH CORRECT AWLN NOISE MODEL, WIDTH=0.50
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.50 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 914 valid. Average 25.1 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 86, with src errs 86, both 86
Bit error rate (on message bits only): 6.130e-03
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.55
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.55 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 907 valid. Average 25.6 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 93, with src errs 93, both 93
Bit error rate (on message bits only): 6.474e-03
# DECODING WITH AWLN NOISE MODEL, WIDTH=0.45
decode ex-wrong-model.pchk ex-wrong-model.rec - awln 0.45 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 893 valid. Average 27.5 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 107, with src errs 107, both 107
Bit error rate (on message bits only): 7.744e-03
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.80
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.80 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 702 valid. Average 44.9 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 298, with src errs 298, both 298
Bit error rate (on message bits only): 2.245e-02
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.85
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.85 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 765 valid. Average 39.4 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 235, with src errs 235, both 235
Bit error rate (on message bits only): 1.693e-02
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.90
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.90 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 808 valid. Average 35.7 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 192, with src errs 192, both 192
Bit error rate (on message bits only): 1.374e-02
# DECODING WITH AWGN NOISE MODEL, SIGMA=0.95
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 0.95 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 814 valid. Average 34.6 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 186, with src errs 186, both 186
Bit error rate (on message bits only): 1.291e-02
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.00
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.00 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 808 valid. Average 35.6 iterations, 12% bit changes
Block counts: tot 1000, with chk errs 192, with src errs 192, both 192
Bit error rate (on message bits only): 1.320e-02
# DECODING WITH AWGN NOISE MODEL, SIGMA=1.05
decode ex-wrong-model.pchk ex-wrong-model.rec - awgn 1.05 prprp 100 \
| verify ex-wrong-model.pchk - ex-wrong-model.gen ex-wrong-model.src
Decoded 1000 blocks, 771 valid. Average 40.7 iterations, 11% bit changes
Block counts: tot 1000, with chk errs 229, with src errs 228, both 228
Bit error rate (on message bits only): 1.524e-02

View File

@ -1,87 +0,0 @@
<HTML><HEAD>
<TITLE> Examples of LDPC Program Usage </TITLE>
</HEAD><BODY>
<H1> Examples of LDPC Program Usage </H1>
<P>Below, are some command files containing examples of the use of
the <A HREF="progs.html">LDPC programs</A>, together with the output I
obtained for these examples. Output on other machines might
conceivably be slightly different, due to different round-off errors.
The <A HREF="run-examples"><TT>run-examples</TT></A> script runs all the example
scripts and compares their output with the outputs that I obtained (on
a Pentium machine).
<P><A HREF="ex-ham7b">ex-ham7b</A>,
output in <A HREF="ex-ham7b-out">ex-ham7b-out</A>
<BLOCKQUOTE>
A (7,4) Hamming code used with a BSC.
Demonstrates encoding of random messages and decoding to minimize
bit error rate by exhaustive enumeration.
</BLOCKQUOTE>
<P><A HREF="ex-ham7a">ex-ham7a</A>,
output in <A HREF="ex-ham7a-out">ex-ham7a-out</A>
<BLOCKQUOTE>
A (7,4) Hamming code used with an AWGN channel. Tested using zero messages.
Decoded by exhaustive enumeration to minimize either block or bit error rate,
and by probability propagation.
</BLOCKQUOTE>
<P><A HREF="ex-dep">ex-dep</A>,
output in <A HREF="ex-dep-out">ex-dep-out</A>
<BLOCKQUOTE>
Examples of how parity check matrices with linearly dependent rows (ie,
redundant parity checks) are handled. This is probably not of
great interest to most users.
</BLOCKQUOTE>
<P><A HREF="ex-ldpc-encode">ex-ldpc-encode</A>,
output in <A HREF="ex-ldpc-encode-out">ex-ldpc-encode-out</A>
<BLOCKQUOTE>
Encodes messages with an LDPC code using sparse, dense, and mixed
representations of the generator matrix.
</BLOCKQUOTE>
<P><A HREF="ex-ldpc36-1000a">ex-ldpc36-1000a</A>,
output in <A HREF="ex-ldpc36-1000a-out">ex-ldpc36-1000a-out</A>
<BLOCKQUOTE>
A (2000,1000) LDPC code with 3 checks per bit and 6 bits per check.
Three encoding methods are tried out, and the code is
tested on an AWGN channel at various noise levels, using random messages.
</BLOCKQUOTE>
<P><A HREF="ex-ldpc36-5000a">ex-ldpc36-5000a</A>,
output in <A HREF="ex-ldpc36-5000a-out">ex-ldpc36-5000a-out</A>
<BLOCKQUOTE>
A (10000,5000) LDPC code with 3 checks per bit and 6 bits per check.
Tested on an AWGN channel at various noise levels, using random messages.
Pipes are used to avoid creating lots of files.
</BLOCKQUOTE>
<P><A HREF="ex-ldpcvar-5000a">ex-ldpcvar-5000a</A>,
output in <A HREF="ex-ldpcvar-5000a-out">ex-ldpcvar-5000a-out</A>
<BLOCKQUOTE>
A (10000,5000) LDPC code with the number of checks per bit varying from 2 to 7.
Tested on an AWGN channel at various noise levels, using random messages.
Pipes are used to avoid creating lots of files. Performance is better than
for the code above in which the number of checks is the same for all bits.
</BLOCKQUOTE>
<P><A HREF="ex-wrong-model">ex-wrong-model</A>,
output in <A HREF="ex-wrong-model-out">ex-wrong-model-out</A>
<BLOCKQUOTE>
Tests what happens when messages are decoded using the wrong noise
model, including using the right type of model but with the wrong
noise level, and using the wrong type of model (ie, using an AWLN model
for messages transmitted through an AWGN channel, or vice versa).
</BLOCKQUOTE>
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,112 +0,0 @@
/* EXTRACT.C - Extract message bits from coded blocks. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "alloc.h"
#include "blockio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *gen_file, *coded_file, *ext_file;
FILE *codef, *extf;
char *cblk;
int i;
/* Look at arguments. */
if (!(gen_file = argv[1])
|| !(coded_file = argv[2])
|| !(ext_file = argv[3])
|| argv[4])
{ usage();
}
if ((strcmp(gen_file,"-")==0) + (strcmp(coded_file,"-")==0) > 1)
{ fprintf(stderr,"Can't read more than one stream from standard input\n");
exit(1);
}
/* Read generator matrix file, up to the point of finding out which
are the message bits. */
read_gen(gen_file,1,1);
/* Open decoded file. */
codef = open_file_std(coded_file,"r");
if (codef==NULL)
{ fprintf(stderr,"Can't open coded file: %s\n",coded_file);
exit(1);
}
/* Open file to write extracted message bits to. */
extf = open_file_std(ext_file,"w");
if (extf==NULL)
{ fprintf(stderr,"Can't create file for extracted bits: %s\n",ext_file);
exit(1);
}
cblk = chk_alloc (N, sizeof *cblk);
for (;;)
{
/* Read block from coded file. */
if (blockio_read(codef,cblk,N)==EOF) break;
/* Extract message bits and write to file, followed by newline to mark
block boundary. */
for (i = M; i<N; i++)
{ putc("01"[cblk[cols[i]]],extf);
}
putc('\n',extf);
}
if (ferror(extf) || fclose(extf)!=0)
{ fprintf(stderr,"Error writing extracted data to %s\n",ext_file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,
"Usage: extract gen-file decoded-file extracted-file\n");
exit(1);
}

View File

@ -1,67 +0,0 @@
<HTML><HEAD>
<TITLE> Github Facilities </TITLE>
</HEAD><BODY>
<H1> Github Facilities </H1>
<P>Starting with the Version of 2012-02-11, the source code repository
for this software is hosted by <A HREF="http://github.com">Github</A>,
and is located at <A
HREF="http://github.com/radfordneal/LDPC-codes">http://github.com/radfordneal/LDPC-codes</A>.
This repository includes the annotated log of changes made since the
Version of 2006-02-08.
<P>You can use the facilities at Github to obtain the source-code
repository, report bugs, and contribute to the wiki.
<H2>Obtaining the source repository, and modifying it</H2>
<P>To obtain a copy of the source-code repository, issue the following
command (in a Unix/Linux/Cygwin environment that has git installed):
<BLOCKQUOTE><PRE>
git clone git://github.com/radfordneal/LDPC-codes
</PRE></BLOCKQUOTE>
This will retrieve the current state of the software, storing it
in the directory <TT>LDPC-codes</TT>, which you should ensure does not
exist before issuing this command above.
<P>Note that if all you want to do is compile and use the current
version, you can instead download the source without development
history as described in the <A HREF="install.html">installation
instructions</A>.
<P>The <TT>LDPC-codes</TT> directory created by the <TT>git clone</TT>
command is a git repository, which can be manipulated with the various
forms of the <TT>git</TT> command, which are documented, for example,
<A HREF="http://git-scm.com/documentation">here</A>.
<P>Each stable version of the software is a separate branch of the
repository. The documentation on the most recent stable version is in
the "gh-pages" branch. The current development version is on the
"master" branch. The are other branches for each stable version that
was released.
<P>You can make local changes to your copy of the repository, and use
the modified software. If you wish, you can ask me
(radfordneal@gmail.com) to include your changes in a new release, or,
if you register as a <A HREF="http://github.com">Github</A> user, you can set
up your own fork of the software for you and other people to use.
<H2>Reporting Bugs</H2>
You can use the Github "Issues" facility to report bugs in the
software. You have to register as a <A HREF="github.com">Github</A>
user to do this (which is free). You can then go <A
HREF="https://github.com/radfordneal/LDPC-codes/issues">here</A> and
click on "New issue" to report a bug. You can also use this facility
to suggest new features or other revisions. I may not have time to
implement them, but perhaps someone else will.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,89 +0,0 @@
<HTML><HEAD>
<TITLE> Software for Low Density Parity Check Codes </TITLE>
</HEAD><BODY>
<H1> Software for Low Density Parity Check Codes </H1>
<P>Version in development.
<P>This collection of programs and modules, written in C, is intended
to support research and education concerning Low Density Parity Check
(LDPC) codes. (Note, however, that the copyright notice no longer
restricts use to these purposes). These error-correcting codes were
invented by Robert Gallager in the early 1960's, and re-invented and
shown to have very good performance by David MacKay and myself in the
mid-1990's. The decoding algorithm for LDPC codes is related to that
used for Turbo codes, and to probabilistic inference methods used in
other fields. Variations on LDPC and Turbo codes are currently the
best practical codes known, in terms of their ability to transmit data
at rates approaching channel capacity with very low error probability.
<p>This and past versions of the software are available <A
HREF="http://www.cs.utoronto.ca/~radford/ldpc.software.html">here</A>,
from <A HREF="http://www.cs.utoronto.ca/~radford/">Radford Neal<A>'s
web page. The source code for this software is also <A
HREF="http://github.com/radfordneal/LDPC-codes">hosted at Github</A>,
where there is a <A HREF="http://radfordneal.github.com/LDPC-codes/">copy
of these documentation pages</A> for the latest release. Github also
provides facilities for bug reporting and discussion.
<H2>Index to Documentation</H2>
<A HREF="install.html">Download and installation instructions</A>
<BLOCKQUOTE>
How to get and compile the programs and modules.
</BLOCKQUOTE>
<A HREF="github.html">Github facilities</A>
<BLOCKQUOTE>
How to get the source repository, report bugs, etc.
</BLOCKQUOTE>
<A HREF="release.html">Release notes</A>
<BLOCKQUOTE>
A log of changes made in each release of this software.
</BLOCKQUOTE>
<A HREF="progs.html">Software and program usage documentation</A>
<BLOCKQUOTE>
General documentation on the methods implemented, and details of
program usage.
</BLOCKQUOTE>
<A HREF="examples.html">Examples of program usage</A>
<BLOCKQUOTE>
Examples using simple Hamming codes, and using more interesting LDPC codes.
</BLOCKQUOTE>
<A HREF="modify.html">How to modify the programs</A>
<BLOCKQUOTE>
Notes on how to add new channel types, new decoding methods, etc.
</BLOCKQUOTE>
<A HREF="modules.html">Module documentation</A>
<BLOCKQUOTE>
Modules used by the programs for modulo-2 matrix
operations and random number generation.
</BLOCKQUOTE>
<A HREF="refs.html">References</A>
<BLOCKQUOTE>
Classic and more recent papers on LDPC codes and related topics.
</BLOCKQUOTE>
<H2> <A NAME="copyright">Copyright and Lack of Warranty</A> </H2>
<P> Except as otherwise specified, all of this software and
documentation is copyright &copy; 1995-2012 by Radford M. Neal.
<P>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.
<P>Some routines in the module rand.c are taken from the GNU C Library,
and are copyrighted as described there and in the file LGPL.
</BODY></HTML>

View File

@ -1,82 +0,0 @@
<HTML><HEAD>
<TITLE> Installing the LDPC Software </TITLE>
</HEAD><BODY>
<H1> Installing the LDPC Software </H1>
The LDPC software is written in C, and may well work with any C
compiler, though it has been tested only with gcc, in Unix and Linux
environments, and in the <A HREF="http://www.cygwin.com">Cygwin</A>
Unix-like environment that runs under Microsoft Windows. The
installation instructions below assume that you are using a Unix-like
system.
<P>All the software, including the documentation you are viewing here,
is contained in a tar file, which you can download by clicking one
of the options below:
<BLOCKQUOTE>
<A HREF="http://www.cs.utoronto.ca/~radford/ftp/LDPC-yyyy-mm-dd/LDPC-yyyy-mm-dd.tar">Tar
file of LDPC software</A> (0.9 Megabytes)<BR>
<A HREF="http://www.cs.utoronto.ca/~radford/ftp/LDPC-yyyy-mm-dd/LDPC-yyyy-mm-dd.tar.gz">Gzipped
tar file of LDPC software</A> (0.4 Megabytes)
</BLOCKQUOTE>
<P>Once you obtain the tar file (and uncompress it with gunzip if
necessary), you should extract the files with the following Unix command:
<BLOCKQUOTE><PRE>
tar xf LDPC-yyyy-mm-dd.tar
</PRE></BLOCKQUOTE>
This will create a source directory called <TT>LDPC-yyyy-mm-dd</TT>, and place
all the source, documentation, and other files in this directory.
<P>If you prefer for this directory to be called something else,
rename it <B>now</B>, before compiling the programs, since the file
<TT>randfile</TT> in this directory, containing natural random numbers,
is accessed according to its path when the programs were compiled.
<P>Once the tar command above has finished, you should change into the
newly-created directory, and type
<BLOCKQUOTE><PRE>
make
</PRE></BLOCKQUOTE>
If all goes well, this should compile all the programs (except for some
test programs, which can be compiled with <TT>make test</TT>). You
may want to edit the file <TT>Makefile</TT> before running <TT>make</TT>
in order to change compilation options, such as the optimization level.
<P>You can run the programs from this source directory, or you can copy
them to some other directory by running the <TT>LDPC-install</TT>
shell file. For instance, to install them in a bin directory in your
home directory, do the following:
<BLOCKQUOTE><PRE>
./LDPC-install $HOME/bin
</PRE></BLOCKQUOTE>
<P>The source directory contains a copy of all the HTML files
documenting the software, such as the one you are reading now, with
the file <TT>index.html</TT> being the starting point. It is best to
use this local copy when referring to the documentation, rather than
get it off the web, since that is faster and also insures that the
documentation is for the version that you are using. Just tell your
browser to open the URL
<BLOCKQUOTE><PRE>
file:<I>path-to-software</I>/index.html
</PRE></BLOCKQUOTE>
where <TT><I>path-to-software</I></TT> is the full path (starting with "/")
to the directory where you've put the software.
<P>The command
<BLOCKQUOTE><PRE>
make clean
</PRE></BLOCKQUOTE>
will remove all the compiled programs, as well as the files created when
the <A HREF="examples.html">examples</A> are run, and <TT>core</TT>, if it
exists.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,110 +0,0 @@
/* INTIO.C - Routines to read and write integers one byte at a time. */
/* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include "intio.h"
/* READ AN INTEGER ONE BYTE AT A TIME. Four bytes are read, ordered from
low to high order. These are considered to represent a signed integer,
in two's complement form. The value returned is this integer, converted
to whatever a C "int" is. The conversion should work as long as an "int"
is at least four bytes, even if it's not in two's complement representation
(except for the largest two's complement negative integer).
If an error or eof is encountered, zero is returned. The caller can
check for these events using feof and ferror.
The file read from should have been opened as "binary".
*/
int intio_read
( FILE *f /* File to read from */
)
{
unsigned char b[4];
int top;
int i;
for (i = 0; i<4; i++)
{ if (fread(&b[i],1,1,f) != 1) return 0;
}
top = b[3]>127 ? (int)b[3] - 256 : b[3];
return (top<<24) + (b[2]<<16) + (b[1]<<8) + b[0];
}
/* WRITE AN INTEGER ONE BYTE AT A TIME. Four bytes are written, ordered from
low to high order. These are considered to represent a signed integer,
in two's complement form. This should work as long as the integer passed
can be represented in four bytes, even if a C "int" is longer than this.
The file written to should have been opened as "binary".
*/
void intio_write
( FILE *f, /* File to write to */
int v /* Value to write to file */
)
{
unsigned char b;
int i;
for (i = 0; i<3; i++)
{ b = v&0xff;
fwrite(&b,1,1,f);
v >>= 8;
}
b = v>0 ? v : v+256;
fwrite(&b,1,1,f);
}
/* TEST PROGRAM. */
#ifdef TEST_INTIO
main(void)
{
FILE *f;
f = fopen("test","wb");
intio_write(f,334);
intio_write(f,-40000);
intio_write(f,0x8fffffff);
intio_write(f,-0x8fffffff);
fclose(f);
f = fopen("test","rb");
if (intio_read(f)!=334
|| intio_read(f)!=-40000
|| intio_read(f)!=0x8fffffff
|| intio_read(f)!=-0x8fffffff)
{ fprintf(stderr,"got back bad data\n");
exit(1);
}
if (intio_read(f)!=0 || !feof(f) || ferror(f))
{ fprintf(stderr,"eof not handled correctly\n");
exit(1);
}
fclose(f);
fprintf(stderr,"OK\n");
exit(0);
}
#endif

View File

@ -1,17 +0,0 @@
/* INTIO.H - Interface for reading and writing integers one byte at a time. */
/* 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.
*/
int intio_read (FILE *); /* Read an integer */
void intio_write (FILE *, int); /* Write an integer */

View File

@ -1,12 +0,0 @@
rate 1/2 constraint len 13, bpsk, ngood, nbad 10^6 trials
0.00 43968 30
0.50 111824 33
1.00 238157 21
1.50 425263 20
2.00 634824 14
2.50 812206 2
3.00 924507 2
3.50 975836 0
4.00 993832 0
4.50 998695 0
5.00 999771 0

View File

@ -1,350 +0,0 @@
/* MAKE-GEN.C - Make generator matrix from parity-check matrix. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "alloc.h"
#include "intio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
typedef enum { Sparse, Dense, Mixed } make_method; /* Ways of making it */
void make_dense_mixed (FILE *, make_method, char *); /* Procs to make it */
void make_sparse (FILE *, mod2sparse_strategy, int, int);
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *pchk_file, *gen_file, *other_gen_file;
mod2sparse_strategy strategy;
int abandon_when, abandon_number;
make_method method;
char *meth;
char junk;
FILE *f;
/* Look at arguments. */
if (!(pchk_file = argv[1])
|| !(gen_file = argv[2])
|| !(meth = argv[3]))
{ usage();
}
if (strcmp(meth,"sparse")==0)
{ method = Sparse;
strategy = Mod2sparse_minprod;
abandon_number = 0;
if (argv[4])
{ if (strcmp(argv[4],"first")==0) strategy = Mod2sparse_first;
else if (strcmp(argv[4],"mincol")==0) strategy = Mod2sparse_mincol;
else if (strcmp(argv[4],"minprod")==0) strategy = Mod2sparse_minprod;
else
{ usage();
}
if (argv[5])
{ if (sscanf(argv[5],"%d%c",&abandon_number,&junk)!=1 || abandon_number<=0
|| !argv[6]
|| sscanf(argv[6],"%d%c",&abandon_when,&junk)!=1 || abandon_when<=0
|| argv[7])
{ usage();
}
}
}
}
else if (strcmp(meth,"dense")==0)
{ method = Dense;
other_gen_file = argv[4];
if (other_gen_file && argv[5])
{ usage();
}
}
else if (strcmp(meth,"mixed")==0)
{ method = Mixed;
other_gen_file = argv[4];
if (other_gen_file && argv[5])
{ usage();
}
}
else
{ usage();
}
/* Read parity check matrix. */
read_pchk(pchk_file);
if (N<=M)
{ fprintf(stderr,
"Can't encode if number of bits (%d) isn't greater than number of checks (%d)\n",N,M);
exit(1);
}
/* Create generator matrix file. */
f = open_file_std(gen_file,"wb");
if (f==NULL)
{ fprintf(stderr,"Can't create generator matrix file: %s\n",gen_file);
exit(1);
}
/* Allocate space for row and column permutations. */
cols = chk_alloc (N, sizeof *cols);
rows = chk_alloc (M, sizeof *rows);
/* Create generator matrix with specified method. */
switch (method)
{ case Sparse:
{ make_sparse(f,strategy,abandon_number,abandon_when);
break;
}
case Dense: case Mixed:
{ make_dense_mixed(f,method,other_gen_file);
break;
}
default: abort();
}
/* Check for error writing file. */
if (ferror(f) || fclose(f)!=0)
{ fprintf(stderr,"Error writing to generator matrix file\n");
exit(1);
}
return 0;
}
/* MAKE DENSE OR MIXED REPRESENTATION OF GENERATOR MATRIX. */
void make_dense_mixed
( FILE *f,
make_method method,
char *other_gen_file
)
{
mod2dense *DH, *A, *A2, *AI, *B;
int i, j, c, c2, n;
int *rows_inv;
DH = mod2dense_allocate(M,N);
AI = mod2dense_allocate(M,M);
B = mod2dense_allocate(M,N-M);
G = mod2dense_allocate(M,N-M);
mod2sparse_to_dense(H,DH);
/* If another generator matrix was specified, invert using the set of
columns it specifies. */
if (other_gen_file)
{
read_gen(other_gen_file,1,0);
A = mod2dense_allocate(M,M);
mod2dense_copycols(DH,A,cols);
if (!mod2dense_invert(A,AI))
{ fprintf(stderr,
"Couldn't invert sub-matrix with column order given in other file\n");
exit(1);
}
mod2dense_copycols(DH,B,cols+M);
}
/* If no other generator matrix was specified, invert using whatever
selection of rows/columns is needed to get a non-singular sub-matrix. */
if (!other_gen_file)
{
A = mod2dense_allocate(M,N);
A2 = mod2dense_allocate(M,N);
n = mod2dense_invert_selected(DH,A2,rows,cols);
mod2sparse_to_dense(H,DH); /* DH was destroyed by invert_selected */
if (n>0)
{ fprintf(stderr,"Note: Parity check matrix has %d redundant checks\n",n);
}
rows_inv = chk_alloc (M, sizeof *rows_inv);
for (i = 0; i<M; i++)
{ rows_inv[rows[i]] = i;
}
mod2dense_copyrows(A2,A,rows);
mod2dense_copycols(A,A2,cols);
mod2dense_copycols(A2,AI,rows_inv);
mod2dense_copycols(DH,B,cols+M);
}
/* Form final generator matrix. */
if (method==Dense)
{ mod2dense_multiply(AI,B,G);
}
else if (method==Mixed)
{ G = AI;
}
else
{ abort();
}
/* Compute and print number of 1s. */
if (method==Dense)
{ c = 0;
for (i = 0; i<M; i++)
{ for (j = 0; j<N-M; j++)
{ c += mod2dense_get(G,i,j);
}
}
fprintf(stderr,
"Number of 1s per check in Inv(A) X B is %.1f\n", (double)c/M);
}
if (method==Mixed)
{ c = 0;
for (i = 0; i<M; i++)
{ for (j = 0; j<M; j++)
{ c += mod2dense_get(G,i,j);
}
}
c2 = 0;
for (i = M; i<N; i++)
{ c2 += mod2sparse_count_col(H,cols[i]);
}
fprintf(stderr,
"Number of 1s per check in Inv(A) is %.1f, in B is %.1f, total is %.1f\n",
(double)c/M, (double)c2/M, (double)(c+c2)/M);
}
/* Write the represention of the generator matrix to the file. */
intio_write(f,('G'<<8)+0x80);
if (method==Dense)
{ fwrite ("d", 1, 1, f);
}
if (method==Mixed)
{ fwrite ("m", 1, 1, f);
}
intio_write(f,M);
intio_write(f,N);
for (i = 0; i<N; i++)
{ intio_write(f,cols[i]);
}
mod2dense_write (f, G);
}
/* MAKE SPARSE REPRESENTATION OF GENERATOR MATRIX. */
void make_sparse
( FILE *f,
mod2sparse_strategy strategy,
int abandon_number,
int abandon_when
)
{
int n, cL, cU, cB;
int i;
/* Find LU decomposition. */
L = mod2sparse_allocate(M,M);
U = mod2sparse_allocate(M,N);
n = mod2sparse_decomp(H,M,L,U,rows,cols,strategy,abandon_number,abandon_when);
if (n!=0 && abandon_number==0)
{ fprintf(stderr,"Note: Parity check matrix has %d redundant checks\n",n);
}
if (n!=0 && abandon_number>0)
{ fprintf(stderr,
"Note: Have %d dependent columns, but this could be due to abandonment.\n",n);
fprintf(stderr,
" Try again with lower abandonment number.\n");
exit(1);
}
/* Compute and print number of 1s. */
cL = cU = cB = 0;
for (i = 0; i<M; i++) cL += mod2sparse_count_row(L,i);
for (i = 0; i<M; i++) cU += mod2sparse_count_row(U,i);
for (i = M; i<N; i++) cB += mod2sparse_count_col(H,cols[i]);
fprintf(stderr,
"Number of 1s per check in L is %.1f, U is %.1f, B is %.1f, total is %.1f\n",
(double)cU/M, (double)cL/M, (double)cB/M, (double)(cL+cU+cB)/M);
/* Write it all to the generator matrix file. */
intio_write(f,('G'<<8)+0x80);
fwrite ("s", 1, 1, f);
intio_write(f,M);
intio_write(f,N);
for (i = 0; i<N; i++)
{ intio_write(f,cols[i]);
}
for (i = 0; i<M; i++)
{ intio_write(f,rows[i]);
}
mod2sparse_write (f, L);
mod2sparse_write (f, U);
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf (stderr,
"Usage: make-gen pchk-file gen-file method\n");
fprintf (stderr,
"Method: sparse [ \"first\" | \"mincol\" | \"minprod\" ] [ abandon_num abandon_when ]\n");
fprintf (stderr,
" or: dense [ other-gen-file ]\n");
fprintf (stderr,
" or: mixed [ other-gen-file ]\n");
exit(1);
}

View File

@ -1,415 +0,0 @@
/* MAKE-LDPC.C - Make a Low Density Parity Check code's parity check matrix. */
/* Copyright (c) 1995-2012 by Radford M. Neal and Peter Junteng Liu.
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "rand.h"
#include "alloc.h"
#include "intio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
#include "distrib.h"
/* METHODS FOR CONSTRUCTING CODES. */
typedef enum
{ Evencol, /* Uniform number of bits per column, with number specified */
Evenboth /* Uniform (as possible) over both columns and rows */
} make_method;
void make_ldpc (int, make_method, distrib *, int);
int *column_partition (distrib *, int);
void usage (void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
make_method method;
char *file, **meth;
int seed, no4cycle;
distrib *d;
char junk;
FILE *f;
/* Look at initial arguments. */
if (!(file = argv[1])
|| !argv[2] || sscanf(argv[2],"%d%c",&M,&junk)!=1 || M<=0
|| !argv[3] || sscanf(argv[3],"%d%c",&N,&junk)!=1 || N<=0
|| !argv[4] || sscanf(argv[4],"%d%c",&seed,&junk)!=1)
{ usage();
}
/* Look at the arguments specifying the method for producing the code. */
meth = argv+5;
if (!meth[0]) usage();
no4cycle = 0;
if (strcmp(meth[0],"evencol")==0 || strcmp(meth[0],"evenboth")==0)
{ method = strcmp(meth[0],"evencol")==0 ? Evencol : Evenboth;
if (!meth[1])
{ usage();
}
d = distrib_create(meth[1]);
if (d==0)
{ usage();
}
if (meth[2])
{ if (strcmp(meth[2],"no4cycle")==0)
{ no4cycle = 1;
if (meth[3])
{ usage();
}
}
else
{ usage();
}
}
}
else
{ usage();
}
/* Check for some problems. */
if (distrib_max(d)>M)
{ fprintf(stderr,
"At least one checks per bit (%d) is greater than total checks (%d)\n",
distrib_max(d), M);
exit(1);
}
if (distrib_max(d)==M && N>1 && no4cycle)
{ fprintf(stderr,
"Can't eliminate cycles of length four with this many checks per bit\n");
exit(1);
}
/* Make the parity check matrix. */
make_ldpc(seed,method,d,no4cycle);
/* Write out the parity check matrix. */
f = open_file_std(file,"wb");
if (f==NULL)
{ fprintf(stderr,"Can't create parity check file: %s\n",file);
exit(1);
}
intio_write(f,('P'<<8)+0x80);
if (ferror(f) || !mod2sparse_write(f,H) || fclose(f)!=0)
{ fprintf(stderr,"Error writing to parity check file %s\n",file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage: make-ldpc pchk-file n-checks n-bits seed method\n");
fprintf(stderr,"Method: evencol checks-per-col [ \"no4cycle\" ]\n");
fprintf(stderr," or: evencol checks-distribution [ \"no4cycle\" ]\n");
fprintf(stderr," or: evenboth checks-per-col [ \"no4cycle\" ]\n");
fprintf(stderr," or: evenboth checks-distribution [ \"no4cycle\" ]\n");
exit(1);
}
/* CREATE A SPARSE PARITY-CHECK MATRIX. Of size M by N, stored in H. */
void make_ldpc
( int seed, /* Random number seed */
make_method method, /* How to make it */
distrib *d, /* Distribution list specified */
int no4cycle /* Eliminate cycles of length four? */
)
{
mod2entry *e, *f, *g, *h;
int added, uneven, elim4, all_even, n_full, left;
int i, j, k, t, z, cb_N;
int *part, *u;
rand_seed(10*seed+1);
H = mod2sparse_allocate(M,N);
part = column_partition(d,N);
/* Create the initial version of the parity check matrix. */
switch (method)
{
case Evencol:
{
z = 0;
left = part[z];
for (j = 0; j<N; j++)
{ while (left==0)
{ z += 1;
if (z>distrib_size(d))
{ abort();
}
left = part[z];
}
for (k = 0; k<distrib_num(d,z); k++)
{ do
{ i = rand_int(M);
} while (mod2sparse_find(H,i,j));
mod2sparse_insert(H,i,j);
}
left -= 1;
}
break;
}
case Evenboth:
{
cb_N = 0;
for (z = 0; z<distrib_size(d); z++)
{ cb_N += distrib_num(d,z) * part[z];
}
u = chk_alloc (cb_N, sizeof *u);
for (k = cb_N-1; k>=0; k--)
{ u[k] = k%M;
}
uneven = 0;
t = 0;
z = 0;
left = part[z];
for (j = 0; j<N; j++)
{
while (left==0)
{ z += 1;
if (z>distrib_size(d))
{ abort();
}
left = part[z];
}
for (k = 0; k<distrib_num(d,z); k++)
{
for (i = t; i<cb_N && mod2sparse_find(H,u[i],j); i++) ;
if (i==cb_N)
{ uneven += 1;
do
{ i = rand_int(M);
} while (mod2sparse_find(H,i,j));
mod2sparse_insert(H,i,j);
}
else
{ do
{ i = t + rand_int(cb_N-t);
} while (mod2sparse_find(H,u[i],j));
mod2sparse_insert(H,u[i],j);
u[i] = u[t];
t += 1;
}
}
left -= 1;
}
if (uneven>0)
{ fprintf(stderr,"Had to place %d checks in rows unevenly\n",uneven);
}
break;
}
default: abort();
}
/* Add extra bits to avoid rows with less than two checks. */
added = 0;
for (i = 0; i<M; i++)
{ e = mod2sparse_first_in_row(H,i);
if (mod2sparse_at_end(e))
{ j = rand_int(N);
e = mod2sparse_insert(H,i,j);
added += 1;
}
e = mod2sparse_first_in_row(H,i);
if (mod2sparse_at_end(mod2sparse_next_in_row(e)) && N>1)
{ do
{ j = rand_int(N);
} while (j==mod2sparse_col(e));
mod2sparse_insert(H,i,j);
added += 1;
}
}
if (added>0)
{ fprintf(stderr,
"Added %d extra bit-checks to make row counts at least two\n",
added);
}
/* Add extra bits to try to avoid problems with even column counts. */
n_full = 0;
all_even = 1;
for (z = 0; z<distrib_size(d); z++)
{ if (distrib_num(d,z)==M)
{ n_full += part[z];
}
if (distrib_num(d,z)%2==1)
{ all_even = 0;
}
}
if (all_even && N-n_full>1 && added<2)
{ int a;
for (a = 0; added+a<2; a++)
{ do
{ i = rand_int(M);
j = rand_int(N);
} while (mod2sparse_find(H,i,j));
mod2sparse_insert(H,i,j);
}
fprintf(stderr,
"Added %d extra bit-checks to try to avoid problems from even column counts\n",
a);
}
/* Eliminate cycles of length four, if asked, and if possible. */
if (no4cycle)
{
elim4 = 0;
for (t = 0; t<10; t++)
{ k = 0;
for (j = 0; j<N; j++)
{ for (e = mod2sparse_first_in_col(H,j);
!mod2sparse_at_end(e);
e = mod2sparse_next_in_col(e))
{ for (f = mod2sparse_first_in_row(H,mod2sparse_row(e));
!mod2sparse_at_end(f);
f = mod2sparse_next_in_row(f))
{ if (f==e) continue;
for (g = mod2sparse_first_in_col(H,mod2sparse_col(f));
!mod2sparse_at_end(g);
g = mod2sparse_next_in_col(g))
{ if (g==f) continue;
for (h = mod2sparse_first_in_row(H,mod2sparse_row(g));
!mod2sparse_at_end(h);
h = mod2sparse_next_in_row(h))
{ if (mod2sparse_col(h)==j)
{ do
{ i = rand_int(M);
} while (mod2sparse_find(H,i,j));
mod2sparse_delete(H,e);
mod2sparse_insert(H,i,j);
elim4 += 1;
k += 1;
goto nextj;
}
}
}
}
}
nextj: ;
}
if (k==0) break;
}
if (elim4>0)
{ fprintf(stderr,
"Eliminated %d cycles of length four by moving checks within column\n",
elim4);
}
if (t==10)
{ fprintf(stderr,
"Couldn't eliminate all cycles of length four in 10 passes\n");
}
}
}
/* PARTITION THE COLUMNS ACCORDING TO THE SPECIFIED PROPORTIONS. It
may not be possible to do this exactly. Returns a pointer to an
array of integers containing the numbers of columns corresponding
to the entries in the distribution passed. */
int *column_partition
( distrib *d, /* List of proportions and number of check-bits */
int n /* Total number of columns to partition */
)
{
double *trunc;
int *part;
int cur, used;
int i, j;
trunc = chk_alloc (distrib_size(d), sizeof(double));
part = chk_alloc (distrib_size(d), sizeof(int));
used = 0;
for (i = 0; i<distrib_size(d); i++)
{ cur = floor(distrib_prop(d,i)*n);
part[i] = cur;
trunc[i] = distrib_prop(d,i)*n - cur;
used += cur;
}
if (used>n)
{ abort();
}
while (used<n)
{ cur = 0;
for (j = 1; j<distrib_size(d); j++)
{ if (trunc[j]>trunc[cur])
{ cur = j;
}
}
part[cur] += 1;
used += 1;
trunc[cur] = -1;
}
free(trunc);
return part;
}

View File

@ -1,93 +0,0 @@
/* MAKE-PCHK.C - Make a parity check matrix explicitly. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "alloc.h"
#include "intio.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char **bit_specs;
char *file;
FILE *f;
int i, j, k;
char junk;
if (!(file = argv[1])
|| !argv[2] || sscanf(argv[2],"%d%c",&M,&junk)!=1 || M<=0
|| !argv[3] || sscanf(argv[3],"%d%c",&N,&junk)!=1 || N<=0)
{ usage();
}
bit_specs = argv+4;
if (bit_specs[0]==0)
{ usage();
}
H = mod2sparse_allocate(M,N);
for (k = 0; bit_specs[k]!=0; k++)
{ if (sscanf(bit_specs[k],"%d:%d%c",&i,&j,&junk)!=2 || i<0 || j<0)
{ usage();
}
if (i>=M || j>=N)
{ fprintf(stderr,"Bit %d:%d is out of range\n",i,j);
exit(1);
}
mod2sparse_insert(H,i,j);
}
f = open_file_std(file,"wb");
if (f==NULL)
{ fprintf(stderr,"Can't create parity check file: %s\n",file);
exit(1);
}
intio_write(f,('P'<<8)+0x80);
if (ferror(f) || !mod2sparse_write(f,H) || fclose(f)!=0)
{ fprintf(stderr,"Error writing to parity check file %s\n",file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage: make-pchk pchk-file n-checks n-bits row:col ...\n");
exit(1);
}

View File

@ -1,9 +0,0 @@
Creating sparse matrix.
Converting from sparse to dense.
Converting back to dense again.
Testing for equality of two sparse matrices: OK.
Converting to dense once again.
Testing for equality of two dense matrices: OK.
DONE WITH TESTS.

View File

@ -1,80 +0,0 @@
/* MOD2CONVERT-TEST. C - Program to test mod2convert module. */
/* 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.
*/
/* Correct output for this program is saved in the file mod2convert-test-out */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mod2dense.h"
#include "mod2sparse.h"
#include "mod2convert.h"
#include "rand.h"
#define Rows 40 /* Dimensions of matrix to use in test */
#define Cols 13
#define N 100 /* Number of bits to set in test matrix (some may be
duplicates, leading to fewer 1's in matrix */
main(void)
{
mod2sparse *sm1, *sm2;
mod2dense *dm1, *dm2;
int i;
sm1 = mod2sparse_allocate(Rows,Cols);
sm2 = mod2sparse_allocate(Rows,Cols);
dm1 = mod2dense_allocate(Rows,Cols);
dm2 = mod2dense_allocate(Rows,Cols);
printf("\nCreating sparse matrix.\n");
fflush(stdout);
for (i = 0; i<N; i++)
{ mod2sparse_insert(sm1,rand_int(Rows),rand_int(Cols));
}
printf("Converting from sparse to dense.\n");
fflush(stdout);
mod2sparse_to_dense(sm1,dm1);
printf("Converting back to dense again.\n");
fflush(stdout);
mod2dense_to_sparse(dm1,sm2);
printf("Testing for equality of two sparse matrices: %s.\n",
mod2sparse_equal(sm1,sm2) ? "OK" : "NOT OK");
fflush(stdout);
printf("Converting to dense once again.\n");
fflush(stdout);
mod2sparse_to_dense(sm2,dm2);
printf("Testing for equality of two dense matrices: %s.\n",
mod2dense_equal(dm1,dm2) ? "OK" : "NOT OK");
fflush(stdout);
printf("\nDONE WITH TESTS.\n");
exit(0);
}

View File

@ -1,83 +0,0 @@
/* MOD2CONVERT.C - Routines converting between sparse and 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 mod2convert.html for documentation on these procedures. */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mod2dense.h"
#include "mod2sparse.h"
#include "mod2convert.h"
/* CONVERT A MOD2 MATRIX FROM SPARSE TO DENSE FORM. */
void mod2sparse_to_dense
( mod2sparse *m, /* Sparse matrix to convert */
mod2dense *r /* Place to store result */
)
{
mod2entry *e;
int i;
if (mod2sparse_rows(m)>mod2dense_rows(r)
|| mod2sparse_cols(m)>mod2dense_cols(r))
{ fprintf(stderr,
"mod2sparse_to_dense: Dimension of result matrix is less than source\n");
exit(1);
}
mod2dense_clear(r);
for (i = 0; i<mod2sparse_rows(m); i++)
{ e = mod2sparse_first_in_row(m,i);
while (!mod2sparse_at_end(e))
{ mod2dense_set(r,i,mod2sparse_col(e),1);
e = mod2sparse_next_in_row(e);
}
}
}
/* CONVERT A MOD2 MATRIX FROM DENSE TO SPARSE FORM. */
void mod2dense_to_sparse
( mod2dense *m, /* Dense matrix to convert */
mod2sparse *r /* Place to store result */
)
{
int i, j;
if (mod2dense_rows(m)>mod2sparse_rows(r)
|| mod2dense_cols(m)>mod2sparse_cols(r))
{ fprintf(stderr,
"mod2dense_to_sparse: Dimension of result matrix is less than source\n");
exit(1);
}
mod2sparse_clear(r);
for (i = 0; i<mod2dense_rows(m); i++)
{ for (j = 0; j<mod2dense_cols(m); j++)
{ if (mod2dense_get(m,i,j))
{ mod2sparse_insert(r,i,j);
}
}
}
}

View File

@ -1,18 +0,0 @@
/* MOD2CONVERT.H - Routines converting between sparse and 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.
*/
void mod2sparse_to_dense (mod2sparse *, mod2dense *);
void mod2dense_to_sparse (mod2dense *, mod2sparse *);

View File

@ -1,51 +0,0 @@
<HTML><HEAD>
<TITLE> Modulo-2 Matrix Sparse/Dense Conversion </TITLE>
</HEAD><BODY>
<H1> Modulo-2 Matrix Sparse/Dense Conversion </H1>
<P>The routines below convert modulo-2 matrices between the form used by
the <A HREF="mod2dense.html">routines for dense modulo-2 matrices</A>
and the form used by the <A HREF="mod2dense.html">routines for sparse
modulo-2 matrices</A>.
<P><B>Header files required</B>:
<TT>mod2sparse.h mod2dense.h mod2convert.h</TT>
<P><A NAME="sparse_to_dense"><HR><B>mod2sparse_to_dense</B>:
Convert a modulo-2 matrix from sparse to dense form.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_to_dense
( mod2sparse *m, /* Sparse matrix to convert */
mod2dense *r /* Place to store result */
)
</PRE></BLOCKQUOTE>
The dense matrix, r, must already have been allocated, and must have at
least as many rows and columns as m, the sparse matrix to be converted.
<P><A NAME="dense_to_sparse"><HR><B>mod2dense_to_sparse</B>:
Convert a modulo-2 matrix from dense to sparse form.</A>
<BLOCKQUOTE><PRE>
void mod2dense_to_sparse
( mod2dense *m, /* Dense matrix to convert */
mod2sparse *r /* Place to store result */
)
</PRE></BLOCKQUOTE>
The sparse matrix, r, must already have been allocated, and must have at
least as many rows and columns as m, the dense matrix to be converted.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,699 +0,0 @@
PART 1:
Matrix m1:
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
Matrix m2, as read from file. Should be same as m1 above.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
Test of equality of m1 & m2 (should be 1): 1
Matrix m3, copied from m1 above.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
Test of equality of m1 & m3 (should be 1): 1
Matrix m3 again, should now be all zeros.
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Test of equality of m1 & m3 (should be 0): 0
PART 2:
Transpose of m1.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
PART 3:
Matrix s0.
0 0 0 0 0 0 0
0 0 0 1 1 0 0
1 0 0 0 0 0 0
0 1 0 0 0 0 0
0 0 0 0 0 0 0
Matrix s1.
0 0 0 0 0 0 0
0 0 0 1 0 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 1
0 0 0 0 0 0 0
Matrix s2.
1 0 0 0
0 1 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 1 1 1
0 0 0 0
Sum of s0 and s1.
0 0 0 0 0 0 0
0 0 0 0 1 1 0
1 0 0 0 0 0 0
1 0 0 0 0 0 1
0 0 0 0 0 0 0
Product of s1 and s2.
0 0 0 0
0 1 1 1
0 0 0 0
1 1 0 0
0 0 0 0
Above matrix with (1,2) cleared.
0 0 0 0
0 1 0 1
0 0 0 0
1 1 0 0
0 0 0 0
PART 4:
Matrix s1.
0 0 0 1 0
0 1 0 0 1
1 0 0 0 0
0 1 1 0 0
1 0 1 0 0
Matrix s3, the inverse of s1 (return code 1).
0 0 1 0 0
0 0 1 1 1
0 0 1 0 1
1 0 0 0 0
0 1 1 1 1
Original matrix times inverse (should be identity).
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Inverse times original matrix (should be identity).
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
Inverse of inverse (should be same as original s1).
0 0 0 1 0
0 1 0 0 1
1 0 0 0 0
0 1 1 0 0
1 0 1 0 0
Test of equality with original (should be 1): 1
Matrix s1.
0 0 0 0 1 0 0
0 1 0 0 0 0 1
1 0 0 0 0 0 0
0 1 1 0 0 0 0
1 0 1 0 0 0 0
Matrix s3, from invert_selected applied to s1 (return code 0).
0 0 0 0 1 0 0
1 0 1 0 0 0 1
1 0 0 0 0 0 0
1 0 0 0 0 0 1
1 1 1 0 0 0 1
row ordering returned: 0 1 2 3 4
column ordering returned: 4 1 0 2 6 5 3
Columns extracted in order from original matrix.
1 0 0 0 0
0 1 0 0 1
0 0 1 0 0
0 1 0 1 0
0 0 1 1 0
Inverse of above calculated using mod2dense_inverse (return code 1)
1 0 0 0 0
0 0 1 1 1
0 0 1 0 0
0 0 1 0 1
0 1 1 1 1
Columns extracted in order from s3 (should also be inverse of above).
1 0 0 0 0
0 0 1 1 1
0 0 1 0 0
0 0 1 0 1
0 1 1 1 1
Matrix s1.
1 1 0 0 0 0 0
0 1 1 0 0 0 0
1 0 1 0 0 0 0
0 0 0 1 1 0 0
0 0 0 0 0 0 0
Matrix s3, from invert_selected applied to s1 (return code 2).
1 1 0 0 0 0 0
0 1 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0
row ordering returned: 0 1 3 4 2
column ordering returned: 0 1 3 2 4 5 6
Matrix s4, from copying rows in order from s3.
1 1 0 0 0 0 0
0 1 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
PART 5:
Matrix s1.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1
Matrix s3, the inverse of s1 (return code 1).
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 1 1 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 1
0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0
0 0 0 1 0 0 0 0 0 0 1 0 1 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 0 0 1 0 0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0
0 0 0 0 1 0 0 0 1 0 0 1 1 0 0 0 0 1 1 0 1 0 0 1 0 0 0 0 0 0 1 0 0 1 1
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
Original matrix times inverse (should be identity).
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
Inverse times original matrix (should be identity).
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
Inverse of inverse (should be same as original s1).
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1
Test of equality with original (should be 1): 1
PART 6:
Matrix s1.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Result of forcibly inverting s1 (needed to alter 7 elements).
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Altered elements at these indexes:
3 3
7 7
15 15
21 21
23 23
29 29
32 12
Inverse of inverse of altered matrix.
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
DONE WITH TESTS.

View File

@ -1,560 +0,0 @@
/* MOD2DENSE-TEST. C - Program to test mod2dense module. */
/* 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.
*/
/* Correct output for this program is saved in the file mod2dense-test-out */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mod2dense.h"
main(void)
{
mod2dense *m1, *m2, *m3, *m4;
mod2dense *s0, *s1, *s2, *s3, *s4, *s5;
int a_row[35], a_col[35];
int code;
int i, j;
FILE *f;
printf("\nPART 1:\n\n");
/* Set up m1 with bits on a diagonal plus a few more set to 1. */
m1 = mod2dense_allocate(35,40);
mod2dense_clear(m1);
for (i = 0; i<35; i++) mod2dense_set(m1,i,i,1);
mod2dense_set(m1,2,3,1);
mod2dense_set(m1,34,4,1);
mod2dense_set(m1,10,38,1);
/* Print m1. */
printf("Matrix m1:\n\n");
mod2dense_print(stdout,m1);
printf("\n"); fflush(stdout);
/* Store m1 in a file. */
f = fopen("test-file","wb");
if (f==0)
{ fprintf(stderr,"Can't create test-file\n");
exit(1);
}
if (!mod2dense_write(f,m1))
{ printf("Error from mod2dense_write\n");
}
fclose(f);
/* Read matrix written above back into m2. */
f = fopen("test-file","rb");
if (f==0)
{ fprintf(stderr,"Can't open test-file\n");
exit(1);
}
m2 = mod2dense_read(f);
if (m2==0)
{ printf("Error from mod2dense_read\n");
exit(1);
}
/* Print m2, along with result of equality test. */
printf("Matrix m2, as read from file. Should be same as m1 above.\n\n");
mod2dense_print(stdout,m2);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m2 (should be 1): %d\n\n",
mod2dense_equal(m1,m2));
/* Copy m1 to m3. */
m3 = mod2dense_allocate(mod2dense_rows(m1),mod2dense_cols(m1));
mod2dense_copy(m1,m3);
/* Print m3, along with result of equality test. */
printf("Matrix m3, copied from m1 above.\n\n");
mod2dense_print(stdout,m3);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m3 (should be 1): %d\n\n",
mod2dense_equal(m1,m3));
/* Clear m3. */
mod2dense_clear(m3);
/* Print m3 again. */
printf("Matrix m3 again, should now be all zeros.\n\n");
mod2dense_print(stdout,m3);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m3 (should be 0): %d\n\n",
mod2dense_equal(m1,m3));
printf("\nPART 2:\n\n");
/* Compute transpose of m1. */
m4 = mod2dense_allocate(mod2dense_cols(m1),mod2dense_rows(m1));
mod2dense_transpose(m1,m4);
/* Print transpose. */
printf("Transpose of m1.\n\n");
mod2dense_print(stdout,m4);
printf("\n"); fflush(stdout);
/* Free space for m1, m2, and m3. */
mod2dense_free(m1);
mod2dense_free(m2);
mod2dense_free(m3);
printf("\nPART 3:\n\n");
/* Allocate some small matrices. */
s0 = mod2dense_allocate(5,7);
s1 = mod2dense_allocate(5,7);
s2 = mod2dense_allocate(7,4);
s3 = mod2dense_allocate(5,4);
s4 = mod2dense_allocate(5,7);
/* Set up the contents of s0, s1, and s2. */
mod2dense_clear(s0);
mod2dense_clear(s1);
mod2dense_clear(s2);
mod2dense_set(s0,1,3,1);
mod2dense_set(s0,1,4,1);
mod2dense_set(s0,2,0,1);
mod2dense_set(s0,3,1,1);
mod2dense_set(s1,1,3,1);
mod2dense_set(s1,1,5,1);
mod2dense_set(s1,3,0,1);
mod2dense_set(s1,3,1,1);
mod2dense_set(s1,3,6,1);
mod2dense_set(s2,5,1,1);
mod2dense_set(s2,5,2,1);
mod2dense_set(s2,5,3,1);
mod2dense_set(s2,0,0,1);
mod2dense_set(s2,1,1,1);
/* Print s0, s1, and s2. */
printf("Matrix s0.\n\n");
mod2dense_print(stdout,s0);
printf("\nMatrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\nMatrix s2.\n\n");
mod2dense_print(stdout,s2);
printf("\n"); fflush(stdout);
/* Add s0 and s1, storing the result in s4, then print s4. */
mod2dense_add(s0,s1,s4);
printf("Sum of s0 and s1.\n\n");
mod2dense_print(stdout,s4);
printf("\n"); fflush(stdout);
/* Multiply s1 and s2, storing the product in s3, and then print s3. */
mod2dense_multiply(s1,s2,s3);
printf("Product of s1 and s2.\n\n");
mod2dense_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Try clearing a bit in s3, then printing the result. */
mod2dense_set(s3,1,2,0);
printf("Above matrix with (1,2) cleared.\n\n");
mod2dense_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Free space for s0, s1, s2, s3, and s4. */
mod2dense_free(s0);
mod2dense_free(s1);
mod2dense_free(s2);
mod2dense_free(s3);
mod2dense_free(s4);
printf("\nPART 4:\n\n");
/* Set up a small square matrix, s1. Also copy it to s2. */
s1 = mod2dense_allocate(5,5);
s2 = mod2dense_allocate(5,5);
mod2dense_clear(s1);
mod2dense_set(s1,0,3,1);
mod2dense_set(s1,1,4,1);
mod2dense_set(s1,1,1,1);
mod2dense_set(s1,2,0,1);
mod2dense_set(s1,3,1,1);
mod2dense_set(s1,3,2,1);
mod2dense_set(s1,4,2,1);
mod2dense_set(s1,4,0,1);
mod2dense_copy(s1,s2);
/* Print s1. */
printf("Matrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute inverse of s1, storing it in s3. */
s3 = mod2dense_allocate(5,5);
code = mod2dense_invert(s1,s3);
/* Print inverse (s3). */
printf("Matrix s3, the inverse of s1 (return code %d).\n\n",code);
mod2dense_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Compute and print product of inverse and original matrix, both ways. */
mod2dense_multiply(s2,s3,s1);
printf("Original matrix times inverse (should be identity).\n\n");
mod2dense_print(stdout,s1);
mod2dense_multiply(s3,s2,s1);
printf("\nInverse times original matrix (should be identity).\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute and print inverse of inverse, and do equality check. */
mod2dense_invert(s3,s1);
printf("Inverse of inverse (should be same as original s1).\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
printf("Test of equality with original (should be 1): %d\n\n",
mod2dense_equal(s1,s2));
/* Free s1, s2, and s3. */
mod2dense_free(s1);
mod2dense_free(s2);
mod2dense_free(s3);
/* Set up a rectangular matrix like s1 above, but with two zero columns.
Copy to s4 as well. */
s1 = mod2dense_allocate(5,7);
mod2dense_clear(s1);
mod2dense_set(s1,0,4,1);
mod2dense_set(s1,1,6,1);
mod2dense_set(s1,1,1,1);
mod2dense_set(s1,2,0,1);
mod2dense_set(s1,3,1,1);
mod2dense_set(s1,3,2,1);
mod2dense_set(s1,4,2,1);
mod2dense_set(s1,4,0,1);
s4 = mod2dense_allocate(5,7);
mod2dense_copy(s1,s4);
/* Print s1. */
printf("Matrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute inverse of sub-matrix of s1, storing it in s3. Print results. */
s3 = mod2dense_allocate(5,7);
code = mod2dense_invert_selected(s1,s3,a_row,a_col);
printf("Matrix s3, from invert_selected applied to s1 (return code %d).\n\n",
code);
mod2dense_print(stdout,s3);
printf("\n row ordering returned:");
for (i = 0; i<5; i++) printf(" %d",a_row[i]);
printf("\n");
printf("\n column ordering returned:");
for (j = 0; j<7; j++) printf(" %d",a_col[j]);
printf("\n");
printf("\n"); fflush(stdout);
printf("Columns extracted in order from original matrix.\n\n");
s2 = mod2dense_allocate(5,5);
mod2dense_copycols(s4,s2,a_col);
mod2dense_print(stdout,s2);
printf("\n"); fflush(stdout);
s5 = mod2dense_allocate(5,5);
code = mod2dense_invert(s2,s5);
printf(
"Inverse of above calculated using mod2dense_inverse (return code %d)\n\n",
code);
mod2dense_print(stdout,s5);
printf("\n"); fflush(stdout);
printf(
"Columns extracted in order from s3 (should also be inverse of above).\n\n");
mod2dense_copycols(s3,s2,a_col);
mod2dense_print(stdout,s2);
printf("\n"); fflush(stdout);
/* Try out mod2dense_invert_selected again. */
mod2dense_clear(s1);
mod2dense_set(s1,0,0,1);
mod2dense_set(s1,0,1,1);
mod2dense_set(s1,1,1,1);
mod2dense_set(s1,1,2,1);
mod2dense_set(s1,2,0,1);
mod2dense_set(s1,2,2,1);
mod2dense_set(s1,3,3,1);
mod2dense_set(s1,3,4,1);
printf("Matrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
code = mod2dense_invert_selected(s1,s3,a_row,a_col);
printf("Matrix s3, from invert_selected applied to s1 (return code %d).\n\n",
code);
mod2dense_print(stdout,s3);
printf("\n row ordering returned:");
for (i = 0; i<5; i++) printf(" %d",a_row[i]);
printf("\n");
printf("\n column ordering returned:");
for (j = 0; j<7; j++) printf(" %d",a_col[j]);
printf("\n");
printf("\n"); fflush(stdout);
printf("Matrix s4, from copying rows in order from s3.\n\n");
mod2dense_copyrows(s3,s4,a_row);
mod2dense_print(stdout,s4);
free(s1);
free(s2);
free(s3);
free(s4);
free(s5);
printf("\nPART 5:\n\n");
/* Set up a larger square matrix, s1. Also copy it to s2. */
s1 = mod2dense_allocate(35,35);
s2 = mod2dense_allocate(35,35);
mod2dense_clear(s1);
for (i = 0; i<35; i++) mod2dense_set(s1,i,i,1);
mod2dense_set(s1,10,3,1);
mod2dense_set(s1,11,4,1);
mod2dense_set(s1,11,11,1);
mod2dense_set(s1,12,20,1);
mod2dense_set(s1,13,31,1);
mod2dense_set(s1,23,12,1);
mod2dense_set(s1,24,12,1);
mod2dense_set(s1,14,10,1);
mod2dense_set(s1,2,20,1);
mod2dense_set(s1,3,31,1);
mod2dense_set(s1,3,12,1);
mod2dense_set(s1,24,2,1);
mod2dense_set(s1,24,0,1);
mod2dense_set(s1,5,3,1);
mod2dense_set(s1,18,3,1);
mod2dense_set(s1,17,11,1);
mod2dense_set(s1,32,23,1);
mod2dense_set(s1,9,24,1);
mod2dense_set(s1,19,11,1);
mod2dense_set(s1,11,30,1);
mod2dense_set(s1,21,27,1);
mod2dense_set(s1,21,22,1);
mod2dense_set(s1,23,33,1);
mod2dense_set(s1,24,23,1);
mod2dense_set(s1,24,25,1);
mod2dense_set(s1,30,34,1);
mod2dense_set(s1,31,10,1);
mod2dense_set(s1,33,17,1);
mod2dense_set(s1,33,18,1);
mod2dense_set(s1,34,8,1);
mod2dense_set(s1,34,11,1);
mod2dense_set(s1,34,3,1);
mod2dense_set(s1,34,24,1);
mod2dense_set(s1,25,34,1);
mod2dense_set(s1,13,34,1);
mod2dense_set(s1,3,3,0);
mod2dense_set(s1,11,11,0);
mod2dense_set(s1,23,23,0);
mod2dense_set(s1,24,24,0);
mod2dense_copy(s1,s2);
/* Print s1. */
printf("Matrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute inverse of s1, storing it in s3. */
s3 = mod2dense_allocate(35,35);
code = mod2dense_invert(s1,s3);
/* Print inverse (s3). */
printf("Matrix s3, the inverse of s1 (return code %d).\n\n",code);
mod2dense_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Compute and print product of inverse and original matrix, both ways. */
mod2dense_multiply(s2,s3,s1);
printf("Original matrix times inverse (should be identity).\n\n");
mod2dense_print(stdout,s1);
mod2dense_multiply(s3,s2,s1);
printf("\nInverse times original matrix (should be identity).\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute and print inverse of inverse, and do equality check. */
mod2dense_invert(s3,s1);
printf("Inverse of inverse (should be same as original s1).\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
printf("Test of equality with original (should be 1): %d\n\n",
mod2dense_equal(s1,s2));
/* Free s1, s2, and s3. */
mod2dense_free(s1);
mod2dense_free(s2);
mod2dense_free(s3);
printf("\nPART 6:\n\n");
/* Set up a largish square matrix, s1. Also copy it to s2. */
s1 = mod2dense_allocate(35,35);
s2 = mod2dense_allocate(35,35);
mod2dense_clear(s1);
for (i = 0; i<10; i++)
{ if (i!=3 && i!=7)
{ mod2dense_set(s1,i,i,1);
}
}
for (i = 10; i<35; i++)
{ if (i!=15 && i!=21 && i!=32)
{ mod2dense_set(s1,i,34-(i-10),1);
}
}
/* Print s1. */
printf("Matrix s1.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Forcibly invert s1, storing inverse in s3. */
s3 = mod2dense_allocate(35,35);
code = mod2dense_forcibly_invert(s1,s3,a_row,a_col);
/* Print inverse, and list of altered elements. */
printf("Result of forcibly inverting s1 (needed to alter %d elements).\n\n",
code);
mod2dense_print(stdout,s3);
printf("\n"); fflush(stdout);
printf("Altered elements at these indexes:\n\n");
for (i = 0; i<code; i++)
{ printf("%3d %3d\n",a_row[i],a_col[i]);
}
printf("\n"); fflush(stdout);
/* Compute and print inverse of inverse. */
mod2dense_invert(s3,s1);
printf("Inverse of inverse of altered matrix.\n\n");
mod2dense_print(stdout,s1);
printf("\n"); fflush(stdout);
printf("\nDONE WITH TESTS.\n");
exit(0);
}

View File

@ -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;
}

View File

@ -1,113 +0,0 @@
/* MOD2DENSE.H - Interface to module 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.
*/
/* This module implements operations on matrices of mod2 elements (bits,
with addition and multiplication being done modulo 2). The matrices
are stored with consecutive bits of a column packed into words, and
the procedures are implemented where possible using bit operations
on these words. This is an appropriate representation when the matrices
are dense (ie, 0s and 1s are about equally frequent).
All procedures in this module display an error message on standard
error and terminate the program if passed an invalid argument (indicative
of a programming error), or if memory cannot be allocated. Errors from
invalid contents of a file result in an error code being returned to the
caller, with no message being printed by this module.
*/
#include <stdint.h> /* Has the definition of uint32_t used below */
/* PACKING OF BITS INTO WORDS. Bits are packed into 32-bit words, with
the low-order bit coming first. */
typedef uint32_t mod2word; /* Data type that holds packed bits. If uint32_t
doesn't exist, change it to unsigned long */
#define mod2_wordsize 32 /* Number of bits that fit in a mod2word. Can't
be increased without changing intio module */
#define mod2_wordsize_shift 5 /* Amount to shift by to divide by wordsize */
#define mod2_wordsize_mask 0x1f /* What to AND with to produce mod wordsize */
/* Extract the i'th bit of a mod2word. */
#define mod2_getbit(w,i) (((w)>>(i))&1)
/* Make a word like w, but with the i'th bit set to 1 (if it wasn't already). */
#define mod2_setbit1(w,i) ((w)|(1<<(i)))
/* Make a word like w, but with the i'th bit set to 0 (if it wasn't already). */
#define mod2_setbit0(w,i) ((w)&(~(1<<(i))))
/* STRUCTURE REPRESENTING A DENSE MATRIX. These structures are dynamically
allocated using mod2dense_allocate (or by other procedures that call
mod2dense_allocate). They should be freed with mod2dense_free when no
longer required.
Direct access to this structure should be avoided except in low-level
routines. Use the macros and procedures defined below instead. */
typedef struct
{
int n_rows; /* Number of rows in the matrix */
int n_cols; /* Number of columns in the matrix */
int n_words; /* Number of words used to store a column of bits */
mod2word **col; /* Pointer to array of pointers to columns */
mod2word *bits; /* Pointer to storage block for bits in this matrix
(pieces of this block are pointed to from col) */
} mod2dense;
/* MACROS. */
#define mod2dense_rows(m) ((m)->n_rows) /* Get the number of rows or columns */
#define mod2dense_cols(m) ((m)->n_cols) /* in a matrix */
/* PROCEDURES. */
mod2dense *mod2dense_allocate (int, int);
void mod2dense_free (mod2dense *);
void mod2dense_clear (mod2dense *);
void mod2dense_copy (mod2dense *, mod2dense *);
void mod2dense_copyrows (mod2dense*, mod2dense *, int *);
void mod2dense_copycols (mod2dense*, mod2dense *, int *);
void mod2dense_print (FILE *, mod2dense *);
int mod2dense_write (FILE *, mod2dense *);
mod2dense *mod2dense_read (FILE *);
int mod2dense_get (mod2dense *, int, int);
void mod2dense_set (mod2dense *, int, int, int);
int mod2dense_flip(mod2dense *, int, int);
void mod2dense_transpose (mod2dense *, mod2dense *);
void mod2dense_add (mod2dense *, mod2dense *, mod2dense *);
void mod2dense_multiply (mod2dense *, mod2dense *, mod2dense *);
int mod2dense_equal (mod2dense *, mod2dense *);
int mod2dense_invert (mod2dense *, mod2dense *);
int mod2dense_forcibly_invert (mod2dense *, mod2dense *, int *, int *);
int mod2dense_invert_selected (mod2dense *, mod2dense *, int *, int *);

View File

@ -1,487 +0,0 @@
<HTML><HEAD>
<TITLE> Dense Modulo-2 Matrix Routines </TITLE>
</HEAD><BODY>
<H1> Dense Modulo-2 Matrix Routines </H1>
<P>This module implements operations on matrices in which the elements
are all 0 or 1, with addition and multiplication being done modulo 2.
The matrices are stored with consecutive bits of a column packed into
32-bit words, and the procedures are implemented where possible using
bit operations on these words.
<P>This is an appropriate representation when the matrices are dense
(ie, 0s and 1s are about equally frequent). Matrices in which most
elements are 0s may be better handled with the <A
HREF="mod2sparse.html">sparse modulo-2 matrix routines</A>. Matrices
can be converted between these two formats using the <A
HREF="mod2convert.html">module-2 matrix conversion routines</A>.
<P>All procedures in this module display an error message on standard
error and terminate the program if passed an invalid argument
(indicative of a programming error), or if memory cannot be allocated.
Errors from invalid contents of a file result in an error code being
returned to the caller, with no message being printed by this module.
<H2>Representation of dense matrices</H2>
<P>This module represents a matrix by a pointer to a structure of type
<TT>mod2dense</TT>. This structure records the number of rows and
columns in the matrix, and contains an array of pointers to where the
bits making up each column are stored. These bits are packed 32 per
word. When possible, bits in a column are manipulated 32 bits at a
time, which operations such as adding one column to another much
faster than the corresponding operations on rows. The pointer
structure also allows the columns of a matrix to easily be rearranged,
which may be necessary when doing matrix inversion.
<P><B>Header files required</B>:
<TT>mod2dense.h</TT>
<A NAME="dimension-sec">
<P><HR>
<CENTER><BIG>Dimension Macros</BIG></CENTER>
</A>
<HR>The following macros take a pointer to a mod2dense structure as their
argument, and return the number of rows or the number of columns in
the matrix pointed to, which will have been fixed when the matrix was
created with <A HREF="#allocate">mod2dense_allocate</A>:
<BLOCKQUOTE><PRE>
mod2dense_rows(m) /* Returns the number of rows in m */
mod2dense_cols(m) /* Returns the number of columns in m */
</PRE></BLOCKQUOTE>
<A NAME="alloc-sec">
<P><HR>
<CENTER><BIG>Allocating and Freeing Dense Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="allocate"><HR><B>mod2dense_allocate</B>:
Allocate space for a dense module-2 matrix.</A>
<BLOCKQUOTE><PRE>
mod2dense *mod2dense_allocate
( int n_rows, /* Number of rows in matrix */
int n_cols /* Number of columns in matrix */
)
</PRE></BLOCKQUOTE>
Allocates space for a matrix with the given number of rows and
columns, and returns a pointer to it. If there is not enough memory
available, a message is displayed on standard error and the program is
terminated. The matrix should be freed with <A
HREF="#free"><TT>mod2dense_free</TT></A> once it is no longer in use.
<P><A NAME="free"><HR><B>mod2dense_free</B>:
Free the space occupied by a dense module-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2dense_free
( mod2dense *m /* Pointer to matrix to free */
)
</PRE></BLOCKQUOTE>
Frees the space occupied by the matrix for re-use. The pointer passed
should no longer be used.
<A NAME="copy-clear-sec">
<P><HR>
<CENTER><BIG>Copying and Clearing Dense Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="clear"><HR><B>mod2dense_clear</B>:
Set all elements of a matrix to zero.</A>
<BLOCKQUOTE><PRE>
void mod2dense_clear
( mod2dense *m /* Pointer to matrix to clear */
)
</PRE></BLOCKQUOTE>
Sets all of the elements of the matrix passed to 0.
<P><A NAME="copy"><HR><B>mod2dense_copy</B>:
Copy the contents of one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2dense_copy
( mod2dense *m /* Pointer to matrix to copy from */
mod2dense *r /* Pointer to matrix to receive data */
)
</PRE></BLOCKQUOTE>
Copies the contents of the first matrix passed, <B>m</B>, to the
second matrix passed, <B>r</B>, which must already have been
allocated, and must have at least as many rows and columns as the
first. If <B>r</B> is larger than <B>m</B>, its elements that have
row or column indexes greater than the dimension of <B>m</B> are set
to zeros.
<P><A NAME="copyrows"><HR><B>mod2dense_copyrows</B>:
Copy selected rows from one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2dense_copyrows
( mod2dense *m, /* Pointer to matrix to copy columns from */
mod2dense *r, /* Pointer to matrix in which to store data */
int *rows /* Indexes of rows, numbered from 0 */
)
</PRE></BLOCKQUOTE>
Copies selected rows of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many columns as <B>m</B>. The indexes of the
rows to copy are given in order as an array of length the same as
the number of rows in <B>r</B>; duplicates are allowed. Row
indexes start at 0. These rows are copied to <B>r</B>, with the
row indexed by the first entry in <B>rows</B> going to the first
row of <B>r</B>, and so forth. If <B>r</B> has more columns than
<B>m</B>, the extra entries in each row are set to zeros.
<P><A NAME="copycols"><HR><B>mod2dense_copycols</B>:
Copy selected columns from one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2dense_copycols
( mod2dense *m, /* Pointer to matrix to copy columns from */
mod2dense *r, /* Pointer to matrix in which to store data */
int *cols /* Indexes of columns, numbered from 0 */
)
</PRE></BLOCKQUOTE>
Copies selected columns of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many rows as <B>m</B>. The indexes of the
columns to copy are given in order as an array of length the same as
the number of columns in <B>r</B>; duplicates are allowed. Column
indexes start at 0. These columns are copied to <B>r</B>, with the
column indexed by the first entry in <B>cols</B> going to the first
column of <B>r</B>, and so forth. If <B>r</B> has more rows than
<B>m</B>, the extra entries in each column are set to zeros.
<A NAME="input-output-sec">
<P><HR>
<CENTER><BIG>Input and Output of Dense Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="print"><HR><B>mod2dense_print</B>:
Print a dense modulo-2 matrix in human-readable form.</A>
<BLOCKQUOTE><PRE>
void mod2dense_print
( FILE *f, /* File to print to */
mod2dense *m /* Pointer to matrix to print */
)
</PRE></BLOCKQUOTE>
The matrix is printed on standard output as "0" and "1" characters,
each preceded by a space, with one line of "0"s and "1"s for each row
of the matrix.
<P><A NAME="write"><HR><B>mod2dense_write</B>:
Write a dense modulo-2 matrix to a file in machine-readable format.</A>
<BLOCKQUOTE><PRE>
int mod2dense_write
( FILE *f, /* File to write data to */
mod2dense *m /* Pointer to matrix write out */
)
</PRE></BLOCKQUOTE>
Writes a machine-readable representation the dense matrix <B>m</B> to
the file <B>f</B>. The file should have been opened in binary mode
(with a "b" in the mode passed to fopen). The contents written will
not be text, and will not be human-readable. Other binary data may
precede or follow the data for the matrix written.
<P>The data written to the file consists of the number of rows and the
number of columns, followed by the bits in each column, packed into
32-bit words. The data should be readable by <A
HREF="#read"><TT>mod2dense_read</TT></A> even on a machine with a
different byte-ordering.
<P>The value returned by <TT>mod2dense_write</TT> is one if the
operation was successful, zero if an error of some sort occurred.
<P><A NAME="read"><HR><B>mod2dense_read</B>:
Read a dense modulo-2 matrix from a file.</A>
<BLOCKQUOTE><PRE>
mod2dense *mod2dense_read
( FILE *f, /* File to read data from */
)
</PRE></BLOCKQUOTE>
Reads a dense modulo-2 matrix from the file <B>f</B>. This file
should have been opened in binary mode (with a "b" in the mode passed
to fopen). The contents of the file at the point when
<TT>mod2dense_read</TT> is called should have been written by <A
HREF="#write"><TT>mod2dense_write</TT></A>. Other binary data may
precede or follow this data.
<P>The value returned is a pointer to the matrix read, for which space
will have been allocated by <TT>mod2dense_read</TT>, or zero if an
error occurred (either an error reading the file, or data not in the
right format).
<A NAME="elementary-sec">
<P><HR>
<CENTER><BIG>Elementary Operations on Dense Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="get"><HR><B>mod2dense_get</B>:
Get an element of a dense modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
int mod2dense_get
( mod2dense *m, /* Pointer to matrix to get element from */
int row, /* Row of element (indexed from zero) */
int col /* Column of element (indexed from zero) */
)
</PRE></BLOCKQUOTE>
Returns the value (0 or 1) of the element in the given row and column
of the matrix <B>m</B>.
<P><A NAME="set"><HR><B>mod2dense_set</B>:
Set an element of a dense modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2dense_set
( mod2dense *m, /* Pointer to matrix to get element from */
int row, /* Row of element (indexed from zero) */
int col, /* Column of element (indexed from zero) */
int value /* New value of element (0 or 1) */
)
</PRE></BLOCKQUOTE>
Set the element in the given row and column of the matrix <B>m</B> to
the specified value.
<P><A NAME="flip"><HR><B>mod2dense_flip</B>:
Flip an element of a dense modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
int mod2dense_flip
( mod2dense *m, /* Pointer to matrix to get element from */
int row, /* Row of element (indexed from zero) */
int col /* Column of element (indexed from zero) */
)
</PRE></BLOCKQUOTE>
Flips the value of the element in the given row and column of the
matrix <B>m</B>, changing it to 0 if it was 1, and to 1 if it was 0.
Returns the new value of this element.
<A NAME="arith-sec">
<P><HR>
<CENTER><BIG>Dense Modulo-2 Matrix Arithmetic and Comparison</BIG></CENTER>
</A>
<A NAME="transpose"><HR><B>mod2dense_transpose</B>:
Compute the transpose of a dense modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2dense_transpose
( mod2dense *m, /* Matrix to compute transpose of */
mod2dense *r /* Result of transpose operation */
)
</PRE></BLOCKQUOTE>
Stores the transpose of its first argument, <B>m</B>, in the matrix
pointed to by its second argument, <B>r</B>, which must already have
been allocated, and which must have as many rows as <B>m</B> has
columns, and as many columns as <B>m</B> has rows. The two matrices
<B>m</B> and <B>r</B> must not be the same (ie, the two pointers
passed must be different).
<P><A NAME="add"><HR><B>mod2dense_add</B>:
Add two dense modulo-2 matrices.</A>
<BLOCKQUOTE><PRE>
void mod2dense_add
( mod2dense *m1, /* Left operand of add */
mod2dense *m2, /* Right operand of add */
mod2dense *r /* Place to store result of add */
)
</PRE></BLOCKQUOTE>
Adds matrices <B>m1</B> and <B>m2</B>, storing the result in the
matrix pointed to by <B>r</B>. All three matrices must have the same
numbers of rows and columns. It is permissible for <B>r</B> to be the
same as <B>m1</B> and/or <B>m2</B>. Neither of the first two matrices is
changed by this procedure (unless they are the same as <B>r</B>).
<P><A NAME="multiply"><HR><B>mod2dense_multiply</B>:
Multiply two dense modulo-2 matrices.</A>
<BLOCKQUOTE><PRE>
void mod2dense_multiply
( mod2dense *m1, /* Left operand of multiply */
mod2dense *m2, /* Right operand of multiply */
mod2dense *r /* Place to store result of multiply */
)
</PRE></BLOCKQUOTE>
Does a matrix multiplication of <B>m1</B> by <B>m2</B>, and stores the
result in the matrix pointed to by <B>r</B>. The matrices must have
compatible numbers of rows and columns. Neither of the first two
matrices is changed by this procedure. The result matrix, <B>r</B>,
must not be the same as either <B>m1</B> or <B>m2</B>.
<P>The algorithm used runs faster if <B>m2</B> contains mostly 0s, but
it is also appropriate for matrices with many 1s.
<P><A NAME="equal"><HR><B>mod2dense_equal</B>:
Check whether two dense modulo-2 matrices are equal.</A>
<BLOCKQUOTE><PRE>
int mod2dense_equal
( mod2dense *m1, /* Pointers to the two matrices */
mod2dense *m2 /* to compare */
)
</PRE></BLOCKQUOTE>
Returns one if every element of <B>m1</B> is equal to the
corresponding element of <B>m2</B>, and otherwise returns zero. The
two matrices must have the same number of rows and the same number of
columns.
<A NAME="invert-sec">
<P><HR>
<CENTER><BIG>Dense Modulo-2 Matrix Inversion</BIG></CENTER>
</A>
<A NAME="invert"><HR><B>mod2dense_invert</B>:
Invert a dense modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
int mod2dense_invert
( mod2dense *m, /* Matrix to find inverse of (destroyed) */
mod2dense *r /* Place to store the inverse */
)
</PRE></BLOCKQUOTE>
<P>Inverts the first matrix passed, <B>m</B>, and stores its inverse in
the second matrix, <B>r</B>. The contents of <B>m</B> are destroyed
by this operation, though it remains a valid matrix for storing into
later. The matrix <B>m</B> must have the same number of rows as
columns. The matrix <B>r</B> must already have been allocated, and
must have the same number of rows and columns as <B>m</B>. The
two matrices passed must not be the same.
<P>The value returned is one if the inversion was successful and zero
if the matrix turned out to be singular (in which case the contents of
both the original matrix and the result matrix will be garbage).
<P>The algorithm used is based on inverting M by transforming the equation
MI = M to the equation MR = I using column operations, at which point R
is the inverse of M. The representation of matrices used allows easy
swapping of columns as needed by fiddling pointers.
<P><A NAME="forcibly_invert"><HR><B>mod2dense_forcibly_invert</B>:
Forcibly invert a matrix by changing bits if necessary.</A>
<BLOCKQUOTE><PRE>
int mod2dense_forcibly_invert
( mod2dense *m, /* Matrix to find 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 */
)
</PRE></BLOCKQUOTE>
<P>Inverts the first matrix passed, <B>m</B>, and stores its inverse
in the second matrix, <B>r</B>, proceeding with the inversion even if
<B>m</B> is singular, by changing some elements as necessary. The
contents of <B>m</B> are destroyed by this operation, though it
remains a valid matrix for storing into later. The matrix <B>m</B>
must have the same number of rows as columns. The matrix <B>r</B>
must already have been allocated, and must have the same number of
rows and columns as <B>m</B>. The two matrices passed must not be the
same.
<P>The value returned is the number of elements of <B>m</B> that had
to be changed to make inversion possible (zero, if the original matrix
was non-singular). The row and column indexes of the elements of the
original matrix that were changed are stored in the arrays passed as
the last two elements. These arrays must have as many elements as the
dimension of the matrix. (This is so even if it is known that fewer
elements than this will be changed, as these arrays are also used as
temporary storage by this routine.)
<P>See <A HREF="#invert"><TT>mod2dense_invert</TT></A> for the algorithm used.
<P><A NAME="invert_selected"><HR><B>mod2dense_invert_selected</B>:
Invert a matrix with columns selected from a bigger matrix.</A>
<BLOCKQUOTE><PRE>
int mod2dense_invert_selected
( mod2dense *m, /* Matrix from which a submatrix is inverted (destroyed) */
mod2dense *r, /* Place to store the inverse */
int *rows, /* Place to store indexes of rows used and not used */
int *cols /* Place to store indexes of columns used and not used */
)
</PRE></BLOCKQUOTE>
<P>Inverts a matrix obtained by selecting certain columns from the
first matrix passed, <B>m</B>, which must have at least as many
columns as rows. The second matrix passed, <B>r</B>, must already
exist, and must have the same number of rows and columns as <B>m</B>.
The result of inverting the sub-matrix of <B>m</B> is stored in the
corresponding columns of <B>r</B>, with the other columns being set to
garbage (or zero, see below). Normally, one would extract just the
relevant columns afterwards using <A
HREF="#copycols"><TT>mod2dense_copycols</TT></A>.) The contents of
<B>m</B> are destroyed (though it remains a valid matrix for storing
into later. The two matrices passed must not be the same.
<P>The indexes of the columns selected are stored, in order, in the last
argument, <B>cols</B>, followed by the columns not selected (in
arbitrary order). The argument <B>rows</B> is set to the indexes of
the rows used, which will be simply the indexes from zero up if the
matrix is invertible, and will otherwise give an ordering that allows
the inversion to proceed as far as possible.
<P>The value returned is zero if an invertible matrix was found, and
is otherwise the number of columns/rows that are redundant (ie, the
amount by which matrix falls short of being of full rank). If
inversion fails, partial results are stored in the columns and rows of
<B>r</B> identified by the initial portions of <B>cols</B> and
<B>rows</B>, such that if these rows and columns were extracted in
their new order, they would constitute the inverse of the
corresponding re-ordered submatrix of <B>m</B>. The remaining portion
of <B>cols</B> up to the number of rows in <B>m</B> will contain
indexes of columns of <B>r</B> that are selected arbitrarily; these
columns will, however, be set to contain all zeros.
<P>Note that when the first matrix is square, and non-singular, the
result is NOT in general the same as that obtained by calling <A
HREF="#invert"></TT>mod2dense_invert</TT></A>, since that procedure
orders the columns of the inverse so that it applies to the original
ordering of the columns of the first matrix.
<P>See <A HREF="#invert"><TT>mod2dense_invert</TT></A> for the algorithm used.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,431 +0,0 @@
PART 1:
Matrix m1:
0: 0
1: 1
2: 2 3
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
10: 10 38
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 4 34
Matrix m2, as read from file. Should be same as m1 above.
0: 0
1: 1
2: 2 3
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
10: 10 38
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 4 34
Test of equality of m1 & m2 (should be 1): 1
Matrix m3, copied from m1 above.
0: 0
1: 1
2: 2 3
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
10: 10 38
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 4 34
Test of equality of m1 & m3 (should be 1): 1
Matrix m3 again, should now be all zeros.
0:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
Test of equality of m1 & m3 (should be 0): 0
PART 2:
Transpose of m1.
0: 0
1: 1
2: 2
3: 2 3
4: 4 34
5: 5
6: 6
7: 7
8: 8
9: 9
10: 10
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 34
35:
36:
37:
38: 10
39:
Matrix m1 after adding rows 2 and 12 and 3 to 10.
0: 0
1: 1
2: 2 3
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
10: 2 10 12 38
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 4 34
Matrix m1 after further adding column 34 to 0.
0: 0
1: 1
2: 2 3
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9
10: 2 10 12 38
11: 11
12: 12
13: 13
14: 14
15: 15
16: 16
17: 17
18: 18
19: 19
20: 20
21: 21
22: 22
23: 23
24: 24
25: 25
26: 26
27: 27
28: 28
29: 29
30: 30
31: 31
32: 32
33: 33
34: 0 4 34
PART 3:
Matrix s0.
0:
1: 3 4
2: 0
3: 1
4:
Matrix s1.
0:
1: 3 5
2:
3: 0 1 6
4:
Matrix s2.
0: 0
1: 1
2:
3:
4:
5: 1 2 3
6:
Maxtrix s1 times unpacked vector ( 1 0 0 1 0 1 0 ).
( 0 0 0 1 0 )
Sum of s0 and s1.
0:
1: 4 5
2: 0
3: 0 6
4:
Product of s1 and s2.
0:
1: 1 2 3
2:
3: 0 1
4:
Tried to find (1,2), actually found: (1,2)
Above matrix with (1,2) cleared.
0:
1: 1 3
2:
3: 0 1
4:
Tried to find (1,1), actually found: (1,1)
Matrix with (1,1) cleared as well.
0:
1: 3
2:
3: 0 1
4:
PART 4:
Matrix s1.
0: 3 5
1: 1 6
2: 0
3: 1 2
4: 0 2
5: 6
LU decomposition (returned value was 0).
L=
0: 3
1: 1
2: 0
3: 1 2
4: 0 2 4
5:
U=
0: 0
1: 1 6
2: 2 6
3: 3
4: 6
cols: 0 1 2 3 6 5 4
rows: 2 1 3 0 4 5
Product of L and U.
0: 3
1: 1 6
2: 0
3: 1 2
4: 0 2
5:
Solution of Ly=x with x from ( 0 1 1 0 1 0 ) according to rows selected.
1 1 1 0 1
Returned value from forward_sub was 1
Solution of Uz=y.
1 0 0 0 0 0 1
Returned value from backward_sub was 1
PART 5:
Matrix m1:
0: 3
1: 1
2: 2
3: 0
Matrix m2, copyrows of m1 in order 3,1,2,0 (should be identity)
0: 0
1: 1
2: 2
3: 3
Matrix m3, copycols of m1 in order 3,1,2,0 (should be identity)
0: 0
1: 1
2: 2
3: 3
DONE WITH TESTS.

View File

@ -1,378 +0,0 @@
/* MOD2SPARSE-TEST. C - Program to test mod2sparse module. */
/* 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.
*/
/* Correct output for this program is saved in the file mod2sparse-test-out */
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "mod2sparse.h"
main(void)
{
mod2sparse *m1, *m2, *m3, *m4;
mod2sparse *s0, *s1, *s2, *s3, *s4;
mod2sparse *L, *U;
mod2entry *e;
int rows[5], cols[7];
int i, j;
FILE *f;
printf("\nPART 1:\n\n");
/* Set up m1 with bits on a diagonal plus a few more set to 1. */
m1 = mod2sparse_allocate(35,40);
mod2sparse_clear(m1);
for (i = 0; i<35; i++) mod2sparse_insert(m1,i,i);
mod2sparse_insert(m1,2,3);
mod2sparse_insert(m1,34,4);
mod2sparse_insert(m1,10,38);
/* Print m1. */
printf("Matrix m1:\n\n");
mod2sparse_print(stdout,m1);
printf("\n"); fflush(stdout);
/* Store m1 in a file. */
f = fopen("test-file","wb");
if (f==0)
{ fprintf(stderr,"Can't create test-file\n");
exit(1);
}
if (!mod2sparse_write(f,m1))
{ printf("Error from mod2sparse_write\n");
}
fclose(f);
/* Read matrix written above back into m2. */
f = fopen("test-file","rb");
if (f==0)
{ fprintf(stderr,"Can't open test-file\n");
exit(1);
}
m2 = mod2sparse_read(f);
if (m2==0)
{ printf("Error from mod2sparse_read\n");
exit(1);
}
/* Print m2, along with result of equality test. */
printf("Matrix m2, as read from file. Should be same as m1 above.\n\n");
mod2sparse_print(stdout,m2);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m2 (should be 1): %d\n\n",
mod2sparse_equal(m1,m2));
/* Copy m1 to m3. */
m3 = mod2sparse_allocate(mod2sparse_rows(m1),mod2sparse_cols(m1));
mod2sparse_copy(m1,m3);
/* Print m3, along with result of equality test. */
printf("Matrix m3, copied from m1 above.\n\n");
mod2sparse_print(stdout,m3);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m3 (should be 1): %d\n\n",
mod2sparse_equal(m1,m3));
/* Clear m3. */
mod2sparse_clear(m3);
/* Print m3 again. */
printf("Matrix m3 again, should now be all zeros.\n\n");
mod2sparse_print(stdout,m3);
printf("\n"); fflush(stdout);
printf("Test of equality of m1 & m3 (should be 0): %d\n\n",
mod2sparse_equal(m1,m3));
printf("\nPART 2:\n\n");
/* Compute transpose of m1. */
m4 = mod2sparse_allocate(mod2sparse_cols(m1),mod2sparse_rows(m1));
mod2sparse_transpose(m1,m4);
/* Print transpose. */
printf("Transpose of m1.\n\n");
mod2sparse_print(stdout,m4);
printf("\n"); fflush(stdout);
/* Add rows and columns in m1. */
mod2sparse_add_row(m1,10,m1,2);
mod2sparse_add_row(m1,10,m1,12);
mod2sparse_add_row(m1,10,m1,3);
printf("Matrix m1 after adding rows 2 and 12 and 3 to 10.\n\n");
mod2sparse_print(stdout,m1);
printf("\n"); fflush(stdout);
printf("Matrix m1 after further adding column 34 to 0.\n\n");
mod2sparse_add_col(m1,0,m1,34);
mod2sparse_print(stdout,m1);
printf("\n"); fflush(stdout);
/* Free space for m1, m2, and m3. */
mod2sparse_free(m1);
mod2sparse_free(m2);
mod2sparse_free(m3);
printf("\nPART 3:\n\n");
/* Allocate some small matrices. */
s0 = mod2sparse_allocate(5,7);
s1 = mod2sparse_allocate(5,7);
s2 = mod2sparse_allocate(7,4);
s3 = mod2sparse_allocate(5,4);
s4 = mod2sparse_allocate(5,7);
/* Set up the contents of s0, s1, and s2. */
mod2sparse_clear(s0);
mod2sparse_clear(s1);
mod2sparse_clear(s2);
mod2sparse_insert(s0,1,3);
mod2sparse_insert(s0,1,4);
mod2sparse_insert(s0,2,0);
mod2sparse_insert(s0,3,1);
mod2sparse_insert(s1,1,3);
mod2sparse_insert(s1,1,5);
mod2sparse_insert(s1,3,0);
mod2sparse_insert(s1,3,1);
mod2sparse_insert(s1,3,6);
mod2sparse_insert(s2,5,1);
mod2sparse_insert(s2,5,2);
mod2sparse_insert(s2,5,3);
mod2sparse_insert(s2,0,0);
mod2sparse_insert(s2,1,1);
/* Print s0, s1, and s2. */
printf("Matrix s0.\n\n");
mod2sparse_print(stdout,s0);
printf("\nMatrix s1.\n\n");
mod2sparse_print(stdout,s1);
printf("\nMatrix s2.\n\n");
mod2sparse_print(stdout,s2);
printf("\n"); fflush(stdout);
/* Multiply s1 by vector (1 1 0 1 0 1 0). */
{ char u[7] = { 1, 0, 0, 1, 0, 1, 0 };
char v[5];
int i;
printf("Maxtrix s1 times unpacked vector ( 1 0 0 1 0 1 0 ).\n\n(");
mod2sparse_mulvec(s1,u,v);
for (i = 0; i<5; i++) printf(" %d",v[i]);
printf(" )\n\n");
}
/* Add s0 and s1, storing the result in s4, then print s4. */
mod2sparse_add(s0,s1,s4);
printf("Sum of s0 and s1.\n\n");
mod2sparse_print(stdout,s4);
printf("\n"); fflush(stdout);
/* Multiply s1 and s2, storing the product in s3, and then print s3. */
mod2sparse_multiply(s1,s2,s3);
printf("Product of s1 and s2.\n\n");
mod2sparse_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Try clearing a bit in s3, then printing the result. */
e = mod2sparse_find(s3,1,2);
printf("Tried to find (1,2), actually found: (%d,%d)\n\n",
mod2sparse_row(e), mod2sparse_col(e));
mod2sparse_delete(s3,e);
printf("Above matrix with (1,2) cleared.\n\n");
mod2sparse_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Try clearing another bit in s3, then printing the result. */
e = mod2sparse_find(s3,1,1);
printf("Tried to find (1,1), actually found: (%d,%d)\n\n",
mod2sparse_row(e), mod2sparse_col(e));
mod2sparse_delete(s3,e);
printf("Matrix with (1,1) cleared as well.\n\n");
mod2sparse_print(stdout,s3);
printf("\n"); fflush(stdout);
/* Free space for s0, s1, s2, s3, and s4. */
mod2sparse_free(s0);
mod2sparse_free(s1);
mod2sparse_free(s2);
mod2sparse_free(s3);
mod2sparse_free(s4);
printf("\nPART 4:\n\n");
/* Set up a small rectangular matrix, s1. */
s1 = mod2sparse_allocate(6,7);
mod2sparse_clear(s1);
mod2sparse_insert(s1,0,3);
mod2sparse_insert(s1,0,5);
mod2sparse_insert(s1,1,6);
mod2sparse_insert(s1,1,1);
mod2sparse_insert(s1,2,0);
mod2sparse_insert(s1,3,1);
mod2sparse_insert(s1,3,2);
mod2sparse_insert(s1,4,2);
mod2sparse_insert(s1,4,0);
mod2sparse_insert(s1,5,6);
/* Print s1. */
printf("Matrix s1.\n\n");
mod2sparse_print(stdout,s1);
printf("\n"); fflush(stdout);
/* Compute and print LU decomposition. */
L = mod2sparse_allocate(6,5);
U = mod2sparse_allocate(5,7);
i = mod2sparse_decomp(s1,5,L,U,rows,cols,Mod2sparse_first,0,0);
printf("LU decomposition (returned value was %d).\n\n",i);
printf("L=\n");
mod2sparse_print(stdout,L);
printf("\nU=\n");
mod2sparse_print(stdout,U);
printf("\n");
printf("cols:");
for (j = 0; j<7; j++) printf(" %d",cols[j]);
printf("\n");
printf("rows:");
for (i = 0; i<6; i++) printf(" %d",rows[i]);
printf("\n\n");
fflush(stdout);
/* Compute and print product of L and U. Should match s1 for the
sub-matrix found. */
s2 = mod2sparse_allocate(6,7);
mod2sparse_multiply(L,U,s2);
printf("Product of L and U.\n\n");
mod2sparse_print(stdout,s2);
printf("\n");
fflush(stdout);
/* Solve system by forward and backward substitution. */
{ char x[6] = { 0, 1, 1, 0, 1, 0 };
static char y[5], z[7];
int i, r;
r = mod2sparse_forward_sub (L, rows, x, y);
printf(
"Solution of Ly=x with x from ( 0 1 1 0 1 0 ) according to rows selected.\n\n");
for (i = 0; i<5; i++) printf(" %d",y[i]);
printf("\n\nReturned value from forward_sub was %d\n\n",r);
fflush(stdout);
r = mod2sparse_backward_sub (U, cols, y, z);
printf("Solution of Uz=y.\n\n");
for (i = 0; i<7; i++) printf(" %d",z[i]);
printf("\n\nReturned value from backward_sub was %d\n\n",r);
fflush(stdout);
}
printf("\nPART 5:\n\n");
m1 = mod2sparse_allocate(4,4);
m2 = mod2sparse_allocate(4,4);
m3 = mod2sparse_allocate(4,4);
mod2sparse_insert(m1,0,3);
mod2sparse_insert(m1,1,1);
mod2sparse_insert(m1,2,2);
mod2sparse_insert(m1,3,0);
printf("Matrix m1:\n\n");
mod2sparse_print(stdout,m1);
printf("\n"); fflush(stdout);
printf("Matrix m2, copyrows of m1 in order 3,1,2,0 (should be identity)\n\n");
{ int rows[] = { 3, 1, 2, 0 };
mod2sparse_copyrows(m1,m2,rows);
}
mod2sparse_print(stdout,m2);
printf("\n"); fflush(stdout);
printf("Matrix m3, copycols of m1 in order 3,1,2,0 (should be identity)\n\n");
{ int cols[] = { 3, 1, 2, 0 };
mod2sparse_copycols(m1,m3,cols);
}
mod2sparse_print(stdout,m3);
printf("\n"); fflush(stdout);
printf("\nDONE WITH TESTS.\n");
exit(0);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,147 +0,0 @@
/* MOD2SPARSE.H - Interface to module for handling sparse 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.
*/
/* This module implements operations on sparse matrices of mod2 elements
(bits, with addition and multiplication being done modulo 2).
All procedures in this module display an error message on standard
error and terminate the program if passed an invalid argument (indicative
of a programming error), or if memory cannot be allocated. Errors from
invalid contents of a file result in an error code being returned to the
caller, with no message being printed by this module.
*/
/* DATA STRUCTURES USED TO STORE A SPARSE MATRIX. Non-zero entries (ie, 1s)
are represented by nodes that are doubly-linked both by row and by column,
with the headers for these lists being kept in arrays. Nodes are allocated
in blocks to reduce time and space overhead. Freed nodes are kept for
reuse in the same matrix, rather than being freed for other uses, except
that they are all freed when the matrix is cleared to all zeros by the
mod2sparse_clear procedure, or copied into by mod2sparse_copy.
Direct access to these structures should be avoided except in low-level
routines. Use the macros and procedures defined below instead. */
typedef struct mod2entry /* Structure representing a non-zero entry, or
the header for a row or column */
{
int row, col; /* Row and column indexes of this entry, starting
at 0, and with -1 for a row or column header */
struct mod2entry *left, *right, /* Pointers to entries adjacent in row */
*up, *down; /* and column, or to headers. Free */
/* entries are linked by 'left'. */
double pr, lr; /* Probability and likelihood ratios - not used */
/* by the mod2sparse module itself */
} mod2entry;
#define Mod2sparse_block 10 /* Number of entries to block together for
memory allocation */
typedef struct mod2block /* Block of entries allocated all at once */
{
struct mod2block *next; /* Next block that has been allocated */
mod2entry entry[Mod2sparse_block]; /* Entries in this block */
} mod2block;
typedef struct /* Representation of a sparse matrix */
{
int n_rows; /* Number of rows in the matrix */
int n_cols; /* Number of columns in the matrix */
mod2entry *rows; /* Pointer to array of row headers */
mod2entry *cols; /* Pointer to array of column headers */
mod2block *blocks; /* Blocks that have been allocated */
mod2entry *next_free; /* Next free entry */
} mod2sparse;
/* MACROS TO GET AT ELEMENTS OF A SPARSE MATRIX. The 'first', 'last', 'next',
and 'prev' macros traverse the elements in a row or column. Moving past
the first/last element gets one to a header element, which can be identified
using the 'at_end' macro. Macros also exist for finding out the row
and column of an entry, and for finding out the dimensions of a matrix. */
#define mod2sparse_first_in_row(m,i) ((m)->rows[i].right) /* Find the first */
#define mod2sparse_first_in_col(m,j) ((m)->cols[j].down) /* or last entry in */
#define mod2sparse_last_in_row(m,i) ((m)->rows[i].left) /* a row or column */
#define mod2sparse_last_in_col(m,j) ((m)->cols[j].up)
#define mod2sparse_next_in_row(e) ((e)->right) /* Move from one entry to */
#define mod2sparse_next_in_col(e) ((e)->down) /* another in any of the four */
#define mod2sparse_prev_in_row(e) ((e)->left) /* possible directions */
#define mod2sparse_prev_in_col(e) ((e)->up)
#define mod2sparse_at_end(e) ((e)->row<0) /* See if we've reached the end */
#define mod2sparse_row(e) ((e)->row) /* Find out the row or column index */
#define mod2sparse_col(e) ((e)->col) /* of an entry (indexes start at 0) */
#define mod2sparse_rows(m) ((m)->n_rows) /* Get the number of rows or columns*/
#define mod2sparse_cols(m) ((m)->n_cols) /* in a matrix */
/* POSSIBLE LU DECOMPOSITION STRATEGIES. For use with mod2sparse_decomp. */
typedef enum
{ Mod2sparse_first,
Mod2sparse_mincol,
Mod2sparse_minprod
} mod2sparse_strategy;
/* PROCEDURES TO MANIPULATE SPARSE MATRICES. */
mod2sparse *mod2sparse_allocate (int, int);
void mod2sparse_free (mod2sparse *);
void mod2sparse_clear (mod2sparse *);
void mod2sparse_copy (mod2sparse *, mod2sparse *);
void mod2sparse_copyrows (mod2sparse *, mod2sparse *, int *);
void mod2sparse_copycols (mod2sparse *, mod2sparse *, int *);
void mod2sparse_print (FILE *, mod2sparse *);
int mod2sparse_write (FILE *, mod2sparse *);
mod2sparse *mod2sparse_read (FILE *);
mod2entry *mod2sparse_find (mod2sparse *, int, int);
mod2entry *mod2sparse_insert (mod2sparse *, int, int);
void mod2sparse_delete (mod2sparse *, mod2entry *);
void mod2sparse_transpose (mod2sparse *, mod2sparse *);
void mod2sparse_add (mod2sparse *, mod2sparse *, mod2sparse *);
void mod2sparse_multiply (mod2sparse *, mod2sparse *, mod2sparse *);
void mod2sparse_mulvec (mod2sparse *, char *, char *);
int mod2sparse_equal (mod2sparse *, mod2sparse *);
int mod2sparse_count_row (mod2sparse *, int);
int mod2sparse_count_col (mod2sparse *, int);
void mod2sparse_add_row (mod2sparse *, int, mod2sparse *, int);
void mod2sparse_add_col (mod2sparse *, int, mod2sparse *, int);
int mod2sparse_decomp (mod2sparse *, int, mod2sparse *, mod2sparse *,
int *, int *, mod2sparse_strategy, int, int);
int mod2sparse_forward_sub (mod2sparse *, int *, char *, char *);
int mod2sparse_backward_sub (mod2sparse *, int *, char *, char *);

View File

@ -1,719 +0,0 @@
<HTML><HEAD>
<TITLE> Sparse Modulo-2 Matrix Routines </TITLE>
</HEAD><BODY>
<H1> Sparse Modulo-2 Matrix Routines </H1>
<P>This module implements operations on matrices in which the elements
are all 0 or 1, with addition and multiplication being done modulo 2.
The matrices are represented by doubly-linked lists of entries
representing the elements in each row and column that are 1s, with
other elements being assumed to be zero.
<P>This is an appropriate representation when the matrices are sparse
(ie, 0s are much more frequent that 1s). Matrices in which 0s and 1s
are about equally likely may be better handled with the <A
HREF="mod2dense.html">dense modulo-2 matrix routines</A>. Matrices
can be converted between these two formats using the <A
HREF="mod2convert.html">module-2 matrix conversion routines</A>.
<P>All procedures in this module display an error message on standard
error and terminate the program if passed an invalid argument (indicative
of a programming error), or if memory cannot be allocated. Errors from
invalid contents of a file result in an error code being returned to the
caller, with no message being printed by this module.
<A NAME="rep"><H2>Representation of sparse matrices</H2></A>
<P>This module represents a non-zero element of a matrix (which must have
the value 1, since these are modulo-2 matrices) by a node of type
<TT>mod2entry</TT>, which contains the row and column of the element,
pointers to the next non-zero elements above and below in its column
and to the left and the right in its row, and two double-precision
floating-point numbers called <B>pr</B> and <B>lr</B>, which are
of no significance to this module, but which are used by the routines
for <A HREF="decoding.html#prprp">decoding LDPC codes by probability
propagation</A>.
<P>The <TT>mod2sparse</TT> type represents a matrix. It records the
number of rows and columns in the matrix, and contains arrays of
pointers to the <TT>mod2entry</TT> structures for the first non-zero
element in each row and the first non-zero element in each column.
<P>Matrices must be created by the <A
HREF="#allocate"><TT>mod2sparse_allocate</TT></A> procedure, which
returns a pointer to a <TT>mod2sparse</TT> structure. When a matrix
is no longer needed, the space it occupies can be freed with <A
HREF="#free"><TT>mod2sparse_free</TT></A>. Elements within a matrix,
represented by <TT>mod2entry</TT> nodes, are allocated as needed, and
if deleted, they will be reused for new elements within the same
matrix. The space they occupy is not reusable for other matrices or
other purposes until the entire matrix is either freed, with <A
HREF="#free"><TT>mod2sparse_free</TT></A>, or cleared to all zeros,
with <A HREF="#clear"><TT>mod2sparse_clear</TT></A>, or used as
the result matrix for copying or arithmetic operations.
<P><B>Header files required</B>:
<TT>mod2sparse.h</TT>
<A NAME="dimension-sec">
<P><HR>
<CENTER><BIG>Dimension Macros</BIG></CENTER>
</A>
<HR>The following macros take a pointer to a mod2sparse structure as their
argument, and return the number of rows or the number of columns in
the matrix pointed to, which will have been fixed when the matrix was
created with <A HREF="#allocate">mod2sparse_allocate</A>:
<BLOCKQUOTE><PRE>
mod2sparse_rows(m) /* Returns the number of rows in m */
mod2sparse_cols(m) /* Returns the number of columns in m */
</PRE></BLOCKQUOTE>
<A NAME="traversal-sec">
<P><HR>
<CENTER><BIG>Traversal Macros</BIG></CENTER>
</A>
<HR>The following macros are used to move around a sparse matrix by
following the pointers from one non-zero element to the next or
previous non-zero element in the same row or column. If such a
movement takes one beyond the last or before first entry in a row or
column, or if one tries to find the first or last non-zero entry in a
row or column that has no non-zero entries, the entry returned will be
a special one that can be identified using the
<TT>mod2sparse_at_end</TT> macro. If one is already at this special
entry, moving further wraps one around to the first or last entry.
<P>The macros for finding the first or last entry in a row or column
take as their arguments a pointer to the matrix (<TT>mod2sparse
*</TT>) and a row or column index, starting at zero. The other macros
take as their arguments a pointer to an entry (<TT>mod2entry *</TT>)
within some matrix.
<BLOCKQUOTE><PRE>
mod2sparse_first_in_row(m,i) /* Returns the first entry in row i of m */
mod2sparse_first_in_col(m,j) /* Returns the first entry in column j of m */
mod2sparse_last_in_row(m,i) /* Returns the last entry in row i of m */
mod2sparse_last_in_col(m,j) /* Returns the last entry in column j of m */
mod2sparse_next_in_row(e) /* Returns the entry after e in its row */
mod2sparse_next_in_col(e) /* Returns the entry after e in its column */
mod2sparse_prev_in_row(e) /* Returns the entry before e in its row */
mod2sparse_prev_in_col(e) /* Returns the entry before e in its col */
mod2sparse_row(e) /* Returns the row index of entry e */
mod2sparse_col(e) /* Returns the column index of entry e */
mod2sparse_at_end(e) /* Returns 1 if e is a special entry obtained
by moving past the end, returns 0 otherwise */
</PRE></BLOCKQUOTE>
<A NAME="alloc-sec">
<P><HR>
<CENTER><BIG>Allocating and Freeing Sparse Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="allocate"><HR><B>mod2sparse_allocate</B>:
Allocate space for a sparse module-2 matrix.</A>
<BLOCKQUOTE><PRE>
mod2sparse *mod2sparse_allocate
( int n_rows, /* Number of rows in matrix */
int n_cols /* Number of columns in matrix */
)
</PRE></BLOCKQUOTE>
Allocates space for a matrix with the given number of rows and
columns, and returns a pointer to it. The matrix will initially
be all zero.
<P>If there is not enough memory available, a message is displayed on
standard error and the program is terminated. The matrix should be
freed with <A HREF="#free"><TT>mod2sparse_free</TT></A> once it is no
longer in use.
<P><A NAME="free"><HR><B>mod2sparse_free</B>:
Free the space occupied by a sparse module-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_free
( mod2sparse *m /* Pointer to matrix to free */
)
</PRE></BLOCKQUOTE>
Frees the space occupied by the matrix for re-use. The pointer passed
should not be used afterward. Note that space for the individual matrix
elements (but not the matrix as a whole) is also freed when <A
HREF="#clear"><TT>mod2sparse_clear</TT></A> is called, or the matrix
is used as the destination for other operations.
<A NAME="copy-clear-sec">
<P><HR>
<CENTER><BIG>Copying and Clearing Sparse Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="clear"><HR><B>mod2sparse_clear</B>:
Set all elements of a matrix to zero.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_clear
( mod2sparse *m /* Pointer to matrix to clear */
)
</PRE></BLOCKQUOTE>
Sets all of the elements of the matrix passed to 0. The space occupied
by the previous non-zero elements is freed for use in other matrices, or
other purposes. The matrix itself is not freed, however. To do that,
use <A HREF="#free"><TT>mod2sparse_free</TT></A>.
<P><A NAME="copy"><HR><B>mod2sparse_copy</B>:
Copy the contents of one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_copy
( mod2sparse *m /* Pointer to matrix to copy from */
mod2sparse *r /* Pointer to matrix to receive data */
)
</PRE></BLOCKQUOTE>
Copies the contents of the first matrix passed, <B>m</B>, to the
second matrix passed, <B>r</B>, which must already have been
allocated, and must have at least as many rows and columns as the
first. If <B>r</B> is larger than <B>m</B>, its elements that have
row or column indexes greater than the dimension of <B>m</B> are set
to zeros.
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).
<P><A NAME="copyrows"><HR><B>mod2sparse_copyrows</B>:
Copy selected rows from one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_copyrows
( mod2sparse *m, /* Pointer to matrix to copy rows from */
mod2sparse *r, /* Pointer to matrix in which to store data */
int *rows /* Indexes of rows, numbered from 0 */
)
</PRE></BLOCKQUOTE>
Copies selected rows of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many columns as <B>m</B>. The indexes of the
rows to copy are given in order as an array of length the same as
the number of rows in <B>r</B>; duplicates are allowed. Row
indexes start at 0. These rows are copied to <B>r</B>, with the
row indexed by the first entry in <B>rows</B> going to the
first row of <B>r</B>, and so forth. If <B>r</B> has more columns than
<B>m</B>, the extra entries in each row are set to zeros.
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).
<P><A NAME="copycols"><HR><B>mod2sparse_copycols</B>:
Copy selected columns from one matrix to another.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_copycols
( mod2sparse *m, /* Pointer to matrix to copy columns from */
mod2sparse *r, /* Pointer to matrix in which to store data */
int *cols /* Indexes of columns, numbered from 0 */
)
</PRE></BLOCKQUOTE>
Copies selected columns of the first matrix, <B>m</B>, to the second
matrix, <B>r</B>, which must already have been allocated, and which
must have at least as many rows as <B>m</B>. The indexes of the
columns to copy are given in order as an array of length the same as
the number of columns in <B>r</B>; duplicates are allowed. Column
indexes start at 0. These columns are copied to <B>r</B>, with the
column indexed by the first entry in <B>cols</B> going to the
first column of <B>r</B>, and so forth. If <B>r</B> has more rows than
<B>m</B>, the extra entries in each column are set to zeros.
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use (which may include being reused immediately for
the copies of the entries in <B>m</B>).
<A NAME="input-output-sec">
<P><HR>
<CENTER><BIG>Input and Output of Sparse Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="print"><HR><B>mod2sparse_print</B>:
Print a sparse modulo-2 matrix in human-readable form.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_print
( FILE *f, /* File to print to */
mod2sparse *m /* Pointer to matrix to print */
)
</PRE></BLOCKQUOTE>
The matrix is printed on standard output with one line of output per row,
of the form
<BLOCKQUOTE><PRE>
<I>row</I>: <I>col col col ...</I>
</PRE></BLOCKQUOTE>
where <I>row</I> is the index of the row, and the <I>col</I> entries are
the indexes of columns that are non-zero in that row. Row and column
indexes start at zero. Rows with no entries are printed with no column
indexes after the colon. The number of columns is not indicated in the output.
<P><A NAME="write"><HR><B>mod2sparse_write</B>:
Write a sparse modulo-2 matrix to a file in machine-readable format.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_write
( FILE *f, /* File to write data to */
mod2sparse *m /* Pointer to matrix write out */
)
</PRE></BLOCKQUOTE>
Writes a machine-readable representation the sparse matrix <B>m</B> to
the file <B>f</B>. The file should have been opened in binary mode
(with a "b" in the mode passed to fopen). The contents written will
not be text, and will not be human-readable. Other binary data may
precede or follow the data for the matrix written.
<P>The data written to the file starts with the number of rows and the
number of columns. Following this are negative integers giving row
indexes (starting at 1), which apply until the next row index, and
positive integers giving column indexes (starting at 1) for a non-zero
entry in the matrix. The data should be readable by <A
HREF="#read"><TT>mod2sparse_read</TT></A> even on a machine with a
different byte-ordering.
<P>The value returned by <TT>mod2sparse_write</TT> is one if the
operation was successful, zero if an error of some sort occurred.
<P><A NAME="read"><HR><B>mod2sparse_read</B>:
Read a sparse modulo-2 matrix from a file.</A>
<BLOCKQUOTE><PRE>
mod2sparse *mod2sparse_read
( FILE *f, /* File to read data from */
)
</PRE></BLOCKQUOTE>
Reads a sparse modulo-2 matrix from the file <B>f</B>. This file
should have been opened in binary mode (with a "b" in the mode passed
to fopen). The contents of the file at the point when
<TT>mod2sparse_read</TT> is called should have been written by <A
HREF="#write"><TT>mod2sparse_write</TT></A>. Other binary data may
precede or follow this data.
<P>The value returned is a pointer to the matrix read, for which space
will have been allocated by <TT>mod2sparse_read</TT>, or zero if an
error occurred (either an error reading the file, or data not in the
right format).
<A NAME="elementary-sec">
<P><HR>
<CENTER><BIG>Elementary Operations on Sparse Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="find"><HR><B>mod2sparse_find</B>:
Look for an entry at a given row and column.</A>
<BLOCKQUOTE><PRE>
mod2entry *mod2sparse_find
( mod2sparse *m, /* Matrix in which to look for entry */
int row, /* Row index (from 0) */
int col /* Column index (from 0) */
)
</PRE></BLOCKQUOTE>
Looks for an entry at the given row and column in the matrix <B>m</B>,
representing a non-zero element (ie, one with value 1). Returns a
pointer to this entry if it exists, or zero (a null pointer) if it
does not exist (ie, if that element of the matrix has value 0).
<P>The search strategy is to first look at the end of the row and the
end of the column. The entry might be found at one of these two
places, or it might be determinable from these end entries that no
entry exists at the given row and column. Otherwise, searches are
done from the start of the row and the start of the column, in
parallel, until an entry with the given row and column are found, or
until it can be determined that such an entry does not exist.
Searching in parallel ensures that the operation will be fast if
either the row is sparse or the column is sparse.
<P><A NAME="insert"><HR><B>mod2sparse_insert</B>:
Insert an entry at a given row and column.</A>
<BLOCKQUOTE><PRE>
mod2entry *mod2sparse_insert
( mod2sparse *m, /* Matrix in which to insert an entry */
int row, /* Row index (from 0) */
int col /* Column index (from 0) */
)
</PRE></BLOCKQUOTE>
Adds a new entry (representing an element with value 1) at the given
row and column position in the matrix <B>m</B>. If such an entry
already exists, nothing is done (this is not considered to be an
error). The new (or existing) entry is returned as the value of
this procedure.
<P>The search strategy is to first look at the end of the row for an
existing entry or for the place where the new entry belongs. If this
fails, the row is searched from the beginning. If an existing entry
is found, it is returned. Otherwise, a new entry is created, it is
inserted in its correct place in the row, and it is inserted in its
correct place in its column, once again by first looking at the end,
and then if required searching from the beginning.
<P>The effect of this strategy is that a sparse matrix can be efficiently
created by either adding entries in increasing order by row and column or in
decreasing order by row and column.
<P><A NAME="delete"><HR><B>mod2sparse_delete</B>:
Delete an entry from a sparse modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_delete
( mod2sparse *m, /* Matrix in which to delete an entry */
mod2entry *e /* Entry to delete - MUST be in m */
)
</PRE></BLOCKQUOTE>
Deletes the entry <B>e</B> from the sparse matrix <B>m</B>, which
effectively sets to zero the element of the matrix that this entry
corresponded to. The entry is freed for future use in the same
matrix, but not (immediately, at least) for use in other matrices, or
generally. The pointer to this entry should not be used again once
it is deleted.
<P>The time required for this operation does not depend on how many
entries are currently in the matrix.
<P><B>Warning:</B> It is an error if <B>e</B> is not an entry of
<B>m</B>. This error is not currently diagnosed, but doing this may
cause serious problems, as it may lead later to entries for <B>m</B>
being erroneously freed when the matrix to which <B>e</B> properly
belongs is freed.
<A NAME="arith-sec">
<P><HR>
<CENTER><BIG>Sparse Modulo-2 Matrix Arithmetic and Comparison</BIG></CENTER>
</A>
<A NAME="transpose"><HR><B>mod2sparse_transpose</B>:
Compute the transpose of a sparse modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_transpose
( mod2sparse *m, /* Matrix to compute transpose of */
mod2sparse *r /* Result of transpose operation */
)
</PRE></BLOCKQUOTE>
Stores the transpose of its first argument, <B>m</B>, in the matrix
pointed to by its second argument, <B>r</B>, which must already have
been allocated, and which must have as many rows as <B>m</B> has
columns, and as many columns as <B>m</B> has rows. The two matrices
<B>m</B> and <B>r</B> must not be the same (ie, the two pointers
passed must be different).
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.
<P><A NAME="add"><HR><B>mod2sparse_add</B>:
Add two sparse modulo-2 matrices.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_add
( mod2sparse *m1, /* Left operand of add */
mod2sparse *m2, /* Right operand of add */
mod2sparse *r /* Place to store result of add */
)
</PRE></BLOCKQUOTE>
Adds matrices <B>m1</B> and <B>m2</B>, storing the result in the
matrix pointed to by <B>r</B>. All three matrices must have the same
numbers of rows and columns. It is permissible for <B>r</B> to be the
same as <B>m1</B> and/or <B>m2</B>. Neither of the first two matrices is
changed by this procedure (unless they are the same as <B>r</B>).
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.
<P><A NAME="multiply"><HR><B>mod2sparse_multiply</B>:
Multiply two sparse modulo-2 matrices.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_multiply
( mod2sparse *m1, /* Left operand of multiply */
mod2sparse *m2, /* Right operand of multiply */
mod2sparse *r /* Place to store result of multiply */
)
</PRE></BLOCKQUOTE>
Does a matrix multiplication of <B>m1</B> by <B>m2</B>, and stores the
result in the matrix pointed to by <B>r</B>. The matrices must have
compatible numbers of rows and columns. Neither of the first two
matrices is changed by this procedure. The result matrix, <B>r</B>,
must not be the same as either <B>m1</B> or <B>m2</B>.
<P>The space occupied by the previous non-zero entries of <B>r</B> is
freed for general use.
<P><A NAME="mulvec"><HR><B>mod2sparse_mulvec</B>:
Multiply a vector by a sparse modulo-2 matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_mulvec
( mod2sparse *m, /* Pointer to matrix to multiply by, M rows, N columns */
char *u, /* Pointer to unpacked vector to multiply, N long */
char *v /* Pointer to unpacked result vector, M long */
)
</PRE></BLOCKQUOTE>
Multiplies the vector <B>u</B> on the left by the sparse modulo-2
matrix <B>m</B>, storing the result in <B>v</B>. Both <B>u</B> and
<B>v</B> are modulo-2 vectors, but are stored unpacked, with one bit
per char. Any non-zero value in <B>u</B> is equivalent to '1'.
The vectors <B>u</B> and <B>v</B> must not overlap.
<P><A NAME="equal"><HR><B>mod2sparse_equal</B>:
Check whether two sparse modulo-2 matrices are equal.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_equal
( mod2sparse *m1, /* Pointers to the two matrices */
mod2sparse *m2 /* to compare */
)
</PRE></BLOCKQUOTE>
Returns one if every element of <B>m1</B> is equal to the
corresponding element of <B>m2</B>, and otherwise returns zero. The
two matrices must have the same number of rows and the same number of
columns.
<A NAME="row-col-ops-sec">
<P><HR>
<CENTER><BIG>Row/Column Operations on Sparse Modulo-2 Matrices</BIG>
</CENTER></A>
<A NAME="count_row"><HR><B>mod2sparse_count_row</B>:
Count the number of 1s in a row of a sparse matrix.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_count_row
( mod2sparse *m, /* Pointer to matrix */
int row /* Index of row to count (from 0) */
)
</PRE></BLOCKQUOTE>
Returns the number of 1s in the given row of the matrix, by counting
the number of entries in that row.
<P><A NAME="count_col"><HR><B>mod2sparse_count_col</B>:
Count the number of 1s in a column of a sparse matrix.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_count_col
( mod2sparse *m, /* Pointer to matrix */
int col /* Index of column to count (from 0) */
)
</PRE></BLOCKQUOTE>
Returns the number of 1s in the given column of the matrix, by counting
the number of entries in that column.
<P><A NAME="add_row"><HR><B>mod2sparse_add_row</B>:
Add a row to a row of a sparse matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_add_row
( mod2sparse *m1, /* Matrix containing row to add to */
int row1, /* Index in this matrix of row to add to */
mod2sparse *m2, /* Matrix containing row to add from */
int row2 /* Index in this matrix of row to add from */
)
</PRE></BLOCKQUOTE>
Modifies the row with index <B>row1</B> in the matrix <B>m1</B> by
adding to that row the row with index <B>row2</B> in the matrix
<B>m2</B>. The matrix <B>m1</B> must have at least as many columns as
<B>m2</B>. This operation is performed by inserting entries into the
row of <B>m1</B> at positions where they exist in the row of <B>m2</B>
but not in the row of <B>m1</B>, and deleting entries in the row of
<B>m1</B> that exist in the same position in the row of <B>m2</B>.
The matrix <B>m2</B> is not modified.
<P><A NAME="add_col"><HR><B>mod2sparse_add_col</B>:
Add a column to a column of a sparse matrix.</A>
<BLOCKQUOTE><PRE>
void mod2sparse_add_col
( mod2sparse *m1, /* Matrix containing column to add to */
int col1, /* Index in this matrix of col to add to */
mod2sparse *m2, /* Matrix containing column to add from */
int col2 /* Index in this matrix of column to add from */
)
</PRE></BLOCKQUOTE>
Modifies the column with index <B>col1</B> in the matrix <B>m1</B> by
adding to that column the column with index <B>col2</B> in the matrix
<B>m2</B>. The matrix <B>m1</B> must have at least as many rows as
<B>m2</B>. This operation is performed by inserting entries into the
column of <B>m1</B> at positions where they exist in the column of
<B>m2</B> but not in the column of <B>m1</B>, and deleting entries in
the column of <B>m1</B> that exist in the same position in the column
of <B>m2</B>. The matrix <B>m2</B> is not modified.
<A NAME="lu-decomp-sec">
<P><HR>
<CENTER><BIG>LU Decomposition of Sparse Modulo-2 Matrices</BIG></CENTER>
</A>
<A NAME="decomp"><HR><B>mod2sparse_decomp</B>:
Find an LU decomposition of a sparse modulo-2 (sub-)matrix.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_decomp
( mod2sparse *A, /* Matrix to find LU decomposition within, M by N */
int K, /* Size of sub-matrix to find LU decomposition of */
mod2sparse *L, /* Matrix in which L is stored, M by K */
mod2sparse *U, /* Matrix in which U is stored, K by N */
int *rows, /* Array where row indexes are stored, M long */
int *cols, /* Array where column indexes are stored, N long */
mod2sparse_strategy strategy, /* Strategy to follow in picking rows/columns */
int abandon_number, /* Number of columns to abandon at some point */
int abandon_when /* When to abandon these columns */
)
</PRE></BLOCKQUOTE>
<P>Takes as input a matrix, <B>A</B>, having <I>M</I> rows and
<I>N</I> columns, and an integer <I>K</I>. Finds an LU decomposition
of a <I>K</I> by <I>K</I> sub-matrix of <B>A</B>. The decomposition
is stored in the matrix <B>L</B>, with <I>M</I> rows and <I>K</I>
columns, and the matrix <B>U</B>, with <I>K</I> rows and <I>N</I>
columns. The product of <B>L</B> and <B>U</B> will be equal to the
<I>K</I> by <I>K</I> submatrix of <B>A</B> obtained by taking only
rows and columns that are given in the first <I>K</I> elements of the
<B>rows</B> and <B>cols</B> arrays, which are set by this procedure,
with this sub-matrix distributed over the original <I>M</I> rows and
<I>N</I> columns. Furthermore, the ordering of the row and column
indexes in these arrays will be set so that if the rows of <B>L</B>
and the columns of <B>U</B> were rearranged in this order, <B>L</B>
would be lower triangular, with zeros in rows past row <I>K</I>, and
<B>U</B> would be upper triangular, with zeros in columns past column
<I>K</I>. The <B>rows</B> array is <I>M</I> long, and the <B>cols</B>
array is <I>N</I> long. The elements in both arrays after the first
<I>K</I> contain the indexes of the rows and columns not selected to
be part of the sub-matrix of <B>A</B>, in arbitrary order.
<P>The rows and columns of <B>A</B> are selected in order to try to
make the LU decomposition as sparse as possible, using the strategy
identified by the <B>strategy</B>, <B>abandon_number</B>, and
<B>abandon_when</B> parameters. The possible strategies are
<TT>Mod2sparse_first</TT>, <TT>Mod2sparse_mincol</TT>, and
<TT>Mod2sparse_minprod</TT>. If <B>abandon_number</B> is greater than
zero, it is possible that the matrix will appear to have linearly
dependent rows when it actually does not. See the <A
HREF="sparse-LU.html">discussion of sparse LU decomposition
methods</A> for details about these strategies.
<P>If <B>A</B> is not of rank <I>K</I> or more, <B>L</B> will contain
some number less than <I>K</I> of non-zero columns, and <B>U</B> will
contain an equal number of non-zero rows. The entries in the
<B>rows</B> and <B>cols</B> arrays for the extra zero rows or columns
will be arbitrary (but valid). The number of extra zero columns is
returned as the value of this procedure (hence a return value of zero
indicates that a <I>K</I> by <I>K</I> sub-matrix of full rank was
found).
<P>The matrix <B>A</B> is not altered. The previous contents of
<B>L</B> and <B>U</B> are cleared.
<P><A NAME="forward_sub"><HR><B>mod2sparse_forward_sub</B>:
Solve a lower-triangular system by forward substitution.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_forward_sub
( mod2sparse *L, /* Matrix that is lower triangular after reordering */
int *rows, /* Array of indexes (from 0) of rows for new order */
char *x, /* Vector on right of equation, also reordered */
char *y /* Place to store solution */
)
</PRE></BLOCKQUOTE>
<P>Solves the system of equations <B>Ly</B>=<B>x</B> for <B>y</B> by
forward substitution, based on <B>L</B> being lower triangular after
its rows are reordered according to the given index array. The
vectors <B>x</B> and <B>y</B> are stored unpacked, one bit per
character. If <B>L</B> is <I>M</I> by <I>K</I>, then <B>x</B> should
be <I>M</I> long, but only the <I>K</I> bits indexed by <B>rows</B>
are looked at. The solution vector, <B>y</B>, must be <I>K</I> long.
Only <I>K</I> rows of <B>L</B> are used, as also determined by the
<I>K</I> indexes in the <B>rows</B> argument. If <B>rows</B> is null,
the first <I>K</I> rows of <B>L</B> and the first <I>K</I> elements of
<B>x</B> are used.
<P>If the matrix <B>L</B> does not have 1s on its diagonal (after row
rearrangement), there may be no solution, depending on what <B>x</B>
is. If no solution exists, this procedure returns zero, otherwise it
returns one. Any arbitrary bits in the solution are set to zero.
<P><A NAME="backward_sub"><HR><B>mod2sparse_backward_sub</B>:
Solve an upper-triangular system by backward substitution.</A>
<BLOCKQUOTE><PRE>
int mod2sparse_backward_sub
( mod2sparse *U, /* Matrix that is upper triangular after reordering */
int *cols, /* Array of indexes (from 0) of columns for new order */
char *y, /* Vector on right of equation */
char *z /* Place to store solution, also reordered */
)
</PRE></BLOCKQUOTE>
<P>Solves <B>Uz</B>=<B>y</B> for <B>z</B> by backward substitution,
based on <B>U</B> being upper triangular after its columns are
reordered according to the given index array. The vectors <B>y</B>
and <B>z</B> are stored unpacked, one bit per character. If <B>U</B>
is <I>K</I> by <I>N</I>, then the solution vector, <I>z</I>, should be
<I>N</I> long, but only the <I>K</I> bits indexed by <B>cols</B> are
set. The vector <B>y</B> must be <I>K</I> long. Only <I>K</I> columns
of <B>U</B> are used, as also determined by the <I>K</I> indexes in
the <B>cols</B> argument. The other columns of <B>U</B> must be zero
(this is not checked, but is necessary for the method used to work).
If <B>cols</B> is null, the first <I>K</I> columns of <B>U</B> and the
first <I>K</I> elements of <B>z</B> are used.
<P>If the matrix <B>U</B> does not have 1s on its diagonal (after
column rearrangement) there may be no solution, depending on what y
is. If no solution exists, this procedure returns zero, otherwise it
returns one. Any arbitrary bits in the solution are set to zero.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,125 +0,0 @@
<HTML><HEAD>
<TITLE> Notes on Modifying the LDPC Programs </TITLE>
</HEAD><BODY>
<H1> Notes on Modifying the LDPC Programs </H1>
<P>Here are a few notes on how to modify the programs to add new types of
channel, new decoding procedures, etc. You should also look at the <A
HREF="modules.html">module documentation</A>.
<H2> Adding a new type of channel </H2>
<P>Channels are involved in two programs:
<A HREF="channel.html#transmit"><B>transmit</B></A> and
<A HREF="decoding.html#decode"><B>decode</B></A>.
Adding another type of memoryless channel should be straightforward.
Adding a channel with memory may involve more work. Here are the
steps needed if no major reorganizations are required:
<OL>
<LI> Decide on a syntax for specifying the new channel type and its
parameters, and on an internal name for the channel type. Add
the internal name as a possibility in the enumerated <TT>channel_type</TT>
declared in <A HREF="channel.h"><TT>channel.h</TT></A>. You
may also need to declare new global variables to store parameters of
the channel in <A HREF="channel.h"><TT>channel.h</TT></A> and
<A HREF="channel.c"><TT>channel.c</TT></A>.
<LI> Modify the <TT>channel_parse</TT> and
<TT>channel_usage</TT> procedures in
<A HREF="channel.c"><TT>channel.c</TT></A> to
parse the specification of the new channel and display an appropriate
usage message.
<LI> Decide on how the new channel's output is represented in a file
(eg, for an erasure channel, what the symbol for an erasure is), and
update <A HREF="transmit.c"><TT>transmit.c</TT></A> to write the
new channel's output for each transmitted bit, after randomly generating
any noise (see
the <A HREF="rand.html">documentation on random number generation</A>).
<LI> Modify <A HREF="decode.c"><TT>decode.c</TT></A> in three places to
accommodate the new channel. The three sections of code to modify
allocate space for data from the channel, read data from the channel,
and set likelihood ratios based on the data read. The setting of
likelihood ratios is based on the assumption that the channel is
memoryless (ie, data received for different bits is independent).
Adding a channel with memory would require changing this assumption,
which would involve modifications to the decoding procedures too.
<LI> Document the new channel type in <A HREF="channel.html">channel.html</A>
and <A HREF="decoding.html">decoding.html</A>.
</OL>
<H2> Adding a new decoding procedure </H2>
A new decoding method can be implemented as follows:
<OL>
<LI> Decide on a syntax for specifying the method and its parameters,
using the trailing arguments to the
<A HREF="decoding.html#decode"><TT>decode</TT></A> program. Pick an
internal name for the method, and add it as a possibility in the
enumerated <TT>decoding_method</TT> type in
<A HREF="dec.h"><TT>dec.h</TT></A>. You may also need to declare
new variables for the method's parameters in
<A HREF="dec.h"><TT>dec.h</TT></A> and <A HREF="dec.c"><TT>dec.c</TT></A>.
<LI> Modify the argument parsing code in
<A HREF="decode.c"><TT>decode.c</TT></A>
to handle specifications of the new method, and change the <TT>usage</TT>
procedure to display the syntax for specifying the new method.
<LI> Write a setup procedure for your decoding method, putting it in
<A HREF="dec.c"><TT>dec.c</TT></A>, with a declaration in
<A HREF="dec.h"><TT>dec.h</TT></A>. At a minimum, this procedure
should print headers for the table of detailed decoding information
when the <B>-T</B> option was specified.
<LI> Write a decode procedure implementing your method, putting it in
<A HREF="dec.c"><TT>dec.c</TT></A>, with a declaration in
<A HREF="dec.h"><TT>dec.h</TT></A>. This procedure should output
detailed trace information when the <B>-T</B> option was specified.
<LI> Modify <A HREF="decode.c"><TT>decode.c</TT></A> in the appropriate
places to call the setup procedure and the decode procedure you wrote.
<LI> Document the new decoding method in
<A HREF="decoding.html">decoding.html</A> and
<A HREF="decode-detail.html">decode-detail.html</A>.
</OL>
<H2> Adding a new method of making a low-density parity-check matrix </H2>
<P>The <A HREF="pchk.html#make-ldpc"><B>make-ldpc</B></A> program can be
changed to add a new method for generating a LDPC code by modifying
<A HREF="make-ldpc.c"><TT>make-ldpc.c</TT></A>. A radically different
method might better be implemented by writing a new program of similar
structure.
<H2> Adding a new encoding method </H2>
<P>A new heuristic for finding a sparse LU decomposition can be
implemented by changing <A HREF="make-gen.c">make-gen.c</A> to allow
the new heuristic to be specified on the command line, changing the <A
HREF="mod2sparse.html#decomp"><B>mod2sparse_decomp</B></A> procedure
in <A HREF="mod2sparse.c"><TT>mod2sparse.c</TT></A> to implement the
heuristic, and documenting the new heuristic in <A
HREF="encoding.html">encoding.html</A>, <A
HREF="sparse-LU.html">sparse-LU.html</A>, and <A
HREF="mod2sparse.html">mod2sparse.html</A>.
<P>To implement a completely new encoding method, you will first need
to define a new file format for a generator matrix, modify <A
HREF="make-gen.c">make-gen.c</A> appropriately to write out this new
format, and modify the <TT>read_gen</TT> procedure in <A
HREF="rcode.c"><TT>rcode.c</TT></A> to read this format. You will
need to implement the new method in a procedure in <A
HREF="enc.c">enc.c</A>, and modify <A HREF="encode.c">encode.c</A> so
that it will call this new procedure when the new method is used. The
<TT>enum_decode</TT> procedure in <A HREF="dec.c">dec.c</A> will also
need to be modified so it can call the new encoding method. Finally,
you should document the new method in <A
HREF="encoding.html">encoding.html</A>
<P>
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,89 +0,0 @@
<HTML><HEAD>
<TITLE> Modules Used in LDPC Programs </TITLE>
</HEAD><BODY>
<H1> Modules Used in LDPC Programs </H1>
You may need to familiarize yourself with the modules documented here
in order to <A HREF="modify.html">modify the LDPC programs</A>.
These modules may also be useful for other purposes.
<P>Click on the title of a module below for general information, or on
specific routines for detailed documentation.
<P><A HREF="mod2dense.html">Dense modulo-2 matrix routines</A>:
<BLOCKQUOTE><PRE>
<A HREF="mod2dense.html#dimension-sec"><I>Dimension macros:</I> mod2dense_rows mod2dense_cols</A>
<I><A HREF="mod2dense.html#alloc-sec">Allocation:</A> <A HREF="mod2dense.html#copy-clear-sec">Copy/Clear:</A> <A HREF="mod2dense.html#input-output-sec">Input/Output:</A> <A HREF="mod2dense.html#elementary-sec">Elementary ops:</A></I>
<A HREF="mod2dense.html#allocate">mod2dense_allocate</A> <A HREF="mod2dense.html#clear">mod2dense_clear</A> <A HREF="mod2dense.html#print">mod2dense_print</A> <A HREF="mod2dense.html#get">mod2dense_get</A>
<A HREF="mod2dense.html#free">mod2dense_free</A> <A HREF="mod2dense.html#copy">mod2dense_copy</A> <A HREF="mod2dense.html#write">mod2dense_write</A> <A HREF="mod2dense.html#set">mod2dense_set</A>
<A HREF="mod2dense.html#copyrows">mod2dense_copyrows</A> <A HREF="mod2dense.html#read">mod2dense_read</A> <A HREF="mod2dense.html#flip">mod2dense_flip</A>
<A HREF="mod2dense.html#copycols">mod2dense_copycols</A>
<I><A HREF="mod2dense.html#arith-sec">Matrix arithmetic:</A> <A HREF="mod2dense.html#invert-sec">Matrix inversion:</A></I>
<A HREF="mod2dense.html#transpose">mod2dense_transpose</A> <A HREF="mod2dense.html#invert">mod2dense_invert</A>
<A HREF="mod2dense.html#add">mod2dense_add</A> <A HREF="mod2dense.html#forcibly_invert">mod2dense_forcibly_invert</A>
<A HREF="mod2dense.html#multiply">mod2dense_multiply</A> <A HREF="mod2dense.html#invert_selected">mod2dense_invert_selected</A>
<A HREF="mod2dense.html#equal">mod2dense_equal</A>
</PRE></BLOCKQUOTE>
<P><A HREF="mod2sparse.html">Sparse modulo-2 matrix routines</A>:
<BLOCKQUOTE><PRE>
<A HREF="mod2sparse.html#dimension-sec"><I>Dimension macros:</I> mod2sparse_rows mod2sparse_cols</A>
<A HREF="mod2sparse.html#traversal-sec"><I>Traversal macros:</I> mod2sparse_first_in_row mod2sparse_next_in_row ...</A>
<I><A HREF="mod2sparse.html#alloc-sec">Allocation:</A> <A HREF="mod2sparse.html#copy-clear-sec">Copy/Clear:</A> <A HREF="mod2sparse.html#input-output-sec">Input/Output:</A> <A HREF="mod2sparse.html#elementary-sec">Elementary ops:</A></I>
<A HREF="mod2sparse.html#allocate">mod2sparse_allocate</A> <A HREF="mod2sparse.html#clear">mod2sparse_clear</A> <A HREF="mod2sparse.html#print">mod2sparse_print</A> <A HREF="mod2sparse.html#find">mod2sparse_find</A>
<A HREF="mod2sparse.html#free">mod2sparse_free</A> <A HREF="mod2sparse.html#copy">mod2sparse_copy</A> <A HREF="mod2sparse.html#write">mod2sparse_write</A> <A HREF="mod2sparse.html#insert">mod2sparse_insert</A>
<A HREF="mod2sparse.html#copyrows">mod2sparse_copyrows</A> <A HREF="mod2sparse.html#read">mod2sparse_read</A> <A HREF="mod2sparse.html#delete">mod2sparse_delete</A>
<A HREF="mod2sparse.html#copycols">mod2sparse_copycols</A>
<I><A HREF="mod2sparse.html#arith-sec">Matrix arithmetic:</A> <A HREF="mod2sparse.html#row-col-ops-sec">Row/Column ops:</A> <A HREF="mod2sparse.html#lu-decomp-sec">LU decomposition:</A></I>
<A HREF="mod2sparse.html#transpose">mod2sparse_transpose</A> <A HREF="mod2sparse.html#count_row">mod2sparse_count_row</A> <A HREF="mod2sparse.html#decomp">mod2sparse_decomp</A>
<A HREF="mod2sparse.html#add">mod2sparse_add</A> <A HREF="mod2sparse.html#count_col">mod2sparse_count_col</A> <A HREF="mod2sparse.html#forward_sub">mod2sparse_forward_sub</A>
<A HREF="mod2sparse.html#multiply">mod2sparse_multiply</A> <A HREF="mod2sparse.html#add_row">mod2sparse_add_row</A> <A HREF="mod2sparse.html#backward_sub">mod2sparse_backward_sub</A>
<A HREF="mod2sparse.html#mulvec">mod2sparse_mulvec</A> <A HREF="mod2sparse.html#add_col">mod2sparse_add_col</A>
<A HREF="mod2sparse.html#equal">mod2sparse_equal</A>
</PRE>
<A HREF="sparse-LU.html">Discussion of sparse LU decomposition methods.</A>
</BLOCKQUOTE>
<P><A HREF="mod2convert.html">Modulo-2 matrix sparse/dense conversion</A>:
<BLOCKQUOTE><PRE>
<A HREF="mod2convert.html#sparse_to_dense">mod2sparse_to_dense</A>
<A HREF="mod2convert.html#dense_to_sparse">mod2dense_to_sparse</A>
</PRE></BLOCKQUOTE>
<P><A HREF="rand.html">Random variate generation routines</A>:
<BLOCKQUOTE><PRE>
<I><A HREF="rand.html#get-set-sec">Set/Get state:<A> <A HREF="rand.html#uniform-sec">Uniform:</A> <A HREF="rand.html#discrete-sec">Discrete:</A> <A HREF="rand.html#continuous-sec">Continuous:</A></I>
<A HREF="rand.html#seed">rand_seed</A> <A HREF="rand.html#uniform">rand_uniform</A> <A HREF="rand.html#int">rand_int</A> <A HREF="rand.html#gaussian">rand_gaussian</A>
<A HREF="rand.html#get_state">rand_get_state</A> <A HREF="rand.html#uniopen">rand_uniopen</A> <A HREF="rand.html#pickd">rand_pickd</A> <A HREF="rand.html#logistic">rand_logistic</A>
<A HREF="rand.html#use_state">rand_use_state</A> <A HREF="rand.html#pickf">rand_pickf</A> <A HREF="rand.html#cauchy">rand_cauchy</A>
<A HREF="rand.html#poisson">rand_poisson</A> <A HREF="rand.html#gamma">rand_gamma</A>
<A HREF="rand.html#permutation">rand_permutation</A> <A HREF="rand.html#exp">rand_exp</A>
<A HREF="rand.html#beta">rand_beta</A>
</PRE></BLOCKQUOTE>
<P>Each of the modules above has a test program, called
<TT><I>module</I>-test</TT>. These programs are compiled by the command
<BLOCKQUOTE><PRE>
make tests
</PRE></BLOCKQUOTE>
See the source files for these test programs for further information.
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,76 +0,0 @@
program msksim
use, intrinsic :: iso_c_binding
! To change to a new code, edit the following line and the filenames
! that contain the parity check and generator matrices.
parameter (N=198, M=126, K=72) ! M and N are global variables on the C side.
character(50) pchk_file,gen_file
integer(1) codeword(1:N), decoded(1:K), message(1:K)
real*8 lratio(N), rxdata(N)
pchk_file="./jtmode_codes/peg-198-72-irreg-8x3-2x4.pchk"
gen_file="./jtmode_codes/peg-198-72-irreg-8x3-2x4.gen"
rate=real(K)/real(N)
call init_ldpc(trim(pchk_file)//char(0),trim(gen_file)//char(0))
message(1:K/2)=1
message((K/2+1):K)=0
call ldpc_encode(message,codeword)
max_iterations=50
ntrials=1000000
write(*,*) "Eb/N0 ngood nundetected"
do idb = 0, 11
db=idb/2.0-0.5
sigma=1/sqrt( 2*rate*(10**(db/10.0)) )
ngood=0
nue=0
do itrial=1, ntrials
do i=1,N
rxdata(i) = 2.0*(codeword(i)-0.5) + sigma*gran()
enddo
! correct signal normalization is important for this decoder.
rxav=sum(rxdata)/N
rx2av=sum(rxdata*rxdata)/N
rxsig=sqrt(rx2av-rxav*rxav)
rxdata=rxdata/rxsig
! s can be tuned to trade a few tenth's dB of threshold
! for an order of magnitude in UER
do i=1,N
s=0.75
lratio(i)=exp(2.0*rxdata(i)/(s*s))
enddo
call ldpc_decode(lratio, decoded, max_iterations, niterations)
if( niterations .ge. 0 ) then
nueflag=0
do i=1,K
if( message(i) .ne. decoded(i) ) then
nueflag=1
endif
enddo
if( nueflag .eq. 1 ) then
nue=nue+1
else
ngood=ngood+1;
endif
endif
enddo
write(*,"(f4.1,1x,i8,1x,i8)") db,ngood,nue
enddo
end program msksim

View File

@ -1,50 +0,0 @@
/* OPEN.C - Routine for opening file that might be stdin/stdout. */
/* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "open.h"
/* OPEN A FILE THAT MIGHT BE STANDARD INPUT OR OUTPUT. If the file name
given is "-", this procedure just returns stdin or stdout, depending on
whether the mode is for reading or writing. Otherwise, fopen is called.
*/
FILE *open_file_std
( char *fname, /* Name of file to open, or "-" for stdin/stdout */
char *mode /* Mode for opening: eg, "r" or "w" */
)
{
if (strcmp(fname,"-")==0)
{ switch (mode[0])
{ case 'r':
{ return stdin;
}
case 'w':
{ return stdout;
}
default:
{ fprintf(stderr,"Bad mode passed to open_file_std: %s\n",mode);
exit(1);
}
}
}
else
{ return fopen(fname,mode);
}
}

View File

@ -1,16 +0,0 @@
/* OPEN.H - Interface to routine for opening file that might be stdin/stdout. */
/* 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.
*/
FILE *open_file_std (char *, char *);

View File

@ -1,166 +0,0 @@
/* ALIST-TO-PCHK.C - Convert a parity check matrix to alist format. */
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "alloc.h"
#include "open.h"
#include "mod2sparse.h"
#include "mod2dense.h"
#include "mod2convert.h"
#include "rcode.h"
void usage(void);
/* MAIN PROGRAM. */
int main
( int argc,
char **argv
)
{
char *alist_file, *pchk_file;
FILE *af, *pf;
int mxrw, mxcw;
int *rw, *cw;
int i, j, k;
mod2entry *e;
int trans;
int nozeros;
int last;
trans = 0;
nozeros = 0;
for (;;)
{
if (argc>1 && strcmp(argv[1],"-t")==0)
{ trans = 1;
argc -= 1;
argv += 1;
}
else if (argc>1 && strcmp(argv[1],"-z")==0)
{ nozeros = 1;
argc -= 1;
argv += 1;
}
else
{ break;
}
}
if (argc!=3)
{ usage();
}
pchk_file = argv[1];
alist_file = argv[2];
read_pchk(pchk_file);
if (trans)
{ mod2sparse *HT;
HT = H;
H = mod2sparse_allocate(N,M);
mod2sparse_transpose(HT,H);
M = mod2sparse_rows(H);
N = mod2sparse_cols(H);
}
af = open_file_std(alist_file,"wb");
if (af==NULL)
{ fprintf(stderr,"Can't create alist file: %s\n",alist_file);
exit(1);
}
fprintf(af,"%d %d\n",M,N);
rw = (int *) chk_alloc (M, sizeof *rw);
mxrw = 0;
for (i = 0; i<M; i++)
{ rw[i] = mod2sparse_count_row(H,i);
if (rw[i]>mxrw)
{ mxrw = rw[i];
}
}
cw = (int *) chk_alloc (N, sizeof *cw);
mxcw = 0;
for (j = 0; j<N; j++)
{ cw[j] = mod2sparse_count_col(H,j);
if (cw[j]>mxcw)
{ mxcw = cw[j];
}
}
fprintf(af,"%d %d\n",mxrw,mxcw);
for (i = 0; i<M; i++)
{ fprintf(af,"%d%c",rw[i],i==M-1?'\n':' ');
}
for (j = 0; j<N; j++)
{ fprintf(af,"%d%c",cw[j],j==N-1?'\n':' ');
}
for (i = 0; i<M; i++)
{ e = mod2sparse_first_in_row(H,i);
last = 0;
for (k = 0; !last; k++)
{ last = nozeros ? k==rw[i]-1 : k==mxrw-1;
fprintf (af, "%d%c", mod2sparse_at_end(e)?0:mod2sparse_col(e)+1,
last?'\n':' ');
if (!mod2sparse_at_end(e))
{ e = mod2sparse_next_in_row(e);
}
}
}
for (j = 0; j<N; j++)
{ e = mod2sparse_first_in_col(H,j);
last = 0;
for (k = 0; !last; k++)
{ last = nozeros ? k==cw[j]-1 : k==mxcw-1;
fprintf (af, "%d%c", mod2sparse_at_end(e)?0:mod2sparse_row(e)+1,
last?'\n':' ');
if (!mod2sparse_at_end(e))
{ e = mod2sparse_next_in_col(e);
}
}
}
if (ferror(af) || fclose(af)!=0)
{ fprintf(stderr,"Error writing to alist file %s\n",alist_file);
exit(1);
}
return 0;
}
/* PRINT USAGE MESSAGE AND EXIT. */
void usage(void)
{ fprintf(stderr,"Usage: pchk-to-alist [ -t ] [ -z ] pchk-file alist-file\n");
exit(1);
}

View File

@ -1,371 +0,0 @@
<HTML><HEAD>
<TITLE> Creating a Parity Check Matrix </TITLE>
</HEAD><BODY>
<H1> Creating a Parity Check Matrix </H1>
<P>This software deals only with linear block codes for binary (ie,
modulo-2, GF(2)) vectors. The set of valid codewords for a linear
code can be specified by giving a <I>parity check matrix</I>,
<B>H</B>, with <I>M</I> rows and <I>N</I> columns. The valid
codewords are the vectors, <B>x</B>, of length <I>N</I>, for which
<B>Hx</B>=<B>0</B>, where all arithmetic is done modulo-2. Each row
of <B>H</B> represents a parity check on a subset of the bits in
<B>x</B>; all these parity checks must be satisfied for <B>x</B> to be
a codeword. Note that the parity check matrix for a given code (ie,
for a given set of valid codewords) is not unique, even after
eliminating rows of <B>H</B> that are redundant because they are
linear combinations of other rows.
<P>This software stores parity check matrices in files in a sparse
format. These parity-check files are <I>not</I> human-readable
(except by using the <A HREF="#print-pchk"><TT>print-pchk</TT></A>
program). However, they <I>are</I> readable on a machine with a
different architecture than they were written on.
<P>Some LDPC software by David MacKay and others uses the
<A HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
format</A> for parity check matrices. Two programs for converting
between this format and the format for sparse parity check matrices
used by this software are provided.
<A NAME="ldpc"><H2>Methods for constructing LDPC codes</H2></A>
<P>This software is primarily intended for experimentation with Low
Density Parity Check (LDPC) codes. These codes can be constructed by
various methods, which generally involve some random selection of
where to put 1s in a parity check matrix. Any such method for
constructing LDPC codes will have the property that it produces parity
check matrices in which the number of 1s in a column is approximately
the same (perhaps on average) for any size parity check matrix. For a
given code rate, these matrices therefore become increasingly sparse
as the length of a codeword, and hence the number of parity checks,
increases.
<P>Many methods for constructing LDPC matrices are described in the
<A HREF="refs.html">references</A>. Two simple methods are currently
implemented by this software, both of which operate according to the
following scheme:
<OL>
<LI> Create a preliminary parity check matrix by one of the methods.
<LI> Add 1s to the parity check matrix in order to avoid rows that have no
1s in them, and hence are redundant, or which have only one 1 in them,
in which case the corresponding codeword bits will always be zero.
The places within such a row to add these 1s are selected randomly.
<LI> If the preliminary parity check matrix constructed in step (1) had
an even number of 1s in each column, add further 1s to avoid the problem
that this will cause the rows to add to zero, and hence at least
one check will be redundant. Up to two 1s are added (since it is also
undesirable for the sum of the rows to have only one 1 in it), at
positions selected randomly from the entire matrix. However, the
number of 1s to add in this step is reduced by the number already added
in step (2). (Note that although redundant checks are not disastrous,
they are better avoided; see the discussion of <A HREF="dep-H.html">linear
dependence in parity check matrices</A>.)
<LI> If requested, try to eliminate
situations where a pair of columns both have 1s in a particular pair of
rows, which correspond to cycles of length four in the factor graph of
the parity check matrix. When such a situation is detected, one of the
1s involved is moved randomly within its column. This continues until
no such situations remain, or until 10 passes over all columns have
failed to eliminate all such situations.
</OL>
<P>The <I>evencol</I> method is the simplest way of performing step
(1) of the above procedure. For each column of the parity check
matrix, independently, it places a specified number of 1s in positions
selected uniformly at random, with the only constraint being that
these 1s be in distinct rows. Note that despite the name, the columns
do not have to have the same number of 1s - a distribution over
several values for the number of 1s in a column can be specified
instead. Such codes with different-weight columns are sometimes
better than codes in which every column has the same weight.
<P>The <I>evenboth</I> method also puts a specified number of 1s in
each column, but it tries as well to keep the numbers of 1s in the
rows approximately the same. Initially, it creates indicators for all
the 1s that will be required, and assigns these 1s to rows as evenly
as it can, favouring earlier rows if an exactly even split is not
possible. It then assigns 1s to successive columns by selecting
randomly, without replacement, from this initial supply of 1s, subject
only to the constraint that the 1s assigned to a column must be in
distinct rows. If at some point it is impossible to put the required
number of 1s in a column by picking from the 1s remaining, a 1 is set
in that column without reference to other columns, creating a possible
unevenness.
<P>Note that regardless of how evenly 1s are distributed in the
preliminary parity check matrix created in step (1), steps (2) and (3)
can make the numbers of 1s in the both rows and columns be uneven, and
step (4), if done, can make the numbers of 1s in rows be uneven.
<P><A NAME="make-pchk"><HR><B>make-pchk</B>: Make a parity check
matrix by explicit specification.
<BLOCKQUOTE><PRE>
make-pchk <I>pchk-file n-checks n-bits row</I>:<I>col ...</I>
</PRE></BLOCKQUOTE>
<P>Creates a file named <TT><I>pchk-file</I></TT> in
which it stores a parity check matrix with <TT><I>n-checks</I></TT>
rows and <TT><I>n-bits</I></TT> columns. This parity check matrix
consists of all 0s except for 1s at the <I>row</I>:<I>col</I>
positions listed. Rows and columns are numbered starting at zero.
This program is intended primarily for testing and demonstration
purposes.
<P><B>Example:</B> The well-known Hamming code with codewords of
length <I>N</I>=7 and with <I>M</I>=3 parity checks can be can be
created as follows:
<UL><PRE>
<LI>make-pchk ham7.pchk 3 7 0:0 0:3 0:4 0:5 1:1 1:3 1:4 1:6 2:2 2:4 2:5 2:6
</PRE></UL>
<P><A NAME="alist-to-pchk"><HR><B>alist-to-pchk</B>: Convert a parity
check matrix from alist format to the sparse matrix format used by
this software.
<BLOCKQUOTE><PRE>
alist-to-pchk [ -t ] <I>alist-file pchk-file</I>
</PRE></BLOCKQUOTE>
<P>Converts a parity check matrix in
<A HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
format</A> stored in the file named <TT><I>alist-file</I></TT> to
the sparse matrix format used by this software, storing it in the
file named <TT><I>pchk-file</I></TT>.
<P>If the <B>-t</B> option is given, the transpose of the parity check
matrix in <TT><I>alist-file</I></TT> is stored in the
<TT><I>pchk-file</I></TT>.
<P>Any zeros indexes in the alist file are ignored, so that alist files
with zero padding (as required in the specification) are accepted,
but files without this zero padding are also accepted. Newlines
are ignored by <TT>alist-to-pchk</TT>, so no error is reported if
the set of indexes in a row or column description are not those
on a single line.
<P><A NAME="pchk-to-alist"><HR><B>pchk-to-alist</B>: Convert a parity
check matrix to alist format.
<BLOCKQUOTE><PRE>
pchk-to-alist [ -t ] [ -z ] <I>pchk-file alist-file</I>
</PRE></BLOCKQUOTE>
<P>Converts a parity check matrix stored in the sparse matrix format
used by this software, in the file named <TT><I>pchk-file</I></TT>, to
the <A
HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
format</A>, storing it in the file named <TT><I>alist-file</I></TT>.
<P>If the <B>-t</B> option is given, the transpose of the parity check
matrix is converted to alist format.
<P>If the number of 1s is not
the same for each row or each column, the alist format specification
says that the list of indexes of 1s for each row or column should
be padded with zeros to the maximum number of indexes. By default,
<TT>pchk-to-alist</TT> does this, but output of these 0s can be
suppressed by specifying the <B>-z</B> option. (The <TT>alist-to-pchk</TT>
program will accept alist files produced with or without the <B>-z</B>
option.)
<P><A NAME="print-pchk"><HR><B>print-pchk</B>: Print a parity check matrix.
<BLOCKQUOTE><PRE>
print-pchk [ -d ] [ -t ] <I>pchk-file</I>
</PRE></BLOCKQUOTE>
<P>Prints a human-readable representation of the parity check matrix stored
in <TT><I>pchk-file</I></TT>.
The <B>-d</B> option causes the matrix to be printed in a dense
format, even though parity check matrices are always stored in the
file in a sparse format. If the <B>-t</B> option is present, what is
printed is the transpose of the parity check matrix.
<P>The sparse display format consists of one line for every row of the
matrix, consisting of the row number, a colon, and the column numbers
at which 1s are located (possibly none). Row and columns numbers
start at zero. No attempt is made to wrap long lines.
<P>The dense display is the obvious array of 0s and 1s. Long lines
are not wrapped.
<P><B>Example</B>: The parity check matrix for the Hamming code created
by the example for <A HREF="#make-pchk"><TT>make-pchk</TT></A> would print
as follows:
<UL><PRE>
<LI>print-pchk ham7.pchk
Parity check matrix in ham7.pchk (sparse format):
0: 0 3 4 5
1: 1 3 4 6
2: 2 4 5 6
<LI>print-pchk -d ham7.pchk
Parity check matrix in ham7.pchk (dense format):
1 0 0 1 1 1 0
0 1 0 1 1 0 1
0 0 1 0 1 1 1
</PRE></UL>
<P><A NAME="make-ldpc"><HR><B>make-ldpc</B>: Make a low density parity
check matrix, by random generation.
<BLOCKQUOTE><PRE>
make-ldpc <I>pchk-file n-checks n-bits seed method</I>
</PRE>
<BLOCKQUOTE>
where <TT><I>method</I></TT> is one of the following:
<BLOCKQUOTE><PRE>
evencol <I>checks-per-col</I> [ no4cycle ]
evencol <I>checks-distribution</I> [ no4cycle ]
evenboth <I>checks-per-col</I> [ no4cycle ]
evenboth <I>checks-distribution</I> [ no4cycle ]
</PRE></BLOCKQUOTE>
</BLOCKQUOTE>
</BLOCKQUOTE>
<P>Creates a Low Density Parity Check matrix with
<TT><I>n-checks</I></TT> rows and <TT><I>n-bits</I></TT> columns. The
parity check matrix will be generated pseudo-randomly by the indicated
method, using a pseudo-random number stream determined by <TT><I>seed</I></TT>.
The actual random number seed used is 10 times <TT><I>seed</I></TT> plus 1,
so as to avoid using the same stream as any of the other programs.
<P>Two methods are currently available for creating the LDPC matrix,
specified by <TT>evencol</TT> or <TT>evenboth</TT>. Both methods
produce a matrix in which the number of 1s in each column is
approximately <TT><I>checks-per-col</I></TT>, or varies from column
to column according the the <TT><I>checks-distribution</I></TT>.
The <TT>evenboth</TT> method also tries to make the number of checks per row be
approximately uniform; if this is not achieved, a message saying that
how many bits were placed unevenly is displayed on standard error.
<P>For both methods, the <TT>no4cycle</TT> option will cause cycles of
length four in the factor graph representation of the code to be
eliminated (if possible). A message is displayed on standard error if
this is not achieved.
<P>A <TT><I>checks-distribution</I></TT> has the form
<BLOCKQUOTE><PRE>
<I>prop</I>x<I>count</I>/<I>prop</I>x<I>count</I>/...
</PRE></BLOCKQUOTE>
Here, <TT><I>prop</I></TT> is a proportion of columns that have the
associated <TT><I>count</I></TT>. The proportions need not sum to one,
since they will be automatically normalized. For example, <TT>0.3x4/0.2x5</TT>
specifies that 60% of the columns will contain four 1s and 40% will
contain five 1s.
<P>See the <A HREF="#ldpc">discussion above</A> for more details
on how these methods construct LDPC matrices.
<P><B>Example 1:</B> The <TT>make-ldpc</TT> command below creates
a 20 by 40 low density parity check matrix with three 1s per
column and six 1s per row, using random seed 1. The matrix
is then printed in sparse format
using <A HREF="#print-pchk">print-pchk</A>.
<UL><PRE>
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 3
<LI>print-pchk ldpc.pchk
Parity check matrix in ldpc.pchk (sparse format):
0: 10 14 18 27 38 39
1: 2 3 5 11 27 30
2: 15 19 20 21 24 26
3: 2 4 25 28 32 38
4: 7 9 12 22 33 34
5: 5 6 21 22 26 32
6: 1 4 13 24 25 28
7: 1 14 28 29 30 36
8: 11 13 22 23 32 37
9: 6 8 13 20 31 33
10: 0 3 24 29 31 38
11: 7 12 15 16 17 23
12: 3 16 29 34 35 39
13: 0 8 10 18 36 37
14: 6 11 18 20 35 39
15: 0 7 14 16 25 37
16: 2 4 9 19 30 31
17: 5 9 10 17 19 23
18: 8 15 17 21 26 27
19: 1 12 33 34 35 36
</PRE></UL>
<P><B>Example 2:</B> The two <TT>make-ldpc</TT> commands
below both create a 20 by 40 low density parity check matrix with 30%
of columns with two 1s, 60% of columns with three 1s, and 10% of
columns with seven 1s. The transpose of the parity check matrix
is then printed in sparse format.
<UL><PRE>
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 0.3x2/0.6x3/0.1x7
<LI>make-ldpc ldpc.pchk 20 40 1 evenboth 3x2/6x3/1x7
<LI>print-pchk -t ldpc.pchk
Transpose of parity check matrix in ldpc.pchk (sparse format):
0: 13 16
1: 9 18
2: 1 10
3: 3 15
4: 4 14
5: 14 17
6: 4 5
7: 1 8
8: 0 4
9: 9 14
10: 5 8
11: 6 16
12: 2 12 19
13: 3 17 18
14: 2 16 17
15: 2 11 18
16: 12 13 19
17: 7 13 18
18: 2 5 11
19: 10 12 14
20: 1 8 16
21: 10 18 19
22: 3 6 17
23: 7 11 12
24: 1 2 19
25: 0 6 7
26: 5 8 15
27: 1 4 7
28: 6 13 19
29: 3 4 11
30: 3 8 17
31: 4 5 9
32: 0 10 15
33: 7 11 13
34: 8 12 19
35: 0 2 10
36: 0 5 9 11 15 17 18
37: 0 1 2 6 7 14 16
38: 0 1 3 9 12 13 15
39: 3 6 9 10 14 15 16
</PRE></UL>
<HR>
<A HREF="index.html">Back to index for LDPC software</A>
</BODY></HTML>

View File

@ -1,4 +0,0 @@
1
4
1.0

View File

@ -1,573 +0,0 @@
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include "BigGirth.h"
#include "Random.h"
using namespace std;
NodesInGraph::NodesInGraph(void) {
connectionParityBit=NULL;
connectionSymbolBit=NULL;
}
void NodesInGraph::setNumOfConnectionSymbolBit(int deg) {
if(deg<=0) {cout<<"Wrong NodesInGraph::setNumOfConnectionSymbolBit()"<<endl;exit(-1);}
numOfConnectionSymbolBit=deg;
connectionSymbolBit=new int[deg];
}
void NodesInGraph::initConnectionParityBit(void) {
maxDegParity=10000;
numOfConnectionParityBit=0;
connectionParityBit=new int[1];//dummy memory, actually not used
}
void NodesInGraph::initConnectionParityBit(int deg) {
maxDegParity=deg;
numOfConnectionParityBit=0;
connectionParityBit=new int[1];//dummy memory, actually not used
}
NodesInGraph::~NodesInGraph(void) {
delete [] connectionParityBit;
delete [] connectionSymbolBit;
}
BigGirth::BigGirth(void) : H(NULL), verbose(true) { }
BigGirth::BigGirth(int M, int N, int *symbolDegSequence, const char *filename, int sglConcent, int tgtGirth, bool verbose_) : H(NULL), verbose(verbose_) {
int i, j, k, m, index, localDepth=100;
int *mid;
EXPAND_DEPTH=(tgtGirth-4)/2;
if(EXPAND_DEPTH<0) EXPAND_DEPTH=0;
// corresponds to depth l in the PEG paper;
// the target girth = 2*EXPAND_DEPTH+4
// if set large, then GREEDY algorithm
myrandom=new Random(); //(12345678l, 987654321lu);
this->M=M;
this->N=N;
this->filename=filename;
mid=new int[M];
localGirth=new int[N];
nodesInGraph=new NodesInGraph [N];
for(i=0;i<N;i++)
nodesInGraph[i].setNumOfConnectionSymbolBit(symbolDegSequence[i]);
j=0;
for(k=0;k<N;k++) j+=symbolDegSequence[k];
k=j/M;
for(i=0;i<M;i++) mid[i]=k;
for(i=0;i<j-k*M;i++) mid[i]++;
k=0; for(i=0;i<M;i++) k+=mid[i];
if(k!=j) {cout<<"Wrong in computing maxDegParity!"<<endl;exit(-1);}
for(i=0;i<M;i++) {
if(sglConcent==0) nodesInGraph[i].initConnectionParityBit(mid[i]);
else nodesInGraph[i].initConnectionParityBit();
}
for(k=0;k<N;k++){
m=1000000;index=-1;
for(i=0;i<M;i++){
if(nodesInGraph[i].numOfConnectionParityBit<m && nodesInGraph[i].numOfConnectionParityBit<nodesInGraph[i].maxDegParity) {
m=nodesInGraph[i].numOfConnectionParityBit;
index=i;
}
}
nodesInGraph[k].connectionSymbolBit[0]=index;//least connections of parity bit
int iter=0;
ITER:
localGirth[k]=100;
for(m=1;m<nodesInGraph[k].numOfConnectionSymbolBit;m++){
nodesInGraph[k].connectionSymbolBit[m]=selectParityConnect(k, m, localDepth);
localGirth[k]=(localGirth[k]>localDepth)?localDepth:localGirth[k];
if(k>0 && localGirth[k]<localGirth[k-1] && iter<20) {iter++; goto ITER;}
if(localGirth[k]==0 && iter<30) {iter++; goto ITER;}
}
//if((k+1)%100==0) {
if(verbose) {
cout<<"k="<<k<<" ";
for(m=0;m<nodesInGraph[k].numOfConnectionSymbolBit;m++)
cout<<nodesInGraph[k].connectionSymbolBit[m]<<" ";
cout<<"LocalGirth="<<2*localGirth[k]+4;
cout<<endl;
}
updateConnection(k);
}
if(verbose) {
cout<<"Showing the row weight distribution..."<<endl;
for(i=0;i<M;i++)
cout<<nodesInGraph[i].numOfConnectionParityBit<<" ";
cout<<endl;
}
delete [] mid;
ofstream cycleFile;
cycleFile.open("leftHandGirth.log", ios::out);
localDepth=100;
for(k=0;k<N;k++) {
if(localGirth[k]<localDepth) localDepth=localGirth[k];
if(localDepth==100) cycleFile<<"inf ";
else cycleFile<<2*localDepth+4<<" ";
}
cycleFile<<endl;
cycleFile.close();
if(verbose) {
cout<<"*************************************************************"<<endl;
cout<<" The global girth of the PEG Tanner graph :="<< 2*localDepth+4<<endl;
cout<<"*************************************************************"<<endl;
}
loadH();
}
BigGirth::~BigGirth(void) {
if(H!=NULL) {
for(int i=0;i<M;i++)
delete [] H[i];
delete [] H;
H=NULL;
}
delete [] localGirth;
delete [] nodesInGraph;
nodesInGraph=NULL;
delete myrandom;
}
int BigGirth::selectParityConnect(int kthSymbol, int mthConnection, int & cycle) {
int i, j, k, index, mincycles, numCur, cpNumCur;
int *tmp, *med;
int *current;//take note of the covering parity bits
mincycles=0;
tmp=new int[M]; med=new int[M];
numCur=mthConnection;
current=new int[mthConnection];
for(i=0;i<mthConnection;i++) current[i]=nodesInGraph[kthSymbol].connectionSymbolBit[i];
LOOP:
mincycles++;
for(i=0;i<M;i++) tmp[i]=0;
//maintain
for(i=0;i<mthConnection;i++) tmp[nodesInGraph[kthSymbol].connectionSymbolBit[i]]=1;
for(i=0;i<numCur;i++){
for(j=0;j<nodesInGraph[current[i]].numOfConnectionParityBit;j++){
for(k=0;k<nodesInGraph[nodesInGraph[current[i]].connectionParityBit[j]].numOfConnectionSymbolBit;k++){
tmp[nodesInGraph[nodesInGraph[current[i]].connectionParityBit[j]].connectionSymbolBit[k]]=1;
}
}
}
index=0; cpNumCur=0;
for(i=0;i<M;i++) {
if(tmp[i]==1) cpNumCur++;
if(tmp[i]==1 || nodesInGraph[i].numOfConnectionParityBit>=nodesInGraph[i].maxDegParity)
index++;
}
if(cpNumCur==numCur) {//can not expand any more
//additional handlement to select one having least connections
j=10000000; //dummy number
for(i=0;i<M;i++){
if(tmp[i]==0 && nodesInGraph[i].numOfConnectionParityBit<j && nodesInGraph[i].numOfConnectionParityBit<nodesInGraph[i].maxDegParity)
j=nodesInGraph[i].numOfConnectionParityBit;
}
for(i=0;i<M;i++){
if(tmp[i]==0){
if(nodesInGraph[i].numOfConnectionParityBit!=j || nodesInGraph[i].numOfConnectionParityBit>=nodesInGraph[i].maxDegParity){
tmp[i]=1;
}
}
}
index=0;
for(i=0;i<M;i++) if(tmp[i]==1) index++;
//----------------------------------------------------------------
j=(*myrandom).uniform(0, M-index)+1; //randomly selected
index=0;
for(i=0;i<M;i++){
if(tmp[i]==0) index++;
if(index==j) break;
}
delete [] tmp; tmp=NULL;
delete [] current; current=NULL;
return(i);
}
else if(index==M || mincycles>EXPAND_DEPTH){//covering all parity nodes or meet the upper bound on cycles
cycle=mincycles-1;
for(i=0;i<M;i++) tmp[i]=0;
for(i=0;i<numCur;i++) tmp[current[i]]=1;
index=0;
for(i=0;i<M;i++) if(tmp[i]==1) index++;
if(index!=numCur) {cout<<"Error in the case of (index==M)"<<endl;exit(-1);}
//additional handlement to select one having least connections
j=10000000;
for(i=0;i<M;i++){
if(tmp[i]==0 && nodesInGraph[i].numOfConnectionParityBit<j && nodesInGraph[i].numOfConnectionParityBit<nodesInGraph[i].maxDegParity)
j=nodesInGraph[i].numOfConnectionParityBit;
}
for(i=0;i<M;i++){
if(tmp[i]==0){
if(nodesInGraph[i].numOfConnectionParityBit!=j || nodesInGraph[i].numOfConnectionParityBit>=nodesInGraph[i].maxDegParity){
tmp[i]=1;
}
}
}
index=0;
for(i=0;i<M;i++) if(tmp[i]==1) index++;
j=(*myrandom).uniform(0, M-index)+1;
index=0;
for(i=0;i<M;i++){
if(tmp[i]==0) index++;
if(index==j) break;
}
delete [] tmp; tmp=NULL;
delete [] current; current=NULL;
return(i);
}
else if(cpNumCur>numCur && index!=M){
delete [] current;
current=NULL;
numCur=cpNumCur;
current=new int[numCur];
index=0;
for(i=0;i<M;i++) {
if(tmp[i]==1) {current[index]=i; index++;}
}
goto LOOP;
}
else {
cout<<"Should not come to this point..."<<endl;
cout<<"Error in BigGirth::selectParityConnect()"<<endl;
return(-1);
}
}
void BigGirth::updateConnection(int kthSymbol){
int i, j, m;
int *tmp;
for(i=0;i<nodesInGraph[kthSymbol].numOfConnectionSymbolBit;i++){
m=nodesInGraph[kthSymbol].connectionSymbolBit[i];//m [0, M) parity node
tmp=new int[nodesInGraph[m].numOfConnectionParityBit+1];
for(j=0;j<nodesInGraph[m].numOfConnectionParityBit;j++)
tmp[j]=nodesInGraph[m].connectionParityBit[j];
tmp[nodesInGraph[m].numOfConnectionParityBit]=kthSymbol;
delete [] nodesInGraph[m].connectionParityBit;
nodesInGraph[m].connectionParityBit=NULL;
nodesInGraph[m].numOfConnectionParityBit++; //increase by 1
nodesInGraph[m].connectionParityBit=new int[nodesInGraph[m].numOfConnectionParityBit];
for(j=0;j<nodesInGraph[m].numOfConnectionParityBit;j++)
nodesInGraph[m].connectionParityBit[j]=tmp[j];
delete [] tmp;
tmp=NULL;
}
}
void BigGirth::loadH(void){
int i, j;
if(H==NULL) {
H=new int*[M];
for(i=0;i<M;i++) H[i]=new int[N];
}
for(i=0;i<M;i++){
for(j=0;j<N;j++){
H[i][j]=0;
}
}
for(i=0;i<M;i++){
for(j=0;j<nodesInGraph[i].numOfConnectionParityBit;j++){
H[i][nodesInGraph[i].connectionParityBit[j]]=1;
}
}
}
void BigGirth::writeToFile_Hmatrix(void){
int i, j;
loadH();
//cout<<"---------------code format--------------------------"<<endl;
//cout<<"- Block length N -"<<endl;
//cout<<"- Num of Check Nodex M -"<<endl;
//cout<<"- H matrix -"<<endl;
//cout<<"----------------------------------------------------"<<endl;
ofstream codefile;
codefile.open(filename,ios::out);
codefile<<N<<" "<<M<<endl;
for(i=0;i<M;i++){
for(j=0;j<N;j++){
codefile<<H[i][j]<<" ";
}
codefile<<endl;
}
codefile.close();
}
void BigGirth::writeToFile_Hcompressed(void){
int i, j, max_col;
int *(*parityCheck_compressed);
//cout<<"---------------code format--------------------------"<<endl;
//cout<<"- Block length N -"<<endl;
//cout<<"- Num of Check Nodex M -"<<endl;
//cout<<"- Num of column in the compressed H -"<<endl;
//cout<<"- H matrix (compressed) -"<<endl;
//cout<<"----------------------------------------------------"<<endl;
//finding the num of columns, l, of the compressed parity-check matrix
max_col=0;
for(i=0;i<M;i++)
if(nodesInGraph[i].numOfConnectionParityBit>max_col)
max_col=nodesInGraph[i].numOfConnectionParityBit;
parityCheck_compressed=new int * [M];
for(i=0;i<M;i++)
parityCheck_compressed[i]=new int[max_col];
for(i=0;i<M;i++){
for(j=0;j<max_col;j++) parityCheck_compressed[i][j]=0;
for(j=0;j<nodesInGraph[i].numOfConnectionParityBit;j++){
parityCheck_compressed[i][j]=nodesInGraph[i].connectionParityBit[j]+1;
}
}
ofstream codefile;
codefile.open(filename,ios::out);
codefile<<N<<endl;
codefile<<M<<endl;
codefile<<max_col<<endl;
for(i=0;i<M;i++){
for(j=0;j<max_col;j++)
codefile<<parityCheck_compressed[i][j]<<" ";
codefile<<endl;
}
codefile.close();
for(i=0;i<M;i++){
delete [] parityCheck_compressed[i];
parityCheck_compressed[i]=NULL;
}
delete [] parityCheck_compressed;
parityCheck_compressed=NULL;
}
void BigGirth::writeToFile(void){
int i, j, k, d, redun;
int imed, max_row, index, max_col;
int *Index, *J, *itmp, *(*generator), *(*generator_compressed), *(*parityCheck_compressed);
//Gaussian Ellimination
Index=new int[M];
J=new int[N];
itmp=new int[N];
for(i=0;i<M;i++) Index[i]=0; //indicator of redudant rows
for(j=0;j<N;j++) J[j]=j; //column permutation
redun=0;//the number of redundant rows
loadH();
for(k=0;k<M;k++){
if(H[k][J[k-redun]]==0) {
d=k;
for(i=k+1-redun;i<N;i++)
if(H[k][J[i]]!=0) {d=i;break;}
if(d==k) {//full-zero row:delete this row
redun++;
Index[k]=1;
continue;
}
else {//SWAP d column and k column in H matrix
imed=J[k-redun];
J[k-redun]=J[d];
J[d]=imed;
}
}
if(H[k][J[k-redun]]==0) {
cout<<"ERROR: should not come to this point"<<endl;
exit(-1);
}
else {
for(i=k+1;i<M;i++){
if(H[i][J[k-redun]]!=0){
for(j=k-redun;j<N;j++)
H[i][J[j]]=(H[i][J[j]]+H[k][J[j]])%2;
}
}
}
}
if(verbose)
cout<<"Row rank of parity check matrix="<<M-redun<<endl;
K=N-M+redun;//num of the information bits
index=0;
for(i=0;i<M;i++){
if(Index[i]==0){ // all-zero row
for(j=0;j<N;j++)
itmp[j]=H[i][J[j]];
for(j=0;j<N;j++)
H[index][j]=itmp[j]; //Note: itmp can not be omitted here!!!
index++;
}
}
if(index!=M-redun) {cout<<"ERROR...if(index!=M-redun)"<<endl;exit(-1);}
for(k=index-1;k>0;k--){
for(i=k-1;i>=0;i--){
if(H[i][k]==1)
for(j=k;j<N;j++)
H[i][j]=(H[i][j]+H[k][j])%2;
}
}
if(verbose) {
cout<<"****************************************************"<<endl;
cout<<" Computing the compressed generator"<<endl;
cout<<"****************************************************"<<endl;
}
generator=new int * [K];
for(i=0;i<K;i++)
generator[i]=new int[N-K];
for(i=0;i<K;i++){
for(j=0;j<N-K;j++)
generator[i][j]=H[j][i+N-K];
//for(j=N-K;j<N;j++)
//generator[i][j]=0;
//generator[i][i+N-K]=1;
}
max_row=0;
for(j=0;j<N-K;j++){
imed=0;
for(i=0;i<K;i++)
imed+=generator[i][j];
if(imed>max_row) max_row=imed;
}
generator_compressed=new int * [max_row];
for(i=0;i<max_row;i++)
generator_compressed[i]=new int[N];
for(j=0;j<N-K;j++){
index=0;
for(i=0;i<max_row;i++) generator_compressed[i][j]=0;
for(i=0;i<K;i++){
if(generator[i][j]==1) {
generator_compressed[index][j]=i+1;
if(index>=max_row-1) break;
index++;
}
}
}
for(j=0;j<K;j++){
for(i=0;i<max_row;i++) generator_compressed[i][j+N-K]=0;
generator_compressed[0][j+N-K]=j+1;
}
if(verbose) {
cout<<"*****************************************************"<<endl;
cout<<" Computing the compressed parity-check matrix"<<endl;
cout<<"*****************************************************"<<endl;
}
//finding the num of columns, l, of the compressed parity-check matrix
loadH(); //loading parity check matrix again
max_col=0;
for(i=0;i<M;i++){
imed=0;
for(j=0;j<N;j++)
imed+=H[i][j];
if(imed>max_col) max_col=imed;
}
parityCheck_compressed=new int * [M];
for(i=0;i<M;i++)
parityCheck_compressed[i]=new int[max_col];
for(i=0;i<M;i++){
for(j=0;j<max_col;j++) parityCheck_compressed[i][j]=0;
index=0;
for(j=0;j<N;j++){
if(H[i][J[j]]==1) {
parityCheck_compressed[i][index]=j+1;
if(index>=max_col-1) break;
index++;
}
}
}
if(verbose) {
cout<<"****************************************************"<<endl;
cout<<" Write to file (TEXT!) "<<endl;
cout<<"****************************************************"<<endl;
}
ofstream codefile;
codefile.open(filename,ios::out);
codefile<<N<<endl;
codefile<<K<<endl;
codefile<<M<<endl;
codefile<<max_row<<endl;
codefile<<max_col<<endl;
for(i=0;i<max_row;i++){
for(j=0;j<N;j++)
codefile<<generator_compressed[i][j]<<" ";
codefile<<endl;
}
for(i=0;i<M;i++){
for(j=0;j<max_col;j++)
codefile<<parityCheck_compressed[i][j]<<" ";
codefile<<endl;
}
for(i=N-K;i<N;i++)
codefile<<i+1<<" ";
codefile<<endl;
codefile.close();
if(verbose) {
cout<<"****************************************************"<<endl;
cout<<" Free memory"<<endl;
cout<<"****************************************************"<<endl;
}
delete [] Index;
Index=NULL;
delete [] J;
J=NULL;
delete [] itmp;
itmp=NULL;
for(i=0;i<M;i++){
delete [] parityCheck_compressed[i];
parityCheck_compressed[i]=NULL;
}
delete [] parityCheck_compressed;
parityCheck_compressed=NULL;
for(i=0;i<max_row;i++){
delete [] generator_compressed[i];
generator_compressed[i]=NULL;
}
delete [] generator_compressed;
generator_compressed=NULL;
for(i=0;i<K;i++){
delete [] generator[i];
generator[i]=NULL;
}
delete [] generator;
generator=NULL;
if(verbose) {
cout<<"****************************************************"<<endl;
cout<<" OK!"<<endl;
cout<<"****************************************************"<<endl;
}
}

View File

@ -1,54 +0,0 @@
#ifndef BIGGIRTH
#define BIGGIRTH 1
#include <cstdlib>
#include <iostream> // C++ I/O library header
#include "Random.h"
class NodesInGraph{
public:
int numOfConnectionParityBit;
int *connectionParityBit;
int numOfConnectionSymbolBit;
int *connectionSymbolBit;
int maxDegParity;
NodesInGraph(void);
~NodesInGraph(void);
void setNumOfConnectionSymbolBit(int deg);
void initConnectionParityBit(void);
void initConnectionParityBit(int deg);
};
class BigGirth {
public:
int M, N;
int K;
int EXPAND_DEPTH;
const char *filename;
int *(*H);
int *localGirth;
NodesInGraph *nodesInGraph;
Random *myrandom;
BigGirth(int m, int n, int *symbolDegSequence, const char *filename, int sglConcent, int tgtGirth, bool verbose_ = true);
BigGirth(void);
void writeToFile_Hcompressed(void);
void writeToFile_Hmatrix(void);
void writeToFile(void);
void loadH(void);
~BigGirth(void);
private:
int selectParityConnect(int kthSymbol, int mthConnection, int & cycle);
void updateConnection(int kthSymbol);
bool verbose;
};
#endif

View File

@ -1,68 +0,0 @@
64
16
48
14
5
3 1 3 6 1 4 1 1 1 1 2 1 1 1 1 6 6 2 2 1 1 2 2 1 2 6 2 6 1 1 2 1 1 6 3 2 6 2 1 1 6 1 1 2 1 1 1 7 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
4 2 4 9 3 6 2 2 3 2 4 2 3 3 3 7 9 6 4 3 2 6 6 2 4 9 6 7 2 2 4 3 3 7 4 4 7 4 3 3 7 2 2 6 3 2 2 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
6 3 6 10 4 9 4 4 4 4 5 4 4 4 4 8 10 8 5 4 3 7 7 4 6 13 9 9 4 4 5 4 4 8 6 5 8 5 4 4 9 4 4 8 4 3 4 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
7 4 12 12 6 12 5 5 6 5 6 5 5 6 6 9 11 9 6 5 4 11 9 5 7 0 10 10 5 5 6 6 5 9 8 6 11 6 5 5 11 5 5 9 6 4 5 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
9 5 16 15 9 15 6 6 7 6 7 6 6 9 7 10 12 11 8 6 5 13 13 6 8 0 11 11 6 6 9 8 6 11 11 8 12 7 6 6 13 6 6 12 10 5 6 11 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
10 6 0 16 11 16 8 7 9 8 8 7 7 12 8 11 13 13 9 11 6 14 14 8 9 0 13 12 8 9 11 9 7 12 12 10 13 8 8 7 0 8 7 15 12 6 8 12 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
13 8 0 0 13 0 10 8 13 9 10 10 9 13 9 12 14 15 11 13 7 16 16 9 13 0 15 13 10 11 16 11 11 13 16 12 14 9 11 10 0 9 11 0 13 12 9 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
15 12 0 0 14 0 11 10 15 11 12 11 10 15 11 13 15 0 13 14 12 0 0 12 14 0 0 14 14 13 0 14 13 0 0 15 0 11 12 13 0 10 12 0 15 13 10 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 13 0 0 15 0 12 12 16 12 14 14 14 16 14 14 0 0 15 15 14 0 0 13 0 0 0 15 15 15 0 15 14 0 0 16 0 13 13 14 0 12 14 0 16 14 11 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 15 0 0 16 0 14 14 0 13 15 0 16 0 16 16 0 0 16 16 15 0 0 14 0 0 0 16 0 16 0 16 16 0 0 0 0 14 15 16 0 14 15 0 0 15 12 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 16 0 0 0 0 15 15 0 15 16 0 0 0 0 0 0 0 0 0 16 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 15 16 0 0 15 0 0 0 16 13 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 9 49 58 64
2 39 50 59 0
3 6 51 57 63
4 6 52 58 0
5 20 53 57 0
4 37 48 60 0
7 36 49 59 62
8 29 55 60 0
9 14 55 60 0
10 30 56 60 0
11 31 48 61 64
12 24 48 62 0
13 40 57 61 0
1 35 48 62 0
15 32 55 63 0
16 28 56 63 0
17 28 55 64 0
18 27 56 58 0
19 31 56 61 63
5 32 56 61 0
21 43 51 59 64
22 23 57 59 0
22 44 48 58 0
12 43 58 60 63
25 38 53 59 63
26 41 55 59 0
18 44 59 60 61
17 27 50 60 62
29 42 57 60 64
8 30 48 63 0
19 38 55 62 64
15 45 48 64 0
20 33 55 63 0
34 41 56 60 0
14 45 57 58 0
11 36 55 62 0
34 37 57 62 0
7 47 57 61 0
2 46 56 62 0
33 40 58 59 0
3 35 56 59 0
10 47 58 62 0
21 46 55 61 0
23 25 52 56 64
13 39 48 64 0
26 54 57 61 0
24 42 58 61 0
16 48 54 63 0
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

View File

@ -1,237 +0,0 @@
#include "CyclesOfGraph.h"
NodesOfGraph::NodesOfGraph(void) { parityConnections=NULL;symbolConnections=NULL;
}
NodesOfGraph::~NodesOfGraph(void) {
delete [] parityConnections;
delete [] symbolConnections;
delete [] symbolMapping;
}
void NodesOfGraph::setParityConnections(int num, int *value) {
numOfParityConnections=num;
parityConnections=new int[num];
for(int i=0;i<numOfParityConnections;i++){
parityConnections[i]=value[i];
//cout<<parityConnections[i]<<" ";
}
//cout<<endl;
}
void NodesOfGraph::setSymbolConnections(int num, int *value) {
numOfSymbolConnections=num;
symbolConnections=new int[num];
for(int i=0;i<numOfSymbolConnections;i++){
symbolConnections[i]=value[i];
//cout<<symbolConnections[i]<<" ";
}
//cout<<endl;
}
void NodesOfGraph::setSymbolMapping(int num, int *value) {
numOfSymbolMapping=num;
//cout<<num<<endl;
symbolMapping=new int[num];
for(int i=0;i<numOfSymbolMapping;i++){
symbolMapping[i]=value[i];
//cout<<symbolMapping[i]<<" ";
}
//cout<<endl;
}
CyclesOfGraph::CyclesOfGraph(int mm, int n, int *(*h)){
int i, j, k, m, index;
M=mm;
N=n;
H=h;
tmp=new int [N];
med=new int [N];
tmpCycles=new int [N];
cyclesTable=new int [N];
nodesOfGraph=new NodesOfGraph [N];
//cout<<M<<" "<<N<<endl;
/*
for(i=0;i<M;i++){
for(j=0;j<N;j++)
cout<<H[i][j]<<" ";
cout<<endl;
}
*/
for(i=0;i<N;i++){
index=0;
for(j=0;j<M;j++){
if(H[j][i]==1){
tmp[index]=j;
index++;
}
}
nodesOfGraph[i].setSymbolConnections(index, tmp);
}
for(i=0;i<M;i++){
index=0;
for(j=0;j<N;j++){
if(H[i][j]==1){
tmp[index]=j;
index++;
}
}
nodesOfGraph[i].setParityConnections(index, tmp);
}
for(i=0;i<N;i++){
index=0;
for(j=0;j<nodesOfGraph[i].numOfSymbolConnections;j++){
for(k=0;k<nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;k++){
int t=0;
for(m=0;m<index;m++){
if(nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k]==tmp[m]){
t=1; break;
}
}
if(nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k]==i) t=1;
if(t==0) {
tmp[index]=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k];
index++;
}
}
}
nodesOfGraph[i].setSymbolMapping(index, tmp);
}
}
CyclesOfGraph::~CyclesOfGraph(void){
delete [] tmp;
tmp=NULL;
delete [] med;
med=NULL;
delete [] tmpCycles;
tmpCycles=NULL;
delete [] cyclesTable;
cyclesTable=NULL;
delete [] nodesOfGraph;
nodesOfGraph=NULL;
}
void CyclesOfGraph::getCyclesTable(void) {
int i, j, k, m, n, t, imed;
for(i=0;i<N;i++){
//special handlement for nodes having only one or zero connections
if(nodesOfGraph[i].numOfSymbolConnections<=1) {
cyclesTable[i]=2*N;
continue;
}
for(j=0;j<nodesOfGraph[i].numOfSymbolConnections-1;j++){ //-1 because the graph is undirected
for(k=0;k<nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;k++){
tmp[k]=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].parityConnections[k];
//cout<<tmp[k]<<" ";
}
//cout<<endl;
int cycles=2;
int index=nodesOfGraph[nodesOfGraph[i].symbolConnections[j]].numOfParityConnections;
LOOP:
imed=0;
for(k=0;k<index;k++){
if(tmp[k]==i) continue;
//cout<<"k="<<k<<" "<<tmp[k]<<endl;
for(m=0;m<nodesOfGraph[tmp[k]].numOfSymbolConnections;m++){
for(n=0;n<nodesOfGraph[i].numOfSymbolConnections;n++){
if((n!=j)&&(nodesOfGraph[tmp[k]].symbolConnections[m]==nodesOfGraph[i].symbolConnections[n])){
cycles+=2;
goto OUTLOOP;
}
}
}
for(m=0;m<nodesOfGraph[tmp[k]].numOfSymbolMapping;m++){
t=0;
for(int l=0;l<imed;l++) {
if(nodesOfGraph[tmp[k]].symbolMapping[m]==med[l]){
t=1; break;
}
}
if(t==0){
med[imed]=nodesOfGraph[tmp[k]].symbolMapping[m];
//cout<<med[imed]<<endl;
imed++;
}
}
}
index=imed;//cout<<index<<" "<<endl;
for(k=0;k<index;k++) {
tmp[k]=med[k];//cout<<tmp[k]<<" ";
}
//cout<<"j="<<j<<endl;
cycles+=2;
if(cycles>=2*N) //dead lock
goto OUTLOOP;
else
goto LOOP;
OUTLOOP:
tmpCycles[j]=cycles;
}
//for(j=0;j<nodesOfGraph[i].numOfSymbolConnections-1;j++) cout<<tmpCycles[j]<<" ";
//cout<<endl;
cyclesTable[i]=tmpCycles[0];
for(j=1;j<nodesOfGraph[i].numOfSymbolConnections-1;j++){
if(cyclesTable[i]>tmpCycles[j])
cyclesTable[i]=tmpCycles[j];
}
//OUTPUT cycles per symbol node
//cout<<"i="<<i<<" "<<cyclesTable[i]<<endl;
}
}
int CyclesOfGraph::girth(void) {
int girth=2*N;
for(int i=0;i<N;i++)
if(girth>cyclesTable[i]) girth=cyclesTable[i];
return(girth);
}
void CyclesOfGraph::printCyclesTable(void){
using namespace std;
int i, temp[20];
/*
for(i=0;i<N;i++)
cout<<cyclesTable[i]<<" ";
cout<<endl;
*/
for(i=0;i<20;i++) temp[i]=0;
for(i=0;i<N;i++){
if(cyclesTable[i]==4) temp[0]++;
else if(cyclesTable[i]==6) temp[1]++;
else if(cyclesTable[i]==8) temp[2]++;
else if(cyclesTable[i]==10) temp[3]++;
else if(cyclesTable[i]==12) temp[4]++;
else if(cyclesTable[i]==14) temp[5]++;
else if(cyclesTable[i]==16) temp[6]++;
else if(cyclesTable[i]==18) temp[7]++;
else if(cyclesTable[i]==20) temp[8]++;
else if(cyclesTable[i]==22) temp[9]++;
else if(cyclesTable[i]==24) temp[10]++;
else if(cyclesTable[i]==26) temp[11]++;
else if(cyclesTable[i]==28) temp[12]++;
else if(cyclesTable[i]==30) temp[13]++;
else {
cout<<"Wrong cycles calculation "<<cyclesTable[i]<<endl;
exit(-1);
}
}
cout<<endl;
cout<<"Num of Nodes with local girth 4: "<< temp[0]<<endl;
cout<<"Num of Nodes with local girth 6: "<< temp[1]<<endl;
cout<<"Num of Nodes with local girth 8: "<< temp[2]<<endl;
cout<<"Num of Nodes with local girth 10: "<< temp[3]<<endl;
cout<<"Num of Nodes with local girth 12: "<< temp[4]<<endl;
cout<<"Num of Nodes with local girth 14: "<< temp[5]<<endl;
cout<<"Num of Nodes with local girth 16: "<< temp[6]<<endl;
cout<<"Num of Nodes with local girth 18: "<< temp[7]<<endl;
cout<<"Num of Nodes with local girth 20: "<< temp[8]<<endl;
cout<<"Num of Nodes with local girth 22: "<< temp[9]<<endl;
cout<<"Num of Nodes with local girth 24: "<< temp[10]<<endl;
cout<<"Num of Nodes with local girth 26: "<< temp[11]<<endl;
cout<<"Num of Nodes with local girth 28: "<< temp[12]<<endl;
cout<<"Num of Nodes with local girth 30: "<< temp[13]<<endl;
}

View File

@ -1,40 +0,0 @@
#ifndef CYCLESOFGRAPH
#define CYCLESOFGRAPH 1
#include <cstdlib>
#include <iostream> // C++ I/O library header
//#include <iomanip.h>
class NodesOfGraph{
public:
int numOfParityConnections;
int *parityConnections;
int numOfSymbolConnections;
int *symbolConnections;
int numOfSymbolMapping;
int *symbolMapping;
NodesOfGraph(void);
~NodesOfGraph(void);
void setParityConnections(int num, int *value);
void setSymbolConnections(int num, int *value);
void setSymbolMapping(int num, int *values);
}; //Why this is necessary?
class CyclesOfGraph {
public:
int M, N;
int *(*H);
int *cyclesTable;
NodesOfGraph *nodesOfGraph;
CyclesOfGraph(int mm, int n, int *(*h));
~CyclesOfGraph(void);
void getCyclesTable(void);
void printCyclesTable(void);
int girth(void);
private:
int *tmp, *med, *tmpCycles;
};
#endif

View File

@ -1,3 +0,0 @@
4
2 3 4 11
0.450013 0.370771 0.0307238 0.1484922

View File

@ -1,3 +0,0 @@
7
2 3 4 5 7 14 15
0.477081 0.280572 0.0349963 0.0963301 0.0090884 0.00137443 0.10055777

View File

@ -1,4 +0,0 @@
9
2 3 4 6 7 8 9 19 20
0.457827 0.323775 0.0214226 0.0592851 0.0389015 0.0248109 0.00884569
0.0176697 0.04746251

Some files were not shown because too many files have changed in this diff Show More