mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-04-05 06:35:33 -04:00
Add ldpc sandbox folder.
git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6437 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
bef405970f
commit
5ac886855d
15
lib/ldpc/COPYRIGHT
Executable file
15
lib/ldpc/COPYRIGHT
Executable file
@ -0,0 +1,15 @@
|
||||
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.
|
||||
28
lib/ldpc/LDPC-install
Executable file
28
lib/ldpc/LDPC-install
Executable file
@ -0,0 +1,28 @@
|
||||
#!/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
|
||||
463
lib/ldpc/LGPL
Executable file
463
lib/ldpc/LGPL
Executable file
@ -0,0 +1,463 @@
|
||||
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
|
||||
116
lib/ldpc/Makefile
Executable file
116
lib/ldpc/Makefile
Executable file
@ -0,0 +1,116 @@
|
||||
# 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
|
||||
6
lib/ldpc/README
Executable file
6
lib/ldpc/README
Executable file
@ -0,0 +1,6 @@
|
||||
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.
|
||||
168
lib/ldpc/alist-to-pchk.c
Executable file
168
lib/ldpc/alist-to-pchk.c
Executable file
@ -0,0 +1,168 @@
|
||||
/* 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);
|
||||
}
|
||||
42
lib/ldpc/alloc.c
Executable file
42
lib/ldpc/alloc.c
Executable file
@ -0,0 +1,42 @@
|
||||
/* 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;
|
||||
}
|
||||
18
lib/ldpc/alloc.h
Executable file
18
lib/ldpc/alloc.h
Executable file
@ -0,0 +1,18 @@
|
||||
/* 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 */
|
||||
85
lib/ldpc/blockio.c
Executable file
85
lib/ldpc/blockio.c
Executable file
@ -0,0 +1,85 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
19
lib/ldpc/blockio.h
Executable file
19
lib/ldpc/blockio.h
Executable file
@ -0,0 +1,19 @@
|
||||
/* 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);
|
||||
99
lib/ldpc/channel.c
Executable file
99
lib/ldpc/channel.c
Executable file
@ -0,0 +1,99 @@
|
||||
/* 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");
|
||||
}
|
||||
32
lib/ldpc/channel.h
Executable file
32
lib/ldpc/channel.h
Executable file
@ -0,0 +1,32 @@
|
||||
/* 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);
|
||||
182
lib/ldpc/channel.html
Executable file
182
lib/ldpc/channel.html
Executable file
@ -0,0 +1,182 @@
|
||||
<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>
|
||||
177
lib/ldpc/check.c
Executable file
177
lib/ldpc/check.c
Executable file
@ -0,0 +1,177 @@
|
||||
/* 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);
|
||||
}
|
||||
25
lib/ldpc/check.h
Executable file
25
lib/ldpc/check.h
Executable file
@ -0,0 +1,25 @@
|
||||
/* 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);
|
||||
385
lib/ldpc/dec.c
Executable file
385
lib/ldpc/dec.c
Executable file
@ -0,0 +1,385 @@
|
||||
/* 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 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 (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 (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 (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 (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;
|
||||
}
|
||||
}
|
||||
}
|
||||
43
lib/ldpc/dec.h
Executable file
43
lib/ldpc/dec.h
Executable file
@ -0,0 +1,43 @@
|
||||
/* 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 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 *);
|
||||
99
lib/ldpc/decode-detail.html
Executable file
99
lib/ldpc/decode-detail.html
Executable file
@ -0,0 +1,99 @@
|
||||
<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>
|
||||
384
lib/ldpc/decode.c
Executable file
384
lib/ldpc/decode.c
Executable file
@ -0,0 +1,384 @@
|
||||
/* 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. */
|
||||
|
||||
table = 0;
|
||||
blockio_flush = 0;
|
||||
|
||||
while (argc>1)
|
||||
{
|
||||
if (strcmp(argv[1],"-t")==0)
|
||||
{ if (table!=0) usage();
|
||||
table = 1;
|
||||
}
|
||||
else if (strcmp(argv[1],"-T")==0)
|
||||
{ if (table!=0) usage();
|
||||
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 ((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 (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 (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);
|
||||
}
|
||||
342
lib/ldpc/decoding.html
Executable file
342
lib/ldpc/decoding.html
Executable file
@ -0,0 +1,342 @@
|
||||
<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>
|
||||
85
lib/ldpc/dep-H.html
Executable file
85
lib/ldpc/dep-H.html
Executable file
@ -0,0 +1,85 @@
|
||||
<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>
|
||||
188
lib/ldpc/distrib.c
Executable file
188
lib/ldpc/distrib.c
Executable file
@ -0,0 +1,188 @@
|
||||
/* 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
|
||||
49
lib/ldpc/distrib.h
Executable file
49
lib/ldpc/distrib.h
Executable file
@ -0,0 +1,49 @@
|
||||
/* 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 *);
|
||||
154
lib/ldpc/enc.c
Executable file
154
lib/ldpc/enc.c
Executable file
@ -0,0 +1,154 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
18
lib/ldpc/enc.h
Executable file
18
lib/ldpc/enc.h
Executable file
@ -0,0 +1,18 @@
|
||||
/* 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 *);
|
||||
195
lib/ldpc/encode.c
Executable file
195
lib/ldpc/encode.c
Executable file
@ -0,0 +1,195 @@
|
||||
/* 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);
|
||||
}
|
||||
283
lib/ldpc/encoding.html
Executable file
283
lib/ldpc/encoding.html
Executable file
@ -0,0 +1,283 @@
|
||||
<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>><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><<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>
|
||||
60
lib/ldpc/ex-dep
Executable file
60
lib/ldpc/ex-dep
Executable file
@ -0,0 +1,60 @@
|
||||
#!/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
|
||||
224
lib/ldpc/ex-dep-out
Executable file
224
lib/ldpc/ex-dep-out
Executable file
@ -0,0 +1,224 @@
|
||||
|
||||
# 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
|
||||
38
lib/ldpc/ex-ham7a
Executable file
38
lib/ldpc/ex-ham7a
Executable file
@ -0,0 +1,38 @@
|
||||
#!/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
|
||||
33
lib/ldpc/ex-ham7a-out
Executable file
33
lib/ldpc/ex-ham7a-out
Executable file
@ -0,0 +1,33 @@
|
||||
|
||||
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
|
||||
21
lib/ldpc/ex-ham7b
Executable file
21
lib/ldpc/ex-ham7b
Executable file
@ -0,0 +1,21 @@
|
||||
#!/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
|
||||
15
lib/ldpc/ex-ham7b-out
Executable file
15
lib/ldpc/ex-ham7b-out
Executable file
@ -0,0 +1,15 @@
|
||||
|
||||
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
|
||||
45
lib/ldpc/ex-ldpc-encode
Executable file
45
lib/ldpc/ex-ldpc-encode
Executable file
@ -0,0 +1,45 @@
|
||||
#!/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
|
||||
47
lib/ldpc/ex-ldpc-encode-out
Executable file
47
lib/ldpc/ex-ldpc-encode-out
Executable file
@ -0,0 +1,47 @@
|
||||
|
||||
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
|
||||
50
lib/ldpc/ex-ldpc36-1000a
Executable file
50
lib/ldpc/ex-ldpc36-1000a
Executable file
@ -0,0 +1,50 @@
|
||||
#!/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
|
||||
57
lib/ldpc/ex-ldpc36-1000a-out
Executable file
57
lib/ldpc/ex-ldpc36-1000a-out
Executable file
@ -0,0 +1,57 @@
|
||||
|
||||
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
|
||||
44
lib/ldpc/ex-ldpc36-5000a
Executable file
44
lib/ldpc/ex-ldpc36-5000a
Executable file
@ -0,0 +1,44 @@
|
||||
#!/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
|
||||
54
lib/ldpc/ex-ldpc36-5000a-out
Executable file
54
lib/ldpc/ex-ldpc36-5000a-out
Executable file
@ -0,0 +1,54 @@
|
||||
|
||||
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
|
||||
46
lib/ldpc/ex-ldpcvar-5000a
Executable file
46
lib/ldpc/ex-ldpcvar-5000a
Executable file
@ -0,0 +1,46 @@
|
||||
#!/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
|
||||
54
lib/ldpc/ex-ldpcvar-5000a-out
Executable file
54
lib/ldpc/ex-ldpcvar-5000a-out
Executable file
@ -0,0 +1,54 @@
|
||||
|
||||
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
|
||||
124
lib/ldpc/ex-wrong-model
Executable file
124
lib/ldpc/ex-wrong-model
Executable file
@ -0,0 +1,124 @@
|
||||
#!/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
|
||||
163
lib/ldpc/ex-wrong-model-out
Executable file
163
lib/ldpc/ex-wrong-model-out
Executable file
@ -0,0 +1,163 @@
|
||||
|
||||
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
|
||||
87
lib/ldpc/examples.html
Executable file
87
lib/ldpc/examples.html
Executable file
@ -0,0 +1,87 @@
|
||||
<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>
|
||||
112
lib/ldpc/extract.c
Executable file
112
lib/ldpc/extract.c
Executable file
@ -0,0 +1,112 @@
|
||||
/* 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);
|
||||
}
|
||||
67
lib/ldpc/github.html
Executable file
67
lib/ldpc/github.html
Executable file
@ -0,0 +1,67 @@
|
||||
<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>
|
||||
89
lib/ldpc/index.html
Executable file
89
lib/ldpc/index.html
Executable file
@ -0,0 +1,89 @@
|
||||
<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 © 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>
|
||||
|
||||
82
lib/ldpc/install.html
Executable file
82
lib/ldpc/install.html
Executable file
@ -0,0 +1,82 @@
|
||||
<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>
|
||||
110
lib/ldpc/intio.c
Executable file
110
lib/ldpc/intio.c
Executable file
@ -0,0 +1,110 @@
|
||||
/* 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
|
||||
17
lib/ldpc/intio.h
Executable file
17
lib/ldpc/intio.h
Executable file
@ -0,0 +1,17 @@
|
||||
/* 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 */
|
||||
3995
lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf
Normal file
3995
lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf
Normal file
File diff suppressed because it is too large
Load Diff
59
lib/ldpc/jtmode_codes/ldpc-144-72
Executable file
59
lib/ldpc/jtmode_codes/ldpc-144-72
Executable file
@ -0,0 +1,59 @@
|
||||
#!/bin/sh
|
||||
# this script characterizes a single code over a narrow range of Eb/No
|
||||
# note relationship between noise standard deviation, sigma, and Eb/No:
|
||||
# Ps/Pn = 1/(2*sigma^2)
|
||||
# Ps/Pn = (Es/tau_s)/(W*No)=(Eb/R)/(tau_s*W*No)=(Eb/No)*(1/(tau_s*R*W))
|
||||
# If pulses are sent at Nyquist signaling limit, then: 1/tau_s=2*W -> tau_s*W=1/2
|
||||
# so Eb/No=(1/2*sigma^2)*(2*R) =
|
||||
|
||||
set -e # Stop if an error occurs
|
||||
set -v # Echo commands as they are read
|
||||
|
||||
#make-ldpc ldpc-144-72.pchk 80 160 12 evenboth 6x3/4x4 no4cycle
|
||||
#make-ldpc ldpc-144-72.pchk 72 144 33 evenboth 6x3/4x4 no4cycle
|
||||
#make-ldpc ldpc-144-72.pchk 72 144 8 evenboth 3 no4cycle
|
||||
cp ldpc-144-72-6x3-4x4-sf1.pchk ldpc-144-72.pchk
|
||||
make-gen ldpc-144-72.pchk ldpc-144-72.gen dense
|
||||
rand-src ldpc-144-72.src 1 72x1000000
|
||||
encode ldpc-144-72.pchk ldpc-144-72.gen ldpc-144-72.src \
|
||||
ldpc-144-72.enc
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.75, Eb/N0 = 2.50 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.75
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.75\
|
||||
prprp 250
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.80
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.80\
|
||||
prprp 250
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.85
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.85\
|
||||
prprp 250
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.90
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.90\
|
||||
prprp 250
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.95
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.95\
|
||||
prprp 250
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
BIN
lib/ldpc/jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk
Normal file
BIN
lib/ldpc/jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk
Normal file
Binary file not shown.
34
lib/ldpc/jtmode_codes/ldpc-144-72-search
Executable file
34
lib/ldpc/jtmode_codes/ldpc-144-72-search
Executable file
@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Example of a (144,72) 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
|
||||
|
||||
for i in `seq 1 1000`;
|
||||
do
|
||||
seed=$i
|
||||
echo seed $seed
|
||||
make-ldpc ldpc-144-72.pchk 72 144 $seed evenboth 6x3/4x4 no4cycle
|
||||
make-gen ldpc-144-72.pchk ldpc-144-72.gen dense
|
||||
rand-src ldpc-144-72.src 2 72x100000
|
||||
encode ldpc-144-72.pchk ldpc-144-72.gen ldpc-144-72.src \
|
||||
ldpc-144-72.enc
|
||||
|
||||
|
||||
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB
|
||||
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.80
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.80\
|
||||
prprp 50
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \
|
||||
ldpc-144-72.src
|
||||
|
||||
|
||||
done
|
||||
85
lib/ldpc/jtmode_codes/ldpc-144-72-sf1.results.rtf
Normal file
85
lib/ldpc/jtmode_codes/ldpc-144-72-sf1.results.rtf
Normal file
@ -0,0 +1,85 @@
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170
|
||||
{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
\margl1440\margr1440\vieww21500\viewh8400\viewkind0
|
||||
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural
|
||||
|
||||
\f0\fs30 \cf0 \CocoaLigature0 Stevens-MacBook-Air:LDPC-codes-master sfranke$ ldpc-144-72\
|
||||
\
|
||||
#make-ldpc ldpc-144-72.pchk 80 160 12 evenboth 6x3/4x4 no4cycle\
|
||||
#make-ldpc ldpc-144-72.pchk 72 144 33 evenboth 6x3/4x4 no4cycle\
|
||||
#make-ldpc ldpc-144-72.pchk 72 144 8 evenboth 3 no4cycle\
|
||||
cp ldpc-144-72-6x3-4x4-sf1.pchk ldpc-144-72.pchk\
|
||||
make-gen ldpc-144-72.pchk ldpc-144-72.gen dense\
|
||||
Number of 1s per check in Inv(A) X B is 29.4\
|
||||
rand-src ldpc-144-72.src 1 72x1000000\
|
||||
encode ldpc-144-72.pchk ldpc-144-72.gen ldpc-144-72.src \\\
|
||||
ldpc-144-72.enc\
|
||||
Encoded 1000000 blocks, source block size 72, encoded block size 144\
|
||||
\
|
||||
# NOISE STANDARD DEVIATION 0.75, Eb/N0 = 2.50 dB\
|
||||
\
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.75\
|
||||
Transmitted 144000000 bits\
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.75\\\
|
||||
prprp 250\
|
||||
Decoded 1000000 blocks, 912331 valid. Average 28.0 iterations, 9% bit changes\
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\
|
||||
ldpc-144-72.src \
|
||||
Block counts: tot 1000000, with chk errs 87669, with src errs 87561, both 87506\
|
||||
Total good frames: 912276 Total undetected errors: 55\
|
||||
Bit error rate (on message bits only): 8.969e-03\
|
||||
\
|
||||
# NOISE STANDARD DEVIATION 0.80, Eb/N0 = 1.94 dB\
|
||||
\
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.80\
|
||||
Transmitted 144000000 bits\
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.80\\\
|
||||
prprp 250\
|
||||
Decoded 1000000 blocks, 747691 valid. Average 69.4 iterations, 10% bit changes\
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\
|
||||
ldpc-144-72.src \
|
||||
Block counts: tot 1000000, with chk errs 252309, with src errs 251953, both 251862\
|
||||
Total good frames: 747600 Total undetected errors: 91\
|
||||
Bit error rate (on message bits only): 2.627e-02\
|
||||
\
|
||||
# NOISE STANDARD DEVIATION 0.85, Eb/N0 = 1.41 dB\
|
||||
\
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.85\
|
||||
Transmitted 144000000 bits\
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.85\\\
|
||||
prprp 250\
|
||||
Decoded 1000000 blocks, 513359 valid. Average 126.8 iterations, 10% bit changes\
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\
|
||||
ldpc-144-72.src \
|
||||
Block counts: tot 1000000, with chk errs 486641, with src errs 485965, both 485838\
|
||||
Total good frames: 513232 Total undetected errors: 127\
|
||||
Bit error rate (on message bits only): 5.295e-02\
|
||||
\
|
||||
# NOISE STANDARD DEVIATION 0.90, Eb/N0 = 0.92 dB\
|
||||
\
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.90\
|
||||
Transmitted 144000000 bits\
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.90\\\
|
||||
prprp 250\
|
||||
Decoded 1000000 blocks, 287970 valid. Average 181.4 iterations, 9% bit changes\
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\
|
||||
ldpc-144-72.src \
|
||||
Block counts: tot 1000000, with chk errs 712030, with src errs 711238, both 711123\
|
||||
Total good frames: 287855 Total undetected errors: 115\
|
||||
Bit error rate (on message bits only): 8.316e-02\
|
||||
\
|
||||
# NOISE STANDARD DEVIATION 0.95, Eb/N0 = 0.45 dB\
|
||||
\
|
||||
transmit ldpc-144-72.enc ldpc-144-72.rec 1 awgn 0.95\
|
||||
Transmitted 144000000 bits\
|
||||
decode ldpc-144-72.pchk ldpc-144-72.rec ldpc-144-72.dec awgn 0.95\\\
|
||||
prprp 250\
|
||||
Decoded 1000000 blocks, 130537 valid. Average 219.2 iterations, 8% bit changes\
|
||||
verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\
|
||||
ldpc-144-72.src\
|
||||
Block counts: tot 1000000, with chk errs 869463, with src errs 868761, both 868683\
|
||||
Total good frames: 130459 Total undetected errors: 78\
|
||||
Bit error rate (on message bits only): 1.110e-01\
|
||||
Stevens-MacBook-Air:LDPC-codes-master sfranke$ \
|
||||
}
|
||||
8953
lib/ldpc/jtmode_codes/search_144-72-6x3-4x4.txt
Normal file
8953
lib/ldpc/jtmode_codes/search_144-72-6x3-4x4.txt
Normal file
File diff suppressed because it is too large
Load Diff
350
lib/ldpc/make-gen.c
Executable file
350
lib/ldpc/make-gen.c
Executable file
@ -0,0 +1,350 @@
|
||||
/* 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);
|
||||
}
|
||||
415
lib/ldpc/make-ldpc.c
Executable file
415
lib/ldpc/make-ldpc.c
Executable file
@ -0,0 +1,415 @@
|
||||
/* 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;
|
||||
}
|
||||
93
lib/ldpc/make-pchk.c
Executable file
93
lib/ldpc/make-pchk.c
Executable file
@ -0,0 +1,93 @@
|
||||
/* 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);
|
||||
}
|
||||
9
lib/ldpc/mod2convert-test-out
Executable file
9
lib/ldpc/mod2convert-test-out
Executable file
@ -0,0 +1,9 @@
|
||||
|
||||
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.
|
||||
80
lib/ldpc/mod2convert-test.c
Executable file
80
lib/ldpc/mod2convert-test.c
Executable file
@ -0,0 +1,80 @@
|
||||
/* 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);
|
||||
}
|
||||
83
lib/ldpc/mod2convert.c
Executable file
83
lib/ldpc/mod2convert.c
Executable file
@ -0,0 +1,83 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
lib/ldpc/mod2convert.h
Executable file
18
lib/ldpc/mod2convert.h
Executable file
@ -0,0 +1,18 @@
|
||||
/* 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 *);
|
||||
51
lib/ldpc/mod2convert.html
Executable file
51
lib/ldpc/mod2convert.html
Executable file
@ -0,0 +1,51 @@
|
||||
<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>
|
||||
699
lib/ldpc/mod2dense-test-out
Executable file
699
lib/ldpc/mod2dense-test-out
Executable file
@ -0,0 +1,699 @@
|
||||
|
||||
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.
|
||||
560
lib/ldpc/mod2dense-test.c
Executable file
560
lib/ldpc/mod2dense-test.c
Executable file
@ -0,0 +1,560 @@
|
||||
/* 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);
|
||||
}
|
||||
752
lib/ldpc/mod2dense.c
Executable file
752
lib/ldpc/mod2dense.c
Executable file
@ -0,0 +1,752 @@
|
||||
/* 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 */
|
||||
)
|
||||
{ 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;
|
||||
}
|
||||
113
lib/ldpc/mod2dense.h
Executable file
113
lib/ldpc/mod2dense.h
Executable file
@ -0,0 +1,113 @@
|
||||
/* 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 *);
|
||||
487
lib/ldpc/mod2dense.html
Executable file
487
lib/ldpc/mod2dense.html
Executable file
@ -0,0 +1,487 @@
|
||||
<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>
|
||||
431
lib/ldpc/mod2sparse-test-out
Executable file
431
lib/ldpc/mod2sparse-test-out
Executable file
@ -0,0 +1,431 @@
|
||||
|
||||
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.
|
||||
378
lib/ldpc/mod2sparse-test.c
Executable file
378
lib/ldpc/mod2sparse-test.c
Executable file
@ -0,0 +1,378 @@
|
||||
/* 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);
|
||||
}
|
||||
1361
lib/ldpc/mod2sparse.c
Executable file
1361
lib/ldpc/mod2sparse.c
Executable file
File diff suppressed because it is too large
Load Diff
147
lib/ldpc/mod2sparse.h
Executable file
147
lib/ldpc/mod2sparse.h
Executable file
@ -0,0 +1,147 @@
|
||||
/* 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 *);
|
||||
719
lib/ldpc/mod2sparse.html
Executable file
719
lib/ldpc/mod2sparse.html
Executable file
@ -0,0 +1,719 @@
|
||||
<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>
|
||||
125
lib/ldpc/modify.html
Executable file
125
lib/ldpc/modify.html
Executable file
@ -0,0 +1,125 @@
|
||||
<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>
|
||||
89
lib/ldpc/modules.html
Executable file
89
lib/ldpc/modules.html
Executable file
@ -0,0 +1,89 @@
|
||||
<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>
|
||||
50
lib/ldpc/open.c
Executable file
50
lib/ldpc/open.c
Executable file
@ -0,0 +1,50 @@
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
16
lib/ldpc/open.h
Executable file
16
lib/ldpc/open.h
Executable file
@ -0,0 +1,16 @@
|
||||
/* 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 *);
|
||||
166
lib/ldpc/pchk-to-alist.c
Executable file
166
lib/ldpc/pchk-to-alist.c
Executable file
@ -0,0 +1,166 @@
|
||||
/* 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);
|
||||
}
|
||||
371
lib/ldpc/pchk.html
Executable file
371
lib/ldpc/pchk.html
Executable file
@ -0,0 +1,371 @@
|
||||
<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>
|
||||
|
||||
139
lib/ldpc/print-gen.c
Executable file
139
lib/ldpc/print-gen.c
Executable file
@ -0,0 +1,139 @@
|
||||
/* PRINT-CODE.C - Print a Low Density Parity Check code's 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "rand.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 *gen_file;
|
||||
int dprint;
|
||||
int i, j;
|
||||
|
||||
dprint = 0;
|
||||
if (argc>1 && strcmp(argv[1],"-d")==0)
|
||||
{ dprint = 1;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
}
|
||||
|
||||
if (!(gen_file = argv[1]) || argv[2])
|
||||
{ usage();
|
||||
}
|
||||
|
||||
read_gen(gen_file,0,1);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
{
|
||||
printf("\nGenerator matrix in %s (sparse representation):\n\n",gen_file);
|
||||
|
||||
printf("Column order (message bits at end):\n");
|
||||
for (j = 0; j<N; j++)
|
||||
{ if (j%20==0) printf("\n");
|
||||
printf(" %3d",cols[j]);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
printf("Row order:\n");
|
||||
for (i = 0; i<M; i++)
|
||||
{ if (i%20==0) printf("\n");
|
||||
printf(" %3d",rows[i]);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
if (dprint)
|
||||
{ mod2dense *Ld, *Ud;
|
||||
Ld = mod2dense_allocate(M,M);
|
||||
Ud = mod2dense_allocate(M,N);
|
||||
mod2sparse_to_dense(L,Ld);
|
||||
mod2sparse_to_dense(U,Ud);
|
||||
printf("L:\n\n");
|
||||
mod2dense_print(stdout,Ld);
|
||||
printf("\n");
|
||||
printf("U:\n\n");
|
||||
mod2dense_print(stdout,Ud);
|
||||
printf("\n");
|
||||
}
|
||||
else
|
||||
{ printf("L:\n\n");
|
||||
mod2sparse_print(stdout,L);
|
||||
printf("\n");
|
||||
printf("U:\n\n");
|
||||
mod2sparse_print(stdout,U);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd': case 'm':
|
||||
{
|
||||
if (type=='d')
|
||||
{ printf("\nGenerator matrix in %s (dense representation):\n\n",gen_file);
|
||||
}
|
||||
if (type=='m')
|
||||
{ printf("\nGenerator matrix in %s (mixed representation):\n\n",gen_file);
|
||||
}
|
||||
|
||||
printf("Column order (message bits at end):\n");
|
||||
for (j = 0; j<N; j++)
|
||||
{ if (j%20==0) printf("\n");
|
||||
printf(" %3d",cols[j]);
|
||||
}
|
||||
printf("\n\n");
|
||||
|
||||
printf (type=='d' ? "Inv(A) X B:\n\n" : "Inv(A):\n\n");
|
||||
mod2dense_print(stdout,G);
|
||||
printf("\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{ fprintf(stderr,"Unknown type of generator matrix file\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,"Usage: print-gen [ -d ] gen-file\n");
|
||||
exit(1);
|
||||
}
|
||||
114
lib/ldpc/print-pchk.c
Executable file
114
lib/ldpc/print-pchk.c
Executable file
@ -0,0 +1,114 @@
|
||||
/* PRINT-PCHK.C - Print the parity check matrix for a code. */
|
||||
|
||||
/* 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 "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
|
||||
)
|
||||
{
|
||||
mod2dense *D;
|
||||
mod2sparse *T;
|
||||
|
||||
char *pchk_file;
|
||||
int dprint, trans;
|
||||
|
||||
dprint = 0;
|
||||
trans = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (argc>1 && strcmp(argv[1],"-d")==0)
|
||||
{ dprint = 1;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
}
|
||||
else if (argc>1 && strcmp(argv[1],"-t")==0)
|
||||
{ trans = 1;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
}
|
||||
else
|
||||
{ break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(pchk_file = argv[1]) || argv[2])
|
||||
{ usage();
|
||||
}
|
||||
|
||||
read_pchk(pchk_file);
|
||||
|
||||
if (trans)
|
||||
{ T = mod2sparse_allocate(N,M);
|
||||
mod2sparse_transpose(H,T);
|
||||
}
|
||||
|
||||
if (dprint)
|
||||
{ if (trans)
|
||||
{ D = mod2dense_allocate(N,M);
|
||||
mod2sparse_to_dense(T,D);
|
||||
printf("\nTranspose of parity check matrix in %s (dense format):\n\n",
|
||||
pchk_file);
|
||||
mod2dense_print(stdout,D);
|
||||
}
|
||||
else
|
||||
{ D = mod2dense_allocate(M,N);
|
||||
mod2sparse_to_dense(H,D);
|
||||
printf("\nParity check matrix in %s (dense format):\n\n",pchk_file);
|
||||
mod2dense_print(stdout,D);
|
||||
}
|
||||
}
|
||||
else /* sparse */
|
||||
{ if (trans)
|
||||
{ printf("\nTranspose of parity check matrix in %s (sparse format):\n\n",
|
||||
pchk_file);
|
||||
mod2sparse_print(stdout,T);
|
||||
}
|
||||
else
|
||||
{ printf("\nParity check matrix in %s (sparse format):\n\n",pchk_file);
|
||||
mod2sparse_print(stdout,H);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,"Usage: print-pchk [ -d ] [ -t ] pchk-file\n");
|
||||
exit(1);
|
||||
}
|
||||
80
lib/ldpc/progs.html
Executable file
80
lib/ldpc/progs.html
Executable file
@ -0,0 +1,80 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> Programs for Low Density Parity Check Codes </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> Programs for Low Density Parity Check Codes </H1>
|
||||
|
||||
Programs are available for creating LDPC codes, encoding messages,
|
||||
simulating transmission through a channel, and decoding the received
|
||||
message. There are links here to the general documentation on each of
|
||||
these operations, and to the detailed documentation on the relevant
|
||||
programs.
|
||||
|
||||
<P>The programs names below are followed by the form of arguments they
|
||||
take; a similar usage message is displayed when a program is run with
|
||||
no arguments. In these descriptions, things to be entered literally
|
||||
are in roman font, descriptions of something to be supplied are in
|
||||
italic. Arguments in square brackets are optional. A vertical bar
|
||||
separates alternatives. Dots represent indefinite repetition.
|
||||
|
||||
<P>Many of the arguments are file names, which can be a dash ("-") in
|
||||
order to specify that standard input or standard output is to be used.
|
||||
(However, you can't use standard input or output for more than one thing.)
|
||||
|
||||
<P>Click on a main title below for general information on that aspect
|
||||
of the software, or on the name of a program for detailed information.
|
||||
|
||||
<P><A HREF="pchk.html">Creating a parity check matrix for a code</A>:
|
||||
<BLOCKQUOTE><PRE>
|
||||
<A HREF="pchk.html#make-pchk">make-pchk</A> <I>pchk-file n-checks n-bits row</I>:<I>col ...</I>
|
||||
|
||||
<A HREF="pchk.html#alist-to-pchk">alist-to-pchk</A> [ -t ] <I>alist-file pchk-file</I>
|
||||
|
||||
<A HREF="pchk.html#pchk-to-alist">pchk-to-alist</A> [ -t ] [ -z ] <I>pchk-file alist-file</I>
|
||||
|
||||
<A HREF="pchk.html#print-pchk">print-pchk</A> [ -d ] [ -t ] <I>pchk-file</I>
|
||||
|
||||
<A HREF="pchk.html#make-ldpc">make-ldpc</A> <I>pchk-file n-checks n-bits seed method</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P><A HREF="encoding.html">Encoding message blocks as codewords</A>:
|
||||
<BLOCKQUOTE><PRE>
|
||||
<A HREF="encoding.html#make-gen">make-gen</A> <I>pchk-file gen-file method</I>
|
||||
|
||||
<A HREF="encoding.html#print-gen">print-gen</A> [ -d ] <I>gen-file</I>
|
||||
|
||||
<A HREF="encoding.html#encode">encode</A> [ -f ] <I>pchk-file gen-file source-file encoded-file</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P><A HREF="channel.html">Transmitting bits through a simulated channel:</A>
|
||||
<BLOCKQUOTE><PRE>
|
||||
<A HREF="channel.html#transmit">transmit</A> <I>encoded-file</I>|<I>n-zeros received-file seed channel</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P><A HREF="decoding.html">Decoding received blocks:</A>
|
||||
<BLOCKQUOTE><PRE>
|
||||
<A HREF="decoding.html#decode">decode</A> [ -f ] [ -t | -T ] <I>pchk-file received-file decoded-file</I> [ <I>bp-file</I> ] <I>channel method</I>
|
||||
|
||||
<A HREF="decoding.html#extract">extract</A> <I>gen-file decoded-file extracted-file</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P><A HREF="support.html">Support programs:</A>
|
||||
<BLOCKQUOTE><PRE>
|
||||
<A HREF="support.html#rand-src">rand-src</A> <I>source-file seed n-bits</I>
|
||||
|
||||
<A HREF="support.html#verify">verify</A> [ -t ] <I>pchk-file decoded-file</I> [ <I>gen-file</I> [ <I>source-file</I> ] ]
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
See also the discussions of <A HREF="dep-H.html">linear dependence in
|
||||
parity check matrices</A> and of <A HREF="sparse-LU.html">sparse LU
|
||||
decomposition methods</A>, and the <A HREF="examples.html">examples
|
||||
of program usage</A>.
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
86
lib/ldpc/rand-src.c
Executable file
86
lib/ldpc/rand-src.c
Executable file
@ -0,0 +1,86 @@
|
||||
/* RAND-SRC.C - Generate random message bits. */
|
||||
|
||||
/* 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 "open.h"
|
||||
#include "rand.h"
|
||||
|
||||
void usage(void);
|
||||
|
||||
|
||||
/* MAIN PROGRAM. */
|
||||
|
||||
int main
|
||||
( int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
int seed, bs, nb;
|
||||
char *file, *n_bits;
|
||||
char junk;
|
||||
int i, j;
|
||||
FILE *f;
|
||||
|
||||
if (!(file = argv[1])
|
||||
|| !argv[2] || sscanf(argv[2],"%d%c",&seed,&junk)!=1
|
||||
|| !(n_bits = argv[3])
|
||||
|| argv[4])
|
||||
{ usage();
|
||||
}
|
||||
|
||||
if (sscanf(n_bits,"%d%c",&nb,&junk)==1)
|
||||
{ if (nb<=0) usage();
|
||||
bs = 1;
|
||||
}
|
||||
else if (sscanf(n_bits,"%dx%d%c",&bs,&nb,&junk)==2)
|
||||
{ if (nb<=0 || bs<=0) usage();
|
||||
}
|
||||
else
|
||||
{ usage();
|
||||
}
|
||||
|
||||
f = open_file_std(file,"w");
|
||||
if (f==NULL)
|
||||
{ fprintf(stderr,"Can't create source file: %s\n",file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
rand_seed(10*seed+2);
|
||||
|
||||
for (i = 0; i<nb; i++)
|
||||
{ for (j = 0; j<bs; j++)
|
||||
{ fprintf(f,"%d",rand_int(2));
|
||||
}
|
||||
fprintf(f,"\n");
|
||||
}
|
||||
|
||||
if (ferror(f) || fclose(f)!=0)
|
||||
{ fprintf(stderr,"Error writing random source blocks to %s\n",file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,"Usage: rand-src source-file seed n-bits\n");
|
||||
exit(1);
|
||||
}
|
||||
266
lib/ldpc/rand-test.c
Executable file
266
lib/ldpc/rand-test.c
Executable file
@ -0,0 +1,266 @@
|
||||
/* RAND-TEST.C - Program to test random number generators. */
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* Usage:
|
||||
|
||||
rand-test seed generator { parameters } / sample-size [ low high bins ]
|
||||
|
||||
Using the seed given, tests the random number generator identified by
|
||||
the second argument, for the parameter values specified. The possible
|
||||
generators and required parameters are as follows:
|
||||
|
||||
uniform Uniform from [0,1)
|
||||
uniopen Uniform from (0,1)
|
||||
int n Uniform from the set { 0, 1, ..., (n-1) }
|
||||
gaussian From Gaussian with mean zero and unit variance
|
||||
exp From exponential with mean one
|
||||
cauchy From Cauchy centred at zero with unit width
|
||||
gamma alpha From Gamma with shape parameter (and mean) alpha
|
||||
beta a b From Beta with parameters a and b
|
||||
|
||||
The size of the sample to use is also specified. The program reports
|
||||
the mean and variance of the sample. A histogram is also printed if a
|
||||
low and high range and number of bins are for it are specified.
|
||||
|
||||
These tests are not really adequate to detect subtle forms of bias due
|
||||
to use of pseudo-random numbers, but are hopefully good enough to find
|
||||
most programming errors.
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "rand.h"
|
||||
|
||||
|
||||
#define Max_bins 1000 /* Maximum number of histogram bins */
|
||||
|
||||
static void usage (void);
|
||||
|
||||
|
||||
/* MAIN PROGRAM. */
|
||||
|
||||
main
|
||||
( int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
int seed, sample_size, bins, np;
|
||||
double low, high;
|
||||
char *generator;
|
||||
double p1, p2;
|
||||
|
||||
double mean, variance;
|
||||
double tmean, tvariance;
|
||||
int undef_mean, undef_variance;
|
||||
|
||||
int count[Max_bins];
|
||||
int under, over;
|
||||
|
||||
char **ap;
|
||||
double x;
|
||||
int i, n;
|
||||
|
||||
bins = 0;
|
||||
|
||||
if (argc<5) usage();
|
||||
|
||||
if ((seed = atoi(argv[1]))==0 && strcmp(argv[1],"0")!=0) usage();
|
||||
|
||||
generator = argv[2];
|
||||
|
||||
if (strcmp(generator,"uniform")==0) np = 0;
|
||||
else if (strcmp(generator,"uniopen")==0) np = 0;
|
||||
else if (strcmp(generator,"int")==0) np = 1;
|
||||
else if (strcmp(generator,"poisson")==0) np = 1;
|
||||
else if (strcmp(generator,"gaussian")==0) np = 0;
|
||||
else if (strcmp(generator,"exp")==0) np = 0;
|
||||
else if (strcmp(generator,"cauchy")==0) np = 0;
|
||||
else if (strcmp(generator,"gamma")==0) np = 1;
|
||||
else if (strcmp(generator,"beta")==0) np = 2;
|
||||
else
|
||||
{ fprintf(stderr,"Unknown generator: %s\n",generator);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ap = argv+3;
|
||||
|
||||
if (np>0)
|
||||
{ if (*ap==0 || (p1 = atof(*ap++))<=0) usage();
|
||||
}
|
||||
if (np>1)
|
||||
{ if (*ap==0 || (p2 = atof(*ap++))<=0) usage();
|
||||
}
|
||||
|
||||
if (*ap==0 || strcmp(*ap++,"/")!=0) usage();
|
||||
|
||||
if (*ap==0 || (sample_size = atoi(*ap++))<=0) usage();
|
||||
|
||||
if (*ap!=0)
|
||||
{ low = atof(*ap++);
|
||||
if (*ap==0) usage();
|
||||
high = atof(*ap++);
|
||||
if (high<=low) usage();
|
||||
if (*ap==0 || (bins = atoi(*ap++))<=0) usage();
|
||||
if (bins>Max_bins)
|
||||
{ fprintf(stderr,"Too many histogram bins\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (*ap!=0) usage();
|
||||
|
||||
printf("\nTest of %s(",generator);
|
||||
if (np>0) printf("%.4f",p1);
|
||||
if (np>1) printf(",%.4f",p2);
|
||||
printf(") generator using sample of size %d with seed %d\n\n",
|
||||
sample_size, seed);
|
||||
|
||||
undef_mean = undef_variance = 0;
|
||||
|
||||
if (strcmp(generator,"uniform")==0)
|
||||
{ tmean = 0.5;
|
||||
tvariance = 1.0/12.0;
|
||||
}
|
||||
else if (strcmp(generator,"uniopen")==0)
|
||||
{ tmean = 0.5;
|
||||
tvariance = 1.0/12.0;
|
||||
}
|
||||
else if (strcmp(generator,"int")==0)
|
||||
{ tmean = (p1-1)/2;
|
||||
tvariance = p1*p1/3.0 - p1/2.0 + 1/6.0 - tmean*tmean;
|
||||
}
|
||||
else if (strcmp(generator,"poisson")==0)
|
||||
{ tmean = p1;
|
||||
tvariance = p1;
|
||||
}
|
||||
else if (strcmp(generator,"gaussian")==0)
|
||||
{ tmean = 0;
|
||||
tvariance = 1;
|
||||
}
|
||||
else if (strcmp(generator,"exp")==0)
|
||||
{ tmean = 1;
|
||||
tvariance = 1;
|
||||
}
|
||||
else if (strcmp(generator,"cauchy")==0)
|
||||
{ undef_mean = 1;
|
||||
undef_variance = 1;
|
||||
}
|
||||
else if (strcmp(generator,"gamma")==0)
|
||||
{ tmean = p1;
|
||||
tvariance = p1;
|
||||
}
|
||||
else if (strcmp(generator,"beta")==0)
|
||||
{ tmean = p1 / (p1+p2);
|
||||
tvariance = (p1*p2) / ((p1+p2)*(p1+p2)*(p1+p2+1));
|
||||
}
|
||||
else
|
||||
{ abort();
|
||||
}
|
||||
|
||||
mean = 0;
|
||||
variance = 0;
|
||||
|
||||
if (bins>0)
|
||||
{ for (i = 0; i<bins; i++) count[i] = 0;
|
||||
under = over = 0;
|
||||
}
|
||||
|
||||
rand_seed(seed);
|
||||
|
||||
for (n = 0; n<sample_size; n++)
|
||||
{
|
||||
if (strcmp(generator,"uniform")==0) x = rand_uniform();
|
||||
else if (strcmp(generator,"uniopen")==0) x = rand_uniopen();
|
||||
else if (strcmp(generator,"int")==0) x = rand_int((int)p1);
|
||||
else if (strcmp(generator,"poisson")==0) x = rand_poisson(p1);
|
||||
else if (strcmp(generator,"gaussian")==0) x = rand_gaussian();
|
||||
else if (strcmp(generator,"exp")==0) x = rand_exp();
|
||||
else if (strcmp(generator,"cauchy")==0) x = rand_cauchy();
|
||||
else if (strcmp(generator,"gamma")==0) x = rand_gamma(p1);
|
||||
else if (strcmp(generator,"beta")==0) x = rand_beta(p1,p2);
|
||||
else abort();
|
||||
|
||||
mean += x;
|
||||
variance += x*x;
|
||||
|
||||
if (bins>0)
|
||||
{ if (x<low)
|
||||
{ under += 1;
|
||||
}
|
||||
else
|
||||
{ i = (int) ((x-low)/((high-low)/bins));
|
||||
if (i>=bins)
|
||||
{ over += 1;
|
||||
}
|
||||
else
|
||||
{ count[i] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mean /= sample_size;
|
||||
variance /= sample_size;
|
||||
variance -= mean*mean;
|
||||
|
||||
printf("Sample mean: %.4f",mean);
|
||||
if (undef_mean)
|
||||
{ printf(" (true value: undefined)\n");
|
||||
}
|
||||
else
|
||||
{ printf(" (true value: %.4f)\n",tmean);
|
||||
}
|
||||
|
||||
printf("Sample variance: %.4f",variance);
|
||||
if (undef_variance)
|
||||
{ printf(" (true value: undefined)\n");
|
||||
}
|
||||
else
|
||||
{ printf(" (true value: %.4f)\n",tvariance);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (bins!=0)
|
||||
{ printf("Histogram:\n");
|
||||
printf(" under : %8d %.5f\n\n",
|
||||
under, (double)under / sample_size);
|
||||
for (i = 0; i<bins; i++)
|
||||
{ printf(" %10.4f - %10.4f : %8d %.5f\n",
|
||||
i*(high-low)/bins + low, (i+1)*(high-low)/bins + low,
|
||||
count[i], (double)count[i] / sample_size);
|
||||
}
|
||||
printf("\n over : %8d %.5f\n",
|
||||
over, (double)over / sample_size);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
static void usage (void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: rand-test seed generator { parameters } / sample-size [ low high bins ]\n");
|
||||
|
||||
exit(1);
|
||||
}
|
||||
567
lib/ldpc/rand.c
Executable file
567
lib/ldpc/rand.c
Executable file
@ -0,0 +1,567 @@
|
||||
/* RAND.C - Random number generation 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.
|
||||
*/
|
||||
|
||||
/* Random generation routines at the end of this file are taken from the
|
||||
GNU C library, see the copyright notice there. */
|
||||
|
||||
|
||||
/* NOTE: See rand.html for documentation on these procedures. */
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "rand.h"
|
||||
|
||||
|
||||
static long int this_nrand48 (unsigned short int [3]);
|
||||
/* Local version of nrand48 */
|
||||
|
||||
|
||||
/* This module uses the 'this_nrand48' pseudo-random number generator from the
|
||||
GNU C library, included below, but renamed to 'this_nrand48'. The
|
||||
output of this generator is combined with a file of real random numbers.
|
||||
|
||||
Many of the methods used in this module may be found in the following
|
||||
reference:
|
||||
|
||||
Devroye, L. (1986) Non-Uniform Random Variate Generation,
|
||||
New York: Springer-Verlag.
|
||||
|
||||
The methods used here are not necessarily the fastest available. They're
|
||||
selected to be reasonably fast while also being easy to write.
|
||||
*/
|
||||
|
||||
|
||||
/* CONSTANT PI. Defined here if not in <math.h>. */
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
/* TABLES OF REAL RANDOM NUMBERS. A file of 100000 real random numbers
|
||||
(NOT pseudo-random) is used in conjunction with pseudo-random numbers
|
||||
for extra insurance. These are employed in the form of five tables
|
||||
of 5000 32-bit integers.
|
||||
|
||||
The file must be located at the path given by RAND_FILE, which should
|
||||
be defined on the "cc" command line. */
|
||||
|
||||
#define Table_size 5000 /* Number of words in each table */
|
||||
|
||||
static int rn[N_tables][Table_size]; /* Random number tables */
|
||||
|
||||
|
||||
/* STATE OF RANDOM NUMBER GENERATOR. */
|
||||
|
||||
static int initialized = 0; /* Has module been initialized? */
|
||||
|
||||
static rand_state state0; /* Default state structure */
|
||||
|
||||
static rand_state *state; /* Pointer to current state */
|
||||
|
||||
|
||||
/* INITIALIZE MODULE. Sets things up using the default state structure,
|
||||
set as if rand_seed had been called with a seed of one. */
|
||||
|
||||
static void initialize (void)
|
||||
{
|
||||
int i, j, k, w;
|
||||
char b;
|
||||
FILE *f;
|
||||
|
||||
if (!initialized)
|
||||
{
|
||||
f = fopen(RAND_FILE,"rb");
|
||||
|
||||
if (f==NULL)
|
||||
{ fprintf(stderr,"Can't open file of random numbers (%s)\n",RAND_FILE);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i<N_tables; i++)
|
||||
{ for (j = 0; j<Table_size; j++)
|
||||
{ w = 0;
|
||||
for (k = 0; k<4; k++)
|
||||
{ if (fread(&b,1,1,f)!=1)
|
||||
{ fprintf(stderr,"Error reading file of random numbers (%s)\n",
|
||||
RAND_FILE);
|
||||
exit(1);
|
||||
}
|
||||
w = (w<<8) | (b&0xff);
|
||||
}
|
||||
rn[i][j] = w;
|
||||
}
|
||||
}
|
||||
|
||||
state = &state0;
|
||||
|
||||
initialized = 1;
|
||||
|
||||
rand_seed(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* SET CURRENT STATE ACCORDING TO SEED. */
|
||||
|
||||
void rand_seed
|
||||
( int seed
|
||||
)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (!initialized) initialize();
|
||||
|
||||
state->seed = seed;
|
||||
|
||||
state->state48[0] = seed>>16;
|
||||
state->state48[1] = seed&0xffff;
|
||||
state->state48[2] = rn[0][(seed&0x7fffffff)%Table_size];
|
||||
|
||||
for (j = 0; j<N_tables; j++)
|
||||
{ state->ptr[j] = seed%Table_size;
|
||||
seed /= Table_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* SET STATE STRUCTURE TO USE. */
|
||||
|
||||
void rand_use_state
|
||||
( rand_state *st
|
||||
)
|
||||
{
|
||||
if (!initialized) initialize();
|
||||
|
||||
state = st;
|
||||
}
|
||||
|
||||
|
||||
/* RETURN POINTER TO CURRENT STATE. */
|
||||
|
||||
rand_state *rand_get_state (void)
|
||||
{
|
||||
if (!initialized) initialize();
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE RANDOM 31-BIT INTEGER. Not really meant for use outside this
|
||||
module. */
|
||||
|
||||
int rand_word(void)
|
||||
{
|
||||
int v;
|
||||
int j;
|
||||
|
||||
if (!initialized) initialize();
|
||||
|
||||
v = this_nrand48(state->state48);
|
||||
|
||||
for (j = 0; j<N_tables; j++)
|
||||
{ v ^= rn[j][state->ptr[j]];
|
||||
}
|
||||
|
||||
for (j = 0; j<N_tables && state->ptr[j]==Table_size-1; j++)
|
||||
{ state->ptr[j] = 0;
|
||||
}
|
||||
|
||||
if (j<N_tables)
|
||||
{ state->ptr[j] += 1;
|
||||
}
|
||||
|
||||
return v & 0x7fffffff;
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE UNIFORMLY FROM [0,1). */
|
||||
|
||||
double rand_uniform (void)
|
||||
{
|
||||
return (double)rand_word() / (1.0+(double)0x7fffffff);
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE UNIFORMLY FORM (0,1). */
|
||||
|
||||
double rand_uniopen (void)
|
||||
{
|
||||
return (0.5+(double)rand_word()) / (1.0+(double)0x7fffffff);
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE RANDOM INTEGER FROM 0, 1, ..., (n-1). */
|
||||
|
||||
int rand_int
|
||||
( int n
|
||||
)
|
||||
{
|
||||
return (int) (n * rand_uniform());
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE INTEGER FROM 0, 1, ..., (n-1), WITH GIVEN DISTRIBUTION. */
|
||||
|
||||
int rand_pickd
|
||||
( double *p,
|
||||
int n
|
||||
)
|
||||
{
|
||||
double t, r;
|
||||
int i;
|
||||
|
||||
t = 0;
|
||||
for (i = 0; i<n; i++)
|
||||
{ if (p[i]<0) abort();
|
||||
t += p[i];
|
||||
}
|
||||
|
||||
if (t<=0) abort();
|
||||
|
||||
r = t * rand_uniform();
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ r -= p[i];
|
||||
if (r<0) return i;
|
||||
}
|
||||
|
||||
/* Return value with non-zero probability if we get here due to roundoff. */
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ if (p[i]>0) return i;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/* SAME PROCEDURE AS ABOVE, BUT WITH FLOAT ARGUMENT. */
|
||||
|
||||
int rand_pickf
|
||||
( float *p,
|
||||
int n
|
||||
)
|
||||
{
|
||||
double t, r;
|
||||
int i;
|
||||
|
||||
t = 0;
|
||||
for (i = 0; i<n; i++)
|
||||
{ if (p[i]<=0) abort();
|
||||
t += p[i];
|
||||
}
|
||||
|
||||
if (t<=0) abort();
|
||||
|
||||
r = t * rand_uniform();
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ r -= p[i];
|
||||
if (r<0) return i;
|
||||
}
|
||||
|
||||
/* Return value with non-zero probability if we get here due to roundoff. */
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ if (p[i]>0) return i;
|
||||
}
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
|
||||
/* GENERATE RANDOM PERMUTATION OF INTEGERS FROM 1 TO N. */
|
||||
|
||||
void rand_permutation
|
||||
( int *perm, /* Place to store permutation */
|
||||
int n /* Number of integers to permute */
|
||||
)
|
||||
{
|
||||
int i, j, t;
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ perm[i] = i+1;
|
||||
}
|
||||
|
||||
for (i = 0; i<n; i++)
|
||||
{ t = perm[i];
|
||||
j = i + rand_int(n-i);
|
||||
perm[i] = perm[j];
|
||||
perm[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* POISSON GENERATOR. The method used is simple, but not very fast. See
|
||||
Devroye, p. 503. Very large means are done using Gaussian approximation. */
|
||||
|
||||
int rand_poisson
|
||||
( double lambda
|
||||
)
|
||||
{ int v;
|
||||
if (lambda>10000)
|
||||
{ v = (int) (lambda + rand_gaussian()*sqrt(lambda) + 0.5);
|
||||
}
|
||||
else
|
||||
{ v = 0;
|
||||
for (;;)
|
||||
{ lambda -= rand_exp();
|
||||
if (lambda<=0) break;
|
||||
v += 1;
|
||||
}
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/* GAUSSIAN GENERATOR. Done by using the Box-Muller method, but only one
|
||||
of the variates is retained (using both would require saving more state).
|
||||
See Devroye, p. 235.
|
||||
|
||||
As written, should never deliver exactly zero, which may sometimes be
|
||||
helpful. */
|
||||
|
||||
double rand_gaussian (void)
|
||||
{
|
||||
double a, b;
|
||||
|
||||
a = rand_uniform();
|
||||
b = rand_uniopen();
|
||||
|
||||
return cos(2.0*M_PI*a) * sqrt(-2.0*log(b));
|
||||
}
|
||||
|
||||
|
||||
/* EXPONENTIAL GENERATOR. See Devroye, p. 29. Written so as to never
|
||||
return exactly zero. */
|
||||
|
||||
double rand_exp (void)
|
||||
{
|
||||
return -log(rand_uniopen());
|
||||
}
|
||||
|
||||
|
||||
/* LOGISTIC GENERATOR. Just inverts the CDF. */
|
||||
|
||||
double rand_logistic (void)
|
||||
{ double u;
|
||||
u = rand_uniopen();
|
||||
return log(u/(1-u));
|
||||
}
|
||||
|
||||
|
||||
/* CAUCHY GENERATOR. See Devroye, p. 29. */
|
||||
|
||||
double rand_cauchy (void)
|
||||
{
|
||||
return tan (M_PI * (rand_uniopen()-0.5));
|
||||
}
|
||||
|
||||
|
||||
/* GAMMA GENERATOR. Generates a positive real number, r, with density
|
||||
proportional to r^(a-1) * exp(-r). See Devroye, p. 410 and p. 420.
|
||||
Things are fiddled to avoid ever returning a value that is very near
|
||||
zero. */
|
||||
|
||||
double rand_gamma
|
||||
( double a
|
||||
)
|
||||
{
|
||||
double b, c, X, Y, Z, U, V, W;
|
||||
|
||||
if (a<0.00001)
|
||||
{ X = a;
|
||||
}
|
||||
|
||||
else if (a<=1)
|
||||
{
|
||||
U = rand_uniopen();
|
||||
X = rand_gamma(1+a) * pow(U,1/a);
|
||||
}
|
||||
|
||||
else if (a<1.00001)
|
||||
{ X = rand_exp();
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
b = a-1;
|
||||
c = 3*a - 0.75;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
U = rand_uniopen();
|
||||
V = rand_uniopen();
|
||||
|
||||
W = U*(1-U);
|
||||
Y = sqrt(c/W) * (U-0.5);
|
||||
X = b+Y;
|
||||
|
||||
if (X>=0)
|
||||
{
|
||||
Z = 64*W*W*W*V*V;
|
||||
|
||||
if (Z <= 1 - 2*Y*Y/X || log(Z) <= 2 * (b*log(X/b) - Y)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return X<1e-30 && X<a ? (a<1e-30 ? a : 1e-30) : X;
|
||||
}
|
||||
|
||||
|
||||
/* BETA GENERATOR. Generates a real number, r, in (0,1), with density
|
||||
proportional to r^(a-1) * (1-r)^(b-1). Things are fiddled to avoid
|
||||
the end-points, and to make the procedure symmetric between a and b. */
|
||||
|
||||
double rand_beta
|
||||
( double a,
|
||||
double b
|
||||
)
|
||||
{
|
||||
double x, y, r;
|
||||
|
||||
do
|
||||
{ x = rand_gamma(a);
|
||||
y = rand_gamma(b);
|
||||
r = 1.0 + x/(x+y);
|
||||
r = r - 1.0;
|
||||
} while (r<=0.0 || r>=1.0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* ROUTINES FROM THE GNU C LIBRARY. These were modified to extract
|
||||
only the routines used here, and to allow them to be included in
|
||||
this module without any possible name conflict with other modules.
|
||||
Inclusion here ensures that these routines are always available, and
|
||||
operate in exactly the same way on all systems. The routines as copied
|
||||
below are still easily useable by other programs by simply inserting
|
||||
this source code into an appropriate source file.
|
||||
|
||||
The following is the copyright notice for these routines:
|
||||
|
||||
Copyright (C) 1995, 1996, 1997, 2002 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, write to the Free
|
||||
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307 USA.
|
||||
|
||||
The GNU Lesser General Public License is included with these source
|
||||
files in the file LGPL. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct this_drand48_data
|
||||
{
|
||||
unsigned short int x[3]; /* Current state. */
|
||||
unsigned short int old_x[3]; /* Old state. */
|
||||
unsigned short int c; /* Additive const. in congruential formula. */
|
||||
unsigned short int init; /* Flag for initializing. */
|
||||
unsigned long long int a; /* Factor in congruential formula. */
|
||||
};
|
||||
|
||||
/* Global state for non-reentrant functions. */
|
||||
|
||||
struct this_drand48_data libc_this_drand48_data;
|
||||
|
||||
static int this_nrand48_r (unsigned short int xsubi[3],
|
||||
struct this_drand48_data *buffer,
|
||||
long int *result);
|
||||
|
||||
/* Internal function to compute next state of the generator. */
|
||||
|
||||
static int this_drand48_iterate (unsigned short int xsubi[3],
|
||||
struct this_drand48_data *buffer);
|
||||
|
||||
static long int this_nrand48 (xsubi)
|
||||
unsigned short int xsubi[3];
|
||||
{
|
||||
long int result;
|
||||
|
||||
(void) this_nrand48_r (xsubi, &libc_this_drand48_data, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int this_nrand48_r (xsubi, buffer, result)
|
||||
unsigned short int xsubi[3];
|
||||
struct this_drand48_data *buffer;
|
||||
long int *result;
|
||||
{
|
||||
/* Compute next state. */
|
||||
if (this_drand48_iterate (xsubi, buffer) < 0)
|
||||
return -1;
|
||||
|
||||
/* Store the result. */
|
||||
if (sizeof (unsigned short int) == 2)
|
||||
*result = xsubi[2] << 15 | xsubi[1] >> 1;
|
||||
else
|
||||
*result = xsubi[2] >> 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int this_drand48_iterate (xsubi, buffer)
|
||||
unsigned short int xsubi[3];
|
||||
struct this_drand48_data *buffer;
|
||||
{
|
||||
uint64_t X;
|
||||
uint64_t result;
|
||||
|
||||
/* Initialize buffer, if not yet done. */
|
||||
if (!buffer->init)
|
||||
{
|
||||
buffer->a = 0x5deece66dull;
|
||||
buffer->c = 0xb;
|
||||
buffer->init = 1;
|
||||
}
|
||||
|
||||
/* Do the real work. We choose a data type which contains at least
|
||||
48 bits. Because we compute the modulus it does not care how
|
||||
many bits really are computed. */
|
||||
|
||||
X = (uint64_t) xsubi[2] << 32 | (uint32_t) xsubi[1] << 16 | xsubi[0];
|
||||
|
||||
result = X * buffer->a + buffer->c;
|
||||
|
||||
xsubi[0] = result & 0xffff;
|
||||
xsubi[1] = (result >> 16) & 0xffff;
|
||||
xsubi[2] = (result >> 32) & 0xffff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
lib/ldpc/rand.h
Executable file
54
lib/ldpc/rand.h
Executable file
@ -0,0 +1,54 @@
|
||||
/* RAND.H - Interface to random number generation 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.
|
||||
*/
|
||||
|
||||
|
||||
/* STATE OF RANDOM NUMBER GENERATOR. */
|
||||
|
||||
#define N_tables 5 /* Number of tables of real random numbers */
|
||||
|
||||
typedef struct
|
||||
{ int seed; /* Seed state derives from */
|
||||
int ptr[N_tables]; /* Pointers for tables of real random numbers */
|
||||
unsigned short state48[3]; /* State of 'rand48' pseudo-random generator */
|
||||
} rand_state;
|
||||
|
||||
|
||||
/* BASIC PSEUDO-RANDOM GENERATION PROCEDURES. */
|
||||
|
||||
void rand_seed (int); /* Initialize current state structure by seed */
|
||||
|
||||
void rand_use_state (rand_state *); /* Start using given state structure */
|
||||
rand_state *rand_get_state (void); /* Return pointer to current state */
|
||||
|
||||
int rand_word (void); /* Generate random 31-bit positive integer */
|
||||
|
||||
|
||||
/* GENERATORS FOR VARIOUS DISTRIBUTIONS. */
|
||||
|
||||
double rand_uniform (void); /* Uniform from [0,1) */
|
||||
double rand_uniopen (void); /* Uniform from (0,1) */
|
||||
|
||||
int rand_int (int); /* Uniform from 0, 1, ... (n-1) */
|
||||
int rand_pickd (double *, int); /* From 0 ... (n-1), with given distribution */
|
||||
int rand_pickf (float *, int); /* Same as above, but with floats */
|
||||
void rand_permutation (int *, int); /* Random permutation */
|
||||
|
||||
int rand_poisson (double); /* Poisson with given mean */
|
||||
double rand_gaussian (void); /* Gaussian with mean zero and unit variance */
|
||||
double rand_logistic (void); /* Logistic centred at zero with unit width */
|
||||
double rand_cauchy (void); /* Cauchy centred at zero with unit width */
|
||||
double rand_gamma (double); /* Gamma with given shape parameter */
|
||||
double rand_exp (void); /* Exponential with mean one */
|
||||
double rand_beta (double, double); /* Beta with given parameters */
|
||||
306
lib/ldpc/rand.html
Executable file
306
lib/ldpc/rand.html
Executable file
@ -0,0 +1,306 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> Random Variate Generation Routines </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> Random Variate Generation Routines </H1>
|
||||
|
||||
<P>This module provides facilities for basic pseudo-random number generation,
|
||||
and for generation of random variates from various common distributions.
|
||||
|
||||
<P>All the random generation procedures use the same underlying
|
||||
"stream" of random numbers. This stream is generated using the
|
||||
<TT>nrand48</TT> pseudo-random generation procedure found on most Unix
|
||||
systems, with the output being combined with a limited supply of real
|
||||
random numbers from the file "randfile" in the source
|
||||
directory for this software, in order to reduce the chances that the
|
||||
pseudo-random numbers aren't random enough.
|
||||
|
||||
<P>A pseudo-random number stream is determined by an integer
|
||||
<I>seed</I>, which is typically set by the user for each experimental
|
||||
run (eg, to 1, 2, 3, etc. for successive runs). The state of the
|
||||
random number stream can be saved in a structure of type
|
||||
<TT>rand_state</TT>, and later restored. For example, the state could
|
||||
be saved in a file at the end of a run, and restored if it is later
|
||||
decided that the run should be continued for longer.
|
||||
|
||||
<P>The methods for generating random variates from various distributions
|
||||
are mostly taken from the following reference:
|
||||
<BLOCKQUOTE>
|
||||
Devroye, L. (1986) <I>Non-Uniform Random Variate Generation</I>,
|
||||
New York: Springer-Verlag.
|
||||
</BLOCKQUOTE>
|
||||
The methods used here are not necessarily the fastest available. They were
|
||||
selected to be reasonably fast while also being easy to write.
|
||||
|
||||
<P><B>Header file required</B>: <TT>rand.h</TT>
|
||||
|
||||
|
||||
<A NAME="get-set-sec">
|
||||
<P><HR>
|
||||
<CENTER><BIG>Setting and saving the state</BIG></CENTER>
|
||||
</A>
|
||||
|
||||
|
||||
<A NAME="seed"><HR><B>rand_seed</B>:
|
||||
Set the state from an integer seed.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
void rand_seed
|
||||
( int seed; /* Seed to set state based on */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Sets the random number generator to a state that is determined from
|
||||
the integer <TT>seed</TT>. Setting the seed the same on two occasions,
|
||||
and then calling exactly the same sequence of random generation
|
||||
procedures, should produce exactly the same sequence of random
|
||||
variates. (Note: this may not be true, however, if computers with
|
||||
different architectures are used on the two occasions.)
|
||||
|
||||
<P>Sequential seeds should produce streams that are pretty much
|
||||
independent (unlike the situation for some pseudo-random number
|
||||
generators). Setting the seed randomly according to the time or day,
|
||||
or some such, without recording what it was, is <B>not</B>
|
||||
recommended, since the results are then not reproducible.
|
||||
|
||||
<P><A NAME="get_state"><HR><B>rand_get_state</B>:
|
||||
Get a pointer to the current state.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
rand_state *rand_get_state (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
Returns a pointer to the current state of the random number generator,
|
||||
which is a structure of type <TT>rand_state</TT>. The only use for this
|
||||
pointer is to use it to save a copy of the current state someplace.
|
||||
|
||||
|
||||
<P><A NAME="use_state"><HR><B>rand_use_state</B>:
|
||||
Set the state to use from now on.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
void rand_use_state
|
||||
( rand_state *state /* Pointer to a previously saved state */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
Sets the random number generator to the state pointed to by the argument.
|
||||
This state must be valid. The only way to get a valid state is by using
|
||||
<TT>rand_get_state</TT>.
|
||||
|
||||
|
||||
<A NAME="uniform-sec">
|
||||
<P><HR>
|
||||
<CENTER><BIG>Generating uniform random variates</BIG></CENTER>
|
||||
</A>
|
||||
|
||||
|
||||
<A NAME="uniform"><HR><B>rand_uniform</B>:
|
||||
Generate uniformly from [0,1).</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_uniform (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
Returns a random number that is uniformly distributed between 0 and 1,
|
||||
with a value of exactly 0 being possible, but with a value of exactly 1
|
||||
not being possible.
|
||||
|
||||
<P><A NAME="uniopen"><HR><B>rand_uniopen</B>:
|
||||
Generate uniformly from (0,1).</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_uniopen (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
Returns a random number that is uniformly distributed between 0 and 1,
|
||||
with neither a value of exactly 0 nor a value of exactly 1
|
||||
being possible.
|
||||
|
||||
|
||||
<A NAME="discrete-sec">
|
||||
<P><HR>
|
||||
<CENTER><BIG>Generating discrete random variates</BIG></CENTER>
|
||||
</A>
|
||||
|
||||
|
||||
<A NAME="int"><HR><B>rand_int</B>:
|
||||
Pick an integer uniformly from <I>0</I> to <I>n-1</I>.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
int rand_int
|
||||
( int n /* Number of integers (from 0) to pick from */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Randomly picks an integer from the set { <TT>0, 1, ..., n-1</TT> },
|
||||
with each integer being equally probable. The probabilities may
|
||||
become somewhat unequal, however, if <TT>n</TT> is very large,
|
||||
approaching 2<SUP><SMALL>31</SMALL></SUP>.
|
||||
|
||||
|
||||
<P><A NAME="pickd"><HR><B>rand_pickd</B>: Pick an integer from <I>0</I>
|
||||
to <I>n-1</I> with given probabilities (as doubles).</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
int rand_pickd
|
||||
( double *p, /* Array of probabilities, of length n */
|
||||
int n /* Number of integers (from 0) to pick from */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Randomly picks an integer from the set { <TT>0, 1, ..., n-1</TT> },
|
||||
with probabilities given by the array of double-precision numbers
|
||||
passed as the first argument. These numbers need not sum to one, but they
|
||||
must be non-negative, and must not all be zero. The actual
|
||||
probabilities used are obtained by dividing each number in this array
|
||||
by the sum of all the numbers.
|
||||
|
||||
<P>If one of the probabilities is exactly zero, it is guaranteed that
|
||||
the corresponding integer will not be picked.
|
||||
|
||||
|
||||
<P><A NAME="pickf"><HR><B>rand_pickf</B>: Pick an integer from <I>0</I>
|
||||
to <I>n-1</I> with given probabilities (as floats).</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
int rand_pickf
|
||||
( float *p, /* Array of probabilities, of length n */
|
||||
int n /* Number of integers (from 0) to pick from */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>This procedure is the same as <A HREF="#pickd"><TT>rand_pickd</TT></A>
|
||||
except that the array giving the probabilities is an array of single-precision
|
||||
floating point numbers, rather than double-precision.
|
||||
|
||||
|
||||
<A NAME="poisson"><HR><B>rand_poisson</B>:
|
||||
Generate a non-negative integer from a Poisson distribution.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
int rand_poisson
|
||||
( double lambda /* Mean of the Poisson distribution */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a non-negative integer from the Poisson distribution with mean
|
||||
<tt>lambda</tt>.
|
||||
|
||||
|
||||
<P><A NAME="permutation"><HR><B>rand_permutation</B>: Generate a random
|
||||
permutation of integers from <i>1</i> to <i>n</i>.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
int rand_permutation
|
||||
( int *perm, /* Place to store the permutation */
|
||||
int n /* Number of integers to permute */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Stores a random permutation of the integers from <i>1</i> to <i>n</i> in the
|
||||
array perm, which must be at least <i>n</i> long. All permutations are
|
||||
equally likely.
|
||||
|
||||
|
||||
<A NAME="continuous-sec">
|
||||
<P><HR>
|
||||
<CENTER><BIG>Generating continuous random variates</BIG></CENTER>
|
||||
</A>
|
||||
|
||||
|
||||
<A NAME="gaussian"><HR><B>rand_gaussian</B>:
|
||||
Generate a standard Gaussian (normal) random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_gaussian (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the Gaussian (normal) distribution
|
||||
with mean zero and standard deviation one, whose density function is
|
||||
proportional to exp(-<I>x<SUP><SMALL>2</SMALL></SUP></I>/2), with <I>x</I>
|
||||
being any real value.
|
||||
|
||||
|
||||
<A NAME="logistic"><HR><B>rand_logistic</B>:
|
||||
Generate a logistic random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_logistic (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the logistic distribution with
|
||||
location parameter zero and width parameter one, whose density
|
||||
function is proportional to
|
||||
exp(-<I>x</I>) / [1 + exp(-<I>x</I>)]<SUP><SMALL>2</SMALL></SUP>,
|
||||
with <I>x</I> being any real value.
|
||||
|
||||
|
||||
<P><A NAME="cauchy"><HR><B>rand_cauchy</B>:
|
||||
Generate a Cauchy random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_cauchy (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the Cauchy distribution with centre
|
||||
at zero and width one, whose density function is proportional to
|
||||
1 / (1+<I>x<SUP><SMALL>2</SMALL></SUP></I>), with <I>x</I> being any real value.
|
||||
|
||||
|
||||
<P><A NAME="gamma"><HR><B>rand_gamma</B>:
|
||||
Generate a gamma-distributed random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_gamma
|
||||
( double A /* Shape parameter */
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the gamma distribution with
|
||||
positive shape parameter <I>A</I>, whose density function is proportional
|
||||
to <I>x<SUP><SMALL>A-1</SMALL></SUP></I> exp(-<I>x</I>), with <I>x</I>
|
||||
being any positive real. This procedure will never return a value that is
|
||||
exactly zero.
|
||||
|
||||
|
||||
<P><A NAME="exp"><HR><B>rand_exp</B>:
|
||||
Generate an exponentially-distributed random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_exponential (void)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the exponential distribution with
|
||||
mean one, whose density function is exp(-<I>x</I>), with <I>x</I> being
|
||||
any positive real. This procedure will never return a value that is
|
||||
exactly zero.
|
||||
|
||||
<P>Note: This is a common special case of the gamma distribution.
|
||||
|
||||
|
||||
<P><A NAME="beta"><HR><B>rand_beta</B>:
|
||||
Generate a beta-distributed random variate.</A>
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
double rand_beta
|
||||
( double A, /* Parameters of distribution */
|
||||
double B
|
||||
)
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Generates a random value drawn from the beta distribution with positive
|
||||
parameters <I>A</I> and <I>B</I>, whose density function is proportional
|
||||
to <I>x<SUP><SMALL>A-1</SMALL></SUP>(1-x)<SUP><SMALL>B-1</SMALL></SUP></I>,
|
||||
with <I>x</I> being any real in the interval (0,1). This procedure
|
||||
will never return a value that is exactly zero or exactly one.
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
BIN
lib/ldpc/randfile
Executable file
BIN
lib/ldpc/randfile
Executable file
Binary file not shown.
200
lib/ldpc/rcode.c
Executable file
200
lib/ldpc/rcode.c
Executable file
@ -0,0 +1,200 @@
|
||||
/* RCODE.C - Procedures to read parity check and generator 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.
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
/* VARIABLES DECLARED IN RCODE.H. These global variables are set to
|
||||
representations of the parity check and generator matrices by read_pchk
|
||||
and read_gen. */
|
||||
|
||||
mod2sparse *H; /* Parity check matrix */
|
||||
|
||||
int M; /* Number of rows in parity check matrix */
|
||||
int N; /* Number of columns in parity check matrix */
|
||||
|
||||
char type; /* Type of generator matrix representation (s/d/m) */
|
||||
int *cols; /* Ordering of columns in generator matrix */
|
||||
|
||||
mod2sparse *L, *U; /* Sparse LU decomposition, if type=='s' */
|
||||
int *rows; /* Ordering of rows in generator matrix (type 's') */
|
||||
|
||||
mod2dense *G; /* Dense or mixed representation of generator matrix,
|
||||
if type=='d' or type=='m' */
|
||||
|
||||
|
||||
/* READ PARITY CHECK MATRIX. Sets the H, M, and N global variables. If an
|
||||
error is encountered, a message is displayed on standard error, and the
|
||||
program is terminated. */
|
||||
|
||||
void read_pchk
|
||||
( char *pchk_file
|
||||
)
|
||||
{
|
||||
FILE *f;
|
||||
|
||||
f = open_file_std(pchk_file,"rb");
|
||||
if (f==NULL)
|
||||
{ fprintf(stderr,"Can't open parity check file: %s\n",pchk_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (intio_read(f)!=('P'<<8)+0x80)
|
||||
{ fprintf(stderr,"File %s doesn't contain a parity check matrix\n",pchk_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
H = mod2sparse_read(f);
|
||||
|
||||
if (H==0)
|
||||
{ fprintf(stderr,"Error reading parity check matrix from %s\n",pchk_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
M = mod2sparse_rows(H);
|
||||
N = mod2sparse_cols(H);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
||||
/* READ GENERATOR MATRIX. The parity check matrix must have already been
|
||||
read, unless the last argument is set to 1. The generator matrix must be
|
||||
compatible with the parity check matrix, if it has been read. If the
|
||||
second argument is 1, only the column ordering (the last N-M of which are
|
||||
the indexes of the message bits) is read, into the 'cols' global variable.
|
||||
Otherwise, everything is read, into the global variables appropriate
|
||||
to the representation. The 'type' global variable is set to a letter
|
||||
indicating which represention is used.
|
||||
|
||||
If an error is encountered, a message is displayed on standard error,
|
||||
and the program is terminated. */
|
||||
|
||||
void read_gen
|
||||
( char *gen_file, /* Name of generator matrix file */
|
||||
int cols_only, /* Read only column ordering? */
|
||||
int no_pchk_file /* No parity check file used? */
|
||||
)
|
||||
{
|
||||
int M2, N2;
|
||||
FILE *f;
|
||||
int i;
|
||||
|
||||
f = open_file_std(gen_file,"rb");
|
||||
if (f==NULL)
|
||||
{ fprintf(stderr,"Can't open generator matrix file: %s\n",gen_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (intio_read(f)!=('G'<<8)+0x80)
|
||||
{ fprintf(stderr,"File %s doesn't contain a generator matrix\n",gen_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fread (&type, 1, 1, f) != 1) goto error;
|
||||
|
||||
M2 = intio_read(f);
|
||||
N2 = intio_read(f);
|
||||
|
||||
if (feof(f) || ferror(f)) goto error;
|
||||
|
||||
if (no_pchk_file)
|
||||
{ M = M2;
|
||||
N = N2;
|
||||
}
|
||||
else
|
||||
{ if (M2!=M || N2!=N)
|
||||
{ fprintf(stderr,
|
||||
"Generator matrix and parity-check matrix are incompatible\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
cols = chk_alloc (N, sizeof *cols);
|
||||
rows = chk_alloc (M, sizeof *rows);
|
||||
|
||||
for (i = 0; i<N; i++)
|
||||
{ cols[i] = intio_read(f);
|
||||
if (feof(f) || ferror(f)) goto error;
|
||||
}
|
||||
|
||||
if (!cols_only)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 's':
|
||||
{
|
||||
for (i = 0; i<M; i++)
|
||||
{ rows[i] = intio_read(f);
|
||||
if (feof(f) || ferror(f)) goto error;
|
||||
}
|
||||
|
||||
if ((L = mod2sparse_read(f)) == 0) goto error;
|
||||
if ((U = mod2sparse_read(f)) == 0) goto error;
|
||||
|
||||
if (mod2sparse_rows(L)!=M || mod2sparse_cols(L)!=M) goto garbled;
|
||||
if (mod2sparse_rows(U)!=M || mod2sparse_cols(U)<M) goto garbled;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd':
|
||||
{
|
||||
if ((G = mod2dense_read(f)) == 0) goto error;
|
||||
|
||||
if (mod2dense_rows(G)!=M || mod2dense_cols(G)!=N-M) goto garbled;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'm':
|
||||
{
|
||||
if ((G = mod2dense_read(f)) == 0) goto error;
|
||||
|
||||
if (mod2dense_rows(G)!=M || mod2dense_cols(G)!=M) goto garbled;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{ fprintf(stderr,
|
||||
"Unknown type of generator matrix in file %s\n",gen_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
return;
|
||||
|
||||
error:
|
||||
fprintf(stderr,"Error reading generator matrix from file %s\n",gen_file);
|
||||
exit(1);
|
||||
|
||||
garbled:
|
||||
fprintf(stderr,"Garbled generator matrix in file %s\n",gen_file);
|
||||
exit(1);
|
||||
}
|
||||
37
lib/ldpc/rcode.h
Executable file
37
lib/ldpc/rcode.h
Executable file
@ -0,0 +1,37 @@
|
||||
/* RCODE.H - Parity chk and gen matrix storage, and procedures to read them.*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
|
||||
/* VARIABLES HOLDING DATA READ. These are declared for real in rcode.c. */
|
||||
|
||||
extern mod2sparse *H; /* Parity check matrix */
|
||||
|
||||
extern int M; /* Number of rows in parity check matrix */
|
||||
extern int N; /* Number of columns in parity check matrix */
|
||||
|
||||
extern char type; /* Type of generator matrix representation */
|
||||
extern int *cols; /* Ordering of columns in generator matrix */
|
||||
|
||||
extern mod2sparse *L, *U; /* Sparse LU decomposition, if type=='s' */
|
||||
extern int *rows; /* Ordering of rows in generator matrix (type 's') */
|
||||
|
||||
extern mod2dense *G; /* Dense or mixed representation of generator matrix,
|
||||
if type=='d' or type=='m' */
|
||||
|
||||
|
||||
/* PROCEDURES FOR READING DATA. */
|
||||
|
||||
void read_pchk (char *);
|
||||
void read_gen (char *, int, int);
|
||||
58
lib/ldpc/refs.html
Executable file
58
lib/ldpc/refs.html
Executable file
@ -0,0 +1,58 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> References on Low Density Parity Check Codes </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> References on Low Density Parity Check Codes </H1>
|
||||
|
||||
Robert Gallager's original work on low density parity check codes was published
|
||||
as the following book, based his doctoral dissertation, and a related paper:
|
||||
<BLOCKQUOTE>
|
||||
<P>Gallager, R. G. (1963) <I>Low Density Parity Check Codes</I>,
|
||||
Cambridge, MA: MIT Press.
|
||||
<P>Gallager, R. G. (1962) ``Low-density parity-check codes'', <I>IRE
|
||||
Transactions on Information Theory</I>, vol. IT-8, pp. 21-28.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
More recent work on these codes by David MacKay and myself was published
|
||||
as follows:
|
||||
<BLOCKQUOTE>
|
||||
<P>MacKay, D. J. C. and Neal, R. M. (1996) ``Near Shannon limit performance
|
||||
of low density parity check codes'', <I>Electronics Letters</I>,
|
||||
vol. 32, pp. 1645-1646. Reprinted with printing errors corrected
|
||||
in vol. 33, pp. 457-458.
|
||||
<P>MacKay, D. J. C. (1999) ``Good error-correcting codes based on very
|
||||
sparse matrices'', <I>IEEE Transactions on Information Theory</I>,
|
||||
vol. 45, pp. 399-431.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
The decoding algorithms described in the above references can visualized
|
||||
in terms of a ``factor graph'' representation of the code, as described
|
||||
in the following paper:
|
||||
<BLOCKQUOTE>
|
||||
<P>Kschischang, F. R., Frey, B. J., and Loeliger, H.-A. (1998) ``Factor graphs
|
||||
and the sum-product algorithm'', <I>IEEE Transactions on Information
|
||||
Theory</I>, vol. 47, pp. 498-519.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
I presented the application of sparse matrix techniques to encoding of
|
||||
LDPC codes at the IMA workshop on Codes, Systems and Graphical Models,
|
||||
Minneapolis, 1999. You can view the slides of this talk <A
|
||||
HREF="sparse-encode.pdf">here</A>. <B>Note</B>: Due to a bug in the
|
||||
program I used then, the results shown for the minimal product heuristic in
|
||||
these slides are somewhat worse than the actual performance. For instance,
|
||||
the number of bit operations per check bit for for <I>M</I>=3200 with
|
||||
3 checks per bit is actually around 12.7, not the value around 17 shown
|
||||
on one of the slides.
|
||||
|
||||
<P>Text and references to many more recent and classical papers can be
|
||||
obtained via the <A HREF="http://www.ima.umn.edu/csg/">IMA workshop's
|
||||
web page</A>.
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
244
lib/ldpc/release.html
Executable file
244
lib/ldpc/release.html
Executable file
@ -0,0 +1,244 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE>Release Notes for LDPC-codes Software</TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1>Release Notes for LDPC-codes Software</H1>
|
||||
|
||||
These notes describe all the stable public releases of this software. Old
|
||||
and future releases can be obtained via
|
||||
<BLOCKQUOTE>
|
||||
<A HREF="http://www.cs.toronto.edu/~radford/ldpc.software.html">
|
||||
<TT>http://www.cs.toronto.edu/~radford/ldpc.software.html</TT></A>
|
||||
</BLOCKQUOTE>
|
||||
The current development version is now maintained at
|
||||
<BLOCKQUOTE>
|
||||
<A HREF="http://github.com/radfordneal/LDPC-codes">
|
||||
<TT>http://github.com/radfordneal/LDPC-code</TT></A>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<H2>Version of 2012-02-11.</H2>
|
||||
This version has a few bug fixes and some minor new features. The major
|
||||
change is that a source repository for the software is now hosted
|
||||
at github.com, making it easier for people to create and release
|
||||
their own versions of this software.
|
||||
<OL>
|
||||
<LI> Changed the copyright notice (in the file COPYRIGHT, and elsewhere)
|
||||
to remove the requirement that my web site be referenced. (Nowadays,
|
||||
I think users should have no problem finding the sources using a
|
||||
search engine.)
|
||||
<LI> Included a copy of the nrand48 routine from the GNU C library
|
||||
in the rand.c module, to ensure that it is always available
|
||||
and always the same. (This isn't so on some versions of cygwin.)
|
||||
<LI> Added a -f option to encode and decode that forces flushing
|
||||
after writing each block. Useful for allowing encode or
|
||||
decode to be used as a server, reading and writing blocks
|
||||
from named pipes.
|
||||
<LI> Added a -z option for pchk-to-alist to suppress output of 0
|
||||
row and column indexes that pad up to the maximum number used.
|
||||
<LI> Documented the previously undocumented -t options for pchk-to-alist
|
||||
and alist-to-pchk.
|
||||
<LI> Changed alist-to-pchk so that it no longer requires zero indexes
|
||||
that pad out to the maximum needed for a row or column (thanks
|
||||
to Monica Kolb for suggesting this).
|
||||
<LI> Changed mod2word type in mod2dense.c to uint32_t, to avoid
|
||||
wasted space when long is 64 bits (thanks to Mathieu Cunche
|
||||
and Vincent Roca for suggesting this).
|
||||
<LI> Fixed bug in distrib.c affecting distributions with a single
|
||||
number (thanks to Mike Vicuna for pointing it out).
|
||||
<LI> Fixed bug in -t option for pchk-to-alist (thanks to Andrea Fontana
|
||||
for reporting this).
|
||||
<LI> Fixed references in the documentation to mod2sparse_multvec
|
||||
that should be to mod2sparse_mulvec (thanks to Andrea Fontana
|
||||
for reporting this).
|
||||
</OL>
|
||||
|
||||
|
||||
<H2>Version of 2006-02-08.</H2>
|
||||
|
||||
The copyright notice has been changed in this release to no longer
|
||||
restrict use to purposes of research or education. The new copyright
|
||||
notice can be read <A HREF="index.html#copyright">here</A>. It is now
|
||||
possible to create LDPC codes with varying numbers of checks per bit
|
||||
(an extension based on work by Peter Junteng Liu). New programs for
|
||||
converting to and from the <A
|
||||
HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
|
||||
format</A> for parity check matrices, used by David MacKay and others,
|
||||
have also been added.
|
||||
|
||||
<P>The following new features have been added:
|
||||
<OL>
|
||||
<LI> The <A HREF="pchk.html#make-ldpc"><TT>make-ldpc</TT></A> program can
|
||||
new create LDPC codes with varying numbers of checks per bit. The
|
||||
<A HREF="examples.html">examples</A> now include a code of this sort.
|
||||
<LI> New programs <A HREF="pchk.html#pchk-to-alist"><TT>pchk-to-alist</TT></A>
|
||||
and <A HREF="pchk.html#alist-to-pchk"><TT>alist-to-pchk</TT></A> have
|
||||
been added, which convert to and from <A
|
||||
HREF="http://www.inference.phy.cam.ac.uk/mackay/codes/alist.html">alist
|
||||
format</A>.
|
||||
<LI> A <A HREF="run-examples"><TT>run-examples</TT></A> script has been
|
||||
added, which runs all the <A HREF="examples.html">examples</A> and
|
||||
compares with the saved output that I obtained.
|
||||
</OL>
|
||||
|
||||
|
||||
<H2>Version of 2001-11-18.</H2>
|
||||
|
||||
This is a minor release, whose main purpose is fixing bug (1) below.
|
||||
Also, this release has been tested and found to work with the <A
|
||||
HREF="http://www.cygwin.com">cygwin</A> Unix environment that runs
|
||||
under Microsoft Windows.
|
||||
|
||||
<P>The following new feature has been added:
|
||||
<OL>
|
||||
<LI> A new <B>-t</B> option has been added to
|
||||
<A HREF="pchk.html#print-pchk"><TT>print-pchk</TT></A>, which
|
||||
causes it to print the transpose of the parity check matrix.
|
||||
</OL>
|
||||
|
||||
The following program module change was made:
|
||||
<OL>
|
||||
|
||||
<LI> The behaviour of <A
|
||||
HREF="mod2dense.html#invert_selected">mod2dense_invert_selected</A>
|
||||
has been changed when the matrix has dependent rows. The result returned
|
||||
contains the inverse of a sub-matrix in its initial columns. The contents
|
||||
of the remaining columns up to the number of rows was previously undefined,
|
||||
but these columns are now set to contain zeros. This was done to fix
|
||||
bug (1) below.
|
||||
</OL>
|
||||
|
||||
The following bugs were fixed:
|
||||
<OL>
|
||||
<LI> A bug has been fixed in
|
||||
<A HREF="encoding.html#make-gen"><TT>make-gen</TT></A>
|
||||
which sometimes
|
||||
produced invalid `dense' or `mixed' generator matrices when the parity
|
||||
check matrix had redundant rows.
|
||||
The `sparse' generator matrices were not affected. The output of the
|
||||
<A HREF="ex-dep"><TT>ex-dep</TT></A> example has changed slightly as a
|
||||
result.
|
||||
<LI> The open mode for reading the file of random numbers has been changed from
|
||||
"r" to "rb", for compatibility with non-Unix systems.
|
||||
<LI> <A HREF="mod2sparse.html#copy"><TT>mod2sparse_copy</TT></A> has
|
||||
been fixed so that it copies the <B>lr</B> and <B>pr</B> fields
|
||||
of entries.
|
||||
<LI> The "set -v -e" in the command files for the examples has
|
||||
been replaced by two commands, "set -e" and "set -v", since some
|
||||
shells can't set two options at once.
|
||||
</OL>
|
||||
|
||||
A few minor fixes to the documentation have also been made.
|
||||
|
||||
|
||||
<H2>Version of 2001-05-04.</H2>
|
||||
|
||||
Changes and new features regarding programs and associated
|
||||
documentation and examples:
|
||||
<OL>
|
||||
<LI> Warnings have been added to the documentation about the dangers of
|
||||
using zero codewords for testing (due to the possibility of the decoder
|
||||
accidently being non-symmetric). The examples have been changed to
|
||||
not use zero codewords, except for
|
||||
<A HREF="ex-ham7a"><TT>ex-ham7a</TT></A>, which still
|
||||
demonstrates this facility.
|
||||
<LI> Decoding by probability propagation has been changed so that if
|
||||
a probability ratio gets set to NaN ("not a number", the result of
|
||||
infinite but conflicting evidence from different sources), the probability
|
||||
ratio is changed to 1, in hopes that something sensible may result.
|
||||
<LI> The decoding procedures have been changed to decode a bit to a 1 if
|
||||
there is a tie, so that any resulting asymmetry in decoding will
|
||||
make zero decoding less, rather than more, likely. See point (1) above.
|
||||
<LI> All programs now allow a file name argument to be "-", which specifies
|
||||
standard input or standard output, as appropriate. The
|
||||
<A HREF="ex-ldpc36-5000a"><TT>ex-ldpc36-5000a</TT></A> example has been
|
||||
changed to use this facility in order to avoid creating lots of files.
|
||||
<LI> Channels with noise from a logistic distribution (AWLN) have been
|
||||
implemented. For details,
|
||||
see the <A HREF="channel.html">channel documentation</A>.
|
||||
<LI> The <B>make-gen</B> program for "dense" or "mixed" options was modified
|
||||
so that when some parity checks are redundant, others are not declared
|
||||
redundant when they aren't. This makes the result compatible with
|
||||
what is obtained with the "sparse" option. The example in the
|
||||
<A HREF="dep-H.html">discussion of linear dependence in parity check
|
||||
matrices</A> has changed slightly as a result.
|
||||
<LI> The messages displayed by the <A HREF="decoding.html#decode">decode</A>
|
||||
program have changed slightly: The block size is no longer displayed,
|
||||
and the percentage of bits changed is now shown. The data output
|
||||
when the <B>-t</B> option is specified now includes the number of
|
||||
bits changed in each block.
|
||||
<LI> A new <B>-T</B> option to <A HREF="decoding.html#decode">decode</A>
|
||||
for displaying
|
||||
<A HREF="decode-detail.html">detailed information on decoding</A>
|
||||
has been added.
|
||||
<LI> Doing a <B>make clean</B> will now remove the files created
|
||||
by running the <A HREF="examples.html">examples</A>.
|
||||
<LI> The files created by the <A HREF="examples.html">examples</A> now
|
||||
start with "<TT>ex-</TT>" and contain a ".", to make them easier to
|
||||
identify for cleanup, and the saved output file now ends in
|
||||
"<TT>-out</TT>" rather than "<TT>.out</TT>".
|
||||
<LI> The scripts for the examples now use the <B>-v</B> option of <B>set</B>
|
||||
rather than <B>-x</B>, so that the command lines are echoed
|
||||
faithfully as they are read.
|
||||
<LI> Two new <A HREF="examples.html">examples</A> have been added:
|
||||
<TT>ex-dep</TT> demonstrates what happens when parity check matrices
|
||||
have redundant row, and <TT>ex-wrong-model</TT> investigates what
|
||||
happens when the wrong model is used to decode.
|
||||
</OL>
|
||||
Changes and new features regarding program modules and other internals:
|
||||
<OL>
|
||||
<LI> Instructions have been added on
|
||||
<A HREF="modify.html">how to modify the programs</A>, and some
|
||||
code has been reorganized to facilitate modifications.
|
||||
<LI> The makefile has been made trivial, simply recompiling everything
|
||||
from scratch every time. This is simpler and less error prone
|
||||
than putting in dependencies.
|
||||
Compiling all the programs takes only about five seconds on a
|
||||
modern PC.
|
||||
<LI> The
|
||||
<A HREF="mod2dense.html#invert_selected"><TT>mod2dense_invert_selected</TT></A>
|
||||
procedure has been changed
|
||||
to take an additional argument in which a permutation of rows is
|
||||
returned. This extension is needed in order for the result when
|
||||
the matrix is not of full rank to include as many rows as possible,
|
||||
as needed for the above modification of <B>make-gen</B>.
|
||||
<LI> New routines
|
||||
<A HREF="mod2dense.html#copyrows"><TT>mod2dense_copyrows</TT></A> and
|
||||
<A HREF="mod2sparse.html#copyrows"><TT>mod2sparse_copyrows</TT></A> have
|
||||
been added, analogous to the previous routines for copying columns.
|
||||
<LI> The decoding procedures have been changed to always return the bit
|
||||
probabilities (previously, one could pass a null pointer to suppress
|
||||
this). This makes things simpler, and facilitates the production of
|
||||
detailed trace output when the <B>-T</B> option is used.
|
||||
</OL>
|
||||
|
||||
The following bugs were fixed:
|
||||
<OL>
|
||||
<LI> A problem with <B>print-gen</B> prevented the <B>-d</B> option from working
|
||||
in most cases. The documentation was also fixed to note what
|
||||
the <B>L</B> and <B>U</B> matrices printed will look like.
|
||||
<LI> The documentation for
|
||||
<A HREF="mod2sparse.html#copycols"><TT>mod2sparse_copycols</TT></A> and
|
||||
<A HREF="mod2dense.html#copycols"><TT>mod2dense_copycols</TT></A>
|
||||
was ambiguous. It has been clarified. The dense and sparse
|
||||
implementations were inconsistent. The sparse version has been changed
|
||||
to match the dense version, which was and is the only version actually
|
||||
used in the LDPC software.
|
||||
<LI> In <TT>decode.c</TT>, a variable declared to be <TT>float</TT> was printed
|
||||
using "<TT>%f</TT>", which strangely didn't work with one compiler.
|
||||
It's now declared as <TT>double</TT>.
|
||||
</OL>
|
||||
|
||||
There were also numerous minor cleanups of program code and documentation.
|
||||
|
||||
<H2>Version of 2000-03-19.</H2>
|
||||
|
||||
This was the first public release.
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
12
lib/ldpc/run-examples
Executable file
12
lib/ldpc/run-examples
Executable file
@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Run all the examples, and check the output against the corresponding -out
|
||||
# file. Note that slight differences are possible when the examples are
|
||||
# run on different machines, due to slightly different round-off errors.
|
||||
|
||||
for e in `ls ex-* | grep -v "\\." | grep -v .-out`
|
||||
do
|
||||
echo Running $e:
|
||||
$e 2>&1 | diff ${e}-out -
|
||||
echo " "
|
||||
done
|
||||
90
lib/ldpc/sparse-LU.html
Executable file
90
lib/ldpc/sparse-LU.html
Executable file
@ -0,0 +1,90 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> Sparse LU Decomposition Methods </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> Sparse LU Decomposition Methods </H1>
|
||||
|
||||
<P>The sparse modulo-2 matrix LU decomposition routine <A
|
||||
HREF="mod2sparse.html#decomp"><TT>mod2sparse_decomp</TT></A> (which
|
||||
is used by the <A HREF="encoding.html#make-gen"><TT>make-gen</TT></A>
|
||||
program when it is asked to create a sparse generator matrix) tries to
|
||||
find an sub-matrix of a matrix (for <TT>make-gen</TT>, the parity
|
||||
check matrix), and an ordering of rows and columns for this
|
||||
sub-matrix, that leads to the lower-triangular matrix <B>L</B> and the
|
||||
upper-triangular matrix <B>U</B> making up the LU decomposition being
|
||||
as sparse as possible. Finding an optimal solution is too difficult,
|
||||
so instead a heuristic strategy is used.
|
||||
|
||||
<P>The overall algorithm finds <B>L</B> and <B>U</B> a column at a
|
||||
time, from left to right (as reordered, in the case of <B>U</B>). As
|
||||
this is done, a copy, <B>B</B>, of the original matrix is modified.
|
||||
To create column <I>i</I> of <B>L</B> and <B>U</B>, some element with
|
||||
value 1 in <B>B</B> whose row and column indexes, after reordering,
|
||||
are both greater than <I>i</I> is found. The row and column of this
|
||||
element are considered to come next in the reordering, and the
|
||||
contents of the column containing this element is copied to <B>L</B>
|
||||
and <B>U</B> (upper elements going to <B>U</B>, lower to <B>L</B>).
|
||||
The row containing this element is then added to some later rows so as
|
||||
to clear the lower part of this column to zeros.
|
||||
|
||||
<P>At the first step of this process - selecting an element with value
|
||||
1 from the later rows and columns - there will often be several
|
||||
possibilities. Different choices can lead to the final result being
|
||||
more or less sparse. The possible strategies for picking an element
|
||||
are identified by the constants <TT>Mod2sparse_first</TT>,
|
||||
<TT>Mod2sparse_mincol</TT>, and <TT>Mod2sparse_minprod</TT>. These
|
||||
strategies operate as follows:
|
||||
|
||||
<P><TT>Mod2sparse_first</TT>
|
||||
<BLOCKQUOTE>
|
||||
Select the first element with value 1 that is encountered in a top
|
||||
to bottom, left to right search.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><TT>Mod2sparse_mincol</TT>
|
||||
<BLOCKQUOTE>
|
||||
Select the first element with value 1 that is contained in a column
|
||||
of <B>B</B> that has the smallest number of 1s of any column.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P><TT>Mod2sparse_minprod</TT>
|
||||
<BLOCKQUOTE>
|
||||
Select an element with value 1 for which the product of the number of
|
||||
1s in that row of <B>B</B> minus one times the number of 1s in that
|
||||
column of <B>B</B> minus one is as small as possible.
|
||||
</BLOCKQUOTE>
|
||||
|
||||
<P>The <B>abandon_number</B> and <B>abandon_when</B> parameters can
|
||||
modify the basic strategy. If <B>abandon_number</B> is greater than
|
||||
zero, then after <B>abandon_when</B> columns have been selected,
|
||||
<B>abandon_number</B> of the remaining columns are abandoned as
|
||||
candidates for possible future selection, the abandoned columns being
|
||||
those with the greatest number of entries. Abandoning such columns
|
||||
saves space and time, but may make the final result less sparse than
|
||||
it would otherwise be, and can possibly result in the matrix appearing
|
||||
to have lower rank than it actually has.
|
||||
|
||||
<P>The methods described here are fairly straightforward adaptations
|
||||
of standard methods for sparse square matrices of reals, as described, for
|
||||
example, in
|
||||
<BLOCKQUOTE>
|
||||
I. S. Duff, A. M. Erisman, J. K. Reid (1986) <I>Direct Methods for
|
||||
Sparse Matrices</I>, Oxford: Clarendon Press.
|
||||
</BLOCKQUOTE>
|
||||
In the coding context, however, we are interested in matrices of
|
||||
modulo-2 elements, and it is enough to find a sparse LU decomposition
|
||||
of any square sub-matrix that can be obtained by selecting columns of
|
||||
the rectangular parity check matrix. I talked about the application
|
||||
of sparse matrix methods to encoding of LDPC codes at the 1999 IMA
|
||||
workshop on Codes, Systems and Graphical Models (see the <A
|
||||
HREF="refs.html">references</A>).
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
BIN
lib/ldpc/sparse-encode.pdf
Executable file
BIN
lib/ldpc/sparse-encode.pdf
Executable file
Binary file not shown.
100
lib/ldpc/support.html
Executable file
100
lib/ldpc/support.html
Executable file
@ -0,0 +1,100 @@
|
||||
<HTML><HEAD>
|
||||
|
||||
<TITLE> Support Programs </TITLE>
|
||||
|
||||
</HEAD><BODY>
|
||||
|
||||
|
||||
<H1> Support Programs </H1>
|
||||
|
||||
The following programs provide support for testing and performance
|
||||
assessment.
|
||||
|
||||
|
||||
<P><A NAME="rand-src"><HR><B>rand-src</B>: Generate random message bits.
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
rand-src <I>source-file seed n-bits</I>
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Creates a file of random messages bits called
|
||||
<TT><I>source-file</I></TT>, which is suitable for testing the
|
||||
correctness and performance of other programs. The bits in the file
|
||||
are independent, and are equally likely to be 0 or 1. They are
|
||||
generated pseudo-randomly based on <TT><I>seed</I></TT>. The actual
|
||||
random number seed used will be <TT><I>seed</I></TT> times 10 plus 2,
|
||||
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 <TT><I>n-bits</I></TT> argument specifies the number of bits to
|
||||
produce. It can be a single number, or it can consist of a block size
|
||||
and a number of blocks, written with <TT>x</TT> separating these
|
||||
numbers, with no spaces. Each block is written as a single line, with
|
||||
the bits in the block represented by the characters '0' and '1', with
|
||||
no intervening spaces. If the bit count is given by a single number,
|
||||
the block size is assumed to be one.
|
||||
|
||||
<P><B>Example:</B> The following command produces a file containing
|
||||
3 blocks, each consisting of 15 random bits, produced using the pseudo-random
|
||||
number stream identified by the <TT><I>seed</I></TT> of 17:
|
||||
<UL><PRE>
|
||||
<LI>rand-src rsrc 17 15x3
|
||||
</PRE></UL>
|
||||
The contents of the file <TT>rsrc</TT> after this command might be something
|
||||
like the following:
|
||||
<BLOCKQUOTE><PRE>
|
||||
111011000110000
|
||||
010010110010111
|
||||
100000000000111
|
||||
</BLOCKQUOTE></PRE>
|
||||
|
||||
|
||||
<P><A NAME="verify"><HR><B>verify</B>: Verify that decoded blocks are
|
||||
codewords, and that they match the source.
|
||||
|
||||
<BLOCKQUOTE><PRE>
|
||||
verify [ -t ] <I>pchk-file decoded-file</I> [ <I>gen-file</I> [ <I>source-file</I> ] ]
|
||||
</PRE></BLOCKQUOTE>
|
||||
|
||||
<P>Checks whether or not the blocks in <TT><I>decoded-file</I></TT>
|
||||
are codewords, according to the parity check matrix in
|
||||
<TT><I>pchk-file</I></TT>. If <TT><I>gen-file</I></TT> is specified,
|
||||
the message bits of the blocks are also checked against the
|
||||
corresponding blocks of <TT><I>source-file</I></TT>, or against zero
|
||||
if <TT><I>source-file</I></TT> is not given. (Normally, one would
|
||||
leave out <TT><I>source-file</I></TT> only if the <A
|
||||
HREF="channel.html#transmit"><TT>transmit</TT></A> command was used
|
||||
with an argument specifying that zeros are to be transmitted, rather
|
||||
than a file of encoded data.)
|
||||
|
||||
<P>A summary of the results is displayed on standard error, giving the
|
||||
total numbers of blocks, the number with parity check errors, and, if
|
||||
<TT><I>gen-file</I></TT> was specified, the number of blocks with
|
||||
source errors and the number with errors of both kinds. If
|
||||
<TT><I>gen-file</I></TT> was specified, a second
|
||||
summary line displays the bit error rate from
|
||||
comparing the decoded message bits with the true message bits (zeros
|
||||
if no <TT><I>source file</I></TT> was given).
|
||||
|
||||
<P>If the <B>-t</B> option is given, block-by-block results are
|
||||
printed on standard output in two or three columns, giving the block
|
||||
number (from zero), the number of parity check errors for that block,
|
||||
and the number of errors in source bits. The last column is omitted
|
||||
if <TT><I>gen-file</I></TT> is not specified. The columns are
|
||||
preceded by a line of headers, so the file 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>Warning messages are displayed on standard error if the number of
|
||||
bits in <TT><I>decoded-file</I></TT> is not a multiple of the block
|
||||
length, or if <TT><I>source-file</I></TT> is too short. Newlines
|
||||
in these files are ignored, even though they would normally occur
|
||||
at the ends of blocks.
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="index.html">Back to index for LDPC software</A>
|
||||
|
||||
</BODY></HTML>
|
||||
170
lib/ldpc/transmit.c
Executable file
170
lib/ldpc/transmit.c
Executable file
@ -0,0 +1,170 @@
|
||||
/* TRANSMIT.C - Simulate transmission of bits through a channel. */
|
||||
|
||||
/* 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"
|
||||
#include "open.h"
|
||||
#include "rand.h"
|
||||
|
||||
void usage(void);
|
||||
|
||||
|
||||
/* MAIN PROGRAM. */
|
||||
|
||||
int main
|
||||
( int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
char *tfile, *rfile;
|
||||
FILE *tf, *rf;
|
||||
int block_size, n_bits;
|
||||
char junk;
|
||||
int seed;
|
||||
int cnt;
|
||||
int n, b;
|
||||
|
||||
/* Look at arguments. The arguments specifying the channel are looked
|
||||
at by channel_parse in channel.c */
|
||||
|
||||
if (!(tfile = argv[1])
|
||||
|| !(rfile = argv[2])
|
||||
|| !argv[3] || sscanf(argv[3],"%d%c",&seed,&junk)!=1)
|
||||
{ usage();
|
||||
}
|
||||
|
||||
n = channel_parse(argv+4,argc-4);
|
||||
if (n<=0 || argc-4-n!=0)
|
||||
{ usage();
|
||||
}
|
||||
|
||||
/* See if the source is all zeros or a file. */
|
||||
|
||||
if (sscanf(tfile,"%d%c",&n_bits,&junk)==1 && n_bits>0)
|
||||
{ block_size = 1;
|
||||
tf = NULL;
|
||||
}
|
||||
else if (sscanf(tfile,"%dx%d%c",&block_size,&n_bits,&junk)==2
|
||||
&& block_size>0 && n_bits>0)
|
||||
{ n_bits *= block_size;
|
||||
tf = NULL;
|
||||
}
|
||||
else
|
||||
{ tf = open_file_std(tfile,"r");
|
||||
if (tf==NULL)
|
||||
{ fprintf(stderr,"Can't open encoded file to transmit: %s\n",tfile);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open output file. */
|
||||
|
||||
rf = open_file_std(rfile,"w");
|
||||
if (rf==NULL)
|
||||
{ fprintf(stderr,"Can't create file for received data: %s\n",rfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Set random seed to avoid duplications with other programs. */
|
||||
|
||||
rand_seed(10*seed+3);
|
||||
|
||||
/* Transmit bits. */
|
||||
|
||||
for (cnt = 0; ; cnt++)
|
||||
{
|
||||
/* Get next bit to transmit. */
|
||||
|
||||
if (tf) /* Data comes from a file */
|
||||
{
|
||||
for (;;)
|
||||
{ b = getc(tf);
|
||||
if (b!=' ' && b!='\t' && b!='\n' && b!='\r')
|
||||
{ break;
|
||||
}
|
||||
putc(b,rf);
|
||||
}
|
||||
|
||||
if (b==EOF) break;
|
||||
|
||||
if (b!='0' && b!='1')
|
||||
{ fprintf(stderr,"Bad character (code %d) file being transmitted\n",b);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
else /* Data is all zeros */
|
||||
{
|
||||
if (cnt>0 && cnt%block_size==0)
|
||||
{ putc('\n',rf);
|
||||
}
|
||||
|
||||
if (cnt==n_bits) break;
|
||||
|
||||
b = '0';
|
||||
}
|
||||
|
||||
b = b=='1';
|
||||
|
||||
/* Produce the channel output for this transmitted bit. */
|
||||
|
||||
switch (channel)
|
||||
{ case BSC:
|
||||
{ int bsc_noise;
|
||||
bsc_noise = rand_uniform() < error_prob;
|
||||
fprintf (rf, "%d", b^bsc_noise);
|
||||
break;
|
||||
}
|
||||
case AWGN:
|
||||
{ double awgn_noise;
|
||||
awgn_noise = std_dev * rand_gaussian();
|
||||
fprintf (rf, " %+5.2f", b ? 1+awgn_noise : -1+awgn_noise);
|
||||
break;
|
||||
}
|
||||
case AWLN:
|
||||
{ double awln_noise;
|
||||
awln_noise = lwidth * rand_logistic();
|
||||
fprintf (rf, " %+5.2f", b ? 1+awln_noise : -1+awln_noise);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{ abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr,"Transmitted %d bits\n",cnt);
|
||||
|
||||
if (ferror(rf) || fclose(rf)!=0)
|
||||
{ fprintf(stderr,"Error writing received bits to %s\n",rfile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,
|
||||
"Usage: transmit encoded-file|n-zeros received-file seed channel\n");
|
||||
channel_usage();
|
||||
exit(1);
|
||||
}
|
||||
254
lib/ldpc/verify.c
Executable file
254
lib/ldpc/verify.c
Executable file
@ -0,0 +1,254 @@
|
||||
/* VERIFY.C - Verify encoded or decoded 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"
|
||||
#include "check.h"
|
||||
|
||||
void usage(void);
|
||||
|
||||
|
||||
/* MAIN PROGRAM. */
|
||||
|
||||
int main
|
||||
( int argc,
|
||||
char **argv
|
||||
)
|
||||
{
|
||||
char *coded_file, *source_file;
|
||||
char *pchk_file, *gen_file;
|
||||
int table;
|
||||
|
||||
char *sblk, *cblk, *chks;
|
||||
int seof, ceof;
|
||||
int srcerr, chkerr, bit_errs;
|
||||
int i, n;
|
||||
FILE *srcf, *codef;
|
||||
|
||||
int tot_srcerrs, tot_chkerrs, tot_botherrs, tot_undeterrs, tot_good;
|
||||
|
||||
/* Look at arguments. */
|
||||
|
||||
table = 0;
|
||||
if (argc>1 && strcmp(argv[1],"-t")==0)
|
||||
{ table = 1;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
}
|
||||
|
||||
if (argc<3 || argc>5) usage();
|
||||
|
||||
if (!(pchk_file = argv[1])
|
||||
|| !(coded_file = argv[2]))
|
||||
{ usage();
|
||||
}
|
||||
|
||||
gen_file = 0;
|
||||
source_file = 0;
|
||||
|
||||
if (argv[3])
|
||||
{ gen_file = argv[3];
|
||||
if (argv[4])
|
||||
{ source_file = argv[4];
|
||||
if (argv[5])
|
||||
{ usage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((strcmp(pchk_file,"-")==0)
|
||||
+ (strcmp(coded_file,"-")==0)
|
||||
+ (source_file!=0 && strcmp(source_file,"-")==0)
|
||||
+ (gen_file!=0 && strcmp(gen_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,
|
||||
"Number of bits (%d) should be greater than number of checks (%d)\n",N,M);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read generator matrix file, if given, up to the point of finding
|
||||
out which are the message bits. */
|
||||
|
||||
if (gen_file!=0)
|
||||
{ read_gen(gen_file,1,0);
|
||||
}
|
||||
|
||||
/* Open coded file to check. */
|
||||
|
||||
codef = open_file_std(coded_file,"r");
|
||||
if (codef==NULL)
|
||||
{ fprintf(stderr,"Can't open coded file: %s\n",coded_file);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Open source file to verify against, if given. */
|
||||
|
||||
if (source_file!=0)
|
||||
{
|
||||
srcf = open_file_std(source_file,"r");
|
||||
if (srcf==NULL)
|
||||
{ fprintf(stderr,"Can't open source file: %s\n",source_file);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
sblk = chk_alloc (N-M, sizeof *sblk);
|
||||
cblk = chk_alloc (N, sizeof *cblk);
|
||||
chks = chk_alloc (M, sizeof *chks);
|
||||
|
||||
/* Print header for table. */
|
||||
|
||||
if (table)
|
||||
{ if (gen_file!=0)
|
||||
{ printf(" block chkerrs srcerrs\n");
|
||||
}
|
||||
else
|
||||
{ printf(" block chkerrs\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify successive blocks. */
|
||||
|
||||
tot_srcerrs = 0;
|
||||
tot_chkerrs = 0;
|
||||
tot_botherrs = 0;
|
||||
tot_undeterrs = 0;
|
||||
tot_good = 0;
|
||||
|
||||
bit_errs = 0;
|
||||
|
||||
seof = 0;
|
||||
ceof = 0;
|
||||
|
||||
for (n = 0; ; n++)
|
||||
{
|
||||
/* Read block from coded file. */
|
||||
|
||||
if (blockio_read(codef,cblk,N)==EOF)
|
||||
{ ceof = 1;
|
||||
}
|
||||
|
||||
/* Read block from source file, if given. */
|
||||
|
||||
if (source_file!=0 && !ceof && !seof)
|
||||
{ if (blockio_read(srcf,sblk,N-M)==EOF)
|
||||
{ fprintf(stderr,"Warning: Not enough source blocks (only %d)\n",n);
|
||||
seof = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop if end of received file. */
|
||||
|
||||
if (ceof) break;
|
||||
|
||||
/* Check that received block is a code word, and if not find the number of
|
||||
parity check errors. */
|
||||
|
||||
chkerr = check(H,cblk,chks);
|
||||
|
||||
/* Check against source block, if provided, or against zeros, if
|
||||
the generator matrix was provided but no source file. */
|
||||
|
||||
if (gen_file!=0)
|
||||
{ srcerr = 0;
|
||||
if (source_file!=0 && !seof)
|
||||
{ for (i = M; i<N; i++)
|
||||
{ if (cblk[cols[i]]!=sblk[i-M])
|
||||
{ srcerr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (source_file==0)
|
||||
{ for (i = M; i<N; i++)
|
||||
{ if (cblk[cols[i]]!=0)
|
||||
{ srcerr += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
bit_errs += srcerr;
|
||||
}
|
||||
|
||||
/* Print table entry. */
|
||||
|
||||
if (table)
|
||||
{ if (gen_file!=0)
|
||||
{ printf("%6d %7d %7d\n",n,chkerr,srcerr);
|
||||
}
|
||||
else
|
||||
{ printf("%6d %7d\n",n,chkerr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment totals. */
|
||||
|
||||
if (chkerr) tot_chkerrs += 1;
|
||||
if (gen_file!=0 && (source_file==0 || !seof))
|
||||
{ if (srcerr) tot_srcerrs += 1;
|
||||
if (srcerr && chkerr) tot_botherrs += 1;
|
||||
if (srcerr && (chkerr==0) ) tot_undeterrs += 1;
|
||||
if ((srcerr==0) && (chkerr==0) ) tot_good += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write final statistics to standard error. Flush standard output
|
||||
first to avoid mixing of output. */
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (gen_file!=0)
|
||||
{ fprintf(stderr,
|
||||
"Block counts: tot %d, with chk errs %d, with src errs %d, both %d\n",
|
||||
n, tot_chkerrs, tot_srcerrs, tot_botherrs, tot_undeterrs);
|
||||
fprintf(stderr,
|
||||
"Total good frames: %d Total undetected errors: %d\n",
|
||||
tot_good, tot_undeterrs);
|
||||
fprintf(stderr,
|
||||
"Bit error rate (on message bits only): %.3e\n",
|
||||
(double)bit_errs/(n*(N-M)));
|
||||
}
|
||||
else
|
||||
{ fprintf (stderr,
|
||||
"Block counts: tot %d, with chk errs %d\n", n, tot_chkerrs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* PRINT USAGE MESSAGE AND EXIT. */
|
||||
|
||||
void usage(void)
|
||||
{ fprintf(stderr,
|
||||
"Usage: verify [ -t ] pchk-file decoded-file [ gen-file [ source-file ] ]\n");
|
||||
exit(1);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user