From 5ac886855df16953ee42e5468ce279c5788e0953 Mon Sep 17 00:00:00 2001 From: Steven Franke Date: Mon, 25 Jan 2016 00:04:21 +0000 Subject: [PATCH] Add ldpc sandbox folder. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6437 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- lib/ldpc/COPYRIGHT | 15 + lib/ldpc/LDPC-install | 28 + lib/ldpc/LGPL | 463 + lib/ldpc/Makefile | 116 + lib/ldpc/README | 6 + lib/ldpc/alist-to-pchk.c | 168 + lib/ldpc/alloc.c | 42 + lib/ldpc/alloc.h | 18 + lib/ldpc/blockio.c | 85 + lib/ldpc/blockio.h | 19 + lib/ldpc/channel.c | 99 + lib/ldpc/channel.h | 32 + lib/ldpc/channel.html | 182 + lib/ldpc/check.c | 177 + lib/ldpc/check.h | 25 + lib/ldpc/dec.c | 385 + lib/ldpc/dec.h | 43 + lib/ldpc/decode-detail.html | 99 + lib/ldpc/decode.c | 384 + lib/ldpc/decoding.html | 342 + lib/ldpc/dep-H.html | 85 + lib/ldpc/distrib.c | 188 + lib/ldpc/distrib.h | 49 + lib/ldpc/enc.c | 154 + lib/ldpc/enc.h | 18 + lib/ldpc/encode.c | 195 + lib/ldpc/encoding.html | 283 + lib/ldpc/ex-dep | 60 + lib/ldpc/ex-dep-out | 224 + lib/ldpc/ex-ham7a | 38 + lib/ldpc/ex-ham7a-out | 33 + lib/ldpc/ex-ham7b | 21 + lib/ldpc/ex-ham7b-out | 15 + lib/ldpc/ex-ldpc-encode | 45 + lib/ldpc/ex-ldpc-encode-out | 47 + lib/ldpc/ex-ldpc36-1000a | 50 + lib/ldpc/ex-ldpc36-1000a-out | 57 + lib/ldpc/ex-ldpc36-5000a | 44 + lib/ldpc/ex-ldpc36-5000a-out | 54 + lib/ldpc/ex-ldpcvar-5000a | 46 + lib/ldpc/ex-ldpcvar-5000a-out | 54 + lib/ldpc/ex-wrong-model | 124 + lib/ldpc/ex-wrong-model-out | 163 + lib/ldpc/examples.html | 87 + lib/ldpc/extract.c | 112 + lib/ldpc/github.html | 67 + lib/ldpc/index.html | 89 + lib/ldpc/install.html | 82 + lib/ldpc/intio.c | 110 + lib/ldpc/intio.h | 17 + .../144-72-evenboth-3.results.rtf | 3995 ++++++++ lib/ldpc/jtmode_codes/ldpc-144-72 | 59 + .../jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk | Bin 0 -> 2264 bytes lib/ldpc/jtmode_codes/ldpc-144-72-search | 34 + .../jtmode_codes/ldpc-144-72-sf1.results.rtf | 85 + .../jtmode_codes/search_144-72-6x3-4x4.txt | 8953 +++++++++++++++++ lib/ldpc/make-gen.c | 350 + lib/ldpc/make-ldpc.c | 415 + lib/ldpc/make-pchk.c | 93 + lib/ldpc/mod2convert-test-out | 9 + lib/ldpc/mod2convert-test.c | 80 + lib/ldpc/mod2convert.c | 83 + lib/ldpc/mod2convert.h | 18 + lib/ldpc/mod2convert.html | 51 + lib/ldpc/mod2dense-test-out | 699 ++ lib/ldpc/mod2dense-test.c | 560 ++ lib/ldpc/mod2dense.c | 752 ++ lib/ldpc/mod2dense.h | 113 + lib/ldpc/mod2dense.html | 487 + lib/ldpc/mod2sparse-test-out | 431 + lib/ldpc/mod2sparse-test.c | 378 + lib/ldpc/mod2sparse.c | 1361 +++ lib/ldpc/mod2sparse.h | 147 + lib/ldpc/mod2sparse.html | 719 ++ lib/ldpc/modify.html | 125 + lib/ldpc/modules.html | 89 + lib/ldpc/open.c | 50 + lib/ldpc/open.h | 16 + lib/ldpc/pchk-to-alist.c | 166 + lib/ldpc/pchk.html | 371 + lib/ldpc/print-gen.c | 139 + lib/ldpc/print-pchk.c | 114 + lib/ldpc/progs.html | 80 + lib/ldpc/rand-src.c | 86 + lib/ldpc/rand-test.c | 266 + lib/ldpc/rand.c | 567 ++ lib/ldpc/rand.h | 54 + lib/ldpc/rand.html | 306 + lib/ldpc/randfile | Bin 0 -> 100000 bytes lib/ldpc/rcode.c | 200 + lib/ldpc/rcode.h | 37 + lib/ldpc/refs.html | 58 + lib/ldpc/release.html | 244 + lib/ldpc/run-examples | 12 + lib/ldpc/sparse-LU.html | 90 + lib/ldpc/sparse-encode.pdf | Bin 0 -> 185688 bytes lib/ldpc/support.html | 100 + lib/ldpc/transmit.c | 170 + lib/ldpc/verify.c | 254 + 99 files changed, 28805 insertions(+) create mode 100755 lib/ldpc/COPYRIGHT create mode 100755 lib/ldpc/LDPC-install create mode 100755 lib/ldpc/LGPL create mode 100755 lib/ldpc/Makefile create mode 100755 lib/ldpc/README create mode 100755 lib/ldpc/alist-to-pchk.c create mode 100755 lib/ldpc/alloc.c create mode 100755 lib/ldpc/alloc.h create mode 100755 lib/ldpc/blockio.c create mode 100755 lib/ldpc/blockio.h create mode 100755 lib/ldpc/channel.c create mode 100755 lib/ldpc/channel.h create mode 100755 lib/ldpc/channel.html create mode 100755 lib/ldpc/check.c create mode 100755 lib/ldpc/check.h create mode 100755 lib/ldpc/dec.c create mode 100755 lib/ldpc/dec.h create mode 100755 lib/ldpc/decode-detail.html create mode 100755 lib/ldpc/decode.c create mode 100755 lib/ldpc/decoding.html create mode 100755 lib/ldpc/dep-H.html create mode 100755 lib/ldpc/distrib.c create mode 100755 lib/ldpc/distrib.h create mode 100755 lib/ldpc/enc.c create mode 100755 lib/ldpc/enc.h create mode 100755 lib/ldpc/encode.c create mode 100755 lib/ldpc/encoding.html create mode 100755 lib/ldpc/ex-dep create mode 100755 lib/ldpc/ex-dep-out create mode 100755 lib/ldpc/ex-ham7a create mode 100755 lib/ldpc/ex-ham7a-out create mode 100755 lib/ldpc/ex-ham7b create mode 100755 lib/ldpc/ex-ham7b-out create mode 100755 lib/ldpc/ex-ldpc-encode create mode 100755 lib/ldpc/ex-ldpc-encode-out create mode 100755 lib/ldpc/ex-ldpc36-1000a create mode 100755 lib/ldpc/ex-ldpc36-1000a-out create mode 100755 lib/ldpc/ex-ldpc36-5000a create mode 100755 lib/ldpc/ex-ldpc36-5000a-out create mode 100755 lib/ldpc/ex-ldpcvar-5000a create mode 100755 lib/ldpc/ex-ldpcvar-5000a-out create mode 100755 lib/ldpc/ex-wrong-model create mode 100755 lib/ldpc/ex-wrong-model-out create mode 100755 lib/ldpc/examples.html create mode 100755 lib/ldpc/extract.c create mode 100755 lib/ldpc/github.html create mode 100755 lib/ldpc/index.html create mode 100755 lib/ldpc/install.html create mode 100755 lib/ldpc/intio.c create mode 100755 lib/ldpc/intio.h create mode 100644 lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf create mode 100755 lib/ldpc/jtmode_codes/ldpc-144-72 create mode 100644 lib/ldpc/jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk create mode 100755 lib/ldpc/jtmode_codes/ldpc-144-72-search create mode 100644 lib/ldpc/jtmode_codes/ldpc-144-72-sf1.results.rtf create mode 100644 lib/ldpc/jtmode_codes/search_144-72-6x3-4x4.txt create mode 100755 lib/ldpc/make-gen.c create mode 100755 lib/ldpc/make-ldpc.c create mode 100755 lib/ldpc/make-pchk.c create mode 100755 lib/ldpc/mod2convert-test-out create mode 100755 lib/ldpc/mod2convert-test.c create mode 100755 lib/ldpc/mod2convert.c create mode 100755 lib/ldpc/mod2convert.h create mode 100755 lib/ldpc/mod2convert.html create mode 100755 lib/ldpc/mod2dense-test-out create mode 100755 lib/ldpc/mod2dense-test.c create mode 100755 lib/ldpc/mod2dense.c create mode 100755 lib/ldpc/mod2dense.h create mode 100755 lib/ldpc/mod2dense.html create mode 100755 lib/ldpc/mod2sparse-test-out create mode 100755 lib/ldpc/mod2sparse-test.c create mode 100755 lib/ldpc/mod2sparse.c create mode 100755 lib/ldpc/mod2sparse.h create mode 100755 lib/ldpc/mod2sparse.html create mode 100755 lib/ldpc/modify.html create mode 100755 lib/ldpc/modules.html create mode 100755 lib/ldpc/open.c create mode 100755 lib/ldpc/open.h create mode 100755 lib/ldpc/pchk-to-alist.c create mode 100755 lib/ldpc/pchk.html create mode 100755 lib/ldpc/print-gen.c create mode 100755 lib/ldpc/print-pchk.c create mode 100755 lib/ldpc/progs.html create mode 100755 lib/ldpc/rand-src.c create mode 100755 lib/ldpc/rand-test.c create mode 100755 lib/ldpc/rand.c create mode 100755 lib/ldpc/rand.h create mode 100755 lib/ldpc/rand.html create mode 100755 lib/ldpc/randfile create mode 100755 lib/ldpc/rcode.c create mode 100755 lib/ldpc/rcode.h create mode 100755 lib/ldpc/refs.html create mode 100755 lib/ldpc/release.html create mode 100755 lib/ldpc/run-examples create mode 100755 lib/ldpc/sparse-LU.html create mode 100755 lib/ldpc/sparse-encode.pdf create mode 100755 lib/ldpc/support.html create mode 100755 lib/ldpc/transmit.c create mode 100755 lib/ldpc/verify.c diff --git a/lib/ldpc/COPYRIGHT b/lib/ldpc/COPYRIGHT new file mode 100755 index 000000000..9cd0d7f65 --- /dev/null +++ b/lib/ldpc/COPYRIGHT @@ -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. diff --git a/lib/ldpc/LDPC-install b/lib/ldpc/LDPC-install new file mode 100755 index 000000000..0ca12aceb --- /dev/null +++ b/lib/ldpc/LDPC-install @@ -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 diff --git a/lib/ldpc/LGPL b/lib/ldpc/LGPL new file mode 100755 index 000000000..7106bb0ae --- /dev/null +++ b/lib/ldpc/LGPL @@ -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 diff --git a/lib/ldpc/Makefile b/lib/ldpc/Makefile new file mode 100755 index 000000000..13c372303 --- /dev/null +++ b/lib/ldpc/Makefile @@ -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 diff --git a/lib/ldpc/README b/lib/ldpc/README new file mode 100755 index 000000000..dd34af58a --- /dev/null +++ b/lib/ldpc/README @@ -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. diff --git a/lib/ldpc/alist-to-pchk.c b/lib/ldpc/alist-to-pchk.c new file mode 100755 index 000000000..21831ded1 --- /dev/null +++ b/lib/ldpc/alist-to-pchk.c @@ -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 +#include +#include +#include + +#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; iN) + { bad_alist_file(); + } + } + + cw = (int *) chk_alloc (N, sizeof *cw); + + for (j = 0; jM) + { 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; iN || 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; jM || !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); +} diff --git a/lib/ldpc/alloc.c b/lib/ldpc/alloc.c new file mode 100755 index 000000000..f289ceb84 --- /dev/null +++ b/lib/ldpc/alloc.c @@ -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 +#include + +#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; +} diff --git a/lib/ldpc/alloc.h b/lib/ldpc/alloc.h new file mode 100755 index 000000000..aa1fb1738 --- /dev/null +++ b/lib/ldpc/alloc.h @@ -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 */ diff --git a/lib/ldpc/blockio.c b/lib/ldpc/blockio.c new file mode 100755 index 000000000..c9d08632a --- /dev/null +++ b/lib/ldpc/blockio.c @@ -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 +#include + +#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; i0) + { 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 +#include +#include +#include + +#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"); +} diff --git a/lib/ldpc/channel.h b/lib/ldpc/channel.h new file mode 100755 index 000000000..0522e856d --- /dev/null +++ b/lib/ldpc/channel.h @@ -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); diff --git a/lib/ldpc/channel.html b/lib/ldpc/channel.html new file mode 100755 index 000000000..ad5129195 --- /dev/null +++ b/lib/ldpc/channel.html @@ -0,0 +1,182 @@ + + + Transmission Through a Simulated Channel + + + + +

Transmission Through a Simulated Channel

+ +

Once a codeword has been found to represent a source message, it +can be sent through a channel, 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. + +

For a Binary Symmetric Channel (BSC), each bit sent +results in a bit being received. The bit received differs from the +bit sent with some error probability, p, 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: +

+P(receive 1 | send 1) = P(receive 0 | send 0) = 1-p
+P(receive 1 | send 0) = P(receive 0 | send 1) = p +
+ +

For an Additive White Gaussian Noise (AWGN) channel, the +data received at each time is equal to the data sent plus Gaussian +noise with mean zero and some standard deviation, s, +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: +

+data received | send 1 ~ N(+1,s2)
+data received | send 0 ~ N(-1,s2) +
+ +

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 R will then be the same as is obtained +using a code that repeats each bit n times, and sends these +bits at rate nR (assuming optimal decoding of each bit by +thresholding the sum of the n channel outputs corresponding to +that bit). Another way of looking at this scaling for s 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. + +

To account for this, it is common to compare codes for AWGN +channels in terms of their bit error rate and the value of +

+Eb / N0 += 1 / 2Rs2 +
+at which they operate, where R=K/N is the rate +of the code, and s 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 +Eb / +N0 in decibels (db), equal to +10 log10(Eb +/ N0). + +

The Additive White Logistic Noise (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 +

+(1/w) exp(-n/w) / [1 + exp(-n/w)]2 +
+where n is the amount of noise, and w is a width parameter +for the distribution, analogous to the s parameter for +Gaussian noise. (However, w is not equal to the standard deviation +for the logistic distribution, which is +sqrt(pi2/3)w.) Note: 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. + + +


transmit: Transmit bits through a +simulated channel. + +
+transmit encoded-file|n-zeros received-file seed channel
+
+
+where channel is one of the following: +
+bsc error-probability
+
+awgn standard-deviation
+
+awln width
+
+
+
+ +

Simulates the transmission of the bits in +encoded-file through a channel, with the received data +being stored in received-file. Typically, +encoded-file will have been produced by the encode program, but it could +also come from rand-src +or another program. If newlines separate blocks in +encoded-file, these block boundaries will be preserved +in received-file. + +

Alternatively, a count of zeros to transmit can be given, rather +than a encoded-file. This count can be the product of the +block size and the number of blocks, written with x +separating these numbers, with no spaces. The +received-file 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. Warning: 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. + +

The transmission will be corrupted by random noise, which will be +generated pseudo-randomly based on seed. The actual +random seed used will be seed 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. + +

The fourth argument specifies the type of channel, currently either +bsc (or BSC) for the Binary Symmetric Channel, or +awgn (or AWGN) for the Additive White Gaussian +Noise channel, or awln (or AWLN) for the Additive White +Logistic Noise channel. The channel type is followed by an argument +specifying the characteristics of the channel, as follows: +

+

BSC: The probability that a bit will be flipped by noise - ie, the + probability that the bit received is an error. + +

AWGN: The standard deviation of the Gaussian noise that is added to the + encodings of the bits. + +

AWLN: The width parameter of the logistic distribution for the noise + that is added to the encodings of the bits. +

+ +See the description of channel transmission +for more details. + +

Examples: The command: +

    +
  • transmit 10x3 rec 1 bsc 0.1 +
+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 rec: +
+0000000000
+1000000000
+0100000000
+
+If an AWGN channel is used instead, as follows: +
    +
  • transmit 10x3 rec 1 awgn 0.5 +
+then the file rec will contain data such as: +
+ -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
+
+ +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/check.c b/lib/ldpc/check.c new file mode 100755 index 000000000..e22b1dd9b --- /dev/null +++ b/lib/ldpc/check.c @@ -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 +#include +#include + +#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; i1); + } + + 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; i0) + { 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; j0 && bpr[j]<1) + { e -= bpr[j]*log(bpr[j]) + (1-bpr[j])*log(1-bpr[j]); + } + } + + return e/log(2.0); +} diff --git a/lib/ldpc/check.h b/lib/ldpc/check.h new file mode 100755 index 000000000..7ac005446 --- /dev/null +++ b/lib/ldpc/check.h @@ -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); diff --git a/lib/ldpc/dec.c b/lib/ldpc/dec.c new file mode 100755 index 000000000..fa4f8f939 --- /dev/null +++ b/lib/ldpc/dec.c @@ -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 +#include +#include + +#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=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; jmaxlk) + { for (j = 0; 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; jpr = 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; ilr = 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; jpr = 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; + } + } +} diff --git a/lib/ldpc/dec.h b/lib/ldpc/dec.h new file mode 100755 index 000000000..6623937c5 --- /dev/null +++ b/lib/ldpc/dec.h @@ -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 *); diff --git a/lib/ldpc/decode-detail.html b/lib/ldpc/decode-detail.html new file mode 100755 index 000000000..f829febac --- /dev/null +++ b/lib/ldpc/decode-detail.html @@ -0,0 +1,99 @@ + + + Detailed Decoding Trace Information + + + + +

Detailed Decoding Trace Information

+ +The -T option to decode +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. + + +

Enum-bit and Enum-block decoding methods

+ +For source messages with K bits, 2K lines are output +for each block, containing the following information: +
+ + + + + + + + + + +
block The number of the block, from zero
decoding A possible decoding for the message bits, expressed as a hexadecimal + number. The other bits are determined by the message bits.
likelihood The likelihood for this decoding (ie, the probability of obtaining + the data received if this was the message sent).
+
+ +For these methods, the number of "iterations" (output with the +-t option) is always 2K. + + +

Prprp decoding method

+ +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: +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
block The number of the block, from zero
iter The number of an iteration, zero for the initial state.
changed 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.)
perrs The number of parity check errors in the current tentative + decoding.
loglik The log likelihood of the current tentative decoding.
Eperrs 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.
Eloglik The expected log likelihood of a decoding found by randomly picking + a value for each bit, independently, according to the current bit + probabilities. +
entropy The entropy (in bits) of the distribution defined by the current bit + probablities, assumed to apply to bits independently.
+
+ +The number of "iterations" (output with the -t option) is +the obvious count of probability propagation iterations. The +initial state does not count as an iteration. + +
+ +Back to decoding documentation
+Back to index for LDPC software + + diff --git a/lib/ldpc/decode.c b/lib/ldpc/decode.c new file mode 100755 index 000000000..a82e5c9cc --- /dev/null +++ b/lib/ldpc/decode.c @@ -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 +#include +#include +#include + +#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; i0) + { 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= 2^31 */ + fflush(stdout); + } + + /* Write decoded block. */ + + blockio_write(df,dblk,N); + + /* Write bit probabilities, if asked to. */ + + if (pfile) + { for (j = 0; j + + Decoding Received Blocks + + + + +

Decoding Received Blocks

+ +Transmitted codewords are decoded from the received data on the basis +of the likelihood 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 likelihood +ratio in favour of a 1, which is P(data | bit is 1) / P(data | +bit is 0). + +

For a Binary Symmetric Channel with error probability p, +the likelihood ratio in favour of a 1 bit is as follows: +

+ If the received data was +1: (1-p) / p
+ If the received data was -1: p / (1-p) +
+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 s, the +likelihood ratio in favour of a 1 bit when data y was received is +
+ exp ( 2y / s2 ) +
+For an Additive White Logistic Noise channel, the corresponding +likelihood ratio is +d1/d0, +where +d1=e1 +/ (1+e1)2 and +d0=e0 +/ (1+e0)2, +with e1=exp(-(y-1)/w) and +e0=exp(-(y+1)/w). +
+ +

It is usual to consider codewords to be equally likely a +priori. 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 linear dependence in parity check matrices. +This minor complication is mostly ignored here, except by the exhaustive +enumeration decoding methods. + +

Assuming equal a priori 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. + +

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. + +

Decoding by probability propagation

+ +

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 references for details. Below, I give a fairly +intuitive description of the algorithm. + +

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. + +

The begin, information about each bit of the codeword derived from +the received data for that bit alone is expressed as a probability +ratio, 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 a priori. 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 other parity checks, +along with the data received for the bit. + +

For each parity check, the algorithm maintains separate +likelihood ratios (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 other +bits participating in this check being 1, as derived from the +probability ratios for these bits with respect to this check. + +

The algorithm alternates between recalculating the likelihood +ratios for each check, which are stored in the lr fields of the +parity check matrix entries, and recalculating the probability ratios +for each bit, which are stored in the pr fields of the entries +in the sparse matrix representation of the parity check matrix. (See +the documentation on representation of +sparse matrices for details on these entries.) + +

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 +

+ t + = product of [ 1 / (1+pi) + - pi / + (1+pi) ] + = product of [ 2 / (1+pi) - 1 ] +
+where the product is over the probability ratios +pi for the other bits participating +in this check. Factor i in this product is equal to probability +of bit 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 +t 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-t)/(1+t). + +

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-1 by the running product of the factors from i+1 on +gives the product needed for bit 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. + +

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 other +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. + +

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. + +

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. + + +


decode: Decode blocks of received data +into codewords. + +
+decode [ -f ] [ -t | -T ] pchk-file received-file decoded-file [ bp-file ] channel method
+
+
+where channel is one of: +
+bsc error-probability
+
+awgn standard-deviation
+
+awln width
+
+and method is one of: +
+enum-block gen-file
+
+enum-bit gen-file
+
+prprp [-]max-iterations
+
+
+
+ +

Decodes the blocks in received-file, which are +assumed to be have been received through the specified channel. The +results written to decoded-file 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 +bp-file, if given. + +

A newline is output at the end of each block written to +decoded-file and bp-file. Newlines in +received-file are ignored. A warning is displayed on +standard error if the number of bits in received-file +is not a multiple of the block length. + +

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. + +

If the -t 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: +

+ + + + + + + + + + + + + +
block The number of the block, from zero
iterations The number of "iterations" used in decoding. What exactly an iteration + is depends on the decoding method used (see + here).
valid Has the value 1 if the decoding is a valid codeword, 0 if not.
changed 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.
+
+The file produced is is suitable for +reading into the S-Plus or R statistics packages, with a command such as +
+data <- read.table(file,header=T)
+
+ +

If instead the -T option is given, detailed information on +the process of decoding each block will be written to standard output. +For a description, see the documentation +on detailed decoding trace information. + +

The type of channel that is assumed is specified after the file +name arguments. This may currently be either bsc (or +BSC) for the Binary Symmetric Channel, or awgn (or +AWGN) for the Additive White Gaussian Noise channel, or +awln (or AWLN) for the Additive White Logistic Noise +channel. The channel type is followed by an argument specifying the +assumed characteristics of the channel, as follows: +

+

BSC: The probability that a bit will be flipped by noise - ie, the + probability that the bit received is an error. + +

AWGN: The standard deviation of the Gaussian noise added to the + encodings of the bits. + +

AWLN: The width parameter of the logistic distribution for the noise + that is added to the encodings of the bits. +

+See the description of channel transmission +for more about these channels. + +

Following the channel specification is a specification of the +decoding method to use. The enum-block and enum-bit +methods find the optimal decoding by exhaustive enumeration of +codewords derived from all possible source messages. They differ in +that enum-block decodes to the most likely codeword, whereas +enum-bit 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 linear +dependence in parity check matrices). + +

The prprp decoding method decodes using probability propagation. The maximum number of +iterations of probability propagation to do is given following +prprp. 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 +bp-file 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. + +

If the -f option is given, output to decoded-file +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. + + +


extract: Extract the message bits from a block. + +
+extract gen-file decoded-file extracted-file
+
+ +

Given a file of codewords in decoded-file (usually, +decoded blocks output by decode), and a +generator matrix from gen-file (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 extracted-file. + +

A newline is output at the end of each block written to +extracted-file. Newlines in +decoded-file are ignored. A warning is displayed on +standard error if the number of bits in decoded-file +is not a multiple of the block length. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/dep-H.html b/lib/ldpc/dep-H.html new file mode 100755 index 000000000..b80b2a5c2 --- /dev/null +++ b/lib/ldpc/dep-H.html @@ -0,0 +1,85 @@ + + + Linear Dependence in Parity Check Matrices + + + + +

Linear Dependence in Parity Check Matrices

+ +

If a code is specified by means of a M by N parity +check matrix, H, in which some rows are linearly dependent - a +situation that is usually avoided - it would be possible to map more +than the usual K=N-M message bits into a codeword, since one or +more rows of H could have been deleted without affecting which +bit vectors are codewords. + +

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 description of generator matrix +representations, this is accomplished by partially computing +what would normally be A-1 (for a +dense or mixed representations) or the L and U matrices +(for a sparse representation), even though singularity prevents this +computation from being carried out fully. + +

Example: The parity check matrix created below is redundant, +since the 10100 row is equal to the sum of the 11000 and 01100 rows. +

    +
  • make-pchk dep.pchk 4 5 0:0 0:1 1:1 1:2 2:0 2:2 3:3 3:4 +
  • 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 + +
  • 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 +
  • 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 +
+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 +A-1B, 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. + +

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. + +

Note that codeword bits that are always zero can arise even when H +does not have linearly dependent rows. For example, if a row of H +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 M independent rows is equivalent to adding additional rows +to H in which only one bit is 1, in order to produce M +independent checks. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/distrib.c b/lib/ldpc/distrib.c new file mode 100755 index 000000000..879c54adf --- /dev/null +++ b/lib/ldpc/distrib.c @@ -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 +#include +#include +#include + +#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; isize; 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; ilist[]). */ + +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 *); diff --git a/lib/ldpc/enc.c b/lib/ldpc/enc.c new file mode 100755 index 000000000..0ff1520a7 --- /dev/null +++ b/lib/ldpc/enc.c @@ -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 +#include +#include + +#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 +#include +#include +#include + +#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 + + Encoding Message Blocks + + + + +

Encoding Message Blocks

+ +To use a code to send messages, we must define a mapping from a bit +vector, s, of length K, representing a source message, +to a codeword, x, of length N>K. We will +consider only linear mappings, which can be written in the form +x=GTs, where G +is a generator matrix. For a code with parity check matrix +H, whose codewords satisfy Hx=0, the generator +matrix must satisfy HGT=0. +This software assumes that the number of rows in the parity check +matrix, M, is equal to N-K, as would normally be the +case. + +

This software deals only with systematic encodings, in which +the K bits of s are copied unchanged to some subset of +the N bits of x (the message bits), and the +remaining M=N-K check bits of x 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 K columns of the K by N generator matrix +will then be the identity matrix. + +

However, this software does not 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 decode) 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 extract). + +

This software stores representations of generator matrices in files +in a format that is not human-readable (except by using the print-gen program). However, these +files are readable on a machine with a different architecture +than they were written on. + + +

Generator matrix representations

+ +

For simplicity of exposition, it will be assumed for the next few +paragraphs that the message bits are located at the end of the +codeword, so a codeword can be divided into M check bits, +c, followed by K message bits, s. + +

On the above assumption, the parity check matrix, H, can be divided +into an M by M matrix A occupying +the first M columns of H and an M by K matrix +B occupying the remaining columns of H. The requirement that +a codeword, x, satisfy all parity checks (ie, that Hx=0) +can then be written as +

+ Ac + Bs = 0 +
+Provided that A is non-singular, it follows that +
+ c = A-1Bs +
+A may be singular for some choices of which codeword bits are message +bits, but a choice for which A is non-singular always exists if the +rows of H are linearly independent. It is possible, however, that the +rows of H 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 linear +dependence in parity check matrices for the details. + +

The equation c = A-1Bs +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 G mentioned above.) + +

In the dense representation, the M by K matrix +A-1B is computed, and stored +in a dense format (see the dense modulo-2 +matrix package). A message is encoded by multiplying the +source bits, s, by this matrix to obtain the required check bits. + +

In the mixed representation, the M by M matrix +A-1 is computed and stored in a dense +format, and the M by K matrix B, the right +portion of the parity check matrix, is also stored, in a sparse format +(see the sparse modulo-2 matrix package). +To encode a message, the source vector s is first multiplied on +the left by B, an operation which can be done very quickly if +B is sparse (as it will be for LDPC codes). The result is then +multiplied on the left by A-1. If +M<K, the total time may be less than when using the +dense representation above. + +

The sparse representation goes further, and avoids +explicitly computing A-1, which tends +to be dense even if H is sparse. Instead, a LU +decomposition of A is found, consisting of a lower +triangular matrix L and an upper triangular matrix U for +which LU=A. The effect of multiplying Bs=z by +A-1 can then be obtained by +

+ Solving Ly=z for y using forward substitution.
+ Solving Uc=y for c using backward substitution. +
+Both of these operations will be fast if L and U are +sparse. Heuristics are used to try to achieve this, by rearranging the +rows and columns of H in the process of selecting A and +finding its LU decomposition. + + +


make-gen: Make a generator matrix from +a parity check matrix. + +
+make-gen pchk-file gen-file method
+
+
+where method is one of the following: +
+sparse [ first | mincol | minprod ] [ abandon-num abandon-when ]
+
+dense [ other-gen-file  ]
+
+mixed [ other-gen-file  ]
+
+
+
+ +

Finds a generator matrix for the code whose parity check matrix is +in pchk-file, and writes a representation of this +generator matrix to gen-file. The remaining arguments +specify what representation of the generator matrix is to be used (see +the description above), 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. + +

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 dense and +mixed representations, an other-gen-file 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 +A matrix; redundant rows of H are not allowed with this +option). Otherwise, make-gen 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. + +

The dense representation consists of a dense representation +of the matrix A-1B, where +A is the matrix consisting of the first M columns (after +reordering) of the parity check matrix, and B is the remaining +columns. If H contains redundant rows, there is an additional +reordering of columns of A in order create the same effect as +if the redundant rows came last. + +

The mixed representation consists of a dense representation +of the matrix A-1, where A is +the matrix consisting of the first M columns (after reordering) +of the parity check matrix. The remaining columns of the parity check +matrix, making up the matrix B, are also part of the +representation, but are not written to gen-file, since +they can be obtained from pchk-file. As for mixed +representations, an additional reordering of columns of A may +be needed if H has redundant rows. + +

A sparse representation consists of sparse representations +of the L and U matrices, whose product is A, the +first M columns of the parity check matrix (whose columns and +rows may both have been reordered). The matrix B, consisting +of the remaining columns of the parity check matrix, is also part of +the representation, but it is not written to gen-file, +since it can be obtained from pchk-file. + +

If a sparse representation is chosen, arguments after +sparse specify what heuristic is used when reordering columns +and rows in order to try to make L and U as sparse as +possible. The default if no heuristic is specified is +minprod. If the abandon-num and +abandon-when options are given, some information is +discarded in order to speed up the process of finding L and +U, at a possible cost in terms of how good a result is +obtained. For details on these heuristics, see the descriptions of sparse LU decomposition methods. + +

Example: A dense representation of a generator matrix for the +Hamming code created by the example for make-pchk can be created as follows: +

    +
  • make-gen ham7.pchk ham7.gen dense +Number of 1s per check in Inv(A) X B is 3.0 +
+ + +


print-gen: Print a representation of a +generator matrix. + +
+print-gen [ -d ] gen-file
+
+ +

Prints in human-readable form the representation of the generator +matrix that is stored in gen-file. The -d +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 description above for details of generator matrix +representations. Note that the L matrix for a sparse representation +will be lower triangular only after the rows are rearranged, and the U +matrix will be upper triangular only after the columns are rearranged. +The matrix B that is part of the sparse +and mixed representations is not printed, since it is not stored +in the gen-file, but is rather a subset of columns +of the parity check matrix. + +

Example: The generator matrix for the +Hamming code created by the example for make-gen can be printed as follows: +

    +
  • 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 +
+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. + +


encode: Encode message blocks as codewords + +
+encode [ -f ] pchk-file gen-file source-file encoded-file
+
+ +Encodes message blocks of length K, read from +source-file, as codewords of length N, which +are written to encoded-file, replacing any previous +data in this file. Here, N is the number of columns in the +parity check matrix in pchk-file, and +K=N-M, where M is the number of rows in the +parity check matrix. The generator matrix used, from +gen-file, 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 +pchk-file using
make-gen. + +

A newline is output at the end of each block written to +encoded-file. Newlines in source-file +are ignored. + +

If the -f option is given, output to encoded-file +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. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/ex-dep b/lib/ldpc/ex-dep new file mode 100755 index 000000000..3acebedca --- /dev/null +++ b/lib/ldpc/ex-dep @@ -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 diff --git a/lib/ldpc/ex-dep-out b/lib/ldpc/ex-dep-out new file mode 100755 index 000000000..c4df520a7 --- /dev/null +++ b/lib/ldpc/ex-dep-out @@ -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 diff --git a/lib/ldpc/ex-ham7a b/lib/ldpc/ex-ham7a new file mode 100755 index 000000000..7ccc08097 --- /dev/null +++ b/lib/ldpc/ex-ham7a @@ -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 diff --git a/lib/ldpc/ex-ham7a-out b/lib/ldpc/ex-ham7a-out new file mode 100755 index 000000000..eaa4ea522 --- /dev/null +++ b/lib/ldpc/ex-ham7a-out @@ -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 diff --git a/lib/ldpc/ex-ham7b b/lib/ldpc/ex-ham7b new file mode 100755 index 000000000..3bdd4a60f --- /dev/null +++ b/lib/ldpc/ex-ham7b @@ -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 diff --git a/lib/ldpc/ex-ham7b-out b/lib/ldpc/ex-ham7b-out new file mode 100755 index 000000000..37ecfc493 --- /dev/null +++ b/lib/ldpc/ex-ham7b-out @@ -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 diff --git a/lib/ldpc/ex-ldpc-encode b/lib/ldpc/ex-ldpc-encode new file mode 100755 index 000000000..7165e4823 --- /dev/null +++ b/lib/ldpc/ex-ldpc-encode @@ -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 diff --git a/lib/ldpc/ex-ldpc-encode-out b/lib/ldpc/ex-ldpc-encode-out new file mode 100755 index 000000000..0dc1a1cf8 --- /dev/null +++ b/lib/ldpc/ex-ldpc-encode-out @@ -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 diff --git a/lib/ldpc/ex-ldpc36-1000a b/lib/ldpc/ex-ldpc36-1000a new file mode 100755 index 000000000..19c4ba080 --- /dev/null +++ b/lib/ldpc/ex-ldpc36-1000a @@ -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 diff --git a/lib/ldpc/ex-ldpc36-1000a-out b/lib/ldpc/ex-ldpc36-1000a-out new file mode 100755 index 000000000..418ed5c96 --- /dev/null +++ b/lib/ldpc/ex-ldpc36-1000a-out @@ -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 diff --git a/lib/ldpc/ex-ldpc36-5000a b/lib/ldpc/ex-ldpc36-5000a new file mode 100755 index 000000000..f791e0568 --- /dev/null +++ b/lib/ldpc/ex-ldpc36-5000a @@ -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 diff --git a/lib/ldpc/ex-ldpc36-5000a-out b/lib/ldpc/ex-ldpc36-5000a-out new file mode 100755 index 000000000..f7bae5b91 --- /dev/null +++ b/lib/ldpc/ex-ldpc36-5000a-out @@ -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 diff --git a/lib/ldpc/ex-ldpcvar-5000a b/lib/ldpc/ex-ldpcvar-5000a new file mode 100755 index 000000000..e8995e54c --- /dev/null +++ b/lib/ldpc/ex-ldpcvar-5000a @@ -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 diff --git a/lib/ldpc/ex-ldpcvar-5000a-out b/lib/ldpc/ex-ldpcvar-5000a-out new file mode 100755 index 000000000..3cdb2081e --- /dev/null +++ b/lib/ldpc/ex-ldpcvar-5000a-out @@ -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 diff --git a/lib/ldpc/ex-wrong-model b/lib/ldpc/ex-wrong-model new file mode 100755 index 000000000..a8304c6c8 --- /dev/null +++ b/lib/ldpc/ex-wrong-model @@ -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 diff --git a/lib/ldpc/ex-wrong-model-out b/lib/ldpc/ex-wrong-model-out new file mode 100755 index 000000000..cde814c92 --- /dev/null +++ b/lib/ldpc/ex-wrong-model-out @@ -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 diff --git a/lib/ldpc/examples.html b/lib/ldpc/examples.html new file mode 100755 index 000000000..bc94faed1 --- /dev/null +++ b/lib/ldpc/examples.html @@ -0,0 +1,87 @@ + + + Examples of LDPC Program Usage + + + + +

Examples of LDPC Program Usage

+ +

Below, are some command files containing examples of the use of +the LDPC programs, 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 run-examples script runs all the example +scripts and compares their output with the outputs that I obtained (on +a Pentium machine). + +

ex-ham7b, +output in ex-ham7b-out +

+A (7,4) Hamming code used with a BSC. +Demonstrates encoding of random messages and decoding to minimize +bit error rate by exhaustive enumeration. +
+ +

ex-ham7a, +output in ex-ham7a-out +

+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. +
+ +

ex-dep, +output in ex-dep-out +

+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. +
+ +

ex-ldpc-encode, +output in ex-ldpc-encode-out +

+Encodes messages with an LDPC code using sparse, dense, and mixed +representations of the generator matrix. +
+ +

ex-ldpc36-1000a, +output in ex-ldpc36-1000a-out +

+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. +
+ +

ex-ldpc36-5000a, +output in ex-ldpc36-5000a-out +

+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. +
+ +

ex-ldpcvar-5000a, +output in ex-ldpcvar-5000a-out +

+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. +
+ +

ex-wrong-model, +output in ex-wrong-model-out +

+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). +
+ +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/extract.c b/lib/ldpc/extract.c new file mode 100755 index 000000000..f969f8970 --- /dev/null +++ b/lib/ldpc/extract.c @@ -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 +#include +#include +#include + +#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 + + Github Facilities + + + +

Github Facilities

+ +

Starting with the Version of 2012-02-11, the source code repository +for this software is hosted by Github, +and is located at http://github.com/radfordneal/LDPC-codes. +This repository includes the annotated log of changes made since the +Version of 2006-02-08. + +

You can use the facilities at Github to obtain the source-code +repository, report bugs, and contribute to the wiki. + +

Obtaining the source repository, and modifying it

+ +

To obtain a copy of the source-code repository, issue the following +command (in a Unix/Linux/Cygwin environment that has git installed): +

+git clone git://github.com/radfordneal/LDPC-codes
+
+This will retrieve the current state of the software, storing it +in the directory LDPC-codes, which you should ensure does not +exist before issuing this command above. + +

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 installation +instructions. + +

The LDPC-codes directory created by the git clone +command is a git repository, which can be manipulated with the various +forms of the git command, which are documented, for example, +here. + +

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. + +

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 Github user, you can set +up your own fork of the software for you and other people to use. + + +

Reporting Bugs

+ +You can use the Github "Issues" facility to report bugs in the +software. You have to register as a Github +user to do this (which is free). You can then go here 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. + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/index.html b/lib/ldpc/index.html new file mode 100755 index 000000000..11aa1248e --- /dev/null +++ b/lib/ldpc/index.html @@ -0,0 +1,89 @@ + + + Software for Low Density Parity Check Codes + + + + +

Software for Low Density Parity Check Codes

+ +

Version in development. + +

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. + +

This and past versions of the software are available here, +from Radford Neal's +web page. The source code for this software is also hosted at Github, +where there is a copy +of these documentation pages for the latest release. Github also +provides facilities for bug reporting and discussion. + +

Index to Documentation

+ +Download and installation instructions +
+ How to get and compile the programs and modules. +
+Github facilities +
+ How to get the source repository, report bugs, etc. +
+Release notes +
+ A log of changes made in each release of this software. +
+Software and program usage documentation +
+ General documentation on the methods implemented, and details of + program usage. +
+Examples of program usage +
+ Examples using simple Hamming codes, and using more interesting LDPC codes. +
+How to modify the programs +
+ Notes on how to add new channel types, new decoding methods, etc. +
+Module documentation +
+ Modules used by the programs for modulo-2 matrix + operations and random number generation. +
+References +
+ Classic and more recent papers on LDPC codes and related topics. +
+ +

Copyright and Lack of Warranty

+ +

Except as otherwise specified, all of this software and +documentation is copyright © 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. + + + diff --git a/lib/ldpc/install.html b/lib/ldpc/install.html new file mode 100755 index 000000000..f6966ab58 --- /dev/null +++ b/lib/ldpc/install.html @@ -0,0 +1,82 @@ + + + Installing the LDPC Software + + + +

Installing the LDPC Software

+ +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 Cygwin +Unix-like environment that runs under Microsoft Windows. The +installation instructions below assume that you are using a Unix-like +system. + +

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: +

+ Tar + file of LDPC software (0.9 Megabytes)
+ Gzipped + tar file of LDPC software (0.4 Megabytes) +
+ +

Once you obtain the tar file (and uncompress it with gunzip if +necessary), you should extract the files with the following Unix command: +

+tar xf LDPC-yyyy-mm-dd.tar
+
+This will create a source directory called LDPC-yyyy-mm-dd, and place +all the source, documentation, and other files in this directory. + +

If you prefer for this directory to be called something else, +rename it now, before compiling the programs, since the file +randfile in this directory, containing natural random numbers, +is accessed according to its path when the programs were compiled. + +

Once the tar command above has finished, you should change into the +newly-created directory, and type +

+make
+
+If all goes well, this should compile all the programs (except for some +test programs, which can be compiled with make test). You +may want to edit the file Makefile before running make +in order to change compilation options, such as the optimization level. + +

You can run the programs from this source directory, or you can copy +them to some other directory by running the LDPC-install +shell file. For instance, to install them in a bin directory in your +home directory, do the following: +

+./LDPC-install $HOME/bin
+
+ +

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 index.html 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 +

+file:path-to-software/index.html
+
+where path-to-software is the full path (starting with "/") +to the directory where you've put the software. + +

The command +

+make clean
+
+will remove all the compiled programs, as well as the files created when +the examples are run, and core, if it +exists. + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/intio.c b/lib/ldpc/intio.c new file mode 100755 index 000000000..bfa8db9f3 --- /dev/null +++ b/lib/ldpc/intio.c @@ -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 +#include + +#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 diff --git a/lib/ldpc/intio.h b/lib/ldpc/intio.h new file mode 100755 index 000000000..03979d0ce --- /dev/null +++ b/lib/ldpc/intio.h @@ -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 */ diff --git a/lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf b/lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf new file mode 100644 index 000000000..8dd3b7446 --- /dev/null +++ b/lib/ldpc/jtmode_codes/144-72-evenboth-3.results.rtf @@ -0,0 +1,3995 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1348\cocoasubrtf170 +{\fonttbl\f0\fnil\fcharset0 Menlo-Regular;} +{\colortbl;\red255\green255\blue255;} +\margl1440\margr1440\vieww22580\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-search\ +\ +for i in `seq 1 1000`;\ +do\ + seed=$i\ + echo seed $seed\ +make-ldpc ldpc-144-72.pchk 72 144 $seed evenboth 3 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 250\ +verify ldpc-144-72.pchk ldpc-144-72.dec ldpc-144-72.gen \\\ + ldpc-144-72.src \ +\ +\ +done\ +seq 1 1000\ +seed 1\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79230 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20770, with src errs 20936, both 20741\ +Total good frames: 79035 Total undetected errors: 195\ +Bit error rate (on message bits only): 2.035e-02\ +seed 2\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78842 valid. Average 59.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21158, with src errs 21182, both 21107\ +Total good frames: 78767 Total undetected errors: 75\ +Bit error rate (on message bits only): 2.034e-02\ +seed 3\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79636 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20364, with src errs 20402, both 20319\ +Total good frames: 79553 Total undetected errors: 83\ +Bit error rate (on message bits only): 2.009e-02\ +seed 4\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79563 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20437, with src errs 20463, both 20397\ +Total good frames: 79497 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.988e-02\ +seed 5\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80016 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19984, with src errs 20083, both 19952\ +Total good frames: 79885 Total undetected errors: 131\ +Bit error rate (on message bits only): 1.987e-02\ +seed 6\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79204 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20796, with src errs 20819, both 20764\ +Total good frames: 79149 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.028e-02\ +seed 7\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79599 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20401, with src errs 20411, both 20362\ +Total good frames: 79550 Total undetected errors: 49\ +Bit error rate (on message bits only): 1.969e-02\ +seed 8\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80060 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19940, with src errs 19925, both 19889\ +Total good frames: 80024 Total undetected errors: 36\ +Bit error rate (on message bits only): 1.965e-02\ +seed 9\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79911 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20089, with src errs 20132, both 20040\ +Total good frames: 79819 Total undetected errors: 92\ +Bit error rate (on message bits only): 1.981e-02\ +seed 10\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79435 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20565, with src errs 21049, both 20530\ +Total good frames: 78916 Total undetected errors: 519\ +Bit error rate (on message bits only): 2.055e-02\ +seed 11\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78802 valid. Average 59.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21198, with src errs 21219, both 21155\ +Total good frames: 78738 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.045e-02\ +seed 12\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79426 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20574, with src errs 20674, both 20554\ +Total good frames: 79306 Total undetected errors: 120\ +Bit error rate (on message bits only): 2.036e-02\ +seed 13\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79574 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20426, with src errs 20531, both 20396\ +Total good frames: 79439 Total undetected errors: 135\ +Bit error rate (on message bits only): 2.003e-02\ +seed 14\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79932 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20068, with src errs 20624, both 20029\ +Total good frames: 79337 Total undetected errors: 595\ +Bit error rate (on message bits only): 2.000e-02\ +seed 15\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80087 valid. Average 56.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19913, with src errs 19927, both 19874\ +Total good frames: 80034 Total undetected errors: 53\ +Bit error rate (on message bits only): 1.980e-02\ +seed 16\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79432 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20568, with src errs 20581, both 20501\ +Total good frames: 79352 Total undetected errors: 80\ +Bit error rate (on message bits only): 1.983e-02\ +seed 17\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79384 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20616, with src errs 20652, both 20572\ +Total good frames: 79304 Total undetected errors: 80\ +Bit error rate (on message bits only): 2.026e-02\ +seed 18\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79266 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20734, with src errs 20799, both 20680\ +Total good frames: 79147 Total undetected errors: 119\ +Bit error rate (on message bits only): 2.031e-02\ +seed 19\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79656 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20344, with src errs 20393, both 20320\ +Total good frames: 79583 Total undetected errors: 73\ +Bit error rate (on message bits only): 2.002e-02\ +seed 20\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79526 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20474, with src errs 20556, both 20423\ +Total good frames: 79393 Total undetected errors: 133\ +Bit error rate (on message bits only): 2.024e-02\ +seed 21\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79335 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20665, with src errs 20734, both 20617\ +Total good frames: 79218 Total undetected errors: 117\ +Bit error rate (on message bits only): 2.005e-02\ +seed 22\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79857 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20143, with src errs 20112, both 20071\ +Total good frames: 79816 Total undetected errors: 41\ +Bit error rate (on message bits only): 1.974e-02\ +seed 23\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79896 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20104, with src errs 20130, both 20068\ +Total good frames: 79834 Total undetected errors: 62\ +Bit error rate (on message bits only): 2.010e-02\ +seed 24\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79606 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20394, with src errs 20497, both 20347\ +Total good frames: 79456 Total undetected errors: 150\ +Bit error rate (on message bits only): 2.007e-02\ +seed 25\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79646 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20354, with src errs 20379, both 20307\ +Total good frames: 79574 Total undetected errors: 72\ +Bit error rate (on message bits only): 1.992e-02\ +seed 26\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79350 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20650, with src errs 20721, both 20597\ +Total good frames: 79226 Total undetected errors: 124\ +Bit error rate (on message bits only): 2.015e-02\ +seed 27\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78968 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21032, with src errs 21145, both 20991\ +Total good frames: 78814 Total undetected errors: 154\ +Bit error rate (on message bits only): 2.035e-02\ +seed 28\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79319 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20681, with src errs 20680, both 20611\ +Total good frames: 79250 Total undetected errors: 69\ +Bit error rate (on message bits only): 1.989e-02\ +seed 29\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79615 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20385, with src errs 20411, both 20351\ +Total good frames: 79555 Total undetected errors: 60\ +Bit error rate (on message bits only): 2.010e-02\ +seed 30\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79695 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20305, with src errs 20371, both 20267\ +Total good frames: 79591 Total undetected errors: 104\ +Bit error rate (on message bits only): 2.005e-02\ +seed 31\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79485 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20515, with src errs 20547, both 20474\ +Total good frames: 79412 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.987e-02\ +seed 32\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79282 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20718, with src errs 20740, both 20671\ +Total good frames: 79213 Total undetected errors: 69\ +Bit error rate (on message bits only): 2.017e-02\ +seed 33\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79443 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20557, with src errs 20566, both 20512\ +Total good frames: 79389 Total undetected errors: 54\ +Bit error rate (on message bits only): 1.989e-02\ +seed 34\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79668 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20332, with src errs 20326, both 20275\ +Total good frames: 79617 Total undetected errors: 51\ +Bit error rate (on message bits only): 1.978e-02\ +seed 35\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79406 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20594, with src errs 20633, both 20559\ +Total good frames: 79332 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.005e-02\ +seed 36\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79619 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20381, with src errs 20414, both 20344\ +Total good frames: 79549 Total undetected errors: 70\ +Bit error rate (on message bits only): 1.999e-02\ +seed 37\ +Eliminated 20 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80004 valid. Average 56.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19996, with src errs 20114, both 19959\ +Total good frames: 79849 Total undetected errors: 155\ +Bit error rate (on message bits only): 1.982e-02\ +seed 38\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79978 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20022, with src errs 20045, both 19975\ +Total good frames: 79908 Total undetected errors: 70\ +Bit error rate (on message bits only): 1.965e-02\ +seed 39\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79321 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20679, with src errs 20736, both 20636\ +Total good frames: 79221 Total undetected errors: 100\ +Bit error rate (on message bits only): 2.030e-02\ +seed 40\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79614 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20386, with src errs 20380, both 20344\ +Total good frames: 79578 Total undetected errors: 36\ +Bit error rate (on message bits only): 1.976e-02\ +seed 41\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79141 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20859, with src errs 20934, both 20807\ +Total good frames: 79014 Total undetected errors: 127\ +Bit error rate (on message bits only): 2.037e-02\ +seed 42\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79943 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20057, with src errs 20125, both 20006\ +Total good frames: 79824 Total undetected errors: 119\ +Bit error rate (on message bits only): 2.000e-02\ +seed 43\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79278 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20722, with src errs 20772, both 20684\ +Total good frames: 79190 Total undetected errors: 88\ +Bit error rate (on message bits only): 2.008e-02\ +seed 44\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79128 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20872, with src errs 20877, both 20778\ +Total good frames: 79029 Total undetected errors: 99\ +Bit error rate (on message bits only): 2.026e-02\ +seed 45\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80077 valid. Average 56.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19923, with src errs 20046, both 19885\ +Total good frames: 79916 Total undetected errors: 161\ +Bit error rate (on message bits only): 1.990e-02\ +seed 46\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79598 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20402, with src errs 20402, both 20329\ +Total good frames: 79525 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.994e-02\ +seed 47\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79236 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20764, with src errs 20816, both 20727\ +Total good frames: 79147 Total undetected errors: 89\ +Bit error rate (on message bits only): 2.037e-02\ +seed 48\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79396 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20604, with src errs 20623, both 20559\ +Total good frames: 79332 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.009e-02\ +seed 49\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79445 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20555, with src errs 20650, both 20499\ +Total good frames: 79294 Total undetected errors: 151\ +Bit error rate (on message bits only): 2.000e-02\ +seed 50\ +Had to place 1 checks in rows unevenly\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79413 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20587, with src errs 20595, both 20532\ +Total good frames: 79350 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.996e-02\ +seed 51\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78928 valid. Average 59.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21072, with src errs 21107, both 21036\ +Total good frames: 78857 Total undetected errors: 71\ +Bit error rate (on message bits only): 2.054e-02\ +seed 52\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79337 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20663, with src errs 20691, both 20626\ +Total good frames: 79272 Total undetected errors: 65\ +Bit error rate (on message bits only): 2.026e-02\ +seed 53\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79690 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20310, with src errs 20380, both 20272\ +Total good frames: 79582 Total undetected errors: 108\ +Bit error rate (on message bits only): 1.999e-02\ +seed 54\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79476 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20524, with src errs 20521, both 20465\ +Total good frames: 79420 Total undetected errors: 56\ +Bit error rate (on message bits only): 2.017e-02\ +seed 55\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79621 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20379, with src errs 20400, both 20337\ +Total good frames: 79558 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.999e-02\ +seed 56\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79515 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20485, with src errs 20498, both 20454\ +Total good frames: 79471 Total undetected errors: 44\ +Bit error rate (on message bits only): 2.007e-02\ +seed 57\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79393 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20607, with src errs 20711, both 20563\ +Total good frames: 79245 Total undetected errors: 148\ +Bit error rate (on message bits only): 2.026e-02\ +seed 58\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79521 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20479, with src errs 20527, both 20450\ +Total good frames: 79444 Total undetected errors: 77\ +Bit error rate (on message bits only): 1.993e-02\ +seed 59\ +Eliminated 21 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79830 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20170, with src errs 20197, both 20131\ +Total good frames: 79764 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.990e-02\ +seed 60\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79537 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20463, with src errs 20459, both 20396\ +Total good frames: 79474 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.982e-02\ +seed 61\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79701 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20299, with src errs 20492, both 20257\ +Total good frames: 79466 Total undetected errors: 235\ +Bit error rate (on message bits only): 1.994e-02\ +seed 62\ +Eliminated 50 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79176 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20824, with src errs 20885, both 20786\ +Total good frames: 79077 Total undetected errors: 99\ +Bit error rate (on message bits only): 2.054e-02\ +seed 63\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79354 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20646, with src errs 20659, both 20595\ +Total good frames: 79290 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.029e-02\ +seed 64\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79905 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20095, with src errs 20145, both 20054\ +Total good frames: 79814 Total undetected errors: 91\ +Bit error rate (on message bits only): 1.977e-02\ +seed 65\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79584 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20416, with src errs 20493, both 20352\ +Total good frames: 79443 Total undetected errors: 141\ +Bit error rate (on message bits only): 1.970e-02\ +seed 66\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80025 valid. Average 56.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19975, with src errs 20026, both 19953\ +Total good frames: 79952 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.959e-02\ +seed 67\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79295 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20705, with src errs 20726, both 20663\ +Total good frames: 79232 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.997e-02\ +seed 68\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79830 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20170, with src errs 20637, both 20130\ +Total good frames: 79323 Total undetected errors: 507\ +Bit error rate (on message bits only): 2.003e-02\ +seed 69\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79275 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20725, with src errs 21215, both 20671\ +Total good frames: 78731 Total undetected errors: 544\ +Bit error rate (on message bits only): 2.033e-02\ +seed 70\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79290 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20710, with src errs 21250, both 20672\ +Total good frames: 78712 Total undetected errors: 578\ +Bit error rate (on message bits only): 2.043e-02\ +seed 71\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79510 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20490, with src errs 20568, both 20430\ +Total good frames: 79372 Total undetected errors: 138\ +Bit error rate (on message bits only): 1.985e-02\ +seed 72\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79453 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20547, with src errs 20568, both 20505\ +Total good frames: 79390 Total undetected errors: 63\ +Bit error rate (on message bits only): 2.000e-02\ +seed 73\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79036 valid. Average 59.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20964, with src errs 21042, both 20898\ +Total good frames: 78892 Total undetected errors: 144\ +Bit error rate (on message bits only): 2.014e-02\ +seed 74\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79782 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20218, with src errs 20229, both 20186\ +Total good frames: 79739 Total undetected errors: 43\ +Bit error rate (on message bits only): 1.994e-02\ +seed 75\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79444 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20556, with src errs 21122, both 20521\ +Total good frames: 78843 Total undetected errors: 601\ +Bit error rate (on message bits only): 2.003e-02\ +seed 76\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79282 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20718, with src errs 20743, both 20682\ +Total good frames: 79221 Total undetected errors: 61\ +Bit error rate (on message bits only): 2.033e-02\ +seed 77\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79224 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20776, with src errs 20869, both 20724\ +Total good frames: 79079 Total undetected errors: 145\ +Bit error rate (on message bits only): 2.014e-02\ +seed 78\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79359 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20641, with src errs 20680, both 20586\ +Total good frames: 79265 Total undetected errors: 94\ +Bit error rate (on message bits only): 2.010e-02\ +seed 79\ +Eliminated 48 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79380 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20620, with src errs 20688, both 20575\ +Total good frames: 79267 Total undetected errors: 113\ +Bit error rate (on message bits only): 2.024e-02\ +seed 80\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79753 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20247, with src errs 20333, both 20209\ +Total good frames: 79629 Total undetected errors: 124\ +Bit error rate (on message bits only): 1.999e-02\ +seed 81\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78765 valid. Average 59.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21235, with src errs 21321, both 21175\ +Total good frames: 78619 Total undetected errors: 146\ +Bit error rate (on message bits only): 2.047e-02\ +seed 82\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79365 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20635, with src errs 20671, both 20594\ +Total good frames: 79288 Total undetected errors: 77\ +Bit error rate (on message bits only): 2.007e-02\ +seed 83\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79580 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20420, with src errs 20460, both 20379\ +Total good frames: 79499 Total undetected errors: 81\ +Bit error rate (on message bits only): 2.017e-02\ +seed 84\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79528 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20472, with src errs 20506, both 20433\ +Total good frames: 79455 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.963e-02\ +seed 85\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79219 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20781, with src errs 20795, both 20733\ +Total good frames: 79157 Total undetected errors: 62\ +Bit error rate (on message bits only): 1.996e-02\ +seed 86\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79217 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20783, with src errs 20816, both 20730\ +Total good frames: 79131 Total undetected errors: 86\ +Bit error rate (on message bits only): 2.012e-02\ +seed 87\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79690 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20310, with src errs 20346, both 20257\ +Total good frames: 79601 Total undetected errors: 89\ +Bit error rate (on message bits only): 1.983e-02\ +seed 88\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 35.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79548 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20452, with src errs 20518, both 20408\ +Total good frames: 79438 Total undetected errors: 110\ +Bit error rate (on message bits only): 2.016e-02\ +seed 89\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79699 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20301, with src errs 20308, both 20265\ +Total good frames: 79656 Total undetected errors: 43\ +Bit error rate (on message bits only): 2.009e-02\ +seed 90\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79587 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20413, with src errs 20440, both 20371\ +Total good frames: 79518 Total undetected errors: 69\ +Bit error rate (on message bits only): 2.004e-02\ +seed 91\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79650 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20350, with src errs 20375, both 20298\ +Total good frames: 79573 Total undetected errors: 77\ +Bit error rate (on message bits only): 1.994e-02\ +seed 92\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79354 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20646, with src errs 20728, both 20594\ +Total good frames: 79220 Total undetected errors: 134\ +Bit error rate (on message bits only): 2.003e-02\ +seed 93\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79352 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20648, with src errs 20643, both 20580\ +Total good frames: 79289 Total undetected errors: 63\ +Bit error rate (on message bits only): 2.010e-02\ +seed 94\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79548 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20452, with src errs 20513, both 20407\ +Total good frames: 79442 Total undetected errors: 106\ +Bit error rate (on message bits only): 1.976e-02\ +seed 95\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79672 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20328, with src errs 20344, both 20291\ +Total good frames: 79619 Total undetected errors: 53\ +Bit error rate (on message bits only): 2.032e-02\ +seed 96\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79368 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20632, with src errs 20697, both 20553\ +Total good frames: 79224 Total undetected errors: 144\ +Bit error rate (on message bits only): 1.983e-02\ +seed 97\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79855 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20145, with src errs 20163, both 20105\ +Total good frames: 79797 Total undetected errors: 58\ +Bit error rate (on message bits only): 2.001e-02\ +seed 98\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79282 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20718, with src errs 20720, both 20665\ +Total good frames: 79227 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.019e-02\ +seed 99\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79886 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20114, with src errs 20174, both 20073\ +Total good frames: 79785 Total undetected errors: 101\ +Bit error rate (on message bits only): 1.952e-02\ +seed 100\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79441 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20559, with src errs 20570, both 20506\ +Total good frames: 79377 Total undetected errors: 64\ +Bit error rate (on message bits only): 1.988e-02\ +seed 101\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80007 valid. Average 56.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19993, with src errs 20441, both 19943\ +Total good frames: 79509 Total undetected errors: 498\ +Bit error rate (on message bits only): 1.980e-02\ +seed 102\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79766 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20234, with src errs 20232, both 20180\ +Total good frames: 79714 Total undetected errors: 52\ +Bit error rate (on message bits only): 1.998e-02\ +seed 103\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79266 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20734, with src errs 20782, both 20696\ +Total good frames: 79180 Total undetected errors: 86\ +Bit error rate (on message bits only): 2.015e-02\ +seed 104\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79221 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20779, with src errs 20848, both 20734\ +Total good frames: 79107 Total undetected errors: 114\ +Bit error rate (on message bits only): 2.026e-02\ +seed 105\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79582 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20418, with src errs 20446, both 20373\ +Total good frames: 79509 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.990e-02\ +seed 106\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79555 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20445, with src errs 20524, both 20418\ +Total good frames: 79449 Total undetected errors: 106\ +Bit error rate (on message bits only): 1.994e-02\ +seed 107\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79905 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20095, with src errs 20081, both 20018\ +Total good frames: 79842 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.959e-02\ +seed 108\ +Eliminated 47 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78851 valid. Average 59.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21149, with src errs 21146, both 21066\ +Total good frames: 78771 Total undetected errors: 80\ +Bit error rate (on message bits only): 2.020e-02\ +seed 109\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79414 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20586, with src errs 20608, both 20551\ +Total good frames: 79357 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.017e-02\ +seed 110\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79230 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20770, with src errs 21240, both 20705\ +Total good frames: 78695 Total undetected errors: 535\ +Bit error rate (on message bits only): 1.998e-02\ +seed 111\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79212 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20788, with src errs 20806, both 20751\ +Total good frames: 79157 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.038e-02\ +seed 112\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79803 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20197, with src errs 20223, both 20162\ +Total good frames: 79742 Total undetected errors: 61\ +Bit error rate (on message bits only): 1.987e-02\ +seed 113\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79365 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20635, with src errs 20715, both 20586\ +Total good frames: 79236 Total undetected errors: 129\ +Bit error rate (on message bits only): 1.996e-02\ +seed 114\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79506 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20494, with src errs 20525, both 20452\ +Total good frames: 79433 Total undetected errors: 73\ +Bit error rate (on message bits only): 2.013e-02\ +seed 115\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78872 valid. Average 59.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21128, with src errs 21543, both 21073\ +Total good frames: 78402 Total undetected errors: 470\ +Bit error rate (on message bits only): 2.058e-02\ +seed 116\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79348 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20652, with src errs 20690, both 20616\ +Total good frames: 79274 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.040e-02\ +seed 117\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79723 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20277, with src errs 20312, both 20234\ +Total good frames: 79645 Total undetected errors: 78\ +Bit error rate (on message bits only): 1.971e-02\ +seed 118\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79125 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20875, with src errs 20921, both 20831\ +Total good frames: 79035 Total undetected errors: 90\ +Bit error rate (on message bits only): 2.054e-02\ +seed 119\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79601 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20399, with src errs 20907, both 20358\ +Total good frames: 79052 Total undetected errors: 549\ +Bit error rate (on message bits only): 1.977e-02\ +seed 120\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79729 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20271, with src errs 20344, both 20237\ +Total good frames: 79622 Total undetected errors: 107\ +Bit error rate (on message bits only): 2.008e-02\ +seed 121\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79057 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20943, with src errs 20907, both 20871\ +Total good frames: 79021 Total undetected errors: 36\ +Bit error rate (on message bits only): 2.011e-02\ +seed 122\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79323 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20677, with src errs 20696, both 20639\ +Total good frames: 79266 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.009e-02\ +seed 123\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78774 valid. Average 59.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21226, with src errs 21228, both 21162\ +Total good frames: 78708 Total undetected errors: 66\ +Bit error rate (on message bits only): 2.018e-02\ +seed 124\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79469 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20531, with src errs 20532, both 20477\ +Total good frames: 79414 Total undetected errors: 55\ +Bit error rate (on message bits only): 1.997e-02\ +seed 125\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79721 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20279, with src errs 20379, both 20235\ +Total good frames: 79577 Total undetected errors: 144\ +Bit error rate (on message bits only): 1.976e-02\ +seed 126\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79775 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20225, with src errs 20276, both 20175\ +Total good frames: 79674 Total undetected errors: 101\ +Bit error rate (on message bits only): 1.984e-02\ +seed 127\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79193 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20807, with src errs 20916, both 20771\ +Total good frames: 79048 Total undetected errors: 145\ +Bit error rate (on message bits only): 2.053e-02\ +seed 128\ +Eliminated 46 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78999 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21001, with src errs 21077, both 20949\ +Total good frames: 78871 Total undetected errors: 128\ +Bit error rate (on message bits only): 2.013e-02\ +seed 129\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79552 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20448, with src errs 20498, both 20402\ +Total good frames: 79456 Total undetected errors: 96\ +Bit error rate (on message bits only): 2.006e-02\ +seed 130\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79684 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20316, with src errs 20342, both 20277\ +Total good frames: 79619 Total undetected errors: 65\ +Bit error rate (on message bits only): 1.984e-02\ +seed 131\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78142 valid. Average 61.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21858, with src errs 21867, both 21800\ +Total good frames: 78075 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.053e-02\ +seed 132\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79855 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20145, with src errs 20140, both 20089\ +Total good frames: 79804 Total undetected errors: 51\ +Bit error rate (on message bits only): 1.998e-02\ +seed 133\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79963 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20037, with src errs 20092, both 19996\ +Total good frames: 79867 Total undetected errors: 96\ +Bit error rate (on message bits only): 2.004e-02\ +seed 134\ +Eliminated 52 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78994 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21006, with src errs 21090, both 20939\ +Total good frames: 78843 Total undetected errors: 151\ +Bit error rate (on message bits only): 2.001e-02\ +seed 135\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79472 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20528, with src errs 20531, both 20478\ +Total good frames: 79419 Total undetected errors: 53\ +Bit error rate (on message bits only): 1.998e-02\ +seed 136\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79559 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20441, with src errs 20449, both 20387\ +Total good frames: 79497 Total undetected errors: 62\ +Bit error rate (on message bits only): 1.986e-02\ +seed 137\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80061 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19939, with src errs 19940, both 19899\ +Total good frames: 80020 Total undetected errors: 41\ +Bit error rate (on message bits only): 1.967e-02\ +seed 138\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79871 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20129, with src errs 20249, both 20101\ +Total good frames: 79723 Total undetected errors: 148\ +Bit error rate (on message bits only): 1.982e-02\ +seed 139\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79359 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20641, with src errs 20742, both 20602\ +Total good frames: 79219 Total undetected errors: 140\ +Bit error rate (on message bits only): 2.023e-02\ +seed 140\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79448 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20552, with src errs 20547, both 20490\ +Total good frames: 79391 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.040e-02\ +seed 141\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79311 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20689, with src errs 20772, both 20639\ +Total good frames: 79178 Total undetected errors: 133\ +Bit error rate (on message bits only): 2.010e-02\ +seed 142\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79797 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20203, with src errs 20226, both 20155\ +Total good frames: 79726 Total undetected errors: 71\ +Bit error rate (on message bits only): 1.969e-02\ +seed 143\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79497 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20503, with src errs 20535, both 20476\ +Total good frames: 79438 Total undetected errors: 59\ +Bit error rate (on message bits only): 1.994e-02\ +seed 144\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79044 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20956, with src errs 20979, both 20905\ +Total good frames: 78970 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.031e-02\ +seed 145\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79202 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20798, with src errs 20836, both 20762\ +Total good frames: 79128 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.020e-02\ +seed 146\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78878 valid. Average 59.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21122, with src errs 21292, both 21074\ +Total good frames: 78660 Total undetected errors: 218\ +Bit error rate (on message bits only): 2.032e-02\ +seed 147\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79491 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20509, with src errs 20565, both 20477\ +Total good frames: 79403 Total undetected errors: 88\ +Bit error rate (on message bits only): 2.004e-02\ +seed 148\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79250 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20750, with src errs 20841, both 20705\ +Total good frames: 79114 Total undetected errors: 136\ +Bit error rate (on message bits only): 2.018e-02\ +seed 149\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79627 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20373, with src errs 20408, both 20333\ +Total good frames: 79552 Total undetected errors: 75\ +Bit error rate (on message bits only): 2.006e-02\ +seed 150\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79715 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20285, with src errs 20337, both 20247\ +Total good frames: 79625 Total undetected errors: 90\ +Bit error rate (on message bits only): 1.985e-02\ +seed 151\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79302 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20698, with src errs 21168, both 20643\ +Total good frames: 78777 Total undetected errors: 525\ +Bit error rate (on message bits only): 2.047e-02\ +seed 152\ +Eliminated 19 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80020 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19980, with src errs 20020, both 19945\ +Total good frames: 79945 Total undetected errors: 75\ +Bit error rate (on message bits only): 1.968e-02\ +seed 153\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79054 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20946, with src errs 20953, both 20898\ +Total good frames: 78999 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.031e-02\ +seed 154\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 25.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78902 valid. Average 59.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21098, with src errs 21131, both 21001\ +Total good frames: 78772 Total undetected errors: 130\ +Bit error rate (on message bits only): 2.014e-02\ +seed 155\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79894 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20106, with src errs 20154, both 20063\ +Total good frames: 79803 Total undetected errors: 91\ +Bit error rate (on message bits only): 1.983e-02\ +seed 156\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79831 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20169, with src errs 20192, both 20133\ +Total good frames: 79772 Total undetected errors: 59\ +Bit error rate (on message bits only): 1.992e-02\ +seed 157\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78895 valid. Average 59.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21105, with src errs 21185, both 21051\ +Total good frames: 78761 Total undetected errors: 134\ +Bit error rate (on message bits only): 2.045e-02\ +seed 158\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79512 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20488, with src errs 20492, both 20443\ +Total good frames: 79463 Total undetected errors: 49\ +Bit error rate (on message bits only): 2.017e-02\ +seed 159\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79571 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20429, with src errs 20416, both 20336\ +Total good frames: 79491 Total undetected errors: 80\ +Bit error rate (on message bits only): 1.997e-02\ +seed 160\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79345 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20655, with src errs 20654, both 20582\ +Total good frames: 79273 Total undetected errors: 72\ +Bit error rate (on message bits only): 1.986e-02\ +seed 161\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79532 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20468, with src errs 20487, both 20427\ +Total good frames: 79472 Total undetected errors: 60\ +Bit error rate (on message bits only): 1.994e-02\ +seed 162\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79449 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20551, with src errs 20546, both 20485\ +Total good frames: 79388 Total undetected errors: 61\ +Bit error rate (on message bits only): 1.985e-02\ +seed 163\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79591 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20409, with src errs 20437, both 20370\ +Total good frames: 79524 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.039e-02\ +seed 164\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79763 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20237, with src errs 20272, both 20207\ +Total good frames: 79698 Total undetected errors: 65\ +Bit error rate (on message bits only): 1.990e-02\ +seed 165\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79761 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20239, with src errs 20245, both 20190\ +Total good frames: 79706 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.008e-02\ +seed 166\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79309 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20691, with src errs 20694, both 20627\ +Total good frames: 79242 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.030e-02\ +seed 167\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79727 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20273, with src errs 20296, both 20245\ +Total good frames: 79676 Total undetected errors: 51\ +Bit error rate (on message bits only): 2.005e-02\ +seed 168\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79814 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20186, with src errs 20623, both 20130\ +Total good frames: 79321 Total undetected errors: 493\ +Bit error rate (on message bits only): 1.998e-02\ +seed 169\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79927 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20073, with src errs 20152, both 20030\ +Total good frames: 79805 Total undetected errors: 122\ +Bit error rate (on message bits only): 1.980e-02\ +seed 170\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79377 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20623, with src errs 20633, both 20577\ +Total good frames: 79321 Total undetected errors: 56\ +Bit error rate (on message bits only): 1.994e-02\ +seed 171\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79956 valid. Average 56.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20044, with src errs 20489, both 19984\ +Total good frames: 79451 Total undetected errors: 505\ +Bit error rate (on message bits only): 1.996e-02\ +seed 172\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78742 valid. Average 59.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21258, with src errs 21361, both 21222\ +Total good frames: 78603 Total undetected errors: 139\ +Bit error rate (on message bits only): 2.051e-02\ +seed 173\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79474 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20526, with src errs 20541, both 20468\ +Total good frames: 79401 Total undetected errors: 73\ +Bit error rate (on message bits only): 2.024e-02\ +seed 174\ +Had to place 1 checks in rows unevenly\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79564 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20436, with src errs 20461, both 20395\ +Total good frames: 79498 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.995e-02\ +seed 175\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79542 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20458, with src errs 20488, both 20421\ +Total good frames: 79475 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.009e-02\ +seed 176\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79093 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20907, with src errs 20947, both 20837\ +Total good frames: 78983 Total undetected errors: 110\ +Bit error rate (on message bits only): 2.040e-02\ +seed 177\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79832 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20168, with src errs 20170, both 20123\ +Total good frames: 79785 Total undetected errors: 47\ +Bit error rate (on message bits only): 2.000e-02\ +seed 178\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79908 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20092, with src errs 20127, both 20050\ +Total good frames: 79831 Total undetected errors: 77\ +Bit error rate (on message bits only): 1.979e-02\ +seed 179\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79551 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20449, with src errs 20459, both 20400\ +Total good frames: 79492 Total undetected errors: 59\ +Bit error rate (on message bits only): 2.006e-02\ +seed 180\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79891 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20109, with src errs 20146, both 20071\ +Total good frames: 79816 Total undetected errors: 75\ +Bit error rate (on message bits only): 2.001e-02\ +seed 181\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79827 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20173, with src errs 20228, both 20129\ +Total good frames: 79728 Total undetected errors: 99\ +Bit error rate (on message bits only): 1.978e-02\ +seed 182\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79601 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20399, with src errs 20392, both 20341\ +Total good frames: 79550 Total undetected errors: 51\ +Bit error rate (on message bits only): 1.986e-02\ +seed 183\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79752 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20248, with src errs 20382, both 20214\ +Total good frames: 79584 Total undetected errors: 168\ +Bit error rate (on message bits only): 2.007e-02\ +seed 184\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78986 valid. Average 59.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21014, with src errs 21130, both 20974\ +Total good frames: 78830 Total undetected errors: 156\ +Bit error rate (on message bits only): 2.016e-02\ +seed 185\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79717 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20283, with src errs 20295, both 20255\ +Total good frames: 79677 Total undetected errors: 40\ +Bit error rate (on message bits only): 1.988e-02\ +seed 186\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79791 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20209, with src errs 20225, both 20169\ +Total good frames: 79735 Total undetected errors: 56\ +Bit error rate (on message bits only): 2.001e-02\ +seed 187\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79404 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20596, with src errs 20626, both 20561\ +Total good frames: 79339 Total undetected errors: 65\ +Bit error rate (on message bits only): 2.020e-02\ +seed 188\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79833 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20167, with src errs 20193, both 20110\ +Total good frames: 79750 Total undetected errors: 83\ +Bit error rate (on message bits only): 1.964e-02\ +seed 189\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79578 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20422, with src errs 20446, both 20381\ +Total good frames: 79513 Total undetected errors: 65\ +Bit error rate (on message bits only): 1.993e-02\ +seed 190\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79979 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20021, with src errs 20071, both 19964\ +Total good frames: 79872 Total undetected errors: 107\ +Bit error rate (on message bits only): 1.967e-02\ +seed 191\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79377 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20623, with src errs 20644, both 20575\ +Total good frames: 79308 Total undetected errors: 69\ +Bit error rate (on message bits only): 2.000e-02\ +seed 192\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79656 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20344, with src errs 20366, both 20298\ +Total good frames: 79588 Total undetected errors: 68\ +Bit error rate (on message bits only): 1.985e-02\ +seed 193\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79358 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20642, with src errs 20641, both 20570\ +Total good frames: 79287 Total undetected errors: 71\ +Bit error rate (on message bits only): 1.990e-02\ +seed 194\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 25.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79295 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20705, with src errs 20710, both 20651\ +Total good frames: 79236 Total undetected errors: 59\ +Bit error rate (on message bits only): 2.017e-02\ +seed 195\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78672 valid. Average 59.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21328, with src errs 21793, both 21275\ +Total good frames: 78154 Total undetected errors: 518\ +Bit error rate (on message bits only): 2.037e-02\ +seed 196\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79651 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20349, with src errs 20434, both 20306\ +Total good frames: 79523 Total undetected errors: 128\ +Bit error rate (on message bits only): 2.010e-02\ +seed 197\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79535 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20465, with src errs 20562, both 20423\ +Total good frames: 79396 Total undetected errors: 139\ +Bit error rate (on message bits only): 1.985e-02\ +seed 198\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79923 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20077, with src errs 20103, both 20043\ +Total good frames: 79863 Total undetected errors: 60\ +Bit error rate (on message bits only): 1.976e-02\ +seed 199\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79725 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20275, with src errs 20303, both 20246\ +Total good frames: 79668 Total undetected errors: 57\ +Bit error rate (on message bits only): 1.977e-02\ +seed 200\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79603 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20397, with src errs 20431, both 20357\ +Total good frames: 79529 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.000e-02\ +seed 201\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79563 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20437, with src errs 20531, both 20405\ +Total good frames: 79437 Total undetected errors: 126\ +Bit error rate (on message bits only): 1.999e-02\ +seed 202\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79760 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20240, with src errs 20348, both 20212\ +Total good frames: 79624 Total undetected errors: 136\ +Bit error rate (on message bits only): 2.011e-02\ +seed 203\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79741 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20259, with src errs 20350, both 20204\ +Total good frames: 79595 Total undetected errors: 146\ +Bit error rate (on message bits only): 1.990e-02\ +seed 204\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79430 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20570, with src errs 20611, both 20530\ +Total good frames: 79349 Total undetected errors: 81\ +Bit error rate (on message bits only): 2.027e-02\ +seed 205\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79833 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20167, with src errs 20211, both 20135\ +Total good frames: 79757 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.995e-02\ +seed 206\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79332 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20668, with src errs 20756, both 20606\ +Total good frames: 79182 Total undetected errors: 150\ +Bit error rate (on message bits only): 1.981e-02\ +seed 207\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79632 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20368, with src errs 20529, both 20328\ +Total good frames: 79431 Total undetected errors: 201\ +Bit error rate (on message bits only): 2.007e-02\ +seed 208\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80136 valid. Average 56.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19864, with src errs 19863, both 19819\ +Total good frames: 80092 Total undetected errors: 44\ +Bit error rate (on message bits only): 1.981e-02\ +seed 209\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79207 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20793, with src errs 20814, both 20737\ +Total good frames: 79130 Total undetected errors: 77\ +Bit error rate (on message bits only): 2.005e-02\ +seed 210\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78944 valid. Average 59.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21056, with src errs 21017, both 20973\ +Total good frames: 78900 Total undetected errors: 44\ +Bit error rate (on message bits only): 1.998e-02\ +seed 211\ +Had to place 1 checks in rows unevenly\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79547 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20453, with src errs 20492, both 20424\ +Total good frames: 79479 Total undetected errors: 68\ +Bit error rate (on message bits only): 2.016e-02\ +seed 212\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79299 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20701, with src errs 20713, both 20646\ +Total good frames: 79232 Total undetected errors: 67\ +Bit error rate (on message bits only): 1.987e-02\ +seed 213\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79673 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20327, with src errs 20397, both 20283\ +Total good frames: 79559 Total undetected errors: 114\ +Bit error rate (on message bits only): 2.024e-02\ +seed 214\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79439 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20561, with src errs 20607, both 20527\ +Total good frames: 79359 Total undetected errors: 80\ +Bit error rate (on message bits only): 2.005e-02\ +seed 215\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79536 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20464, with src errs 20499, both 20422\ +Total good frames: 79459 Total undetected errors: 77\ +Bit error rate (on message bits only): 1.985e-02\ +seed 216\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79160 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20840, with src errs 20888, both 20795\ +Total good frames: 79067 Total undetected errors: 93\ +Bit error rate (on message bits only): 2.015e-02\ +seed 217\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79526 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20474, with src errs 20489, both 20427\ +Total good frames: 79464 Total undetected errors: 62\ +Bit error rate (on message bits only): 2.026e-02\ +seed 218\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79266 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20734, with src errs 20736, both 20690\ +Total good frames: 79220 Total undetected errors: 46\ +Bit error rate (on message bits only): 1.996e-02\ +seed 219\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79364 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20636, with src errs 20660, both 20588\ +Total good frames: 79292 Total undetected errors: 72\ +Bit error rate (on message bits only): 2.018e-02\ +seed 220\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78971 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21029, with src errs 21087, both 20998\ +Total good frames: 78882 Total undetected errors: 89\ +Bit error rate (on message bits only): 2.023e-02\ +seed 221\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79290 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20710, with src errs 21255, both 20672\ +Total good frames: 78707 Total undetected errors: 583\ +Bit error rate (on message bits only): 2.036e-02\ +seed 222\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79819 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20181, with src errs 20277, both 20140\ +Total good frames: 79682 Total undetected errors: 137\ +Bit error rate (on message bits only): 1.981e-02\ +seed 223\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79287 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20713, with src errs 20713, both 20651\ +Total good frames: 79225 Total undetected errors: 62\ +Bit error rate (on message bits only): 2.019e-02\ +seed 224\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79005 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20995, with src errs 21013, both 20961\ +Total good frames: 78953 Total undetected errors: 52\ +Bit error rate (on message bits only): 2.050e-02\ +seed 225\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79052 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20948, with src errs 20973, both 20907\ +Total good frames: 78986 Total undetected errors: 66\ +Bit error rate (on message bits only): 2.019e-02\ +seed 226\ +Eliminated 21 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79819 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20181, with src errs 20226, both 20136\ +Total good frames: 79729 Total undetected errors: 90\ +Bit error rate (on message bits only): 1.985e-02\ +seed 227\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79087 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20913, with src errs 20950, both 20843\ +Total good frames: 78980 Total undetected errors: 107\ +Bit error rate (on message bits only): 2.051e-02\ +seed 228\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79286 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20714, with src errs 20735, both 20667\ +Total good frames: 79218 Total undetected errors: 68\ +Bit error rate (on message bits only): 2.038e-02\ +seed 229\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80265 valid. Average 56.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19735, with src errs 19806, both 19678\ +Total good frames: 80137 Total undetected errors: 128\ +Bit error rate (on message bits only): 1.953e-02\ +seed 230\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79828 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20172, with src errs 20635, both 20126\ +Total good frames: 79319 Total undetected errors: 509\ +Bit error rate (on message bits only): 1.982e-02\ +seed 231\ +Eliminated 21 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80034 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19966, with src errs 20457, both 19938\ +Total good frames: 79515 Total undetected errors: 519\ +Bit error rate (on message bits only): 1.984e-02\ +seed 232\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79648 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20352, with src errs 20434, both 20309\ +Total good frames: 79523 Total undetected errors: 125\ +Bit error rate (on message bits only): 1.989e-02\ +seed 233\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79575 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20425, with src errs 20477, both 20382\ +Total good frames: 79480 Total undetected errors: 95\ +Bit error rate (on message bits only): 1.984e-02\ +seed 234\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79445 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20555, with src errs 20569, both 20493\ +Total good frames: 79369 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.987e-02\ +seed 235\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79754 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20246, with src errs 20240, both 20202\ +Total good frames: 79716 Total undetected errors: 38\ +Bit error rate (on message bits only): 1.973e-02\ +seed 236\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79857 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20143, with src errs 20193, both 20111\ +Total good frames: 79775 Total undetected errors: 82\ +Bit error rate (on message bits only): 1.989e-02\ +seed 237\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79844 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20156, with src errs 20192, both 20121\ +Total good frames: 79773 Total undetected errors: 71\ +Bit error rate (on message bits only): 2.013e-02\ +seed 238\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79818 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20182, with src errs 20222, both 20157\ +Total good frames: 79753 Total undetected errors: 65\ +Bit error rate (on message bits only): 1.994e-02\ +seed 239\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79332 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20668, with src errs 20682, both 20625\ +Total good frames: 79275 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.011e-02\ +seed 240\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79212 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20788, with src errs 20826, both 20749\ +Total good frames: 79135 Total undetected errors: 77\ +Bit error rate (on message bits only): 2.009e-02\ +seed 241\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79829 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20171, with src errs 20180, both 20130\ +Total good frames: 79779 Total undetected errors: 50\ +Bit error rate (on message bits only): 1.998e-02\ +seed 242\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79294 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20706, with src errs 20712, both 20656\ +Total good frames: 79238 Total undetected errors: 56\ +Bit error rate (on message bits only): 1.997e-02\ +seed 243\ +Had to place 1 checks in rows unevenly\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79682 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20318, with src errs 20318, both 20273\ +Total good frames: 79637 Total undetected errors: 45\ +Bit error rate (on message bits only): 2.010e-02\ +seed 244\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79459 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20541, with src errs 20574, both 20507\ +Total good frames: 79392 Total undetected errors: 67\ +Bit error rate (on message bits only): 1.995e-02\ +seed 245\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79700 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20300, with src errs 20757, both 20262\ +Total good frames: 79205 Total undetected errors: 495\ +Bit error rate (on message bits only): 2.010e-02\ +seed 246\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79816 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20184, with src errs 20229, both 20147\ +Total good frames: 79734 Total undetected errors: 82\ +Bit error rate (on message bits only): 1.976e-02\ +seed 247\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79073 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20927, with src errs 20911, both 20866\ +Total good frames: 79028 Total undetected errors: 45\ +Bit error rate (on message bits only): 2.023e-02\ +seed 248\ +Eliminated 52 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79343 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20657, with src errs 20658, both 20609\ +Total good frames: 79294 Total undetected errors: 49\ +Bit error rate (on message bits only): 2.000e-02\ +seed 249\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79683 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20317, with src errs 20345, both 20276\ +Total good frames: 79614 Total undetected errors: 69\ +Bit error rate (on message bits only): 1.997e-02\ +seed 250\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79779 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20221, with src errs 20303, both 20188\ +Total good frames: 79664 Total undetected errors: 115\ +Bit error rate (on message bits only): 2.001e-02\ +seed 251\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79848 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20152, with src errs 20217, both 20105\ +Total good frames: 79736 Total undetected errors: 112\ +Bit error rate (on message bits only): 1.968e-02\ +seed 252\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79637 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20363, with src errs 20387, both 20322\ +Total good frames: 79572 Total undetected errors: 65\ +Bit error rate (on message bits only): 1.995e-02\ +seed 253\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79828 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20172, with src errs 20202, both 20143\ +Total good frames: 79769 Total undetected errors: 59\ +Bit error rate (on message bits only): 1.985e-02\ +seed 254\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79994 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20006, with src errs 20065, both 19960\ +Total good frames: 79889 Total undetected errors: 105\ +Bit error rate (on message bits only): 1.950e-02\ +seed 255\ +Eliminated 18 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80411 valid. Average 55.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19589, with src errs 19630, both 19547\ +Total good frames: 80328 Total undetected errors: 83\ +Bit error rate (on message bits only): 1.954e-02\ +seed 256\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79388 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20612, with src errs 21139, both 20563\ +Total good frames: 78812 Total undetected errors: 576\ +Bit error rate (on message bits only): 2.040e-02\ +seed 257\ +Eliminated 19 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80063 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19937, with src errs 19982, both 19901\ +Total good frames: 79982 Total undetected errors: 81\ +Bit error rate (on message bits only): 1.963e-02\ +seed 258\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79533 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20467, with src errs 20537, both 20422\ +Total good frames: 79418 Total undetected errors: 115\ +Bit error rate (on message bits only): 1.994e-02\ +seed 259\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79807 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20193, with src errs 20229, both 20151\ +Total good frames: 79729 Total undetected errors: 78\ +Bit error rate (on message bits only): 1.959e-02\ +seed 260\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79837 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20163, with src errs 20196, both 20130\ +Total good frames: 79771 Total undetected errors: 66\ +Bit error rate (on message bits only): 2.004e-02\ +seed 261\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79765 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20235, with src errs 20330, both 20178\ +Total good frames: 79613 Total undetected errors: 152\ +Bit error rate (on message bits only): 2.002e-02\ +seed 262\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79534 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20466, with src errs 20484, both 20429\ +Total good frames: 79479 Total undetected errors: 55\ +Bit error rate (on message bits only): 2.018e-02\ +seed 263\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79060 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20940, with src errs 21028, both 20899\ +Total good frames: 78931 Total undetected errors: 129\ +Bit error rate (on message bits only): 2.015e-02\ +seed 264\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78878 valid. Average 59.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21122, with src errs 21151, both 21052\ +Total good frames: 78779 Total undetected errors: 99\ +Bit error rate (on message bits only): 2.048e-02\ +seed 265\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79512 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20488, with src errs 20609, both 20438\ +Total good frames: 79341 Total undetected errors: 171\ +Bit error rate (on message bits only): 2.024e-02\ +seed 266\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79709 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20291, with src errs 20290, both 20235\ +Total good frames: 79654 Total undetected errors: 55\ +Bit error rate (on message bits only): 1.975e-02\ +seed 267\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79249 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20751, with src errs 20848, both 20707\ +Total good frames: 79108 Total undetected errors: 141\ +Bit error rate (on message bits only): 2.024e-02\ +seed 268\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79937 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20063, with src errs 20077, both 20026\ +Total good frames: 79886 Total undetected errors: 51\ +Bit error rate (on message bits only): 1.973e-02\ +seed 269\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79153 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20847, with src errs 20837, both 20788\ +Total good frames: 79104 Total undetected errors: 49\ +Bit error rate (on message bits only): 2.027e-02\ +seed 270\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79133 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20867, with src errs 20920, both 20839\ +Total good frames: 79052 Total undetected errors: 81\ +Bit error rate (on message bits only): 2.036e-02\ +seed 271\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79914 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20086, with src errs 20120, both 20038\ +Total good frames: 79832 Total undetected errors: 82\ +Bit error rate (on message bits only): 1.963e-02\ +seed 272\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79665 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20335, with src errs 20382, both 20308\ +Total good frames: 79591 Total undetected errors: 74\ +Bit error rate (on message bits only): 1.999e-02\ +seed 273\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79481 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20519, with src errs 20549, both 20495\ +Total good frames: 79427 Total undetected errors: 54\ +Bit error rate (on message bits only): 2.047e-02\ +seed 274\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79662 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20338, with src errs 20359, both 20298\ +Total good frames: 79601 Total undetected errors: 61\ +Bit error rate (on message bits only): 1.997e-02\ +seed 275\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79446 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20554, with src errs 20644, both 20513\ +Total good frames: 79315 Total undetected errors: 131\ +Bit error rate (on message bits only): 2.012e-02\ +seed 276\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78823 valid. Average 59.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21177, with src errs 21204, both 21128\ +Total good frames: 78747 Total undetected errors: 76\ +Bit error rate (on message bits only): 2.042e-02\ +seed 277\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79632 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20368, with src errs 20391, both 20328\ +Total good frames: 79569 Total undetected errors: 63\ +Bit error rate (on message bits only): 2.005e-02\ +seed 278\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79578 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20422, with src errs 20416, both 20342\ +Total good frames: 79504 Total undetected errors: 74\ +Bit error rate (on message bits only): 1.985e-02\ +seed 279\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79802 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20198, with src errs 20243, both 20167\ +Total good frames: 79726 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.976e-02\ +seed 280\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79559 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20441, with src errs 20465, both 20395\ +Total good frames: 79489 Total undetected errors: 70\ +Bit error rate (on message bits only): 2.002e-02\ +seed 281\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79676 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20324, with src errs 20398, both 20290\ +Total good frames: 79568 Total undetected errors: 108\ +Bit error rate (on message bits only): 2.007e-02\ +seed 282\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79230 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20770, with src errs 20860, both 20724\ +Total good frames: 79094 Total undetected errors: 136\ +Bit error rate (on message bits only): 2.009e-02\ +seed 283\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79639 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20361, with src errs 20402, both 20328\ +Total good frames: 79565 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.004e-02\ +seed 284\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79496 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20504, with src errs 20516, both 20467\ +Total good frames: 79447 Total undetected errors: 49\ +Bit error rate (on message bits only): 2.036e-02\ +seed 285\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79270 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20730, with src errs 20746, both 20668\ +Total good frames: 79192 Total undetected errors: 78\ +Bit error rate (on message bits only): 2.022e-02\ +seed 286\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79486 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20514, with src errs 20599, both 20474\ +Total good frames: 79361 Total undetected errors: 125\ +Bit error rate (on message bits only): 2.001e-02\ +seed 287\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79444 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20556, with src errs 20555, both 20498\ +Total good frames: 79387 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.003e-02\ +seed 288\ +Had to place 1 checks in rows unevenly\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79476 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20524, with src errs 20563, both 20495\ +Total good frames: 79408 Total undetected errors: 68\ +Bit error rate (on message bits only): 2.010e-02\ +seed 289\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79454 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20546, with src errs 20980, both 20491\ +Total good frames: 78965 Total undetected errors: 489\ +Bit error rate (on message bits only): 1.986e-02\ +seed 290\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79758 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20242, with src errs 20339, both 20196\ +Total good frames: 79615 Total undetected errors: 143\ +Bit error rate (on message bits only): 1.986e-02\ +seed 291\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79761 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20239, with src errs 20272, both 20187\ +Total good frames: 79676 Total undetected errors: 85\ +Bit error rate (on message bits only): 1.987e-02\ +seed 292\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79215 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20785, with src errs 20825, both 20722\ +Total good frames: 79112 Total undetected errors: 103\ +Bit error rate (on message bits only): 1.998e-02\ +seed 293\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79491 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20509, with src errs 20625, both 20463\ +Total good frames: 79329 Total undetected errors: 162\ +Bit error rate (on message bits only): 1.990e-02\ +seed 294\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79054 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20946, with src errs 20955, both 20895\ +Total good frames: 78994 Total undetected errors: 60\ +Bit error rate (on message bits only): 2.044e-02\ +seed 295\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79569 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20431, with src errs 20484, both 20375\ +Total good frames: 79460 Total undetected errors: 109\ +Bit error rate (on message bits only): 2.024e-02\ +seed 296\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79985 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20015, with src errs 20061, both 19975\ +Total good frames: 79899 Total undetected errors: 86\ +Bit error rate (on message bits only): 1.979e-02\ +seed 297\ +Had to place 1 checks in rows unevenly\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79602 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20398, with src errs 20429, both 20357\ +Total good frames: 79530 Total undetected errors: 72\ +Bit error rate (on message bits only): 2.013e-02\ +seed 298\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78977 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21023, with src errs 21430, both 20966\ +Total good frames: 78513 Total undetected errors: 464\ +Bit error rate (on message bits only): 2.043e-02\ +seed 299\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79285 valid. Average 58.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20715, with src errs 20742, both 20653\ +Total good frames: 79196 Total undetected errors: 89\ +Bit error rate (on message bits only): 1.989e-02\ +seed 300\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79698 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20302, with src errs 20421, both 20255\ +Total good frames: 79532 Total undetected errors: 166\ +Bit error rate (on message bits only): 1.983e-02\ +seed 301\ +Eliminated 17 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79900 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20100, with src errs 20129, both 20071\ +Total good frames: 79842 Total undetected errors: 58\ +Bit error rate (on message bits only): 1.989e-02\ +seed 302\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79536 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20464, with src errs 20471, both 20417\ +Total good frames: 79482 Total undetected errors: 54\ +Bit error rate (on message bits only): 1.992e-02\ +seed 303\ +Eliminated 47 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79026 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20974, with src errs 21000, both 20933\ +Total good frames: 78959 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.042e-02\ +seed 304\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79558 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20442, with src errs 20563, both 20412\ +Total good frames: 79407 Total undetected errors: 151\ +Bit error rate (on message bits only): 1.988e-02\ +seed 305\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79590 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20410, with src errs 20430, both 20364\ +Total good frames: 79524 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.999e-02\ +seed 306\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79647 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20353, with src errs 20361, both 20305\ +Total good frames: 79591 Total undetected errors: 56\ +Bit error rate (on message bits only): 2.014e-02\ +seed 307\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79494 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20506, with src errs 20520, both 20469\ +Total good frames: 79443 Total undetected errors: 51\ +Bit error rate (on message bits only): 1.999e-02\ +seed 308\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79789 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20211, with src errs 20254, both 20181\ +Total good frames: 79716 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.990e-02\ +seed 309\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78928 valid. Average 59.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21072, with src errs 21164, both 21034\ +Total good frames: 78798 Total undetected errors: 130\ +Bit error rate (on message bits only): 2.034e-02\ +seed 310\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79434 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20566, with src errs 20601, both 20532\ +Total good frames: 79365 Total undetected errors: 69\ +Bit error rate (on message bits only): 2.007e-02\ +seed 311\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79849 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20151, with src errs 20158, both 20098\ +Total good frames: 79789 Total undetected errors: 60\ +Bit error rate (on message bits only): 1.983e-02\ +seed 312\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79060 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20940, with src errs 20986, both 20883\ +Total good frames: 78957 Total undetected errors: 103\ +Bit error rate (on message bits only): 2.019e-02\ +seed 313\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79726 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20274, with src errs 20295, both 20224\ +Total good frames: 79655 Total undetected errors: 71\ +Bit error rate (on message bits only): 1.987e-02\ +seed 314\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79601 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20399, with src errs 20421, both 20348\ +Total good frames: 79528 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.977e-02\ +seed 315\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79418 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20582, with src errs 20582, both 20523\ +Total good frames: 79359 Total undetected errors: 59\ +Bit error rate (on message bits only): 1.989e-02\ +seed 316\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79264 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20736, with src errs 20746, both 20684\ +Total good frames: 79202 Total undetected errors: 62\ +Bit error rate (on message bits only): 2.024e-02\ +seed 317\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79501 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20499, with src errs 20558, both 20445\ +Total good frames: 79388 Total undetected errors: 113\ +Bit error rate (on message bits only): 1.976e-02\ +seed 318\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79684 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20316, with src errs 20323, both 20256\ +Total good frames: 79617 Total undetected errors: 67\ +Bit error rate (on message bits only): 1.995e-02\ +seed 319\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79108 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20892, with src errs 20931, both 20853\ +Total good frames: 79030 Total undetected errors: 78\ +Bit error rate (on message bits only): 2.026e-02\ +seed 320\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79769 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20231, with src errs 20259, both 20201\ +Total good frames: 79711 Total undetected errors: 58\ +Bit error rate (on message bits only): 1.993e-02\ +seed 321\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79933 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20067, with src errs 20104, both 20028\ +Total good frames: 79857 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.974e-02\ +seed 322\ +Eliminated 46 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79574 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20426, with src errs 20480, both 20388\ +Total good frames: 79482 Total undetected errors: 92\ +Bit error rate (on message bits only): 1.991e-02\ +seed 323\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79312 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20688, with src errs 21168, both 20643\ +Total good frames: 78787 Total undetected errors: 525\ +Bit error rate (on message bits only): 2.026e-02\ +seed 324\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79658 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20342, with src errs 20358, both 20277\ +Total good frames: 79577 Total undetected errors: 81\ +Bit error rate (on message bits only): 1.976e-02\ +seed 325\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80169 valid. Average 56.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19831, with src errs 20324, both 19805\ +Total good frames: 79650 Total undetected errors: 519\ +Bit error rate (on message bits only): 1.985e-02\ +seed 326\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79631 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20369, with src errs 20439, both 20304\ +Total good frames: 79496 Total undetected errors: 135\ +Bit error rate (on message bits only): 1.997e-02\ +seed 327\ +Eliminated 43 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79410 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20590, with src errs 20626, both 20530\ +Total good frames: 79314 Total undetected errors: 96\ +Bit error rate (on message bits only): 1.955e-02\ +seed 328\ +Eliminated 47 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79234 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20766, with src errs 20895, both 20715\ +Total good frames: 79054 Total undetected errors: 180\ +Bit error rate (on message bits only): 2.008e-02\ +seed 329\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79462 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20538, with src errs 20607, both 20498\ +Total good frames: 79353 Total undetected errors: 109\ +Bit error rate (on message bits only): 1.995e-02\ +seed 330\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79486 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20514, with src errs 20525, both 20462\ +Total good frames: 79423 Total undetected errors: 63\ +Bit error rate (on message bits only): 2.013e-02\ +seed 331\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79328 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20672, with src errs 20697, both 20632\ +Total good frames: 79263 Total undetected errors: 65\ +Bit error rate (on message bits only): 2.012e-02\ +seed 332\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79186 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20814, with src errs 20847, both 20728\ +Total good frames: 79067 Total undetected errors: 119\ +Bit error rate (on message bits only): 1.971e-02\ +seed 333\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79562 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20438, with src errs 20538, both 20398\ +Total good frames: 79422 Total undetected errors: 140\ +Bit error rate (on message bits only): 2.014e-02\ +seed 334\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80011 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19989, with src errs 20013, both 19957\ +Total good frames: 79955 Total undetected errors: 56\ +Bit error rate (on message bits only): 1.969e-02\ +seed 335\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79478 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20522, with src errs 20554, both 20484\ +Total good frames: 79408 Total undetected errors: 70\ +Bit error rate (on message bits only): 2.000e-02\ +seed 336\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79543 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20457, with src errs 20466, both 20409\ +Total good frames: 79486 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.002e-02\ +seed 337\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79764 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20236, with src errs 20235, both 20191\ +Total good frames: 79720 Total undetected errors: 44\ +Bit error rate (on message bits only): 1.986e-02\ +seed 338\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79293 valid. Average 58.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20707, with src errs 20710, both 20652\ +Total good frames: 79235 Total undetected errors: 58\ +Bit error rate (on message bits only): 1.996e-02\ +seed 339\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79730 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20270, with src errs 20313, both 20233\ +Total good frames: 79650 Total undetected errors: 80\ +Bit error rate (on message bits only): 1.992e-02\ +seed 340\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79881 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20119, with src errs 20147, both 20083\ +Total good frames: 79817 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.003e-02\ +seed 341\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79255 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20745, with src errs 20745, both 20687\ +Total good frames: 79197 Total undetected errors: 58\ +Bit error rate (on message bits only): 2.010e-02\ +seed 342\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79477 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20523, with src errs 20529, both 20470\ +Total good frames: 79418 Total undetected errors: 59\ +Bit error rate (on message bits only): 2.013e-02\ +seed 343\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79490 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20510, with src errs 20533, both 20465\ +Total good frames: 79422 Total undetected errors: 68\ +Bit error rate (on message bits only): 1.989e-02\ +seed 344\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79906 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20094, with src errs 20198, both 20056\ +Total good frames: 79764 Total undetected errors: 142\ +Bit error rate (on message bits only): 1.989e-02\ +seed 345\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79490 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20510, with src errs 20531, both 20453\ +Total good frames: 79412 Total undetected errors: 78\ +Bit error rate (on message bits only): 1.992e-02\ +seed 346\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79572 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20428, with src errs 20439, both 20379\ +Total good frames: 79512 Total undetected errors: 60\ +Bit error rate (on message bits only): 2.019e-02\ +seed 347\ +Had to place 1 checks in rows unevenly\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79614 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20386, with src errs 20419, both 20348\ +Total good frames: 79543 Total undetected errors: 71\ +Bit error rate (on message bits only): 2.004e-02\ +seed 348\ +Eliminated 21 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79889 valid. Average 56.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20111, with src errs 20161, both 20080\ +Total good frames: 79808 Total undetected errors: 81\ +Bit error rate (on message bits only): 1.985e-02\ +seed 349\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 25.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79246 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20754, with src errs 20757, both 20691\ +Total good frames: 79180 Total undetected errors: 66\ +Bit error rate (on message bits only): 2.002e-02\ +seed 350\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79187 valid. Average 58.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20813, with src errs 20814, both 20746\ +Total good frames: 79119 Total undetected errors: 68\ +Bit error rate (on message bits only): 2.017e-02\ +seed 351\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79619 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20381, with src errs 20484, both 20350\ +Total good frames: 79485 Total undetected errors: 134\ +Bit error rate (on message bits only): 2.028e-02\ +seed 352\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79719 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20281, with src errs 20274, both 20200\ +Total good frames: 79645 Total undetected errors: 74\ +Bit error rate (on message bits only): 2.016e-02\ +seed 353\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79465 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20535, with src errs 20535, both 20490\ +Total good frames: 79420 Total undetected errors: 45\ +Bit error rate (on message bits only): 2.027e-02\ +seed 354\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79383 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20617, with src errs 20641, both 20568\ +Total good frames: 79310 Total undetected errors: 73\ +Bit error rate (on message bits only): 2.000e-02\ +seed 355\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79578 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20422, with src errs 20454, both 20378\ +Total good frames: 79502 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.975e-02\ +seed 356\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79674 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20326, with src errs 20358, both 20282\ +Total good frames: 79598 Total undetected errors: 76\ +Bit error rate (on message bits only): 2.002e-02\ +seed 357\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79572 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20428, with src errs 20443, both 20384\ +Total good frames: 79513 Total undetected errors: 59\ +Bit error rate (on message bits only): 2.020e-02\ +seed 358\ +Had to place 1 checks in rows unevenly\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79688 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20312, with src errs 20315, both 20249\ +Total good frames: 79622 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.983e-02\ +seed 359\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79940 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20060, with src errs 20075, both 20002\ +Total good frames: 79867 Total undetected errors: 73\ +Bit error rate (on message bits only): 1.954e-02\ +seed 360\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79572 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20428, with src errs 20485, both 20385\ +Total good frames: 79472 Total undetected errors: 100\ +Bit error rate (on message bits only): 2.009e-02\ +seed 361\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79495 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20505, with src errs 20512, both 20464\ +Total good frames: 79447 Total undetected errors: 48\ +Bit error rate (on message bits only): 2.018e-02\ +seed 362\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79338 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20662, with src errs 20666, both 20599\ +Total good frames: 79271 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.010e-02\ +seed 363\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78532 valid. Average 60.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21468, with src errs 21475, both 21411\ +Total good frames: 78468 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.048e-02\ +seed 364\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79474 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20526, with src errs 20527, both 20475\ +Total good frames: 79422 Total undetected errors: 52\ +Bit error rate (on message bits only): 1.998e-02\ +seed 365\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79569 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20431, with src errs 20486, both 20394\ +Total good frames: 79477 Total undetected errors: 92\ +Bit error rate (on message bits only): 2.004e-02\ +seed 366\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79881 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20119, with src errs 20132, both 20082\ +Total good frames: 79831 Total undetected errors: 50\ +Bit error rate (on message bits only): 1.996e-02\ +seed 367\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78996 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21004, with src errs 21087, both 20953\ +Total good frames: 78862 Total undetected errors: 134\ +Bit error rate (on message bits only): 2.015e-02\ +seed 368\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79466 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20534, with src errs 20520, both 20469\ +Total good frames: 79415 Total undetected errors: 51\ +Bit error rate (on message bits only): 2.011e-02\ +seed 369\ +Eliminated 49 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 77447 valid. Average 62.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 22553, with src errs 22592, both 22511\ +Total good frames: 77366 Total undetected errors: 81\ +Bit error rate (on message bits only): 2.136e-02\ +seed 370\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79777 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20223, with src errs 20245, both 20178\ +Total good frames: 79710 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.023e-02\ +seed 371\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79821 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20179, with src errs 20179, both 20134\ +Total good frames: 79776 Total undetected errors: 45\ +Bit error rate (on message bits only): 1.974e-02\ +seed 372\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78710 valid. Average 59.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21290, with src errs 21317, both 21249\ +Total good frames: 78642 Total undetected errors: 68\ +Bit error rate (on message bits only): 2.074e-02\ +seed 373\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79094 valid. Average 58.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20906, with src errs 21000, both 20851\ +Total good frames: 78945 Total undetected errors: 149\ +Bit error rate (on message bits only): 2.006e-02\ +seed 374\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79644 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20356, with src errs 20387, both 20302\ +Total good frames: 79559 Total undetected errors: 85\ +Bit error rate (on message bits only): 1.983e-02\ +seed 375\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79434 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20566, with src errs 20573, both 20510\ +Total good frames: 79371 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.998e-02\ +seed 376\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79501 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20499, with src errs 20613, both 20456\ +Total good frames: 79344 Total undetected errors: 157\ +Bit error rate (on message bits only): 2.024e-02\ +seed 377\ +Eliminated 46 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78991 valid. Average 59.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21009, with src errs 21081, both 20957\ +Total good frames: 78867 Total undetected errors: 124\ +Bit error rate (on message bits only): 2.022e-02\ +seed 378\ +Eliminated 46 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79224 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20776, with src errs 21233, both 20746\ +Total good frames: 78737 Total undetected errors: 487\ +Bit error rate (on message bits only): 2.042e-02\ +seed 379\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79534 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20466, with src errs 20504, both 20424\ +Total good frames: 79454 Total undetected errors: 80\ +Bit error rate (on message bits only): 2.017e-02\ +seed 380\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79449 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20551, with src errs 20523, both 20487\ +Total good frames: 79413 Total undetected errors: 36\ +Bit error rate (on message bits only): 2.015e-02\ +seed 381\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79702 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20298, with src errs 20340, both 20248\ +Total good frames: 79610 Total undetected errors: 92\ +Bit error rate (on message bits only): 2.000e-02\ +seed 382\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79349 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20651, with src errs 20752, both 20597\ +Total good frames: 79194 Total undetected errors: 155\ +Bit error rate (on message bits only): 2.026e-02\ +seed 383\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79628 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20372, with src errs 20377, both 20310\ +Total good frames: 79561 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.000e-02\ +seed 384\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79764 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20236, with src errs 20253, both 20185\ +Total good frames: 79696 Total undetected errors: 68\ +Bit error rate (on message bits only): 1.971e-02\ +seed 385\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 34.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79752 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20248, with src errs 20276, both 20215\ +Total good frames: 79691 Total undetected errors: 61\ +Bit error rate (on message bits only): 2.003e-02\ +seed 386\ +Eliminated 38 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79659 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20341, with src errs 20386, both 20307\ +Total good frames: 79580 Total undetected errors: 79\ +Bit error rate (on message bits only): 1.982e-02\ +seed 387\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79402 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20598, with src errs 20613, both 20551\ +Total good frames: 79340 Total undetected errors: 62\ +Bit error rate (on message bits only): 2.039e-02\ +seed 388\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79946 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20054, with src errs 20069, both 20005\ +Total good frames: 79882 Total undetected errors: 64\ +Bit error rate (on message bits only): 1.980e-02\ +seed 389\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79838 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20162, with src errs 20253, both 20128\ +Total good frames: 79713 Total undetected errors: 125\ +Bit error rate (on message bits only): 1.985e-02\ +seed 390\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78889 valid. Average 59.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21111, with src errs 21199, both 21046\ +Total good frames: 78736 Total undetected errors: 153\ +Bit error rate (on message bits only): 1.994e-02\ +seed 391\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79438 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20562, with src errs 20588, both 20528\ +Total good frames: 79378 Total undetected errors: 60\ +Bit error rate (on message bits only): 2.006e-02\ +seed 392\ +Eliminated 20 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79733 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20267, with src errs 20267, both 20221\ +Total good frames: 79687 Total undetected errors: 46\ +Bit error rate (on message bits only): 2.017e-02\ +seed 393\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79552 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20448, with src errs 20471, both 20394\ +Total good frames: 79475 Total undetected errors: 77\ +Bit error rate (on message bits only): 1.998e-02\ +seed 394\ +Eliminated 48 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78941 valid. Average 59.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21059, with src errs 21535, both 21029\ +Total good frames: 78435 Total undetected errors: 506\ +Bit error rate (on message bits only): 2.086e-02\ +seed 395\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79423 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20577, with src errs 20587, both 20535\ +Total good frames: 79371 Total undetected errors: 52\ +Bit error rate (on message bits only): 2.023e-02\ +seed 396\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79170 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20830, with src errs 20838, both 20774\ +Total good frames: 79106 Total undetected errors: 64\ +Bit error rate (on message bits only): 1.999e-02\ +seed 397\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79692 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20308, with src errs 20313, both 20260\ +Total good frames: 79639 Total undetected errors: 53\ +Bit error rate (on message bits only): 1.990e-02\ +seed 398\ +Eliminated 22 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 33.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80037 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19963, with src errs 20020, both 19929\ +Total good frames: 79946 Total undetected errors: 91\ +Bit error rate (on message bits only): 2.006e-02\ +seed 399\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79928 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20072, with src errs 20608, both 20041\ +Total good frames: 79361 Total undetected errors: 567\ +Bit error rate (on message bits only): 2.017e-02\ +seed 400\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80296 valid. Average 55.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19704, with src errs 19804, both 19678\ +Total good frames: 80170 Total undetected errors: 126\ +Bit error rate (on message bits only): 1.975e-02\ +seed 401\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79715 valid. Average 57.3 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20285, with src errs 20348, both 20230\ +Total good frames: 79597 Total undetected errors: 118\ +Bit error rate (on message bits only): 2.027e-02\ +seed 402\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79649 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20351, with src errs 20361, both 20313\ +Total good frames: 79601 Total undetected errors: 48\ +Bit error rate (on message bits only): 2.007e-02\ +seed 403\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79458 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20542, with src errs 20543, both 20492\ +Total good frames: 79407 Total undetected errors: 51\ +Bit error rate (on message bits only): 2.033e-02\ +seed 404\ +Eliminated 39 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79238 valid. Average 58.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20762, with src errs 20802, both 20713\ +Total good frames: 79149 Total undetected errors: 89\ +Bit error rate (on message bits only): 2.027e-02\ +seed 405\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79742 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20258, with src errs 20284, both 20217\ +Total good frames: 79675 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.004e-02\ +seed 406\ +Eliminated 27 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79799 valid. Average 57.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20201, with src errs 20208, both 20164\ +Total good frames: 79755 Total undetected errors: 44\ +Bit error rate (on message bits only): 2.002e-02\ +seed 407\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79565 valid. Average 57.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20435, with src errs 20521, both 20388\ +Total good frames: 79432 Total undetected errors: 133\ +Bit error rate (on message bits only): 2.005e-02\ +seed 408\ +Eliminated 50 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79304 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20696, with src errs 20704, both 20647\ +Total good frames: 79247 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.015e-02\ +seed 409\ +Eliminated 19 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79949 valid. Average 56.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20051, with src errs 20126, both 20005\ +Total good frames: 79828 Total undetected errors: 121\ +Bit error rate (on message bits only): 1.972e-02\ +seed 410\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79479 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20521, with src errs 20544, both 20480\ +Total good frames: 79415 Total undetected errors: 64\ +Bit error rate (on message bits only): 2.003e-02\ +seed 411\ +Eliminated 29 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79814 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20186, with src errs 20212, both 20146\ +Total good frames: 79748 Total undetected errors: 66\ +Bit error rate (on message bits only): 1.971e-02\ +seed 412\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79308 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20692, with src errs 20784, both 20645\ +Total good frames: 79169 Total undetected errors: 139\ +Bit error rate (on message bits only): 2.017e-02\ +seed 413\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.4\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79907 valid. Average 56.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20093, with src errs 20103, both 20059\ +Total good frames: 79863 Total undetected errors: 44\ +Bit error rate (on message bits only): 1.983e-02\ +seed 414\ +Eliminated 26 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79705 valid. Average 57.4 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20295, with src errs 20378, both 20237\ +Total good frames: 79564 Total undetected errors: 141\ +Bit error rate (on message bits only): 1.974e-02\ +seed 415\ +Had to place 1 checks in rows unevenly\ +Eliminated 23 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79436 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20564, with src errs 20600, both 20507\ +Total good frames: 79343 Total undetected errors: 93\ +Bit error rate (on message bits only): 2.027e-02\ +seed 416\ +Eliminated 35 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80047 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19953, with src errs 20010, both 19917\ +Total good frames: 79954 Total undetected errors: 93\ +Bit error rate (on message bits only): 1.972e-02\ +seed 417\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79772 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20228, with src errs 20279, both 20187\ +Total good frames: 79680 Total undetected errors: 92\ +Bit error rate (on message bits only): 1.994e-02\ +seed 418\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79680 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20320, with src errs 20347, both 20280\ +Total good frames: 79613 Total undetected errors: 67\ +Bit error rate (on message bits only): 2.018e-02\ +seed 419\ +Eliminated 48 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.7\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79777 valid. Average 57.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20223, with src errs 20259, both 20183\ +Total good frames: 79701 Total undetected errors: 76\ +Bit error rate (on message bits only): 1.984e-02\ +seed 420\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.1\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79432 valid. Average 58.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20568, with src errs 21147, both 20525\ +Total good frames: 78810 Total undetected errors: 622\ +Bit error rate (on message bits only): 2.010e-02\ +seed 421\ +Eliminated 32 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.0\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79608 valid. Average 57.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20392, with src errs 20413, both 20348\ +Total good frames: 79543 Total undetected errors: 65\ +Bit error rate (on message bits only): 2.001e-02\ +seed 422\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79558 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20442, with src errs 20472, both 20383\ +Total good frames: 79469 Total undetected errors: 89\ +Bit error rate (on message bits only): 1.986e-02\ +seed 423\ +Eliminated 42 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79513 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20487, with src errs 20535, both 20454\ +Total good frames: 79432 Total undetected errors: 81\ +Bit error rate (on message bits only): 1.988e-02\ +seed 424\ +Eliminated 31 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 27.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79998 valid. Average 56.5 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20002, with src errs 20446, both 19966\ +Total good frames: 79518 Total undetected errors: 480\ +Bit error rate (on message bits only): 1.972e-02\ +seed 425\ +Eliminated 21 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80143 valid. Average 56.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19857, with src errs 19903, both 19810\ +Total good frames: 80050 Total undetected errors: 93\ +Bit error rate (on message bits only): 1.970e-02\ +seed 426\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79353 valid. Average 58.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20647, with src errs 21098, both 20601\ +Total good frames: 78856 Total undetected errors: 497\ +Bit error rate (on message bits only): 2.012e-02\ +seed 427\ +Eliminated 25 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79792 valid. Average 57.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20208, with src errs 20236, both 20176\ +Total good frames: 79732 Total undetected errors: 60\ +Bit error rate (on message bits only): 2.003e-02\ +seed 428\ +Eliminated 44 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 78987 valid. Average 59.1 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 21013, with src errs 21471, both 20960\ +Total good frames: 78476 Total undetected errors: 511\ +Bit error rate (on message bits only): 2.043e-02\ +seed 429\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79477 valid. Average 57.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20523, with src errs 20570, both 20491\ +Total good frames: 79398 Total undetected errors: 79\ +Bit error rate (on message bits only): 2.004e-02\ +seed 430\ +Eliminated 28 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80108 valid. Average 56.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19892, with src errs 19887, both 19843\ +Total good frames: 80064 Total undetected errors: 44\ +Bit error rate (on message bits only): 1.965e-02\ +seed 431\ +Eliminated 41 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.8\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79590 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20410, with src errs 20501, both 20365\ +Total good frames: 79454 Total undetected errors: 136\ +Bit error rate (on message bits only): 1.996e-02\ +seed 432\ +Eliminated 33 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.9\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79035 valid. Average 59.0 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20965, with src errs 21044, both 20890\ +Total good frames: 78881 Total undetected errors: 154\ +Bit error rate (on message bits only): 2.012e-02\ +seed 433\ +Eliminated 36 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 31.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79183 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20817, with src errs 20822, both 20765\ +Total good frames: 79126 Total undetected errors: 57\ +Bit error rate (on message bits only): 2.002e-02\ +seed 434\ +Eliminated 45 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79065 valid. Average 58.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20935, with src errs 20927, both 20871\ +Total good frames: 79009 Total undetected errors: 56\ +Bit error rate (on message bits only): 2.013e-02\ +seed 435\ +Eliminated 34 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 26.2\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79337 valid. Average 58.2 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20663, with src errs 20673, both 20610\ +Total good frames: 79274 Total undetected errors: 63\ +Bit error rate (on message bits only): 1.987e-02\ +seed 436\ +Eliminated 16 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.6\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 80343 valid. Average 55.8 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 19657, with src errs 19747, both 19615\ +Total good frames: 80211 Total undetected errors: 132\ +Bit error rate (on message bits only): 1.962e-02\ +seed 437\ +Eliminated 40 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 28.3\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79101 valid. Average 58.9 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20899, with src errs 20904, both 20820\ +Total good frames: 79017 Total undetected errors: 84\ +Bit error rate (on message bits only): 2.041e-02\ +seed 438\ +Eliminated 24 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 32.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79545 valid. Average 57.6 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20455, with src errs 20470, both 20424\ +Total good frames: 79499 Total undetected errors: 46\ +Bit error rate (on message bits only): 1.994e-02\ +seed 439\ +Eliminated 37 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 29.5\ +Encoded 100000 blocks, source block size 72, encoded block size 144\ +Transmitted 14400000 bits\ +Decoded 100000 blocks, 79482 valid. Average 57.7 iterations, 10% bit changes\ +Block counts: tot 100000, with chk errs 20518, with src errs 20607, both 20484\ +Total good frames: 79359 Total undetected errors: 123\ +Bit error rate (on message bits only): 2.012e-02\ +seed 440\ +Eliminated 30 cycles of length four by moving checks within column\ +Number of 1s per check in Inv(A) X B is 30.2\ +Encoded 100000 blocks, source block size 72, encoded block size 14400000\ +} \ No newline at end of file diff --git a/lib/ldpc/jtmode_codes/ldpc-144-72 b/lib/ldpc/jtmode_codes/ldpc-144-72 new file mode 100755 index 000000000..8a0cf9089 --- /dev/null +++ b/lib/ldpc/jtmode_codes/ldpc-144-72 @@ -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 diff --git a/lib/ldpc/jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk b/lib/ldpc/jtmode_codes/ldpc-144-72-6x3-4x4-sf1.pchk new file mode 100644 index 0000000000000000000000000000000000000000..92dee5fc6d37f49fa116a28b4788d7c2b0548ef0 GIT binary patch literal 2264 zcmXZcg;P~g5P%IaXp5evz+9Y=GwIh&bfoC%H02?{9^^NWlc;pa4Hu(~KB}o`}X| z%z}IPPTtyL!PWz5n2L0m&&M~`R3%o!BzSKSzGEZ4k}pYYini#0IJl251FU4`A=W}&#K1nMp#XQu+pBg+!Vq}B?_Z59++mINHAXYI$3d`$8MsZ}8mq&1 zgd!4t_qWJ-*7m0>rXd?a+$2|tXlzW(nJ-goM2m9t6d0yAa^&s}e0N4}v z<*Z*L*MjJteCH%sr}t;VS@GOg;wo!Bx504E^5B_n!4-1WR~b#=xs1Rvtb*U@W!6+6 zy6=`43!k$Am&n;$`)}Wz)$y2ubWF!Z);J@6Ypu}@_TM_3a=?;Q4#MJ+S^+ zu!pBv6G61s_R{n4jMlSFf_(R) zYcq-VIUmQl-hh}0d+Ztb+#D3*7;t;utMDJ^YE^z+Y)?qKXVnokrB>axkkO7~)hkSYBAlQ5B z&4SOc-mrgea|k|c-GeBdHMbM&6wLst_m?6_Ru;#w^Vp8zGnw( d{Pq)&j0JFSIdERKlaC;#U_P?poY;T={sZ` +#include +#include + +#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; i0) + { 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 +#include +#include +#include + +#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; jdistrib_size(d)) + { abort(); + } + left = part[z]; + } + for (k = 0; k=0; k--) + { u[k] = k%M; + } + + uneven = 0; + t = 0; + z = 0; + left = part[z]; + + for (j = 0; jdistrib_size(d)) + { abort(); + } + left = part[z]; + } + + for (k = 0; k0) + { 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; i1) + { 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; z1 && 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; j0) + { 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; in) + { abort(); + } + + while (usedtrunc[cur]) + { cur = j; + } + } + part[cur] += 1; + used += 1; + trunc[cur] = -1; + } + + free(trunc); + return part; +} diff --git a/lib/ldpc/make-pchk.c b/lib/ldpc/make-pchk.c new file mode 100755 index 000000000..7459ca9b8 --- /dev/null +++ b/lib/ldpc/make-pchk.c @@ -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 +#include +#include +#include + +#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); +} diff --git a/lib/ldpc/mod2convert-test-out b/lib/ldpc/mod2convert-test-out new file mode 100755 index 000000000..430eec0b4 --- /dev/null +++ b/lib/ldpc/mod2convert-test-out @@ -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. diff --git a/lib/ldpc/mod2convert-test.c b/lib/ldpc/mod2convert-test.c new file mode 100755 index 000000000..eac257ff5 --- /dev/null +++ b/lib/ldpc/mod2convert-test.c @@ -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 +#include +#include + +#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 +#include +#include + +#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; imod2sparse_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 + + Modulo-2 Matrix Sparse/Dense Conversion + + + + +

Modulo-2 Matrix Sparse/Dense Conversion

+ +

The routines below convert modulo-2 matrices between the form used by +the routines for dense modulo-2 matrices +and the form used by the routines for sparse +modulo-2 matrices. + +

Header files required: +mod2sparse.h mod2dense.h mod2convert.h + + +


mod2sparse_to_dense: +Convert a modulo-2 matrix from sparse to dense form. + +
+void mod2sparse_to_dense 
+( mod2sparse *m,  /* Sparse matrix to convert */
+  mod2dense *r    /* Place to store result */
+)
+
+ +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. + + +


mod2dense_to_sparse: +Convert a modulo-2 matrix from dense to sparse form. + +
+void mod2dense_to_sparse 
+( mod2dense *m,  /* Dense matrix to convert */
+  mod2sparse *r  /* Place to store result */
+)
+
+ +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. + + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/mod2dense-test-out b/lib/ldpc/mod2dense-test-out new file mode 100755 index 000000000..e38525b6c --- /dev/null +++ b/lib/ldpc/mod2dense-test-out @@ -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. diff --git a/lib/ldpc/mod2dense-test.c b/lib/ldpc/mod2dense-test.c new file mode 100755 index 000000000..f38ad54f0 --- /dev/null +++ b/lib/ldpc/mod2dense-test.c @@ -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 +#include +#include + +#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 +#include +#include + +#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; jn_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; jn_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; jn_words; k++) + { r->col[j][k] = m->col[j][k]; + } + for ( ; kn_words; k++) + { r->col[j][k] = 0; + } + } + + for ( ; jn_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(m)) + { fprintf(stderr,"mod2dense_copyrows: Row index out of range\n"); + exit(1); + } + for (j = 0; jmod2dense_rows(r)) + { fprintf(stderr, + "mod2dense_copycols: Destination matrix has fewer rows than source\n"); + exit(1); + } + + for (j = 0; j=mod2dense_cols(m)) + { fprintf(stderr,"mod2dense_copycols: Column index out of range\n"); + exit(1); + } + for (k = 0; kn_words; k++) + { r->col[j][k] = m->col[cols[j]][k]; + } + for ( ; kn_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; in_rows); + if (ferror(f)) return 0; + + intio_write(f,m->n_cols); + if (ferror(f)) return 0; + + for (j = 0; jn_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; jn_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> mod2_wordsize_shift; + v = 1 << (j1 & mod2_wordsize_mask); + + p = m->col[j1]; + k1 = 0; + + for (j2 = 0; j2col[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; jn_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; jn_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; jcol[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> mod2_wordsize_shift; + b0 = i & mod2_wordsize_mask; + + for (j = i; jcol[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; jcol[j][k0],b0)) + { s = m->col[j]; + t = m->col[i]; + for (k = k0; kcol[j]; + t = r->col[i]; + for (k = 0; kn_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> mod2_wordsize_shift; + b0 = rows[i] & mod2_wordsize_mask; + + for (j = i; jcol[cols[j]][k0],b0)) break; + } + + if (jcol[j][k0],b0)) + { s = m->col[j]; + t = m->col[c]; + for (k = 0; kcol[j]; + t = r->col[c]; + for (k = 0; kcol[cols[j]]; + for (k = 0; kn_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> mod2_wordsize_shift; + b0 = i & mod2_wordsize_mask; + + for (j = i; jcol[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; jcol[j][k0],b0)) + { s = m->col[j]; + t = m->col[i]; + for (k = k0; kcol[j]; + t = r->col[i]; + for (k = 0; k /* 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 *); diff --git a/lib/ldpc/mod2dense.html b/lib/ldpc/mod2dense.html new file mode 100755 index 000000000..2b8313873 --- /dev/null +++ b/lib/ldpc/mod2dense.html @@ -0,0 +1,487 @@ + + + Dense Modulo-2 Matrix Routines + + + + +

Dense Modulo-2 Matrix Routines

+ +

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. + +

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 sparse modulo-2 matrix routines. Matrices +can be converted between these two formats using the module-2 matrix conversion routines. + +

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. + + +

Representation of dense matrices

+ +

This module represents a matrix by a pointer to a structure of type +mod2dense. 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. + + +

Header files required: +mod2dense.h + + + +


+
Dimension Macros
+
+ +
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 mod2dense_allocate: +
+mod2dense_rows(m)   /* Returns the number of rows in m */
+
+mod2dense_cols(m)   /* Returns the number of columns in m */
+
+ + + +


+
Allocating and Freeing Dense Modulo-2 Matrices
+
+ + +
mod2dense_allocate: +Allocate space for a dense module-2 matrix.
+ +
+mod2dense *mod2dense_allocate 
+( int n_rows,    /* Number of rows in matrix */
+  int n_cols     /* Number of columns in matrix */
+)
+
+ +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 mod2dense_free once it is no longer in use. + +


mod2dense_free: +Free the space occupied by a dense module-2 matrix. + +
+void mod2dense_free 
+( mod2dense *m   /* Pointer to matrix to free */
+)
+
+ +Frees the space occupied by the matrix for re-use. The pointer passed +should no longer be used. + + + +


+
Copying and Clearing Dense Modulo-2 Matrices
+
+ +
mod2dense_clear: +Set all elements of a matrix to zero.
+ +
+void mod2dense_clear
+( mod2dense *m   /* Pointer to matrix to clear */
+)
+
+ +Sets all of the elements of the matrix passed to 0. + +


mod2dense_copy: +Copy the contents of one matrix to another. + +
+void mod2dense_copy
+( mod2dense *m   /* Pointer to matrix to copy from */
+  mod2dense *r   /* Pointer to matrix to receive data */
+)
+
+ +Copies the contents of the first matrix passed, m, to the +second matrix passed, r, which must already have been +allocated, and must have at least as many rows and columns as the +first. If r is larger than m, its elements that have +row or column indexes greater than the dimension of m are set +to zeros. + + +


mod2dense_copyrows: +Copy selected rows from one matrix to another. + +
+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 */
+)
+
+ +Copies selected rows of the first matrix, m, to the second +matrix, r, which must already have been allocated, and which +must have at least as many columns as m. The indexes of the +rows to copy are given in order as an array of length the same as +the number of rows in r; duplicates are allowed. Row +indexes start at 0. These rows are copied to r, with the +row indexed by the first entry in rows going to the first +row of r, and so forth. If r has more columns than +m, the extra entries in each row are set to zeros. + + +


mod2dense_copycols: +Copy selected columns from one matrix to another. + +
+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 */
+)
+
+ +Copies selected columns of the first matrix, m, to the second +matrix, r, which must already have been allocated, and which +must have at least as many rows as m. The indexes of the +columns to copy are given in order as an array of length the same as +the number of columns in r; duplicates are allowed. Column +indexes start at 0. These columns are copied to r, with the +column indexed by the first entry in cols going to the first +column of r, and so forth. If r has more rows than +m, the extra entries in each column are set to zeros. + + + +


+
Input and Output of Dense Modulo-2 Matrices
+
+ +
mod2dense_print: +Print a dense modulo-2 matrix in human-readable form.
+ +
+void mod2dense_print
+( FILE *f,       /* File to print to */
+  mod2dense *m   /* Pointer to matrix to print */
+)
+
+ +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. + +


mod2dense_write: +Write a dense modulo-2 matrix to a file in machine-readable format. + +
+int mod2dense_write
+( FILE *f,       /* File to write data to */
+  mod2dense *m   /* Pointer to matrix write out */
+)
+
+ +Writes a machine-readable representation the dense matrix m to +the file f. 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. + +

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 mod2dense_read even on a machine with a +different byte-ordering. + +

The value returned by mod2dense_write is one if the +operation was successful, zero if an error of some sort occurred. + +


mod2dense_read: +Read a dense modulo-2 matrix from a file. + +
+mod2dense *mod2dense_read
+( FILE *f,       /* File to read data from */
+)
+
+ +Reads a dense modulo-2 matrix from the file f. 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 +mod2dense_read is called should have been written by mod2dense_write. Other binary data may +precede or follow this data. + +

The value returned is a pointer to the matrix read, for which space +will have been allocated by mod2dense_read, or zero if an +error occurred (either an error reading the file, or data not in the +right format). + + + +


+
Elementary Operations on Dense Modulo-2 Matrices
+
+ +
mod2dense_get: +Get an element of a dense modulo-2 matrix.
+ +
+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) */
+)
+
+ +Returns the value (0 or 1) of the element in the given row and column +of the matrix m. + +


mod2dense_set: +Set an element of a dense modulo-2 matrix. + +
+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) */
+)
+
+ +Set the element in the given row and column of the matrix m to +the specified value. + +


mod2dense_flip: +Flip an element of a dense modulo-2 matrix. + +
+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) */
+)
+
+ +Flips the value of the element in the given row and column of the +matrix m, changing it to 0 if it was 1, and to 1 if it was 0. +Returns the new value of this element. + + + +


+
Dense Modulo-2 Matrix Arithmetic and Comparison
+
+ +
mod2dense_transpose: +Compute the transpose of a dense modulo-2 matrix.
+ +
+void mod2dense_transpose
+( mod2dense *m,   /* Matrix to compute transpose of */
+  mod2dense *r    /* Result of transpose operation */
+)
+
+ +Stores the transpose of its first argument, m, in the matrix +pointed to by its second argument, r, which must already have +been allocated, and which must have as many rows as m has +columns, and as many columns as m has rows. The two matrices +m and r must not be the same (ie, the two pointers +passed must be different). + +


mod2dense_add: +Add two dense modulo-2 matrices. + +
+void mod2dense_add
+( mod2dense *m1,  /* Left operand of add */
+  mod2dense *m2,  /* Right operand of add */
+  mod2dense *r    /* Place to store result of add */
+)
+
+ +Adds matrices m1 and m2, storing the result in the +matrix pointed to by r. All three matrices must have the same +numbers of rows and columns. It is permissible for r to be the +same as m1 and/or m2. Neither of the first two matrices is +changed by this procedure (unless they are the same as r). + + +


mod2dense_multiply: +Multiply two dense modulo-2 matrices. + +
+void mod2dense_multiply 
+( mod2dense *m1,  /* Left operand of multiply */
+  mod2dense *m2,  /* Right operand of multiply */
+  mod2dense *r    /* Place to store result of multiply */
+)
+
+ +Does a matrix multiplication of m1 by m2, and stores the +result in the matrix pointed to by r. The matrices must have +compatible numbers of rows and columns. Neither of the first two +matrices is changed by this procedure. The result matrix, r, +must not be the same as either m1 or m2. + +

The algorithm used runs faster if m2 contains mostly 0s, but +it is also appropriate for matrices with many 1s. + +


mod2dense_equal: +Check whether two dense modulo-2 matrices are equal. + +
+int mod2dense_equal
+( mod2dense *m1, /* Pointers to the two matrices */
+  mod2dense *m2  /*   to compare                 */
+)
+
+ +Returns one if every element of m1 is equal to the +corresponding element of m2, and otherwise returns zero. The +two matrices must have the same number of rows and the same number of +columns. + + +


+
Dense Modulo-2 Matrix Inversion
+
+ +
mod2dense_invert: +Invert a dense modulo-2 matrix.
+ +
+int mod2dense_invert
+( mod2dense *m,   /* Matrix to find inverse of (destroyed) */
+  mod2dense *r    /* Place to store the inverse */
+)
+
+ +

Inverts the first matrix passed, m, and stores its inverse in +the second matrix, r. The contents of m are destroyed +by this operation, though it remains a valid matrix for storing into +later. The matrix m must have the same number of rows as +columns. The matrix r must already have been allocated, and +must have the same number of rows and columns as m. The +two matrices passed must not be the same. + +

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). + +

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. + +


mod2dense_forcibly_invert: +Forcibly invert a matrix by changing bits if necessary. + +
+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 */
+)
+
+ +

Inverts the first matrix passed, m, and stores its inverse +in the second matrix, r, proceeding with the inversion even if +m is singular, by changing some elements as necessary. The +contents of m are destroyed by this operation, though it +remains a valid matrix for storing into later. The matrix m +must have the same number of rows as columns. The matrix r +must already have been allocated, and must have the same number of +rows and columns as m. The two matrices passed must not be the +same. + +

The value returned is the number of elements of m 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.) + +

See mod2dense_invert for the algorithm used. + +


mod2dense_invert_selected: +Invert a matrix with columns selected from a bigger matrix. + +
+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 */
+)
+
+ +

Inverts a matrix obtained by selecting certain columns from the +first matrix passed, m, which must have at least as many +columns as rows. The second matrix passed, r, must already +exist, and must have the same number of rows and columns as m. +The result of inverting the sub-matrix of m is stored in the +corresponding columns of r, with the other columns being set to +garbage (or zero, see below). Normally, one would extract just the +relevant columns afterwards using mod2dense_copycols.) The contents of +m are destroyed (though it remains a valid matrix for storing +into later. The two matrices passed must not be the same. + +

The indexes of the columns selected are stored, in order, in the last +argument, cols, followed by the columns not selected (in +arbitrary order). The argument rows 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. + +

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 +r identified by the initial portions of cols and +rows, 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 m. The remaining portion +of cols up to the number of rows in m will contain +indexes of columns of r that are selected arbitrarily; these +columns will, however, be set to contain all zeros. + +

Note that when the first matrix is square, and non-singular, the +result is NOT in general the same as that obtained by calling mod2dense_invert, since that procedure +orders the columns of the inverse so that it applies to the original +ordering of the columns of the first matrix. + +

See mod2dense_invert for the algorithm used. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/mod2sparse-test-out b/lib/ldpc/mod2sparse-test-out new file mode 100755 index 000000000..5d17ddecf --- /dev/null +++ b/lib/ldpc/mod2sparse-test-out @@ -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. diff --git a/lib/ldpc/mod2sparse-test.c b/lib/ldpc/mod2sparse-test.c new file mode 100755 index 000000000..04c26250a --- /dev/null +++ b/lib/ldpc/mod2sparse-test.c @@ -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 +#include +#include + +#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); +} diff --git a/lib/ldpc/mod2sparse.c b/lib/ldpc/mod2sparse.c new file mode 100755 index 000000000..66e66799d --- /dev/null +++ b/lib/ldpc/mod2sparse.c @@ -0,0 +1,1361 @@ +/* MOD2SPARSE.C - Procedures 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. + */ + + +/* NOTE: See mod2sparse.html for documentation on these procedures. */ + + +#include +#include +#include + +#include "alloc.h" +#include "intio.h" +#include "mod2sparse.h" + + +/* ALLOCATE AN ENTRY WITHIN A MATRIX. This local procedure is used to + allocate a new entry, representing a non-zero element, within a given + matrix. Entries in this matrix that were previously allocated and + then freed are re-used. If there are no such entries, a new block + of entries is allocated. */ + +static mod2entry *alloc_entry +( mod2sparse *m +) +{ + mod2block *b; + mod2entry *e; + int k; + + if (m->next_free==0) + { + b = chk_alloc (1, sizeof *b); + + b->next = m->blocks; + m->blocks = b; + + for (k = 0; kentry[k].left = m->next_free; + m->next_free = &b->entry[k]; + } + } + + e = m->next_free; + m->next_free = e->left; + + e->pr = 0; + e->lr = 0; + + return e; +} + + +/* ALLOCATE SPACE FOR A SPARSE MOD2 MATRIX. */ + +mod2sparse *mod2sparse_allocate +( int n_rows, /* Number of rows in matrix */ + int n_cols /* Number of columns in matrix */ +) +{ + mod2sparse *m; + mod2entry *e; + int i, j; + + if (n_rows<=0 || n_cols<=0) + { fprintf(stderr,"mod2sparse_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->rows = chk_alloc (n_rows, sizeof *m->rows); + m->cols = chk_alloc (n_cols, sizeof *m->cols); + + m->blocks = 0; + m->next_free = 0; + + for (i = 0; irows[i]; + e->left = e->right = e->up = e->down = e; + e->row = e->col = -1; + } + + for (j = 0; jcols[j]; + e->left = e->right = e->up = e->down = e; + e->row = e->col = -1; + } + + return m; +} + + +/* FREE SPACE OCCUPIED BY A SPARSE MOD2 MATRIX. */ + +void mod2sparse_free +( mod2sparse *m /* Matrix to free */ +) +{ + mod2block *b; + + free(m->rows); + free(m->cols); + + while (m->blocks!=0) + { b = m->blocks; + m->blocks = b->next; + free(b); + } +} + + +/* CLEAR A SPARSE MATRIX TO ALL ZEROS. */ + +void mod2sparse_clear +( mod2sparse *r +) +{ + mod2block *b; + mod2entry *e; + int i, j; + + for (i = 0; irows[i]; + e->left = e->right = e->up = e->down = e; + } + + for (j = 0; jcols[j]; + e->left = e->right = e->up = e->down = e; + } + + while (r->blocks!=0) + { b = r->blocks; + r->blocks = b->next; + free(b); + } +} + + +/* COPY A SPARSE MATRIX. */ + +void mod2sparse_copy +( mod2sparse *m, /* Matrix to copy */ + mod2sparse *r /* Place to store copy of matrix */ +) +{ + mod2entry *e, *f; + int i; + + if (mod2sparse_rows(m)>mod2sparse_rows(r) + || mod2sparse_cols(m)>mod2sparse_cols(r)) + { fprintf(stderr,"mod2sparse_copy: Destination matrix is too small\n"); + exit(1); + } + + mod2sparse_clear(r); + + for (i = 0; irow,e->col); + f->lr = e->lr; + f->pr = e->pr; + e = mod2sparse_next_in_row(e); + } + } +} + + +/* COPY ROWS OF A SPARSE MOD2 MATRIX. */ + +void mod2sparse_copyrows +( mod2sparse *m, /* Matrix to copy */ + mod2sparse *r, /* Place to store copy of matrix */ + int *rows /* Indexes of rows to copy, from 0 */ +) +{ + mod2entry *e; + int i; + + if (mod2sparse_cols(m)>mod2sparse_cols(r)) + { fprintf(stderr, + "mod2sparse_copyrows: Destination matrix has fewer columns than source\n"); + exit(1); + } + + mod2sparse_clear(r); + + for (i = 0; i=mod2sparse_rows(m)) + { fprintf(stderr,"mod2sparse_copyrows: Row index out of range\n"); + exit(1); + } + e = mod2sparse_first_in_row(m,rows[i]); + while (!mod2sparse_at_end(e)) + { mod2sparse_insert(r,i,e->col); + e = mod2sparse_next_in_row(e); + } + } +} + + +/* COPY COLUMNS OF A SPARSE MOD2 MATRIX. */ + +void mod2sparse_copycols +( mod2sparse *m, /* Matrix to copy */ + mod2sparse *r, /* Place to store copy of matrix */ + int *cols /* Indexes of columns to copy, from 0 */ +) +{ + mod2entry *e; + int j; + + if (mod2sparse_rows(m)>mod2sparse_rows(r)) + { fprintf(stderr, + "mod2sparse_copycols: Destination matrix has fewer rows than source\n"); + exit(1); + } + + mod2sparse_clear(r); + + for (j = 0; j=mod2sparse_cols(m)) + { fprintf(stderr,"mod2sparse_copycols: Column index out of range\n"); + exit(1); + } + e = mod2sparse_first_in_col(m,cols[j]); + while (!mod2sparse_at_end(e)) + { mod2sparse_insert(r,e->row,j); + e = mod2sparse_next_in_col(e); + } + } +} + + +/* PRINT A SPARSE MOD2 MATRIX IN HUMAN-READABLE FORM. */ + +void mod2sparse_print +( FILE *f, + mod2sparse *m +) +{ + int rdigits, cdigits; + mod2entry *e; + int i; + + rdigits = mod2sparse_rows(m)<=10 ? 1 + : mod2sparse_rows(m)<=100 ? 2 + : mod2sparse_rows(m)<=1000 ? 3 + : mod2sparse_rows(m)<=10000 ? 4 + : mod2sparse_rows(m)<=100000 ? 5 + : 6; + + cdigits = mod2sparse_cols(m)<=10 ? 1 + : mod2sparse_cols(m)<=100 ? 2 + : mod2sparse_cols(m)<=1000 ? 3 + : mod2sparse_cols(m)<=10000 ? 4 + : mod2sparse_cols(m)<=100000 ? 5 + : 6; + + for (i = 0; in_rows); + if (ferror(f)) return 0; + + intio_write(f,m->n_cols); + if (ferror(f)) return 0; + + for (i = 0; i=n_rows) break; + } + else + { col = v-1; + if (col>=n_cols) break; + if (row==-1) break; + mod2sparse_insert(m,row,col); + } + } + + /* Error if we get here. */ + + mod2sparse_free(m); + return 0; +} + + +/* LOOK FOR AN ENTRY WITH GIVEN ROW AND COLUMN. */ + +mod2entry *mod2sparse_find +( mod2sparse *m, + int row, + int col +) +{ + mod2entry *re, *ce; + + if (row<0 || row>=mod2sparse_rows(m) || col<0 || col>=mod2sparse_cols(m)) + { fprintf(stderr,"mod2sparse_find: row or column index out of bounds\n"); + exit(1); + } + + /* Check last entries in row and column. */ + + re = mod2sparse_last_in_row(m,row); + if (mod2sparse_at_end(re) || mod2sparse_col(re)col) + { return 0; + } + if (mod2sparse_col(re)==col) + { return re; + } + + if (mod2sparse_at_end(ce) || mod2sparse_row(ce)>row) + { return 0; + } + if (mod2sparse_row(ce)==row) + { return ce; + } + + re = mod2sparse_next_in_row(re); + ce = mod2sparse_next_in_col(ce); + } +} + + +/* INSERT AN ENTRY WITH GIVEN ROW AND COLUMN. */ + +mod2entry *mod2sparse_insert +( mod2sparse *m, + int row, + int col +) +{ + mod2entry *re, *ce, *ne; + + if (row<0 || row>=mod2sparse_rows(m) || col<0 || col>=mod2sparse_cols(m)) + { fprintf(stderr,"mod2sparse_insert: row or column index out of bounds\n"); + exit(1); + } + + /* Find old entry and return it, or allocate new entry and insert into row. */ + + re = mod2sparse_last_in_row(m,row); + + if (!mod2sparse_at_end(re) && mod2sparse_col(re)==col) + { return re; + } + + if (mod2sparse_at_end(re) || mod2sparse_col(re)right; + } + else + { + re = mod2sparse_first_in_row(m,row); + + for (;;) + { + if (!mod2sparse_at_end(re) && mod2sparse_col(re)==col) + { return re; + } + + if (mod2sparse_at_end(re) || mod2sparse_col(re)>col) + { break; + } + + re = mod2sparse_next_in_row(re); + } + } + + ne = alloc_entry(m); + + ne->row = row; + ne->col = col; + + ne->left = re->left; + ne->right = re; + ne->left->right = ne; + ne->right->left = ne; + + /* Insert new entry into column. If we find an existing entry here, + the matrix must be garbled, since we didn't find it in the row. */ + + ce = mod2sparse_last_in_col(m,col); + + if (!mod2sparse_at_end(ce) && mod2sparse_row(ce)==row) + { fprintf(stderr,"mod2sparse_insert: Garbled matrix\n"); + exit(1); + } + + if (mod2sparse_at_end(ce) || mod2sparse_row(ce)down; + } + else + { + ce = mod2sparse_first_in_col(m,col); + + for (;;) + { + if (!mod2sparse_at_end(ce) && mod2sparse_row(ce)==row) + { fprintf(stderr,"mod2sparse_insert: Garbled matrix\n"); + exit(1); + } + + if (mod2sparse_at_end(ce) || mod2sparse_row(ce)>row) + { break; + } + + ce = mod2sparse_next_in_col(ce); + } + } + + ne->up = ce->up; + ne->down = ce; + ne->up->down = ne; + ne->down->up = ne; + + /* Return the new entry. */ + + return ne; +} + + +/* DELETE AN ENTRY FROM A SPARSE MATRIX. */ + +void mod2sparse_delete +( mod2sparse *m, + mod2entry *e +) +{ + if (e==0) + { fprintf(stderr,"mod2sparse_delete: Trying to delete a null entry\n"); + exit(1); + } + + if (e->row<0 || e->col<0) + { fprintf(stderr,"mod2sparse_delete: Trying to delete a header entry\n"); + exit(1); + } + + e->left->right = e->right; + e->right->left = e->left; + + e->up->down = e->down; + e->down->up = e->up; + + e->left = m->next_free; + m->next_free = e; +} + + +/* TEST WHETHER TWO SPARSE MATRICES ARE EQUAL. */ + +int mod2sparse_equal +( mod2sparse *m1, + mod2sparse *m2 +) +{ + mod2entry *e1, *e2; + int i; + + if (mod2sparse_rows(m1)!=mod2sparse_rows(m2) + || mod2sparse_cols(m1)!=mod2sparse_cols(m2)) + { fprintf(stderr,"mod2sparse_equal: Matrices have different dimensions\n"); + exit(1); + } + + for (i = 0; i=mod2sparse_rows(m)) + { fprintf(stderr,"mod2sparse_count_row: row index out of bounds\n"); + exit(1); + } + + count = 0; + + for (e = mod2sparse_first_in_row(m,row); + !mod2sparse_at_end(e); + e = mod2sparse_next_in_row(e)) + { count += 1; + } + + return count; +} + + +/* COUNT ENTRIES IN A COLUMN. */ + +int mod2sparse_count_col +( mod2sparse *m, + int col +) +{ + mod2entry *e; + int count; + + if (col<0 || col>=mod2sparse_cols(m)) + { fprintf(stderr,"mod2sparse_count_col: column index out of bounds\n"); + exit(1); + } + + count = 0; + + for (e = mod2sparse_first_in_col(m,col); + !mod2sparse_at_end(e); + e = mod2sparse_next_in_col(e)) + { count += 1; + } + + return count; +} + + +/* ADD TO A ROW. */ + +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 */ +) +{ + mod2entry *f1, *f2, *ft; + + if (mod2sparse_cols(m1)=mod2sparse_rows(m1) + || row2<0 || row2>=mod2sparse_rows(m2)) + { fprintf (stderr,"mod2sparse_add_row: row index out of range\n"); + exit(1); + } + + f1 = mod2sparse_first_in_row(m1,row1); + f2 = mod2sparse_first_in_row(m2,row2); + + while (!mod2sparse_at_end(f1) && !mod2sparse_at_end(f2)) + { if (mod2sparse_col(f1)>mod2sparse_col(f2)) + { mod2sparse_insert(m1,row1,mod2sparse_col(f2)); + f2 = mod2sparse_next_in_row(f2); + } + else + { ft = mod2sparse_next_in_row(f1); + if (mod2sparse_col(f1)==mod2sparse_col(f2)) + { mod2sparse_delete(m1,f1); + f2 = mod2sparse_next_in_row(f2); + } + f1 = ft; + } + } + + while (!mod2sparse_at_end(f2)) + { mod2sparse_insert(m1,row1,mod2sparse_col(f2)); + f2 = mod2sparse_next_in_row(f2); + } +} + + +/* ADD TO A COLUMN. */ + +void mod2sparse_add_col +( mod2sparse *m1, /* Matrix containing column to add to */ + int col1, /* Index in this matrix of column to add to */ + mod2sparse *m2, /* Matrix containing column to add from */ + int col2 /* Index in this matrix of column to add from */ +) +{ + mod2entry *f1, *f2, *ft; + + if (mod2sparse_rows(m1)=mod2sparse_cols(m1) + || col2<0 || col2>=mod2sparse_cols(m2)) + { fprintf (stderr,"mod2sparse_add_col: Column index out of range\n"); + exit(1); + } + + f1 = mod2sparse_first_in_col(m1,col1); + f2 = mod2sparse_first_in_col(m2,col2); + + while (!mod2sparse_at_end(f1) && !mod2sparse_at_end(f2)) + { if (mod2sparse_row(f1)>mod2sparse_row(f2)) + { mod2sparse_insert(m1,mod2sparse_row(f2),col1); + f2 = mod2sparse_next_in_col(f2); + } + else + { ft = mod2sparse_next_in_col(f1); + if (mod2sparse_row(f1)==mod2sparse_row(f2)) + { mod2sparse_delete(m1,f1); + f2 = mod2sparse_next_in_col(f2); + } + f1 = ft; + } + } + + while (!mod2sparse_at_end(f2)) + { mod2sparse_insert(m1,mod2sparse_row(f2),col1); + f2 = mod2sparse_next_in_col(f2); + } +} + + +/* FIND AN LU DECOMPOSITION OF A SPARSE MATRIX. */ + +int mod2sparse_decomp +( mod2sparse *A, /* Input matrix, 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 */ +) +{ + int *rinv, *cinv, *acnt, *rcnt; + mod2sparse *B; + int M, N; + + mod2entry *e, *f, *fn, *e2; + int i, j, k, cc, cc2, cc3, cr2, pr; + int found, nnf; + + M = mod2sparse_rows(A); + N = mod2sparse_cols(A); + + if (mod2sparse_cols(L)!=K || mod2sparse_rows(L)!=M + || mod2sparse_cols(U)!=N || mod2sparse_rows(U)!=K) + { fprintf (stderr, + "mod2sparse_decomp: Matrices have incompatible dimensions\n"); + exit(1); + } + + if (abandon_number>N-K) + { fprintf(stderr,"Trying to abandon more columns than allowed\n"); + exit(1); + } + + rinv = chk_alloc (M, sizeof *rinv); + cinv = chk_alloc (N, sizeof *cinv); + + if (abandon_number>0) + { acnt = chk_alloc (M+1, sizeof *acnt); + } + + if (strategy==Mod2sparse_minprod) + { rcnt = chk_alloc (M, sizeof *rcnt); + } + + mod2sparse_clear(L); + mod2sparse_clear(U); + + /* Copy A to B. B will be modified, then discarded. */ + + B = mod2sparse_allocate(M,N); + mod2sparse_copy(A,B); + + /* Count 1s in rows of B, if using minprod strategy. */ + + if (strategy==Mod2sparse_minprod) + { for (i = 0; i=i) + { found = 1; + goto out_first; + } + e = mod2sparse_next_in_col(e); + } + } + + out_first: + break; + } + + case Mod2sparse_mincol: + { + found = 0; + + for (j = i; j=i) + { found = 1; + cc = cc2; + e = e2; + k = j; + break; + } + e2 = mod2sparse_next_in_col(e2); + } + } + } + + break; + } + + case Mod2sparse_minprod: + { + found = 0; + + for (j = i; j=i) + { cr2 = rcnt[mod2sparse_row(e2)]; + if (!found || cc2==1 || (cc2-1)*(cr2-1)i) + { mod2sparse_add_row(B,k,B,mod2sparse_row(e)); + if (strategy==Mod2sparse_minprod) + { rcnt[k] = mod2sparse_count_row(B,k); + } + mod2sparse_insert(L,k,i); + } + else if (rinv[k]0 && i==abandon_when) + { + for (k = 0; kk || cc3==k && cc>0) + { if (cc3==k) cc -= 1; + for (;;) + { f = mod2sparse_first_in_col(B,j); + if (mod2sparse_at_end(f)) break; + mod2sparse_delete(B,f); + } + cc2 += 1; + } + } + + if (cc2!=abandon_number) abort(); + + if (strategy==Mod2sparse_minprod) + { for (j = 0; j0) free(acnt); + + return nnf; +} + + +/* SOLVE A LOWER-TRIANGULAR SYSTEM BY FORWARD SUBSTITUTION. */ + +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 */ +) +{ + int K, i, j, ii, b, d; + mod2entry *e; + + K = mod2sparse_cols(L); + + /* Make sure that L is lower-triangular, after row re-ordering. */ + + for (i = 0; ii) + { fprintf(stderr, + "mod2sparse_forward_sub: Matrix is not lower-triangular\n"); + exit(1); + } + } + + /* Solve system by forward substitution. */ + + for (i = 0; ii) + { fprintf(stderr, + "mod2sparse_backward_sub: Matrix is not upper-triangular\n"); + exit(1); + } + } + + /* Solve system by backward substitution. */ + + for (i = K-1; i>=0; i--) + { + ii = cols ? cols[i] : i; + + /* Look at bits in this row, forming inner product with partial + solution, and seeing if the diagonal is 1. */ + + d = 0; + b = 0; + + for (e = mod2sparse_first_in_row(U,i); + !mod2sparse_at_end(e); + e = mod2sparse_next_in_row(e)) + { + j = mod2sparse_col(e); + + if (j==ii) + { d = 1; + } + else + { b ^= z[j]; + } + } + + /* Check for no solution if the diagonal isn't 1. */ + + if (!d && b!=y[i]) + { return 0; + } + + /* Set bit of solution, zero if arbitrary. */ + + z[ii] = b^y[i]; + } + + return 1; +} diff --git a/lib/ldpc/mod2sparse.h b/lib/ldpc/mod2sparse.h new file mode 100755 index 000000000..23d8d79f2 --- /dev/null +++ b/lib/ldpc/mod2sparse.h @@ -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 *); diff --git a/lib/ldpc/mod2sparse.html b/lib/ldpc/mod2sparse.html new file mode 100755 index 000000000..1681d4a7e --- /dev/null +++ b/lib/ldpc/mod2sparse.html @@ -0,0 +1,719 @@ + + + Sparse Modulo-2 Matrix Routines + + + + +

Sparse Modulo-2 Matrix Routines

+ +

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. + +

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 dense modulo-2 matrix routines. Matrices +can be converted between these two formats using the module-2 matrix conversion routines. + +

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. + + +

Representation of sparse matrices

+ +

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 +mod2entry, 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 pr and lr, which are +of no significance to this module, but which are used by the routines +for decoding LDPC codes by probability +propagation. + +

The mod2sparse type represents a matrix. It records the +number of rows and columns in the matrix, and contains arrays of +pointers to the mod2entry structures for the first non-zero +element in each row and the first non-zero element in each column. + +

Matrices must be created by the mod2sparse_allocate procedure, which +returns a pointer to a mod2sparse structure. When a matrix +is no longer needed, the space it occupies can be freed with mod2sparse_free. Elements within a matrix, +represented by mod2entry 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 mod2sparse_free, or cleared to all zeros, +with mod2sparse_clear, or used as +the result matrix for copying or arithmetic operations. + + +

Header files required: +mod2sparse.h + + + +


+
Dimension Macros
+
+ +
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 mod2sparse_allocate: +
+mod2sparse_rows(m)   /* Returns the number of rows in m */
+
+mod2sparse_cols(m)   /* Returns the number of columns in m */
+
+ + + +


+
Traversal Macros
+
+ +
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 +mod2sparse_at_end macro. If one is already at this special +entry, moving further wraps one around to the first or last entry. + +

The macros for finding the first or last entry in a row or column +take as their arguments a pointer to the matrix (mod2sparse +*) and a row or column index, starting at zero. The other macros +take as their arguments a pointer to an entry (mod2entry *) +within some matrix. + +

+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 */
+
+ + + +


+
Allocating and Freeing Sparse Modulo-2 Matrices
+
+ + +
mod2sparse_allocate: +Allocate space for a sparse module-2 matrix.
+ +
+mod2sparse *mod2sparse_allocate 
+( int n_rows,     /* Number of rows in matrix */
+  int n_cols      /* Number of columns in matrix */
+)
+
+ +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. + +

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 mod2sparse_free once it is no +longer in use. + +


mod2sparse_free: +Free the space occupied by a sparse module-2 matrix. + +
+void mod2sparse_free 
+( mod2sparse *m   /* Pointer to matrix to free */
+)
+
+ +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 mod2sparse_clear is called, or the matrix +is used as the destination for other operations. + + + +


+
Copying and Clearing Sparse Modulo-2 Matrices
+
+ +
mod2sparse_clear: +Set all elements of a matrix to zero.
+ +
+void mod2sparse_clear
+( mod2sparse *m   /* Pointer to matrix to clear */
+)
+
+ +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 mod2sparse_free. + + +


mod2sparse_copy: +Copy the contents of one matrix to another. + +
+void mod2sparse_copy
+( mod2sparse *m   /* Pointer to matrix to copy from */
+  mod2sparse *r   /* Pointer to matrix to receive data */
+)
+
+ +Copies the contents of the first matrix passed, m, to the +second matrix passed, r, which must already have been +allocated, and must have at least as many rows and columns as the +first. If r is larger than m, its elements that have +row or column indexes greater than the dimension of m are set +to zeros. + +

The space occupied by the previous non-zero entries of r is +freed for general use (which may include being reused immediately for +the copies of the entries in m). + + +


mod2sparse_copyrows: +Copy selected rows from one matrix to another. + +
+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 */
+)
+
+ +Copies selected rows of the first matrix, m, to the second +matrix, r, which must already have been allocated, and which +must have at least as many columns as m. The indexes of the +rows to copy are given in order as an array of length the same as +the number of rows in r; duplicates are allowed. Row +indexes start at 0. These rows are copied to r, with the +row indexed by the first entry in rows going to the +first row of r, and so forth. If r has more columns than +m, the extra entries in each row are set to zeros. + +

The space occupied by the previous non-zero entries of r is +freed for general use (which may include being reused immediately for +the copies of the entries in m). + + +


mod2sparse_copycols: +Copy selected columns from one matrix to another. + +
+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 */
+)
+
+ +Copies selected columns of the first matrix, m, to the second +matrix, r, which must already have been allocated, and which +must have at least as many rows as m. The indexes of the +columns to copy are given in order as an array of length the same as +the number of columns in r; duplicates are allowed. Column +indexes start at 0. These columns are copied to r, with the +column indexed by the first entry in cols going to the +first column of r, and so forth. If r has more rows than +m, the extra entries in each column are set to zeros. + +

The space occupied by the previous non-zero entries of r is +freed for general use (which may include being reused immediately for +the copies of the entries in m). + + + +


+
Input and Output of Sparse Modulo-2 Matrices
+
+ +
mod2sparse_print: +Print a sparse modulo-2 matrix in human-readable form.
+ +
+void mod2sparse_print
+( FILE *f,        /* File to print to */
+  mod2sparse *m   /* Pointer to matrix to print */
+)
+
+ +The matrix is printed on standard output with one line of output per row, +of the form +
+row: col col col ...
+
+where row is the index of the row, and the col 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. + +


mod2sparse_write: +Write a sparse modulo-2 matrix to a file in machine-readable format. + +
+int mod2sparse_write
+( FILE *f,        /* File to write data to */
+  mod2sparse *m   /* Pointer to matrix write out */
+)
+
+ +Writes a machine-readable representation the sparse matrix m to +the file f. 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. + +

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 mod2sparse_read even on a machine with a +different byte-ordering. + +

The value returned by mod2sparse_write is one if the +operation was successful, zero if an error of some sort occurred. + +


mod2sparse_read: +Read a sparse modulo-2 matrix from a file. + +
+mod2sparse *mod2sparse_read
+( FILE *f,        /* File to read data from */
+)
+
+ +Reads a sparse modulo-2 matrix from the file f. 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 +mod2sparse_read is called should have been written by mod2sparse_write. Other binary data may +precede or follow this data. + +

The value returned is a pointer to the matrix read, for which space +will have been allocated by mod2sparse_read, or zero if an +error occurred (either an error reading the file, or data not in the +right format). + + + +


+
Elementary Operations on Sparse Modulo-2 Matrices
+
+ +
mod2sparse_find: +Look for an entry at a given row and column.
+ +
+mod2entry *mod2sparse_find
+( mod2sparse *m,  /* Matrix in which to look for entry */
+  int row,        /* Row index (from 0) */
+  int col         /* Column index (from 0) */
+)
+
+ +Looks for an entry at the given row and column in the matrix m, +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). + +

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. + +


mod2sparse_insert: +Insert an entry at a given row and column. + +
+mod2entry *mod2sparse_insert
+( mod2sparse *m,  /* Matrix in which to insert an entry */
+  int row,        /* Row index (from 0) */
+  int col         /* Column index (from 0) */
+)
+
+ +Adds a new entry (representing an element with value 1) at the given +row and column position in the matrix m. 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. + +

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. + +

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. + +


mod2sparse_delete: +Delete an entry from a sparse modulo-2 matrix. + +
+void mod2sparse_delete
+( mod2sparse *m,  /* Matrix in which to delete an entry */
+  mod2entry *e    /* Entry to delete - MUST be in m */
+)
+
+ +Deletes the entry e from the sparse matrix m, 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. + +

The time required for this operation does not depend on how many +entries are currently in the matrix. + +

Warning: It is an error if e is not an entry of +m. This error is not currently diagnosed, but doing this may +cause serious problems, as it may lead later to entries for m +being erroneously freed when the matrix to which e properly +belongs is freed. + + +


+
Sparse Modulo-2 Matrix Arithmetic and Comparison
+
+ +
mod2sparse_transpose: +Compute the transpose of a sparse modulo-2 matrix.
+ +
+void mod2sparse_transpose
+( mod2sparse *m,  /* Matrix to compute transpose of */
+  mod2sparse *r   /* Result of transpose operation */
+)
+
+ +Stores the transpose of its first argument, m, in the matrix +pointed to by its second argument, r, which must already have +been allocated, and which must have as many rows as m has +columns, and as many columns as m has rows. The two matrices +m and r must not be the same (ie, the two pointers +passed must be different). + +

The space occupied by the previous non-zero entries of r is +freed for general use. + +


mod2sparse_add: +Add two sparse modulo-2 matrices. + +
+void mod2sparse_add
+( mod2sparse *m1, /* Left operand of add */
+  mod2sparse *m2, /* Right operand of add */
+  mod2sparse *r   /* Place to store result of add */
+)
+
+ +Adds matrices m1 and m2, storing the result in the +matrix pointed to by r. All three matrices must have the same +numbers of rows and columns. It is permissible for r to be the +same as m1 and/or m2. Neither of the first two matrices is +changed by this procedure (unless they are the same as r). + +

The space occupied by the previous non-zero entries of r is +freed for general use. + + +


mod2sparse_multiply: +Multiply two sparse modulo-2 matrices. + +
+void mod2sparse_multiply 
+( mod2sparse *m1, /* Left operand of multiply */
+  mod2sparse *m2, /* Right operand of multiply */
+  mod2sparse *r   /* Place to store result of multiply */
+)
+
+ +Does a matrix multiplication of m1 by m2, and stores the +result in the matrix pointed to by r. The matrices must have +compatible numbers of rows and columns. Neither of the first two +matrices is changed by this procedure. The result matrix, r, +must not be the same as either m1 or m2. + +

The space occupied by the previous non-zero entries of r is +freed for general use. + +


mod2sparse_mulvec: +Multiply a vector by a sparse modulo-2 matrix. + +
+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 */
+)
+
+ +Multiplies the vector u on the left by the sparse modulo-2 +matrix m, storing the result in v. Both u and +v are modulo-2 vectors, but are stored unpacked, with one bit +per char. Any non-zero value in u is equivalent to '1'. +The vectors u and v must not overlap. + +


mod2sparse_equal: +Check whether two sparse modulo-2 matrices are equal. + +
+int mod2sparse_equal
+( mod2sparse *m1, /* Pointers to the two matrices */
+  mod2sparse *m2  /*   to compare                 */
+)
+
+ +Returns one if every element of m1 is equal to the +corresponding element of m2, and otherwise returns zero. The +two matrices must have the same number of rows and the same number of +columns. + + + +


+
Row/Column Operations on Sparse Modulo-2 Matrices +
+ +
mod2sparse_count_row: +Count the number of 1s in a row of a sparse matrix.
+ +
+int mod2sparse_count_row
+( mod2sparse *m,  /* Pointer to matrix */
+  int row         /* Index of row to count (from 0) */
+)
+
+ +Returns the number of 1s in the given row of the matrix, by counting +the number of entries in that row. + +


mod2sparse_count_col: +Count the number of 1s in a column of a sparse matrix. + +
+int mod2sparse_count_col
+( mod2sparse *m,  /* Pointer to matrix */
+  int col         /* Index of column to count (from 0) */
+)
+
+ +Returns the number of 1s in the given column of the matrix, by counting +the number of entries in that column. + +


mod2sparse_add_row: +Add a row to a row of a sparse matrix. + +
+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 */
+)
+
+ +Modifies the row with index row1 in the matrix m1 by +adding to that row the row with index row2 in the matrix +m2. The matrix m1 must have at least as many columns as +m2. This operation is performed by inserting entries into the +row of m1 at positions where they exist in the row of m2 +but not in the row of m1, and deleting entries in the row of +m1 that exist in the same position in the row of m2. +The matrix m2 is not modified. + +


mod2sparse_add_col: +Add a column to a column of a sparse matrix. + +
+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 */
+)
+
+ +Modifies the column with index col1 in the matrix m1 by +adding to that column the column with index col2 in the matrix +m2. The matrix m1 must have at least as many rows as +m2. This operation is performed by inserting entries into the +column of m1 at positions where they exist in the column of +m2 but not in the column of m1, and deleting entries in +the column of m1 that exist in the same position in the column +of m2. The matrix m2 is not modified. + + + +


+
LU Decomposition of Sparse Modulo-2 Matrices
+
+ +
mod2sparse_decomp: +Find an LU decomposition of a sparse modulo-2 (sub-)matrix.
+ +
+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 */
+)
+
+ +

Takes as input a matrix, A, having M rows and +N columns, and an integer K. Finds an LU decomposition +of a K by K sub-matrix of A. The decomposition +is stored in the matrix L, with M rows and K +columns, and the matrix U, with K rows and N +columns. The product of L and U will be equal to the +K by K submatrix of A obtained by taking only +rows and columns that are given in the first K elements of the +rows and cols arrays, which are set by this procedure, +with this sub-matrix distributed over the original M rows and +N columns. Furthermore, the ordering of the row and column +indexes in these arrays will be set so that if the rows of L +and the columns of U were rearranged in this order, L +would be lower triangular, with zeros in rows past row K, and +U would be upper triangular, with zeros in columns past column +K. The rows array is M long, and the cols +array is N long. The elements in both arrays after the first +K contain the indexes of the rows and columns not selected to +be part of the sub-matrix of A, in arbitrary order. + +

The rows and columns of A are selected in order to try to +make the LU decomposition as sparse as possible, using the strategy +identified by the strategy, abandon_number, and +abandon_when parameters. The possible strategies are +Mod2sparse_first, Mod2sparse_mincol, and +Mod2sparse_minprod. If abandon_number is greater than +zero, it is possible that the matrix will appear to have linearly +dependent rows when it actually does not. See the discussion of sparse LU decomposition +methods for details about these strategies. + +

If A is not of rank K or more, L will contain +some number less than K of non-zero columns, and U will +contain an equal number of non-zero rows. The entries in the +rows and cols 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 K by K sub-matrix of full rank was +found). + +

The matrix A is not altered. The previous contents of +L and U are cleared. + +


mod2sparse_forward_sub: +Solve a lower-triangular system by forward substitution. + +
+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 */
+)
+
+ +

Solves the system of equations Ly=x for y by +forward substitution, based on L being lower triangular after +its rows are reordered according to the given index array. The +vectors x and y are stored unpacked, one bit per +character. If L is M by K, then x should +be M long, but only the K bits indexed by rows +are looked at. The solution vector, y, must be K long. +Only K rows of L are used, as also determined by the +K indexes in the rows argument. If rows is null, +the first K rows of L and the first K elements of +x are used. + +

If the matrix L does not have 1s on its diagonal (after row +rearrangement), there may be no solution, depending on what x +is. If no solution exists, this procedure returns zero, otherwise it +returns one. Any arbitrary bits in the solution are set to zero. + +


mod2sparse_backward_sub: +Solve an upper-triangular system by backward substitution. + +
+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 */
+)
+
+ +

Solves Uz=y for z by backward substitution, +based on U being upper triangular after its columns are +reordered according to the given index array. The vectors y +and z are stored unpacked, one bit per character. If U +is K by N, then the solution vector, z, should be +N long, but only the K bits indexed by cols are +set. The vector y must be K long. Only K columns +of U are used, as also determined by the K indexes in +the cols argument. The other columns of U must be zero +(this is not checked, but is necessary for the method used to work). +If cols is null, the first K columns of U and the +first K elements of z are used. + +

If the matrix U 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. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/modify.html b/lib/ldpc/modify.html new file mode 100755 index 000000000..209b3ea7e --- /dev/null +++ b/lib/ldpc/modify.html @@ -0,0 +1,125 @@ + + + Notes on Modifying the LDPC Programs + + + + +

Notes on Modifying the LDPC Programs

+ +

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 module documentation. + +

Adding a new type of channel

+ +

Channels are involved in two programs: +transmit and +decode. +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: +

    +
  1. 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 channel_type + declared in channel.h. You + may also need to declare new global variables to store parameters of + the channel in channel.h and + channel.c. +
  2. Modify the channel_parse and + channel_usage procedures in + channel.c to + parse the specification of the new channel and display an appropriate + usage message. +
  3. 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 transmit.c to write the + new channel's output for each transmitted bit, after randomly generating + any noise (see + the documentation on random number generation). +
  4. Modify decode.c 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. +
  5. Document the new channel type in channel.html + and decoding.html. +
+ +

Adding a new decoding procedure

+ +A new decoding method can be implemented as follows: +
    +
  1. Decide on a syntax for specifying the method and its parameters, + using the trailing arguments to the + decode program. Pick an + internal name for the method, and add it as a possibility in the + enumerated decoding_method type in + dec.h. You may also need to declare + new variables for the method's parameters in + dec.h and dec.c. +
  2. Modify the argument parsing code in + decode.c + to handle specifications of the new method, and change the usage + procedure to display the syntax for specifying the new method. +
  3. Write a setup procedure for your decoding method, putting it in + dec.c, with a declaration in + dec.h. At a minimum, this procedure + should print headers for the table of detailed decoding information + when the -T option was specified. +
  4. Write a decode procedure implementing your method, putting it in + dec.c, with a declaration in + dec.h. This procedure should output + detailed trace information when the -T option was specified. +
  5. Modify decode.c in the appropriate + places to call the setup procedure and the decode procedure you wrote. +
  6. Document the new decoding method in + decoding.html and + decode-detail.html. +
+ +

Adding a new method of making a low-density parity-check matrix

+ +

The make-ldpc program can be +changed to add a new method for generating a LDPC code by modifying +make-ldpc.c. A radically different +method might better be implemented by writing a new program of similar +structure. + + +

Adding a new encoding method

+ +

A new heuristic for finding a sparse LU decomposition can be +implemented by changing make-gen.c to allow +the new heuristic to be specified on the command line, changing the mod2sparse_decomp procedure +in mod2sparse.c to implement the +heuristic, and documenting the new heuristic in encoding.html, sparse-LU.html, and mod2sparse.html. + +

To implement a completely new encoding method, you will first need +to define a new file format for a generator matrix, modify make-gen.c appropriately to write out this new +format, and modify the read_gen procedure in rcode.c to read this format. You will +need to implement the new method in a procedure in enc.c, and modify encode.c so +that it will call this new procedure when the new method is used. The +enum_decode procedure in dec.c will also +need to be modified so it can call the new encoding method. Finally, +you should document the new method in encoding.html + +

+ +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/modules.html b/lib/ldpc/modules.html new file mode 100755 index 000000000..93228ffe3 --- /dev/null +++ b/lib/ldpc/modules.html @@ -0,0 +1,89 @@ + + + Modules Used in LDPC Programs + + + + +

Modules Used in LDPC Programs

+ +You may need to familiarize yourself with the modules documented here +in order to modify the LDPC programs. +These modules may also be useful for other purposes. + +

Click on the title of a module below for general information, or on +specific routines for detailed documentation. + +

Dense modulo-2 matrix routines: +

+Dimension macros:    mod2dense_rows  mod2dense_cols
+
+Allocation:          Copy/Clear:         Input/Output:    Elementary ops:
+
+mod2dense_allocate   mod2dense_clear     mod2dense_print  mod2dense_get
+mod2dense_free       mod2dense_copy      mod2dense_write  mod2dense_set
+                     mod2dense_copyrows  mod2dense_read   mod2dense_flip
+                     mod2dense_copycols
+
+Matrix arithmetic:   Matrix inversion:
+
+mod2dense_transpose  mod2dense_invert
+mod2dense_add        mod2dense_forcibly_invert
+mod2dense_multiply   mod2dense_invert_selected
+mod2dense_equal
+
+ +

Sparse modulo-2 matrix routines: +

+Dimension macros:    mod2sparse_rows  mod2sparse_cols
+
+Traversal macros:    mod2sparse_first_in_row  mod2sparse_next_in_row  ...
+
+Allocation:          Copy/Clear:         Input/Output:     Elementary ops:
+
+mod2sparse_allocate  mod2sparse_clear    mod2sparse_print  mod2sparse_find
+mod2sparse_free      mod2sparse_copy     mod2sparse_write  mod2sparse_insert
+                     mod2sparse_copyrows mod2sparse_read   mod2sparse_delete
+                     mod2sparse_copycols
+
+Matrix arithmetic:   Row/Column ops:       LU decomposition:
+
+mod2sparse_transpose mod2sparse_count_row  mod2sparse_decomp
+mod2sparse_add       mod2sparse_count_col  mod2sparse_forward_sub
+mod2sparse_multiply  mod2sparse_add_row    mod2sparse_backward_sub
+mod2sparse_mulvec    mod2sparse_add_col
+mod2sparse_equal
+
+Discussion of sparse LU decomposition methods. +
+ +

Modulo-2 matrix sparse/dense conversion: +

+mod2sparse_to_dense
+mod2dense_to_sparse
+
+ +

Random variate generation routines: +

+Set/Get state:   Uniform:       Discrete:         Continuous:
+
+rand_seed        rand_uniform   rand_int          rand_gaussian
+rand_get_state   rand_uniopen   rand_pickd        rand_logistic
+rand_use_state                  rand_pickf        rand_cauchy
+                                rand_poisson      rand_gamma
+                                rand_permutation  rand_exp
+                                                  rand_beta
+
+ +

Each of the modules above has a test program, called +module-test. These programs are compiled by the command +

+make tests 
+
+See the source files for these test programs for further information. + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/open.c b/lib/ldpc/open.c new file mode 100755 index 000000000..8e850681d --- /dev/null +++ b/lib/ldpc/open.c @@ -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 +#include +#include + +#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); + } +} diff --git a/lib/ldpc/open.h b/lib/ldpc/open.h new file mode 100755 index 000000000..2cb88b267 --- /dev/null +++ b/lib/ldpc/open.h @@ -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 *); diff --git a/lib/ldpc/pchk-to-alist.c b/lib/ldpc/pchk-to-alist.c new file mode 100755 index 000000000..9670105ae --- /dev/null +++ b/lib/ldpc/pchk-to-alist.c @@ -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 +#include +#include +#include + +#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; imxrw) + { mxrw = rw[i]; + } + } + + cw = (int *) chk_alloc (N, sizeof *cw); + mxcw = 0; + + for (j = 0; jmxcw) + { mxcw = cw[j]; + } + } + + fprintf(af,"%d %d\n",mxrw,mxcw); + + for (i = 0; i + + Creating a Parity Check Matrix + + + + +

Creating a Parity Check Matrix

+ +

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 parity check matrix, +H, with M rows and N columns. The valid +codewords are the vectors, x, of length N, for which +Hx=0, where all arithmetic is done modulo-2. Each row +of H represents a parity check on a subset of the bits in +x; all these parity checks must be satisfied for x 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 H that are redundant because they are +linear combinations of other rows. + +

This software stores parity check matrices in files in a sparse +format. These parity-check files are not human-readable +(except by using the print-pchk +program). However, they are readable on a machine with a +different architecture than they were written on. + +

Some LDPC software by David MacKay and others uses the +alist +format 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. + + +

Methods for constructing LDPC codes

+ +

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. + +

Many methods for constructing LDPC matrices are described in the +references. Two simple methods are currently +implemented by this software, both of which operate according to the +following scheme: +

    +
  1. Create a preliminary parity check matrix by one of the methods. +
  2. 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. +
  3. 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 linear + dependence in parity check matrices.) +
  4. 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. +
+ +

The evencol 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. + +

The evenboth 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. + +

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. + + +


make-pchk: Make a parity check +matrix by explicit specification. + +
+make-pchk pchk-file n-checks n-bits row:col ...
+
+ +

Creates a file named pchk-file in +which it stores a parity check matrix with n-checks +rows and n-bits columns. This parity check matrix +consists of all 0s except for 1s at the row:col +positions listed. Rows and columns are numbered starting at zero. +This program is intended primarily for testing and demonstration +purposes. + +

Example: The well-known Hamming code with codewords of +length N=7 and with M=3 parity checks can be can be +created as follows: +

    +
  • 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 +
+ + +


alist-to-pchk: Convert a parity +check matrix from alist format to the sparse matrix format used by +this software. + +
+alist-to-pchk [ -t ] alist-file pchk-file
+
+ +

Converts a parity check matrix in +alist +format stored in the file named alist-file to +the sparse matrix format used by this software, storing it in the +file named pchk-file. + +

If the -t option is given, the transpose of the parity check +matrix in alist-file is stored in the +pchk-file. + +

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 alist-to-pchk, so no error is reported if +the set of indexes in a row or column description are not those +on a single line. + + +


pchk-to-alist: Convert a parity +check matrix to alist format. + +
+pchk-to-alist [ -t ] [ -z ] pchk-file alist-file
+
+ +

Converts a parity check matrix stored in the sparse matrix format +used by this software, in the file named pchk-file, to +the alist +format, storing it in the file named alist-file. + +

If the -t option is given, the transpose of the parity check +matrix is converted to alist format. + +

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, +pchk-to-alist does this, but output of these 0s can be +suppressed by specifying the -z option. (The alist-to-pchk +program will accept alist files produced with or without the -z +option.) + + +


print-pchk: Print a parity check matrix. + +
+print-pchk [ -d ] [ -t ] pchk-file
+
+ +

Prints a human-readable representation of the parity check matrix stored +in pchk-file. +The -d 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 -t option is present, what is +printed is the transpose of the parity check matrix. + +

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. + +

The dense display is the obvious array of 0s and 1s. Long lines +are not wrapped. + +

Example: The parity check matrix for the Hamming code created +by the example for make-pchk would print +as follows: +

    +
  • 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 + +
  • 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 +
+ + +


make-ldpc: Make a low density parity +check matrix, by random generation. + +
+make-ldpc pchk-file n-checks n-bits seed method
+
+
+where method is one of the following: +
+evencol checks-per-col [ no4cycle ]
+
+evencol checks-distribution [ no4cycle ]
+
+evenboth checks-per-col [ no4cycle ]
+
+evenboth checks-distribution [ no4cycle ]
+
+
+
+ +

Creates a Low Density Parity Check matrix with +n-checks rows and n-bits columns. The +parity check matrix will be generated pseudo-randomly by the indicated +method, using a pseudo-random number stream determined by seed. +The actual random number seed used is 10 times seed plus 1, +so as to avoid using the same stream as any of the other programs. + +

Two methods are currently available for creating the LDPC matrix, +specified by evencol or evenboth. Both methods +produce a matrix in which the number of 1s in each column is +approximately checks-per-col, or varies from column +to column according the the checks-distribution. +The evenboth 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. + +

For both methods, the no4cycle 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. + +

A checks-distribution has the form +

+propxcount/propxcount/...
+
+Here, prop is a proportion of columns that have the +associated count. The proportions need not sum to one, +since they will be automatically normalized. For example, 0.3x4/0.2x5 +specifies that 60% of the columns will contain four 1s and 40% will +contain five 1s. + +

See the discussion above for more details +on how these methods construct LDPC matrices. + +

Example 1: The make-ldpc 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 print-pchk. +

    +
  • make-ldpc ldpc.pchk 20 40 1 evenboth 3 +
  • 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 +
+ +

Example 2: The two make-ldpc 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. +

    +
  • make-ldpc ldpc.pchk 20 40 1 evenboth 0.3x2/0.6x3/0.1x7 +
  • make-ldpc ldpc.pchk 20 40 1 evenboth 3x2/6x3/1x7 +
  • 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 +
+ +
+ +Back to index for LDPC software + + + diff --git a/lib/ldpc/print-gen.c b/lib/ldpc/print-gen.c new file mode 100755 index 000000000..53d339e71 --- /dev/null +++ b/lib/ldpc/print-gen.c @@ -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 +#include +#include +#include + +#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 +#include +#include +#include + +#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); +} diff --git a/lib/ldpc/progs.html b/lib/ldpc/progs.html new file mode 100755 index 000000000..8bb50d35e --- /dev/null +++ b/lib/ldpc/progs.html @@ -0,0 +1,80 @@ + + + Programs for Low Density Parity Check Codes + + + + +

Programs for Low Density Parity Check Codes

+ +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. + +

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. + +

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.) + +

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. + +

Creating a parity check matrix for a code: +

+make-pchk pchk-file n-checks n-bits row:col ...
+
+alist-to-pchk [ -t ] alist-file pchk-file
+
+pchk-to-alist [ -t ] [ -z ] pchk-file alist-file
+
+print-pchk [ -d ] [ -t ] pchk-file
+
+make-ldpc pchk-file n-checks n-bits seed method
+
+ +

Encoding message blocks as codewords: +

+make-gen pchk-file gen-file method
+
+print-gen [ -d ] gen-file 
+
+encode [ -f ] pchk-file gen-file source-file encoded-file
+
+ +

Transmitting bits through a simulated channel: +

+transmit encoded-file|n-zeros received-file seed channel
+
+ +

Decoding received blocks: +

+decode [ -f ] [ -t | -T ] pchk-file received-file decoded-file [ bp-file ] channel method
+
+extract gen-file decoded-file extracted-file
+
+ +

Support programs: +

+rand-src source-file seed n-bits
+
+verify [ -t ] pchk-file decoded-file [ gen-file [ source-file ] ]
+
+ +See also the discussions of linear dependence in +parity check matrices and of sparse LU +decomposition methods, and the examples +of program usage. + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/rand-src.c b/lib/ldpc/rand-src.c new file mode 100755 index 000000000..31a2410dc --- /dev/null +++ b/lib/ldpc/rand-src.c @@ -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 +#include +#include + +#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 +#include +#include +#include + +#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; i0) + { if (x=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 +#include +#include +#include +#include + +#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 . */ + +#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; iseed = seed; + + state->state48[0] = seed>>16; + state->state48[1] = seed&0xffff; + state->state48[2] = rn[0][(seed&0x7fffffff)%Table_size]; + + for (j = 0; jptr[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; jptr[j]]; + } + + for (j = 0; jptr[j]==Table_size-1; j++) + { state->ptr[j] = 0; + } + + if (jptr[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; i0) 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; i0) 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; i10000) + { 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=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 , 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 +#include +#include + +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; +} diff --git a/lib/ldpc/rand.h b/lib/ldpc/rand.h new file mode 100755 index 000000000..bb896d406 --- /dev/null +++ b/lib/ldpc/rand.h @@ -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 */ diff --git a/lib/ldpc/rand.html b/lib/ldpc/rand.html new file mode 100755 index 000000000..5754b86a6 --- /dev/null +++ b/lib/ldpc/rand.html @@ -0,0 +1,306 @@ + + + Random Variate Generation Routines + + + + +

Random Variate Generation Routines

+ +

This module provides facilities for basic pseudo-random number generation, +and for generation of random variates from various common distributions. + +

All the random generation procedures use the same underlying +"stream" of random numbers. This stream is generated using the +nrand48 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. + +

A pseudo-random number stream is determined by an integer +seed, 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 +rand_state, 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. + +

The methods for generating random variates from various distributions +are mostly taken from 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 were +selected to be reasonably fast while also being easy to write. + +

Header file required: rand.h + + + +


+
Setting and saving the state
+
+ + +
rand_seed: +Set the state from an integer seed.
+ +
+void rand_seed
+( int seed;  /* Seed to set state based on */
+)
+
+ +

Sets the random number generator to a state that is determined from +the integer seed. 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.) + +

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 not +recommended, since the results are then not reproducible. + +


rand_get_state: +Get a pointer to the current state. + +
+rand_state *rand_get_state (void)
+
+ +Returns a pointer to the current state of the random number generator, +which is a structure of type rand_state. The only use for this +pointer is to use it to save a copy of the current state someplace. + + +


rand_use_state: +Set the state to use from now on. + +
+void rand_use_state 
+( rand_state *state  /* Pointer to a previously saved state */
+)
+
+ +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 +rand_get_state. + + + +


+
Generating uniform random variates
+
+ + +
rand_uniform: +Generate uniformly from [0,1).
+ +
+double rand_uniform (void)
+
+ +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. + +


rand_uniopen: +Generate uniformly from (0,1). + +
+double rand_uniopen (void)
+
+ +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. + + + +


+
Generating discrete random variates
+
+ + +
rand_int: +Pick an integer uniformly from 0 to n-1.
+ +
+int rand_int 
+( int n  /* Number of integers (from 0) to pick from */
+)
+
+ +

Randomly picks an integer from the set { 0, 1, ..., n-1 }, +with each integer being equally probable. The probabilities may +become somewhat unequal, however, if n is very large, +approaching 231. + + +


rand_pickd: Pick an integer from 0 +to n-1 with given probabilities (as doubles). + +
+int rand_pickd
+( double *p,  /* Array of probabilities, of length n */
+  int n       /* Number of integers (from 0) to pick from */
+)
+
+ +

Randomly picks an integer from the set { 0, 1, ..., n-1 }, +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. + +

If one of the probabilities is exactly zero, it is guaranteed that +the corresponding integer will not be picked. + + +


rand_pickf: Pick an integer from 0 +to n-1 with given probabilities (as floats). + +
+int rand_pickf
+( float *p,  /* Array of probabilities, of length n */
+  int n      /* Number of integers (from 0) to pick from */
+)
+
+ +

This procedure is the same as rand_pickd +except that the array giving the probabilities is an array of single-precision +floating point numbers, rather than double-precision. + + +


rand_poisson: +Generate a non-negative integer from a Poisson distribution. + +
+int rand_poisson
+( double lambda  /* Mean of the Poisson distribution */
+)
+
+ +

Generates a non-negative integer from the Poisson distribution with mean +lambda. + + +


rand_permutation: Generate a random +permutation of integers from 1 to n. + +
+int rand_permutation
+( int *perm,  /* Place to store the permutation */
+  int n       /* Number of integers to permute */
+)
+
+ +

Stores a random permutation of the integers from 1 to n in the +array perm, which must be at least n long. All permutations are +equally likely. + + + +


+
Generating continuous random variates
+
+ + +
rand_gaussian: +Generate a standard Gaussian (normal) random variate.
+ +
+double rand_gaussian (void)
+
+ +

Generates a random value drawn from the Gaussian (normal) distribution +with mean zero and standard deviation one, whose density function is +proportional to exp(-x2/2), with x +being any real value. + + +


rand_logistic: +Generate a logistic random variate. + +
+double rand_logistic (void)
+
+ +

Generates a random value drawn from the logistic distribution with +location parameter zero and width parameter one, whose density +function is proportional to +exp(-x) / [1 + exp(-x)]2, +with x being any real value. + + +


rand_cauchy: +Generate a Cauchy random variate. + +
+double rand_cauchy (void)
+
+ +

Generates a random value drawn from the Cauchy distribution with centre +at zero and width one, whose density function is proportional to +1 / (1+x2), with x being any real value. + + +


rand_gamma: +Generate a gamma-distributed random variate. + +
+double rand_gamma
+( double A   /* Shape parameter */
+)
+
+ +

Generates a random value drawn from the gamma distribution with +positive shape parameter A, whose density function is proportional +to xA-1 exp(-x), with x +being any positive real. This procedure will never return a value that is +exactly zero. + + +


rand_exp: +Generate an exponentially-distributed random variate. + +
+double rand_exponential (void)
+
+ +

Generates a random value drawn from the exponential distribution with +mean one, whose density function is exp(-x), with x being +any positive real. This procedure will never return a value that is +exactly zero. + +

Note: This is a common special case of the gamma distribution. + + +


rand_beta: +Generate a beta-distributed random variate. + +
+double rand_beta
+( double A,  /* Parameters of distribution */
+  double B
+)
+
+ +

Generates a random value drawn from the beta distribution with positive +parameters A and B, whose density function is proportional +to xA-1(1-x)B-1, +with x being any real in the interval (0,1). This procedure +will never return a value that is exactly zero or exactly one. + + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/randfile b/lib/ldpc/randfile new file mode 100755 index 0000000000000000000000000000000000000000..3d33d61e250402658f21fc5e82c997c49d0062f7 GIT binary patch literal 100000 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 literal 0 HcmV?d00001 diff --git a/lib/ldpc/rcode.c b/lib/ldpc/rcode.c new file mode 100755 index 000000000..3ccf20c51 --- /dev/null +++ b/lib/ldpc/rcode.c @@ -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 +#include +#include + +#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 + + References on Low Density Parity Check Codes + + + + +

References on Low Density Parity Check Codes

+ +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: +
+

Gallager, R. G. (1963) Low Density Parity Check Codes, + Cambridge, MA: MIT Press. +

Gallager, R. G. (1962) ``Low-density parity-check codes'', IRE + Transactions on Information Theory, vol. IT-8, pp. 21-28. +

+ +More recent work on these codes by David MacKay and myself was published +as follows: +
+

MacKay, D. J. C. and Neal, R. M. (1996) ``Near Shannon limit performance + of low density parity check codes'', Electronics Letters, + vol. 32, pp. 1645-1646. Reprinted with printing errors corrected + in vol. 33, pp. 457-458. +

MacKay, D. J. C. (1999) ``Good error-correcting codes based on very + sparse matrices'', IEEE Transactions on Information Theory, + vol. 45, pp. 399-431. +

+ +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: +
+

Kschischang, F. R., Frey, B. J., and Loeliger, H.-A. (1998) ``Factor graphs +and the sum-product algorithm'', IEEE Transactions on Information +Theory, vol. 47, pp. 498-519. +

+ +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 here. Note: 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 M=3200 with +3 checks per bit is actually around 12.7, not the value around 17 shown +on one of the slides. + +

Text and references to many more recent and classical papers can be +obtained via the IMA workshop's +web page. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/release.html b/lib/ldpc/release.html new file mode 100755 index 000000000..558e7cda8 --- /dev/null +++ b/lib/ldpc/release.html @@ -0,0 +1,244 @@ + + +Release Notes for LDPC-codes Software + + + + +

Release Notes for LDPC-codes Software

+ +These notes describe all the stable public releases of this software. Old +and future releases can be obtained via +
+ +http://www.cs.toronto.edu/~radford/ldpc.software.html +
+The current development version is now maintained at +
+ +http://github.com/radfordneal/LDPC-code +
+ +

Version of 2012-02-11.

+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. +
    +
  1. 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.) +
  2. 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.) +
  3. 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. +
  4. 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. +
  5. Documented the previously undocumented -t options for pchk-to-alist + and alist-to-pchk. +
  6. 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). +
  7. 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). +
  8. Fixed bug in distrib.c affecting distributions with a single + number (thanks to Mike Vicuna for pointing it out). +
  9. Fixed bug in -t option for pchk-to-alist (thanks to Andrea Fontana + for reporting this). +
  10. Fixed references in the documentation to mod2sparse_multvec + that should be to mod2sparse_mulvec (thanks to Andrea Fontana + for reporting this). +
+ + +

Version of 2006-02-08.

+ +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 here. 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 alist +format for parity check matrices, used by David MacKay and others, +have also been added. + +

The following new features have been added: +

    +
  1. The make-ldpc program can + new create LDPC codes with varying numbers of checks per bit. The + examples now include a code of this sort. +
  2. New programs pchk-to-alist + and alist-to-pchk have + been added, which convert to and from alist + format. +
  3. A run-examples script has been + added, which runs all the examples and + compares with the saved output that I obtained. +
+ + +

Version of 2001-11-18.

+ +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 cygwin Unix environment that runs +under Microsoft Windows. + +

The following new feature has been added: +

    +
  1. A new -t option has been added to + print-pchk, which + causes it to print the transpose of the parity check matrix. +
+ +The following program module change was made: +
    + +
  1. The behaviour of mod2dense_invert_selected + 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. +
+ +The following bugs were fixed: +
    +
  1. A bug has been fixed in + make-gen + 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 + ex-dep example has changed slightly as a + result. +
  2. The open mode for reading the file of random numbers has been changed from + "r" to "rb", for compatibility with non-Unix systems. +
  3. mod2sparse_copy has + been fixed so that it copies the lr and pr fields + of entries. +
  4. 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. +
+ +A few minor fixes to the documentation have also been made. + + +

Version of 2001-05-04.

+ +Changes and new features regarding programs and associated +documentation and examples: +
    +
  1. 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 + ex-ham7a, which still + demonstrates this facility. +
  2. 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. +
  3. 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. +
  4. All programs now allow a file name argument to be "-", which specifies + standard input or standard output, as appropriate. The + ex-ldpc36-5000a example has been + changed to use this facility in order to avoid creating lots of files. +
  5. Channels with noise from a logistic distribution (AWLN) have been + implemented. For details, + see the channel documentation. +
  6. The make-gen 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 + discussion of linear dependence in parity check + matrices has changed slightly as a result. +
  7. The messages displayed by the decode + 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 -t option is specified now includes the number of + bits changed in each block. +
  8. A new -T option to decode + for displaying + detailed information on decoding + has been added. +
  9. Doing a make clean will now remove the files created + by running the examples. +
  10. The files created by the examples now + start with "ex-" and contain a ".", to make them easier to + identify for cleanup, and the saved output file now ends in + "-out" rather than ".out". +
  11. The scripts for the examples now use the -v option of set + rather than -x, so that the command lines are echoed + faithfully as they are read. +
  12. Two new examples have been added: + ex-dep demonstrates what happens when parity check matrices + have redundant row, and ex-wrong-model investigates what + happens when the wrong model is used to decode. +
+Changes and new features regarding program modules and other internals: +
    +
  1. Instructions have been added on + how to modify the programs, and some + code has been reorganized to facilitate modifications. +
  2. 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. +
  3. The + mod2dense_invert_selected + 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 make-gen. +
  4. New routines + mod2dense_copyrows and + mod2sparse_copyrows have + been added, analogous to the previous routines for copying columns. +
  5. 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 -T option is used. +
+ +The following bugs were fixed: +
    +
  1. A problem with print-gen prevented the -d option from working + in most cases. The documentation was also fixed to note what + the L and U matrices printed will look like. +
  2. The documentation for + mod2sparse_copycols and + mod2dense_copycols + 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. +
  3. In decode.c, a variable declared to be float was printed + using "%f", which strangely didn't work with one compiler. + It's now declared as double. +
+ +There were also numerous minor cleanups of program code and documentation. + +

Version of 2000-03-19.

+ +This was the first public release. + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/run-examples b/lib/ldpc/run-examples new file mode 100755 index 000000000..7d8859e3f --- /dev/null +++ b/lib/ldpc/run-examples @@ -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 diff --git a/lib/ldpc/sparse-LU.html b/lib/ldpc/sparse-LU.html new file mode 100755 index 000000000..12874aaaf --- /dev/null +++ b/lib/ldpc/sparse-LU.html @@ -0,0 +1,90 @@ + + + Sparse LU Decomposition Methods + + + + +

Sparse LU Decomposition Methods

+ +

The sparse modulo-2 matrix LU decomposition routine mod2sparse_decomp (which +is used by the make-gen +program when it is asked to create a sparse generator matrix) tries to +find an sub-matrix of a matrix (for make-gen, the parity +check matrix), and an ordering of rows and columns for this +sub-matrix, that leads to the lower-triangular matrix L and the +upper-triangular matrix U making up the LU decomposition being +as sparse as possible. Finding an optimal solution is too difficult, +so instead a heuristic strategy is used. + +

The overall algorithm finds L and U a column at a +time, from left to right (as reordered, in the case of U). As +this is done, a copy, B, of the original matrix is modified. +To create column i of L and U, some element with +value 1 in B whose row and column indexes, after reordering, +are both greater than 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 L +and U (upper elements going to U, lower to L). +The row containing this element is then added to some later rows so as +to clear the lower part of this column to zeros. + +

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 Mod2sparse_first, +Mod2sparse_mincol, and Mod2sparse_minprod. These +strategies operate as follows: + +

Mod2sparse_first +

+Select the first element with value 1 that is encountered in a top +to bottom, left to right search. +
+ +

Mod2sparse_mincol +

+Select the first element with value 1 that is contained in a column +of B that has the smallest number of 1s of any column. +
+ +

Mod2sparse_minprod +

+Select an element with value 1 for which the product of the number of +1s in that row of B minus one times the number of 1s in that +column of B minus one is as small as possible. +
+ +

The abandon_number and abandon_when parameters can +modify the basic strategy. If abandon_number is greater than +zero, then after abandon_when columns have been selected, +abandon_number 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. + +

The methods described here are fairly straightforward adaptations +of standard methods for sparse square matrices of reals, as described, for +example, in +

+ I. S. Duff, A. M. Erisman, J. K. Reid (1986) Direct Methods for + Sparse Matrices, Oxford: Clarendon Press. +
+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 references). + + +
+ +Back to index for LDPC software + + diff --git a/lib/ldpc/sparse-encode.pdf b/lib/ldpc/sparse-encode.pdf new file mode 100755 index 0000000000000000000000000000000000000000..30629f31a6e2d90baba4daef1ae949ebe43869aa GIT binary patch literal 185688 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

>G=`B0$^l(T_yHc-w6%Gp3U0CsSJf;Ldl1`66h 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 E3wf#@DF6Tf literal 0 HcmV?d00001 diff --git a/lib/ldpc/support.html b/lib/ldpc/support.html new file mode 100755 index 000000000..921881abd --- /dev/null +++ b/lib/ldpc/support.html @@ -0,0 +1,100 @@ + + + Support Programs + + + + +

Support Programs

+ +The following programs provide support for testing and performance +assessment. + + +


rand-src: Generate random message bits. + +
+rand-src source-file seed n-bits
+
+ +

Creates a file of random messages bits called +source-file, 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 seed. The actual +random number seed used will be seed 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. + +

The n-bits 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 x 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. + +

Example: 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 seed of 17: +

    +
  • rand-src rsrc 17 15x3 +
+The contents of the file rsrc after this command might be something +like the following: +
+111011000110000
+010010110010111
+100000000000111
+
+ + +


verify: Verify that decoded blocks are +codewords, and that they match the source. + +
+verify [ -t ] pchk-file decoded-file [ gen-file [ source-file ] ]
+
+ +

Checks whether or not the blocks in decoded-file +are codewords, according to the parity check matrix in +pchk-file. If gen-file is specified, +the message bits of the blocks are also checked against the +corresponding blocks of source-file, or against zero +if source-file is not given. (Normally, one would +leave out source-file only if the transmit command was used +with an argument specifying that zeros are to be transmitted, rather +than a file of encoded data.) + +

A summary of the results is displayed on standard error, giving the +total numbers of blocks, the number with parity check errors, and, if +gen-file was specified, the number of blocks with +source errors and the number with errors of both kinds. If +gen-file 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 source file was given). + +

If the -t 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 gen-file 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 +

+data <- read.table(file,header=T)
+
+ +

Warning messages are displayed on standard error if the number of +bits in decoded-file is not a multiple of the block +length, or if source-file is too short. Newlines +in these files are ignored, even though they would normally occur +at the ends of blocks. + +


+ +Back to index for LDPC software + + diff --git a/lib/ldpc/transmit.c b/lib/ldpc/transmit.c new file mode 100755 index 000000000..14657d686 --- /dev/null +++ b/lib/ldpc/transmit.c @@ -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 +#include +#include +#include + +#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); +} diff --git a/lib/ldpc/verify.c b/lib/ldpc/verify.c new file mode 100755 index 000000000..e52f79d86 --- /dev/null +++ b/lib/ldpc/verify.c @@ -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 +#include +#include +#include + +#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